Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 37 → Rev 38

/shark/trunk/kernel/kern.c
18,11 → 18,11
 
/**
------------
CVS : $Id: kern.c,v 1.2 2002-11-11 08:34:08 pj Exp $
CVS : $Id: kern.c,v 1.3 2003-01-07 17:07:49 pj Exp $
 
File: $File$
Revision: $Revision: 1.2 $
Last update: $Date: 2002-11-11 08:34:08 $
Revision: $Revision: 1.3 $
Last update: $Date: 2003-01-07 17:07:49 $
------------
 
This file contains:
117,9 → 117,26
/*+ Process descriptor table +*/
proc_des proc_table[MAX_PROC];
 
/*+ Level descriptor table +*/
/* Scheduling modules descriptor table */
/* ------------------------------------------------------------------------ */
 
/* the descriptor table */
level_des *level_table[MAX_SCHED_LEVEL];
/* ... and the size of each descriptor */
size_t level_size[MAX_SCHED_LEVEL];
 
/* an utilization counter incremented if a level is used by another module */
int level_used[MAX_SCHED_LEVEL];
/* these data structures (first, last, free, next & prev)
are used to implement a double linked list of scheduling modules.
That list is used by the scheduler to call the module's schedulers. */
int level_first; /* first module in the list */
int level_last; /* last module in the list */
int level_free; /* free single linked list of free module descriptors. */
int level_next[MAX_SCHED_LEVEL];
int level_prev[MAX_SCHED_LEVEL];
/* ------------------------------------------------------------------------ */
 
/*+ Resource descriptor table +*/
resource_des *resource_table[MAX_RES_LEVEL];
 
197,7 → 214,6
void scheduler(void)
{
LEVEL l; /* a counter */
TIME tx; /* a dummy used for time computation */
struct timespec ty; /* a dummy used for time computation */
 
PID p; /* p is the task chosen by the level scheduler */
211,6 → 227,8
(proc_table[exec_shadow].control & NO_PREEMPT) ) )
return;
 
// kern_printf("(!");
 
/*
exec_shadow = exec = -1 only if the scheduler is called from:
. task_endcycle
229,48 → 247,38
- call an epilogue
*/
 
/* then, we call the epilogue. the epilogue tipically checks the
avail_time field... */
if (exec_shadow != -1) {
// ok is set 4 debug :-(
ok = ll_gettime(TIME_EXACT, &schedule_time);
// kern_printf("(%d sched s%d ns%d)", ok, schedule_time.tv_sec, schedule_time.tv_nsec);
kern_epilogue_macro();
 
/* manage the capacity event */
SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
tx = TIMESPEC2USEC(&ty);
proc_table[exec_shadow].avail_time -= tx;
jet_update_slice(tx);
 
/* if the event didn't fire before, we delete it. */
if (cap_timer != NIL) {
event_delete(cap_timer);
cap_timer = NIL;
}
 
/* then, we call the epilogue. the epilogue tipically checks the
avail_time field... */
 
// kern_printf("(e%d)",exec_shadow);
 
l = proc_table[exec_shadow].task_level;
level_table[l]->task_epilogue(l,exec_shadow);
level_table[l]->public_epilogue(l,exec_shadow);
}
 
l = 0;
// kern_printf("[");
 
l = level_first;
for(;;) {
do {
p = level_table[l]->level_scheduler(l);
p = level_table[l]->public_scheduler(l);
// kern_printf("p=%d",p);
if (p != NIL)
ok = level_table[ proc_table[p].task_level ]->
task_eligible(proc_table[p].task_level,p);
public_eligible(proc_table[p].task_level,p);
else
ok = 0;
// kern_printf(" ok=%d",ok);
} while (ok < 0); /* repeat the level scheduler if the task isn't
eligible... (ex. in the aperiodic servers...) */
if (p != NIL) break;
 
l++; /* THERE MUST BE a level with a task to schedule */
l = level_next[l]; /* THERE MUST BE a level with a task to schedule */
// kern_printf(" l=%d",l);
};
 
// kern_printf("]");
 
/* tracer stuff */
//trc_logevent(exec,TRC_SCHEDULE,NULL,0);
 
284,15 → 292,17
//trc_logevent(exec_shadow,TRC_DISPATCH,NULL,0);
if (old_exec_shadow!=exec_shadow)
trc_logevent(TRC_SCHEDULE,&exec_shadow);
// kern_printf("[%i->%i]",old_exec_shadow,exec_shadow);
// kern_printf("[%i->%i]",old_exec_shadow,exec_shadow);
 
/* we control the correctness of the shadows when we kill */
proc_table[exec_shadow].status = EXE;
//kern_printf("(d%d)",exec_shadow);
// kern_printf("(d%d)",exec_shadow);
l = proc_table[exec_shadow].task_level;
level_table[l]->task_dispatch(l, exec_shadow, exec!=exec_shadow);
level_table[l]->public_dispatch(l, exec_shadow, exec!=exec_shadow);
 
// kern_printf("*");
 
/* Finally,we post the capacity event, BUT
. only if the task require that
. only if exec==exec_shadow (if a task is blocked we don't want
301,13 → 311,13
&& exec==exec_shadow) {
TIMESPEC_ASSIGN(&ty, &schedule_time);
ADDUSEC2TIMESPEC(proc_table[exec_shadow].avail_time,&ty);
// kern_printf("³s%d ns%d sched s%d ns%d³",ty.tv_sec,ty.tv_nsec, schedule_time.tv_sec, schedule_time.tv_nsec);
// kern_printf("³s%d ns%d sched s%d ns%d³",ty.tv_sec,ty.tv_nsec, schedule_time.tv_sec, schedule_time.tv_nsec);
cap_timer = kern_event_post(&ty, capacity_timer, NULL);
}
/* set the time at witch the task is scheduled */
TIMESPEC_ASSIGN(&cap_lasttime, &schedule_time);
 
//if (runlevel != 1) kern_printf("(s%d)",exec_shadow);
// kern_printf("(s%d)",exec_shadow);
}
 
 
325,8 → 335,8
bandwidth_t num=MAX_BANDWIDTH;
int l;
 
for (l =0; l<MAX_SCHED_LEVEL && level_table[l]->level_guarantee; l++)
if (!level_table[l]->level_guarantee(l,&num))
for (l =0; l<MAX_SCHED_LEVEL && level_table[l]->public_guarantee; l++)
if (!level_table[l]->public_guarantee(l,&num))
return -1;
 
return 0; /* OK */
378,7 → 388,7
*
*/
 
runlevel = 0;
runlevel = RUNLEVEL_STARTUP;
 
/* The kernel startup MUST proceed with int disabled! */
kern_cli();
400,7 → 410,6
proc_table[i].frozen_activations = 0;
proc_table[i].sigmask = 0;
proc_table[i].sigpending = 0;
NULL_TIMESPEC(&proc_table[i].request_time);
proc_table[i].avail_time = 0;
proc_table[i].shadow = i;
proc_table[i].cleanup_stack= NULL;
456,7 → 465,11
/* Init VM layer (Interrupts, levels & memory management) */
/* for old exception handling, use excirq_init() */
signals_init();
set_default_exception_handler();
 
/* Clear scheduling modules registration data */
levels_init();
 
sys_tick = __kernel_register_levels__(multiboot);
 
/* tracer stuff */
481,7 → 494,7
parms.tick = sys_tick;
 
/*
* Runlevel 1: Let's go!!!!
* Runlevel INIT: Let's go!!!!
*
*
*/
497,6 → 510,17
/* call the init functions */
call_runlevel_func(RUNLEVEL_INIT, 0);
 
 
 
 
/*
* Runlevel RUNNING: Hoping that all works fine ;-)
*
*
*/
 
runlevel = RUNLEVEL_RUNNING;
 
/* reset keyboard after exit */
// sys_atexit((void(*)(void *))C8042_restore,NULL,AFTER_EXIT);
 
504,7 → 528,7
trc_resume();
/* exec and exec_shadow are already = -1 */
ll_gettime(TIME_EXACT, &schedule_time);
kern_gettime(&schedule_time);
scheduler();
global_context = ll_context_from(); /* It will be used by sys_end */
ll_context_to(proc_table[exec_shadow].context);
519,7 → 543,7
 
 
/*
* Runlevel 2: Shutting down the system... :-(
* Runlevel SHUTDOWN: Shutting down the system... :-(
*
*
*/
535,13 → 559,11
/* 1 when the error code is != 0 */
aborting = global_errnumber > 0;
 
//kern_printf("after - system_counter=%d, task_counter = %d\n",
// system_counter,task_counter);
//kern_printf("after - system_counter=%d, task_counter = %d\n", system_counter,task_counter);
call_runlevel_func(RUNLEVEL_SHUTDOWN, aborting);
//kern_printf("before - system_counter=%d, task_counter = %d\n",
// system_counter,task_counter);
//kern_printf("before - system_counter=%d, task_counter = %d\n", system_counter,task_counter);
 
if (system_counter) {
/* To shutdown the kernel correctly, we have to wait that all the SYSTEM
552,15 → 574,15
We do nothing for user tasks that remain active (because, for example,
they have the cancelability set to deferred) when the system goes to
runlevel 3 */
//kern_printf("Û%lu",ll_gettime(TIME_EXACT,NULL));
//kern_printf("Û%lu",kern_gettime(NULL));
kill_user_tasks();
//kern_printf("Û%lu",ll_gettime(TIME_EXACT,NULL));
//kern_printf("Û%lu",kern_gettime(NULL));
 
/* we have to go again in multitasking mode!!! */
mustexit = 0;
 
/* exec and exec_shadow are already = -1 */
ll_gettime(TIME_EXACT, &schedule_time);
kern_gettime(&schedule_time);
global_context = ll_context_from(); /* It will be used by sys_end */
scheduler();
 
573,7 → 595,7
 
 
/*
* Runlevel 3: Before Halting the system
* Runlevel BEFORE_EXIT: Before Halting the system
*
*
*/
597,7 → 619,7
 
 
/*
* Runlevel 4: After halting...
* Runlevel AFTER_EXIT: After halting...
*
*
*/
620,47 → 642,48
 
}
 
/* IMPORTANT!!!
I'm almost sure the shutdown procedure does not work into interrupts. */
void internal_sys_end(int i)
{
LEVEL l; /* a counter */
TIME tx; /* a dummy used for time computation */
struct timespec ty; /* a dummy used for time computation */
 
/* if something goes wron during the real mode */
if (runlevel==RUNLEVEL_STARTUP || runlevel==RUNLEVEL_AFTER_EXIT)
l1_exit(i);
//kern_printf("mustexit=%d",mustexit);
if (!mustexit) {
if (!ll_ActiveInt())
proc_table[exec_shadow].context = kern_context_save();
global_errnumber = i;
if (mustexit)
return;
 
mustexit = 1;
mustexit = 1;
 
global_errnumber = i;
 
 
if (!ll_ActiveInt()) {
proc_table[exec_shadow].context = kern_context_save();
if (exec_shadow != -1) {
ll_gettime(TIME_EXACT, &schedule_time);
/* manage the capacity event */
SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
tx = TIMESPEC2USEC(&ty);
proc_table[exec_shadow].avail_time -= tx;
jet_update_slice(tx);
/* if the event didn't fire before, we delete it. */
if (cap_timer != NIL) {
event_delete(cap_timer);
cap_timer = NIL;
}
kern_gettime(&schedule_time);
 
kern_epilogue_macro();
/* then, we call the epilogue. the epilogue tipically checks the
avail_time field... */
avail_time field... */
l = proc_table[exec_shadow].task_level;
level_table[l]->task_epilogue(l,exec_shadow);
 
level_table[l]->public_epilogue(l,exec_shadow);
exec_shadow = exec = -1;
}
kern_context_load(global_context);
}
 
if (ll_ActiveInt())
ll_context_to(global_context);
else
kern_context_load(global_context);
if (ll_ActiveInt()) {
ll_context_to(global_context);
/* The context change will be done when all the interrupts end!!! */
}
 
//kern_printf("fine sysend");
 
/* the control reach this line only if we call sys_end() into an event
669,64 → 692,29
}
 
 
/*+ Close the system & return to HOST OS.
Can be called from all the tasks...
The first time it is called it jumps to the global context
The second time it jumps only if there are no system task remaining
The error code passed is 0... (it is saved on the first call!!!) +*/
void sys_end(void)
/*
Close the system & return to HOST OS.
Can be called from tasks and from ISRS
 
*/
void sys_abort(int err)
{
SYS_FLAGS f;
 
/* the sys_end change the context to the global context.
when the first time is called, it simply kills all the users tasks
and waits the system tasks to end... */
 
/*kern_printf("°sys_end %d°",exec_shadow);*/
/*return;*/
f = kern_fsave();
if (runlevel != RUNLEVEL_INIT && system_counter) {
kern_frestore(f);
return;
}
 
internal_sys_end(0);
internal_sys_end(err);
kern_frestore(f);
}
 
/*+ Close the system & return to HOST OS.
Can be called from all the tasks...
The first time it is called it works as the sys_end
The second time it jumps every time
The error code passed is 0... +*/
void sys_abort(int err)
void sys_end(void)
{
/* the sys_end change the context to the global context.
when the first time is called, it simply kills all the users tasks
and waits the system tasks to end... */
 
internal_sys_end(err);
sys_abort(0);
}
 
/*+ equal to sys_end! +*/
void _exit(int status)
{
SYS_FLAGS f;
 
/* the sys_end change the context to the global context.
when the first time is called, it simply kills all the users tasks
and waits the system tasks to end... */
 
/*kern_printf("°sys_end %d°",exec_shadow);*/
/*return;*/
f = kern_fsave();
if (runlevel != RUNLEVEL_INIT && system_counter) {
kern_frestore(f);
return;
}
 
internal_sys_end(status);
kern_frestore(f);
sys_abort(status);
}
 
 
746,7 → 734,7
TIME x;
 
f = kern_fsave();
x = ll_gettime(TIME_EXACT,t);
x = kern_gettime(t);
kern_frestore(f);
 
return x;