Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1663 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
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
11
 *   Luca Abeni          <luca@gandalf.sssup.it>
12
 *   (see the web pages for full authors list)
13
 *
14
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
15
 *
16
 * http://www.sssup.it
17
 * http://retis.sssup.it
18
 * http://shark.sssup.it
19
 */
20
 
21
/**
22
 ------------
23
 CVS :        $Id: rrvalue.c,v 1.1 2004-07-05 14:17:14 pj Exp $
24
 
25
 File:        $File$
26
 Revision:    $Revision: 1.1 $
27
 Last update: $Date: 2004-07-05 14:17:14 $
28
 ------------
29
 
30
 This file contains the scheduling module RRVALUE (Round Robin)
31
 
32
 Read rrvalue.h for further details.
33
 
34
**/
35
 
36
/*
37
 * Copyright (C) 2001 Paolo Gai
38
 *
39
 * This program is free software; you can redistribute it and/or modify
40
 * it under the terms of the GNU General Public License as published by
41
 * the Free Software Foundation; either version 2 of the License, or
42
 * (at your option) any later version.
43
 *
44
 * This program is distributed in the hope that it will be useful,
45
 * but WITHOUT ANY WARRSOFTANTY; without even the implied waRRSOFTanty of
46
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
47
 * GNU General Public License for more details.
48
 *
49
 * You should have received a copy of the GNU General Public License
50
 * along with this program; if not, write to the Free Software
51
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
52
 *
53
 */
54
 
55
 
56
#include "rrvalue.h"
57
#include <ll/stdio.h>
58
#include <ll/string.h>
59
#include <kernel/model.h>
60
#include <kernel/descr.h>
61
#include <kernel/var.h>
62
#include <kernel/func.h>
63
 
64
/*+ Status used in the level +*/
65
#define RRVALUE_READY   MODULE_STATUS_BASE
66
#define RRVALUE_DELAY   MODULE_STATUS_BASE+1
67
#define RRVALUE_IDLE    MODULE_STATUS_BASE+2
68
 
69
/*+ the level redefinition for the Round Robin level +*/
70
typedef struct {
71
  level_des l;     /*+ the standard level descriptor          +*/
72
 
73
  int nact[MAX_PROC]; /*+ number of pending activations       +*/
74
 
75
  QQUEUE ready;    /*+ the ready queue                        +*/
76
 
77
  int slice;       /*+ the level's time slice                 +*/
78
 
79
  TIME period[MAX_PROC]; /*+  activation period               +*/
80
 
81
  struct timespec reactivation_time[MAX_PROC];
82
        /*+ the time at witch  the reactivation timer is post +*/
83
  int reactivation_timer[MAX_PROC];
84
                                   /*+ the recativation timer +*/
85
 
86
  BYTE periodic[MAX_PROC];
87
 
88
 
89
  struct multiboot_info *multiboot; /*+ used if the level have to insert
90
                                        the main task +*/
91
 
92
  BYTE models;      /*+ Task Model that the Module can Handle +*/
93
} RRVALUE_level_des;
94
 
95
 
96
static char *RRVALUE_status_to_a(WORD status)
97
{
98
  if (status < MODULE_STATUS_BASE)
99
    return status_to_a(status);
100
 
101
  switch (status) {
102
    case RRVALUE_READY: return "RRVALUE_Ready";
103
    case RRVALUE_DELAY: return "RRVALUE_Delay";
104
    case RRVALUE_IDLE : return "RRVALUE_Idle";
105
    default      : return "RRVALUE_Unknown";
106
  }
107
}
108
 
109
 
110
/* this is the periodic reactivation of the task... it is posted only
111
   if the task is a periodic task */
112
static void RRVALUE_timer_reactivate(void *par)
113
{
114
  PID p = (PID) par;
115
  RRVALUE_level_des *lev;
116
//  kern_printf("react");
117
 
118
  lev = (RRVALUE_level_des *)level_table[proc_table[p].task_level];
119
 
120
  if (proc_table[p].status == RRVALUE_IDLE) {
121
    /* the task has finished the current activation and must be
122
       reactivated */
123
    proc_table[p].status = RRVALUE_READY;
124
    qq_insertlast(p,&lev->ready);
125
 
126
    event_need_reschedule();
127
  }
128
  else if (lev->nact[p] >= 0)
129
    /* the task has not completed the current activation, so we save
130
       the activation incrementing nact... */
131
    lev->nact[p]++;
132
 
133
  /* repost the event at the next period end... */
134
  ADDUSEC2TIMESPEC(lev->period[p], &lev->reactivation_time[p]);
135
  lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
136
                                               RRVALUE_timer_reactivate,
137
                                               (void *)p);
138
  /* tracer stuff */
139
//  trc_logevent(TRC_INTACTIVATION,&p);
140
}
141
 
142
 
143
/*+ this function is called when a task finish his delay +*/
144
static void RRVALUE_timer_delay(void *par)
145
{
146
  PID p = (PID) par;
147
  RRVALUE_level_des *lev;
148
 
149
  lev = (RRVALUE_level_des *)level_table[proc_table[p].task_level];
150
 
151
  proc_table[p].status = RRVALUE_READY;
152
  qq_insertlast(p,&lev->ready);
153
 
154
  proc_table[p].delay_timer = NIL;  /* Paranoia */
155
 
156
//  kern_printf(" DELAY TIMER %d ", p);
157
 
158
  event_need_reschedule();
159
}
160
 
161
 
162
static int RRVALUE_level_accept_task_model(LEVEL l, TASK_MODEL *m)
163
{
164
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
165
 
166
  if ((m->pclass == NRT_PCLASS || m->pclass == (NRT_PCLASS | l)) && lev->models & RRVALUE_ONLY_NRT)
167
    return 0;
168
  else if ((m->pclass == SOFT_PCLASS || m->pclass == (SOFT_PCLASS | l)) && lev->models & RRVALUE_ONLY_SOFT)
169
    return 0;
170
  else if ((m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l)) && lev->models & RRVALUE_ONLY_HARD)
171
    return 0;
172
  else if ((m->pclass == VALUE_PCLASS || m->pclass == (VALUE_PCLASS | l)) && lev->models & RRVALUE_ONLY_VALUE)
173
    return 0;
174
  else
175
    return -1;
176
}
177
 
178
static int RRVALUE_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
179
{
180
    return -1;
181
}
182
 
183
static void RRVALUE_level_status(LEVEL l)
184
{
185
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
186
  PID p = qq_queryfirst(&lev->ready);
187
 
188
  kern_printf("Slice: %d \n", lev->slice);
189
 
190
  while (p != NIL) {
191
    kern_printf("Pid: %d\t Name: %20s Status: %s\n",p,proc_table[p].name,
192
              RRVALUE_status_to_a(proc_table[p].status));
193
    p = proc_table[p].next;
194
  }
195
 
196
  for (p=0; p<MAX_PROC; p++)
197
    if (proc_table[p].task_level == l && proc_table[p].status != RRVALUE_READY
198
        && proc_table[p].status != FREE )
199
      kern_printf("Pid: %d\t Name: %20s Status: %s\n",p,proc_table[p].name,
200
                RRVALUE_status_to_a(proc_table[p].status));
201
 
202
}
203
 
204
 
205
/* This is not efficient but very fair :-)
206
   The need of all this stuff is because if a task execute a long time
207
   due to (shadow!) priority inheritance, then the task shall go to the
208
   tail of the queue many times... */
209
static PID RRVALUE_level_scheduler(LEVEL l)
210
{
211
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
212
 
213
  PID p;
214
 
215
  for (;;) {
216
    p = qq_queryfirst(&lev->ready);
217
    if (p == -1)
218
      return p;
219
//{kern_printf("(s%d)",p);      return p;}
220
 
221
//    kern_printf("(p=%d l=%d avail=%d wcet =%d)\n",p,l,proc_table[p].avail_time, proc_table[p].wcet);
222
    if (proc_table[p].avail_time <= 0) {
223
      proc_table[p].avail_time += proc_table[p].wcet;
224
      qq_extract(p,&lev->ready);
225
      qq_insertlast(p,&lev->ready);
226
    }
227
    else
228
//{kern_printf("(s%d)",p);      return p;}
229
      return p;
230
 
231
  }
232
}
233
 
234
static int RRVALUE_level_guarantee(LEVEL l, bandwidth_t *freebandwidth)
235
{
236
  /* the RRVALUE level always guarantee... the function is defined because
237
     there can be an aperiodic server at a level with less priority than
238
     the RRVALUE that need guarantee (e.g., a TBS server) */
239
  return 1;
240
}
241
 
242
 
243
static int RRVALUE_task_create(LEVEL l, PID p, TASK_MODEL *m)
244
{
245
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
246
 
247
//  kern_printf("create %d mod %d\n",p,m->pclass);
248
  /* the task state is set at SLEEP by the general task_create
249
     the only thing to set remains the capacity stuffs that are set
250
     to the values passed in the model... */
251
 
252
  /* I used the wcet field because using wcet can account if a task
253
     consume more than the timeslice... */
254
 
255
  if (lev->models & RRVALUE_ONLY_NRT &&
256
      (m->pclass == NRT_PCLASS || m->pclass == (NRT_PCLASS | l))) {
257
    NRT_TASK_MODEL *nrt = (NRT_TASK_MODEL *)m;
258
 
259
//    kern_printf("nrt");
260
    if (nrt->slice) {
261
      proc_table[p].avail_time = nrt->slice;
262
      proc_table[p].wcet       = nrt->slice;
263
    }
264
    else {
265
      proc_table[p].avail_time = lev->slice;
266
      proc_table[p].wcet       = lev->slice;
267
    }
268
    proc_table[p].control   |= CONTROL_CAP;
269
 
270
    if (nrt->arrivals == SAVE_ARRIVALS)
271
      lev->nact[p] = 0;
272
    else
273
      lev->nact[p] = -1;
274
 
275
    lev->periodic[p] = 0;
276
    lev->period[p] = 0;
277
  }
278
  else if (lev->models & RRVALUE_ONLY_SOFT &&
279
           (m->pclass == SOFT_PCLASS || m->pclass == (SOFT_PCLASS | l))) {
280
    SOFT_TASK_MODEL *soft = (SOFT_TASK_MODEL *)m;
281
//    kern_printf("soft");
282
    proc_table[p].avail_time = lev->slice;
283
    proc_table[p].wcet       = lev->slice;
284
    proc_table[p].control   |= CONTROL_CAP;
285
 
286
    if (soft->arrivals == SAVE_ARRIVALS)
287
      lev->nact[p] = 0;
288
    else
289
      lev->nact[p] = -1;
290
 
291
    if (soft->periodicity == PERIODIC) {
292
      lev->periodic[p] = 1;
293
      lev->period[p] = soft->period;
294
    }
295
    else {
296
      lev->periodic[p] = 0;
297
      lev->period[p] = 0;
298
    }
299
  }
300
  else if (lev->models & RRVALUE_ONLY_HARD &&
301
           (m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l))) {
302
    HARD_TASK_MODEL *hard = (HARD_TASK_MODEL *)m;
303
//    kern_printf("hard");
304
    proc_table[p].avail_time = lev->slice;
305
    proc_table[p].wcet       = lev->slice;
306
    proc_table[p].control   |= CONTROL_CAP;
307
 
308
    lev->nact[p] = 0;
309
 
310
    if (hard->periodicity == PERIODIC) {
311
      lev->periodic[p] = 1;
312
      lev->period[p] = hard->mit;
313
    }
314
    else {
315
      lev->periodic[p] = 0;
316
      lev->period[p] = 0;
317
    }
318
  }
319
 
320
  if (lev->models & RRVALUE_ONLY_VALUE &&
321
      (m->pclass == VALUE_PCLASS || m->pclass == (VALUE_PCLASS | l))) {
322
    VALUE_TASK_MODEL *nrt = (NRT_TASK_MODEL *)m;
323
 
324
    proc_table[p].avail_time = lev->slice;
325
    proc_table[p].wcet       = lev->slice;
326
    proc_table[p].control   |= CONTROL_CAP;
327
    lev->nact[p] = -1;
328
    lev->periodic[p] = 0;
329
    lev->period[p] = 0;
330
  }
331
 
332
  return 0; /* OK */
333
}
334
 
335
static void RRVALUE_task_detach(LEVEL l, PID p)
336
{
337
  /* the RRVALUE level doesn't introduce any new field in the TASK_MODEL
338
     so, all detach stuffs are done by the task_create
339
     The task state is set at FREE by the general task_create */
340
}
341
 
342
static int RRVALUE_task_eligible(LEVEL l, PID p)
343
{
344
  return 0; /* if the task p is chosen, it is always eligible */
345
}
346
 
347
#ifdef __TEST1__
348
extern int testactive;
349
extern struct timespec s_stime[];
350
extern TIME s_curr[];
351
extern TIME s_PID[];
352
extern int useds;
353
#endif
354
 
355
static void RRVALUE_task_dispatch(LEVEL l, PID p, int nostop)
356
{
357
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
358
//static int p2count=0;
359
 
360
  /* the task state is set EXE by the scheduler()
361
     we extract the task from the ready queue
362
     NB: we can't assume that p is the first task in the queue!!! */
363
  qq_extract(p, &lev->ready);
364
}
365
 
366
static void RRVALUE_task_epilogue(LEVEL l, PID p)
367
{
368
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
369
 
370
  /* check if the slice is finished and insert the task in the coRRVALUEect
371
     qqueue position */
372
  if (proc_table[p].avail_time <= 0) {
373
    proc_table[p].avail_time += proc_table[p].wcet;
374
    qq_insertlast(p,&lev->ready);
375
  }
376
  else
377
    /* curr is >0, so the running task have to run for another cuRRVALUE usec */
378
    qq_insertfirst(p,&lev->ready);
379
 
380
  proc_table[p].status = RRVALUE_READY;
381
}
382
 
383
static void RRVALUE_task_activate(LEVEL l, PID p)
384
{
385
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
386
 
387
  /* Test if we are trying to activate a non sleeping task    */
388
  /* save activation (only if needed... */
389
  if (proc_table[p].status != SLEEP && proc_table[p].status != RRVALUE_IDLE) {
390
    if (lev->nact[p] != -1)
391
      lev->nact[p]++;
392
    return;
393
  }
394
 
395
  ll_gettime(TIME_EXACT, &proc_table[p].request_time);
396
 
397
  /* Insert task in the coRRVALUEect position */
398
  proc_table[p].status = RRVALUE_READY;
399
  qq_insertlast(p,&lev->ready);
400
 
401
  /* Set the reactivation timer */
402
  if (lev->periodic[p])
403
  {
404
    TIMESPEC_ASSIGN(&lev->reactivation_time[p], &proc_table[p].request_time);
405
    ADDUSEC2TIMESPEC(lev->period[p], &lev->reactivation_time[p]);
406
//    TIMESPEC_ASSIGN(&lev->reactivation_time[p], &lev->cbs_dline[p]);
407
    lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
408
                                                 RRVALUE_timer_reactivate,
409
                                                 (void *)p);
410
  }
411
}
412
 
413
static void RRVALUE_task_insert(LEVEL l, PID p)
414
{
415
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
416
 
417
  /* Similar to RRVALUE_task_activate, but we don't check in what state
418
     the task is and we don't set the request_time */
419
 
420
  /* Insert task in the coRRVALUEect position */
421
  proc_table[p].status = RRVALUE_READY;
422
  qq_insertlast(p,&lev->ready);
423
}
424
 
425
static void RRVALUE_task_extract(LEVEL l, PID p)
426
{
427
  /* Extract the running task from the level
428
     . we have already extract it from the ready queue at the dispatch time.
429
     . the capacity event have to be removed by the generic kernel
430
     . the wcet don't need modification...
431
     . the state of the task is set by the calling function
432
 
433
     So, we do nothing!!!
434
  */
435
}
436
 
437
static void RRVALUE_task_endcycle(LEVEL l, PID p)
438
{
439
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
440
 
441
  if (lev->nact[p] > 0) {
442
    /* continue!!!! */
443
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
444
    lev->nact[p]--;
445
//    qq_insertlast(p,&lev->ready);
446
    qq_insertfirst(p,&lev->ready);
447
    proc_table[p].status = RRVALUE_READY;
448
  }
449
  else
450
    proc_table[p].status = RRVALUE_IDLE;
451
}
452
 
453
static void RRVALUE_task_end(LEVEL l, PID p)
454
{
455
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
456
 
457
  lev->nact[p] = -1;
458
 
459
  /* we delete the reactivation timer */
460
  if (lev->periodic[p]) {
461
    event_delete(lev->reactivation_timer[p]);
462
    lev->reactivation_timer[p] = -1;
463
  }
464
 
465
  /* then, we insert the task in the free queue */
466
  proc_table[p].status = FREE;
467
  q_insert(p,&freedesc);
468
}
469
 
470
static void RRVALUE_task_sleep(LEVEL l, PID p)
471
{
472
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
473
 
474
  if (lev->nact[p] >= 0) lev->nact[p] = 0;
475
 
476
  /* we delete the reactivation timer */
477
  if (lev->periodic[p]) {
478
    event_delete(lev->reactivation_timer[p]);
479
    lev->reactivation_timer[p] = -1;
480
  }
481
 
482
  proc_table[p].status = SLEEP;
483
}
484
 
485
static void RRVALUE_task_delay(LEVEL l, PID p, TIME usdelay)
486
{
487
//  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
488
  struct timespec wakeuptime;
489
 
490
  /* equal to RRVALUE_task_endcycle */
491
  proc_table[p].status = RRVALUE_DELAY;
492
 
493
  /* we need to delete this event if we kill the task while it is sleeping */
494
  ll_gettime(TIME_EXACT,&wakeuptime);
495
  ADDUSEC2TIMESPEC(usdelay,&wakeuptime);
496
  proc_table[p].delay_timer = kern_event_post(&wakeuptime,
497
                                              RRVALUE_timer_delay,
498
                                              (void *)p);
499
}
500
 
501
 
502
static int RRVALUE_guest_create(LEVEL l, PID p, TASK_MODEL *m)
503
{ kern_raise(XUNVALID_GUEST,exec_shadow); return 0; }
504
 
505
static void RRVALUE_guest_detach(LEVEL l, PID p)
506
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
507
 
508
static void RRVALUE_guest_dispatch(LEVEL l, PID p, int nostop)
509
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
510
 
511
static void RRVALUE_guest_epilogue(LEVEL l, PID p)
512
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
513
 
514
static void RRVALUE_guest_activate(LEVEL l, PID p)
515
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
516
 
517
static void RRVALUE_guest_insert(LEVEL l, PID p)
518
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
519
 
520
static void RRVALUE_guest_extract(LEVEL l, PID p)
521
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
522
 
523
static void RRVALUE_guest_endcycle(LEVEL l, PID p)
524
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
525
 
526
static void RRVALUE_guest_end(LEVEL l, PID p)
527
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
528
 
529
static void RRVALUE_guest_sleep(LEVEL l, PID p)
530
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
531
 
532
static void RRVALUE_guest_delay(LEVEL l, PID p,DWORD tickdelay)
533
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
534
 
535
 
536
 
537
 
538
/* Registration functions */
539
 
540
/*+ This init function install the "main" task +*/
541
static void RRVALUE_call_main(void *l)
542
{
543
  LEVEL lev;
544
  PID p;
545
  NRT_TASK_MODEL m;
546
  void *mb;
547
 
548
  lev = (LEVEL)l;
549
 
550
  nrt_task_default_model(m);
551
  nrt_task_def_level(m,lev); /* with this we are sure that the task aRRVALUEives
552
                                to the coRRVALUEect level */
553
 
554
  mb = ((RRVALUE_level_des *)level_table[lev])->multiboot;
555
  nrt_task_def_arg(m,mb);
556
  nrt_task_def_usemath(m);
557
  nrt_task_def_nokill(m);
558
  nrt_task_def_ctrl_jet(m);
559
 
560
  p = task_create("Main", __init__, (TASK_MODEL *)&m, NULL);
561
 
562
  if (p == NIL)
563
    printk("\nPanic!!! can't create main task...\n");
564
 
565
  RRVALUE_task_activate(lev,p);
566
}
567
 
568
 
569
/*+ Registration function:
570
    TIME slice                the slice for the Round Robin queue
571
    int createmain            1 if the level creates the main task 0 otherwise
572
    struct multiboot_info *mb used if createmain specified   +*/
573
void RRVALUE_register_level(TIME slice,
574
                       int createmain,
575
                       struct multiboot_info *mb,
576
                       BYTE models)
577
{
578
  LEVEL l;            /* the level that we register */
579
  RRVALUE_level_des *lev;  /* for readableness only */
580
  PID i;
581
 
582
  printk("RRVALUE_register_level\n");
583
 
584
  /* request an entry in the level_table */
585
  l = level_alloc_descriptor();
586
 
587
  /* alloc the space needed for the RRVALUE_level_des */
588
  lev = (RRVALUE_level_des *)kern_alloc(sizeof(RRVALUE_level_des));
589
 
590
  printk("    lev=%d\n",(int)lev);
591
 
592
  /* update the level_table with the new entry */
593
  level_table[l] = (level_des *)lev;
594
 
595
  /* fill the standard descriptor */
596
  strncpy(lev->l.level_name,  RRVALUE_LEVELNAME, MAX_LEVELNAME);
597
  lev->l.level_code               = RRVALUE_LEVEL_CODE;
598
  lev->l.level_version            = RRVALUE_LEVEL_VERSION;
599
 
600
  lev->l.level_accept_task_model  = RRVALUE_level_accept_task_model;
601
  lev->l.level_accept_guest_model = RRVALUE_level_accept_guest_model;
602
  lev->l.level_status             = RRVALUE_level_status;
603
  lev->l.level_scheduler          = RRVALUE_level_scheduler;
604
  lev->l.level_guarantee          = RRVALUE_level_guarantee;
605
 
606
  lev->l.task_create              = RRVALUE_task_create;
607
  lev->l.task_detach              = RRVALUE_task_detach;
608
  lev->l.task_eligible            = RRVALUE_task_eligible;
609
  lev->l.task_dispatch            = RRVALUE_task_dispatch;
610
  lev->l.task_epilogue            = RRVALUE_task_epilogue;
611
  lev->l.task_activate            = RRVALUE_task_activate;
612
  lev->l.task_insert              = RRVALUE_task_insert;
613
  lev->l.task_extract             = RRVALUE_task_extract;
614
  lev->l.task_endcycle            = RRVALUE_task_endcycle;
615
  lev->l.task_end                 = RRVALUE_task_end;
616
  lev->l.task_sleep               = RRVALUE_task_sleep;
617
  lev->l.task_delay               = RRVALUE_task_delay;
618
 
619
  lev->l.guest_create             = RRVALUE_guest_create;
620
  lev->l.guest_detach             = RRVALUE_guest_detach;
621
  lev->l.guest_dispatch           = RRVALUE_guest_dispatch;
622
  lev->l.guest_epilogue           = RRVALUE_guest_epilogue;
623
  lev->l.guest_activate           = RRVALUE_guest_activate;
624
  lev->l.guest_insert             = RRVALUE_guest_insert;
625
  lev->l.guest_extract            = RRVALUE_guest_extract;
626
  lev->l.guest_endcycle           = RRVALUE_guest_endcycle;
627
  lev->l.guest_end                = RRVALUE_guest_end;
628
  lev->l.guest_sleep              = RRVALUE_guest_sleep;
629
  lev->l.guest_delay              = RRVALUE_guest_delay;
630
 
631
  /* fill the RRVALUE descriptor part */
632
  for (i = 0; i < MAX_PROC; i++) {
633
    lev->nact[i] = -1;
634
    NULL_TIMESPEC(&lev->reactivation_time[i]);
635
    lev->reactivation_timer[i] = -1;
636
    lev->periodic[i] = 0;
637
    lev->period[i] = 0;
638
  }
639
 
640
  qq_init(&lev->ready);
641
 
642
  if (slice < RRVALUE_MINIMUM_SLICE) slice = RRVALUE_MINIMUM_SLICE;
643
  if (slice > RRVALUE_MAXIMUM_SLICE) slice = RRVALUE_MAXIMUM_SLICE;
644
  lev->slice      = slice;
645
 
646
  lev->multiboot  = mb;
647
 
648
  lev->models     = models;
649
 
650
  if (createmain)
651
    sys_atrunlevel(RRVALUE_call_main,(void *) l, RUNLEVEL_INIT);
652
}
653
 
654
 
655
 
656