Subversion Repositories shark

Rev

Rev 14 | Rev 38 | 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
 *   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
 ------------
29 pj 23
 CVS :        $Id: ds.c,v 1.3 2002-11-11 08:32:06 pj Exp $
2 pj 24
 
25
 File:        $File$
29 pj 26
 Revision:    $Revision: 1.3 $
27
 Last update: $Date: 2002-11-11 08:32:06 $
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
 
29 pj 86
  IQUEUE wait;      /*+ the wait queue of the DS              +*/
2 pj 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) {
29 pj 131
      if (iq_query_first(&lev->wait) != NIL) {
132
        lev->activated = iq_getfirst(&lev->wait);
2 pj 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]);
29 pj 181
  PID p = iq_query_first(&lev->wait);
2 pj 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,
29 pj 193
              iq_query_timespec(lev->activated,&lev->wait)->tv_sec,
194
              iq_query_timespec(lev->activated,&lev->wait)->tv_nsec,
2 pj 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));
29 pj 203
    p = iq_query_next(p, &lev->wait);
2 pj 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
29 pj 224
    return iq_query_first(&lev->wait);
2 pj 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
static void DS_task_dispatch(LEVEL l, PID p, int nostop)
279
{
280
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
281
  struct timespec ty;
282
 
283
//  if (nostop) kern_printf("NOSTOP!!!!!!!!!!!!");
284
  /* there is at least one task ready inserted in an EDF or similar
285
     level note that we can't check the status because the scheduler set it
286
     to exe before calling task_dispatch. we have to check
287
     lev->activated != p instead */
288
  if (lev->activated != p) {
29 pj 289
    iq_extract(p, &lev->wait);
2 pj 290
    //kern_printf("#%d#",p);
291
  }
292
  else {
293
    //if (nostop) kern_printf("(gd status=%d)",proc_table[p].status);
294
    level_table[ lev->scheduling_level ]->
295
      guest_dispatch(lev->scheduling_level,p,nostop);
296
  }
297
 
298
  /* set the capacity timer */
299
  if (!nostop) {
300
    TIMESPEC_ASSIGN(&ty, &schedule_time);
301
    ADDUSEC2TIMESPEC(lev->availCs,&ty);
302
    cap_timer = kern_event_post(&ty, capacity_timer, NULL);
303
  }
304
 
305
//  kern_printf("(disp %d %d)",ty.tv_sec, ty.tv_nsec);
306
}
307
 
308
static void DS_task_epilogue(LEVEL l, PID p)
309
{
310
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
311
  struct timespec ty;
312
  TIME tx;
313
 
314
  /* update the server capacity */
315
  if (lev->flags & DS_BACKGROUND)
316
    lev->flags &= ~DS_BACKGROUND;
317
  else {
318
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
319
    tx = TIMESPEC2USEC(&ty);
320
    lev->availCs -= tx;
321
  }
322
 
323
//  kern_printf("(epil %d %d)",lev->availCs, proc_table[p].avail_time);
324
 
325
  /* check if the server capacity is finished... */
326
  if (lev->availCs < 0) {
327
//    kern_printf("(epil Cs%d %d:%d act%d p%d)",
328
//              lev->availCs,proc_table[p].timespec_priority.tv_sec,
329
//              proc_table[p].timespec_priority.tv_nsec,
330
//              lev->activated,p);
331
    /* the server slice has finished... do the task_end!!!
332
       a first version of the module used the task_endcycle, but it was
333
       not conceptually correct because the task didn't stop because it
334
       finished all the work but because the server didn't have budget!
335
       So, if the task_endcycle is called, the task remain into the
336
       master level, and we can't wake him up if, for example, another
337
       task point the shadow to it!!!*/
338
    if (lev->activated == p)
339
      level_table[ lev->scheduling_level ]->
340
        guest_end(lev->scheduling_level,p);
29 pj 341
    iq_insertfirst(p, &lev->wait);
2 pj 342
    proc_table[p].status = DS_WAIT;
343
    lev->activated = NIL;
344
  }
345
  else
346
    /* the task has been preempted. it returns into the ready queue or to the
347
       wait queue by calling the guest_epilogue... */
348
    if (lev->activated == p) {//kern_printf("Û1");
349
      level_table[ lev->scheduling_level ]->
350
        guest_epilogue(lev->scheduling_level,p);
351
    } else { //kern_printf("Û2");
29 pj 352
      iq_insertfirst(p, &lev->wait);
2 pj 353
      proc_table[p].status = DS_WAIT;
354
    }
355
}
356
 
357
static void DS_task_activate(LEVEL l, PID p)
358
{
359
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
360
 
361
  if (lev->activated == p || proc_table[p].status == DS_WAIT) {
362
    if (lev->nact[p] != -1)
363
      lev->nact[p]++;
364
  }
365
  else if (proc_table[p].status == SLEEP) {
366
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
367
 
368
    if (lev->activated == NIL && lev->availCs > 0) {
369
      lev->activated = p;
370
      DS_activation(lev);
371
    }
372
    else {
29 pj 373
      iq_insertlast(p, &lev->wait);
2 pj 374
      proc_table[p].status = DS_WAIT;
375
    }
376
  }
377
  else
378
  {  kern_printf("DS_REJ%d %d %d %d ",p, proc_table[p].status, lev->activated, lev->wait.first);
379
     return; }
380
 
381
}
382
 
383
static void DS_task_insert(LEVEL l, PID p)
384
{
385
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
386
 
387
  lev->flags &= ~DS_BACKGROUND_BLOCK;
388
 
389
  lev->activated = -1;
390
 
391
  /* when we reinsert the task into the system, the server capacity
392
     is always 0 because nobody executes with the DS before... */
29 pj 393
  iq_insertfirst(p, &lev->wait);
2 pj 394
  proc_table[p].status = DS_WAIT;
395
}
396
 
397
static void DS_task_extract(LEVEL l, PID p)
398
{
399
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
400
 
401
  /* update the server capacity */
402
  lev->availCs = 0;
403
 
404
  lev->flags |= DS_BACKGROUND_BLOCK;
405
 
406
  if (lev->activated == p)
407
    level_table[ lev->scheduling_level ]->
408
      guest_end(lev->scheduling_level,p);
409
}
410
 
411
static void DS_task_endcycle(LEVEL l, PID p)
412
{
413
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
414
  struct timespec ty;
415
  TIME tx;
416
 
417
  /* update the server capacity */
418
  if (lev->flags & DS_BACKGROUND)
419
    lev->flags &= ~DS_BACKGROUND;
420
  else {
421
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
422
    tx = TIMESPEC2USEC(&ty);
423
    lev->availCs -= tx;
424
  }
425
 
426
  if (lev->activated == p)
427
    level_table[ lev->scheduling_level ]->
428
      guest_end(lev->scheduling_level,p);
429
  else
29 pj 430
    iq_extract(p, &lev->wait);
2 pj 431
 
432
  if (lev->nact[p] > 0)
433
  {
434
    lev->nact[p]--;
29 pj 435
    iq_insertlast(p, &lev->wait);
2 pj 436
    proc_table[p].status = DS_WAIT;
437
  }
438
  else
439
    proc_table[p].status = SLEEP;
440
 
29 pj 441
  lev->activated = iq_getfirst(&lev->wait);
2 pj 442
  if (lev->activated != NIL)
443
    DS_activation(lev);
444
}
445
 
446
static void DS_task_end(LEVEL l, PID p)
447
{
448
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
449
  struct timespec ty;
450
  TIME tx;
451
 
452
  /* update the server capacity */
453
  if (lev->flags & DS_BACKGROUND)
454
    lev->flags &= ~DS_BACKGROUND;
455
  else {
456
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
457
    tx = TIMESPEC2USEC(&ty);
458
    lev->availCs -= tx;
459
  }
460
 
461
  if (lev->activated == p)
462
    level_table[ lev->scheduling_level ]->
463
      guest_end(lev->scheduling_level,p);
464
 
465
  proc_table[p].status = FREE;
29 pj 466
  iq_insertfirst(p,&freedesc);
2 pj 467
 
29 pj 468
  lev->activated = iq_getfirst(&lev->wait);
2 pj 469
  if (lev->activated != NIL)
470
    DS_activation(lev);
471
}
472
 
473
static void DS_task_sleep(LEVEL l, PID p)
474
{
475
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
476
  struct timespec ty;
477
  TIME tx;
478
 
479
  /* update the server capacity */
480
  if (lev->flags & DS_BACKGROUND)
481
    lev->flags &= ~DS_BACKGROUND;
482
  else {
483
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
484
    tx = TIMESPEC2USEC(&ty);
485
    lev->availCs -= tx;
486
  }
487
 
488
  if (lev->nact[p] >= 0) lev->nact[p] = 0;
489
 
490
  if (lev->activated == p)
491
    level_table[ lev->scheduling_level ]->
492
      guest_end(lev->scheduling_level,p);
493
  else
29 pj 494
    iq_extract(p, &lev->wait);
2 pj 495
 
496
  proc_table[p].status = SLEEP;
497
 
29 pj 498
  lev->activated = iq_getfirst(&lev->wait);
2 pj 499
  if (lev->activated != NIL)
500
    DS_activation(lev);
501
}
502
 
503
 
504
static int DS_guest_create(LEVEL l, PID p, TASK_MODEL *m)
14 pj 505
{ kern_raise(XINVALID_GUEST,exec_shadow); return 0; }
2 pj 506
 
507
static void DS_guest_detach(LEVEL l, PID p)
14 pj 508
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 509
 
510
static void DS_guest_dispatch(LEVEL l, PID p, int nostop)
14 pj 511
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 512
 
513
static void DS_guest_epilogue(LEVEL l, PID p)
14 pj 514
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 515
 
516
static void DS_guest_activate(LEVEL l, PID p)
14 pj 517
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 518
 
519
static void DS_guest_insert(LEVEL l, PID p)
14 pj 520
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 521
 
522
static void DS_guest_extract(LEVEL l, PID p)
14 pj 523
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 524
 
525
static void DS_guest_endcycle(LEVEL l, PID p)
14 pj 526
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 527
 
528
static void DS_guest_end(LEVEL l, PID p)
14 pj 529
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 530
 
531
static void DS_guest_sleep(LEVEL l, PID p)
14 pj 532
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 533
 
534
 
535
 
536
 
537
/* Registration functions */
538
 
539
 
540
/*+ This init function install the DS deadline timer
541
    +*/
542
static void DS_dline_install(void *l)
543
{
544
  DS_level_des *lev = (DS_level_des *)(level_table[(LEVEL)l]);
545
 
546
  ll_gettime(TIME_EXACT,&lev->lastdline);
547
  ADDUSEC2TIMESPEC(lev->period, &lev->lastdline);
548
 
549
  kern_event_post(&lev->lastdline, DS_deadline_timer, l);
550
}
551
 
552
 
553
 
554
/*+ Registration function:
555
    int flags                 the init flags ... see DS.h +*/
556
void DS_register_level(int flags, LEVEL master, int Cs, int per)
557
{
558
  LEVEL l;            /* the level that we register */
559
  DS_level_des *lev;  /* for readableness only */
560
  PID i;              /* a counter */
561
 
562
  printk("DS_register_level\n");
563
 
564
  /* request an entry in the level_table */
565
  l = level_alloc_descriptor();
566
 
567
  printk("    alloco descrittore %d %d\n",l,(int)sizeof(DS_level_des));
568
 
569
  /* alloc the space needed for the DS_level_des */
570
  lev = (DS_level_des *)kern_alloc(sizeof(DS_level_des));
571
 
572
  printk("    lev=%d\n",(int)lev);
573
 
574
  /* update the level_table with the new entry */
575
  level_table[l] = (level_des *)lev;
576
 
577
  /* fill the standard descriptor */
578
  strncpy(lev->l.level_name,  DS_LEVELNAME, MAX_LEVELNAME);
579
  lev->l.level_code               = DS_LEVEL_CODE;
580
  lev->l.level_version            = DS_LEVEL_VERSION;
581
 
582
  lev->l.level_accept_task_model  = DS_level_accept_task_model;
583
  lev->l.level_accept_guest_model = DS_level_accept_guest_model;
584
  lev->l.level_status             = DS_level_status;
585
 
586
  if (flags & DS_ENABLE_BACKGROUND)
587
    lev->l.level_scheduler          = DS_level_schedulerbackground;
588
  else
589
    lev->l.level_scheduler          = DS_level_scheduler;
590
 
591
  if (flags & DS_ENABLE_GUARANTEE_EDF)
592
    lev->l.level_guarantee        = DS_level_guaranteeEDF;
593
  else if (flags & DS_ENABLE_GUARANTEE_RM)
594
    lev->l.level_guarantee        = DS_level_guaranteeRM;
595
  else
596
    lev->l.level_guarantee        = NULL;
597
 
598
  lev->l.task_create              = DS_task_create;
599
  lev->l.task_detach              = DS_task_detach;
600
  lev->l.task_eligible            = DS_task_eligible;
601
  lev->l.task_dispatch            = DS_task_dispatch;
602
  lev->l.task_epilogue            = DS_task_epilogue;
603
  lev->l.task_activate            = DS_task_activate;
604
  lev->l.task_insert              = DS_task_insert;
605
  lev->l.task_extract             = DS_task_extract;
606
  lev->l.task_endcycle            = DS_task_endcycle;
607
  lev->l.task_end                 = DS_task_end;
608
  lev->l.task_sleep               = DS_task_sleep;
609
 
610
  lev->l.guest_create             = DS_guest_create;
611
  lev->l.guest_detach             = DS_guest_detach;
612
  lev->l.guest_dispatch           = DS_guest_dispatch;
613
  lev->l.guest_epilogue           = DS_guest_epilogue;
614
  lev->l.guest_activate           = DS_guest_activate;
615
  lev->l.guest_insert             = DS_guest_insert;
616
  lev->l.guest_extract            = DS_guest_extract;
617
  lev->l.guest_endcycle           = DS_guest_endcycle;
618
  lev->l.guest_end                = DS_guest_end;
619
  lev->l.guest_sleep              = DS_guest_sleep;
620
 
621
  /* fill the DS descriptor part */
622
 
623
  for (i=0; i<MAX_PROC; i++)
624
     lev->nact[i] = -1;
625
 
626
  lev->Cs = Cs;
627
  lev->availCs = 0;
628
 
629
  lev->period = per;
630
 
29 pj 631
  iq_init(&lev->wait, &freedesc, 0);
2 pj 632
  lev->activated = NIL;
633
 
634
  lev->U = (MAX_BANDWIDTH / per) * Cs;
635
 
636
  lev->scheduling_level = master;
637
 
638
  lev->flags = flags & 0x07;
639
 
640
  sys_atrunlevel(DS_dline_install,(void *) l, RUNLEVEL_INIT);
641
}
642
 
643
bandwidth_t DS_usedbandwidth(LEVEL l)
644
{
645
  DS_level_des *lev = (DS_level_des *)(level_table[l]);
646
  if (lev->l.level_code    == DS_LEVEL_CODE &&
647
      lev->l.level_version == DS_LEVEL_VERSION)
648
    return lev->U;
649
  else
650
    return 0;
651
}
652