18,11 → 18,11 |
|
/** |
------------ |
CVS : $Id: kern.c,v 1.12 2004-04-19 12:36:39 giacomo Exp $ |
CVS : $Id: kern.c,v 1.13 2005-01-08 14:41:53 pj Exp $ |
|
File: $File$ |
Revision: $Revision: 1.12 $ |
Last update: $Date: 2004-04-19 12:36:39 $ |
Revision: $Revision: 1.13 $ |
Last update: $Date: 2005-01-08 14:41:53 $ |
------------ |
|
This file contains: |
33,7 → 33,7 |
|
- the scheduler, capacity timer, and grarantee |
|
- the sys_abort, sys_end, sys_gettime |
- the sys_gettime |
|
|
**/ |
78,7 → 78,12 |
/* Kernel System variables */ |
/*----------------------------------------------------------------------*/ |
|
int global_errnumber; /*+ Errno used in system initialization +*/ |
/* error numbers used for system shutdown */ |
static int errnumber_global; |
static int errnumber_shutdown; |
|
|
|
CONTEXT global_context; /*+ Context used during initialization; |
It references also a safe stack +*/ |
|
141,12 → 146,6 |
/*+ Resource descriptor table +*/ |
resource_des *resource_table[MAX_RES_LEVEL]; |
|
/*+ This variable is set by the system call sys_end() or sys_abort(). |
When a sys_end() or sys_abort is called into an event handler, |
we don't have to change context in the reschedule(). |
look at kernel/event.c +*/ |
int mustexit = 0; |
|
/*+ this is the system runlevel... it may be from 0 to 4: |
0 - init |
1 - running |
161,7 → 160,17 |
work in a different way when the system is in the global_context +*/ |
int calling_runlevel_func; |
|
/* this variable is set when _exit is called. in this case, the |
atexit functions will not be called. |
Values: |
- 0 neither exit or _exit have been called |
- 1 exit has been called |
- 2 _exit has been called |
*/ |
|
int _exit_has_been_called; |
|
|
/*----------------------------------------------------------------------*/ |
/* Kernel internal functions */ |
/*----------------------------------------------------------------------*/ |
172,7 → 181,7 |
static int *__errnumber() |
{ |
if (exec_shadow == -1) |
return &global_errnumber; |
return &errnumber_global; |
else |
return &(proc_table[exec_shadow].errnumber); |
} |
354,19 → 363,6 |
} |
|
/*----------------------------------------------------------------------*/ |
/* Abort strings */ |
/*----------------------------------------------------------------------*/ |
|
const char *const _sys_abrtlist[] = { |
"zero - no error", |
"OSLib exception", |
"generic unhandled signal raised", |
"error in signal_init", |
"default exception handler code", |
"ARP table full" |
}; |
|
/*----------------------------------------------------------------------*/ |
/* Kernel main system functions */ |
/*----------------------------------------------------------------------*/ |
|
382,8 → 378,6 |
|
struct ll_initparms parms; /* for the VM */ |
|
int aborting; /* it is set if we are aborting the system */ |
|
struct multiboot_info *multiboot=mbi_address(); |
|
|
451,7 → 445,8 |
iq_insertlast(i,&freedesc); |
|
/* Set up the varius stuff */ |
global_errnumber = 0; |
errnumber_global = 0; |
errnumber_shutdown = 0; |
task_counter = 0; |
system_counter = 0; |
exec = -1; |
461,6 → 456,7 |
sched_levels = 0; /* They are not registered yet... */ |
res_levels = 0; |
calling_runlevel_func = 0; |
_exit_has_been_called = 0; |
|
/* Clear the key-specific data */ |
task_specific_data_init(); |
528,7 → 524,7 |
/* exec and exec_shadow are already = -1 */ |
kern_gettime(&schedule_time); |
scheduler(); |
global_context = ll_context_from(); /* It will be used by sys_end */ |
global_context = ll_context_from(); /* It will be used by exit & co. */ |
ll_context_to(proc_table[exec_shadow].context); |
|
/* |
543,10 → 539,11 |
/* |
* Runlevel SHUTDOWN: Shutting down the system... :-( |
* |
* |
* We return here only when exit or _exit is called |
*/ |
|
event_setlasthandler(NULL); |
event_noreschedule = 0; |
|
// ll_abort(666); |
/* tracer stuff */ |
558,12 → 555,9 |
|
runlevel = RUNLEVEL_SHUTDOWN; |
|
/* 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); |
|
call_runlevel_func(RUNLEVEL_SHUTDOWN, aborting); |
call_runlevel_func(RUNLEVEL_SHUTDOWN, _exit_has_been_called); |
|
//kern_printf("before - system_counter=%d, task_counter = %d\n", system_counter,task_counter); |
|
581,12 → 575,9 |
kill_user_tasks(); |
//kern_printf("Û%lu",kern_gettime(NULL)); |
|
/* we have to go again in multitasking mode!!! */ |
mustexit = 0; |
|
/* exec and exec_shadow are already = -1 */ |
kern_gettime(&schedule_time); |
global_context = ll_context_from(); /* It will be used by sys_end */ |
global_context = ll_context_from(); /* It will be used by sys_abort_shutdown */ |
scheduler(); |
|
event_setlasthandler(kern_after_dispatch); |
609,7 → 600,7 |
|
//kern_printf("Chiamo exit Functions\n"); |
|
call_runlevel_func(RUNLEVEL_BEFORE_EXIT, aborting); |
call_runlevel_func(RUNLEVEL_BEFORE_EXIT, _exit_has_been_called==_EXIT_CALLED); |
|
//kern_printf("Dopo exit Functions\n"); |
|
630,108 → 621,83 |
|
//kern_printf("dopo before Functions\n"); |
kern_cli(); |
if (global_errnumber) { |
/* vm_abort called */ |
kern_printf("Abort detected\nCode : %u (%s)\n",global_errnumber, |
global_errnumber<=LAST_ABORT_NUMBER ? _sys_abrtlist[global_errnumber] : "no description" ); |
l1_exit(-1); |
if (errnumber_global) { |
kern_printf("exit() or _exit() called with code : %u\n", errnumber_global); |
} |
|
l1_exit(0); // System terminated normally |
if (errnumber_shutdown) { |
kern_printf("sys_abort_shutdown() called with code : %u (%s)\n", errnumber_shutdown); |
} |
|
l1_exit(errnumber_shutdown); |
} |
|
/* IMPORTANT!!! |
I'm almost sure the shutdown procedure does not work into interrupts. */ |
void internal_sys_end(int i) |
/* Close the system when we are in runlevel shutdown */ |
void sys_abort_shutdown(int err) |
{ |
LEVEL l; /* a counter */ |
SYS_FLAGS f; |
|
/* if something goes wron during the real mode */ |
if (runlevel==RUNLEVEL_STARTUP || runlevel==RUNLEVEL_AFTER_EXIT) |
l1_exit(i); |
/* Check if the system is in SHUTDOWN mode */ |
if (runlevel != RUNLEVEL_SHUTDOWN) |
exit(0); |
|
//kern_printf("mustexit=%d",mustexit); |
if (mustexit) |
return; |
f = kern_fsave(); |
|
mustexit = 1; |
errnumber_shutdown = err; |
|
global_errnumber = i; |
|
if (!ll_ActiveInt()) { |
proc_table[exec_shadow].context = kern_context_save(); |
|
if (exec_shadow != -1) { |
kern_gettime(&schedule_time); |
|
kern_epilogue_macro(); |
|
/* then, we call the epilogue. the epilogue tipically checks the |
avail_time field... */ |
l = proc_table[exec_shadow].task_level; |
level_table[l]->public_epilogue(l,exec_shadow); |
|
exec_shadow = exec = -1; |
} |
kern_context_load(global_context); |
} |
|
if (ll_ActiveInt()) { |
event_noreschedule=1; |
ll_context_to(global_context); |
/* The context change will be done when all the interrupts end!!! */ |
kern_frestore(f); |
} |
|
//kern_printf("fine sysend"); |
|
/* the control reach this line only if we call sys_end() into an event |
handler (for example, if the event raises an exception with |
SA_USEFAST active and the exception calls sys_end() ) */ |
else { |
task_makefree(TASK_CANCELED); |
// the scheduler is not called here because we are switching to the |
// global context! |
ll_context_to(global_context); |
} |
} |
|
|
/* |
Close the system & return to HOST OS. |
Can be called from tasks and from ISRS, |
but only during runlevel SHUTDOWN |
|
*/ |
void sys_abort(int err) |
void internal_exit(int status, int reason) |
{ |
SYS_FLAGS f; |
|
/* if something goes wron during the real mode */ |
if (runlevel==RUNLEVEL_STARTUP || runlevel==RUNLEVEL_AFTER_EXIT) |
l1_exit(status); |
|
/* Check if the system is in RUNNING mode */ |
if (runlevel != RUNLEVEL_RUNNING) return; |
|
f = kern_fsave(); |
internal_sys_end(err); |
kern_frestore(f); |
|
} |
errnumber_global = status; |
|
/* Close the system when we are in runlevel shutdown */ |
void sys_abort_shutdown(int err) |
{ |
SYS_FLAGS f; |
if (!_exit_has_been_called) |
_exit_has_been_called = reason; |
|
/* Check if the system is in SHUTDOWN mode */ |
if (runlevel != RUNLEVEL_SHUTDOWN) return; |
|
f = kern_fsave(); |
internal_sys_end(err); |
if (ll_ActiveInt()) { |
event_noreschedule=1; |
ll_context_to(global_context); |
kern_frestore(f); |
|
} |
else { |
task_makefree(TASK_CANCELED); |
// the scheduler is not called here because we are switching to the |
// global context! |
ll_context_to(global_context); |
} |
} |
|
|
void sys_end(void) |
void exit(int status) |
{ |
sys_abort(0); |
internal_exit(status, EXIT_CALLED); |
} |
|
void _exit(int status) |
{ |
sys_abort(status); |
internal_exit(status, _EXIT_CALLED); |
} |
|
|