Subversion Repositories shark

Rev

Rev 212 | 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
 ------------
214 giacomo 23
 CVS :        $Id: cbs.c,v 1.7 2003-07-24 12:24:51 giacomo Exp $
2 pj 24
 
25
 File:        $File$
214 giacomo 26
 Revision:    $Revision: 1.7 $
27
 Last update: $Date: 2003-07-24 12:24:51 $
2 pj 28
 ------------
29
 
30
 This file contains the aperiodic server CBS (Total Bandwidth Server)
31
 
32
 Read CBS.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 WARRANTY; without even the implied warranty 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/cbs.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
#include <kernel/trace.h>
64
 
65
/*+ 4 debug purposes +*/
66
#undef CBS_TEST
67
#undef CBS_COUNTER
68
 
69
#ifdef TESTG
70
#include "drivers/glib.h"
71
TIME x,oldx;
72
extern TIME starttime;
73
#endif
74
 
75
 
76
/*+ Status used in the level +*/
77
#define CBS_IDLE          APER_STATUS_BASE   /*+ waiting the activation +*/
78
#define CBS_ZOMBIE        APER_STATUS_BASE+1 /*+ waiting the period end +*/
79
 
80
/*+ task flags +*/
81
#define CBS_SAVE_ARRIVALS 1
82
#define CBS_APERIODIC     2
212 giacomo 83
#define CBS_SLEEP         4
2 pj 84
 
85
/*+ the level redefinition for the Total Bandwidth Server level +*/
86
typedef struct {
87
  level_des l;     /*+ the standard level descriptor          +*/
88
 
89
  /* The wcet are stored in the task descriptor, but we need
90
     an array for the deadlines. We can't use the timespec_priority
91
     field because it is used by the master level!!!...
92
     Notice that however the use of the timespec_priority field
93
     does not cause any problem...                     */
94
 
95
  struct timespec cbs_dline[MAX_PROC]; /*+ CBS deadlines      +*/
96
 
97
  TIME period[MAX_PROC]; /*+ CBS activation period            +*/
98
 
99
  struct timespec reactivation_time[MAX_PROC];
100
        /*+ the time at witch  the reactivation timer is post +*/
101
  int reactivation_timer[MAX_PROC];
102
                                   /*+ the recativation timer +*/
103
 
104
  int nact[MAX_PROC]; /*+ number of pending activations       +*/
105
 
106
  BYTE flag[MAX_PROC]; /*+ task flags                         +*/
107
 
108
  int flags;       /*+ the init flags...                      +*/
109
 
110
  bandwidth_t U;   /*+ the used bandwidth by the server       +*/
111
 
112
  LEVEL scheduling_level;
113
 
114
} CBS_level_des;
115
 
116
#ifdef CBS_COUNTER
117
int cbs_counter=0;
118
int cbs_counter2=0;
119
#endif
120
 
121
 
122
static void CBS_activation(CBS_level_des *lev,
123
                           PID p,
124
                           struct timespec *acttime)
125
{
126
  JOB_TASK_MODEL job;
127
 
128
  /* we have to check if the deadline and the wcet are correct before
129
     activating a new task or an old task... */
130
 
131
  /* check 1: if the deadline is before than the actual scheduling time */
132
 
133
  /* check 2: if ( avail_time >= (cbs_dline - acttime)* (wcet/period) )
134
     (rule 7 in the CBS article!) */
135
  TIME t;
136
  struct timespec t2,t3;
137
 
138
  t = (lev->period[p] * proc_table[p].avail_time) / proc_table[p].wcet;
139
  t3.tv_sec = t / 1000000;
140
  t3.tv_nsec = (t % 1000000) * 1000;
141
 
142
  SUBTIMESPEC(&lev->cbs_dline[p], acttime, &t2);
143
 
144
  if (/* 1 */ TIMESPEC_A_LT_B(&lev->cbs_dline[p], acttime) ||
145
      /* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
146
/*    if (TIMESPEC_A_LT_B(&lev->cbs_dline[p], acttime) )
147
      kern_printf("$");
148
    else
212 giacomo 149
      kern_printf("(Ûdline%d.%d act%d.%d wcet%d per%d avail%dÛ)",
2 pj 150
                  lev->cbs_dline[p].tv_sec,lev->cbs_dline[p].tv_nsec/1000,
151
                  acttime->tv_sec, acttime->tv_nsec/1000,
152
                  proc_table[p].wcet, lev->period[p], proc_table[p].avail_time);
153
*/  /* we modify the deadline ... */
154
    TIMESPEC_ASSIGN(&lev->cbs_dline[p], acttime);
155
    ADDUSEC2TIMESPEC(lev->period[p], &lev->cbs_dline[p]);
156
 
157
    /* and the capacity */
158
    proc_table[p].avail_time = proc_table[p].wcet;
159
  }
160
 
161
#ifdef TESTG
162
      if (starttime && p == 3) {
163
      oldx = x;
164
      x = ((lev->cbs_dline[p].tv_sec*1000000+lev->cbs_dline[p].tv_nsec/1000)/5000 - starttime) + 20;
165
//      kern_printf("(a%d)",lev->cbs_dline[p].tv_sec*1000000+lev->cbs_dline[p].tv_nsec/1000);
166
      if (oldx > x) sys_end();
167
      if (x<640)
168
        grx_plot(x, 15, 8);
169
      }
170
#endif
171
 
172
  /* and, finally, we reinsert the task in the master level */
173
  job_task_default_model(job, lev->cbs_dline[p]);
174
  job_task_def_noexc(job);
175
  level_table[ lev->scheduling_level ]->
38 pj 176
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
2 pj 177
}
178
 
179
static void CBS_avail_time_check(CBS_level_des *lev, PID p)
180
{
181
  /* there is a while because if the wcet is << than the system tick
182
     we need to postpone the deadline many times */
183
  while (proc_table[p].avail_time <= 0) {
184
    ADDUSEC2TIMESPEC(lev->period[p], &lev->cbs_dline[p]);
185
    proc_table[p].avail_time += proc_table[p].wcet;
186
 
187
#ifdef TESTG
188
    if (starttime && p == 3) {
189
    oldx = x;
190
    x = ((lev->cbs_dline[p].tv_sec*1000000+lev->cbs_dline[p].tv_nsec/1000)/5000 - starttime) + 20;
191
//      kern_printf("(e%d avail%d)",lev->cbs_dline[p].tv_sec*1000000+lev->cbs_dline[p].tv_nsec/1000,proc_table[p].avail_time);
192
    if (oldx > x) sys_end();
193
    if (x<640)
194
      grx_plot(x, 15, 2);
195
    }
196
#endif
197
  }
198
}
199
 
200
 
201
/* this is the periodic reactivation of the task... it is posted only
202
   if the task is a periodic task */
203
static void CBS_timer_reactivate(void *par)
204
{
205
  PID p = (PID) par;
206
  CBS_level_des *lev;
207
 
208
  lev = (CBS_level_des *)level_table[proc_table[p].task_level];
209
 
210
  #ifdef CBS_COUNTER
211
    if (p==5) cbs_counter++;
212
  #endif
213
 
212 giacomo 214
  if (lev->flag[p] & CBS_SLEEP && proc_table[p].status == CBS_IDLE) {
215
    proc_table[p].status = SLEEP;
216
    proc_table[p].avail_time = proc_table[p].wcet;
217
    NULL_TIMESPEC(&lev->cbs_dline[p]);
218
    return;
219
  }
220
 
2 pj 221
  if (proc_table[p].status == CBS_IDLE) {
222
    /* the task has finished the current activation and must be
223
       reactivated */
224
    CBS_activation(lev,p,&lev->reactivation_time[p]);
225
 
226
    event_need_reschedule();
227
  }
228
  else if (lev->flag[p] & CBS_SAVE_ARRIVALS)
229
    /* the task has not completed the current activation, so we save
230
       the activation incrementing nact... */
231
    lev->nact[p]++;
232
 
233
  /* repost the event at the next period end... */
234
  ADDUSEC2TIMESPEC(lev->period[p], &lev->reactivation_time[p]);
235
  lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
236
                                               CBS_timer_reactivate,
237
                                               (void *)p);
238
  #ifdef CBS_COUNTER
239
    if (p==5) cbs_counter2++;
240
  #endif
241
  /* tracer stuff */
242
  trc_logevent(TRC_INTACTIVATION,&p);
243
 
244
}
245
 
246
/*+ this function is called when a killed or ended task reach the
247
    period end +*/
248
static void CBS_timer_zombie(void *par)
249
{
250
  PID p = (PID) par;
251
  CBS_level_des *lev;
252
 
253
  lev = (CBS_level_des *)level_table[proc_table[p].task_level];
254
 
255
  /* we finally put the task in the ready queue */
256
  proc_table[p].status = FREE;
29 pj 257
  iq_insertfirst(p,&freedesc);
2 pj 258
 
259
  /* and free the allocated bandwidth */
260
  lev->U -= (MAX_BANDWIDTH/lev->period[p]) * proc_table[p].wcet;
261
 
262
}
263
 
264
 
265
/* The on-line guarantee is enabled only if the appropriate flag is set... */
38 pj 266
static int CBS_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
2 pj 267
{
268
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
269
 
159 pj 270
  if (*freebandwidth >= lev->U) {
271
    *freebandwidth -= lev->U;
272
    return 1;
2 pj 273
  }
274
  else
159 pj 275
    return 0;
2 pj 276
}
277
 
38 pj 278
static int CBS_public_create(LEVEL l, PID p, TASK_MODEL *m)
2 pj 279
{
280
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
38 pj 281
  SOFT_TASK_MODEL *soft;
2 pj 282
 
38 pj 283
  if (m->pclass != SOFT_PCLASS) return -1;
284
  if (m->level != 0 && m->level != l) return -1;
285
  soft = (SOFT_TASK_MODEL *)m;
286
  if (!(soft->met && soft->period)) return -1;
2 pj 287
 
38 pj 288
  soft = (SOFT_TASK_MODEL *)m;
289
 
159 pj 290
  if (lev->flags & CBS_ENABLE_GUARANTEE) {
291
    bandwidth_t b;
292
    b = (MAX_BANDWIDTH / soft->period) * soft->met;
293
 
294
    /* really update lev->U, checking an overflow... */
295
    if (MAX_BANDWIDTH - lev->U > b)
296
      lev->U += b;
297
    else
298
      return -1;
299
  }
300
 
2 pj 301
  /* Enable wcet check */
302
  proc_table[p].avail_time = soft->met;
303
  proc_table[p].wcet       = soft->met;
304
  proc_table[p].control   |= CONTROL_CAP;
305
 
306
  lev->nact[p] = 0;
307
  lev->period[p] = soft->period;
308
  NULL_TIMESPEC(&lev->cbs_dline[p]);
309
 
310
  if (soft->periodicity == APERIODIC)
311
    lev->flag[p] = CBS_APERIODIC;
312
  else
313
    lev->flag[p] = 0;
314
 
315
  if (soft->arrivals == SAVE_ARRIVALS)
316
    lev->flag[p] |= CBS_SAVE_ARRIVALS;
317
 
318
  return 0; /* OK, also if the task cannot be guaranteed... */
319
}
320
 
38 pj 321
static void CBS_public_detach(LEVEL l, PID p)
2 pj 322
{
323
  /* the CBS level doesn't introduce any dinamic allocated new field.
159 pj 324
     we have only to decrement the allocated bandwidth */
2 pj 325
 
326
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
327
 
159 pj 328
  if (lev->flags & CBS_ENABLE_GUARANTEE) {
2 pj 329
    lev->U -= (MAX_BANDWIDTH / lev->period[p]) * proc_table[p].wcet;
159 pj 330
  }
2 pj 331
}
332
 
38 pj 333
static int CBS_public_eligible(LEVEL l, PID p)
2 pj 334
{
335
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
336
  JOB_TASK_MODEL job;
337
 
338
  /* we have to check if the deadline and the wcet are correct...
339
     if the CBS level schedules in background with respect to others
340
     levels, there can be the case in witch a task is scheduled by
341
     schedule_time > CBS_deadline; in this case (not covered in the
342
     article because if there is only the standard scheduling policy
343
     this never apply) we reassign the deadline */
344
 
345
  if ( TIMESPEC_A_LT_B(&lev->cbs_dline[p], &schedule_time) ) {
346
    /* we kill the current activation */
347
    level_table[ lev->scheduling_level ]->
38 pj 348
      private_extract(lev->scheduling_level, p);
2 pj 349
 
350
    /* we modify the deadline ... */
351
    TIMESPEC_ASSIGN(&lev->cbs_dline[p], &schedule_time);
352
    ADDUSEC2TIMESPEC(lev->period[p], &lev->cbs_dline[p]);
353
 
354
    /* and the capacity */
355
    proc_table[p].avail_time = proc_table[p].wcet;
356
 
357
    /* and, finally, we reinsert the task in the master level */
358
    job_task_default_model(job, lev->cbs_dline[p]);
359
    job_task_def_noexc(job);
360
    level_table[ lev->scheduling_level ]->
38 pj 361
      private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
2 pj 362
 
363
    return -1;
364
  }
365
 
366
  return 0;
367
}
368
 
38 pj 369
static void CBS_public_dispatch(LEVEL l, PID p, int nostop)
2 pj 370
{
371
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
372
  level_table[ lev->scheduling_level ]->
38 pj 373
    private_dispatch(lev->scheduling_level,p,nostop);
2 pj 374
}
375
 
38 pj 376
static void CBS_public_epilogue(LEVEL l, PID p)
2 pj 377
{
378
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
379
  JOB_TASK_MODEL job;
380
 
381
  /* check if the wcet is finished... */
382
  if ( proc_table[p].avail_time <= 0) {
383
    /* we kill the current activation */
384
    level_table[ lev->scheduling_level ]->
38 pj 385
      private_extract(lev->scheduling_level, p);
2 pj 386
 
387
    /* we modify the deadline according to rule 4 ... */
388
    CBS_avail_time_check(lev, p);
389
 
390
    /* and, finally, we reinsert the task in the master level */
391
    job_task_default_model(job, lev->cbs_dline[p]);
392
    job_task_def_noexc(job);
393
    level_table[ lev->scheduling_level ]->
38 pj 394
      private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
2 pj 395
//    kern_printf("epil : dl %d per %d p %d |\n",
396
//              lev->cbs_dline[p].tv_nsec/1000,lev->period[p],p);
397
 
398
  }
399
  else
400
    /* the task has been preempted. it returns into the ready queue by
401
       calling the guest_epilogue... */
402
    level_table[ lev->scheduling_level ]->
38 pj 403
      private_epilogue(lev->scheduling_level,p);
2 pj 404
}
405
 
38 pj 406
static void CBS_public_activate(LEVEL l, PID p)
2 pj 407
{
408
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
38 pj 409
  struct timespec t;
2 pj 410
 
212 giacomo 411
  if (lev->flag[p] & CBS_SLEEP) {
412
    lev->flag[p] &= ~CBS_SLEEP;
413
    if (proc_table[p].status != SLEEP) return;
414
  }
415
 
2 pj 416
  /* save activation (only if needed... */
417
  if (proc_table[p].status != SLEEP) {
418
    if (lev->flag[p] & CBS_SAVE_ARRIVALS)
419
      lev->nact[p]++;
420
    return;
421
  }
422
 
38 pj 423
  kern_gettime(&t);
2 pj 424
 
38 pj 425
  CBS_activation(lev, p, &t);
2 pj 426
 
427
  /* Set the reactivation timer */
428
  if (!(lev->flag[p] & CBS_APERIODIC))
429
  {
430
    /* we cannot use the deadline computed by CBS_activation because
431
       the deadline may be != from actual_time + period
432
       (if we call the task_activate after a task_sleep, and the
433
       deadline was postponed a lot...) */
38 pj 434
    TIMESPEC_ASSIGN(&lev->reactivation_time[p], &t);
2 pj 435
    ADDUSEC2TIMESPEC(lev->period[p], &lev->reactivation_time[p]);
436
//    TIMESPEC_ASSIGN(&lev->reactivation_time[p], &lev->cbs_dline[p]);
437
    lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
438
                                                 CBS_timer_reactivate,
439
                                                 (void *)p);
440
    #ifdef CBS_COUNTER
441
      if (p==5) cbs_counter2++;
442
    #endif
443
  }
444
//  kern_printf("act : %d %d |",lev->cbs_dline[p].tv_nsec/1000,p);
445
}
446
 
38 pj 447
static void CBS_public_unblock(LEVEL l, PID p)
2 pj 448
{
449
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
450
  struct timespec acttime;
451
 
38 pj 452
  kern_gettime(&acttime);
2 pj 453
 
454
  CBS_activation(lev,p,&acttime);
455
}
456
 
38 pj 457
static void CBS_public_block(LEVEL l, PID p)
2 pj 458
{
459
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
460
 
461
  /* check if the wcet is finished... */
462
  CBS_avail_time_check(lev, p);
463
 
464
  level_table[ lev->scheduling_level ]->
38 pj 465
    private_extract(lev->scheduling_level,p);
2 pj 466
}
467
 
38 pj 468
static int CBS_public_message(LEVEL l, PID p, void *m)
2 pj 469
{
470
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
471
 
212 giacomo 472
  switch((long)(m)) {
2 pj 473
 
212 giacomo 474
    case (long)(NULL):
2 pj 475
 
212 giacomo 476
      /* check if the wcet is finished... */
477
      CBS_avail_time_check(lev, p);
478
 
479
      if (lev->nact[p]) {
480
        /* continue!!!! */
481
        lev->nact[p]--;
482
        level_table[ lev->scheduling_level ]->
483
          private_epilogue(lev->scheduling_level,p);
484
      } else {
485
        level_table[ lev->scheduling_level ]->
486
          private_extract(lev->scheduling_level,p);
487
 
488
        if (lev->flag[p] & CBS_APERIODIC)
489
          proc_table[p].status = SLEEP;
490
        else  /* the task is soft_periodic */
491
          proc_table[p].status = CBS_IDLE;
492
      }
493
 
494
      jet_update_endcycle(); /* Update the Jet data... */
214 giacomo 495
      trc_logevent(TRC_ENDCYCLE,&p); /* tracer stuff */
212 giacomo 496
 
497
      break;
498
 
499
    case 1:
500
 
501
      lev->flag[p] |= CBS_SLEEP;
214 giacomo 502
      trc_logevent(TRC_DISABLE,&p);
212 giacomo 503
 
504
      break;
505
 
38 pj 506
  }
2 pj 507
 
212 giacomo 508
  return 0;
38 pj 509
 
2 pj 510
}
511
 
38 pj 512
static void CBS_public_end(LEVEL l, PID p)
2 pj 513
{
514
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
515
 
516
  /* check if the wcet is finished... */
517
  CBS_avail_time_check(lev, p);
518
 
519
  level_table[ lev->scheduling_level ]->
38 pj 520
    private_extract(lev->scheduling_level,p);
2 pj 521
 
522
  /* we delete the reactivation timer */
523
  if (!(lev->flag[p] & CBS_APERIODIC)) {
38 pj 524
    kern_event_delete(lev->reactivation_timer[p]);
2 pj 525
    lev->reactivation_timer[p] = -1;
526
  }
527
 
528
  /* Finally, we post the zombie event. when the end period is reached,
529
     the task descriptor and banwidth are freed */
530
  proc_table[p].status = CBS_ZOMBIE;
531
  lev->reactivation_timer[p] = kern_event_post(&lev->cbs_dline[p],
532
                                               CBS_timer_zombie,
533
                                               (void *)p);
534
}
535
 
536
/* Registration functions */
537
 
538
/*+ Registration function:
539
    int flags                 the init flags ... see CBS.h +*/
38 pj 540
LEVEL CBS_register_level(int flags, LEVEL master)
2 pj 541
{
542
  LEVEL l;            /* the level that we register */
543
  CBS_level_des *lev;  /* for readableness only */
544
  PID i;              /* a counter */
545
 
546
  printk("CBS_register_level\n");
547
 
548
  /* request an entry in the level_table */
38 pj 549
  l = level_alloc_descriptor(sizeof(CBS_level_des));
2 pj 550
 
38 pj 551
  lev = (CBS_level_des *)level_table[l];
2 pj 552
 
553
  printk("    lev=%d\n",(int)lev);
554
 
555
  /* fill the standard descriptor */
556
  if (flags & CBS_ENABLE_GUARANTEE)
38 pj 557
    lev->l.public_guarantee = CBS_public_guarantee;
2 pj 558
  else
38 pj 559
    lev->l.public_guarantee = NULL;
560
  lev->l.public_create    = CBS_public_create;
561
  lev->l.public_detach    = CBS_public_detach;
562
  lev->l.public_end       = CBS_public_end;
563
  lev->l.public_eligible  = CBS_public_eligible;
564
  lev->l.public_dispatch  = CBS_public_dispatch;
565
  lev->l.public_epilogue  = CBS_public_epilogue;
566
  lev->l.public_activate  = CBS_public_activate;
567
  lev->l.public_unblock   = CBS_public_unblock;
568
  lev->l.public_block     = CBS_public_block;
569
  lev->l.public_message   = CBS_public_message;
2 pj 570
 
571
  /* fill the CBS descriptor part */
572
  for (i=0; i<MAX_PROC; i++) {
573
     NULL_TIMESPEC(&lev->cbs_dline[i]);
574
     lev->period[i] = 0;
575
     NULL_TIMESPEC(&lev->reactivation_time[i]);
576
     lev->reactivation_timer[i] = -1;
577
     lev->nact[i] = 0;
578
     lev->flag[i] = 0;
579
  }
580
 
581
 
582
  lev->U = 0;
583
 
584
  lev->scheduling_level = master;
585
 
159 pj 586
  lev->flags = flags;
38 pj 587
 
588
  return l;
2 pj 589
}
590
 
591
bandwidth_t CBS_usedbandwidth(LEVEL l)
592
{
593
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
38 pj 594
 
595
  return lev->U;
2 pj 596
}
597
 
598
int CBS_get_nact(LEVEL l, PID p)
599
{
600
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
601
 
602
  return lev->nact[p];
603
}
604