Subversion Repositories shark

Rev

Rev 568 | Rev 958 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   (see the web pages for full authors list)
11
 *
12
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
13
 *
14
 * http://www.sssup.it
15
 * http://retis.sssup.it
16
 * http://shark.sssup.it
17
 */
18
 
19
/**
20
 ------------
913 pj 21
 CVS :        $Id: kern.c,v 1.13 2005-01-08 14:41:53 pj Exp $
2 pj 22
 
23
 File:        $File$
913 pj 24
 Revision:    $Revision: 1.13 $
25
 Last update: $Date: 2005-01-08 14:41:53 $
2 pj 26
 ------------
27
 
28
 This file contains:
29
 
30
 - the kernel system variables
31
 
32
 - the errno functions
33
 
34
 - the scheduler, capacity timer, and grarantee
35
 
913 pj 36
 - the sys_gettime
2 pj 37
 
38
 
39
**/
40
 
41
/*
42
 * Copyright (C) 2000 Paolo Gai
43
 *
44
 * This program is free software; you can redistribute it and/or modify
45
 * it under the terms of the GNU General Public License as published by
46
 * the Free Software Foundation; either version 2 of the License, or
47
 * (at your option) any later version.
48
 *
49
 * This program is distributed in the hope that it will be useful,
50
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
51
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
52
 * GNU General Public License for more details.
53
 *
54
 * You should have received a copy of the GNU General Public License
55
 * along with this program; if not, write to the Free Software
56
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
57
 *
58
 */
59
 
60
#include <stdarg.h>
61
#include <ll/ll.h>
62
#include <ll/stdlib.h>
63
#include <ll/stdio.h>
64
#include <ll/string.h>
65
#include <kernel/config.h>
66
#include <kernel/model.h>
67
#include <kernel/const.h>
68
#include <sys/types.h>
69
#include <kernel/types.h>
70
#include <kernel/descr.h>
71
#include <errno.h>
72
#include <kernel/var.h>
73
#include <kernel/func.h>
74
 
353 giacomo 75
#include <tracer.h>
76
 
2 pj 77
/*----------------------------------------------------------------------*/
78
/* Kernel System variables                                              */
79
/*----------------------------------------------------------------------*/
80
 
913 pj 81
/* error numbers used for system shutdown */
82
static int errnumber_global;
83
static int errnumber_shutdown;
84
 
85
 
86
 
2 pj 87
CONTEXT global_context; /*+ Context used during initialization;
88
                            It references also a safe stack      +*/
89
 
90
int task_counter;       /*+ Application task counter. It represent
91
                            the number of Application tasks in the
92
                            system. When all Application Tasks end,
93
                            also the system ends.                +*/
94
 
95
int system_counter;     /*+ System task counter. It represent
96
                            the number of System tasks in the
97
                            system with the NO_KILL flag reset.
98
                            When all Application Tasks end,
99
                            the system waits for the end of the
100
                            system tasks and then it ends.       +*/
101
 
102
PID exec;               /*+ Task advised by the scheduler        +*/
103
PID exec_shadow;        /*+ Currently executing task             +*/
104
 
29 pj 105
IQUEUE freedesc;        /*+ Free descriptor handled as a queue   +*/
2 pj 106
 
107
DWORD sys_tick;         /*+ System tick (in usec)                +*/
108
struct timespec schedule_time;
109
                        /*+ Timer read at each call to schedule()+*/
110
 
111
int   cap_timer;        /*+ the capacity event posted when the
112
                            task starts                          +*/
113
struct timespec cap_lasttime;
114
                        /*+ the time at whitch the capacity
115
                            event is posted. Normally, it is
116
                            equal to schedule_time               +*/
117
 
118
 
119
 
120
DWORD sched_levels;     /*+ Schedule levels active in the system +*/
121
DWORD res_levels;       /*+ Resource levels active in the system +*/
122
 
123
/*+ Process descriptor table +*/
124
proc_des proc_table[MAX_PROC];
125
 
38 pj 126
/* Scheduling modules descriptor table */
127
/* ------------------------------------------------------------------------ */
128
 
129
/* the descriptor table */
2 pj 130
level_des *level_table[MAX_SCHED_LEVEL];
38 pj 131
/* ... and the size of each descriptor */
132
size_t level_size[MAX_SCHED_LEVEL];
2 pj 133
 
38 pj 134
/* an utilization counter incremented if a level is used by another module */
135
int level_used[MAX_SCHED_LEVEL];
136
/* these data structures (first, last, free, next & prev)
137
   are used to implement a double linked list of scheduling modules.
138
   That list is used by the scheduler to call the module's schedulers. */
139
int level_first; /* first module in the list */
140
int level_last;  /* last module in the list */
141
int level_free;  /* free single linked list of free module descriptors. */
142
int level_next[MAX_SCHED_LEVEL];
143
int level_prev[MAX_SCHED_LEVEL];
144
/* ------------------------------------------------------------------------ */
145
 
2 pj 146
/*+ Resource descriptor table +*/
147
resource_des *resource_table[MAX_RES_LEVEL];
148
 
149
/*+ this is the system runlevel... it may be from 0 to 4:
150
 
151
    1 - running
152
    2 - shutdown
153
    3 - before halting
154
    4 - halting
155
+*/
156
int runlevel;
157
 
158
/*+ this variable is set to 1 into call_runlevel_func (look at init.c)
159
    ad it is used because the task_activate (look at activate.c) must
160
    work in a different way when the system is in the global_context +*/
161
int calling_runlevel_func;
162
 
913 pj 163
/* this variable is set when _exit is called. in this case, the
164
  atexit functions will not be called.
165
  Values:
166
  - 0 neither exit or _exit have been called
167
  - 1 exit has been called
168
  - 2 _exit has been called
169
*/
2 pj 170
 
913 pj 171
int _exit_has_been_called;
172
 
173
 
2 pj 174
/*----------------------------------------------------------------------*/
175
/* Kernel internal functions                                            */
176
/*----------------------------------------------------------------------*/
177
 
178
/*+ errno Handling: this functions returns the correct address for errno.
179
    The address returned can be either the global errno or the errno local
180
    to the execution task */
181
static int *__errnumber()
182
{
183
  if (exec_shadow == -1)
913 pj 184
    return &errnumber_global;
2 pj 185
  else
186
    return &(proc_table[exec_shadow].errnumber);
187
}
188
 
189
/*+ this is the capacity timer. it fires when the running task has expired
190
    his time contained in the avail_time field. The event is tipically
191
    posted in the scheduler() after the task_dispatch. The task_dispatch
192
    can modify the avail_time field to reach his scheduling purposes.
193
    The wcet field is NOT used in the Generic kernel. it is initialized at
194
    init time to 0. +*/
195
void capacity_timer(void *arg)
196
{
197
  /* the capacity event is served, so at the epilogue we
198
     don't have to erase it */
199
  cap_timer = NIL;
200
 
201
//  kern_printf("cap%d ",exec_shadow);
202
 
203
  /* When we reschedule, the call to task_epilogue check the slice and
204
     put the task in the queue's tail */
205
  event_need_reschedule();
206
}
207
 
208
/*+
209
  Generic Scheduler:
210
  This function select the next task that should be executed.
211
  The selection is made calling the level schedulers.
212
  It assume that THERE IS a task that can be scheduled in one
213
  level.
214
 
215
  The general scheduler:
216
  - first, it checks for interrupts.
217
  - then, it calls the epilogue of the task pointed in exec_shadow
218
  - after that, it calls the level schedulers
219
  - then it sets exec and it follows the shadow chain
220
  - finally it calls task_dispatch for the new task (the shadow!!!),
221
    saying if exec != exec_shadow
222
 
223
+*/
224
void scheduler(void)
225
{
226
  LEVEL l;    /* a counter                                     */
227
  struct timespec ty; /* a dummy used for time computation     */
228
 
229
  PID p;      /* p is the task chosen by the level scheduler   */
230
  int ok;     /* 1 only if the task chosen by the level scheduler
231
                 is eligible (normally, it is; but in some server
232
                 it is not always true (i.e., CBS))            */
233
 
234
  PID old_exec_shadow;
235
 
236
  if ( (exec_shadow != -1 &&
237
       (proc_table[exec_shadow].control & NO_PREEMPT) ) )
238
    return;
239
 
38 pj 240
  //  kern_printf("(!");
241
 
2 pj 242
  /*
243
  exec_shadow = exec = -1 only if the scheduler is called from:
244
   . task_endcycle
245
   . task_kill
246
   . task_extract
247
   . task_sleep
248
   . task_delay
249
  and from the system startup routines.
250
 
251
  Normally, the scheduler is called with exec & co != -1...
252
 
253
  if exec & co. is set to -1 before calling scheduler(), the following
254
  stuffs have to be executed before the call
255
  - get the schedule_time
256
  - account the capacity if necessary
257
  - call an epilogue
258
  */
259
 
38 pj 260
  /* then, we call the epilogue. the epilogue tipically checks the
261
     avail_time field... */
2 pj 262
  if (exec_shadow != -1) {
38 pj 263
    kern_epilogue_macro();
2 pj 264
 
265
    l = proc_table[exec_shadow].task_level;
38 pj 266
    level_table[l]->public_epilogue(l,exec_shadow);
2 pj 267
  }
268
 
38 pj 269
  //  kern_printf("[");
270
 
271
  l = level_first;
2 pj 272
  for(;;) {
273
    do {
38 pj 274
      p = level_table[l]->public_scheduler(l);
275
      //      kern_printf("p=%d",p);
2 pj 276
      if (p != NIL)
277
        ok = level_table[ proc_table[p].task_level ]->
38 pj 278
          public_eligible(proc_table[p].task_level,p);
2 pj 279
      else
280
        ok = 0;
38 pj 281
      //      kern_printf(" ok=%d",ok);      
2 pj 282
    } while (ok < 0); /* repeat the level scheduler if the task isn't
283
                         eligible... (ex. in the aperiodic servers...) */
284
    if (p != NIL) break;
285
 
38 pj 286
    l = level_next[l];  /* THERE MUST BE a level with a task to schedule */
287
    //    kern_printf(" l=%d",l);      
2 pj 288
  };
289
 
38 pj 290
  //  kern_printf("]");
291
 
2 pj 292
  /* we follow the shadow chain */
293
  old_exec_shadow=exec_shadow;
294
  exec_shadow = exec = p;
295
  while (exec_shadow != proc_table[exec_shadow].shadow)
296
    exec_shadow = proc_table[exec_shadow].shadow;
297
 
298
  /* tracer stuff */
502 giacomo 299
  TRACER_LOGEVENT(FTrace_EVT_task_schedule,(unsigned short int)proc_table[exec_shadow].context,(unsigned int)proc_table[exec].context);
38 pj 300
  //    kern_printf("[%i->%i]",old_exec_shadow,exec_shadow);
2 pj 301
 
302
  /* we control the correctness of the shadows when we kill */
303
  proc_table[exec_shadow].status = EXE;
304
 
38 pj 305
  //  kern_printf("(d%d)",exec_shadow);
2 pj 306
  l = proc_table[exec_shadow].task_level;
38 pj 307
  level_table[l]->public_dispatch(l, exec_shadow, exec!=exec_shadow);
2 pj 308
 
38 pj 309
  //  kern_printf("*");
310
 
2 pj 311
  /* Finally,we post the capacity event, BUT
312
     . only if the task require that
313
     . only if exec==exec_shadow (if a task is blocked we don't want
314
       to check the capacity!!!) */
315
  if ((proc_table[exec_shadow].control & CONTROL_CAP)
316
      && exec==exec_shadow) {
317
    TIMESPEC_ASSIGN(&ty, &schedule_time);
318
    ADDUSEC2TIMESPEC(proc_table[exec_shadow].avail_time,&ty);
38 pj 319
    //    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);
2 pj 320
    cap_timer = kern_event_post(&ty, capacity_timer, NULL);
321
  }
322
  /* set the time at witch the task is scheduled */
323
  TIMESPEC_ASSIGN(&cap_lasttime, &schedule_time);
324
 
38 pj 325
  //  kern_printf("(s%d)",exec_shadow);
2 pj 326
}
327
 
328
 
329
/*+
330
  Guarantee:
331
  This function guarantees the system: it calls the
332
  level_guarantee of each level that have that function != NULL
333
 
334
  The guarantee is based on a utilization factor basis.
335
  We mantain only a DWORD. num has to be interpreted as num/MAX_DWORD
336
  free bandwidth.
337
+*/
338
int guarantee()
339
{
340
  bandwidth_t num=MAX_BANDWIDTH;
341
  int l;
342
 
38 pj 343
  for (l =0; l<MAX_SCHED_LEVEL && level_table[l]->public_guarantee; l++)
344
    if (!level_table[l]->public_guarantee(l,&num))
2 pj 345
      return -1;
346
 
347
  return 0; /* OK */
348
}
349
 
350
/*----------------------------------------------------------------------*/
351
/* Context switch handling functions                                    */
352
/*----------------------------------------------------------------------*/
353
/* this function is called every time a context change occurs,
354
   when a task is preempted by an event called into an IRQ */
355
void kern_after_dispatch()
356
{
357
  /* every time a task wakes up from an IRQ, it has to check for async
358
     cancellation */
359
  check_killed_async();
360
 
361
  /* Then, look for pending signal delivery */
362
  kern_deliver_pending_signals();
363
}
364
 
365
/*----------------------------------------------------------------------*/
366
/* Kernel main system functions                                         */
367
/*----------------------------------------------------------------------*/
368
 
369
/*+
370
  This function initialize
371
  - the virtual machine (timer, interrupt, mem)
372
  the system's structures (queues, tables) , & the two task main &
373
  dummy, that are always present
374
+*/
45 pj 375
void __kernel_init__(/* struct multiboot_info *multiboot */ void)
2 pj 376
{
377
  int i,j;                                              /* counters */
378
 
379
  struct ll_initparms parms;                          /* for the VM */
380
 
45 pj 381
  struct multiboot_info *multiboot=mbi_address();
2 pj 382
 
383
 
384
 
385
  /*
386
   * Runlevel 0: kernel startup
387
   *
388
   *
389
   */
390
 
38 pj 391
  runlevel = RUNLEVEL_STARTUP;
2 pj 392
 
393
  /* The kernel startup MUST proceed with int disabled!    */
394
  kern_cli();
395
 
396
  /* First we initialize the memory allocator, because it is needed by
397
     __kernel_register_levels__     */
398
  kern_mem_init(multiboot);
399
 
400
  /* Clear the task descriptors */
401
  for (i = 0; i < MAX_PROC; i++) {
402
     proc_table[i].task_level   = -1;
403
     proc_table[i].stack        = NULL;
404
     proc_table[i].name[0]      = 0;
405
     proc_table[i].status       = FREE;
406
     proc_table[i].pclass       = 0;
407
     proc_table[i].group        = 0;
408
     proc_table[i].stacksize    = 0;
409
     proc_table[i].control      = 0;
410
     proc_table[i].frozen_activations = 0;
411
     proc_table[i].sigmask      = 0;
412
     proc_table[i].sigpending   = 0;
413
     proc_table[i].avail_time   = 0;
414
     proc_table[i].shadow       = i;
415
     proc_table[i].cleanup_stack= NULL;
416
     proc_table[i].errnumber    = 0;
29 pj 417
     //proc_table[i].priority     = 0;
418
     //NULL_TIMESPEC(&proc_table[i].timespec_priority);
2 pj 419
     proc_table[i].delay_timer  = -1;
420
     proc_table[i].wcet         = -1;
421
 
422
     proc_table[i].jet_tvalid   = 0;
423
     proc_table[i].jet_curr     = 0;
424
     proc_table[i].jet_max      = 0;
425
     proc_table[i].jet_sum      = 0;
426
     proc_table[i].jet_n        = 0;
427
     for (j=0; j<JET_TABLE_DIM; j++)
428
        proc_table[i].jet_table[j] = 0;
429
 
430
     proc_table[i].waiting_for_me = NIL;
431
     proc_table[i].return_value   = NULL;
432
 
433
     for (j=0; j<PTHREAD_KEYS_MAX; j++)
434
       proc_table[i].keys[j] = NULL;
435
  }
436
 
29 pj 437
  /* set up the free descriptor queue */
438
  //  for (i = 0; i < MAX_PROC-1; i++) proc_table[i].next = i+1;
439
  //  proc_table[MAX_PROC-1].next = NIL;
440
  //  for (i = MAX_PROC-1; i > 0; i--) proc_table[i].prev = i-1;
441
  //  proc_table[0].prev = NIL;
442
  //  freedesc = 0;
443
  iq_init(&freedesc, NULL, 0);
444
  for (i = 0; i < MAX_PROC; i++)
445
    iq_insertlast(i,&freedesc);
446
 
2 pj 447
  /* Set up the varius stuff */
913 pj 448
  errnumber_global = 0;
449
  errnumber_shutdown = 0;
2 pj 450
  task_counter     = 0;
451
  system_counter   = 0;
452
  exec             = -1;
453
  exec_shadow      = -1;
454
  cap_timer        = -1;
455
  NULL_TIMESPEC(&cap_lasttime);
456
  sched_levels     = 0;  /* They are not registered yet... */
457
  res_levels       = 0;
458
  calling_runlevel_func = 0;
913 pj 459
  _exit_has_been_called = 0;
2 pj 460
 
461
  /* Clear the key-specific data */
462
  task_specific_data_init();
463
 
464
  /* Clear exit and init functions */
465
  runlevel_init();
466
 
467
  /* Init VM layer (Interrupts, levels & memory management)           */
468
  /* for old exception handling, use excirq_init() */
469
  signals_init();
38 pj 470
  set_default_exception_handler();
2 pj 471
 
38 pj 472
  /* Clear scheduling modules registration data */
473
  levels_init();
474
 
2 pj 475
  sys_tick = __kernel_register_levels__(multiboot);
476
 
477
  /* test on system tick */
478
  if (sys_tick>=55000)  {
479
     printk("The system tick must be less than 55 mSec!");
480
     l1_exit(0);
481
  }
482
 
483
  /* OSLib initialization */
484
  if (sys_tick)
485
    parms.mode = LL_PERIODIC;
486
  else
487
    parms.mode = LL_ONESHOT; // one shot!!!
488
 
489
  parms.tick = sys_tick;
490
 
491
  /*
38 pj 492
   * Runlevel INIT: Let's go!!!!
2 pj 493
   *
494
   *
495
   */
496
 
497
  runlevel = RUNLEVEL_INIT;
498
 
499
  ll_init();
500
  event_init(&parms);
501
  seterrnumber(__errnumber);
502
  event_setprologue(event_resetepilogue);
503
  event_setlasthandler(kern_after_dispatch);
504
 
505
  /* call the init functions */
506
  call_runlevel_func(RUNLEVEL_INIT, 0);
507
 
38 pj 508
 
509
 
510
 
511
  /*
512
   * Runlevel RUNNING: Hoping that all works fine ;-)
513
   *
514
   *
515
   */
516
 
517
  runlevel = RUNLEVEL_RUNNING;
518
 
2 pj 519
  /* tracer stuff */
353 giacomo 520
  #ifdef __OLD_TRACER__
521
    trc_resume();
522
  #endif
2 pj 523
 
524
  /* exec and exec_shadow are already = -1 */
38 pj 525
  kern_gettime(&schedule_time);
2 pj 526
  scheduler();
913 pj 527
  global_context = ll_context_from(); /* It will be used by exit & co. */
2 pj 528
  ll_context_to(proc_table[exec_shadow].context);
529
 
530
  /*
531
   *
532
   * Now the system starts!!!
533
   * (hoping that someone has created some task(s) )
534
   * The function returns only at system end...
535
   *
536
   */
537
 
538
 
539
  /*
38 pj 540
   * Runlevel SHUTDOWN: Shutting down the system... :-(
2 pj 541
   *
913 pj 542
   * We return here only when exit or _exit is called
2 pj 543
   */
544
 
545
  event_setlasthandler(NULL);
913 pj 546
  event_noreschedule = 0;
2 pj 547
 
548
  // ll_abort(666); 
549
  /* tracer stuff */
353 giacomo 550
  #ifdef __OLD_TRACER__
551
    trc_suspend();
552
  #endif
2 pj 553
 
567 giacomo 554
  remove_default_exception_handler();
555
 
2 pj 556
  runlevel = RUNLEVEL_SHUTDOWN;
557
 
38 pj 558
  //kern_printf("after  - system_counter=%d, task_counter = %d\n", system_counter,task_counter); 
2 pj 559
 
913 pj 560
  call_runlevel_func(RUNLEVEL_SHUTDOWN, _exit_has_been_called);
2 pj 561
 
38 pj 562
  //kern_printf("before - system_counter=%d, task_counter = %d\n", system_counter,task_counter);
2 pj 563
 
564
  if (system_counter) {
565
    /* To shutdown the kernel correctly, we have to wait that all the SYSTEM
566
       tasks that are killable will die...
567
 
568
       We don't mess about the user task... we only kill them and reschedule
569
       The only thing important is that the system tasks shut down correctly.
570
       We do nothing for user tasks that remain active (because, for example,
571
       they have the cancelability set to deferred) when the system goes to
572
       runlevel 3 */
566 giacomo 573
 
38 pj 574
    //kern_printf("Û%lu",kern_gettime(NULL));
2 pj 575
    kill_user_tasks();
38 pj 576
    //kern_printf("Û%lu",kern_gettime(NULL)); 
2 pj 577
 
578
    /* exec and exec_shadow are already = -1 */
38 pj 579
    kern_gettime(&schedule_time);
913 pj 580
    global_context = ll_context_from(); /* It will be used by sys_abort_shutdown */
2 pj 581
    scheduler();
582
 
583
    event_setlasthandler(kern_after_dispatch);
584
    ll_context_to(proc_table[exec_shadow].context);
585
    event_setlasthandler(NULL);
586
  }
587
 
588
  /*
38 pj 589
   * Runlevel BEFORE_EXIT: Before Halting the system
2 pj 590
   *
591
   *
592
   */
593
 
594
  runlevel = RUNLEVEL_BEFORE_EXIT;
595
 
596
  /* the field global_errnumber is
597
     =0  if the system normally ends
598
     !=0 if an abort is issued
599
  */
600
 
601
  //kern_printf("Chiamo exit Functions\n"); 
602
 
913 pj 603
  call_runlevel_func(RUNLEVEL_BEFORE_EXIT, _exit_has_been_called==_EXIT_CALLED);
2 pj 604
 
605
  //kern_printf("Dopo exit Functions\n"); 
606
 
607
  /* Shut down the VM layer */
608
  ll_end();
609
 
610
  /*
38 pj 611
   * Runlevel AFTER_EXIT: After halting...
2 pj 612
   *
613
   *
614
   */
615
 
616
  runlevel = RUNLEVEL_AFTER_EXIT;
617
 
618
  //kern_printf("prima before Functions\n"); 
619
 
620
  call_runlevel_func(RUNLEVEL_AFTER_EXIT, 0);
621
 
622
  //kern_printf("dopo before Functions\n"); 
623
  kern_cli();
913 pj 624
  if (errnumber_global) {
625
    kern_printf("exit() or _exit() called with code : %u\n", errnumber_global);
2 pj 626
  }
627
 
913 pj 628
  if (errnumber_shutdown) {
629
    kern_printf("sys_abort_shutdown() called with code : %u (%s)\n", errnumber_shutdown);
630
  }
2 pj 631
 
913 pj 632
  l1_exit(errnumber_shutdown);
2 pj 633
}
634
 
913 pj 635
/* Close the system when we are in runlevel shutdown */
636
void sys_abort_shutdown(int err)
2 pj 637
{
913 pj 638
  SYS_FLAGS f;
639
 
640
  /* Check if the system is in SHUTDOWN mode */
641
  if (runlevel != RUNLEVEL_SHUTDOWN)
642
    exit(0);
643
 
644
  f = kern_fsave();
38 pj 645
 
913 pj 646
  errnumber_shutdown = err;
2 pj 647
 
38 pj 648
  if (ll_ActiveInt()) {
913 pj 649
    event_noreschedule=1;
38 pj 650
    ll_context_to(global_context);
913 pj 651
    kern_frestore(f);
2 pj 652
  }
913 pj 653
  else {
654
    task_makefree(TASK_CANCELED);
655
    // the scheduler is not called here because we are switching to the
656
    // global context!
657
    ll_context_to(global_context);
658
  }
2 pj 659
}
660
 
661
 
913 pj 662
void internal_exit(int status, int reason)
2 pj 663
{
664
  SYS_FLAGS f;
665
 
913 pj 666
  /* if something goes wron during the real mode */
667
  if (runlevel==RUNLEVEL_STARTUP || runlevel==RUNLEVEL_AFTER_EXIT)
668
    l1_exit(status);
669
 
568 giacomo 670
  /* Check if the system is in RUNNING mode */
671
  if (runlevel != RUNLEVEL_RUNNING) return;
672
 
2 pj 673
  f = kern_fsave();
568 giacomo 674
 
913 pj 675
  errnumber_global = status;
2 pj 676
 
913 pj 677
  if (!_exit_has_been_called)
678
    _exit_has_been_called = reason;
568 giacomo 679
 
913 pj 680
  if (ll_ActiveInt()) {
681
    event_noreschedule=1;
682
    ll_context_to(global_context);
683
    kern_frestore(f);
684
  }
685
  else {
686
    task_makefree(TASK_CANCELED);
687
    // the scheduler is not called here because we are switching to the
688
    // global context!
689
    ll_context_to(global_context);
690
  }
568 giacomo 691
}
692
 
913 pj 693
void exit(int status)
2 pj 694
{
913 pj 695
  internal_exit(status, EXIT_CALLED);
2 pj 696
}
697
 
698
void _exit(int status)
699
{
913 pj 700
  internal_exit(status, _EXIT_CALLED);
2 pj 701
}
702
 
703
 
704
 
705
/* this function is never called... used for the OSLib */
706
void sys_abort_tail(int code)
707
{
708
 //DUMMY!!!!
709
}
710
 
711
 
712
 
713
/*+ this primitive returns the time read from the system timer +*/
714
TIME sys_gettime(struct timespec *t)
715
{
716
  SYS_FLAGS f;
717
  TIME x;
718
 
719
  f = kern_fsave();
38 pj 720
  x = kern_gettime(t);
2 pj 721
  kern_frestore(f);
722
 
723
  return x;
724
}
725
 
726