Subversion Repositories shark

Rev

Rev 3 | 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
 ------------
14 pj 23
 CVS :        $Id: ds.c,v 1.2 2002-10-28 07:55:54 pj Exp $
2 pj 24
 
25
 File:        $File$
14 pj 26
 Revision:    $Revision: 1.2 $
27
 Last update: $Date: 2002-10-28 07:55:54 $
2 pj 28
 ------------
29
 
30
 This file contains the aperiodic server DS (Deferrable Server)
31
 
32
 This module is directly derived from the Polling server one.
33
 All the notes writed for the PS are valid for the DS.
34
 
35
 The difference between DS and PS is that when there are not task to
36
 schedule the capacity is not reset to 0...
37
 
38
**/
39
 
40
/*
41
 * Copyright (C) 2000 Paolo Gai
42
 *
43
 * This program is free software; you can redistribute it and/or modify
44
 * it under the terms of the GNU General Public License as published by
45
 * the Free Software Foundation; either version 2 of the License, or
46
 * (at your option) any later version.
47
 *
48
 * This program is distributed in the hope that it will be useful,
49
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
50
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
51
 * GNU General Public License for more details.
52
 *
53
 * You should have received a copy of the GNU General Public License
54
 * along with this program; if not, write to the Free Software
55
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
56
 *
57
 */
58
 
59
 
60
#include <modules/ds.h>
61
#include <ll/stdio.h>
62
#include <ll/string.h>
63
#include <kernel/model.h>
64
#include <kernel/descr.h>
65
#include <kernel/var.h>
66
#include <kernel/func.h>
67
 
68
/*+ Status used in the level +*/
69
#define DS_WAIT          APER_STATUS_BASE    /*+ waiting the service   +*/
70
 
71
/*+ the level redefinition for the Total Bandwidth Server level +*/
72
typedef struct {
73
  level_des l;     /*+ the standard level descriptor          +*/
74
 
75
  /* The wcet are stored in the task descriptor's priority
76
     field, so no other fields are needed                      */
77
 
78
  int nact[MAX_PROC]; /*+ number of pending activations       +*/
79
 
80
  struct timespec lastdline; /*+ the last deadline assigned to
81
                                 a DS task                    +*/
82
 
83
  int Cs;          /*+ server capacity                        +*/
84
  int availCs;     /*+ server avail time                      +*/
85
 
86
  QQUEUE wait;      /*+ the wait queue of the DS              +*/
87
  PID activated;   /*+ the task inserted in another queue     +*/
88
 
89
  int flags;       /*+ the init flags...                      +*/
90
 
91
  bandwidth_t U;   /*+ the used bandwidth by the server       +*/
92
  int period;
93
 
94
  LEVEL scheduling_level;
95
 
96
} DS_level_des;
97
 
98
/* This static function activates the task pointed by lev->activated) */
99
static __inline__ void DS_activation(DS_level_des *lev)
100
{
101
    PID p;                     /* for readableness    */
102
    JOB_TASK_MODEL j;          /* the guest model     */
103
    LEVEL m;                   /* the master level... only for readableness*/
104
 
105
    p = lev->activated;
106
    m = lev->scheduling_level;
107
    job_task_default_model(j,lev->lastdline);
108
    job_task_def_period(j,lev->period);
109
    level_table[m]->guest_create(m,p,(TASK_MODEL *)&j);
110
    level_table[m]->guest_activate(m,p);
111
//    kern_printf("(%d %d)",lev->lastdline.tv_sec,lev->lastdline.tv_nsec);
112
}
113
 
114
static void DS_deadline_timer(void *a)
115
{
116
  DS_level_des *lev = (DS_level_des *)(level_table[(LEVEL)a]);
117
 
118
  ADDUSEC2TIMESPEC(lev->period, &lev->lastdline);
119
 
120
//  kern_printf("(%d:%d %d)",lev->lastdline.tv_sec,lev->lastdline.tv_nsec, lev->period);
121
  if (lev->availCs >= 0)
122
    lev->availCs = lev->Cs;
123
  else
124
    lev->availCs += lev->Cs;
125
 
126
  /* availCs may be <0 because a task executed via a shadow fo many time
127
     lev->activated == NIL only if the prec task was finished and there
128
     was not any other task to be put in the ready queue
129
     ... we are now activating the next task */
130
  if (lev->availCs > 0 && lev->activated == NIL) {
131
      if (qq_queryfirst(&lev->wait) != NIL) {
132
        lev->activated = qq_getfirst(&lev->wait);
133
        DS_activation(lev);
134
        event_need_reschedule();
135
      }
136
  }
137
 
138
  kern_event_post(&lev->lastdline, DS_deadline_timer, a);
139
//  kern_printf("!");
140
}
141
 
142
static char *DS_status_to_a(WORD status)
143
{
144
  if (status < MODULE_STATUS_BASE)
145
    return status_to_a(status);
146
 
147
  switch (status) {
148
    case DS_WAIT         : return "DS_Wait";
149
    default              : return "DS_Unknown";
150
  }
151
}
152
 
153
 
154
static int DS_level_accept_task_model(LEVEL l, TASK_MODEL *m)
155
{
156
  if (m->pclass == SOFT_PCLASS || m->pclass == (SOFT_PCLASS | l) ) {
157
    SOFT_TASK_MODEL *s = (SOFT_TASK_MODEL *)m;
158
 
159
    if (s->periodicity == APERIODIC)
160
      return 0;
161
  }
162
  return -1;
163
}
164
 
165
static int DS_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
166
{
167
  return -1;
168
}
169
 
170
static char *onoff(int i)
171
{
172
  if (i)
173
    return "On ";
174
  else
175
    return "Off";
176
}
177
 
178
static void DS_level_status(LEVEL l)
179
{
180
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
181
  PID p = qq_queryfirst(&lev->wait);
182
 
183
  kern_printf("On-line guarantee : %s\n",
184
            onoff(lev->flags & DS_ENABLE_GUARANTEE_EDF ||
185
                  lev->flags & DS_ENABLE_GUARANTEE_RM  ));
186
  kern_printf("Used Bandwidth    : %u/%u\n",
187
            lev->U, MAX_BANDWIDTH);
188
 
189
  if (lev->activated != -1)
190
    kern_printf("Activated: Pid: %2d Name: %10s Dl: %ld.%ld Nact: %d Stat: %s\n",
191
              lev->activated,
192
              proc_table[lev->activated].name,
193
              proc_table[lev->activated].timespec_priority.tv_sec,
194
              proc_table[lev->activated].timespec_priority.tv_nsec,
195
              lev->nact[lev->activated],
196
              DS_status_to_a(proc_table[lev->activated].status));
197
 
198
  while (p != NIL) {
199
    kern_printf("Pid: %2d Name: %10s Stat: %s\n",
200
              p,
201
              proc_table[p].name,
202
              DS_status_to_a(proc_table[p].status));
203
    p = proc_table[p].next;
204
  }
205
}
206
 
207
static PID DS_level_scheduler(LEVEL l)
208
{
209
  /* the DS don't schedule anything...
210
     it's an EDF level or similar that do it! */
211
  return NIL;
212
}
213
 
214
static PID DS_level_schedulerbackground(LEVEL l)
215
{
216
  /* the DS catch the background time to exec aperiodic activities */
217
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
218
 
219
  lev->flags |= DS_BACKGROUND;
220
 
221
  if (lev->flags & DS_BACKGROUND_BLOCK)
222
    return NIL;
223
  else
224
    return qq_queryfirst(&lev->wait);
225
}
226
 
227
/* The on-line guarantee is enabled only if the appropriate flag is set... */
228
static int DS_level_guaranteeEDF(LEVEL l, bandwidth_t *freebandwidth)
229
{
230
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
231
 
232
  if (*freebandwidth >= lev->U) {
233
    *freebandwidth -= lev->U;
234
    return 1;
235
  }
236
  else
237
    return 0;
238
}
239
 
240
static int DS_level_guaranteeRM(LEVEL l, bandwidth_t *freebandwidth)
241
{
242
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
243
 
244
  if (*freebandwidth > lev->U + RM_MINFREEBANDWIDTH) {
245
    *freebandwidth -= lev->U;
246
    return 1;
247
  }
248
  else
249
    return 0;
250
}
251
 
252
static int DS_task_create(LEVEL l, PID p, TASK_MODEL *m)
253
{
254
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
255
 
256
  /* if the DS_task_create is called, then the pclass must be a
257
     valid pclass. */
258
  SOFT_TASK_MODEL *s = (SOFT_TASK_MODEL *)m;
259
 
260
  if (s->arrivals == SAVE_ARRIVALS)
261
    lev->nact[p] = 0;
262
  else
263
    lev->nact[p] = -1;
264
 
265
  return 0; /* OK, also if the task cannot be guaranteed... */
266
}
267
 
268
static void DS_task_detach(LEVEL l, PID p)
269
{
270
  /* the DS level doesn't introduce any dinamic allocated new field. */
271
}
272
 
273
static int DS_task_eligible(LEVEL l, PID p)
274
{
275
  return 0; /* if the task p is chosen, it is always eligible */
276
}
277
 
278
#ifdef __TEST1__
279
extern int testactive;
280
extern struct timespec s_stime[];
281
extern TIME s_curr[];
282
extern TIME s_PID[];
283
extern int useds;
284
#endif
285
 
286
static void DS_task_dispatch(LEVEL l, PID p, int nostop)
287
{
288
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
289
  struct timespec ty;
290
 
291
//  if (nostop) kern_printf("NOSTOP!!!!!!!!!!!!");
292
  /* there is at least one task ready inserted in an EDF or similar
293
     level note that we can't check the status because the scheduler set it
294
     to exe before calling task_dispatch. we have to check
295
     lev->activated != p instead */
296
  if (lev->activated != p) {
297
    qq_extract(p, &lev->wait);
298
    //kern_printf("#%d#",p);
299
  }
300
  else {
301
    //if (nostop) kern_printf("(gd status=%d)",proc_table[p].status);
302
    level_table[ lev->scheduling_level ]->
303
      guest_dispatch(lev->scheduling_level,p,nostop);
304
  }
305
 
306
  /* set the capacity timer */
307
  if (!nostop) {
308
    TIMESPEC_ASSIGN(&ty, &schedule_time);
309
    ADDUSEC2TIMESPEC(lev->availCs,&ty);
310
    cap_timer = kern_event_post(&ty, capacity_timer, NULL);
311
  }
312
 
313
//  kern_printf("(disp %d %d)",ty.tv_sec, ty.tv_nsec);
314
 
315
  #ifdef __TEST1__
316
  if (testactive)
317
  {
318
    TIMESPEC_ASSIGN(&s_stime[useds], &schedule_time);
319
    s_curr[useds] = proc_table[p].avail_time;
320
    s_PID[useds]  = p;
321
    useds++;
322
  }
323
  #endif
324
}
325
 
326
static void DS_task_epilogue(LEVEL l, PID p)
327
{
328
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
329
  struct timespec ty;
330
  TIME tx;
331
 
332
  /* update the server capacity */
333
  if (lev->flags & DS_BACKGROUND)
334
    lev->flags &= ~DS_BACKGROUND;
335
  else {
336
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
337
    tx = TIMESPEC2USEC(&ty);
338
    lev->availCs -= tx;
339
  }
340
 
341
//  kern_printf("(epil %d %d)",lev->availCs, proc_table[p].avail_time);
342
 
343
  /* check if the server capacity is finished... */
344
  if (lev->availCs < 0) {
345
//    kern_printf("(epil Cs%d %d:%d act%d p%d)",
346
//              lev->availCs,proc_table[p].timespec_priority.tv_sec,
347
//              proc_table[p].timespec_priority.tv_nsec,
348
//              lev->activated,p);
349
    /* the server slice has finished... do the task_end!!!
350
       a first version of the module used the task_endcycle, but it was
351
       not conceptually correct because the task didn't stop because it
352
       finished all the work but because the server didn't have budget!
353
       So, if the task_endcycle is called, the task remain into the
354
       master level, and we can't wake him up if, for example, another
355
       task point the shadow to it!!!*/
356
    if (lev->activated == p)
357
      level_table[ lev->scheduling_level ]->
358
        guest_end(lev->scheduling_level,p);
359
    qq_insertfirst(p, &lev->wait);
360
    proc_table[p].status = DS_WAIT;
361
    lev->activated = NIL;
362
  }
363
  else
364
    /* the task has been preempted. it returns into the ready queue or to the
365
       wait queue by calling the guest_epilogue... */
366
    if (lev->activated == p) {//kern_printf("Û1");
367
      level_table[ lev->scheduling_level ]->
368
        guest_epilogue(lev->scheduling_level,p);
369
    } else { //kern_printf("Û2");
370
      qq_insertfirst(p, &lev->wait);
371
      proc_table[p].status = DS_WAIT;
372
    }
373
}
374
 
375
static void DS_task_activate(LEVEL l, PID p)
376
{
377
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
378
 
379
  if (lev->activated == p || proc_table[p].status == DS_WAIT) {
380
    if (lev->nact[p] != -1)
381
      lev->nact[p]++;
382
  }
383
  else if (proc_table[p].status == SLEEP) {
384
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
385
 
386
    if (lev->activated == NIL && lev->availCs > 0) {
387
      lev->activated = p;
388
      DS_activation(lev);
389
    }
390
    else {
391
      qq_insertlast(p, &lev->wait);
392
      proc_table[p].status = DS_WAIT;
393
    }
394
  }
395
  else
396
  {  kern_printf("DS_REJ%d %d %d %d ",p, proc_table[p].status, lev->activated, lev->wait.first);
397
     return; }
398
 
399
}
400
 
401
static void DS_task_insert(LEVEL l, PID p)
402
{
403
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
404
 
405
  lev->flags &= ~DS_BACKGROUND_BLOCK;
406
 
407
  lev->activated = -1;
408
 
409
  /* when we reinsert the task into the system, the server capacity
410
     is always 0 because nobody executes with the DS before... */
411
  qq_insertfirst(p, &lev->wait);
412
  proc_table[p].status = DS_WAIT;
413
}
414
 
415
static void DS_task_extract(LEVEL l, PID p)
416
{
417
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
418
 
419
  /* update the server capacity */
420
  lev->availCs = 0;
421
 
422
  lev->flags |= DS_BACKGROUND_BLOCK;
423
 
424
  if (lev->activated == p)
425
    level_table[ lev->scheduling_level ]->
426
      guest_end(lev->scheduling_level,p);
427
}
428
 
429
static void DS_task_endcycle(LEVEL l, PID p)
430
{
431
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
432
  struct timespec ty;
433
  TIME tx;
434
 
435
  /* update the server capacity */
436
  if (lev->flags & DS_BACKGROUND)
437
    lev->flags &= ~DS_BACKGROUND;
438
  else {
439
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
440
    tx = TIMESPEC2USEC(&ty);
441
    lev->availCs -= tx;
442
  }
443
 
444
  if (lev->activated == p)
445
    level_table[ lev->scheduling_level ]->
446
      guest_end(lev->scheduling_level,p);
447
  else
448
    qq_extract(p, &lev->wait);
449
 
450
  if (lev->nact[p] > 0)
451
  {
452
    lev->nact[p]--;
453
    qq_insertlast(p, &lev->wait);
454
    proc_table[p].status = DS_WAIT;
455
  }
456
  else
457
    proc_table[p].status = SLEEP;
458
 
459
  lev->activated = qq_getfirst(&lev->wait);
460
  if (lev->activated != NIL)
461
    DS_activation(lev);
462
}
463
 
464
static void DS_task_end(LEVEL l, PID p)
465
{
466
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
467
  struct timespec ty;
468
  TIME tx;
469
 
470
  /* update the server capacity */
471
  if (lev->flags & DS_BACKGROUND)
472
    lev->flags &= ~DS_BACKGROUND;
473
  else {
474
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
475
    tx = TIMESPEC2USEC(&ty);
476
    lev->availCs -= tx;
477
  }
478
 
479
  if (lev->activated == p)
480
    level_table[ lev->scheduling_level ]->
481
      guest_end(lev->scheduling_level,p);
482
 
483
  proc_table[p].status = FREE;
484
  q_insertfirst(p,&freedesc);
485
 
486
  lev->activated = qq_getfirst(&lev->wait);
487
  if (lev->activated != NIL)
488
    DS_activation(lev);
489
}
490
 
491
static void DS_task_sleep(LEVEL l, PID p)
492
{
493
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
494
  struct timespec ty;
495
  TIME tx;
496
 
497
  /* update the server capacity */
498
  if (lev->flags & DS_BACKGROUND)
499
    lev->flags &= ~DS_BACKGROUND;
500
  else {
501
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
502
    tx = TIMESPEC2USEC(&ty);
503
    lev->availCs -= tx;
504
  }
505
 
506
  if (lev->nact[p] >= 0) lev->nact[p] = 0;
507
 
508
  if (lev->activated == p)
509
    level_table[ lev->scheduling_level ]->
510
      guest_end(lev->scheduling_level,p);
511
  else
512
    qq_extract(p, &lev->wait);
513
 
514
  proc_table[p].status = SLEEP;
515
 
516
  lev->activated = qq_getfirst(&lev->wait);
517
  if (lev->activated != NIL)
518
    DS_activation(lev);
519
}
520
static void DS_task_delay(LEVEL l, PID p, TIME usdelay)
521
{
522
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
523
  struct timespec ty;
524
  TIME tx;
525
 
526
  /* update the server capacity */
527
  if (lev->flags & DS_BACKGROUND)
528
    lev->flags &= ~DS_BACKGROUND;
529
  else {
530
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
531
    tx = TIMESPEC2USEC(&ty);
532
    lev->availCs -= tx;
533
  }
534
 
535
  /* I hope no delay when owning a mutex... */
536
  if (lev->activated == p)
537
    level_table[ lev->scheduling_level ]->
538
      guest_delay(lev->scheduling_level,p,usdelay);
539
}
540
 
541
 
542
static int DS_guest_create(LEVEL l, PID p, TASK_MODEL *m)
14 pj 543
{ kern_raise(XINVALID_GUEST,exec_shadow); return 0; }
2 pj 544
 
545
static void DS_guest_detach(LEVEL l, PID p)
14 pj 546
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 547
 
548
static void DS_guest_dispatch(LEVEL l, PID p, int nostop)
14 pj 549
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 550
 
551
static void DS_guest_epilogue(LEVEL l, PID p)
14 pj 552
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 553
 
554
static void DS_guest_activate(LEVEL l, PID p)
14 pj 555
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 556
 
557
static void DS_guest_insert(LEVEL l, PID p)
14 pj 558
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 559
 
560
static void DS_guest_extract(LEVEL l, PID p)
14 pj 561
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 562
 
563
static void DS_guest_endcycle(LEVEL l, PID p)
14 pj 564
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 565
 
566
static void DS_guest_end(LEVEL l, PID p)
14 pj 567
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 568
 
569
static void DS_guest_sleep(LEVEL l, PID p)
14 pj 570
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 571
 
572
static void DS_guest_delay(LEVEL l, PID p,DWORD tickdelay)
14 pj 573
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 574
 
575
 
576
 
577
 
578
/* Registration functions */
579
 
580
 
581
/*+ This init function install the DS deadline timer
582
    +*/
583
static void DS_dline_install(void *l)
584
{
585
  DS_level_des *lev = (DS_level_des *)(level_table[(LEVEL)l]);
586
 
587
  ll_gettime(TIME_EXACT,&lev->lastdline);
588
  ADDUSEC2TIMESPEC(lev->period, &lev->lastdline);
589
 
590
  kern_event_post(&lev->lastdline, DS_deadline_timer, l);
591
}
592
 
593
 
594
 
595
/*+ Registration function:
596
    int flags                 the init flags ... see DS.h +*/
597
void DS_register_level(int flags, LEVEL master, int Cs, int per)
598
{
599
  LEVEL l;            /* the level that we register */
600
  DS_level_des *lev;  /* for readableness only */
601
  PID i;              /* a counter */
602
 
603
  printk("DS_register_level\n");
604
 
605
  /* request an entry in the level_table */
606
  l = level_alloc_descriptor();
607
 
608
  printk("    alloco descrittore %d %d\n",l,(int)sizeof(DS_level_des));
609
 
610
  /* alloc the space needed for the DS_level_des */
611
  lev = (DS_level_des *)kern_alloc(sizeof(DS_level_des));
612
 
613
  printk("    lev=%d\n",(int)lev);
614
 
615
  /* update the level_table with the new entry */
616
  level_table[l] = (level_des *)lev;
617
 
618
  /* fill the standard descriptor */
619
  strncpy(lev->l.level_name,  DS_LEVELNAME, MAX_LEVELNAME);
620
  lev->l.level_code               = DS_LEVEL_CODE;
621
  lev->l.level_version            = DS_LEVEL_VERSION;
622
 
623
  lev->l.level_accept_task_model  = DS_level_accept_task_model;
624
  lev->l.level_accept_guest_model = DS_level_accept_guest_model;
625
  lev->l.level_status             = DS_level_status;
626
 
627
  if (flags & DS_ENABLE_BACKGROUND)
628
    lev->l.level_scheduler          = DS_level_schedulerbackground;
629
  else
630
    lev->l.level_scheduler          = DS_level_scheduler;
631
 
632
  if (flags & DS_ENABLE_GUARANTEE_EDF)
633
    lev->l.level_guarantee        = DS_level_guaranteeEDF;
634
  else if (flags & DS_ENABLE_GUARANTEE_RM)
635
    lev->l.level_guarantee        = DS_level_guaranteeRM;
636
  else
637
    lev->l.level_guarantee        = NULL;
638
 
639
  lev->l.task_create              = DS_task_create;
640
  lev->l.task_detach              = DS_task_detach;
641
  lev->l.task_eligible            = DS_task_eligible;
642
  lev->l.task_dispatch            = DS_task_dispatch;
643
  lev->l.task_epilogue            = DS_task_epilogue;
644
  lev->l.task_activate            = DS_task_activate;
645
  lev->l.task_insert              = DS_task_insert;
646
  lev->l.task_extract             = DS_task_extract;
647
  lev->l.task_endcycle            = DS_task_endcycle;
648
  lev->l.task_end                 = DS_task_end;
649
  lev->l.task_sleep               = DS_task_sleep;
650
  lev->l.task_delay               = DS_task_delay;
651
 
652
  lev->l.guest_create             = DS_guest_create;
653
  lev->l.guest_detach             = DS_guest_detach;
654
  lev->l.guest_dispatch           = DS_guest_dispatch;
655
  lev->l.guest_epilogue           = DS_guest_epilogue;
656
  lev->l.guest_activate           = DS_guest_activate;
657
  lev->l.guest_insert             = DS_guest_insert;
658
  lev->l.guest_extract            = DS_guest_extract;
659
  lev->l.guest_endcycle           = DS_guest_endcycle;
660
  lev->l.guest_end                = DS_guest_end;
661
  lev->l.guest_sleep              = DS_guest_sleep;
662
  lev->l.guest_delay              = DS_guest_delay;
663
 
664
  /* fill the DS descriptor part */
665
 
666
  for (i=0; i<MAX_PROC; i++)
667
     lev->nact[i] = -1;
668
 
669
  lev->Cs = Cs;
670
  lev->availCs = 0;
671
 
672
  lev->period = per;
673
 
674
  qq_init(&lev->wait);
675
  lev->activated = NIL;
676
 
677
  lev->U = (MAX_BANDWIDTH / per) * Cs;
678
 
679
  lev->scheduling_level = master;
680
 
681
  lev->flags = flags & 0x07;
682
 
683
  sys_atrunlevel(DS_dline_install,(void *) l, RUNLEVEL_INIT);
684
}
685
 
686
bandwidth_t DS_usedbandwidth(LEVEL l)
687
{
688
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
689
  if (lev->l.level_code    == DS_LEVEL_CODE &&
690
      lev->l.level_version == DS_LEVEL_VERSION)
691
    return lev->U;
692
  else
693
    return 0;
694
}
695