38,6 → 38,8 |
*/ |
|
#include "cbsstar.h" |
#include "ll/i386/64bit.h" |
#include <tracer.h> |
|
/* |
* DEBUG stuffs begin |
64,9 → 66,12 |
struct budget_struct { |
TIME Q; /* budget */ |
TIME T; /* period */ |
TIME D; /* deadline */ |
|
struct timespec dline; /* deadline */ |
int dline_timer; /* oslib event for budget reactivation*/ |
struct timespec replenish; /* server period */ |
|
int replenish_timer; /* oslib event for budget reactivation*/ |
int avail; /* current budget */ |
|
LEVEL l; /* Current CBSSTAR level */ |
103,7 → 108,7 |
} CBSSTAR_level_des; |
|
|
static void CBSSTAR_deadline_timer_hardreservation(void *a) |
static void CBSSTAR_replenish_timer_hardreservation(void *a) |
{ |
struct budget_struct *b = a; |
PID p; |
112,7 → 117,7 |
cbsstar_printf("(CS:HrdRes:"); |
#endif |
|
b->dline_timer = NIL; |
b->replenish_timer = NIL; |
|
/* we modify the deadline according to rule 4 ... */ |
/* there is a while because if the wcet is << than the system tick |
123,6 → 128,9 |
|
if (b->avail > 0) b->flags = CBSSTAR_ACTIVE; |
|
/* Tracer */ |
TRACER_LOGEVENT(FTrace_EVT_server_replenish,0,(unsigned int)(b)); |
|
/* avail may be <0 because a task executed via a shadow fo many time |
b->current == NIL only if the prec task was finished and there |
was not any other task to be put in the ready queue |
140,6 → 148,7 |
|
kern_gettime(&b->dline); |
ADDUSEC2TIMESPEC(b->T, &b->dline); |
ADDUSEC2TIMESPEC(b->T, &b->replenish); |
|
b->current = p; |
|
156,10 → 165,11 |
} |
|
if (b->flags == CBSSTAR_NOACTIVE) { |
kern_gettime(&b->dline); |
ADDUSEC2TIMESPEC(b->T, &b->dline); |
|
kern_gettime(&b->replenish); |
ADDUSEC2TIMESPEC(b->T, &b->replenish);; |
|
b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b); |
b->replenish_timer=kern_event_post(&b->replenish, CBSSTAR_replenish_timer_hardreservation, b); |
} |
|
#ifdef CBSSTAR_DEBUG |
187,15 → 197,20 |
TIME t; |
struct timespec t2,t3; |
|
t = (b->T * b->avail) / b->Q; |
mul32div32to32(b->D,b->avail,b->Q,t); |
|
t3.tv_sec = t / 1000000; |
t3.tv_nsec = (t % 1000000) * 1000; |
SUBTIMESPEC(&b->dline, acttime, &t2); |
|
SUBTIMESPEC(&b->dline, acttime, &t2); |
TRACER_LOGEVENT(FTrace_EVT_server_active,0,(unsigned int)b); |
|
if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) || |
/* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) { |
TIMESPEC_ASSIGN(&b->replenish, acttime); |
ADDUSEC2TIMESPEC(b->T, &b->replenish); |
TIMESPEC_ASSIGN(&b->dline, acttime); |
ADDUSEC2TIMESPEC(b->T, &b->dline); |
ADDUSEC2TIMESPEC(b->D, &b->dline); |
b->avail=b->Q; |
b->flags=CBSSTAR_ACTIVE; |
} |
229,16 → 244,21 |
kern_printf("(CS:Cap p%d av=%d)", p, b->avail); |
#endif |
|
if (b->avail <= 0) b->flags = CBSSTAR_NOACTIVE; |
if (b->avail <= 0) { |
b->flags = CBSSTAR_NOACTIVE; |
TRACER_LOGEVENT(FTrace_EVT_server_exhaust,0,(unsigned int)(b)); |
} |
|
if (TIMESPEC_A_LT_B(&b->dline, &schedule_time)) { |
/* we modify the deadline ... */ |
TIMESPEC_ASSIGN(&b->dline, &schedule_time); |
ADDUSEC2TIMESPEC(b->T, &b->dline); |
ADDUSEC2TIMESPEC(b->D, &b->dline); |
TIMESPEC_ASSIGN(&b->replenish, &schedule_time); |
ADDUSEC2TIMESPEC(b->T, &b->replenish); |
} |
|
if (b->flags == CBSSTAR_NOACTIVE && b->dline_timer == NIL) { |
b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b); |
if (b->flags == CBSSTAR_NOACTIVE && b->replenish_timer == NIL) { |
b->replenish_timer=kern_event_post(&b->replenish, CBSSTAR_replenish_timer_hardreservation, b); |
} |
|
} |
282,7 → 302,7 |
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 (b->current == p) { |
|
if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) { |
if (lev->cap_lev!=NIL) { |
kern_event_delete(lev->cap_lev); |
293,16 → 313,21 |
level_table[ lev->scheduling_level ]-> |
private_extract(lev->scheduling_level, p); |
/* we modify the deadline ... */ |
TIMESPEC_ASSIGN(&b->dline, &schedule_time); |
ADDUSEC2TIMESPEC(b->T, &b->dline); |
kern_gettime(&b->replenish); |
TIMESPEC_ASSIGN(&b->dline, &b->replenish); |
ADDUSEC2TIMESPEC(b->D, &b->dline); |
ADDUSEC2TIMESPEC(b->T, &b->replenish); |
|
/* and the capacity */ |
b->avail = b->Q; |
b->flags = CBSSTAR_ACTIVE; |
|
if (b->dline_timer!=NIL) { |
kern_event_delete(b->dline_timer); |
b->dline_timer=NIL; |
/* Tracer */ |
TRACER_LOGEVENT(FTrace_EVT_server_replenish,0,(unsigned int)(b)); |
|
if (b->replenish_timer!=NIL) { |
kern_event_delete(b->replenish_timer); |
b->replenish_timer=NIL; |
} |
|
/* and, finally, we reinsert the task in the master level */ |
314,7 → 339,7 |
return -1; |
|
} |
} |
|
|
return 0; |
|
422,17 → 447,17 |
be extracted! */ |
|
/* ... then, we dispatch it to the master level */ |
level_table[ lev->scheduling_level ]-> |
private_dispatch(lev->scheduling_level,p,nostop); |
if (!nostop) |
level_table[ lev->scheduling_level ]-> |
private_dispatch(lev->scheduling_level,p,nostop); |
|
/* ...and finally, we have to post a capacity event */ |
if (!nostop) { |
TIMESPEC_ASSIGN(&ty, &schedule_time); |
TIMESPEC_ASSIGN(&lev->cap_lasttime, &schedule_time); |
ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty); |
lev->cap_lev = kern_event_post(&ty,capacity_handler, lev); |
TIMESPEC_ASSIGN(&ty, &schedule_time); |
TIMESPEC_ASSIGN(&lev->cap_lasttime, &schedule_time); |
ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty); |
lev->cap_lev = kern_event_post(&ty,capacity_handler, lev); |
|
} |
|
|
} |
|
439,36 → 464,43 |
static void CBSSTAR_private_epilogue(LEVEL l, PID p) |
{ |
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]); |
struct budget_struct *b = &lev->b[lev->tb[p]]; |
struct budget_struct *b; |
int skip_epilog; |
skip_epilog = 0; |
|
#ifdef CBSSTAR_DEBUG |
kern_printf("(CS:Epi:%d)",p); |
#endif |
|
if (p==b->current) { |
if (p==exec) b = &lev->b[lev->tb[p]]; |
else if (lev->tb[exec]!=NIL) { |
b = &lev->b[lev->tb[exec]]; |
p=exec; |
skip_epilog=1; |
} |
else return; |
|
CBSSTAR_account_capacity(lev,p); |
CBSSTAR_account_capacity(lev,p); |
|
// L'evento di capacità va cancellato perchè sarà ripristinato nella successiva dispatch |
/* we have to check if the capacity is still available */ |
if (b->flags) { |
/* there is capacity available, maybe it is simply a preemption; |
the task have to return to the ready queue */ |
// L'evento di capacità va cancellato perchè sarà ripristinato nella successiva dispatch |
/* we have to check if the capacity is still available */ |
if (b->flags) { |
/* there is capacity available, maybe it is simply a preemption; |
the task have to return to the ready queue */ |
if (!skip_epilog) |
level_table[ lev->scheduling_level ]-> |
private_epilogue(lev->scheduling_level,p); |
|
} else { |
/* we kill the current activation */ |
level_table[ lev->scheduling_level ]-> |
private_extract(lev->scheduling_level, p); |
|
iq_insertfirst(p, &b->tasks); |
b->current = NIL; |
|
} |
} else { |
/* we kill the current activation */ |
level_table[ lev->scheduling_level ]-> |
private_extract(lev->scheduling_level, p); |
|
iq_insertfirst(p, &b->tasks); |
b->current = NIL; |
|
} |
|
} |
|
} |
|
/* Registration functions }*/ |
504,7 → 536,8 |
lev->b[i].Q = 0; |
lev->b[i].T = 0; |
NULL_TIMESPEC(&lev->b[i].dline); |
lev->b[i].dline_timer = NIL; |
NULL_TIMESPEC(&lev->b[i].replenish); |
lev->b[i].replenish_timer = NIL; |
lev->b[i].avail = 0; |
lev->b[i].current = -1; |
lev->b[i].flags = CBSSTAR_ACTIVE; |
527,7 → 560,7 |
|
} |
|
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T, LEVEL local_scheduler_level, int scheduler_id) |
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T, TIME D, LEVEL local_scheduler_level, int scheduler_id) |
{ |
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]); |
int r; |
551,6 → 584,7 |
|
lev->b[r].Q = Q; |
lev->b[r].T = T; |
lev->b[r].D = D; |
lev->b[r].avail = Q; |
lev->b[r].flags = CBSSTAR_ACTIVE; |
lev->b[r].loc_sched_id = scheduler_id; |
565,6 → 599,20 |
return -1; |
} |
|
int CBSSTAR_get_remain_capacity(LEVEL l, int budget) |
{ |
struct timespec actual,ty; |
int tx; |
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]); |
kern_gettime(&actual); |
SUBTIMESPEC(&actual, &schedule_time, &ty); |
tx = TIMESPEC2USEC(&ty); |
// the remain capacity is from the first dispatch so is less then |
// actual capacity |
return (lev->b[budget].avail-tx); |
|
} |
|
int CBSSTAR_removebudget(LEVEL l, int budget) |
{ |
|
579,7 → 627,7 |
lev->b[budget].Q = 0; |
lev->b[budget].T = 0; |
NULL_TIMESPEC(&lev->b[budget].dline); |
lev->b[budget].dline_timer = NIL; |
lev->b[budget].replenish_timer = NIL; |
lev->b[budget].avail = 0; |
lev->b[budget].current = -1; |
lev->b[budget].flags = CBSSTAR_ACTIVE; |
588,7 → 636,7 |
|
} |
|
int CBSSTAR_adjust_budget(LEVEL l, TIME Q, TIME T, int budget) |
int CBSSTAR_adjust_budget(LEVEL l, TIME Q, TIME T, TIME D, int budget) |
{ |
|
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]); |
595,12 → 643,13 |
|
lev->b[budget].Q = Q; |
lev->b[budget].T = T; |
lev->b[budget].D = D; |
|
return 0; |
|
} |
|
int CBSSTAR_getbudgetinfo(LEVEL l, TIME *Q, TIME *T, int budget) |
int CBSSTAR_getbudgetinfo(LEVEL l, TIME *Q, TIME *T, TIME *D, int budget) |
{ |
|
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]); |
607,6 → 656,7 |
|
*Q = lev->b[budget].Q; |
*T = lev->b[budget].T; |
*D = lev->b[budget].D; |
|
return 0; |
|
659,3 → 709,18 |
|
} |
|
void CBSSTAR_disable_server(LEVEL l, int budget) |
{ |
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]); |
int avail_budget; |
int spare; |
|
/* force a hard reservation event */ |
avail_budget=lev->b[lev->tb[exec]].avail; |
lev->b[lev->tb[exec]].flags = CBSSTAR_NOACTIVE; |
//kern_printf("(CBS DS %d)", exec); |
/* save the unused capacity */ |
spare=avail_budget+lev->b[lev->tb[exec]].avail; |
if (spare<=0) spare=0; |
|
} |