Subversion Repositories shark

Rev

Rev 1100 | Rev 1123 | Go to most recent revision | Details | Compare with Previous | 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
 ------------
1116 pj 23
 CVS :        $Id: cbsstar.c,v 1.3 2002-11-11 08:17:59 pj Exp $
1089 pj 24
 
25
 File:        $File$
1116 pj 26
 Revision:    $Revision: 1.3 $
27
 Last update: $Date: 2002-11-11 08:17:59 $
1089 pj 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
 
1116 pj 133
  IQUEUE tasks;           /* a FIFO queue for the tasks handled
1089 pj 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
{
1100 pj 277
  kern_raise(XINVALID_TASK,exec_shadow);
1089 pj 278
  return 0; /* OK, also if the task cannot be guaranteed... */
279
}
280
 
281
static void CBSSTAR_task_detach(LEVEL l, PID p)
1100 pj 282
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 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)
1100 pj 340
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 341
 
342
static void CBSSTAR_task_epilogue(LEVEL l, PID p)
1100 pj 343
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 344
 
345
static void CBSSTAR_task_activate(LEVEL l, PID p)
1100 pj 346
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 347
 
348
static void CBSSTAR_task_insert(LEVEL l, PID p)
1100 pj 349
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 350
 
351
static void CBSSTAR_task_extract(LEVEL l, PID p)
1100 pj 352
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 353
 
354
static void CBSSTAR_task_endcycle(LEVEL l, PID p)
1100 pj 355
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 356
 
357
static void CBSSTAR_task_end(LEVEL l, PID p)
1100 pj 358
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 359
 
360
static void CBSSTAR_task_sleep(LEVEL l, PID p)
1100 pj 361
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 362
 
363
static int CBSSTAR_guest_create(LEVEL l, PID p, TASK_MODEL *m)
364
{
365
  /* A task has been activated for some reason. Basically, the task is
366
  inserted in the queue if the queue is empty, otherwise the task is
367
  inserted into the master module, and an oslib event is posted. */
368
 
369
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
370
  BUDGET_TASK_MODEL *budget = (BUDGET_TASK_MODEL *)m;
371
 
372
#ifdef CBSSTAR_DEBUG
373
  cbsstar_printf("(C:gcr %d b%d", p, budget->b);
374
#endif
375
 
376
  lev->tb[p] = budget->b;
377
 
378
  if (lev->b[budget->b].current == NIL) {
379
    /* This is the first task in the budget,
380
       the task have to be inserted into the master module */
381
    struct timespec t;
382
    ll_gettime(TIME_EXACT, &t);
383
    CBSSTAR_activation(lev,p,&t);
384
  } else {
385
    /* The budget is not empty, another task is already into the
386
       master module, so the task is inserted at the end of the budget
387
       queue */
1116 pj 388
    iq_insertlast(p,&lev->b[budget->b].tasks);
1089 pj 389
#ifdef CBSSTAR_DEBUG
390
    cbsstar_printf(" ilast");
391
    cbsstar_printq(&lev->b[budget->b].tasks);
392
#endif
393
  }
394
#ifdef CBSSTAR_DEBUG
395
  cbsstar_printf(")");
396
#endif
397
 
398
  return 0;
399
}
400
 
401
static void CBSSTAR_guest_end(LEVEL l, PID p)
402
{
403
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
404
 
405
#ifdef CBSSTAR_DEBUG
406
  cbsstar_printf("(C:gend p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
407
  cbsstar_printq(&lev->b[lev->tb[p]].tasks);
408
#endif
409
 
410
  /* a task is removed from execution for some reasons. It must be
411
     that it is the first in its budget queue (only the first task in
412
     a budget queue is put into execution!) */
413
  CBSSTAR_account_capacity(lev,p);
414
 
415
  /* remove the task from execution (or from the ready queue) */
416
  if (lev->b[lev->tb[p]].current == p) {
417
    /* remove the task from the master module */
418
    level_table[ lev->scheduling_level ]->
419
      guest_end(lev->scheduling_level, p);
420
 
421
#ifdef CBSSTAR_DEBUG
422
    cbsstar_printq(&lev->b[lev->tb[p]].tasks);
423
#endif
424
 
425
    /* check if the buffer has someone else to schedule */
1116 pj 426
    if (iq_query_first(&lev->b[lev->tb[p]].tasks) == NIL) {
1089 pj 427
      /* the buffer has no tasks! */
428
      lev->b[lev->tb[p]].current = NIL;
429
    }
430
    else {
431
      /* if so, insert the new task into the master module */
432
      PID n;
433
      struct timespec t;
434
 
435
      ll_gettime(TIME_EXACT, &t);
1116 pj 436
      n = iq_getfirst(&lev->b[lev->tb[p]].tasks);
1089 pj 437
#ifdef CBSSTAR_DEBUG
438
      cbsstar_printf("{p%d n%d}",p,n);
439
#endif
440
      CBSSTAR_activation(lev,n,&t);  // it modifies b[lev->tb[p]].current
441
    }
442
  }
443
  else
1116 pj 444
    iq_extract(p, &lev->b[lev->tb[p]].tasks);
1089 pj 445
}
446
 
447
static void CBSSTAR_guest_dispatch(LEVEL l, PID p, int nostop)
448
{
449
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
450
  struct timespec ty;
451
 
452
#ifdef CBSSTAR_DEBUG
453
  cbsstar_printf("(C:gdisp p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
454
  cbsstar_printq(&lev->b[lev->tb[p]].tasks);
455
#endif
456
 
457
  /* the current task (that is the only one inserted in the master module
458
     for the corresponding budget) is dispatched. Note that the current
459
     task is not inserted in any FIFO queue, so the task does not have to
460
     be extracted! */
461
 
462
  /* ... then, we dispatch it to the master level */
463
  level_table[ lev->scheduling_level ]->
464
    guest_dispatch(lev->scheduling_level,p,nostop);
465
 
466
  /* ...and finally, we have to post a capacity event */
467
  if (!nostop) {
468
    TIMESPEC_ASSIGN(&ty, &schedule_time);
469
    ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty);
470
    cap_timer = kern_event_post(&ty, capacity_timer, NULL);
471
  }
472
}
473
 
474
static void CBSSTAR_guest_epilogue(LEVEL l, PID p)
475
{
476
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
477
  struct budget_struct *b = &lev->b[lev->tb[p]];
478
 
479
#ifdef CBSSTAR_DEBUG
480
  cbsstar_printf("(C:gepi %d",p);
481
#endif
482
 
483
  CBSSTAR_account_capacity(lev,p);
484
 
485
  /* we have to check if the capacity is still available */
486
  if (b->avail > 0) {
487
    /* there is capacity available, maybe it is simply a preemption;
488
       the task have to return to the ready queue */
489
    level_table[ lev->scheduling_level ]->
490
      guest_epilogue(lev->scheduling_level,p);
491
#ifdef CBSSTAR_DEBUG
492
    cbsstar_printf2(" *av=%d", b->avail);
493
#endif
494
  } else {
495
    /* The capacity is exausted; the deadline have to be postponed and
496
       the task have to be reinserted in the master module */
497
    JOB_TASK_MODEL job;
498
 
499
    /* we kill the current activation */
500
    level_table[ lev->scheduling_level ]->
501
      guest_end(lev->scheduling_level, p);
502
 
503
    /* we modify the deadline according to rule 4 ... */
504
    /* there is a while because if the wcet is << than the system tick
505
       we need to postpone the deadline many times */
506
    while (b->avail <= 0) {
507
      ADDUSEC2TIMESPEC(b->T, &b->dline);
508
      b->avail += b->Q;
509
#ifdef CBSSTAR_DEBUG
510
      cbsstar_printf3("±%d±",lev->tb[p]);
511
      cbsstar_printblob(lev->tb[p]);
512
#endif
513
    }
514
 
515
#ifdef CBSSTAR_DEBUG
516
    cbsstar_printf2(" %ld.%ld av=%d",b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
517
#endif
518
 
519
    /* and, finally, we reinsert the task in the master level */
520
    job_task_default_model(job, b->dline);
521
    job_task_def_noexc(job);
522
    level_table[ lev->scheduling_level ]->
523
      guest_create(lev->scheduling_level, p, (TASK_MODEL *)&job);
524
    level_table[ lev->scheduling_level ]->
525
      guest_activate(lev->scheduling_level, p);
526
  }
527
#ifdef CBSSTAR_DEBUG
528
  cbsstar_printf(")");
529
#endif
530
}
531
 
532
static void CBSSTAR_guest_detach(LEVEL l, PID p)
1100 pj 533
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 534
 
535
static void CBSSTAR_guest_activate(LEVEL l, PID p)
1100 pj 536
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 537
 
538
static void CBSSTAR_guest_insert(LEVEL l, PID p)
1100 pj 539
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 540
 
541
static void CBSSTAR_guest_extract(LEVEL l, PID p)
1100 pj 542
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 543
 
544
static void CBSSTAR_guest_endcycle(LEVEL l, PID p)
1100 pj 545
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 546
 
547
static void CBSSTAR_guest_sleep(LEVEL l, PID p)
1100 pj 548
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 549
 
550
 
551
 
552
 
553
/* Registration functions */
554
 
555
/*+ Registration function:
556
    int flags                 the init flags ... see CBSSTAR.h +*/
557
LEVEL CBSSTAR_register_level(int n, LEVEL master)
558
{
559
  LEVEL l;            /* the level that we register */
560
  CBSSTAR_level_des *lev;  /* for readableness only */
561
  PID i;              /* a counter */
562
 
563
#ifdef CBSSTAR_DEBUG
564
  cbsstar_printf("CBSSTAR_register_level\n");
565
#endif
566
 
567
  /* request an entry in the level_table */
568
  l = level_alloc_descriptor();
569
 
570
#ifdef CBSSTAR_DEBUG
571
  cbsstar_printf("    alloco descrittore %d %d\n",l,(int)sizeof(CBSSTAR_level_des));
572
#endif
573
 
574
  /* alloc the space needed for the CBSSTAR_level_des */
575
  lev = (CBSSTAR_level_des *)kern_alloc(sizeof(CBSSTAR_level_des));
576
 
577
#ifdef CBSSTAR_DEBUG
578
  cbsstar_printf("    lev=%d\n",(int)lev);
579
#endif
580
 
581
  /* update the level_table with the new entry */
582
  level_table[l] = (level_des *)lev;
583
 
584
  /* fill the standard descriptor */
585
  strncpy(lev->l.level_name, CBSSTAR_LEVELNAME, MAX_LEVELNAME);
586
  lev->l.level_code               = CBSSTAR_LEVEL_CODE;
587
  lev->l.level_version            = CBSSTAR_LEVEL_VERSION;
588
 
589
  lev->l.level_accept_task_model  = CBSSTAR_level_accept_task_model;
590
  lev->l.level_accept_guest_model = CBSSTAR_level_accept_guest_model;
591
  lev->l.level_status             = CBSSTAR_level_status;
592
  lev->l.level_scheduler          = CBSSTAR_level_scheduler;
593
  lev->l.level_guarantee          = CBSSTAR_level_guarantee;
594
 
595
  lev->l.task_create              = CBSSTAR_task_create;
596
  lev->l.task_detach              = CBSSTAR_task_detach;
597
  lev->l.task_eligible            = CBSSTAR_task_eligible;
598
  lev->l.task_dispatch            = CBSSTAR_task_dispatch;
599
  lev->l.task_epilogue            = CBSSTAR_task_epilogue;
600
  lev->l.task_activate            = CBSSTAR_task_activate;
601
  lev->l.task_insert              = CBSSTAR_task_insert;
602
  lev->l.task_extract             = CBSSTAR_task_extract;
603
  lev->l.task_endcycle            = CBSSTAR_task_endcycle;
604
  lev->l.task_end                 = CBSSTAR_task_end;
605
  lev->l.task_sleep               = CBSSTAR_task_sleep;
606
 
607
  lev->l.guest_create             = CBSSTAR_guest_create;
608
  lev->l.guest_detach             = CBSSTAR_guest_detach;
609
  lev->l.guest_dispatch           = CBSSTAR_guest_dispatch;
610
  lev->l.guest_epilogue           = CBSSTAR_guest_epilogue;
611
  lev->l.guest_activate           = CBSSTAR_guest_activate;
612
  lev->l.guest_insert             = CBSSTAR_guest_insert;
613
  lev->l.guest_extract            = CBSSTAR_guest_extract;
614
  lev->l.guest_endcycle           = CBSSTAR_guest_endcycle;
615
  lev->l.guest_end                = CBSSTAR_guest_end;
616
  lev->l.guest_sleep              = CBSSTAR_guest_sleep;
617
 
618
  /* fill the CBSSTAR descriptor part */
619
  lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
620
 
621
  for (i=0; i<n; i++) {
622
    lev->b[i].Q = 0;
623
    lev->b[i].T = 0;
624
    NULL_TIMESPEC(&lev->b[i].dline);
625
    lev->b[i].dline_timer = 0;
626
    lev->b[i].avail = 0;
627
    lev->b[i].current = -1;
1116 pj 628
    iq_init(&lev->b[i].tasks, &freedesc, 0);
1089 pj 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
 
639
  lev->scheduling_level = master;
640
 
641
  return l;
642
}
643
 
644
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T)
645
{
646
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
647
 
648
#ifdef CBSSTAR_DEBUG
649
  cbsstar_printf("(C:sbud)");
650
#endif
651
 
652
  if (lev->l.level_code    == CBSSTAR_LEVEL_CODE &&
653
      lev->l.level_version == CBSSTAR_LEVEL_VERSION) {
654
    if (lev->freebudgets != lev->n) {
655
      bandwidth_t b;
656
      b = (MAX_BANDWIDTH / T) * Q;
657
 
658
      /* really update lev->U, checking an overflow... */
659
      if (Q< T && MAX_BANDWIDTH - lev->U > b) {
660
        int r = lev->freebudgets;  // the return value
661
 
662
        lev->U += b;
663
        lev->freebudgets++;
664
 
665
        lev->b[r].Q = Q;
666
        lev->b[r].T = T;
667
 
668
        return r;
669
      }
670
      else
671
        return -2;
672
    }
673
    else
674
      return -1;
675
  }
676
  else
677
    return -3;
678
}