Subversion Repositories shark

Rev

Rev 2 | 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
 *   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: rrsoft.c,v 1.1.1.1 2002-03-29 14:12:52 pj Exp $
24
 
25
 File:        $File$
26
 Revision:    $Revision: 1.1.1.1 $
27
 Last update: $Date: 2002-03-29 14:12:52 $
28
 ------------
29
 
30
 This file contains the scheduling module RRSOFT (Round Robin)
31
 
32
 Read rrsoft.h for further details.
33
 
34
**/
35
 
36
/*
37
 * Copyright (C) 2000 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 <modules/rrsoft.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 RRSOFT_READY   MODULE_STATUS_BASE
66
#define RRSOFT_DELAY   MODULE_STATUS_BASE+1
67
#define RRSOFT_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
} RRSOFT_level_des;
94
 
95
 
96
static char *RRSOFT_status_to_a(WORD status)
97
{
98
  if (status < MODULE_STATUS_BASE)
99
    return status_to_a(status);
100
 
101
  switch (status) {
102
    case RRSOFT_READY: return "RRSOFT_Ready";
103
    case RRSOFT_DELAY: return "RRSOFT_Delay";
104
    case RRSOFT_IDLE : return "RRSOFT_Idle";
105
    default      : return "RRSOFT_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 RRSOFT_timer_reactivate(void *par)
113
{
114
  PID p = (PID) par;
115
  RRSOFT_level_des *lev;
116
//  kern_printf("react");
117
 
118
  lev = (RRSOFT_level_des *)level_table[proc_table[p].task_level];
119
 
120
  if (proc_table[p].status == RRSOFT_IDLE) {
121
    /* the task has finished the current activation and must be
122
       reactivated */
123
    proc_table[p].status = RRSOFT_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
                                               RRSOFT_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 RRSOFT_timer_delay(void *par)
145
{
146
  PID p = (PID) par;
147
  RRSOFT_level_des *lev;
148
 
149
  lev = (RRSOFT_level_des *)level_table[proc_table[p].task_level];
150
 
151
  proc_table[p].status = RRSOFT_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 RRSOFT_level_accept_task_model(LEVEL l, TASK_MODEL *m)
163
{
164
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
165
 
166
  if ((m->pclass == NRT_PCLASS || m->pclass == (NRT_PCLASS | l)) && lev->models & RRSOFT_ONLY_NRT)
167
    return 0;
168
  else if ((m->pclass == SOFT_PCLASS || m->pclass == (SOFT_PCLASS | l)) && lev->models & RRSOFT_ONLY_SOFT)
169
    return 0;
170
  else if ((m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l)) && lev->models & RRSOFT_ONLY_HARD)
171
    return 0;
172
  else
173
    return -1;
174
}
175
 
176
static int RRSOFT_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
177
{
178
    return -1;
179
}
180
 
181
static void RRSOFT_level_status(LEVEL l)
182
{
183
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
184
  PID p = qq_queryfirst(&lev->ready);
185
 
186
  kern_printf("Slice: %d \n", lev->slice);
187
 
188
  while (p != NIL) {
189
    kern_printf("Pid: %d\t Name: %20s Status: %s\n",p,proc_table[p].name,
190
              RRSOFT_status_to_a(proc_table[p].status));
191
    p = proc_table[p].next;
192
  }
193
 
194
  for (p=0; p<MAX_PROC; p++)
195
    if (proc_table[p].task_level == l && proc_table[p].status != RRSOFT_READY
196
        && proc_table[p].status != FREE )
197
      kern_printf("Pid: %d\t Name: %20s Status: %s\n",p,proc_table[p].name,
198
                RRSOFT_status_to_a(proc_table[p].status));
199
 
200
}
201
 
202
 
203
/* This is not efficient but very fair :-)
204
   The need of all this stuff is because if a task execute a long time
205
   due to (shadow!) priority inheritance, then the task shall go to the
206
   tail of the queue many times... */
207
static PID RRSOFT_level_scheduler(LEVEL l)
208
{
209
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
210
 
211
  PID p;
212
 
213
  for (;;) {
214
    p = qq_queryfirst(&lev->ready);
215
    if (p == -1)
216
      return p;
217
//{kern_printf("(s%d)",p);      return p;}
218
 
219
//    kern_printf("(p=%d l=%d avail=%d wcet =%d)\n",p,l,proc_table[p].avail_time, proc_table[p].wcet);
220
    if (proc_table[p].avail_time <= 0) {
221
      proc_table[p].avail_time += proc_table[p].wcet;
222
      qq_extract(p,&lev->ready);
223
      qq_insertlast(p,&lev->ready);
224
    }
225
    else
226
//{kern_printf("(s%d)",p);      return p;}
227
      return p;
228
 
229
  }
230
}
231
 
232
static int RRSOFT_level_guarantee(LEVEL l, bandwidth_t *freebandwidth)
233
{
234
  /* the RRSOFT level always guarantee... the function is defined because
235
     there can be an aperiodic server at a level with less priority than
236
     the RRSOFT that need guarantee (e.g., a TBS server) */
237
  return 1;
238
}
239
 
240
 
241
static int RRSOFT_task_create(LEVEL l, PID p, TASK_MODEL *m)
242
{
243
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
244
 
245
//  kern_printf("create %d mod %d\n",p,m->pclass);
246
  /* the task state is set at SLEEP by the general task_create
247
     the only thing to set remains the capacity stuffs that are set
248
     to the values passed in the model... */
249
 
250
  /* I used the wcet field because using wcet can account if a task
251
     consume more than the timeslice... */
252
 
253
  if (lev->models & RRSOFT_ONLY_NRT &&
254
      (m->pclass == NRT_PCLASS || m->pclass == (NRT_PCLASS | l))) {
255
    NRT_TASK_MODEL *nrt = (NRT_TASK_MODEL *)m;
256
 
257
//    kern_printf("nrt");
258
    if (nrt->slice) {
259
      proc_table[p].avail_time = nrt->slice;
260
      proc_table[p].wcet       = nrt->slice;
261
    }
262
    else {
263
      proc_table[p].avail_time = lev->slice;
264
      proc_table[p].wcet       = lev->slice;
265
    }
266
    proc_table[p].control   |= CONTROL_CAP;
267
 
268
    if (nrt->arrivals == SAVE_ARRIVALS)
269
      lev->nact[p] = 0;
270
    else
271
      lev->nact[p] = -1;
272
 
273
    lev->periodic[p] = 0;
274
    lev->period[p] = 0;
275
  }
276
  else if (lev->models & RRSOFT_ONLY_SOFT &&
277
           (m->pclass == SOFT_PCLASS || m->pclass == (SOFT_PCLASS | l))) {
278
    SOFT_TASK_MODEL *soft = (SOFT_TASK_MODEL *)m;
279
//    kern_printf("soft");
280
    proc_table[p].avail_time = lev->slice;
281
    proc_table[p].wcet       = lev->slice;
282
    proc_table[p].control   |= CONTROL_CAP;
283
 
284
    if (soft->arrivals == SAVE_ARRIVALS)
285
      lev->nact[p] = 0;
286
    else
287
      lev->nact[p] = -1;
288
 
289
    if (soft->periodicity == PERIODIC) {
290
      lev->periodic[p] = 1;
291
      lev->period[p] = soft->period;
292
    }
293
  }
294
  else if (lev->models & RRSOFT_ONLY_HARD &&
295
           (m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l))) {
296
    HARD_TASK_MODEL *hard = (HARD_TASK_MODEL *)m;
297
//    kern_printf("hard");
298
    proc_table[p].avail_time = lev->slice;
299
    proc_table[p].wcet       = lev->slice;
300
    proc_table[p].control   |= CONTROL_CAP;
301
 
302
    lev->nact[p] = 0;
303
 
304
    if (hard->periodicity == PERIODIC) {
305
      lev->periodic[p] = 1;
306
      lev->period[p] = hard->mit;
307
    }
308
  }
309
 
310
  return 0; /* OK */
311
}
312
 
313
static void RRSOFT_task_detach(LEVEL l, PID p)
314
{
315
  /* the RRSOFT level doesn't introduce any new field in the TASK_MODEL
316
     so, all detach stuffs are done by the task_create
317
     The task state is set at FREE by the general task_create */
318
}
319
 
320
static int RRSOFT_task_eligible(LEVEL l, PID p)
321
{
322
  return 0; /* if the task p is chosen, it is always eligible */
323
}
324
 
325
#ifdef __TEST1__
326
extern int testactive;
327
extern struct timespec s_stime[];
328
extern TIME s_curr[];
329
extern TIME s_PID[];
330
extern int useds;
331
#endif
332
 
333
static void RRSOFT_task_dispatch(LEVEL l, PID p, int nostop)
334
{
335
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
336
//static int p2count=0;
337
 
338
  /* the task state is set EXE by the scheduler()
339
     we extract the task from the ready queue
340
     NB: we can't assume that p is the first task in the queue!!! */
341
  qq_extract(p, &lev->ready);
342
 
343
 
344
  #ifdef __TEST1__
345
  if (testactive)
346
  {
347
    TIMESPEC_ASSIGN(&s_stime[useds],&schedule_time);
348
    s_curr[useds] = proc_table[p].avail_time;
349
    s_PID[useds]  = p;
350
    useds++;
351
  }
352
  #endif
353
}
354
 
355
static void RRSOFT_task_epilogue(LEVEL l, PID p)
356
{
357
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
358
 
359
  /* check if the slice is finished and insert the task in the coRRSOFTect
360
     qqueue position */
361
  if (proc_table[p].avail_time <= 0) {
362
    proc_table[p].avail_time += proc_table[p].wcet;
363
    qq_insertlast(p,&lev->ready);
364
  }
365
  else
366
    /* curr is >0, so the running task have to run for another cuRRSOFT usec */
367
    qq_insertfirst(p,&lev->ready);
368
 
369
  proc_table[p].status = RRSOFT_READY;
370
}
371
 
372
static void RRSOFT_task_activate(LEVEL l, PID p)
373
{
374
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
375
 
376
  /* Test if we are trying to activate a non sleeping task    */
377
  /* save activation (only if needed... */
378
  if (proc_table[p].status != SLEEP && proc_table[p].status != RRSOFT_IDLE) {
379
    if (lev->nact[p] != -1)
380
      lev->nact[p]++;
381
    return;
382
  }
383
 
384
  ll_gettime(TIME_EXACT, &proc_table[p].request_time);
385
 
386
  /* Insert task in the coRRSOFTect position */
387
  proc_table[p].status = RRSOFT_READY;
388
  qq_insertlast(p,&lev->ready);
389
 
390
  /* Set the reactivation timer */
391
  if (lev->periodic[p])
392
  {
393
    TIMESPEC_ASSIGN(&lev->reactivation_time[p], &proc_table[p].request_time);
394
    ADDUSEC2TIMESPEC(lev->period[p], &lev->reactivation_time[p]);
395
//    TIMESPEC_ASSIGN(&lev->reactivation_time[p], &lev->cbs_dline[p]);
396
    lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
397
                                                 RRSOFT_timer_reactivate,
398
                                                 (void *)p);
399
  }
400
}
401
 
402
static void RRSOFT_task_insert(LEVEL l, PID p)
403
{
404
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
405
 
406
  /* Similar to RRSOFT_task_activate, but we don't check in what state
407
     the task is and we don't set the request_time */
408
 
409
  /* Insert task in the coRRSOFTect position */
410
  proc_table[p].status = RRSOFT_READY;
411
  qq_insertlast(p,&lev->ready);
412
}
413
 
414
static void RRSOFT_task_extract(LEVEL l, PID p)
415
{
416
  /* Extract the running task from the level
417
     . we have already extract it from the ready queue at the dispatch time.
418
     . the capacity event have to be removed by the generic kernel
419
     . the wcet don't need modification...
420
     . the state of the task is set by the calling function
421
 
422
     So, we do nothing!!!
423
  */
424
}
425
 
426
static void RRSOFT_task_endcycle(LEVEL l, PID p)
427
{
428
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
429
 
430
  if (lev->nact[p] > 0) {
431
    /* continue!!!! */
432
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
433
    lev->nact[p]--;
434
//    qq_insertlast(p,&lev->ready);
435
    qq_insertfirst(p,&lev->ready);
436
    proc_table[p].status = RRSOFT_READY;
437
  }
438
  else
439
    proc_table[p].status = RRSOFT_IDLE;
440
}
441
 
442
static void RRSOFT_task_end(LEVEL l, PID p)
443
{
444
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
445
 
446
  lev->nact[p] = -1;
447
 
448
  /* we delete the reactivation timer */
449
  if (lev->periodic[p]) {
450
    event_delete(lev->reactivation_timer[p]);
451
    lev->reactivation_timer[p] = -1;
452
  }
453
 
454
  /* then, we insert the task in the free queue */
455
  proc_table[p].status = FREE;
456
  q_insert(p,&freedesc);
457
}
458
 
459
static void RRSOFT_task_sleep(LEVEL l, PID p)
460
{
461
  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
462
 
463
  if (lev->nact[p] >= 0) lev->nact[p] = 0;
464
 
465
  /* we delete the reactivation timer */
466
  if (lev->periodic[p]) {
467
    event_delete(lev->reactivation_timer[p]);
468
    lev->reactivation_timer[p] = -1;
469
  }
470
 
471
  proc_table[p].status = SLEEP;
472
}
473
 
474
static void RRSOFT_task_delay(LEVEL l, PID p, TIME usdelay)
475
{
476
//  RRSOFT_level_des *lev = (RRSOFT_level_des *)(level_table[l]);
477
  struct timespec wakeuptime;
478
 
479
  /* equal to RRSOFT_task_endcycle */
480
  proc_table[p].status = RRSOFT_DELAY;
481
 
482
  /* we need to delete this event if we kill the task while it is sleeping */
483
  ll_gettime(TIME_EXACT,&wakeuptime);
484
  ADDUSEC2TIMESPEC(usdelay,&wakeuptime);
485
  proc_table[p].delay_timer = kern_event_post(&wakeuptime,
486
                                              RRSOFT_timer_delay,
487
                                              (void *)p);
488
}
489
 
490
 
491
static int RRSOFT_guest_create(LEVEL l, PID p, TASK_MODEL *m)
492
{ kern_raise(XUNVALID_GUEST,exec_shadow); return 0; }
493
 
494
static void RRSOFT_guest_detach(LEVEL l, PID p)
495
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
496
 
497
static void RRSOFT_guest_dispatch(LEVEL l, PID p, int nostop)
498
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
499
 
500
static void RRSOFT_guest_epilogue(LEVEL l, PID p)
501
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
502
 
503
static void RRSOFT_guest_activate(LEVEL l, PID p)
504
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
505
 
506
static void RRSOFT_guest_insert(LEVEL l, PID p)
507
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
508
 
509
static void RRSOFT_guest_extract(LEVEL l, PID p)
510
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
511
 
512
static void RRSOFT_guest_endcycle(LEVEL l, PID p)
513
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
514
 
515
static void RRSOFT_guest_end(LEVEL l, PID p)
516
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
517
 
518
static void RRSOFT_guest_sleep(LEVEL l, PID p)
519
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
520
 
521
static void RRSOFT_guest_delay(LEVEL l, PID p,DWORD tickdelay)
522
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
523
 
524
 
525
 
526
 
527
/* Registration functions */
528
 
529
/*+ This init function install the "main" task +*/
530
static void RRSOFT_call_main(void *l)
531
{
532
  LEVEL lev;
533
  PID p;
534
  NRT_TASK_MODEL m;
535
  void *mb;
536
 
537
  lev = (LEVEL)l;
538
 
539
  nrt_task_default_model(m);
540
  nrt_task_def_level(m,lev); /* with this we are sure that the task aRRSOFTives
541
                                to the coRRSOFTect level */
542
 
543
  mb = ((RRSOFT_level_des *)level_table[lev])->multiboot;
544
  nrt_task_def_arg(m,mb);
545
  nrt_task_def_usemath(m);
546
  nrt_task_def_nokill(m);
547
  nrt_task_def_ctrl_jet(m);
548
 
549
  p = task_create("Main", __init__, (TASK_MODEL *)&m, NULL);
550
 
551
  if (p == NIL)
552
    printk("\nPanic!!! can't create main task...\n");
553
 
554
  RRSOFT_task_activate(lev,p);
555
}
556
 
557
 
558
/*+ Registration function:
559
    TIME slice                the slice for the Round Robin queue
560
    int createmain            1 if the level creates the main task 0 otherwise
561
    struct multiboot_info *mb used if createmain specified   +*/
562
void RRSOFT_register_level(TIME slice,
563
                       int createmain,
564
                       struct multiboot_info *mb,
565
                       BYTE models)
566
{
567
  LEVEL l;            /* the level that we register */
568
  RRSOFT_level_des *lev;  /* for readableness only */
569
  PID i;
570
 
571
  printk("RRSOFT_register_level\n");
572
 
573
  /* request an entry in the level_table */
574
  l = level_alloc_descriptor();
575
 
576
  /* alloc the space needed for the RRSOFT_level_des */
577
  lev = (RRSOFT_level_des *)kern_alloc(sizeof(RRSOFT_level_des));
578
 
579
  printk("    lev=%d\n",(int)lev);
580
 
581
  /* update the level_table with the new entry */
582
  level_table[l] = (level_des *)lev;
583
 
584
  /* fill the standard descriptor */
585
  strncpy(lev->l.level_name,  RRSOFT_LEVELNAME, MAX_LEVELNAME);
586
  lev->l.level_code               = RRSOFT_LEVEL_CODE;
587
  lev->l.level_version            = RRSOFT_LEVEL_VERSION;
588
 
589
  lev->l.level_accept_task_model  = RRSOFT_level_accept_task_model;
590
  lev->l.level_accept_guest_model = RRSOFT_level_accept_guest_model;
591
  lev->l.level_status             = RRSOFT_level_status;
592
  lev->l.level_scheduler          = RRSOFT_level_scheduler;
593
  lev->l.level_guarantee          = RRSOFT_level_guarantee;
594
 
595
  lev->l.task_create              = RRSOFT_task_create;
596
  lev->l.task_detach              = RRSOFT_task_detach;
597
  lev->l.task_eligible            = RRSOFT_task_eligible;
598
  lev->l.task_dispatch            = RRSOFT_task_dispatch;
599
  lev->l.task_epilogue            = RRSOFT_task_epilogue;
600
  lev->l.task_activate            = RRSOFT_task_activate;
601
  lev->l.task_insert              = RRSOFT_task_insert;
602
  lev->l.task_extract             = RRSOFT_task_extract;
603
  lev->l.task_endcycle            = RRSOFT_task_endcycle;
604
  lev->l.task_end                 = RRSOFT_task_end;
605
  lev->l.task_sleep               = RRSOFT_task_sleep;
606
  lev->l.task_delay               = RRSOFT_task_delay;
607
 
608
  lev->l.guest_create             = RRSOFT_guest_create;
609
  lev->l.guest_detach             = RRSOFT_guest_detach;
610
  lev->l.guest_dispatch           = RRSOFT_guest_dispatch;
611
  lev->l.guest_epilogue           = RRSOFT_guest_epilogue;
612
  lev->l.guest_activate           = RRSOFT_guest_activate;
613
  lev->l.guest_insert             = RRSOFT_guest_insert;
614
  lev->l.guest_extract            = RRSOFT_guest_extract;
615
  lev->l.guest_endcycle           = RRSOFT_guest_endcycle;
616
  lev->l.guest_end                = RRSOFT_guest_end;
617
  lev->l.guest_sleep              = RRSOFT_guest_sleep;
618
  lev->l.guest_delay              = RRSOFT_guest_delay;
619
 
620
  /* fill the RRSOFT descriptor part */
621
  for (i = 0; i < MAX_PROC; i++) {
622
    lev->nact[i] = -1;
623
    NULL_TIMESPEC(&lev->reactivation_time[i]);
624
    lev->reactivation_timer[i] = -1;
625
    lev->periodic[i] = 0;
626
    lev->period[i] = 0;
627
  }
628
 
629
  qq_init(&lev->ready);
630
 
631
  if (slice < RRSOFT_MINIMUM_SLICE) slice = RRSOFT_MINIMUM_SLICE;
632
  if (slice > RRSOFT_MAXIMUM_SLICE) slice = RRSOFT_MAXIMUM_SLICE;
633
  lev->slice      = slice;
634
 
635
  lev->multiboot  = mb;
636
 
637
  lev->models     = models;
638
 
639
  if (createmain)
640
    sys_atrunlevel(RRSOFT_call_main,(void *) l, RUNLEVEL_INIT);
641
}
642
 
643
 
644
 
645