20,11 → 20,11 |
|
/** |
------------ |
CVS : $Id: slsh.c,v 1.1.1.1 2002-09-02 09:37:41 pj Exp $ |
CVS : $Id: slsh.c,v 1.4 2003-01-07 17:10:18 pj Exp $ |
|
File: $File$ |
Revision: $Revision: 1.1.1.1 $ |
Last update: $Date: 2002-09-02 09:37:41 $ |
Revision: $Revision: 1.4 $ |
Last update: $Date: 2003-01-07 17:10:18 $ |
------------ |
|
This file contains the scheduling module for Slot-Shifting. |
63,6 → 63,7 |
#include <kernel/descr.h> |
#include <kernel/var.h> |
#include <kernel/func.h> |
#include <kernel/trace.h> |
|
//#define eslsh_printf kern_printf |
#define slsh_printf printk |
90,9 → 91,9 |
/* task lists */ |
SLSH_task tasks[MAX_PROC]; /* est and dl's for static and guaranteed task */ |
|
QUEUE idle_statics; /* finished static tasks */ |
IQUEUE idle_statics; /* finished static tasks */ |
|
QQUEUE unspecified; /* tasks with only a wcet */ |
IQUEUE unspecified; /* tasks with only a wcet */ |
|
/* the Intervals list */ |
SLSH_interval intervals[MAX_INTERVALS]; |
107,39 → 108,6 |
} SLSH_level_des; |
|
|
/* Which task models the Slot-Shifting module accepts */ |
static int SLSH_level_accept_task_model(LEVEL l, TASK_MODEL* m) |
{ |
HARD_TASK_MODEL* h; |
SOFT_TASK_MODEL* s; |
|
/* Check the models */ |
switch(m->pclass) |
{ |
case STATIC_PCLASS: /* offline scheduled tasks */ |
return 0; |
case HARD_PCLASS: /* hard aperiodic tasks */ |
h = (HARD_TASK_MODEL *) m; |
if(h->drel != 0 && h->wcet != 0) /* must be set */ |
return 0; |
break; |
case SOFT_PCLASS: /* soft aperiodic tasks */ |
s = (SOFT_TASK_MODEL *) m; |
if(s->wcet != 0) /* must be set */ |
return 0; |
break; |
default: |
} |
|
return -1; /* Not accepted model */ |
} |
|
|
static void SLSH_level_status(LEVEL l) |
{ |
kern_printf("Level status not implemented\n"); |
} |
|
/* check if some tasks are ready, return 0 if ready, -1 otherwise */ |
static int SLSH_R(SLSH_task* tasks) |
{ |
155,9 → 123,9 |
} |
|
/* check if unspecified exists, return 0 if it exists, -1 otherwise */ |
static int SLSH_T(QQUEUE unspecified) |
static int SLSH_T(IQUEUE *unspecified) |
{ |
if(unspecified.first != NIL) |
if(!iq_isempty(unspecified)) |
return 0; |
else |
return -1; |
206,8 → 174,8 |
{ |
lowest_dl = lev->tasks[t].dabs; |
pid = t; |
} |
} |
} |
} |
}/* for all tasks */ |
|
218,7 → 186,7 |
static PID SLSH_candidates(SLSH_task* tasks) |
{ |
int lowest_dl = 0; |
PID pid; |
PID pid = -1; |
int t; |
|
/* Use the EDL algorithm again to decide which task to run */ |
283,7 → 251,7 |
} |
|
/* The scheduler, decides which task to run. */ |
static PID SLSH_level_scheduler(LEVEL l) |
static PID SLSH_public_scheduler(LEVEL l) |
{ |
SLSH_level_des* lev = (SLSH_level_des *)(level_table[l]); |
PID pid; |
300,10 → 268,10 |
else if(SLSH_R(lev->tasks) > 0 && SLSH_sc(lev->intervals, lev->current) > 0) |
{ |
/* If unspecified exist, execute it according to FIFO order */ |
if(SLSH_T(lev->unspecified) == 0) |
if(SLSH_T(&lev->unspecified) == 0) |
{ |
SLSH_decSc(lev->intervals, lev->current, 1); /* decrease sc by 1 */ |
return (PID)qq_getfirst(&lev->unspecified); |
return iq_getfirst(&lev->unspecified); |
} |
else /* No unspecified, execute task from candidates (statics) */ |
{ |
322,7 → 290,7 |
} |
|
/* not used, slot-shifting handles all guarantees itself, it handles all bandwidth */ |
static int SLSH_level_guarantee(LEVEL l, bandwidth_t *freebandwidth) |
static int SLSH_public_guarantee(LEVEL l, bandwidth_t *freebandwidth) |
{ |
*freebandwidth = 0; |
return 1; |
456,7 → 424,7 |
} |
|
/* check if task model is accepted and store nessecary parameters */ |
static int SLSH_task_create(LEVEL l, PID p, TASK_MODEL *m) |
static int SLSH_public_create(LEVEL l, PID p, TASK_MODEL *m) |
{ |
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]); |
STATIC_TASK_MODEL* s; |
463,6 → 431,27 |
HARD_TASK_MODEL* h; |
SOFT_TASK_MODEL* u; |
|
|
/* Check the models */ |
switch(m->pclass) |
{ |
case STATIC_PCLASS: /* offline scheduled tasks */ |
break; |
case HARD_PCLASS: /* hard aperiodic tasks */ |
h = (HARD_TASK_MODEL *) m; |
if (h->drel == 0 || h->wcet == 0) /* must be set */ |
return -1; |
break; |
case SOFT_PCLASS: /* soft aperiodic tasks */ |
u = (SOFT_TASK_MODEL *) m; |
if(u->wcet == 0) /* must be set */ |
return -1; |
break; |
default: |
return -1; |
} |
|
|
/* if the SLSH_task_create is called, then the pclass must be a |
valid pclass. Slot-shifting accepts STATIC_TASK, HARD_TASK |
and SOFT_TASK models with some restrictions */ |
494,7 → 483,7 |
u = (SOFT_TASK_MODEL *) m; |
proc_table[p].avail_time = u->wcet; |
proc_table[p].wcet = u->wcet; |
qq_insertlast(p, &lev->unspecified); /* respect FIFO order */ |
iq_insertlast(p, &lev->unspecified); /* respect FIFO order */ |
break; |
default: /* a task model not supported */ |
return -1; |
505,17 → 494,6 |
return 0; |
} |
|
static void SLSH_task_detach(LEVEL l, PID p) |
{ |
/* do nothing */ |
} |
|
/* check if a task chosen by scheduler is correct */ |
static int SLSH_task_eligible(LEVEL l, PID p) |
{ |
return 0; /* if the task p is chosen, it is always eligible */ |
} |
|
/************* The slot end event handler *************/ |
static void SLSH_slot_end(void* p) |
{ |
543,7 → 521,7 |
{ |
lev->slot = 0; |
|
while((pid = q_getfirst(&lev->idle_statics)) != NIL) |
while((pid = iq_getfirst(&lev->idle_statics)) != NIL) |
{ |
if(lev->tasks[pid].est <= lev->slot) |
proc_table[pid].status = SLSH_READY; |
559,7 → 537,7 |
} |
|
/* when a task becomes executing (EXE status) */ |
static void SLSH_task_dispatch(LEVEL l, PID pid, int nostop) |
static void SLSH_public_dispatch(LEVEL l, PID pid, int nostop) |
{ |
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]); |
struct timespec t; |
569,7 → 547,7 |
NB: we can't assume that p is the first task in the queue!!! */ |
|
if(proc_table[pid].pclass == SOFT_PCLASS) |
qq_extract(pid, &lev->unspecified); |
iq_extract(pid, &lev->unspecified); |
|
/* also start the timer for one slot length */ |
lev->slot_event = kern_event_post(&TIME2TIMESPEC(lev->slot_length, t), |
577,7 → 555,7 |
} |
|
/* called when task is moved from EXE status */ |
static void SLSH_task_epilogue(LEVEL l, PID pid) |
static void SLSH_public_epilogue(LEVEL l, PID pid) |
{ |
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]); |
|
591,7 → 569,7 |
else /* the end of a slot. the task returns into the ready queue... */ |
{ |
if(proc_table[pid].pclass == SOFT_PCLASS) |
qq_insertfirst(pid,&lev->unspecified); |
iq_insertfirst(pid,&lev->unspecified); |
|
proc_table[pid].status = SLSH_READY; |
} |
598,7 → 576,7 |
} |
|
/* when task go from SLEEP to SLSH_READY or SLSH_WAIT */ |
static void SLSH_task_activate(LEVEL l, PID pid) |
static void SLSH_public_activate(LEVEL l, PID pid) |
{ |
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]); |
WORD type = proc_table[pid].pclass; |
620,13 → 598,13 |
/* insert unspecified tasks in QQUEUE and make it ready */ |
if(type == SOFT_PCLASS) |
{ |
qq_insertlast(pid ,&lev->unspecified); |
iq_insertlast(pid ,&lev->unspecified); |
proc_table[pid].status = SLSH_READY; |
} |
} |
|
/* when a task i returned to module from a semaphore, mutex ... */ |
static void SLSH_task_insert(LEVEL l, PID pid) |
static void SLSH_public_unblock(LEVEL l, PID pid) |
{ |
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]); |
|
634,11 → 612,11 |
proc_table[pid].status = SLSH_READY; |
|
if(proc_table[pid].pclass == SOFT_PCLASS) |
qq_insertfirst(pid ,&lev->unspecified); |
iq_insertfirst(pid ,&lev->unspecified); |
} |
|
/* when a semaphore, mutex ... taskes a task from module */ |
static void SLSH_task_extract(LEVEL l, PID pid) |
static void SLSH_public_block(LEVEL l, PID pid) |
{ |
/* Extract the running task from the level |
. we have already extract it from the ready queue at the dispatch time. |
651,14 → 629,8 |
*/ |
} |
|
/* task has finished execution for this period */ |
static void SLSH_task_endcycle(LEVEL l, PID pid) |
{ |
/* do nothing */ |
} |
|
/* the task has finihed its wcet, kill task (dont kill static tasks) */ |
static void SLSH_task_end(LEVEL l, PID pid) |
static void SLSH_public_end(LEVEL l, PID pid) |
{ |
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]); |
|
665,7 → 637,7 |
if(proc_table[pid].pclass == SOFT_PCLASS) |
{ |
if (proc_table[pid].status == SLSH_READY) |
qq_extract(pid, &lev->unspecified); |
iq_extract(pid, &lev->unspecified); |
} |
else if(proc_table[pid].pclass == HARD_PCLASS) |
{ |
678,7 → 650,7 |
{ |
proc_table[pid].avail_time = proc_table[pid].wcet; |
proc_table[pid].status = SLSH_IDLE; |
q_insert(pid, &lev->idle_statics); |
iq_priority_insert(pid, &lev->idle_statics); |
} |
|
proc_table[pid].status = FREE; |
685,61 → 657,25 |
} |
|
/* called when a task should sleep but not execute for awhile, mabe a mode change */ |
static void SLSH_task_sleep(LEVEL l, PID pid) |
{ |
//static void SLSH_task_sleep(LEVEL l, PID pid) |
//{ |
// |
// /* the task has terminated his job before it consume the wcet. All OK! */ |
// proc_table[pid].status = SLEEP; |
// |
// /* we reset the capacity counters... only for static tasks */ |
// if (proc_table[pid].pclass == STATIC_PCLASS) |
// proc_table[pid].avail_time = proc_table[pid].wcet; |
// |
//} |
|
/* the task has terminated his job before it consume the wcet. All OK! */ |
proc_table[pid].status = SLEEP; |
|
/* we reset the capacity counters... only for static tasks */ |
if (proc_table[pid].pclass == STATIC_PCLASS) |
proc_table[pid].avail_time = proc_table[pid].wcet; |
|
} |
|
static void SLSH_task_delay(LEVEL l, PID p, TIME usdelay) { } |
|
/** Guest Functions, slot shifing accepts no guests, so all generates exceptions **/ |
|
static int SLSH_level_accept_guest_model(LEVEL l, TASK_MODEL* m) { return -1; } |
|
static int SLSH_guest_create(LEVEL l, PID p, TASK_MODEL *m) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); return 0; } |
|
static void SLSH_guest_detach(LEVEL l, PID p) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); } |
|
static void SLSH_guest_dispatch(LEVEL l, PID p, int nostop) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); } |
|
static void SLSH_guest_epilogue(LEVEL l, PID p) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); } |
|
static void SLSH_guest_activate(LEVEL l, PID p) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); } |
|
static void SLSH_guest_insert(LEVEL l, PID p) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); } |
|
static void SLSH_guest_extract(LEVEL l, PID p) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); } |
|
static void SLSH_guest_endcycle(LEVEL l, PID p) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); } |
|
static void SLSH_guest_end(LEVEL l, PID p) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); } |
|
static void SLSH_guest_sleep(LEVEL l, PID p) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); } |
|
static void SLSH_guest_delay(LEVEL l, PID p, TIME usdelay) |
{ kern_raise(XUNVALID_GUEST,exec_shadow); } |
|
/******* Registration functions *******/ |
|
/*+ Registration function: */ |
void SLSH_register_level() |
LEVEL SLSH_register_level() |
{ |
LEVEL l; /* the level that we register */ |
SLSH_level_des *lev; /* for readableness only */ |
747,53 → 683,24 |
|
kern_printf("SLSH_register_level\n"); |
|
/* request an entry in the level_table */ |
l = level_alloc_descriptor(); |
/* request an entry in the level_table */ |
l = level_alloc_descriptor(sizeof(SLSH_level_des)); |
|
/* alloc the space needed for the EDF_level_des */ |
lev = (SLSH_level_des *)kern_alloc(sizeof(SLSH_level_des)); |
lev = (SLSH_level_des *)level_table[l]; |
|
/* update the level_table with the new entry */ |
level_table[l] = (level_des *)lev; |
printk(" lev=%d\n",(int)lev); |
|
/* fill the standard descriptor */ |
strncpy(lev->l.level_name, SLSH_LEVELNAME, MAX_LEVELNAME); |
|
lev->l.level_code = SLSH_LEVEL_CODE; |
lev->l.level_version = SLSH_LEVEL_VERSION; |
|
lev->l.level_accept_task_model = SLSH_level_accept_task_model; |
lev->l.level_accept_guest_model = SLSH_level_accept_guest_model; |
lev->l.level_status = SLSH_level_status; |
lev->l.level_scheduler = SLSH_level_scheduler; |
|
lev->l.level_guarantee = SLSH_level_guarantee; |
|
lev->l.task_create = SLSH_task_create; |
lev->l.task_detach = SLSH_task_detach; |
lev->l.task_eligible = SLSH_task_eligible; |
lev->l.task_dispatch = SLSH_task_dispatch; |
lev->l.task_epilogue = SLSH_task_epilogue; |
lev->l.task_activate = SLSH_task_activate; |
lev->l.task_insert = SLSH_task_insert; |
lev->l.task_extract = SLSH_task_extract; |
lev->l.task_endcycle = SLSH_task_endcycle; |
lev->l.task_end = SLSH_task_end; |
lev->l.task_sleep = SLSH_task_sleep; |
lev->l.task_delay = SLSH_task_delay; |
/* fill the standard descriptor */ |
lev->l.public_scheduler = SLSH_public_scheduler; |
lev->l.public_guarantee = SLSH_public_guarantee; |
lev->l.public_create = SLSH_public_create; |
lev->l.public_end = SLSH_public_end; |
lev->l.public_dispatch = SLSH_public_dispatch; |
lev->l.public_epilogue = SLSH_public_epilogue; |
lev->l.public_activate = SLSH_public_activate; |
lev->l.public_unblock = SLSH_public_unblock; |
lev->l.public_block = SLSH_public_block; |
|
lev->l.guest_create = SLSH_guest_create; |
lev->l.guest_detach = SLSH_guest_detach; |
lev->l.guest_dispatch = SLSH_guest_dispatch; |
lev->l.guest_epilogue = SLSH_guest_epilogue; |
lev->l.guest_activate = SLSH_guest_activate; |
lev->l.guest_insert = SLSH_guest_insert; |
lev->l.guest_extract = SLSH_guest_extract; |
lev->l.guest_endcycle = SLSH_guest_endcycle; |
lev->l.guest_end = SLSH_guest_end; |
lev->l.guest_sleep = SLSH_guest_sleep; |
lev->l.guest_delay = SLSH_guest_delay; |
|
/* fill the SLSH descriptor part */ |
for(i = 0; i < MAX_PROC; i++) |
{ |
816,6 → 723,8 |
lev->slot = 0; |
lev->slot_length = 0; |
lev->slot_event = -1; |
|
return l; |
} |
|
|