Subversion Repositories shark

Rev

Rev 1100 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1089 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: cbsstar.c,v 1.1 2002-09-02 10:29:30 pj Exp $
24
 
25
 File:        $File$
26
 Revision:    $Revision: 1.1 $
27
 Last update: $Date: 2002-09-02 10:29:30 $
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
 
74
/*
75
 * DEBUG stuffs begin
76
 */
77
 
78
//#define CBSSTAR_DEBUG
79
 
80
#ifdef CBSSTAR_DEBUF
81
 
82
static __inline__ void fake_printf(char *fmt, ...) {}
83
 
84
//#define cbsstar_printf kern_printf
85
//#define cbsstar_printf2 kern_printf
86
//#define cbsstar_printf3 kern_printf
87
 
88
#define cbsstar_printf fake_printf
89
#define cbsstar_printf2 fake_printf
90
#define cbsstar_printf3 fake_printf
91
 
92
#if 0
93
void cbsstar_printq(QQUEUE *q)
94
{
95
  PID p;
96
  kern_printf("[");
97
  p = q->first;
98
  kern_printf("->%d",p);
99
  while (p != NIL) {
100
    p = proc_table[p].next;
101
    kern_printf("->%d",p);
102
  }
103
  kern_printf("]");
104
}
105
#else
106
static __inline__ void cbsstar_printq(QQUEUE *q) {}
107
#endif
108
 
109
#if 0
110
static __inline__ void cbsstar_printblob(int x) { if (x) cputc('±'); else cputc('Û'); }
111
#else
112
static __inline__ void cbsstar_printblob(int x) {}
113
#endif
114
 
115
#endif
116
 
117
/*
118
 * DEBUG stuffs end
119
 */
120
 
121
 
122
/* this structure contains the status for a single budget */
123
struct budget_struct {
124
  TIME Q;                 /* budget */
125
  TIME T;                 /* period */
126
 
127
  struct timespec dline;  /* deadline */
128
  int dline_timer;        /* oslib event for budget reactivation*/
129
  int avail;              /* current budget */
130
 
131
  PID current;            /* the task currently put in execution */
132
 
133
  QQUEUE tasks;           /* a FIFO queue for the tasks handled
134
                             using the budget */
135
};
136
 
137
typedef struct {
138
  level_des l;               /* the standard level descriptor */
139
 
140
  struct budget_struct *b;   /* the budgets! */
141
  int n;                     /* the maximum index for the budgets */
142
  int freebudgets;           /* number of free budgets; starts from n */
143
 
144
  int tb[MAX_PROC];          /* link task->budget (used in guest_end) */
145
 
146
  bandwidth_t U;   /*+ the used bandwidth by the server       +*/
147
 
148
  LEVEL scheduling_level;
149
 
150
} CBSSTAR_level_des;
151
 
152
 
153
static void CBSSTAR_activation(CBSSTAR_level_des *lev,
154
                           PID p,
155
                           struct timespec *acttime)
156
{
157
  JOB_TASK_MODEL job;
158
  struct budget_struct *b = &lev->b[lev->tb[p]];
159
 
160
  /* we have to check if the deadline and the wcet are correct before
161
     activating a new task or an old task... */
162
 
163
  /* check 1: if the deadline is before than the actual scheduling time */
164
 
165
  /* check 2: if ( avail_time >= (cbs_dline - acttime)* (wcet/period) )
166
     (rule 7 in the CBS article!) */
167
  TIME t;
168
  struct timespec t2,t3;
169
 
170
  t = (b->T * b->avail) / b->Q;
171
  t3.tv_sec = t / 1000000;
172
  t3.tv_nsec = (t % 1000000) * 1000;
173
 
174
  SUBTIMESPEC(&b->dline, acttime, &t2);
175
 
176
  if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) ||
177
      /* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
178
/*    if (TIMESPEC_A_LT_B(&lev->cbs_dline[p], acttime) )
179
      kern_printf("$");
180
    else
181
      kern_printf("(Ûdline%d.%d act%d.%d wcet%d per%d avail%dÛ)",
182
                  lev->cbs_dline[p].tv_sec,lev->cbs_dline[p].tv_nsec/1000,
183
                  acttime->tv_sec, acttime->tv_nsec/1000,
184
                  proc_table[p].wcet, lev->period[p], proc_table[p].avail_time);
185
*/  /* we modify the deadline ... */
186
    TIMESPEC_ASSIGN(&b->dline, acttime);
187
    ADDUSEC2TIMESPEC(b->T, &b->dline);
188
 
189
    /* and the capacity */
190
    b->avail = b->Q;
191
 
192
#ifdef CBSSTAR_DEBUG
193
    cbsstar_printf3("±%d±",lev->tb[p]);
194
    cbsstar_printblob(lev->tb[p]);
195
#endif
196
  }
197
 
198
  /* record the current task inserted in the master module */
199
  b->current = p;
200
 
201
#ifdef CBSSTAR_DEBUG
202
  cbsstar_printf("(C:iact p%d %ld.%ld av=%d)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
203
#endif
204
 
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
  level_table[ lev->scheduling_level ]->
209
    guest_create(lev->scheduling_level, p, (TASK_MODEL *)&job);
210
  level_table[ lev->scheduling_level ]->
211
    guest_activate(lev->scheduling_level, p);
212
 
213
}
214
 
215
 
216
static void CBSSTAR_account_capacity(CBSSTAR_level_des *lev, PID p)
217
{
218
  struct timespec ty;
219
  TIME tx;
220
 
221
  SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
222
  tx = TIMESPEC2USEC(&ty);
223
  lev->b[lev->tb[p]].avail -= tx;
224
 
225
#ifdef CBSSTAR_DEBUG
226
  cbsstar_printf2("(C:cap p%d av=%d)", p, lev->b[lev->tb[p]].avail);
227
#endif
228
}
229
 
230
 
231
static int CBSSTAR_level_accept_task_model(LEVEL l, TASK_MODEL *m)
232
{
233
  return -1;
234
}
235
 
236
static int CBSSTAR_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
237
{
238
  if (m->pclass == BUDGET_PCLASS || m->pclass == (BUDGET_PCLASS | l)) {
239
      return 0;
240
  }
241
 
242
  return -1;
243
}
244
 
245
 
246
static void CBSSTAR_level_status(LEVEL l)
247
{
248
  kern_printf("CBSSTAR level_status (level %d)\n", l);
249
}
250
 
251
static PID CBSSTAR_level_scheduler(LEVEL l)
252
{
253
  /* the CBSSTAR don't schedule anything...
254
     it's an EDF level or similar that do it! */
255
  return NIL;
256
}
257
 
258
/* The on-line guarantee is enabled only if the appropriate flag is set... */
259
static int CBSSTAR_level_guarantee(LEVEL l, bandwidth_t *freebandwidth)
260
{
261
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
262
 
263
#ifdef CBSSTAR_DEBUG
264
  cbsstar_printf("(C:gua)");
265
#endif
266
 
267
  if (*freebandwidth >= lev->U) {
268
    *freebandwidth -= lev->U;
269
    return 1;
270
  }
271
  else
272
    return 0;
273
}
274
 
275
static int CBSSTAR_task_create(LEVEL l, PID p, TASK_MODEL *m)
276
{
277
  kern_raise(XUNVALID_TASK,exec_shadow);
278
  return 0; /* OK, also if the task cannot be guaranteed... */
279
}
280
 
281
static void CBSSTAR_task_detach(LEVEL l, PID p)
282
{ kern_raise(XUNVALID_TASK,exec_shadow); }
283
 
284
static int CBSSTAR_task_eligible(LEVEL l, PID p)
285
{
286
/* this function is never called! ... maybe I should remove it? */
287
#if 0
288
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
289
  struct budget_struct *b = &lev->b[lev->tb[p]];
290
  JOB_TASK_MODEL job;
291
 
292
#ifdef CBSSTAR_DEBUG
293
  cbsstar_printf("(C:eli %d",p);
294
#endif
295
 
296
  /* we have to check if the deadline and the wcet are correct...
297
     if the CBSSTAR level schedules in background with respect to others
298
     levels, there can be the case in witch a task is scheduled by
299
     schedule_time > CBSSTAR_deadline; in this case (not covered in the
300
     article because if there is only the standard scheduling policy
301
     this never apply) we reassign the deadline */
302
 
303
  if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time) ) {
304
    /* we kill the current activation */
305
    level_table[ lev->scheduling_level ]->
306
      guest_end(lev->scheduling_level, p);
307
 
308
    /* we modify the deadline ... */
309
    TIMESPEC_ASSIGN(&b->dline, &schedule_time);
310
    ADDUSEC2TIMESPEC(b->T, &b->dline);
311
 
312
    /* and the capacity */
313
    b->avail = b->Q;
314
 
315
#ifdef CBSSTAR_DEBUG
316
    cbsstar_printf2(" %ld.%ld av=%d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->Q);
317
    cbsstar_printf3("±%d±",lev->tb[p]);
318
    cbsstar_printblob(lev->tb[p]);
319
#endif
320
 
321
    /* and, finally, we reinsert the task in the master level */
322
    job_task_default_model(job, b->dline);
323
    job_task_def_noexc(job);
324
    level_table[ lev->scheduling_level ]->
325
      guest_create(lev->scheduling_level, p, (TASK_MODEL *)&job);
326
    level_table[ lev->scheduling_level ]->
327
      guest_activate(lev->scheduling_level, p);
328
 
329
    return -1;
330
  }
331
#ifdef CBSSTAR_DEBUG
332
  cbsstar_printf(")");
333
#endif
334
 
335
#endif
336
  return 0;
337
}
338
 
339
static void CBSSTAR_task_dispatch(LEVEL l, PID p, int nostop)
340
{ kern_raise(XUNVALID_TASK,exec_shadow); }
341
 
342
static void CBSSTAR_task_epilogue(LEVEL l, PID p)
343
{ kern_raise(XUNVALID_TASK,exec_shadow); }
344
 
345
static void CBSSTAR_task_activate(LEVEL l, PID p)
346
{ kern_raise(XUNVALID_TASK,exec_shadow); }
347
 
348
static void CBSSTAR_task_insert(LEVEL l, PID p)
349
{ kern_raise(XUNVALID_TASK,exec_shadow); }
350
 
351
static void CBSSTAR_task_extract(LEVEL l, PID p)
352
{ kern_raise(XUNVALID_TASK,exec_shadow); }
353
 
354
static void CBSSTAR_task_endcycle(LEVEL l, PID p)
355
{ kern_raise(XUNVALID_TASK,exec_shadow); }
356
 
357
static void CBSSTAR_task_end(LEVEL l, PID p)
358
{ kern_raise(XUNVALID_TASK,exec_shadow); }
359
 
360
static void CBSSTAR_task_sleep(LEVEL l, PID p)
361
{ kern_raise(XUNVALID_TASK,exec_shadow); }
362
 
363
static void CBSSTAR_task_delay(LEVEL l, PID p, TIME usdelay)
364
{ kern_raise(XUNVALID_TASK,exec_shadow); }
365
 
366
static int CBSSTAR_guest_create(LEVEL l, PID p, TASK_MODEL *m)
367
{
368
  /* A task has been activated for some reason. Basically, the task is
369
  inserted in the queue if the queue is empty, otherwise the task is
370
  inserted into the master module, and an oslib event is posted. */
371
 
372
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
373
  BUDGET_TASK_MODEL *budget = (BUDGET_TASK_MODEL *)m;
374
 
375
#ifdef CBSSTAR_DEBUG
376
  cbsstar_printf("(C:gcr %d b%d", p, budget->b);
377
#endif
378
 
379
  lev->tb[p] = budget->b;
380
 
381
  if (lev->b[budget->b].current == NIL) {
382
    /* This is the first task in the budget,
383
       the task have to be inserted into the master module */
384
    struct timespec t;
385
    ll_gettime(TIME_EXACT, &t);
386
    CBSSTAR_activation(lev,p,&t);
387
  } else {
388
    /* The budget is not empty, another task is already into the
389
       master module, so the task is inserted at the end of the budget
390
       queue */
391
    qq_insertlast(p,&lev->b[budget->b].tasks);
392
#ifdef CBSSTAR_DEBUG
393
    cbsstar_printf(" ilast");
394
    cbsstar_printq(&lev->b[budget->b].tasks);
395
#endif
396
  }
397
#ifdef CBSSTAR_DEBUG
398
  cbsstar_printf(")");
399
#endif
400
 
401
  return 0;
402
}
403
 
404
static void CBSSTAR_guest_end(LEVEL l, PID p)
405
{
406
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
407
 
408
#ifdef CBSSTAR_DEBUG
409
  cbsstar_printf("(C:gend p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
410
  cbsstar_printq(&lev->b[lev->tb[p]].tasks);
411
#endif
412
 
413
  /* a task is removed from execution for some reasons. It must be
414
     that it is the first in its budget queue (only the first task in
415
     a budget queue is put into execution!) */
416
  CBSSTAR_account_capacity(lev,p);
417
 
418
  /* remove the task from execution (or from the ready queue) */
419
  if (lev->b[lev->tb[p]].current == p) {
420
    /* remove the task from the master module */
421
    level_table[ lev->scheduling_level ]->
422
      guest_end(lev->scheduling_level, p);
423
 
424
#ifdef CBSSTAR_DEBUG
425
    cbsstar_printq(&lev->b[lev->tb[p]].tasks);
426
#endif
427
 
428
    /* check if the buffer has someone else to schedule */
429
    if (qq_queryfirst(&lev->b[lev->tb[p]].tasks) == NIL) {
430
      /* the buffer has no tasks! */
431
      lev->b[lev->tb[p]].current = NIL;
432
    }
433
    else {
434
      /* if so, insert the new task into the master module */
435
      PID n;
436
      struct timespec t;
437
 
438
      ll_gettime(TIME_EXACT, &t);
439
      n = qq_getfirst(&lev->b[lev->tb[p]].tasks);
440
#ifdef CBSSTAR_DEBUG
441
      cbsstar_printf("{p%d n%d}",p,n);
442
#endif
443
      CBSSTAR_activation(lev,n,&t);  // it modifies b[lev->tb[p]].current
444
    }
445
  }
446
  else
447
    qq_extract(p, &lev->b[lev->tb[p]].tasks);
448
}
449
 
450
static void CBSSTAR_guest_dispatch(LEVEL l, PID p, int nostop)
451
{
452
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
453
  struct timespec ty;
454
 
455
#ifdef CBSSTAR_DEBUG
456
  cbsstar_printf("(C:gdisp p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
457
  cbsstar_printq(&lev->b[lev->tb[p]].tasks);
458
#endif
459
 
460
  /* the current task (that is the only one inserted in the master module
461
     for the corresponding budget) is dispatched. Note that the current
462
     task is not inserted in any FIFO queue, so the task does not have to
463
     be extracted! */
464
 
465
  /* ... then, we dispatch it to the master level */
466
  level_table[ lev->scheduling_level ]->
467
    guest_dispatch(lev->scheduling_level,p,nostop);
468
 
469
  /* ...and finally, we have to post a capacity event */
470
  if (!nostop) {
471
    TIMESPEC_ASSIGN(&ty, &schedule_time);
472
    ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty);
473
    cap_timer = kern_event_post(&ty, capacity_timer, NULL);
474
  }
475
}
476
 
477
static void CBSSTAR_guest_epilogue(LEVEL l, PID p)
478
{
479
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
480
  struct budget_struct *b = &lev->b[lev->tb[p]];
481
 
482
#ifdef CBSSTAR_DEBUG
483
  cbsstar_printf("(C:gepi %d",p);
484
#endif
485
 
486
  CBSSTAR_account_capacity(lev,p);
487
 
488
  /* we have to check if the capacity is still available */
489
  if (b->avail > 0) {
490
    /* there is capacity available, maybe it is simply a preemption;
491
       the task have to return to the ready queue */
492
    level_table[ lev->scheduling_level ]->
493
      guest_epilogue(lev->scheduling_level,p);
494
#ifdef CBSSTAR_DEBUG
495
    cbsstar_printf2(" *av=%d", b->avail);
496
#endif
497
  } else {
498
    /* The capacity is exausted; the deadline have to be postponed and
499
       the task have to be reinserted in the master module */
500
    JOB_TASK_MODEL job;
501
 
502
    /* we kill the current activation */
503
    level_table[ lev->scheduling_level ]->
504
      guest_end(lev->scheduling_level, p);
505
 
506
    /* we modify the deadline according to rule 4 ... */
507
    /* there is a while because if the wcet is << than the system tick
508
       we need to postpone the deadline many times */
509
    while (b->avail <= 0) {
510
      ADDUSEC2TIMESPEC(b->T, &b->dline);
511
      b->avail += b->Q;
512
#ifdef CBSSTAR_DEBUG
513
      cbsstar_printf3("±%d±",lev->tb[p]);
514
      cbsstar_printblob(lev->tb[p]);
515
#endif
516
    }
517
 
518
#ifdef CBSSTAR_DEBUG
519
    cbsstar_printf2(" %ld.%ld av=%d",b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
520
#endif
521
 
522
    /* and, finally, we reinsert the task in the master level */
523
    job_task_default_model(job, b->dline);
524
    job_task_def_noexc(job);
525
    level_table[ lev->scheduling_level ]->
526
      guest_create(lev->scheduling_level, p, (TASK_MODEL *)&job);
527
    level_table[ lev->scheduling_level ]->
528
      guest_activate(lev->scheduling_level, p);
529
  }
530
#ifdef CBSSTAR_DEBUG
531
  cbsstar_printf(")");
532
#endif
533
}
534
 
535
static void CBSSTAR_guest_detach(LEVEL l, PID p)
536
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
537
 
538
static void CBSSTAR_guest_activate(LEVEL l, PID p)
539
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
540
 
541
static void CBSSTAR_guest_insert(LEVEL l, PID p)
542
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
543
 
544
static void CBSSTAR_guest_extract(LEVEL l, PID p)
545
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
546
 
547
static void CBSSTAR_guest_endcycle(LEVEL l, PID p)
548
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
549
 
550
static void CBSSTAR_guest_sleep(LEVEL l, PID p)
551
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
552
 
553
static void CBSSTAR_guest_delay(LEVEL l, PID p, DWORD tickdelay)
554
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
555
 
556
 
557
 
558
 
559
/* Registration functions */
560
 
561
/*+ Registration function:
562
    int flags                 the init flags ... see CBSSTAR.h +*/
563
LEVEL CBSSTAR_register_level(int n, LEVEL master)
564
{
565
  LEVEL l;            /* the level that we register */
566
  CBSSTAR_level_des *lev;  /* for readableness only */
567
  PID i;              /* a counter */
568
 
569
#ifdef CBSSTAR_DEBUG
570
  cbsstar_printf("CBSSTAR_register_level\n");
571
#endif
572
 
573
  /* request an entry in the level_table */
574
  l = level_alloc_descriptor();
575
 
576
#ifdef CBSSTAR_DEBUG
577
  cbsstar_printf("    alloco descrittore %d %d\n",l,(int)sizeof(CBSSTAR_level_des));
578
#endif
579
 
580
  /* alloc the space needed for the CBSSTAR_level_des */
581
  lev = (CBSSTAR_level_des *)kern_alloc(sizeof(CBSSTAR_level_des));
582
 
583
#ifdef CBSSTAR_DEBUG
584
  cbsstar_printf("    lev=%d\n",(int)lev);
585
#endif
586
 
587
  /* update the level_table with the new entry */
588
  level_table[l] = (level_des *)lev;
589
 
590
  /* fill the standard descriptor */
591
  strncpy(lev->l.level_name, CBSSTAR_LEVELNAME, MAX_LEVELNAME);
592
  lev->l.level_code               = CBSSTAR_LEVEL_CODE;
593
  lev->l.level_version            = CBSSTAR_LEVEL_VERSION;
594
 
595
  lev->l.level_accept_task_model  = CBSSTAR_level_accept_task_model;
596
  lev->l.level_accept_guest_model = CBSSTAR_level_accept_guest_model;
597
  lev->l.level_status             = CBSSTAR_level_status;
598
  lev->l.level_scheduler          = CBSSTAR_level_scheduler;
599
  lev->l.level_guarantee          = CBSSTAR_level_guarantee;
600
 
601
  lev->l.task_create              = CBSSTAR_task_create;
602
  lev->l.task_detach              = CBSSTAR_task_detach;
603
  lev->l.task_eligible            = CBSSTAR_task_eligible;
604
  lev->l.task_dispatch            = CBSSTAR_task_dispatch;
605
  lev->l.task_epilogue            = CBSSTAR_task_epilogue;
606
  lev->l.task_activate            = CBSSTAR_task_activate;
607
  lev->l.task_insert              = CBSSTAR_task_insert;
608
  lev->l.task_extract             = CBSSTAR_task_extract;
609
  lev->l.task_endcycle            = CBSSTAR_task_endcycle;
610
  lev->l.task_end                 = CBSSTAR_task_end;
611
  lev->l.task_sleep               = CBSSTAR_task_sleep;
612
  lev->l.task_delay               = CBSSTAR_task_delay;
613
 
614
  lev->l.guest_create             = CBSSTAR_guest_create;
615
  lev->l.guest_detach             = CBSSTAR_guest_detach;
616
  lev->l.guest_dispatch           = CBSSTAR_guest_dispatch;
617
  lev->l.guest_epilogue           = CBSSTAR_guest_epilogue;
618
  lev->l.guest_activate           = CBSSTAR_guest_activate;
619
  lev->l.guest_insert             = CBSSTAR_guest_insert;
620
  lev->l.guest_extract            = CBSSTAR_guest_extract;
621
  lev->l.guest_endcycle           = CBSSTAR_guest_endcycle;
622
  lev->l.guest_end                = CBSSTAR_guest_end;
623
  lev->l.guest_sleep              = CBSSTAR_guest_sleep;
624
  lev->l.guest_delay              = CBSSTAR_guest_delay;
625
 
626
  /* fill the CBSSTAR descriptor part */
627
  lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
628
 
629
  for (i=0; i<n; i++) {
630
    lev->b[i].Q = 0;
631
    lev->b[i].T = 0;
632
    NULL_TIMESPEC(&lev->b[i].dline);
633
    lev->b[i].dline_timer = 0;
634
    lev->b[i].avail = 0;
635
    lev->b[i].current = -1;
636
    qq_init(&lev->b[i].tasks);
637
  }
638
 
639
  lev->n = n;
640
  lev->freebudgets = 0;
641
 
642
  for (i=0; i<MAX_PROC; i++)
643
    lev->tb[i] = NIL;
644
 
645
  lev->U = 0;
646
 
647
  lev->scheduling_level = master;
648
 
649
  return l;
650
}
651
 
652
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T)
653
{
654
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
655
 
656
#ifdef CBSSTAR_DEBUG
657
  cbsstar_printf("(C:sbud)");
658
#endif
659
 
660
  if (lev->l.level_code    == CBSSTAR_LEVEL_CODE &&
661
      lev->l.level_version == CBSSTAR_LEVEL_VERSION) {
662
    if (lev->freebudgets != lev->n) {
663
      bandwidth_t b;
664
      b = (MAX_BANDWIDTH / T) * Q;
665
 
666
      /* really update lev->U, checking an overflow... */
667
      if (Q< T && MAX_BANDWIDTH - lev->U > b) {
668
        int r = lev->freebudgets;  // the return value
669
 
670
        lev->U += b;
671
        lev->freebudgets++;
672
 
673
        lev->b[r].Q = Q;
674
        lev->b[r].T = T;
675
 
676
        return r;
677
      }
678
      else
679
        return -2;
680
    }
681
    else
682
      return -1;
683
  }
684
  else
685
    return -3;
686
}