Subversion Repositories shark

Rev

Rev 1624 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1624 giacomo 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: cbsstar.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
24
 
25
 File:        $File$
26
 Revision:    $Revision: 1.1.1.1 $
27
 Last update: $Date: 2004-05-24 17:54:51 $
28
 ------------
29
 
30
 Read CBSSTAR.h for general details.
31
 
32
 Basically, a budget can be in 2 states:
33
 - Active -> the budget queue is not empty
34
 - Idle   -> the budget queue is empty
35
 
36
 The fact that a task into a budget is inserted into the master module depends
37
 on the value of the remaining time the tasks can spend in the period.
38
 
39
 The module does handle only one oslib event, used to enforce the
40
 temporal isolation between buffers. Note that all is implemented
41
 without using the CONTROL_CAP field.
42
 
43
 Basically, for each budget there can be at most one task inserted
44
 into the master level. Its deadline is modified according to the
45
 usage of its capacity, that is, when a budget is exausted its
46
 deadline is postponed.
47
 
48
*/
49
 
50
/*
51
 * Copyright (C) 2002 Paolo Gai
52
 *
53
 * This program is free software; you can redistribute it and/or modify
54
 * it under the terms of the GNU General Public License as published by
55
 * the Free Software Foundation; either version 2 of the License, or
56
 * (at your option) any later version.
57
 *
58
 * This program is distributed in the hope that it will be useful,
59
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
60
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
61
 * GNU General Public License for more details.
62
 *
63
 * You should have received a copy of the GNU General Public License
64
 * along with this program; if not, write to the Free Software
65
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
66
 *
67
 */
68
 
69
 
70
#include "cbsstar.h"
71
#include <ll/string.h>
72
 
73
#define ACTIVE 1
74
#define NOACTIVE 0
75
#define INIT 2
76
 
77
#define CBSSTAR_IDLE APER_STATUS_BASE
78
/*
79
 * DEBUG stuffs begin
80
 */
81
 
82
//#define CBSSTAR_DEBUG
83
int event_monitor;
84
#ifdef CBSSTAR_DEBUG
85
 
86
 
87
static __inline__ void fake_printf(char *fmt, ...) {}
88
 
89
//#define cbsstar_printf kern_printf
90
//#define cbsstar_printf2 kern_printf
91
//#define cbsstar_printf3 kern_printf
92
 
93
#define cbsstar_printf fake_printf
94
#define cbsstar_printf2 fake_printf
95
#define cbsstar_printf3 fake_printf
96
 
97
#if 0
98
void cbsstar_printq(QQUEUE *q)
99
{
100
  PID p;
101
  kern_printf("[");
102
  p = q->first;
103
  kern_printf("->%d",p);
104
  while (p != NIL) {
105
    p = proc_table[p].next;
106
    kern_printf("->%d",p);
107
  }
108
  kern_printf("]");
109
}
110
#else
111
static __inline__ void cbsstar_printq(QQUEUE *q) {}
112
#endif
113
 
114
#if 0
115
static __inline__ void cbsstar_printblob(int x) { if (x) cputc('±'); else cputc('Û'); }
116
#else
117
static __inline__ void cbsstar_printblob(int x) {}
118
#endif
119
 
120
#endif
121
 
122
/*
123
 * DEBUG stuffs end
124
 */
125
/*+ Status used in the level +*/
126
#define CBSSTAR_WAIT          APER_STATUS_BASE    /*+ waiting the service   +*/
127
 
128
/* this structure contains the status for a single budget */
129
struct budget_struct {
130
  TIME Q;                 /* budget */
131
  TIME T;                 /* period */
132
 
133
  struct timespec dline;  /* deadline */
134
  int dline_timer;        /* oslib event for budget reactivation*/
135
  int avail;              /* current budget */
136
 
137
  PID current;            /* the task currently put in execution */
138
 
139
  int flags;
140
 
141
  IQUEUE tasks;           /* a FIFO queue for the tasks handled
142
                             using the budget */
143
};
144
 
145
typedef struct {
146
  level_des l;               /* the standard level descriptor */
147
 
148
  struct budget_struct *b;   /* the budgets! */
149
  int n;                     /* the maximum index for the budgets */
150
  int freebudgets;           /* number of free budgets; starts from n */
151
 
152
  int tb[MAX_PROC];          /* link task->budget (used in guest_end) */
153
 
154
  bandwidth_t U;   /*+ the used bandwidth by the server       +*/
155
 
156
  int cap_lev;
157
 
158
  PID on_shadow;
159
 
160
  LEVEL scheduling_level;
161
 
162
} CBSSTAR_level_des;
163
 
164
 
165
static void CBSSTAR_deadline_timer_hardreservation(void *a)
166
{
167
  struct budget_struct *b = a;
168
  struct timespec t;
169
 
170
  //kern_printf("*********** %d", b->dline_timer);
171
  b->dline_timer=NIL;
172
    /* we modify the deadline according to rule 4 ... */
173
    /* there is a while because if the wcet is << than the system tick
174
      we need to postpone the deadline many times */
175
  if (b->avail<=0) {
176
    b->avail += b->Q;
177
    if (b->avail>b->Q) b->avail=b->Q;
178
 
179
    //kern_printf("budget recharge %d", b);
180
  }
181
 
182
  if (b->avail>0) b->flags=ACTIVE;
183
 
184
  /* avail may be <0 because a task executed via a shadow fo many time
185
     b->current == NIL only if the prec task was finished and there
186
     was not any other task to be put in the ready queue
187
     ... we are now activating the next task */
188
  if (b->current == NIL && b->flags) {
189
      if (iq_query_first(&(b->tasks)) != NIL) {
190
        //struct timespec t;
191
        CBSSTAR_level_des *lev;
192
        PID p;
193
        JOB_TASK_MODEL job;
194
        //kern_gettime(&t);
195
        //TIMESPEC_ASSIGN(&b->dline, &schedule_time);
196
        //ADDUSEC2TIMESPEC(b->T, &b->dline);
197
        kern_gettime(&t);
198
        TIMESPEC_ASSIGN(&b->dline, &t);
199
        ADDUSEC2TIMESPEC(b->T, &b->dline);
200
 
201
        p = iq_getfirst(&(b->tasks));
202
        b->current=p;
203
        lev = (CBSSTAR_level_des *)(level_table[proc_table[p].task_level]);
204
        //kern_printf("reinsert task p = %d lev = %d ",p,proc_table[p].task_level); 
205
        /* and, finally, we reinsert the task in the master level */
206
        job_task_default_model(job, b->dline);
207
        job_task_def_noexc(job);
208
        //kern_printf("(CR:iact p%d %ld.%ld av=%d)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
209
        //kern_printf("**");
210
        level_table[ lev->scheduling_level ]->
211
          private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
212
 
213
        event_need_reschedule();
214
      }
215
  } else
216
    if (b->current !=NIL && b->avail>0) {
217
      kern_printf("(cap&nil ");
218
    }
219
  if (b->flags==NOACTIVE && b->dline_timer!=NIL){
220
    kern_gettime(&t);
221
    TIMESPEC_ASSIGN(&b->dline, &t);
222
    ADDUSEC2TIMESPEC(b->T, &b->dline);
223
 
224
    b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
225
    event_monitor=b->dline_timer;
226
    //kern_printf("(dline hard %ld.%ld ev %d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->dline_timer);
227
 }
228
}
229
static void CBSSTAR_activation(CBSSTAR_level_des *lev,
230
                           PID p,
231
                           struct timespec *acttime)
232
{
233
  JOB_TASK_MODEL job;
234
  struct budget_struct *b = &lev->b[lev->tb[p]];
235
  /* we have to check if the deadline and the wcet are correct before
236
     activating a new task or an old task... */
237
 
238
  /* check 1: if the deadline is before than the actual scheduling time */
239
 
240
  /* check 2: if ( avail_time >= (cbs_dline - acttime)* (wcet/period) )
241
     (rule 7 in the CBS article!) */
242
  TIME t;
243
  struct timespec t2,t3;
244
 
245
  t = (b->T * b->avail) / b->Q;
246
  t3.tv_sec = t / 1000000;
247
  t3.tv_nsec = (t % 1000000) * 1000;
248
 
249
  SUBTIMESPEC(&b->dline, acttime, &t2);
250
  if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) ||
251
      /* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
252
    TIMESPEC_ASSIGN(&b->dline, acttime);
253
    ADDUSEC2TIMESPEC(b->T, &b->dline);
254
  }  
255
 
256
  /* and the capacity */
257
  if (b->flags==INIT) {
258
    b->avail = b->Q;
259
    b->flags=ACTIVE;
260
  }  
261
 
262
 
263
#ifdef CBSSTAR_DEBUG
264
    cbsstar_printf3("±%d±",lev->tb[p]);
265
    cbsstar_printblob(lev->tb[p]);
266
#endif
267
    //}
268
  //#endif
269
 
270
  /* record the current task inserted in the master module */
271
  b->current = p;
272
 
273
  //#ifdef CBSSTAR_DEBUG
274
  //kern_printf("(CA:iact p%d %ld.%ld av=%d at=%ld.%ld)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail, acttime->tv_sec, acttime->tv_nsec/1000);
275
  //#endif
276
  /* and, finally, we reinsert the task in the master level */
277
  job_task_default_model(job, b->dline);
278
  job_task_def_noexc(job);
279
  level_table[ lev->scheduling_level ]->
280
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
281
  //b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
282
}
283
 
284
static void CBSSTAR_account_capacity(CBSSTAR_level_des *lev, PID p)
285
{
286
  struct timespec ty;
287
  TIME tx;
288
  struct budget_struct *b = &lev->b[lev->tb[p]];
289
  TIME t;
290
  struct timespec t2,t3, acttime;
291
 
292
  if (lev->cap_lev!=NIL && b->current==p) {
293
    kern_event_delete(lev->cap_lev);
294
    lev->cap_lev=NIL;
295
  }
296
 
297
  kern_gettime(&acttime);
298
  t = (b->T * b->avail) / b->Q;
299
  t3.tv_sec = t / 1000000;
300
  t3.tv_nsec = (t % 1000000) * 1000;
301
 
302
  SUBTIMESPEC(&b->dline, &acttime, &t2);
303
 
304
  SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
305
  tx = TIMESPEC2USEC(&ty);
306
  lev->b[lev->tb[p]].avail -= tx;
307
 
308
#ifdef CBSSTAR_DEBUG
309
  cbsstar_printf2("(C:cap p%d av=%d)", p, lev->b[lev->tb[p]].avail);
310
#endif
311
  if (lev->b[lev->tb[p]].avail<=0 || TIMESPEC_A_GT_B(&t3, &t2)) lev->b[lev->tb[p]].flags=NOACTIVE;
312
 
313
  if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time) ) {
314
 
315
    /* we modify the deadline ... */
316
    TIMESPEC_ASSIGN(&b->dline, &schedule_time);
317
    ADDUSEC2TIMESPEC(b->T, &b->dline);
318
  }
319
 
320
  //if (b->flags==NOACTIVE && b->dline_timer!=NIL)
321
  //  kern_printf("flags %d, dline_timer %d", b->flags, b->dline_timer);
322
 
323
  if (b->flags==NOACTIVE && b->dline_timer==NIL)  {
324
    b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
325
    event_monitor=b->dline_timer;
326
    //kern_printf("(dline %ld.%ld ev %d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->dline_timer);
327
  }
328
 
329
 
330
}
331
 
332
 
333
/* The on-line guarantee is enabled only if the appropriate flag is set... */
334
static int CBSSTAR_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
335
{
336
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
337
 
338
#ifdef CBSSTAR_DEBUG
339
  cbsstar_printf("(C:gua)");
340
#endif
341
 
342
  if (*freebandwidth >= lev->U) {
343
    *freebandwidth -= lev->U;
344
    return 1;
345
  }
346
  else
347
    return 0;
348
}
349
 
350
static void capacity_handler(void *l)
351
{
352
  //kern_printf("!"); 
353
  CBSSTAR_level_des *lev =l;
354
  lev->cap_lev=NIL;
355
  event_need_reschedule();
356
 
357
}
358
 
359
static int CBSSTAR_private_eligible(LEVEL l, PID p)
360
{
361
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
362
  struct budget_struct *b = &lev->b[lev->tb[p]];
363
  JOB_TASK_MODEL job;
364
 
365
#ifdef CBSSTAR_DEBUG
366
  //kern_printf("(C:eli %d",p);
367
#endif
368
 
369
  /* we have to check if the deadline and the wcet are correct...
370
     if the CBSSTAR level schedules in background with respect to others
371
     levels, there can be the case in witch a task is scheduled by
372
     schedule_time > CBSSTAR_deadline; in this case (not covered in the
373
     article because if there is only the standard scheduling policy
374
     this never apply) we reassign the deadline */
375
  if (b->current==p) {
376
  if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
377
    if (lev->cap_lev!=NIL) {
378
        kern_event_delete(lev->cap_lev);
379
        lev->cap_lev=NIL;
380
    }
381
 
382
    /* we kill the current activation */
383
    level_table[ lev->scheduling_level ]->
384
      private_extract(lev->scheduling_level, p);
385
   /* we modify the deadline ... */
386
    TIMESPEC_ASSIGN(&b->dline, &schedule_time);
387
    ADDUSEC2TIMESPEC(b->T, &b->dline);
388
 
389
    /* and the capacity */
390
    b->avail = b->Q;
391
    b->flags=ACTIVE;
392
 
393
    if (b->dline_timer!=NIL)  {
394
            kern_event_delete(b->dline_timer);
395
            b->dline_timer=NIL;
396
    }
397
 
398
    //#ifdef CBSSTAR_DEBUG
399
    //kern_printf(" %ld.%ld av=%d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->Q);
400
    //cbsstar_printf3("±%d±",lev->tb[p]);
401
    //cbsstar_printblob(lev->tb[p]);
402
    //#endif
403
 
404
    /* and, finally, we reinsert the task in the master level */
405
    job_task_default_model(job, b->dline);
406
    job_task_def_noexc(job);
407
    //kern_printf("(CE:iact p%d %ld.%ld av=%d)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
408
    level_table[ lev->scheduling_level ]->
409
      private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
410
    //kern_printf("task %d, avail %d", p, b->avail);
411
    return -1;
412
  }  
413
}
414
#ifdef CBSSTAR_DEBUG
415
  cbsstar_printf(")");
416
#endif
417
 
418
  return 0;
419
}
420
 
421
static void CBSSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
422
{
423
  /* A task has been activated for some reason. Basically, the task is
424
  inserted in the queue if the queue is empty, otherwise the task is
425
  inserted into the master module, and an oslib event is posted. */
426
 
427
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
428
  BUDGET_TASK_MODEL *budget;
429
 
430
  if (m->pclass != BUDGET_PCLASS ||
431
      (m->level != 0 && m->level != l)) {
432
    kern_raise(XINVALID_TASK, p);
433
    return;
434
  }
435
  budget = (BUDGET_TASK_MODEL *)m;
436
 
437
#ifdef CBSSTAR_DEBUG
438
  cbsstar_printf("(C:gcr %d b%d", p, budget->b);
439
#endif
440
 
441
  lev->tb[p] = budget->b;
442
 
443
  if (lev->b[budget->b].current == NIL && lev->b[budget->b].flags ) {
444
    /* This is the first task in the budget,
445
       the task have to be inserted into the master module */
446
    struct timespec t;
447
    kern_gettime(&t);
448
    CBSSTAR_activation(lev,p,&t);
449
  } else {
450
    /* The budget is not empty, another task is already into the
451
       master module, so the task is inserted at the end of the budget
452
       queue */
453
    iq_insertlast(p,&lev->b[budget->b].tasks);
454
//#ifdef CBSSTAR_DEBUG
455
    //kern_printf(" ilast flag %d task %d",lev->b[budget->b].flags,lev->b[budget->b].current);
456
 //   cbsstar_printq(&lev->b[budget->b].tasks);
457
//#endif
458
  }
459
#ifdef CBSSTAR_DEBUG
460
  cbsstar_printf(")");
461
#endif
462
}
463
 
464
static void CBSSTAR_private_extract(LEVEL l, PID p)
465
{
466
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
467
 
468
//#ifdef CBSSTAR_DEBUG
469
  //kern_printf("(C:gend p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
470
  //cbsstar_printq(&lev->b[lev->tb[p]].tasks);
471
//#endif
472
 
473
  /* a task is removed from execution for some reasons. It must be
474
     that it is the first in its budget queue (only the first task in
475
     a budget queue is put into execution!) */
476
 
477
  /* remove the task from execution (or from the ready queue) */
478
  if (lev->b[lev->tb[p]].current == p) {
479
 
480
   CBSSTAR_account_capacity(lev,p);
481
    /* remove the task from the master module */
482
    level_table[ lev->scheduling_level ]->
483
      private_extract(lev->scheduling_level, p);
484
 
485
#ifdef CBSSTAR_DEBUG
486
    cbsstar_printq(&lev->b[lev->tb[p]].tasks);
487
#endif
488
 
489
    /* check if the buffer has someone else to schedule */
490
    if (iq_query_first(&lev->b[lev->tb[p]].tasks) == NIL) {
491
      /* the buffer has no tasks! */
492
      lev->b[lev->tb[p]].current = NIL;
493
    }
494
    else if (lev->b[lev->tb[p]].flags) {
495
      /* if so, insert the new task into the master module */
496
      PID n;
497
      struct timespec t;
498
 
499
      kern_gettime(&t);
500
      n = iq_getfirst(&lev->b[lev->tb[p]].tasks);
501
//#ifdef CBSSTAR_DEBUG
502
      //kern_printf("{p%d n%d}",p,n);
503
//#endif
504
      CBSSTAR_activation(lev,n,&t);  // it modifies b[lev->tb[p]].current
505
    }
506
    else
507
        lev->b[lev->tb[p]].current=NIL;
508
 
509
  }
510
  else  {
511
    iq_extract(p, &lev->b[lev->tb[p]].tasks);
512
  }
513
}
514
 
515
static void CBSSTAR_private_dispatch(LEVEL l, PID p, int nostop)
516
{
517
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
518
  struct timespec ty;
519
 
520
//#ifdef CBSSTAR_DEBUG
521
  //kern_printf("(C:gdisp p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
522
//  cbsstar_printq(&lev->b[lev->tb[p]].tasks);
523
//#endif
524
 
525
  /* the current task (that is the only one inserted in the master module
526
     for the corresponding budget) is dispatched. Note that the current
527
     task is not inserted in any FIFO queue, so the task does not have to
528
     be extracted! */
529
 
530
  /* ... then, we dispatch it to the master level */
531
  level_table[ lev->scheduling_level ]->
532
    private_dispatch(lev->scheduling_level,p,nostop);
533
 
534
  /* ...and finally, we have to post a capacity event */
535
  if (!nostop) {
536
    TIMESPEC_ASSIGN(&ty, &schedule_time);
537
    ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty);
538
    lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
539
  }
540
 
541
}
542
 
543
static void CBSSTAR_private_epilogue(LEVEL l, PID p)
544
{
545
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
546
  struct budget_struct *b = &lev->b[lev->tb[p]];
547
 
548
 
549
  //#ifdef CBSSTAR_DEBUG
550
  //kern_printf("(C:gepi %d %d",p, b->current);
551
  //#endif
552
 
553
  if (p==b->current)  {
554
 
555
 CBSSTAR_account_capacity(lev,p);
556
 
557
    // L'evento di capacità va cancellato perchè sarà ripristinato nella successiva dispatch
558
    /* we have to check if the capacity is still available */
559
    if (b->flags)  {
560
      /* there is capacity available, maybe it is simply a preemption;
561
         the task have to return to the ready queue */
562
      level_table[ lev->scheduling_level ]->
563
        private_epilogue(lev->scheduling_level,p);
564
#ifdef CBSSTAR_DEBUG
565
      //kern_printf("(ep *av=%d", b->avail);
566
#endif
567
 
568
 
569
    } else {
570
      /* we kill the current activation */
571
      level_table[ lev->scheduling_level ]->
572
        private_extract(lev->scheduling_level, p);
573
      //kern_printf("extract");
574
      iq_insertfirst(p, &b->tasks);
575
      proc_table[p].status = CBSSTAR_IDLE;
576
      b->current = NIL;
577
 
578
      //kern_printf("budget finish %d", b);
579
    }
580
#ifdef CBSSTAR_DEBUG
581
    cbsstar_printf(")");
582
#endif
583
   }
584
 
585
}
586
 
587
/* Registration functions }*/
588
 
589
/*+ Registration function:
590
    int flags                 the init flags ... see CBSSTAR.h +*/
591
LEVEL CBSSTAR_register_level(int n, LEVEL master)
592
{
593
  LEVEL l;            /* the level that we register */
594
  CBSSTAR_level_des *lev;  /* for readableness only */
595
  PID i;              /* a counter */
596
 
597
#ifdef CBSSTAR_DEBUG
598
  cbsstar_printf("CBSSTAR_register_level\n");
599
#endif
600
 
601
  /* request an entry in the level_table */
602
  l = level_alloc_descriptor(sizeof(CBSSTAR_level_des));
603
 
604
  lev = (CBSSTAR_level_des *)level_table[l];
605
 
606
  printk("    lev=%d\n",(int)lev);
607
 
608
  /* fill the standard descriptor */
609
  lev->l.private_insert   = CBSSTAR_private_insert;
610
  lev->l.private_extract  = CBSSTAR_private_extract;
611
  lev->l.private_eligible = CBSSTAR_private_eligible;
612
  lev->l.private_dispatch = CBSSTAR_private_dispatch;
613
  lev->l.private_epilogue = CBSSTAR_private_epilogue;
614
 
615
  lev->l.public_guarantee = CBSSTAR_public_guarantee;
616
 
617
  /* fill the CBSSTAR descriptor part */
618
  lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
619
 
620
  for (i=0; i<n; i++) {
621
    lev->b[i].Q = 0;
622
    lev->b[i].T = 0;
623
    NULL_TIMESPEC(&lev->b[i].dline);
624
    lev->b[i].dline_timer = NIL;
625
    lev->b[i].avail = 0;
626
    lev->b[i].current = -1;
627
    lev->b[i].flags=INIT;
628
    iq_init(&lev->b[i].tasks, &freedesc, 0);
629
  }
630
 
631
  lev->n = n;
632
  lev->freebudgets = 0;
633
 
634
  for (i=0; i<MAX_PROC; i++)
635
    lev->tb[i] = NIL;
636
 
637
  lev->U = 0;
638
  lev->cap_lev=NIL;
639
  lev->scheduling_level = master;
640
  lev->on_shadow=NIL;
641
 
642
  return l;
643
}
644
 
645
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T)
646
{
647
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
648
 
649
#ifdef CBSSTAR_DEBUG
650
  cbsstar_printf("(C:sbud)");
651
#endif
652
 
653
  if (lev->freebudgets != lev->n) {
654
    bandwidth_t b;
655
    b = (MAX_BANDWIDTH / T) * Q;
656
 
657
    /* really update lev->U, checking an overflow... */
658
    if (Q< T && MAX_BANDWIDTH - lev->U > b) {
659
      int r = lev->freebudgets;  // the return value
660
 
661
      lev->U += b;
662
      lev->freebudgets++;
663
 
664
      lev->b[r].Q = Q;
665
      lev->b[r].T = T;
666
 
667
      return r;
668
    }
669
    else
670
      return -2;
671
  }
672
  else
673
    return -1;
674
}