Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 1088 → Rev 1089

/demos/trunk/first/test1.c
0,0 → 1,250
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: test1.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
this test shows a set of 5 tasks (+main+dummy+keyboard driver).
The first 4 tasks are scheduled by a EDFSTAR Module, whereas the
fifth one is a standard traditional EDF task. The 4 tasks uses a
budget of 10000/100000.
if edfstar.c is compiled with edfstar_printf3 active, a couple
(dline, curtime) is showed (in ms).
if cbsstar.c is compiled with cbsstar_printf3 active, the budget
replenishments are showed.
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "kernel/kern.h"
#include "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level, edfstar_level, mybudget;
 
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
mybudget = CBSSTAR_setbudget(cbsstar_level, 10000, 100000);
edfstar_level = EDFSTAR_register_level(mybudget, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
//keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
 
void *star(void *arg)
{
int i,j;
 
for (i=0; i<5; i++) {
for (j=0; j<100000; j++);
cputc('°');
cputs((char *)arg);
task_endcycle();
}
 
return NULL;
}
 
void *edftask(void *arg)
{
int i,j;
 
for (i=0; i<5; i++) {
for (j=0; j<100000; j++);
cputc('°');
cputs((char *)arg);
task_endcycle();
}
 
return NULL;
}
 
void create1()
{
HARD_TASK_MODEL m1, m2;
PID p1a, p1b, p1c, p1d, p2;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_level(m1,2);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
hard_task_def_arg(m1,(void *)"a");
hard_task_def_mit(m1,10000);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"b");
hard_task_def_mit(m1,15000);
p1b = task_create("b", star, &m1, NULL);
if (p1b == -1) {
perror("Could not create task b ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"c");
hard_task_def_mit(m1,20000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"d");
hard_task_def_mit(m1,30000);
p1d = task_create("d", star, &m1, NULL);
if (p1d == -1) {
perror("Could not create task d ...");
sys_end();
}
 
hard_task_default_model(m2);
hard_task_def_mit(m2,50000); // the budget has dline 100,000!
hard_task_def_wcet(m2, 5000);
hard_task_def_arg(m2,(void *)"Û");
hard_task_def_group(m2,1);
hard_task_def_periodic(m2);
 
p2 = task_create("2", edftask, &m2, NULL);
if (p2 == -1) {
perror("Could not create task edf ...");
sys_end();
}
 
cprintf("stars=%d %d %d %d, star2=%d\n", p1a, p1b, p1c, p1d, p2);
 
group_activate(1);
}
 
int main(int argc, char **argv)
{
char c;
 
set_exchandler_grx();
 
clear();
 
cprintf("Hello, world!");
 
create1();
 
do {
c =keyb_getch(BLOCK);
} while (c != ESC);
 
cprintf("ESC pressed!");
 
sys_end();
 
return 0;
}
 
/demos/trunk/first/test2.c
0,0 → 1,243
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: test2.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
The purpose of this test is to show that two budgets with different
period and capacity schedules correctly.
 
4 periodic tasks are involved
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "kernel/kern.h"
#include "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level, edfstar_level, edfstar_level2, mybudget, mybudget2;
clear();
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
 
mybudget = CBSSTAR_setbudget(cbsstar_level, 1000, 50000);
edfstar_level = EDFSTAR_register_level(mybudget, cbsstar_level);
 
mybudget2 = CBSSTAR_setbudget(cbsstar_level, 10000, 25000);
edfstar_level2 = EDFSTAR_register_level(mybudget2, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
cprintf("edfstar_level=%d, edfstar_level2=%d\n",
edfstar_level,edfstar_level2);
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
 
void *star(void *arg)
{
int i,j,z;
 
for (i=0; i<100; i++) {
for (z=0; z<5; z++) {
for (j=0; j<60000; j++);
cputs((char *)arg);
}
task_endcycle();
}
 
return NULL;
}
 
// version for the "slow" budget
void *slow(void *arg)
{
int i,j,z;
 
for (i=0; i<15; i++) {
for (z=0; z<5; z++) {
for (j=0; j<200000; j++);
cputs((char *)arg);
}
task_endcycle();
}
 
return NULL;
}
 
void create1()
{
HARD_TASK_MODEL m1;
PID p1a, p1b, p1c, p1d;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
 
 
 
hard_task_def_level(m1,2);
 
hard_task_def_arg(m1,(void *)".");
hard_task_def_mit(m1,5000);
p1a = task_create("a", slow, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)",");
hard_task_def_mit(m1,5000);
p1b = task_create("b", slow, &m1, NULL);
if (p1b == -1) {
perror("Could not create task b ...");
sys_end();
}
 
 
 
 
hard_task_def_level(m1,3);
 
hard_task_def_arg(m1,(void *)"o");
hard_task_def_mit(m1,5000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"O");
hard_task_def_mit(m1,5000);
p1d = task_create("d", star, &m1, NULL);
if (p1d == -1) {
perror("Could not create task d ...");
sys_end();
}
 
group_activate(1);
}
 
int main(int argc, char **argv)
{
char c;
 
set_exchandler_grx();
 
cprintf("Hello, world!");
 
create1();
 
do {
c =keyb_getch(BLOCK);
} while (c != ESC);
 
cprintf("ESC pressed!");
 
sys_end();
 
return 0;
}
 
/demos/trunk/first/cbsstar.c
0,0 → 1,686
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: cbsstar.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
Read CBSSTAR.h for general details.
 
Basically, a budget can be in 2 states:
- Active -> the budget queue is not empty
- Idle -> the budget queue is empty
 
The fact that a task into a budget is inserted into the master module depends
on the value of the remaining time the tasks can spend in the period.
 
The module does handle only one oslib event, used to enforce the
temporal isolation between buffers. Note that all is implemented
without using the CONTROL_CAP field.
 
Basically, for each budget there can be at most one task inserted
into the master level. Its deadline is modified according to the
usage of its capacity, that is, when a budget is exausted its
deadline is postponed.
 
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#include "cbsstar.h"
#include <ll/string.h>
 
 
/*
* DEBUG stuffs begin
*/
 
//#define CBSSTAR_DEBUG
 
#ifdef CBSSTAR_DEBUF
 
static __inline__ void fake_printf(char *fmt, ...) {}
 
//#define cbsstar_printf kern_printf
//#define cbsstar_printf2 kern_printf
//#define cbsstar_printf3 kern_printf
 
#define cbsstar_printf fake_printf
#define cbsstar_printf2 fake_printf
#define cbsstar_printf3 fake_printf
 
#if 0
void cbsstar_printq(QQUEUE *q)
{
PID p;
kern_printf("[");
p = q->first;
kern_printf("->%d",p);
while (p != NIL) {
p = proc_table[p].next;
kern_printf("->%d",p);
}
kern_printf("]");
}
#else
static __inline__ void cbsstar_printq(QQUEUE *q) {}
#endif
 
#if 0
static __inline__ void cbsstar_printblob(int x) { if (x) cputc('±'); else cputc('Û'); }
#else
static __inline__ void cbsstar_printblob(int x) {}
#endif
 
#endif
 
/*
* DEBUG stuffs end
*/
 
 
/* this structure contains the status for a single budget */
struct budget_struct {
TIME Q; /* budget */
TIME T; /* period */
 
struct timespec dline; /* deadline */
int dline_timer; /* oslib event for budget reactivation*/
int avail; /* current budget */
 
PID current; /* the task currently put in execution */
 
QQUEUE tasks; /* a FIFO queue for the tasks handled
using the budget */
};
 
typedef struct {
level_des l; /* the standard level descriptor */
 
struct budget_struct *b; /* the budgets! */
int n; /* the maximum index for the budgets */
int freebudgets; /* number of free budgets; starts from n */
 
int tb[MAX_PROC]; /* link task->budget (used in guest_end) */
 
bandwidth_t U; /*+ the used bandwidth by the server +*/
 
LEVEL scheduling_level;
 
} CBSSTAR_level_des;
 
 
static void CBSSTAR_activation(CBSSTAR_level_des *lev,
PID p,
struct timespec *acttime)
{
JOB_TASK_MODEL job;
struct budget_struct *b = &lev->b[lev->tb[p]];
 
/* we have to check if the deadline and the wcet are correct before
activating a new task or an old task... */
 
/* check 1: if the deadline is before than the actual scheduling time */
 
/* check 2: if ( avail_time >= (cbs_dline - acttime)* (wcet/period) )
(rule 7 in the CBS article!) */
TIME t;
struct timespec t2,t3;
 
t = (b->T * b->avail) / b->Q;
t3.tv_sec = t / 1000000;
t3.tv_nsec = (t % 1000000) * 1000;
 
SUBTIMESPEC(&b->dline, acttime, &t2);
 
if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) ||
/* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
/* if (TIMESPEC_A_LT_B(&lev->cbs_dline[p], acttime) )
kern_printf("$");
else
kern_printf("(Ûdline%d.%d act%d.%d wcet%d per%d avail%dÛ)",
lev->cbs_dline[p].tv_sec,lev->cbs_dline[p].tv_nsec/1000,
acttime->tv_sec, acttime->tv_nsec/1000,
proc_table[p].wcet, lev->period[p], proc_table[p].avail_time);
*/ /* we modify the deadline ... */
TIMESPEC_ASSIGN(&b->dline, acttime);
ADDUSEC2TIMESPEC(b->T, &b->dline);
 
/* and the capacity */
b->avail = b->Q;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf3("±%d±",lev->tb[p]);
cbsstar_printblob(lev->tb[p]);
#endif
}
 
/* record the current task inserted in the master module */
b->current = p;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:iact p%d %ld.%ld av=%d)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
#endif
 
/* and, finally, we reinsert the task in the master level */
job_task_default_model(job, b->dline);
job_task_def_noexc(job);
level_table[ lev->scheduling_level ]->
guest_create(lev->scheduling_level, p, (TASK_MODEL *)&job);
level_table[ lev->scheduling_level ]->
guest_activate(lev->scheduling_level, p);
 
}
 
 
static void CBSSTAR_account_capacity(CBSSTAR_level_des *lev, PID p)
{
struct timespec ty;
TIME tx;
 
SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
tx = TIMESPEC2USEC(&ty);
lev->b[lev->tb[p]].avail -= tx;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf2("(C:cap p%d av=%d)", p, lev->b[lev->tb[p]].avail);
#endif
}
 
 
static int CBSSTAR_level_accept_task_model(LEVEL l, TASK_MODEL *m)
{
return -1;
}
 
static int CBSSTAR_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
{
if (m->pclass == BUDGET_PCLASS || m->pclass == (BUDGET_PCLASS | l)) {
return 0;
}
 
return -1;
}
 
 
static void CBSSTAR_level_status(LEVEL l)
{
kern_printf("CBSSTAR level_status (level %d)\n", l);
}
 
static PID CBSSTAR_level_scheduler(LEVEL l)
{
/* the CBSSTAR don't schedule anything...
it's an EDF level or similar that do it! */
return NIL;
}
 
/* The on-line guarantee is enabled only if the appropriate flag is set... */
static int CBSSTAR_level_guarantee(LEVEL l, bandwidth_t *freebandwidth)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:gua)");
#endif
 
if (*freebandwidth >= lev->U) {
*freebandwidth -= lev->U;
return 1;
}
else
return 0;
}
 
static int CBSSTAR_task_create(LEVEL l, PID p, TASK_MODEL *m)
{
kern_raise(XUNVALID_TASK,exec_shadow);
return 0; /* OK, also if the task cannot be guaranteed... */
}
 
static void CBSSTAR_task_detach(LEVEL l, PID p)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static int CBSSTAR_task_eligible(LEVEL l, PID p)
{
/* this function is never called! ... maybe I should remove it? */
#if 0
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
struct budget_struct *b = &lev->b[lev->tb[p]];
JOB_TASK_MODEL job;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:eli %d",p);
#endif
 
/* we have to check if the deadline and the wcet are correct...
if the CBSSTAR level schedules in background with respect to others
levels, there can be the case in witch a task is scheduled by
schedule_time > CBSSTAR_deadline; in this case (not covered in the
article because if there is only the standard scheduling policy
this never apply) we reassign the deadline */
 
if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time) ) {
/* we kill the current activation */
level_table[ lev->scheduling_level ]->
guest_end(lev->scheduling_level, p);
 
/* we modify the deadline ... */
TIMESPEC_ASSIGN(&b->dline, &schedule_time);
ADDUSEC2TIMESPEC(b->T, &b->dline);
 
/* and the capacity */
b->avail = b->Q;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf2(" %ld.%ld av=%d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->Q);
cbsstar_printf3("±%d±",lev->tb[p]);
cbsstar_printblob(lev->tb[p]);
#endif
 
/* and, finally, we reinsert the task in the master level */
job_task_default_model(job, b->dline);
job_task_def_noexc(job);
level_table[ lev->scheduling_level ]->
guest_create(lev->scheduling_level, p, (TASK_MODEL *)&job);
level_table[ lev->scheduling_level ]->
guest_activate(lev->scheduling_level, p);
 
return -1;
}
#ifdef CBSSTAR_DEBUG
cbsstar_printf(")");
#endif
 
#endif
return 0;
}
 
static void CBSSTAR_task_dispatch(LEVEL l, PID p, int nostop)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static void CBSSTAR_task_epilogue(LEVEL l, PID p)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static void CBSSTAR_task_activate(LEVEL l, PID p)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static void CBSSTAR_task_insert(LEVEL l, PID p)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static void CBSSTAR_task_extract(LEVEL l, PID p)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static void CBSSTAR_task_endcycle(LEVEL l, PID p)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static void CBSSTAR_task_end(LEVEL l, PID p)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static void CBSSTAR_task_sleep(LEVEL l, PID p)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static void CBSSTAR_task_delay(LEVEL l, PID p, TIME usdelay)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static int CBSSTAR_guest_create(LEVEL l, PID p, TASK_MODEL *m)
{
/* A task has been activated for some reason. Basically, the task is
inserted in the queue if the queue is empty, otherwise the task is
inserted into the master module, and an oslib event is posted. */
 
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
BUDGET_TASK_MODEL *budget = (BUDGET_TASK_MODEL *)m;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:gcr %d b%d", p, budget->b);
#endif
 
lev->tb[p] = budget->b;
 
if (lev->b[budget->b].current == NIL) {
/* This is the first task in the budget,
the task have to be inserted into the master module */
struct timespec t;
ll_gettime(TIME_EXACT, &t);
CBSSTAR_activation(lev,p,&t);
} else {
/* The budget is not empty, another task is already into the
master module, so the task is inserted at the end of the budget
queue */
qq_insertlast(p,&lev->b[budget->b].tasks);
#ifdef CBSSTAR_DEBUG
cbsstar_printf(" ilast");
cbsstar_printq(&lev->b[budget->b].tasks);
#endif
}
#ifdef CBSSTAR_DEBUG
cbsstar_printf(")");
#endif
 
return 0;
}
 
static void CBSSTAR_guest_end(LEVEL l, PID p)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:gend p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
cbsstar_printq(&lev->b[lev->tb[p]].tasks);
#endif
 
/* a task is removed from execution for some reasons. It must be
that it is the first in its budget queue (only the first task in
a budget queue is put into execution!) */
CBSSTAR_account_capacity(lev,p);
 
/* remove the task from execution (or from the ready queue) */
if (lev->b[lev->tb[p]].current == p) {
/* remove the task from the master module */
level_table[ lev->scheduling_level ]->
guest_end(lev->scheduling_level, p);
 
#ifdef CBSSTAR_DEBUG
cbsstar_printq(&lev->b[lev->tb[p]].tasks);
#endif
 
/* check if the buffer has someone else to schedule */
if (qq_queryfirst(&lev->b[lev->tb[p]].tasks) == NIL) {
/* the buffer has no tasks! */
lev->b[lev->tb[p]].current = NIL;
}
else {
/* if so, insert the new task into the master module */
PID n;
struct timespec t;
ll_gettime(TIME_EXACT, &t);
n = qq_getfirst(&lev->b[lev->tb[p]].tasks);
#ifdef CBSSTAR_DEBUG
cbsstar_printf("{p%d n%d}",p,n);
#endif
CBSSTAR_activation(lev,n,&t); // it modifies b[lev->tb[p]].current
}
}
else
qq_extract(p, &lev->b[lev->tb[p]].tasks);
}
 
static void CBSSTAR_guest_dispatch(LEVEL l, PID p, int nostop)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
struct timespec ty;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:gdisp p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
cbsstar_printq(&lev->b[lev->tb[p]].tasks);
#endif
 
/* the current task (that is the only one inserted in the master module
for the corresponding budget) is dispatched. Note that the current
task is not inserted in any FIFO queue, so the task does not have to
be extracted! */
 
/* ... then, we dispatch it to the master level */
level_table[ lev->scheduling_level ]->
guest_dispatch(lev->scheduling_level,p,nostop);
 
/* ...and finally, we have to post a capacity event */
if (!nostop) {
TIMESPEC_ASSIGN(&ty, &schedule_time);
ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty);
cap_timer = kern_event_post(&ty, capacity_timer, NULL);
}
}
 
static void CBSSTAR_guest_epilogue(LEVEL l, PID p)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
struct budget_struct *b = &lev->b[lev->tb[p]];
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:gepi %d",p);
#endif
 
CBSSTAR_account_capacity(lev,p);
 
/* we have to check if the capacity is still available */
if (b->avail > 0) {
/* there is capacity available, maybe it is simply a preemption;
the task have to return to the ready queue */
level_table[ lev->scheduling_level ]->
guest_epilogue(lev->scheduling_level,p);
#ifdef CBSSTAR_DEBUG
cbsstar_printf2(" *av=%d", b->avail);
#endif
} else {
/* The capacity is exausted; the deadline have to be postponed and
the task have to be reinserted in the master module */
JOB_TASK_MODEL job;
 
/* we kill the current activation */
level_table[ lev->scheduling_level ]->
guest_end(lev->scheduling_level, p);
 
/* we modify the deadline according to rule 4 ... */
/* there is a while because if the wcet is << than the system tick
we need to postpone the deadline many times */
while (b->avail <= 0) {
ADDUSEC2TIMESPEC(b->T, &b->dline);
b->avail += b->Q;
#ifdef CBSSTAR_DEBUG
cbsstar_printf3("±%d±",lev->tb[p]);
cbsstar_printblob(lev->tb[p]);
#endif
}
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf2(" %ld.%ld av=%d",b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
#endif
/* and, finally, we reinsert the task in the master level */
job_task_default_model(job, b->dline);
job_task_def_noexc(job);
level_table[ lev->scheduling_level ]->
guest_create(lev->scheduling_level, p, (TASK_MODEL *)&job);
level_table[ lev->scheduling_level ]->
guest_activate(lev->scheduling_level, p);
}
#ifdef CBSSTAR_DEBUG
cbsstar_printf(")");
#endif
}
 
static void CBSSTAR_guest_detach(LEVEL l, PID p)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
static void CBSSTAR_guest_activate(LEVEL l, PID p)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
static void CBSSTAR_guest_insert(LEVEL l, PID p)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
static void CBSSTAR_guest_extract(LEVEL l, PID p)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
static void CBSSTAR_guest_endcycle(LEVEL l, PID p)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
static void CBSSTAR_guest_sleep(LEVEL l, PID p)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
static void CBSSTAR_guest_delay(LEVEL l, PID p, DWORD tickdelay)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
 
 
 
/* Registration functions */
 
/*+ Registration function:
int flags the init flags ... see CBSSTAR.h +*/
LEVEL CBSSTAR_register_level(int n, LEVEL master)
{
LEVEL l; /* the level that we register */
CBSSTAR_level_des *lev; /* for readableness only */
PID i; /* a counter */
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("CBSSTAR_register_level\n");
#endif
 
/* request an entry in the level_table */
l = level_alloc_descriptor();
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf(" alloco descrittore %d %d\n",l,(int)sizeof(CBSSTAR_level_des));
#endif
 
/* alloc the space needed for the CBSSTAR_level_des */
lev = (CBSSTAR_level_des *)kern_alloc(sizeof(CBSSTAR_level_des));
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf(" lev=%d\n",(int)lev);
#endif
 
/* update the level_table with the new entry */
level_table[l] = (level_des *)lev;
 
/* fill the standard descriptor */
strncpy(lev->l.level_name, CBSSTAR_LEVELNAME, MAX_LEVELNAME);
lev->l.level_code = CBSSTAR_LEVEL_CODE;
lev->l.level_version = CBSSTAR_LEVEL_VERSION;
 
lev->l.level_accept_task_model = CBSSTAR_level_accept_task_model;
lev->l.level_accept_guest_model = CBSSTAR_level_accept_guest_model;
lev->l.level_status = CBSSTAR_level_status;
lev->l.level_scheduler = CBSSTAR_level_scheduler;
lev->l.level_guarantee = CBSSTAR_level_guarantee;
 
lev->l.task_create = CBSSTAR_task_create;
lev->l.task_detach = CBSSTAR_task_detach;
lev->l.task_eligible = CBSSTAR_task_eligible;
lev->l.task_dispatch = CBSSTAR_task_dispatch;
lev->l.task_epilogue = CBSSTAR_task_epilogue;
lev->l.task_activate = CBSSTAR_task_activate;
lev->l.task_insert = CBSSTAR_task_insert;
lev->l.task_extract = CBSSTAR_task_extract;
lev->l.task_endcycle = CBSSTAR_task_endcycle;
lev->l.task_end = CBSSTAR_task_end;
lev->l.task_sleep = CBSSTAR_task_sleep;
lev->l.task_delay = CBSSTAR_task_delay;
 
lev->l.guest_create = CBSSTAR_guest_create;
lev->l.guest_detach = CBSSTAR_guest_detach;
lev->l.guest_dispatch = CBSSTAR_guest_dispatch;
lev->l.guest_epilogue = CBSSTAR_guest_epilogue;
lev->l.guest_activate = CBSSTAR_guest_activate;
lev->l.guest_insert = CBSSTAR_guest_insert;
lev->l.guest_extract = CBSSTAR_guest_extract;
lev->l.guest_endcycle = CBSSTAR_guest_endcycle;
lev->l.guest_end = CBSSTAR_guest_end;
lev->l.guest_sleep = CBSSTAR_guest_sleep;
lev->l.guest_delay = CBSSTAR_guest_delay;
 
/* fill the CBSSTAR descriptor part */
lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
 
for (i=0; i<n; i++) {
lev->b[i].Q = 0;
lev->b[i].T = 0;
NULL_TIMESPEC(&lev->b[i].dline);
lev->b[i].dline_timer = 0;
lev->b[i].avail = 0;
lev->b[i].current = -1;
qq_init(&lev->b[i].tasks);
}
 
lev->n = n;
lev->freebudgets = 0;
 
for (i=0; i<MAX_PROC; i++)
lev->tb[i] = NIL;
 
lev->U = 0;
 
lev->scheduling_level = master;
 
return l;
}
 
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:sbud)");
#endif
 
if (lev->l.level_code == CBSSTAR_LEVEL_CODE &&
lev->l.level_version == CBSSTAR_LEVEL_VERSION) {
if (lev->freebudgets != lev->n) {
bandwidth_t b;
b = (MAX_BANDWIDTH / T) * Q;
/* really update lev->U, checking an overflow... */
if (Q< T && MAX_BANDWIDTH - lev->U > b) {
int r = lev->freebudgets; // the return value
 
lev->U += b;
lev->freebudgets++;
 
lev->b[r].Q = Q;
lev->b[r].T = T;
 
return r;
}
else
return -2;
}
else
return -1;
}
else
return -3;
}
/demos/trunk/first/test3.c
0,0 → 1,215
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: test3.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
The purpose of this test is to show that two budgets with different
period and budgets schedules correctly.
 
2 never ending tasks are involved
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "kernel/kern.h"
#include "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level, edfstar_level, edfstar_level2, mybudget, mybudget2;
clear();
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
 
mybudget = CBSSTAR_setbudget(cbsstar_level, 2000, 50000);
edfstar_level = EDFSTAR_register_level(mybudget, cbsstar_level);
 
mybudget2 = CBSSTAR_setbudget(cbsstar_level, 10000, 25000);
edfstar_level2 = EDFSTAR_register_level(mybudget2, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
cprintf("edfstar_level=%d, edfstar_level2=%d\n",
edfstar_level,edfstar_level2);
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
#include <semaphore.h>
 
sem_t s;
 
void *star(void *arg)
{
int j,z;
 
for (;;) {
for (z=0; z<5; z++) {
for (j=0; j<60000; j++);
sem_wait(&s);
cputs((char *)arg);
sem_post(&s);
}
}
 
return NULL;
}
 
 
void create1()
{
HARD_TASK_MODEL m1;
PID p1a, p1c;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
 
 
 
hard_task_def_level(m1,2);
 
hard_task_def_arg(m1,(void *)"O");
hard_task_def_mit(m1,5000);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
 
hard_task_def_level(m1,3);
 
hard_task_def_arg(m1,(void *)".");
hard_task_def_mit(m1,5000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
group_activate(1);
}
 
void endfun(KEY_EVT *k)
{
cprintf("ESC pressed!");
 
sys_end();
}
 
int main(int argc, char **argv)
{
KEY_EVT k;
 
set_exchandler_grx();
 
sem_init(&s,0,1);
 
k.flag = 0;
k.scan = KEY_ESC;
k.ascii = 27;
keyb_hook(k,endfun);
 
create1();
 
return 0;
}
 
/demos/trunk/first/iqueue.h
0,0 → 1,172
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: iqueue.h,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
/*
IQUEUEs
 
This file contains functions that helps to manage task queues.
 
These functions are different from the functions that manages the
QUEUE and QQUEUE types. In particular, these functions no more relies
on the prev & next fields of the task descriptor. In that way, tasks
can be inserted in more than one queue at a time.
 
Basically, an IQUEUE has an "I"nternal prev/next structure, that may
be shared between one or more queue. Of course, the user MUST
guarantee that the same task will not be inserted in two IQUEUEs that
share the same prev/next buffer.
 
The queue insertion is made by the following functions:
iq_insert -> insertion based on the priority field.
iq_timespec_insert -> same as above but use the timespec_priority field
iq_insertfirst -> insert in the first position of the queue
*/
 
#include <kernel/const.h>
#include <kernel/types.h>
#include <sys/types.h>
 
#define IQUEUE_NO_PRIORITY 1
#define IQUEUE_NO_TIMESPEC 2
 
struct IQUEUE_shared {
PID prev[MAX_PROC];
PID next[MAX_PROC];
struct timespec *timespec_priority;
DWORD *priority;
};
 
typedef struct {
PID first;
PID last;
struct IQUEUE_shared *s;
} IQUEUE;
 
 
 
/* Internal queue initialization:
 
share = &x -> the internal data structure of the IQUEUE x is used
to enqueue the tasks.
 
share = NULL -> an internal data structure to handle prev/next
pairs is dynamically allocated (The amount of
memory that is allocated can be reduced using the
flags).
 
flags can be used to reduce the memory usage of an IQUEUE when share=NULL:
IQUEUE_NO_PRIORITY -> the iqueue do not provide internally a priority field
IQUEUE_NO_TIMESPEC -> the iqueue do not provide internally a timespec field
 
- note that, if these flags are used, the corresponding insert
functions will not work!
- the default value for the flags is, of course, 0
*/
void iq_init (IQUEUE *q, IQUEUE *share, int flags);
 
/* Queue insert functions:
 
- inserts a p into the q. p must not be already inserted into q.
- four versions of the function;
- iq_priority_insert -> ordered insertion using the priority field
- iq_timespec_insert -> ordered insertion using the timespec field
- iq_insertfirst -> insert at the first position of the queue
- iq_insertlast -> insert at the last position of the queue
*/
void iq_priority_insert (PID p, IQUEUE *q);
void iq_timespec_insert (PID p, IQUEUE *q);
void iq_insertfirst (PID p, IQUEUE *q);
void iq_insertlast (PID p, IQUEUE *q);
 
/* Queue extract functions:
 
- extracts a task p from the queue q.
- three versions of the function;
- iq_extract -> extracts given a task p
(that must be inserted in the queue)
 
- iq_getfirst -> extracts the first task in the queue,
NIL if the queue is empty
- iq_getlast -> extracts the last task in the queue,
NIL if the queue is empty
 
*/
void iq_extract (PID p, IQUEUE *q);
PID iq_getfirst ( IQUEUE *q);
PID iq_getlast ( IQUEUE *q);
 
 
/* Queue query functions:
 
The first two functions return the first and the last task in the queue,
NIL if the queue is empty.
 
The second two functions can be used to get/set the priority or the
timespec field used when queuing.
*/
static __inline__ PID iq_queryfirst(IQUEUE *q)
{
return q->first;
}
 
static __inline__ PID iq_querylast(IQUEUE *q)
{
return q->last;
}
 
static __inline__ struct timespec *iq_query_timespec(PID p, IQUEUE *q)
{
return &q->s->timespec_priority[p];
}
 
static __inline__ DWORD *iq_query_priority (PID p, IQUEUE *q)
{
return &q->s->priority[p];
}
/demos/trunk/first/test4.c
0,0 → 1,233
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: test4.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
The purpose of this test is to show that two budgets with different
period and budgets schedules correctly.
2 never ending tasks are involved
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "kernel/kern.h"
#include "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level;
int edfstar_level, edfstar_level2, edfstar_level3;
int mybudget, mybudget2;
 
clear();
 
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
 
mybudget = CBSSTAR_setbudget(cbsstar_level, 2000, 50000);
edfstar_level = EDFSTAR_register_level(mybudget, cbsstar_level);
 
mybudget2 = CBSSTAR_setbudget(cbsstar_level, 10000, 25000);
edfstar_level2 = EDFSTAR_register_level(mybudget2, cbsstar_level);
edfstar_level3 = EDFSTAR_register_level(mybudget2, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
cprintf("edfstar_level=%d, edfstar_level2=%d\n",
edfstar_level,edfstar_level2);
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
//keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
#include <semaphore.h>
 
sem_t s;
 
void *star(void *arg)
{
int j,z;
 
for (;;) {
for (z=0; z<50; z++) {
for (j=0; j<60000; j++);
// sem_wait(&s);
cputs((char *)arg);
// sem_post(&s);
}
task_endcycle();
}
 
return NULL;
}
 
 
void create1()
{
HARD_TASK_MODEL m1;
PID p1a, p1b, p1c;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
 
 
 
hard_task_def_level(m1,2);
 
hard_task_def_arg(m1,(void *)"O");
hard_task_def_mit(m1,5000);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
 
hard_task_def_level(m1,3);
 
hard_task_def_arg(m1,(void *)".");
hard_task_def_mit(m1,5000);
p1b = task_create("b", star, &m1, NULL);
if (p1b == -1) {
perror("Could not create task c ...");
sys_end();
}
 
hard_task_def_level(m1,4);
 
hard_task_def_arg(m1,(void *)",");
hard_task_def_mit(m1,5000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
group_activate(1);
}
 
void endfun(KEY_EVT *k)
{
cprintf("ESC pressed!");
 
sys_end();
}
 
int main(int argc, char **argv)
{
KEY_EVT k;
 
set_exchandler_grx();
 
sem_init(&s,0,1);
 
k.flag = 0;
k.scan = KEY_ESC;
k.ascii = 27;
keyb_hook(k,endfun);
 
create1();
 
return 0;
}
 
/demos/trunk/first/test5.c
0,0 → 1,250
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: test5.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
The purpose of this test is to show that two budgets with different
period and budgets schedules correctly.
2 never ending tasks are involved
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "kernel/kern.h"
#include "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level;
int edfstar_level, edfstar_level2, edfstar_level3;
int mybudget, mybudget2;
 
clear();
 
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
 
mybudget = CBSSTAR_setbudget(cbsstar_level, 2000, 50000);
edfstar_level = EDFSTAR_register_level(mybudget, cbsstar_level);
 
mybudget2 = CBSSTAR_setbudget(cbsstar_level, 10000, 25000);
edfstar_level2 = EDFSTAR_register_level(mybudget2, cbsstar_level);
edfstar_level3 = EDFSTAR_register_level(mybudget2, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
cprintf("edfstar_level=%d, edfstar_level2=%d\n",
edfstar_level,edfstar_level2);
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
CBS_register_level(CBS_ENABLE_ALL, edfstar_level3);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
//keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
#include <semaphore.h>
 
sem_t s;
 
void *star(void *arg)
{
int j,z;
 
for (;;) {
for (z=0; z<50; z++) {
for (j=0; j<60000; j++);
// sem_wait(&s);
cputs((char *)arg);
// sem_post(&s);
}
task_endcycle();
}
 
return NULL;
}
 
 
void create1()
{
HARD_TASK_MODEL m1;
SOFT_TASK_MODEL ms;
PID p1a, p1b, p1c, p2;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
 
 
 
hard_task_def_level(m1,2);
 
hard_task_def_arg(m1,(void *)"O");
hard_task_def_mit(m1,5000);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
 
hard_task_def_level(m1,3);
 
hard_task_def_arg(m1,(void *)".");
hard_task_def_mit(m1,50000);
p1b = task_create("b", star, &m1, NULL);
if (p1b == -1) {
perror("Could not create task c ...");
sys_end();
}
 
hard_task_def_level(m1,4);
 
hard_task_def_arg(m1,(void *)",");
hard_task_def_mit(m1,50000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
soft_task_default_model(ms);
soft_task_def_met(ms, 5000);
soft_task_def_period(ms, 30000);
soft_task_def_group(ms,1);
soft_task_def_periodic(ms);
soft_task_def_level(ms,8);
soft_task_def_arg(ms,(void *)"X");
p2 = task_create("S", star, &ms, NULL);
if (p2 == -1) {
perror("Could not create task S ...");
sys_end();
}
 
group_activate(1);
}
 
void endfun(KEY_EVT *k)
{
cprintf("ESC pressed!");
 
sys_end();
}
 
int main(int argc, char **argv)
{
KEY_EVT k;
 
set_exchandler_grx();
 
sem_init(&s,0,1);
 
k.flag = 0;
k.scan = KEY_ESC;
k.ascii = 27;
keyb_hook(k,endfun);
 
create1();
 
return 0;
}
 
/demos/trunk/first/test6.c
0,0 → 1,250
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: test6.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
this test shows a set of 5 tasks (+main+dummy+keyboard driver).
The first 4 tasks are scheduled by a RMSTAR Module, whereas the
fifth one is a standard traditional EDF task. The 4 tasks uses a
budget of 10000/100000.
if edfstar.c is compiled with edfstar_printf3 active, a couple
(dline, curtime) is showed (in ms).
if cbsstar.c is compiled with cbsstar_printf3 active, the budget
replenishments are showed.
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "kernel/kern.h"
#include "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "rmstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level, rmstar_level, mybudget;
 
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
mybudget = CBSSTAR_setbudget(cbsstar_level, 10000, 100000);
rmstar_level = RMSTAR_register_level(mybudget, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
//keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
 
void *star(void *arg)
{
int i,j;
 
for (i=0; i<5; i++) {
for (j=0; j<100000; j++);
cputc('°');
cputs((char *)arg);
task_endcycle();
}
 
return NULL;
}
 
void *edftask(void *arg)
{
int i,j;
 
for (i=0; i<5; i++) {
for (j=0; j<100000; j++);
cputc('°');
cputs((char *)arg);
task_endcycle();
}
 
return NULL;
}
 
void create1()
{
HARD_TASK_MODEL m1, m2;
PID p1a, p1b, p1c, p1d, p2;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_level(m1,2);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
hard_task_def_arg(m1,(void *)"a");
hard_task_def_mit(m1,10000);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"b");
hard_task_def_mit(m1,15000);
p1b = task_create("b", star, &m1, NULL);
if (p1b == -1) {
perror("Could not create task b ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"c");
hard_task_def_mit(m1,20000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"d");
hard_task_def_mit(m1,30000);
p1d = task_create("d", star, &m1, NULL);
if (p1d == -1) {
perror("Could not create task d ...");
sys_end();
}
 
hard_task_default_model(m2);
hard_task_def_mit(m2,50000); // the budget has dline 100,000!
hard_task_def_wcet(m2, 5000);
hard_task_def_arg(m2,(void *)"Û");
hard_task_def_group(m2,1);
hard_task_def_periodic(m2);
 
p2 = task_create("2", edftask, &m2, NULL);
if (p2 == -1) {
perror("Could not create task edf ...");
sys_end();
}
 
cprintf("stars=%d %d %d %d, star2=%d\n", p1a, p1b, p1c, p1d, p2);
 
group_activate(1);
}
 
int main(int argc, char **argv)
{
char c;
 
set_exchandler_grx();
 
clear();
 
cprintf("Hello, world!");
 
create1();
 
do {
c =keyb_getch(BLOCK);
} while (c != ESC);
 
cprintf("ESC pressed!");
 
sys_end();
 
return 0;
}
 
/demos/trunk/first/cbsstar.h
0,0 → 1,157
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
 
/*
------------
CVS : $Id: cbsstar.h,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
This file contains the budget support for the multiapplication
scheduling algorithm proposed in the framework of the FIRST Project
 
Title:
CBSSTAR
 
Task Models Accepted:
None!
 
Guest Models Accepted:
BUDGET_TASK_MODEL - A task that is attached to a budget
int b; --> the number of the budget which the task is attached to
 
Description:
This module schedule its tasks following the CBS scheme.
Every task is inserted using the guest calls.
The module defines a limited set of budgets that the application
can use. Every guest task will use a particular budget; FIFO
scheduling is used inside a budget to schedule more than one ready
task attached to the same budget.
 
The tasks are inserted in an EDF level (or similar) with a JOB_TASK_MODEL,
and the CBS level expects that the task is scheduled with the absolute
deadline passed in the model.
 
This module tries to implement a simplified version of the guest
task interface:
- To insert a guest task, use guest_create
- When a task is dispatched, use guest_dispatch
- When a task have to be suspended, you have to use:
-> preemption: use guest_epilogue
-> synchronization, end: use guest_end
Remember: no check is done on the budget number passed with the model!!!
 
Exceptions raised:
XUNVALID_TASK
This level doesn't support normal tasks, but just guest tasks.
When a task operation is called, an exception is raised.
 
Restrictions & special features:
- This level doesn't manage the main task.
- At init time we have to specify:
. guarantee check
(when all task are created the system will check that the task_set
will not use more than the available bandwidth)
- A function to return the used bandwidth of the level is provided.
 
- A function is provided to allocate a buffer.
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#ifndef __CBSSTAR_H__
#define __CBSSTAR_H__
 
#include <kernel/kern.h>
 
//#include <ll/ll.h>
//#include <kernel/config.h>
//#include <sys/types.h>
//#include <kernel/types.h>
//#include <modules/codes.h>
 
/* -----------------------------------------------------------------------
BUDGET_TASK_MODEL: a model for guest tasks
----------------------------------------------------------------------- */
 
#define BUDGET_PCLASS 0x0600
typedef struct {
TASK_MODEL t;
int b;
} BUDGET_TASK_MODEL;
 
#define budget_task_default_model(m,buf) \
task_default_model((m).t, BUDGET_PCLASS), \
(m).b = (buf);
 
 
 
/* some constants for registering the Module in the right place */
#define CBSSTAR_LEVELNAME "CBSSTAR"
#define CBSSTAR_LEVEL_CODE 106
#define CBSSTAR_LEVEL_VERSION 1
 
 
 
 
/* Registration function:
int N Maximum number of budgets allocated for the applications
LEVEL master the level that must be used as master level for the
CBS tasks
*/
LEVEL CBSSTAR_register_level(int n, LEVEL master);
 
/* Allocates a budget to be used for an application.
Input parameters:
Q The budget
T The period of the budget
Return value:
0..N The ID of the budget
-1 no more free budgets
-2 The budgets allocated locally to this module have bandwidth > 1
-3 wrong LEVEL id
*/
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T);
 
#endif
/demos/trunk/first/rmstar.c
0,0 → 1,852
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: rmstar.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
**/
 
/*
* Copyright (C) 2001 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "rmstar.h"
#include <ll/stdio.h>
#include <ll/string.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
#include <kernel/trace.h>
 
/* for iqueues */
#include "iqueue.h"
 
/* for BUDGET_TASK_MODEL */
#include "cbsstar.h"
 
/*
* DEBUG stuffs begin
*/
 
//#define RMSTAR_DEBUG
 
#ifdef RMSTAR_DEBUF
 
static __inline__ fake_printf(char *fmt, ...) {}
 
#define rmstar_printf fake_printf
#define rmstar_printf2 fake_printf
#define rmstar_printf3 fake_printf
 
//#define rmstar_printf kern_printf
//#define rmstar_printf2 kern_printf
//#define rmstar_printf3 kern_printf
#endif
 
/*
* DEBUG stuffs end
*/
 
/* Status used in the level */
#define RMSTAR_READY MODULE_STATUS_BASE /* - Ready status */
#define RMSTAR_IDLE MODULE_STATUS_BASE+4 /* to wait the deadline */
 
/* flags */
#define RMSTAR_FLAG_NORAISEEXC 2
 
/* the level redefinition for the Earliest Deadline First level */
typedef struct {
level_des l; /* the standard level descriptor */
 
TIME period[MAX_PROC]; /* The task periods; the deadlines are
stored in the priority field */
int deadline_timer[MAX_PROC];
/* The task deadline timers */
 
struct timespec deadline_timespec[MAX_PROC];
 
int dline_miss[MAX_PROC]; /* Deadline miss counter */
int wcet_miss[MAX_PROC]; /* Wcet miss counter */
 
int nact[MAX_PROC]; /* Wcet miss counter */
 
int flag[MAX_PROC];
/* used to manage the JOB_TASK_MODEL and the
periodicity */
 
IQUEUE ready; /* the ready queue */
 
PID activated; /* the task that has been inserted into the
master module */
 
int budget;
 
int scheduling_level;
} RMSTAR_level_des;
 
static void RMSTAR_check_preemption(RMSTAR_level_des *lev)
{
PID first;
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:chk)");
#endif
 
if ((first = iq_queryfirst(&lev->ready)) != lev->activated) {
if (lev->activated != NIL)
level_table[ lev->scheduling_level ]->
guest_end(lev->scheduling_level, lev->activated);
 
lev->activated = first;
 
if (first != NIL) {
BUDGET_TASK_MODEL b;
budget_task_default_model(b, lev->budget);
 
level_table[ lev->scheduling_level ]->
guest_create(lev->scheduling_level, first, (TASK_MODEL *)&b);
}
}
}
 
static void RMSTAR_timer_deadline(void *par);
 
static void RMSTAR_internal_activate(RMSTAR_level_des *lev, PID p)
{
struct timespec temp;
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:iact)");
#endif
 
TIMESPEC_ASSIGN(&temp, &proc_table[p].request_time);
ADDUSEC2TIMESPEC(lev->period[p], &temp);
 
*iq_query_timespec(p, &lev->ready) = temp;
lev->deadline_timespec[p] = temp;
 
/* Insert task in the correct position */
proc_table[p].status = RMSTAR_READY;
iq_priority_insert(p,&lev->ready);
 
/* needed because when there is a wcet miss I disable CONTROL_CAP */
proc_table[p].control |= CONTROL_CAP;
 
/* check for preemption */
RMSTAR_check_preemption(lev);
}
 
static char *RMSTAR_status_to_a(WORD status)
{
if (status < MODULE_STATUS_BASE)
return status_to_a(status);
 
switch (status) {
case RMSTAR_READY : return "RMSTAR_Ready";
case RMSTAR_IDLE : return "RMSTAR_Idle";
default : return "RMSTAR_Unknown";
}
}
 
static void RMSTAR_timer_deadline(void *par)
{
PID p = (PID) par;
RMSTAR_level_des *lev;
 
#ifdef RMSTAR_DEBUG
// rmstar_printf("(E:tdl ");
#endif
 
lev = (RMSTAR_level_des *)level_table[proc_table[p].task_level];
 
switch (proc_table[p].status) {
case RMSTAR_IDLE:
#ifdef RMSTAR_DEBUG
// rmstar_printf2("I%d",p);
#endif
/* set the request time */
proc_table[p].request_time = *iq_query_timespec(p, &lev->ready);
 
RMSTAR_internal_activate(lev,p);
 
event_need_reschedule();
break;
 
default:
#ifdef RMSTAR_DEBUG
// rmstar_printf2("D%d",p);
#endif
/* else, a deadline miss occurred!!! */
lev->dline_miss[p]++;
 
/* the task is into another state */
lev->nact[p]++;
 
/* Set the deadline timer */
ADDUSEC2TIMESPEC(lev->period[p], &lev->deadline_timespec[p]);
}
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
RMSTAR_timer_deadline,
(void *)p);
 
#ifdef RMSTAR_DEBUG
// rmstar_printf(")");
#endif
}
 
static void RMSTAR_timer_guest_deadline(void *par)
{
PID p = (PID) par;
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:gdl)");
#endif
 
kern_raise(XDEADLINE_MISS,p);
}
 
static int RMSTAR_level_accept_task_model(LEVEL l, TASK_MODEL *m)
{
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:lacct)");
#endif
 
if (m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l)) {
HARD_TASK_MODEL *h = (HARD_TASK_MODEL *)m;
 
if (h->wcet && h->mit && h->periodicity == PERIODIC)
return 0;
}
 
return -1;
}
 
static int RMSTAR_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
{
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:laccg)");
#endif
 
if (m->pclass == JOB_PCLASS || m->pclass == (JOB_PCLASS | l))
return 0;
else
return -1;
}
 
 
static char *onoff(int i)
{
if (i)
return "On ";
else
return "Off";
}
 
static void RMSTAR_level_status(LEVEL l)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
PID p = iq_queryfirst(&lev->ready);
struct timespec temp;
kern_printf("Budget number : %u\n", lev->budget);
kern_printf("Master level : %u\n", lev->scheduling_level);
kern_printf("Active PID : %u\n", lev->activated);
while (p != NIL) {
if ((proc_table[p].pclass) == JOB_PCLASS)
kern_printf("Pid: %2d (GUEST)\n", p);
else {
temp = *iq_query_timespec(p, &lev->ready);
kern_printf("Pid: %2d Name: %10s %s: %9ld Dline: %9ld.%6ld Stat: %s\n",
p,
proc_table[p].name,
"Period ",
lev->period[p],
temp.tv_sec,
temp.tv_nsec/1000,
RMSTAR_status_to_a(proc_table[p].status));
p = proc_table[p].next;
}
}
for (p=0; p<MAX_PROC; p++)
if (proc_table[p].task_level == l
&& proc_table[p].status != RMSTAR_READY
&& proc_table[p].status != FREE ) {
temp = *iq_query_timespec(p, &lev->ready);
kern_printf("Pid: %2d Name: %10s %s: %9ld Dline: %9ld.%6ld Stat: %s\n",
p,
proc_table[p].name,
"Period ",
lev->period[p],
temp.tv_sec,
temp.tv_nsec/1000,
RMSTAR_status_to_a(proc_table[p].status));
}
}
 
/* The scheduler only gets the first task in the queue */
static PID RMSTAR_level_scheduler(LEVEL l)
{
//RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
return NIL;
}
 
static int RMSTAR_task_create(LEVEL l, PID p, TASK_MODEL *m)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
/* if the RMSTAR_task_create is called, then the pclass must be a
valid pclass. */
HARD_TASK_MODEL *h = (HARD_TASK_MODEL *)m;
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:tcr)");
#endif
 
lev->period[p] = h->mit;
*iq_query_priority(p, &lev->ready) = h->mit;
 
lev->flag[p] = 0;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
/* Enable wcet check */
proc_table[p].avail_time = h->wcet;
proc_table[p].wcet = h->wcet;
proc_table[p].control |= CONTROL_CAP;
 
return 0; /* OK, also if the task cannot be guaranteed... */
}
 
static void RMSTAR_task_detach(LEVEL l, PID p)
{
#ifdef RMSTAR_DEBUG
rmstar_printf2("(E:tdt)");
#endif
}
 
static int RMSTAR_task_eligible(LEVEL l, PID p)
{
#ifdef RMSTAR_DEBUG
rmstar_printf2("(E:eli)");
#endif
 
return 0; /* if the task p is chosen, it is always eligible */
}
 
static void RMSTAR_task_dispatch(LEVEL l, PID p, int nostop)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:dis)");
 
rmstar_printf3("(%d %d)",
iq_query_timespec(p, &lev->ready)->tv_nsec/1000000,
schedule_time.tv_nsec/1000000);
#endif
 
level_table[ lev->scheduling_level ]->
guest_dispatch(lev->scheduling_level,p,nostop);
}
 
static void RMSTAR_task_epilogue(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:epi ");
#endif
 
/* check if the wcet is finished... */
if (proc_table[p].avail_time <= 0 && proc_table[p].control&CONTROL_CAP) {
/* wcet finished: disable wcet event and count wcet miss */
#ifdef RMSTAR_DEBUG
rmstar_printf2("W%d",p);
#endif
proc_table[p].control &= ~CONTROL_CAP;
lev->wcet_miss[p]++;
}
#ifdef RMSTAR_DEBUG
rmstar_printf(")");
#endif
 
level_table[ lev->scheduling_level ]->
guest_epilogue(lev->scheduling_level,p);
 
proc_table[p].status = RMSTAR_READY;
}
 
static void RMSTAR_task_activate(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:act)");
#endif
 
/* Test if we are trying to activate a non sleeping task */
/* save activation (only if needed... */
if (proc_table[p].status != SLEEP) {
/* a periodic task cannot be activated when it is already active */
kern_raise(XACTIVATION,p);
return;
}
 
ll_gettime(TIME_EXACT, &proc_table[p].request_time);
 
RMSTAR_internal_activate(lev,p);
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
RMSTAR_timer_deadline,
(void *)p);
 
}
 
static void RMSTAR_task_insert(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:ins)");
#endif
 
/* Insert task in the correct position */
proc_table[p].status = RMSTAR_READY;
iq_priority_insert(p,&lev->ready);
 
/* and check for preemption! */
RMSTAR_check_preemption(lev);
}
 
static void RMSTAR_task_extract(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:ext)");
#endif
 
/* the task is blocked on a synchronization primitive. we have to
remove it from the master module -and- from the local queue! */
iq_extract(p,&lev->ready);
 
/* and finally, a preemption check! (it will also call guest_end) */
RMSTAR_check_preemption(lev);
}
 
static void RMSTAR_task_endcycle(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
struct timespec temp;
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:ecy ");
#endif
 
/* we call guest_end directly here because the same task may
be reinserted in the queue before calling the preemption check! */
level_table[ lev->scheduling_level ]->
guest_end(lev->scheduling_level,p);
lev->activated = NIL;
 
iq_extract(p,&lev->ready);
 
/* we reset the capacity counters... */
proc_table[p].avail_time = proc_table[p].wcet;
 
if (lev->nact[p] > 0) {
#ifdef RMSTAR_DEBUG
rmstar_printf2("E%d",p);
#endif
 
/* Pending activation: reactivate the thread!!! */
lev->nact[p]--;
 
/* see also RMSTAR_timer_deadline */
ll_gettime(TIME_EXACT, &proc_table[p].request_time);
 
RMSTAR_internal_activate(lev,p);
 
/* check if the deadline has already expired */
temp = *iq_query_timespec(p, &lev->ready);
if (TIMESPEC_A_LT_B(&temp, &schedule_time)) {
/* count the deadline miss */
lev->dline_miss[p]++;
event_delete(lev->deadline_timer[p]);
}
 
}
else {
#ifdef RMSTAR_DEBUG
rmstar_printf("e%d",p);
#endif
 
/* the task has terminated his job before it consume the wcet. All OK! */
proc_table[p].status = RMSTAR_IDLE;
 
/* and finally, a preemption check! */
RMSTAR_check_preemption(lev);
 
/* when the deadline timer fire, it recognize the situation and set
correctly all the stuffs (like reactivation, request_time, etc... ) */
}
#ifdef RMSTAR_DEBUG
rmstar_printf(")");
#endif
}
 
static void RMSTAR_task_end(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:end)");
#endif
 
iq_extract(p,&lev->ready);
 
/* we finally put the task in the ready queue */
proc_table[p].status = FREE;
q_insertfirst(p,&freedesc);
if (lev->deadline_timer[p] != -1) {
event_delete(lev->deadline_timer[p]);
}
 
/* and finally, a preemption check! (it will also call guest_end) */
RMSTAR_check_preemption(lev);
}
 
static void RMSTAR_task_sleep(LEVEL l, PID p)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static void RMSTAR_task_delay(LEVEL l, PID p, TIME usdelay)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
/* Guest Functions
These functions manages a JOB_TASK_MODEL, that is used to put
a guest task in the RMSTAR ready queue. */
 
static int RMSTAR_guest_create(LEVEL l, PID p, TASK_MODEL *m)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
JOB_TASK_MODEL *job = (JOB_TASK_MODEL *)m;
 
/* if the RMSTAR_guest_create is called, then the pclass must be a
valid pclass. */
 
*iq_query_timespec(p, &lev->ready) = job->deadline;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
if (job->noraiseexc)
lev->flag[p] = RMSTAR_FLAG_NORAISEEXC;
else
lev->flag[p] = 0;
 
lev->period[p] = job->period;
*iq_query_priority(p, &lev->ready) = job->period;
 
/* there is no bandwidth guarantee at this level, it is performed
by the level that inserts guest tasks... */
 
return 0; /* OK, also if the task cannot be guaranteed... */
}
 
static void RMSTAR_guest_detach(LEVEL l, PID p)
{
/* the RMSTAR level doesn't introduce any dinamic allocated new field.
No guarantee is performed on guest tasks... so we don't have to reset
the NO_GUARANTEE FIELD */
}
 
static void RMSTAR_guest_dispatch(LEVEL l, PID p, int nostop)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
level_table[ lev->scheduling_level ]->
guest_dispatch(lev->scheduling_level,p,nostop);
}
 
static void RMSTAR_guest_epilogue(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
/* the task has been preempted. it returns into the ready queue... */
level_table[ lev->scheduling_level ]->
guest_epilogue(lev->scheduling_level,p);
 
proc_table[p].status = RMSTAR_READY;
}
 
static void RMSTAR_guest_activate(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
/* Insert task in the correct position */
iq_priority_insert(p,&lev->ready);
proc_table[p].status = RMSTAR_READY;
 
/* check for preemption */
RMSTAR_check_preemption(lev);
 
/* Set the deadline timer */
if (!(lev->flag[p] & RMSTAR_FLAG_NORAISEEXC))
lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
RMSTAR_timer_guest_deadline,
(void *)p);
 
}
 
static void RMSTAR_guest_insert(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
/* Insert task in the correct position */
iq_priority_insert(p,&lev->ready);
proc_table[p].status = RMSTAR_READY;
 
/* and check for preemption! */
RMSTAR_check_preemption(lev);
}
 
static void RMSTAR_guest_extract(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
/* the task is blocked on a synchronization primitive. we have to
remove it from the master module -and- from the local queue! */
iq_extract(p,&lev->ready);
 
/* and finally, a preemption check! (it will also call guest_end() */
RMSTAR_check_preemption(lev);
}
 
static void RMSTAR_guest_end(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
//kern_printf("RMSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
#endif
 
iq_extract(p, &lev->ready);
 
/* we remove the deadline timer, because the slice is finished */
if (lev->deadline_timer[p] != NIL) {
#ifdef RMSTAR_DEBUG
// kern_printf("RMSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
#endif
event_delete(lev->deadline_timer[p]);
lev->deadline_timer[p] = NIL;
}
 
/* and finally, a preemption check! (it will also call guest_end() */
RMSTAR_check_preemption(lev);
}
 
static void RMSTAR_guest_endcycle(LEVEL l, PID p)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
static void RMSTAR_guest_sleep(LEVEL l, PID p)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
static void RMSTAR_guest_delay(LEVEL l, PID p, TIME usdelay)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
/* Registration functions */
 
/* Registration function:
int flags the init flags ... see RMSTAR.h */
LEVEL RMSTAR_register_level(int budget, int master)
{
LEVEL l; /* the level that we register */
RMSTAR_level_des *lev; /* for readableness only */
PID i; /* a counter */
 
#ifdef RMSTAR_DEBUG
printk("RMSTAR_register_level\n");
#endif
 
/* request an entry in the level_table */
l = level_alloc_descriptor();
 
#ifdef RMSTAR_DEBUG
printk(" alloco descrittore %d %d\n",l,(int)sizeof(RMSTAR_level_des));
#endif
 
/* alloc the space needed for the RMSTAR_level_des */
lev = (RMSTAR_level_des *)kern_alloc(sizeof(RMSTAR_level_des));
 
#ifdef RMSTAR_DEBUG
printk(" lev=%d\n",(int)lev);
#endif
 
/* update the level_table with the new entry */
level_table[l] = (level_des *)lev;
 
/* fill the standard descriptor */
strncpy(lev->l.level_name, RMSTAR_LEVELNAME, MAX_LEVELNAME);
lev->l.level_code = RMSTAR_LEVEL_CODE;
lev->l.level_version = RMSTAR_LEVEL_VERSION;
 
lev->l.level_accept_task_model = RMSTAR_level_accept_task_model;
lev->l.level_accept_guest_model = RMSTAR_level_accept_guest_model;
lev->l.level_status = RMSTAR_level_status;
lev->l.level_scheduler = RMSTAR_level_scheduler;
lev->l.level_guarantee = NULL;
lev->l.task_create = RMSTAR_task_create;
lev->l.task_detach = RMSTAR_task_detach;
lev->l.task_eligible = RMSTAR_task_eligible;
lev->l.task_dispatch = RMSTAR_task_dispatch;
lev->l.task_epilogue = RMSTAR_task_epilogue;
lev->l.task_activate = RMSTAR_task_activate;
lev->l.task_insert = RMSTAR_task_insert;
lev->l.task_extract = RMSTAR_task_extract;
lev->l.task_endcycle = RMSTAR_task_endcycle;
lev->l.task_end = RMSTAR_task_end;
lev->l.task_sleep = RMSTAR_task_sleep;
lev->l.task_delay = RMSTAR_task_delay;
 
lev->l.guest_create = RMSTAR_guest_create;
lev->l.guest_detach = RMSTAR_guest_detach;
lev->l.guest_dispatch = RMSTAR_guest_dispatch;
lev->l.guest_epilogue = RMSTAR_guest_epilogue;
lev->l.guest_activate = RMSTAR_guest_activate;
lev->l.guest_insert = RMSTAR_guest_insert;
lev->l.guest_extract = RMSTAR_guest_extract;
lev->l.guest_endcycle = RMSTAR_guest_endcycle;
lev->l.guest_end = RMSTAR_guest_end;
lev->l.guest_sleep = RMSTAR_guest_sleep;
lev->l.guest_delay = RMSTAR_guest_delay;
 
/* fill the RMSTAR descriptor part */
for(i=0; i<MAX_PROC; i++) {
lev->period[i] = 0;
lev->deadline_timer[i] = -1;
lev->flag[i] = 0;
lev->dline_miss[i] = 0;
lev->wcet_miss[i] = 0;
lev->nact[i] = 0;
}
 
iq_init(&lev->ready, NULL, 0);
lev->activated = NIL;
 
lev->budget = budget;
lev->scheduling_level = master;
 
return l;
}
 
int RMSTAR_get_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
if (lev->l.level_code == RMSTAR_LEVEL_CODE &&
lev->l.level_version == RMSTAR_LEVEL_VERSION)
return lev->dline_miss[p];
else
return -1;
}
 
int RMSTAR_get_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
if (lev->l.level_code == RMSTAR_LEVEL_CODE &&
lev->l.level_version == RMSTAR_LEVEL_VERSION)
return lev->wcet_miss[p];
else
return -1;
}
 
int RMSTAR_get_nact(PID p)
{
LEVEL l = proc_table[p].task_level;
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
if (lev->l.level_code == RMSTAR_LEVEL_CODE &&
lev->l.level_version == RMSTAR_LEVEL_VERSION)
return lev->nact[p];
else
return -1;
}
 
int RMSTAR_reset_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
if (lev->l.level_code == RMSTAR_LEVEL_CODE &&
lev->l.level_version == RMSTAR_LEVEL_VERSION)
{
lev->dline_miss[p] = 0;
return 0;
}
else
return -1;
}
 
int RMSTAR_reset_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
if (lev->l.level_code == RMSTAR_LEVEL_CODE &&
lev->l.level_version == RMSTAR_LEVEL_VERSION)
{
lev->wcet_miss[p] = 0;
return 0;
}
else
return -1;
}
 
/demos/trunk/first/testiq.c
0,0 → 1,259
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: testiq.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
The purpose of this test is to show that two budgets with different
period and budgets schedules correctly.
2 never ending tasks are involved
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "kernel/kern.h"
#include "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
clear();
 
EDF_register_level(EDF_ENABLE_ALL);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
//keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
#include "iqueue.h"
 
sem_t s;
 
PID p2,p3,p4;
 
void *star(void *arg)
{
int j;
TIME last[5];
 
QUEUE i = NIL;
IQUEUE ii;
 
q_timespec_insert(p2,&i);
q_timespec_insert(p3,&i);
 
iq_init(&ii,NULL,0);
*iq_query_timespec(p2,&ii) = proc_table[p2].timespec_priority;
*iq_query_timespec(p3,&ii) = proc_table[p3].timespec_priority;
*iq_query_timespec(p4,&ii) = proc_table[p4].timespec_priority;
iq_timespec_insert(p2,&ii);
iq_timespec_insert(p3,&ii);
 
cprintf("p2=%ld.%ld\n",proc_table[p2].timespec_priority.tv_sec,proc_table[p2].timespec_priority.tv_nsec/1000);
cprintf("p3=%ld.%ld\n",proc_table[p3].timespec_priority.tv_sec,proc_table[p3].timespec_priority.tv_nsec/1000);
cprintf("p4=%ld.%ld\n",proc_table[p4].timespec_priority.tv_sec,proc_table[p4].timespec_priority.tv_nsec/1000);
 
task_endcycle();
 
for (j=0; j<200000; j++) {
q_timespec_insert(p4,&i);
q_extract(p4,&i);
}
 
 
task_endcycle();
 
for (j=0; j<200000; j++) {
iq_timespec_insert(p4,&ii);
iq_extract(p4,&ii);
}
 
task_endcycle();
 
jet_gettable(exec_shadow, &last[0], 3);
 
cprintf("\ninit=%d queue=%d iqueue=%d\n",
(int)last[0], (int)last[1], (int)last[2]);
 
sys_end();
return NULL;
}
 
void *fake(void *arg)
{
cputs("#");
task_endcycle();
 
return NULL;
}
 
 
void create1()
{
HARD_TASK_MODEL m1;
PID p1a;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 500000);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
hard_task_def_mit(m1,1000000);
hard_task_def_ctrl_jet(m1);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_aperiodic(m1);
hard_task_def_group(m1,1);
 
hard_task_def_mit(m1,100000);
p2 = task_create("a", fake, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_def_mit(m1,100001);
p3 = task_create("a", fake, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_def_mit(m1,100002);
p4 = task_create("a", fake, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
group_activate(1);
}
 
void endfun(KEY_EVT *k)
{
cprintf("ESC pressed!");
 
sys_end();
}
 
int main(int argc, char **argv)
{
KEY_EVT k;
 
set_exchandler_grx();
 
sem_init(&s,0,1);
 
k.flag = 0;
k.scan = KEY_ESC;
k.ascii = 27;
keyb_hook(k,endfun);
 
create1();
 
return 0;
}
 
/demos/trunk/first/rmstar.h
0,0 → 1,129
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: rmstar.h,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
Title:
RMSTAR
 
Task Models Accepted:
HARD_TASK_MODEL - Hard Tasks (only Periodic)
wcet field and mit field must be != 0. They are used to set the wcet
and period of the tasks.
periodicity field can be only PERIODIC
drel field is ignored
Guest Models Accepted:
JOB_TASK_MODEL - a single guest task activation
Identified by an absolute deadline and a period.
period field is ignored
 
Description:
 
This module schedule his tasks following the classic RM
scheme.
 
Note: This module is derived from the EDFSTAR Scheduling Module. I
have just changed RM in EDF and iq_timespec_insert with
iq_priority_insert...
 
Exceptions raised:
XUNVALID_GUEST XUNVALID_TASK
some primitives are not implemented:
task_sleep, task_delay, guest_endcycle, guest_sleep, guest_delay
 
XACTIVATION
If a task is actiated through task_activate or guest_activate more than
one time
Restrictions & special features:
see edfstar.h
 
**/
 
/*
* Copyright (C) 2001 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#ifndef __RMSTAR_H__
#define __RMSTAR_H__
 
#include <ll/ll.h>
#include <kernel/config.h>
#include <sys/types.h>
#include <kernel/types.h>
#include <modules/codes.h>
 
 
 
/* flags... */
#define RMSTAR_ENABLE_GUARANTEE 1 /* Task Guarantee enabled */
#define RMSTAR_ENABLE_ALL 1
 
#define RMSTAR_FAILED_GUARANTEE 8 /* used in the module, unsettabl
in RM_register_level... */
 
 
 
#define RMSTAR_LEVELNAME "RMSTAR base"
#define RMSTAR_LEVEL_CODE 166
#define RMSTAR_LEVEL_VERSION 1
 
 
/* Registration function:
int budget The budget used by this module (see CBSSTAR.h)
int master The master module used by RMSTAR
*/
LEVEL RMSTAR_register_level(int budget, int master);
 
/* returns respectively the number of dline, wcet or nact; -1 if error */
int RMSTAR_get_dline_miss(PID p);
int RMSTAR_get_wcet_miss(PID p);
int RMSTAR_get_nact(PID p);
 
/* resets respectively the number of dline, wcet miss; -1 if error */
int RMSTAR_reset_dline_miss(PID p);
int RMSTAR_reset_wcet_miss(PID p);
 
#endif
 
/demos/trunk/first/edfstar.c
0,0 → 1,850
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: edfstar.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
**/
 
/*
* Copyright (C) 2001 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "edfstar.h"
#include <ll/stdio.h>
#include <ll/string.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
#include <kernel/trace.h>
 
/* for iqueues */
#include "iqueue.h"
 
/* for BUDGET_TASK_MODEL */
#include "cbsstar.h"
 
/*
* DEBUG stuffs begin
*/
 
//#define EDFSTAR_DEBUG
 
#ifdef EDFSTAR_DEBUF
 
static __inline__ fake_printf(char *fmt, ...) {}
 
#define edfstar_printf fake_printf
#define edfstar_printf2 fake_printf
#define edfstar_printf3 fake_printf
 
//#define edfstar_printf kern_printf
//#define edfstar_printf2 kern_printf
//#define edfstar_printf3 kern_printf
#endif
 
/*
* DEBUG stuffs end
*/
 
/* Status used in the level */
#define EDFSTAR_READY MODULE_STATUS_BASE /* - Ready status */
#define EDFSTAR_IDLE MODULE_STATUS_BASE+4 /* to wait the deadline */
 
/* flags */
#define EDFSTAR_FLAG_NORAISEEXC 2
 
/* the level redefinition for the Earliest Deadline First level */
typedef struct {
level_des l; /* the standard level descriptor */
 
TIME period[MAX_PROC]; /* The task periods; the deadlines are
stored in the priority field */
int deadline_timer[MAX_PROC];
/* The task deadline timers */
 
struct timespec deadline_timespec[MAX_PROC];
 
int dline_miss[MAX_PROC]; /* Deadline miss counter */
int wcet_miss[MAX_PROC]; /* Wcet miss counter */
 
int nact[MAX_PROC]; /* Wcet miss counter */
 
int flag[MAX_PROC];
/* used to manage the JOB_TASK_MODEL and the
periodicity */
 
IQUEUE ready; /* the ready queue */
 
PID activated; /* the task that has been inserted into the
master module */
 
int budget;
 
int scheduling_level;
} EDFSTAR_level_des;
 
static void EDFSTAR_check_preemption(EDFSTAR_level_des *lev)
{
PID first;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:chk)");
#endif
 
if ((first = iq_queryfirst(&lev->ready)) != lev->activated) {
if (lev->activated != NIL)
level_table[ lev->scheduling_level ]->
guest_end(lev->scheduling_level, lev->activated);
 
lev->activated = first;
 
if (first != NIL) {
BUDGET_TASK_MODEL b;
budget_task_default_model(b, lev->budget);
 
level_table[ lev->scheduling_level ]->
guest_create(lev->scheduling_level, first, (TASK_MODEL *)&b);
}
}
}
 
static void EDFSTAR_timer_deadline(void *par);
 
static void EDFSTAR_internal_activate(EDFSTAR_level_des *lev, PID p)
{
struct timespec temp;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:iact)");
#endif
 
TIMESPEC_ASSIGN(&temp, &proc_table[p].request_time);
ADDUSEC2TIMESPEC(lev->period[p], &temp);
 
*iq_query_timespec(p, &lev->ready) = temp;
lev->deadline_timespec[p] = temp;
 
/* Insert task in the correct position */
proc_table[p].status = EDFSTAR_READY;
iq_timespec_insert(p,&lev->ready);
 
/* needed because when there is a wcet miss I disable CONTROL_CAP */
proc_table[p].control |= CONTROL_CAP;
 
/* check for preemption */
EDFSTAR_check_preemption(lev);
}
 
static char *EDFSTAR_status_to_a(WORD status)
{
if (status < MODULE_STATUS_BASE)
return status_to_a(status);
 
switch (status) {
case EDFSTAR_READY : return "EDFSTAR_Ready";
case EDFSTAR_IDLE : return "EDFSTAR_Idle";
default : return "EDFSTAR_Unknown";
}
}
 
static void EDFSTAR_timer_deadline(void *par)
{
PID p = (PID) par;
EDFSTAR_level_des *lev;
 
#ifdef EDFSTAR_DEBUG
// edfstar_printf("(E:tdl ");
#endif
 
lev = (EDFSTAR_level_des *)level_table[proc_table[p].task_level];
 
switch (proc_table[p].status) {
case EDFSTAR_IDLE:
#ifdef EDFSTAR_DEBUG
// edfstar_printf2("I%d",p);
#endif
/* set the request time */
proc_table[p].request_time = *iq_query_timespec(p, &lev->ready);
 
EDFSTAR_internal_activate(lev,p);
 
event_need_reschedule();
break;
 
default:
#ifdef EDFSTAR_DEBUG
// edfstar_printf2("D%d",p);
#endif
/* else, a deadline miss occurred!!! */
lev->dline_miss[p]++;
 
/* the task is into another state */
lev->nact[p]++;
 
/* Set the deadline timer */
ADDUSEC2TIMESPEC(lev->period[p], &lev->deadline_timespec[p]);
}
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
EDFSTAR_timer_deadline,
(void *)p);
 
#ifdef EDFSTAR_DEBUG
// edfstar_printf(")");
#endif
}
 
static void EDFSTAR_timer_guest_deadline(void *par)
{
PID p = (PID) par;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:gdl)");
#endif
 
kern_raise(XDEADLINE_MISS,p);
}
 
static int EDFSTAR_level_accept_task_model(LEVEL l, TASK_MODEL *m)
{
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:lacct)");
#endif
 
if (m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l)) {
HARD_TASK_MODEL *h = (HARD_TASK_MODEL *)m;
 
if (h->wcet && h->mit && h->periodicity == PERIODIC)
return 0;
}
 
return -1;
}
 
static int EDFSTAR_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
{
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:laccg)");
#endif
 
if (m->pclass == JOB_PCLASS || m->pclass == (JOB_PCLASS | l))
return 0;
else
return -1;
}
 
 
static char *onoff(int i)
{
if (i)
return "On ";
else
return "Off";
}
 
static void EDFSTAR_level_status(LEVEL l)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
PID p = iq_queryfirst(&lev->ready);
struct timespec temp;
kern_printf("Budget number : %u\n", lev->budget);
kern_printf("Master level : %u\n", lev->scheduling_level);
kern_printf("Active PID : %u\n", lev->activated);
while (p != NIL) {
if ((proc_table[p].pclass) == JOB_PCLASS)
kern_printf("Pid: %2d (GUEST)\n", p);
else {
temp = *iq_query_timespec(p, &lev->ready);
kern_printf("Pid: %2d Name: %10s %s: %9ld Dline: %9ld.%6ld Stat: %s\n",
p,
proc_table[p].name,
"Period ",
lev->period[p],
temp.tv_sec,
temp.tv_nsec/1000,
EDFSTAR_status_to_a(proc_table[p].status));
p = proc_table[p].next;
}
}
for (p=0; p<MAX_PROC; p++)
if (proc_table[p].task_level == l
&& proc_table[p].status != EDFSTAR_READY
&& proc_table[p].status != FREE ) {
temp = *iq_query_timespec(p, &lev->ready);
kern_printf("Pid: %2d Name: %10s %s: %9ld Dline: %9ld.%6ld Stat: %s\n",
p,
proc_table[p].name,
"Period ",
lev->period[p],
temp.tv_sec,
temp.tv_nsec/1000,
EDFSTAR_status_to_a(proc_table[p].status));
}
}
 
/* The scheduler only gets the first task in the queue */
static PID EDFSTAR_level_scheduler(LEVEL l)
{
//EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
return NIL;
}
 
static int EDFSTAR_task_create(LEVEL l, PID p, TASK_MODEL *m)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
/* if the EDFSTAR_task_create is called, then the pclass must be a
valid pclass. */
HARD_TASK_MODEL *h = (HARD_TASK_MODEL *)m;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:tcr)");
#endif
 
lev->period[p] = h->mit;
 
lev->flag[p] = 0;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
/* Enable wcet check */
proc_table[p].avail_time = h->wcet;
proc_table[p].wcet = h->wcet;
proc_table[p].control |= CONTROL_CAP;
 
return 0; /* OK, also if the task cannot be guaranteed... */
}
 
static void EDFSTAR_task_detach(LEVEL l, PID p)
{
#ifdef EDFSTAR_DEBUG
edfstar_printf2("(E:tdt)");
#endif
}
 
static int EDFSTAR_task_eligible(LEVEL l, PID p)
{
#ifdef EDFSTAR_DEBUG
edfstar_printf2("(E:eli)");
#endif
 
return 0; /* if the task p is chosen, it is always eligible */
}
 
static void EDFSTAR_task_dispatch(LEVEL l, PID p, int nostop)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:dis)");
 
edfstar_printf3("(%d %d)",
iq_query_timespec(p, &lev->ready)->tv_nsec/1000000,
schedule_time.tv_nsec/1000000);
#endif
 
level_table[ lev->scheduling_level ]->
guest_dispatch(lev->scheduling_level,p,nostop);
}
 
static void EDFSTAR_task_epilogue(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:epi ");
#endif
 
/* check if the wcet is finished... */
if (proc_table[p].avail_time <= 0 && proc_table[p].control&CONTROL_CAP) {
/* wcet finished: disable wcet event and count wcet miss */
#ifdef EDFSTAR_DEBUG
edfstar_printf2("W%d",p);
#endif
proc_table[p].control &= ~CONTROL_CAP;
lev->wcet_miss[p]++;
}
#ifdef EDFSTAR_DEBUG
edfstar_printf(")");
#endif
 
level_table[ lev->scheduling_level ]->
guest_epilogue(lev->scheduling_level,p);
 
proc_table[p].status = EDFSTAR_READY;
}
 
static void EDFSTAR_task_activate(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:act)");
#endif
 
/* Test if we are trying to activate a non sleeping task */
/* save activation (only if needed... */
if (proc_table[p].status != SLEEP) {
/* a periodic task cannot be activated when it is already active */
kern_raise(XACTIVATION,p);
return;
}
 
ll_gettime(TIME_EXACT, &proc_table[p].request_time);
 
EDFSTAR_internal_activate(lev,p);
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
EDFSTAR_timer_deadline,
(void *)p);
 
}
 
static void EDFSTAR_task_insert(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:ins)");
#endif
 
/* Insert task in the correct position */
proc_table[p].status = EDFSTAR_READY;
iq_timespec_insert(p,&lev->ready);
 
/* and check for preemption! */
EDFSTAR_check_preemption(lev);
}
 
static void EDFSTAR_task_extract(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:ext)");
#endif
 
/* the task is blocked on a synchronization primitive. we have to
remove it from the master module -and- from the local queue! */
iq_extract(p,&lev->ready);
 
/* and finally, a preemption check! (it will also call guest_end) */
EDFSTAR_check_preemption(lev);
}
 
static void EDFSTAR_task_endcycle(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
struct timespec temp;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:ecy ");
#endif
 
/* we call guest_end directly here because the same task may
be reinserted in the queue before calling the preemption check! */
level_table[ lev->scheduling_level ]->
guest_end(lev->scheduling_level,p);
lev->activated = NIL;
 
iq_extract(p,&lev->ready);
 
/* we reset the capacity counters... */
proc_table[p].avail_time = proc_table[p].wcet;
 
if (lev->nact[p] > 0) {
#ifdef EDFSTAR_DEBUG
edfstar_printf2("E%d",p);
#endif
 
/* Pending activation: reactivate the thread!!! */
lev->nact[p]--;
 
/* see also EDFSTAR_timer_deadline */
ll_gettime(TIME_EXACT, &proc_table[p].request_time);
 
EDFSTAR_internal_activate(lev,p);
 
/* check if the deadline has already expired */
temp = *iq_query_timespec(p, &lev->ready);
if (TIMESPEC_A_LT_B(&temp, &schedule_time)) {
/* count the deadline miss */
lev->dline_miss[p]++;
event_delete(lev->deadline_timer[p]);
}
 
}
else {
#ifdef EDFSTAR_DEBUG
edfstar_printf("e%d",p);
#endif
 
/* the task has terminated his job before it consume the wcet. All OK! */
proc_table[p].status = EDFSTAR_IDLE;
 
/* and finally, a preemption check! */
EDFSTAR_check_preemption(lev);
 
/* when the deadline timer fire, it recognize the situation and set
correctly all the stuffs (like reactivation, request_time, etc... ) */
}
#ifdef EDFSTAR_DEBUG
edfstar_printf(")");
#endif
}
 
static void EDFSTAR_task_end(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:end)");
#endif
 
iq_extract(p,&lev->ready);
 
/* we finally put the task in the ready queue */
proc_table[p].status = FREE;
q_insertfirst(p,&freedesc);
if (lev->deadline_timer[p] != -1) {
event_delete(lev->deadline_timer[p]);
}
 
/* and finally, a preemption check! (it will also call guest_end) */
EDFSTAR_check_preemption(lev);
}
 
static void EDFSTAR_task_sleep(LEVEL l, PID p)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
static void EDFSTAR_task_delay(LEVEL l, PID p, TIME usdelay)
{ kern_raise(XUNVALID_TASK,exec_shadow); }
 
/* Guest Functions
These functions manages a JOB_TASK_MODEL, that is used to put
a guest task in the EDFSTAR ready queue. */
 
static int EDFSTAR_guest_create(LEVEL l, PID p, TASK_MODEL *m)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
JOB_TASK_MODEL *job = (JOB_TASK_MODEL *)m;
 
/* if the EDFSTAR_guest_create is called, then the pclass must be a
valid pclass. */
 
*iq_query_timespec(p, &lev->ready) = job->deadline;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
if (job->noraiseexc)
lev->flag[p] = EDFSTAR_FLAG_NORAISEEXC;
else
lev->flag[p] = 0;
 
lev->period[p] = job->period;
 
/* there is no bandwidth guarantee at this level, it is performed
by the level that inserts guest tasks... */
 
return 0; /* OK, also if the task cannot be guaranteed... */
}
 
static void EDFSTAR_guest_detach(LEVEL l, PID p)
{
/* the EDFSTAR level doesn't introduce any dinamic allocated new field.
No guarantee is performed on guest tasks... so we don't have to reset
the NO_GUARANTEE FIELD */
}
 
static void EDFSTAR_guest_dispatch(LEVEL l, PID p, int nostop)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
level_table[ lev->scheduling_level ]->
guest_dispatch(lev->scheduling_level,p,nostop);
}
 
static void EDFSTAR_guest_epilogue(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
/* the task has been preempted. it returns into the ready queue... */
level_table[ lev->scheduling_level ]->
guest_epilogue(lev->scheduling_level,p);
 
proc_table[p].status = EDFSTAR_READY;
}
 
static void EDFSTAR_guest_activate(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
/* Insert task in the correct position */
iq_timespec_insert(p,&lev->ready);
proc_table[p].status = EDFSTAR_READY;
 
/* check for preemption */
EDFSTAR_check_preemption(lev);
 
/* Set the deadline timer */
if (!(lev->flag[p] & EDFSTAR_FLAG_NORAISEEXC))
lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
EDFSTAR_timer_guest_deadline,
(void *)p);
 
}
 
static void EDFSTAR_guest_insert(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
/* Insert task in the correct position */
iq_timespec_insert(p,&lev->ready);
proc_table[p].status = EDFSTAR_READY;
 
/* and check for preemption! */
EDFSTAR_check_preemption(lev);
}
 
static void EDFSTAR_guest_extract(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
/* the task is blocked on a synchronization primitive. we have to
remove it from the master module -and- from the local queue! */
iq_extract(p,&lev->ready);
 
/* and finally, a preemption check! (it will also call guest_end() */
EDFSTAR_check_preemption(lev);
}
 
static void EDFSTAR_guest_end(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
//kern_printf("EDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
#endif
 
iq_extract(p, &lev->ready);
 
/* we remove the deadline timer, because the slice is finished */
if (lev->deadline_timer[p] != NIL) {
#ifdef EDFSTAR_DEBUG
// kern_printf("EDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
#endif
event_delete(lev->deadline_timer[p]);
lev->deadline_timer[p] = NIL;
}
 
/* and finally, a preemption check! (it will also call guest_end() */
EDFSTAR_check_preemption(lev);
}
 
static void EDFSTAR_guest_endcycle(LEVEL l, PID p)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
static void EDFSTAR_guest_sleep(LEVEL l, PID p)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
static void EDFSTAR_guest_delay(LEVEL l, PID p, TIME usdelay)
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
 
/* Registration functions */
 
/* Registration function:
int flags the init flags ... see EDFSTAR.h */
LEVEL EDFSTAR_register_level(int budget, int master)
{
LEVEL l; /* the level that we register */
EDFSTAR_level_des *lev; /* for readableness only */
PID i; /* a counter */
 
#ifdef EDFSTAR_DEBUG
printk("EDFSTAR_register_level\n");
#endif
 
/* request an entry in the level_table */
l = level_alloc_descriptor();
 
#ifdef EDFSTAR_DEBUG
printk(" alloco descrittore %d %d\n",l,(int)sizeof(EDFSTAR_level_des));
#endif
 
/* alloc the space needed for the EDFSTAR_level_des */
lev = (EDFSTAR_level_des *)kern_alloc(sizeof(EDFSTAR_level_des));
 
#ifdef EDFSTAR_DEBUG
printk(" lev=%d\n",(int)lev);
#endif
 
/* update the level_table with the new entry */
level_table[l] = (level_des *)lev;
 
/* fill the standard descriptor */
strncpy(lev->l.level_name, EDFSTAR_LEVELNAME, MAX_LEVELNAME);
lev->l.level_code = EDFSTAR_LEVEL_CODE;
lev->l.level_version = EDFSTAR_LEVEL_VERSION;
 
lev->l.level_accept_task_model = EDFSTAR_level_accept_task_model;
lev->l.level_accept_guest_model = EDFSTAR_level_accept_guest_model;
lev->l.level_status = EDFSTAR_level_status;
lev->l.level_scheduler = EDFSTAR_level_scheduler;
lev->l.level_guarantee = NULL;
lev->l.task_create = EDFSTAR_task_create;
lev->l.task_detach = EDFSTAR_task_detach;
lev->l.task_eligible = EDFSTAR_task_eligible;
lev->l.task_dispatch = EDFSTAR_task_dispatch;
lev->l.task_epilogue = EDFSTAR_task_epilogue;
lev->l.task_activate = EDFSTAR_task_activate;
lev->l.task_insert = EDFSTAR_task_insert;
lev->l.task_extract = EDFSTAR_task_extract;
lev->l.task_endcycle = EDFSTAR_task_endcycle;
lev->l.task_end = EDFSTAR_task_end;
lev->l.task_sleep = EDFSTAR_task_sleep;
lev->l.task_delay = EDFSTAR_task_delay;
 
lev->l.guest_create = EDFSTAR_guest_create;
lev->l.guest_detach = EDFSTAR_guest_detach;
lev->l.guest_dispatch = EDFSTAR_guest_dispatch;
lev->l.guest_epilogue = EDFSTAR_guest_epilogue;
lev->l.guest_activate = EDFSTAR_guest_activate;
lev->l.guest_insert = EDFSTAR_guest_insert;
lev->l.guest_extract = EDFSTAR_guest_extract;
lev->l.guest_endcycle = EDFSTAR_guest_endcycle;
lev->l.guest_end = EDFSTAR_guest_end;
lev->l.guest_sleep = EDFSTAR_guest_sleep;
lev->l.guest_delay = EDFSTAR_guest_delay;
 
/* fill the EDFSTAR descriptor part */
for(i=0; i<MAX_PROC; i++) {
lev->period[i] = 0;
lev->deadline_timer[i] = -1;
lev->flag[i] = 0;
lev->dline_miss[i] = 0;
lev->wcet_miss[i] = 0;
lev->nact[i] = 0;
}
 
iq_init(&lev->ready, NULL, IQUEUE_NO_PRIORITY);
lev->activated = NIL;
 
lev->budget = budget;
lev->scheduling_level = master;
 
return l;
}
 
int EDFSTAR_get_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
if (lev->l.level_code == EDFSTAR_LEVEL_CODE &&
lev->l.level_version == EDFSTAR_LEVEL_VERSION)
return lev->dline_miss[p];
else
return -1;
}
 
int EDFSTAR_get_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
if (lev->l.level_code == EDFSTAR_LEVEL_CODE &&
lev->l.level_version == EDFSTAR_LEVEL_VERSION)
return lev->wcet_miss[p];
else
return -1;
}
 
int EDFSTAR_get_nact(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
if (lev->l.level_code == EDFSTAR_LEVEL_CODE &&
lev->l.level_version == EDFSTAR_LEVEL_VERSION)
return lev->nact[p];
else
return -1;
}
 
int EDFSTAR_reset_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
if (lev->l.level_code == EDFSTAR_LEVEL_CODE &&
lev->l.level_version == EDFSTAR_LEVEL_VERSION)
{
lev->dline_miss[p] = 0;
return 0;
}
else
return -1;
}
 
int EDFSTAR_reset_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
if (lev->l.level_code == EDFSTAR_LEVEL_CODE &&
lev->l.level_version == EDFSTAR_LEVEL_VERSION)
{
lev->wcet_miss[p] = 0;
return 0;
}
else
return -1;
}
 
/demos/trunk/first/makefile
0,0 → 1,33
#
#
#
 
ifndef BASE
BASE=../..
endif
include $(BASE)/config/config.mk
 
PROGS= test1 test2 test3 test4 test5 test6 testiq
 
include $(BASE)/config/example.mk
 
test1:
make -f $(SUBMAKE) APP=test1 INIT= OTHEROBJS="iqueue.o edfstar.o cbsstar.o" OTHERINCL=
 
test2:
make -f $(SUBMAKE) APP=test2 INIT= OTHEROBJS="iqueue.o edfstar.o cbsstar.o" OTHERINCL=
 
test3:
make -f $(SUBMAKE) APP=test3 INIT= OTHEROBJS="iqueue.o edfstar.o cbsstar.o" OTHERINCL=
 
test4:
make -f $(SUBMAKE) APP=test4 INIT= OTHEROBJS="iqueue.o edfstar.o cbsstar.o" OTHERINCL=
 
test5:
make -f $(SUBMAKE) APP=test5 INIT= OTHEROBJS="iqueue.o edfstar.o cbsstar.o" OTHERINCL=
 
test6:
make -f $(SUBMAKE) APP=test6 INIT= OTHEROBJS="iqueue.o rmstar.o cbsstar.o" OTHERINCL=
 
testiq:
make -f $(SUBMAKE) APP=testiq INIT= OTHEROBJS="iqueue.o " OTHERINCL=
/demos/trunk/first/iqueue.c
0,0 → 1,221
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: iqueue.c,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "iqueue.h"
#include <kernel/mem.h>
 
void iq_init (IQUEUE *q, IQUEUE *share, int flags)
{
q->first = NIL;
q->last = NIL;
 
if (share)
q->s = share->s;
else {
q->s = (struct IQUEUE_shared *)kern_alloc(sizeof(struct IQUEUE_shared));
 
if (!(flags & IQUEUE_NO_PRIORITY))
q->s->priority = (DWORD *)kern_alloc(sizeof(DWORD) * MAX_PROC);
if (!(flags & IQUEUE_NO_TIMESPEC))
q->s->timespec_priority = (struct timespec *)
kern_alloc(sizeof(struct timespec) * MAX_PROC);
}
}
 
/*+
This function insert the task with PID i in the queue que.
The insertion is made respecting the priority field.
(the first item in the queue have the less priority)
+*/
void iq_priority_insert (PID i, IQUEUE *que)
{
DWORD prio;
PID p,q;
p = NIL;
q = que->first;
prio = que->s->priority[i];
while ((q != NIL) && (prio >= que->s->priority[q])) {
p = q;
q = que->s->next[q];
}
if (p != NIL)
que->s->next[p] = i;
else
que->first = i;
if (q != NIL)
que->s->prev[q] = i;
else
que->last = i;
que->s->next[i] = q;
que->s->prev[i] = p;
}
 
 
/*
This function insert the task with PID i in the queue que.
The insertion is made respecting the timespec priority field.
(the first item in the queue have the less priority)
*/
void iq_timespec_insert(PID i, IQUEUE *que)
{
struct timespec prio;
PID p,q;
 
p = NIL;
q = que->first;
 
TIMESPEC_ASSIGN(&prio, &que->s->timespec_priority[i]);
while ((q != NIL) &&
!TIMESPEC_A_LT_B(&prio, &que->s->timespec_priority[q])) {
p = q;
q = que->s->next[q];
}
if (p != NIL)
que->s->next[p] = i;
else
que->first = i;
if (q != NIL)
que->s->prev[q] = i;
else
que->last = i;
que->s->next[i] = q;
que->s->prev[i] = p;
}
 
 
 
void iq_insertfirst(PID p, IQUEUE *q)
{
if (q->first != NIL) {
q->s->next[p] = q->first;
q->s->prev[q->first] = p;
}
else {
q->last = p;
q->s->next[p] = NIL;
}
q->s->prev[p] = NIL;
q->first = p;
}
 
 
void iq_insertlast(PID p, IQUEUE *q)
{
if (q->last != NIL) {
q->s->prev[p] = q->last;
q->s->next[q->last] = p;
}
else {
q->first = p;
q->s->prev[p] = NIL;
}
q->s->next[p] = NIL;
q->last = p;
}
 
 
void iq_extract(PID i, IQUEUE *que)
{
PID p,q;
p = que->s->prev[i];
q = que->s->next[i];
if (p != NIL)
que->s->next[p] = que->s->next[i];
else
que->first = q;
if (q != NIL)
que->s->prev[q] = que->s->prev[i];
else
que->last = p;
}
 
PID iq_getfirst(IQUEUE *q)
{
PID p = q->first;
if (p == NIL)
return NIL;
 
q->first = q->s->next[q->first];
 
if (q->first != NIL)
q->s->prev[q->first] = NIL;
else
q->last = NIL;
return p;
}
 
PID iq_getlast(IQUEUE *q)
{
PID p = q->last;
if (p == NIL)
return NIL;
 
q->last = q->s->prev[q->last];
 
if (q->last != NIL)
q->s->next[q->last] = NIL;
else
q->first = NIL;
return p;
}
/demos/trunk/first/edfstar.h
0,0 → 1,139
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: edfstar.h,v 1.1 2002-09-02 10:29:30 pj Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2002-09-02 10:29:30 $
------------
 
Title:
EDFSTAR
 
Task Models Accepted:
HARD_TASK_MODEL - Hard Tasks (only Periodic)
wcet field and mit field must be != 0. They are used to set the wcet
and period of the tasks.
periodicity field can be only PERIODIC
drel field is ignored
Guest Models Accepted:
JOB_TASK_MODEL - a single guest task activation
Identified by an absolute deadline and a period.
period field is ignored
 
Description:
 
This module schedule his tasks following the classic EDF
scheme. This module is derived from the EDFACT Scheduling Module.
 
This module can not stay alone: when it have to schedule a task, it
simply inserts it into another master module using a
BUDGET_TASK_MODEL.
 
No Task guarantee is performed at all.
The tasks scheduled are only periodic.
All the task are put in a queue and the scheduling is based on the
deadline value.
If a task miss a deadline a counter is incremented.
If a task exausts the wcet a counter is incremented
No ZOMBIE support!!!!!!
 
Exceptions raised:
XUNVALID_GUEST XUNVALID_TASK
some primitives are not implemented:
task_sleep, task_delay, guest_endcycle, guest_sleep, guest_delay
 
XACTIVATION
If a task is actiated through task_activate or guest_activate more than
one time
Restrictions & special features:
- This level doesn't manage the main task.
- Functions to return and reset the nact, wcet and dline miss
counters are provided
 
**/
 
/*
* Copyright (C) 2001 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#ifndef __EDFSTAR_H__
#define __EDFSTAR_H__
 
#include <ll/ll.h>
#include <kernel/config.h>
#include <sys/types.h>
#include <kernel/types.h>
#include <modules/codes.h>
 
 
 
/* flags... */
#define EDFSTAR_ENABLE_GUARANTEE 1 /* Task Guarantee enabled */
#define EDFSTAR_ENABLE_ALL 1
 
#define EDFSTAR_FAILED_GUARANTEE 8 /* used in the module, unsettabl
in EDF_register_level... */
 
 
 
#define EDFSTAR_LEVELNAME "EDFSTAR base"
#define EDFSTAR_LEVEL_CODE 166
#define EDFSTAR_LEVEL_VERSION 1
 
 
/* Registration function:
int budget The budget used by this module (see CBSSTAR.h)
int master The master module used by EDFSTAR
*/
LEVEL EDFSTAR_register_level(int budget, int master);
 
/* returns respectively the number of dline, wcet or nact; -1 if error */
int EDFSTAR_get_dline_miss(PID p);
int EDFSTAR_get_wcet_miss(PID p);
int EDFSTAR_get_nact(PID p);
 
/* resets respectively the number of dline, wcet miss; -1 if error */
int EDFSTAR_reset_dline_miss(PID p);
int EDFSTAR_reset_wcet_miss(PID p);
 
#endif