Subversion Repositories shark

Rev

Rev 276 | Rev 278 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
241 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     :
267 giacomo 9
 *   Giacomo Guidi       <giacomo@gandalf.sssup.it>
10
 *   Michael Trimarchi   <trimarchi@gandalf.sssup.it>
241 giacomo 11
 *   (see the web pages for full authors list)
12
 *
13
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
14
 *
15
 * http://www.sssup.it
16
 * http://retis.sssup.it
17
 * http://shark.sssup.it
18
 */
19
 
20
/*
21
 * Copyright (C) 2002 Paolo Gai
22
 *
23
 * This program is free software; you can redistribute it and/or modify
24
 * it under the terms of the GNU General Public License as published by
25
 * the Free Software Foundation; either version 2 of the License, or
26
 * (at your option) any later version.
27
 *
28
 * This program is distributed in the hope that it will be useful,
29
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31
 * GNU General Public License for more details.
32
 *
33
 * You should have received a copy of the GNU General Public License
34
 * along with this program; if not, write to the Free Software
35
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
36
 *
37
 */
38
 
253 giacomo 39
#include "grubstar.h"
241 giacomo 40
 
266 trimarchi 41
//#define GRUBSTAR_DEBUG
241 giacomo 42
 
43
/* this structure contains the status for a single budget */
44
struct budget_struct {
45
  TIME Q;                 /* budget */
46
  TIME T;                 /* period */
277 giacomo 47
  bandwidth_t Ub;         /* bandwidth */
241 giacomo 48
 
49
  struct timespec dline;  /* deadline */
50
  int dline_timer;        /* oslib event for budget reactivation*/
51
  int vtimer;
52
  int avail;              /* current budget */
53
 
253 giacomo 54
  LEVEL l;                /* Current GRUBSTAR level */
241 giacomo 55
  int loc_sched_id;       /* Local scheduler id */
56
  LEVEL loc_sched_level;  /* Local scheduler level */
276 giacomo 57
 
58
  int last_reclaiming;
241 giacomo 59
 
60
  PID current;            /* the task currently put in execution */
61
  int flags;
62
 
63
  IQUEUE tasks;           /* a FIFO queue for the tasks handled
64
                             using the budget */
65
 
66
};
67
 
253 giacomo 68
#define GRUBSTAR_NOACTIVE   0
69
#define GRUBSTAR_ACTIVE     1
70
#define GRUBSTAR_RECLAIMING 2
241 giacomo 71
 
72
typedef struct {
73
  level_des l;               /* the standard level descriptor */
74
 
75
  struct budget_struct *b;   /* the budgets! */
76
  int n;                     /* the maximum index for the budgets */
77
  int freebudgets;           /* number of free budgets; starts from n */
78
 
79
  int tb[MAX_PROC];          /* link task->budget (used in guest_end) */
80
 
267 giacomo 81
  bandwidth_t U;             /*+ the used bandwidth by the server       +*/
82
  bandwidth_t Uf;            /*+ the actual used bandwidth by the server       +*/
241 giacomo 83
 
84
  int cap_lev;
85
 
86
  LEVEL scheduling_level;
87
 
253 giacomo 88
} GRUBSTAR_level_des;
241 giacomo 89
 
90
 
253 giacomo 91
static void GRUBSTAR_deadline_timer_hardreservation(void *a)
241 giacomo 92
{
93
  struct budget_struct *b = a;
94
  PID p;
253 giacomo 95
  GRUBSTAR_level_des *lev;
96
 
97
  lev = (GRUBSTAR_level_des *)(level_table[b->l]);
98
 
99
  #ifdef GRUBSTAR_DEBUG
100
    kern_printf("(GS:HrdRes:");  
241 giacomo 101
  #endif
102
 
103
  b->dline_timer = NIL;
104
 
105
  b->avail += b->Q;
106
  if (b->avail > b->Q) b->avail = b->Q;
107
 
253 giacomo 108
  if (b->flags==GRUBSTAR_RECLAIMING && b->avail>0) {
277 giacomo 109
         lev->Uf += b->Ub;
241 giacomo 110
 
253 giacomo 111
         #ifdef GRUBSTAR_DEBUG
112
              kern_printf("BW=%ld, U=%u, Uf=%u",(long)bw, lev->U, lev->Uf);
113
         #endif
114
  }
115
 
116
  if (b->avail > 0) b->flags = GRUBSTAR_ACTIVE;
117
 
241 giacomo 118
  if (b->current == NIL && b->flags) {
119
      if (iq_query_first(&(b->tasks)) != NIL) {
120
        JOB_TASK_MODEL job;
276 giacomo 121
 
241 giacomo 122
        p = iq_getfirst(&b->tasks);
123
 
253 giacomo 124
        #ifdef GRUBSTAR_DEBUG
125
          kern_printf("%d",p);
241 giacomo 126
        #endif
127
 
128
        kern_gettime(&b->dline);
129
        ADDUSEC2TIMESPEC(b->T, &b->dline);
130
 
131
        b->current = p;
132
 
133
        job_task_default_model(job, b->dline);
134
        job_task_def_noexc(job);
135
        level_table[ lev->scheduling_level ]->
136
          private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
137
 
138
        event_need_reschedule();
139
 
140
    }
141
  }
142
 
253 giacomo 143
  if (b->flags == GRUBSTAR_NOACTIVE) {
241 giacomo 144
    kern_gettime(&b->dline);
145
    ADDUSEC2TIMESPEC(b->T, &b->dline);
146
 
253 giacomo 147
    b->dline_timer=kern_event_post(&b->dline, GRUBSTAR_deadline_timer_hardreservation, b);
241 giacomo 148
  }
149
 
253 giacomo 150
  #ifdef GRUBSTAR_DEBUG
151
    kern_printf(")");
241 giacomo 152
  #endif
153
 
154
}
155
 
253 giacomo 156
void GRUBSTAR_ANC(void *arg)
241 giacomo 157
{
158
  struct budget_struct *b = arg;
253 giacomo 159
  GRUBSTAR_level_des *lev=(GRUBSTAR_level_des *)level_table[b->l];
241 giacomo 160
 
253 giacomo 161
  #ifdef GRUBSTAR_DEBUG
162
    kern_printf("(GS:Rec:");
241 giacomo 163
  #endif
164
 
165
  b->vtimer = NIL;
267 giacomo 166
  if (b->current == NIL && iq_query_first(&(b->tasks)) == NIL && b->flags != GRUBSTAR_RECLAIMING) {
277 giacomo 167
     b->flags = GRUBSTAR_RECLAIMING;
168
     lev->Uf -= b->Ub;
241 giacomo 169
 
253 giacomo 170
     #ifdef GRUBSTAR_DEBUG
171
       kern_printf("bw=%ld, U=%u, Uf=%u",(long)bw, lev->U, lev->Uf);
241 giacomo 172
     #endif
173
 
174
  }
175
 
253 giacomo 176
  #ifdef GRUBSTAR_DEBUG
177
    kern_printf(")");
241 giacomo 178
  #endif
179
 
180
 
181
}
182
 
253 giacomo 183
static void GRUBSTAR_activation(GRUBSTAR_level_des *lev,
241 giacomo 184
                           PID p,
185
                           struct timespec *acttime)
186
{
187
  JOB_TASK_MODEL job;
188
  struct budget_struct *b = &lev->b[lev->tb[p]];
253 giacomo 189
  TIME t;
190
  struct timespec t2,t3;
241 giacomo 191
 
253 giacomo 192
  t = (b->T * b->avail) / b->Q;
193
  t3.tv_sec = t / 1000000;
194
  t3.tv_nsec = (t % 1000000) * 1000;
241 giacomo 195
 
275 trimarchi 196
  if (b->vtimer!=NIL) kern_event_delete(b->vtimer);
197
  b->vtimer=NIL;
198
 
253 giacomo 199
  SUBTIMESPEC(&b->dline, acttime, &t2);
200
  if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) ||
241 giacomo 201
       /* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
202
       TIMESPEC_ASSIGN(&b->dline, acttime);
203
       ADDUSEC2TIMESPEC(b->T, &b->dline);
204
       b->avail=b->Q;
276 giacomo 205
 
206
  }
207
 
208
  if (b->flags==GRUBSTAR_RECLAIMING) {
277 giacomo 209
    lev->Uf += b->Ub;
241 giacomo 210
 
276 giacomo 211
    #ifdef grubSTAR_DEBUG
212
      kern_printf("BW=%ld, U=%u, Uf=%u",(long)bw, lev->U, lev->Uf);
213
    #endif
241 giacomo 214
 
276 giacomo 215
  }
241 giacomo 216
 
276 giacomo 217
  b->flags=GRUBSTAR_ACTIVE;
241 giacomo 218
 
219
 
220
  /* record the current task inserted in the master module */
221
  b->current = p;
275 trimarchi 222
 
241 giacomo 223
  job_task_default_model(job, b->dline);
224
  job_task_def_noexc(job);
225
  level_table[ lev->scheduling_level ]->
226
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
227
 
228
}
229
 
253 giacomo 230
static void GRUBSTAR_account_capacity(GRUBSTAR_level_des *lev, PID p)
241 giacomo 231
{
232
  struct timespec ty;
233
  TIME tx;
234
  struct budget_struct *b = &lev->b[lev->tb[p]];
276 giacomo 235
  TIME t;
236
  struct timespec t2,t3;
241 giacomo 237
 
276 giacomo 238
 
239
  if (b->vtimer!=NIL) kern_event_delete(b->vtimer);
240
  b->vtimer=NIL;
241
 
241 giacomo 242
  if (lev->cap_lev != NIL && b->current == p) {
243
    kern_event_delete(lev->cap_lev);
244
    lev->cap_lev = NIL;
245
  }
246
 
247
  SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
248
  tx = TIMESPEC2USEC(&ty);
266 trimarchi 249
  #ifdef GRUBSTAR_DEBUG
250
      kern_printf("(GS:Cap p%d av=%d)", p, b->avail);
251
  #endif
241 giacomo 252
 
276 giacomo 253
  b->last_reclaiming = (unsigned int)((long long)(tx) * (long long)(lev->U - lev->Uf)/MAX_BANDWIDTH);
266 trimarchi 254
 
276 giacomo 255
  b->avail -= tx - b->last_reclaiming;
267 giacomo 256
 
253 giacomo 257
  #ifdef GRUBSTAR_DEBUG
273 giacomo 258
    kern_printf("(GS:Cap p%d av=%d Uf=%u U=%u, tx=%d)", p, b->avail,lev->Uf, lev->U,(int)tx);
241 giacomo 259
  #endif
260
 
253 giacomo 261
  if (b->avail <= 0) b->flags = GRUBSTAR_NOACTIVE;
241 giacomo 262
 
263
  if (TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
264
    /* we modify the deadline ... */
265
    TIMESPEC_ASSIGN(&b->dline, &schedule_time);
266
    ADDUSEC2TIMESPEC(b->T, &b->dline);
267
  }
268
 
253 giacomo 269
  if (b->flags == GRUBSTAR_NOACTIVE && b->dline_timer == NIL)  {
270
    b->dline_timer=kern_event_post(&b->dline, GRUBSTAR_deadline_timer_hardreservation, b);
276 giacomo 271
  } else {
272
    t = (b->T * b->avail) / b->Q;
273
    t3.tv_sec = t / 1000000;
274
    t3.tv_nsec = (t % 1000000) * 1000;
275
    SUBTIMESPEC(&b->dline, &t3, &t2);
276
    b->vtimer = kern_event_post(&t2, GRUBSTAR_ANC, b);
241 giacomo 277
  }
278
}
279
 
280
 
281
/* The on-line guarantee is enabled only if the appropriate flag is set... */
253 giacomo 282
static int GRUBSTAR_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
241 giacomo 283
{
253 giacomo 284
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 285
 
253 giacomo 286
  #ifdef GRUBSTAR_DEBUG
287
    kern_printf("(GS:Gua)");
241 giacomo 288
  #endif
289
 
290
  if (*freebandwidth >= lev->U) {
291
    *freebandwidth -= lev->U;
292
    return 1;
293
  }
294
  else
295
    return 0;
296
}
297
 
298
static void capacity_handler(void *l)
299
{
300
 
253 giacomo 301
  GRUBSTAR_level_des *lev = l;
241 giacomo 302
  lev->cap_lev = NIL;
303
  event_need_reschedule();
304
 
305
}
306
 
253 giacomo 307
static int GRUBSTAR_private_eligible(LEVEL l, PID p)
241 giacomo 308
{
253 giacomo 309
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 310
  struct budget_struct *b = &lev->b[lev->tb[p]];
311
  JOB_TASK_MODEL job;
312
 
313
  if (b->current == p) {
314
    if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
315
      if (lev->cap_lev!=NIL) {
316
        kern_event_delete(lev->cap_lev);
317
        lev->cap_lev=NIL;
318
      }
319
 
320
      /* we kill the current activation */
321
      level_table[ lev->scheduling_level ]->
322
        private_extract(lev->scheduling_level, p);
323
      /* we modify the deadline ... */
324
      TIMESPEC_ASSIGN(&b->dline, &schedule_time);
325
      ADDUSEC2TIMESPEC(b->T, &b->dline);
326
 
327
      /* and the capacity */
328
      b->avail = b->Q;
276 giacomo 329
 
330
      if (b->flags == GRUBSTAR_RECLAIMING) {
277 giacomo 331
        lev->Uf += b->Ub;
276 giacomo 332
      }
333
 
253 giacomo 334
      b->flags = GRUBSTAR_ACTIVE;
241 giacomo 335
 
336
      if (b->dline_timer!=NIL)  {
337
        kern_event_delete(b->dline_timer);
338
        b->dline_timer=NIL;
339
      }
275 trimarchi 340
 
341
      if (b->vtimer!=NIL)  {
342
            kern_event_delete(b->vtimer);
343
            b->vtimer=NIL;
344
      }
345
 
241 giacomo 346
 
347
      /* and, finally, we reinsert the task in the master level */
348
      job_task_default_model(job, b->dline);
349
      job_task_def_noexc(job);
350
      level_table[ lev->scheduling_level ]->
351
        private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
352
 
353
      return -1;
354
 
355
    }  
356
  }
357
 
358
  return 0;
359
 
360
}
361
 
253 giacomo 362
static void GRUBSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
241 giacomo 363
{
253 giacomo 364
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 365
  BUDGET_TASK_MODEL *budget;
366
 
367
  if (m->pclass != BUDGET_PCLASS ||
368
      (m->level != 0 && m->level != l)) {
369
    kern_raise(XINVALID_TASK, p);
370
    return;
371
  }
372
  budget = (BUDGET_TASK_MODEL *)m;
373
 
253 giacomo 374
  #ifdef GRUBSTAR_DEBUG
375
    kern_printf("(GS:PriIns:%d:%d", p, budget->b);
241 giacomo 376
  #endif
377
 
378
  if (budget->b == -1)
379
    return;
380
 
381
  lev->tb[p] = budget->b;
382
 
383
  if (lev->b[budget->b].current == NIL && lev->b[budget->b].flags ) {
384
    /* This is the first task in the budget,
385
       the task have to be inserted into the master module */
386
    struct timespec t;
387
    kern_gettime(&t);
253 giacomo 388
    GRUBSTAR_activation(lev,p,&t);
241 giacomo 389
  } else {
390
    /* The budget is not empty, another task is already into the
391
       master module, so the task is inserted at the end of the budget
392
       queue */
393
    iq_insertlast(p,&lev->b[budget->b].tasks);
394
  }
395
 
253 giacomo 396
  #ifdef GRUBSTAR_DEBUG
397
    kern_printf(")");
241 giacomo 398
  #endif
399
 
400
}
401
 
253 giacomo 402
static void GRUBSTAR_private_extract(LEVEL l, PID p)
241 giacomo 403
{
253 giacomo 404
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 405
 
253 giacomo 406
  #ifdef GRUBSTAR_DEBUG
407
    kern_printf("(GS:Ext:%d)", p);
241 giacomo 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
 
414
  /* remove the task from execution (or from the ready queue) */
415
  if (lev->b[lev->tb[p]].current == p) {
416
 
253 giacomo 417
   GRUBSTAR_account_capacity(lev,p);
241 giacomo 418
    /* remove the task from the master module */
419
    level_table[ lev->scheduling_level ]->
420
      private_extract(lev->scheduling_level, p);
421
 
422
    /* check if the buffer has someone else to schedule */
423
    if (iq_query_first(&lev->b[lev->tb[p]].tasks) == NIL) {
424
      /* the buffer has no tasks! */
425
      lev->b[lev->tb[p]].current = NIL;
426
    }
427
    else if (lev->b[lev->tb[p]].flags) {
428
      /* if so, insert the new task into the master module */
429
      PID n;
430
      struct timespec t;
431
 
432
      kern_gettime(&t);
433
      n = iq_getfirst(&lev->b[lev->tb[p]].tasks);
253 giacomo 434
      GRUBSTAR_activation(lev,n,&t);  // it modifies b[lev->tb[p]].current
241 giacomo 435
    }
436
    else
437
      lev->b[lev->tb[p]].current=NIL;
438
 
439
  }
440
  else  {
441
    iq_extract(p, &lev->b[lev->tb[p]].tasks);
442
  }
443
}
444
 
253 giacomo 445
static void GRUBSTAR_private_dispatch(LEVEL l, PID p, int nostop)
241 giacomo 446
{
253 giacomo 447
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 448
  struct timespec ty;
449
 
253 giacomo 450
  #ifdef GRUBSTAR_DEBUG
451
    kern_printf("(GS:Dsp:%d)", p);
241 giacomo 452
  #endif
453
 
454
  /* the current task (that is the only one inserted in the master module
455
     for the corresponding budget) is dispatched. Note that the current
456
     task is not inserted in any FIFO queue, so the task does not have to
457
     be extracted! */
458
 
459
  /* ... then, we dispatch it to the master level */
460
  level_table[ lev->scheduling_level ]->
461
    private_dispatch(lev->scheduling_level,p,nostop);
462
 
463
  /* ...and finally, we have to post a capacity event */
464
  if (!nostop) {
465
    TIMESPEC_ASSIGN(&ty, &schedule_time);
466
    ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty);
467
    lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
468
  }
469
 
470
}
471
 
253 giacomo 472
static void GRUBSTAR_private_epilogue(LEVEL l, PID p)
241 giacomo 473
{
253 giacomo 474
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 475
  struct budget_struct *b = &lev->b[lev->tb[p]];
476
 
253 giacomo 477
  #ifdef GRUBSTAR_DEBUG
254 giacomo 478
    kern_printf("(GS:Epi:%d)",p);
241 giacomo 479
  #endif
480
 
481
  if (p==b->current)  {
482
 
253 giacomo 483
    GRUBSTAR_account_capacity(lev,p);
241 giacomo 484
 
485
    // L'evento di capacità va cancellato perchè sarà ripristinato nella successiva dispatch
486
    /* we have to check if the capacity is still available */
487
    if (b->flags)  {
276 giacomo 488
 
241 giacomo 489
      /* there is capacity available, maybe it is simply a preemption;
490
         the task have to return to the ready queue */
491
      level_table[ lev->scheduling_level ]->
492
        private_epilogue(lev->scheduling_level,p);
493
 
494
    } else {
495
      /* we kill the current activation */
496
      level_table[ lev->scheduling_level ]->
497
        private_extract(lev->scheduling_level, p);    
498
 
499
      iq_insertfirst(p, &b->tasks);
500
      b->current = NIL;
501
 
502
    }
503
 
504
  }
505
 
506
}
507
 
267 giacomo 508
static int GRUBSTAR_public_message(LEVEL l, PID p, void *m)
509
{
510
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
511
  struct budget_struct *b = &lev->b[lev->tb[p]];
512
 
513
  switch((long)(m)) {
514
 
515
    case (long)(NULL):
516
 
517
      if (b->current == NIL && iq_query_first(&(b->tasks)) == NIL && b->flags != GRUBSTAR_RECLAIMING) {
518
        b->flags = GRUBSTAR_RECLAIMING;
277 giacomo 519
        lev->Uf -= b->Ub;
267 giacomo 520
      }
521
 
522
      break;
523
 
524
    case 1:
525
 
526
      break;
527
 
528
  }
529
 
530
  return 0;
531
 
532
}
533
 
241 giacomo 534
/* Registration functions }*/
535
 
253 giacomo 536
LEVEL GRUBSTAR_register_level(int n, LEVEL master)
241 giacomo 537
{
538
  LEVEL l;            /* the level that we register */
253 giacomo 539
  GRUBSTAR_level_des *lev;  /* for readableness only */
241 giacomo 540
  PID i;              /* a counter */
541
 
253 giacomo 542
  printk("GRUBSTAR_register_level\n");
241 giacomo 543
 
544
  /* request an entry in the level_table */
253 giacomo 545
  l = level_alloc_descriptor(sizeof(GRUBSTAR_level_des));
241 giacomo 546
 
253 giacomo 547
  lev = (GRUBSTAR_level_des *)level_table[l];
241 giacomo 548
 
549
  /* fill the standard descriptor */
253 giacomo 550
  lev->l.private_insert   = GRUBSTAR_private_insert;
551
  lev->l.private_extract  = GRUBSTAR_private_extract;
552
  lev->l.private_eligible = GRUBSTAR_private_eligible;
553
  lev->l.private_dispatch = GRUBSTAR_private_dispatch;
554
  lev->l.private_epilogue = GRUBSTAR_private_epilogue;
241 giacomo 555
 
253 giacomo 556
  lev->l.public_guarantee = GRUBSTAR_public_guarantee;
267 giacomo 557
  lev->l.public_message = GRUBSTAR_public_message;
241 giacomo 558
 
559
  lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
560
 
561
  for (i=0; i<n; i++) {
562
    lev->b[i].Q = 0;
563
    lev->b[i].T = 0;
277 giacomo 564
    lev->b[i].Ub = 0;
241 giacomo 565
    NULL_TIMESPEC(&lev->b[i].dline);
566
    lev->b[i].dline_timer = NIL;
253 giacomo 567
    lev->b[i].vtimer=NIL;
241 giacomo 568
    lev->b[i].avail = 0;
569
    lev->b[i].current = -1;
253 giacomo 570
    lev->b[i].flags = GRUBSTAR_ACTIVE;
276 giacomo 571
    lev->b[i].l = l;
572
    lev->b[i].last_reclaiming = 0;
253 giacomo 573
    iq_init(&lev->b[i].tasks, NULL, 0);
241 giacomo 574
  }
575
 
576
  lev->n = n;
577
  lev->freebudgets = 0;
578
 
579
  for (i=0; i<MAX_PROC; i++)
580
    lev->tb[i] = NIL;
581
 
582
  lev->U = 0;
583
  lev->Uf = 0;
584
  lev->cap_lev = NIL;
585
  lev->scheduling_level = master;
586
 
587
  return l;
588
 
589
}
590
 
253 giacomo 591
int GRUBSTAR_setbudget(LEVEL l, TIME Q, TIME T, LEVEL local_scheduler_level, int scheduler_id)
241 giacomo 592
{
253 giacomo 593
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 594
  int r;
595
 
253 giacomo 596
  #ifdef GRUBSTAR_DEBUG
597
    kern_printf("(GS:SetBud)");
241 giacomo 598
  #endif
599
 
600
  for (r = 0; r < lev->n; r++)
601
    if (lev->b[r].Q == 0) break;
602
 
603
  if (r != lev->n) {
604
    bandwidth_t b;
605
    b = (MAX_BANDWIDTH / T) * Q;
606
 
607
    /* really update lev->U, checking an overflow... */
608
    if (Q< T && MAX_BANDWIDTH - lev->U > b) {
609
 
610
      lev->U += b;
611
      lev->Uf += b;
612
      lev->freebudgets++;
613
 
614
      lev->b[r].Q = Q;
615
      lev->b[r].T = T;
277 giacomo 616
      lev->b[r].Ub = b;
241 giacomo 617
      lev->b[r].avail = Q;
253 giacomo 618
      lev->b[r].flags = GRUBSTAR_ACTIVE;
241 giacomo 619
      lev->b[r].loc_sched_id = scheduler_id;
620
      lev->b[r].loc_sched_level = local_scheduler_level;
276 giacomo 621
      lev->b[r].last_reclaiming = 0;  
622
 
241 giacomo 623
      return r;
624
    }
625
    else
626
      return -2;
627
  }
628
  else
629
    return -1;
630
}
631
 
253 giacomo 632
int GRUBSTAR_removebudget(LEVEL l, int budget)
241 giacomo 633
{
634
 
253 giacomo 635
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 636
 
637
  bandwidth_t b;
638
 
639
  b = (MAX_BANDWIDTH / lev->b[budget].T) * lev->b[budget].Q;
640
 
641
  lev->U -= b;
642
 
643
  lev->b[budget].Q = 0;
644
  lev->b[budget].T = 0;
277 giacomo 645
  lev->b[budget].Ub = 0;
241 giacomo 646
  NULL_TIMESPEC(&lev->b[budget].dline);
647
  lev->b[budget].dline_timer = NIL;
648
  lev->b[budget].avail = 0;
649
  lev->b[budget].current = -1;
253 giacomo 650
  lev->b[budget].flags = GRUBSTAR_ACTIVE;
277 giacomo 651
  lev->b[budget].last_reclaiming = 0;
241 giacomo 652
 
653
  return 0;
654
 
655
}
656
 
253 giacomo 657
int GRUBSTAR_adjust_budget(LEVEL l, TIME Q, TIME T, int budget)
241 giacomo 658
{
659
 
253 giacomo 660
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 661
 
662
  lev->b[budget].Q = Q;
663
  lev->b[budget].T = T;
277 giacomo 664
  lev->b[budget].Ub = (MAX_BANDWIDTH / T) * Q;
241 giacomo 665
 
666
  return 0;
667
 
668
}
669
 
253 giacomo 670
int GRUBSTAR_getbudgetinfo(LEVEL l, TIME *Q, TIME *T, int budget)
241 giacomo 671
{
672
 
253 giacomo 673
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 674
 
675
  *Q = lev->b[budget].Q;
676
  *T = lev->b[budget].T;
677
 
678
  return 0;
679
 
680
}
681
 
276 giacomo 682
int GRUBSTAR_get_last_reclaiming(LEVEL l, PID p)
267 giacomo 683
{
684
 
685
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
686
 
276 giacomo 687
  return lev->b[lev->tb[p]].last_reclaiming;
267 giacomo 688
 
689
}
690
 
253 giacomo 691
int GRUBSTAR_is_active(LEVEL l, int budget)
241 giacomo 692
{
253 giacomo 693
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 694
 
695
  return lev->b[budget].flags;
696
 
697
}
698
 
253 giacomo 699
int GRUBSTAR_get_local_scheduler_level_from_budget(LEVEL l, int budget)
241 giacomo 700
{
253 giacomo 701
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 702
 
703
  return lev->b[budget].loc_sched_level;
704
 
705
}
706
 
253 giacomo 707
int GRUBSTAR_get_local_scheduler_level_from_pid(LEVEL l, PID p)
241 giacomo 708
{
253 giacomo 709
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 710
 
711
  return lev->b[lev->tb[p]].loc_sched_level;
712
 
713
}
714
 
253 giacomo 715
int GRUBSTAR_get_local_scheduler_id_from_budget(LEVEL l, int budget)
241 giacomo 716
{
253 giacomo 717
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 718
 
719
  return lev->b[budget].loc_sched_id;
720
 
721
}
722
 
253 giacomo 723
int GRUBSTAR_get_local_scheduler_id_from_pid(LEVEL l, PID p)
241 giacomo 724
{
253 giacomo 725
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 726
 
727
  return lev->b[lev->tb[p]].loc_sched_id;
728
 
729
}
730