Subversion Repositories shark

Rev

Rev 279 | Rev 287 | 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;
279 giacomo 85
  struct timespec cap_lasttime;
241 giacomo 86
 
87
  LEVEL scheduling_level;
88
 
253 giacomo 89
} GRUBSTAR_level_des;
241 giacomo 90
 
91
 
253 giacomo 92
static void GRUBSTAR_deadline_timer_hardreservation(void *a)
241 giacomo 93
{
94
  struct budget_struct *b = a;
95
  PID p;
253 giacomo 96
  GRUBSTAR_level_des *lev;
97
 
98
  lev = (GRUBSTAR_level_des *)(level_table[b->l]);
99
 
100
  #ifdef GRUBSTAR_DEBUG
101
    kern_printf("(GS:HrdRes:");  
241 giacomo 102
  #endif
103
 
104
  b->dline_timer = NIL;
105
 
106
  b->avail += b->Q;
107
  if (b->avail > b->Q) b->avail = b->Q;
108
 
278 giacomo 109
  if (b->flags==GRUBSTAR_RECLAIMING && b->avail>0)
110
    lev->Uf += b->Ub;
241 giacomo 111
 
253 giacomo 112
  if (b->avail > 0) b->flags = GRUBSTAR_ACTIVE;
113
 
241 giacomo 114
  if (b->current == NIL && b->flags) {
115
      if (iq_query_first(&(b->tasks)) != NIL) {
116
        JOB_TASK_MODEL job;
276 giacomo 117
 
241 giacomo 118
        p = iq_getfirst(&b->tasks);
119
 
253 giacomo 120
        #ifdef GRUBSTAR_DEBUG
121
          kern_printf("%d",p);
241 giacomo 122
        #endif
123
 
124
        ADDUSEC2TIMESPEC(b->T, &b->dline);
125
 
126
        b->current = p;
127
 
128
        job_task_default_model(job, b->dline);
129
        job_task_def_noexc(job);
130
        level_table[ lev->scheduling_level ]->
131
          private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
132
 
133
        event_need_reschedule();
134
 
135
    }
136
  }
137
 
253 giacomo 138
  if (b->flags == GRUBSTAR_NOACTIVE) {
241 giacomo 139
    kern_gettime(&b->dline);
140
    ADDUSEC2TIMESPEC(b->T, &b->dline);
141
 
253 giacomo 142
    b->dline_timer=kern_event_post(&b->dline, GRUBSTAR_deadline_timer_hardreservation, b);
241 giacomo 143
  }
144
 
253 giacomo 145
  #ifdef GRUBSTAR_DEBUG
146
    kern_printf(")");
241 giacomo 147
  #endif
148
 
149
}
150
 
253 giacomo 151
void GRUBSTAR_ANC(void *arg)
241 giacomo 152
{
153
  struct budget_struct *b = arg;
253 giacomo 154
  GRUBSTAR_level_des *lev=(GRUBSTAR_level_des *)level_table[b->l];
241 giacomo 155
 
253 giacomo 156
  #ifdef GRUBSTAR_DEBUG
157
    kern_printf("(GS:Rec:");
241 giacomo 158
  #endif
159
 
160
  b->vtimer = NIL;
267 giacomo 161
  if (b->current == NIL && iq_query_first(&(b->tasks)) == NIL && b->flags != GRUBSTAR_RECLAIMING) {
277 giacomo 162
     b->flags = GRUBSTAR_RECLAIMING;
163
     lev->Uf -= b->Ub;
241 giacomo 164
 
253 giacomo 165
     #ifdef GRUBSTAR_DEBUG
278 giacomo 166
       kern_printf("U=%u, Uf=%u",lev->U, lev->Uf);
241 giacomo 167
     #endif
168
 
169
  }
170
 
253 giacomo 171
  #ifdef GRUBSTAR_DEBUG
172
    kern_printf(")");
241 giacomo 173
  #endif
174
 
175
 
176
}
177
 
253 giacomo 178
static void GRUBSTAR_activation(GRUBSTAR_level_des *lev,
241 giacomo 179
                           PID p,
180
                           struct timespec *acttime)
181
{
182
  JOB_TASK_MODEL job;
183
  struct budget_struct *b = &lev->b[lev->tb[p]];
253 giacomo 184
  TIME t;
185
  struct timespec t2,t3;
241 giacomo 186
 
253 giacomo 187
  t = (b->T * b->avail) / b->Q;
188
  t3.tv_sec = t / 1000000;
189
  t3.tv_nsec = (t % 1000000) * 1000;
241 giacomo 190
 
275 trimarchi 191
  if (b->vtimer!=NIL) kern_event_delete(b->vtimer);
192
  b->vtimer=NIL;
193
 
253 giacomo 194
  SUBTIMESPEC(&b->dline, acttime, &t2);
195
  if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) ||
241 giacomo 196
       /* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
197
       TIMESPEC_ASSIGN(&b->dline, acttime);
198
       ADDUSEC2TIMESPEC(b->T, &b->dline);
199
       b->avail=b->Q;
276 giacomo 200
  }
201
 
278 giacomo 202
  if (b->flags==GRUBSTAR_RECLAIMING)
277 giacomo 203
    lev->Uf += b->Ub;
241 giacomo 204
 
276 giacomo 205
  b->flags=GRUBSTAR_ACTIVE;
241 giacomo 206
 
207
  /* record the current task inserted in the master module */
208
  b->current = p;
275 trimarchi 209
 
241 giacomo 210
  job_task_default_model(job, b->dline);
211
  job_task_def_noexc(job);
212
  level_table[ lev->scheduling_level ]->
213
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
214
 
215
}
216
 
253 giacomo 217
static void GRUBSTAR_account_capacity(GRUBSTAR_level_des *lev, PID p)
241 giacomo 218
{
219
  struct timespec ty;
220
  TIME tx;
221
  struct budget_struct *b = &lev->b[lev->tb[p]];
276 giacomo 222
  TIME t;
223
  struct timespec t2,t3;
241 giacomo 224
 
276 giacomo 225
 
226
  if (b->vtimer!=NIL) kern_event_delete(b->vtimer);
227
  b->vtimer=NIL;
228
 
241 giacomo 229
  if (lev->cap_lev != NIL && b->current == p) {
230
    kern_event_delete(lev->cap_lev);
231
    lev->cap_lev = NIL;
232
  }
233
 
279 giacomo 234
  SUBTIMESPEC(&schedule_time, &lev->cap_lasttime, &ty);
241 giacomo 235
  tx = TIMESPEC2USEC(&ty);
236
 
276 giacomo 237
  b->last_reclaiming = (unsigned int)((long long)(tx) * (long long)(lev->U - lev->Uf)/MAX_BANDWIDTH);
266 trimarchi 238
 
276 giacomo 239
  b->avail -= tx - b->last_reclaiming;
267 giacomo 240
 
253 giacomo 241
  #ifdef GRUBSTAR_DEBUG
278 giacomo 242
    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 243
  #endif
244
 
253 giacomo 245
  if (b->avail <= 0) b->flags = GRUBSTAR_NOACTIVE;
241 giacomo 246
 
247
  if (TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
248
    /* we modify the deadline ... */
249
    TIMESPEC_ASSIGN(&b->dline, &schedule_time);
250
    ADDUSEC2TIMESPEC(b->T, &b->dline);
251
  }
252
 
253 giacomo 253
  if (b->flags == GRUBSTAR_NOACTIVE && b->dline_timer == NIL)  {
254
    b->dline_timer=kern_event_post(&b->dline, GRUBSTAR_deadline_timer_hardreservation, b);
276 giacomo 255
  } else {
256
    t = (b->T * b->avail) / b->Q;
257
    t3.tv_sec = t / 1000000;
258
    t3.tv_nsec = (t % 1000000) * 1000;
259
    SUBTIMESPEC(&b->dline, &t3, &t2);
260
    b->vtimer = kern_event_post(&t2, GRUBSTAR_ANC, b);
241 giacomo 261
  }
262
}
263
 
264
 
265
/* The on-line guarantee is enabled only if the appropriate flag is set... */
253 giacomo 266
static int GRUBSTAR_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
241 giacomo 267
{
253 giacomo 268
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 269
 
253 giacomo 270
  #ifdef GRUBSTAR_DEBUG
271
    kern_printf("(GS:Gua)");
241 giacomo 272
  #endif
273
 
274
  if (*freebandwidth >= lev->U) {
275
    *freebandwidth -= lev->U;
276
    return 1;
277
  }
278
  else
279
    return 0;
280
}
281
 
282
static void capacity_handler(void *l)
283
{
284
 
253 giacomo 285
  GRUBSTAR_level_des *lev = l;
241 giacomo 286
  lev->cap_lev = NIL;
279 giacomo 287
 
241 giacomo 288
  event_need_reschedule();
289
 
290
}
291
 
253 giacomo 292
static int GRUBSTAR_private_eligible(LEVEL l, PID p)
241 giacomo 293
{
253 giacomo 294
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 295
  struct budget_struct *b = &lev->b[lev->tb[p]];
296
  JOB_TASK_MODEL job;
297
 
298
  if (b->current == p) {
299
    if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
300
      if (lev->cap_lev!=NIL) {
301
        kern_event_delete(lev->cap_lev);
302
        lev->cap_lev=NIL;
303
      }
304
 
305
      /* we kill the current activation */
306
      level_table[ lev->scheduling_level ]->
307
        private_extract(lev->scheduling_level, p);
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;
276 giacomo 314
 
315
      if (b->flags == GRUBSTAR_RECLAIMING) {
277 giacomo 316
        lev->Uf += b->Ub;
276 giacomo 317
      }
318
 
253 giacomo 319
      b->flags = GRUBSTAR_ACTIVE;
241 giacomo 320
 
321
      if (b->dline_timer!=NIL)  {
322
        kern_event_delete(b->dline_timer);
323
        b->dline_timer=NIL;
324
      }
275 trimarchi 325
 
326
      if (b->vtimer!=NIL)  {
327
            kern_event_delete(b->vtimer);
328
            b->vtimer=NIL;
329
      }
330
 
241 giacomo 331
 
332
      /* and, finally, we reinsert the task in the master level */
333
      job_task_default_model(job, b->dline);
334
      job_task_def_noexc(job);
335
      level_table[ lev->scheduling_level ]->
336
        private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
337
 
338
      return -1;
339
 
340
    }  
341
  }
342
 
343
  return 0;
344
 
345
}
346
 
253 giacomo 347
static void GRUBSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
241 giacomo 348
{
253 giacomo 349
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 350
  BUDGET_TASK_MODEL *budget;
351
 
352
  if (m->pclass != BUDGET_PCLASS ||
353
      (m->level != 0 && m->level != l)) {
354
    kern_raise(XINVALID_TASK, p);
355
    return;
356
  }
357
  budget = (BUDGET_TASK_MODEL *)m;
358
 
253 giacomo 359
  #ifdef GRUBSTAR_DEBUG
360
    kern_printf("(GS:PriIns:%d:%d", p, budget->b);
241 giacomo 361
  #endif
362
 
363
  if (budget->b == -1)
364
    return;
365
 
366
  lev->tb[p] = budget->b;
367
 
368
  if (lev->b[budget->b].current == NIL && lev->b[budget->b].flags ) {
369
    /* This is the first task in the budget,
370
       the task have to be inserted into the master module */
371
    struct timespec t;
372
    kern_gettime(&t);
253 giacomo 373
    GRUBSTAR_activation(lev,p,&t);
241 giacomo 374
  } else {
375
    /* The budget is not empty, another task is already into the
376
       master module, so the task is inserted at the end of the budget
377
       queue */
378
    iq_insertlast(p,&lev->b[budget->b].tasks);
379
  }
380
 
253 giacomo 381
  #ifdef GRUBSTAR_DEBUG
382
    kern_printf(")");
241 giacomo 383
  #endif
384
 
385
}
386
 
253 giacomo 387
static void GRUBSTAR_private_extract(LEVEL l, PID p)
241 giacomo 388
{
253 giacomo 389
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 390
 
253 giacomo 391
  #ifdef GRUBSTAR_DEBUG
392
    kern_printf("(GS:Ext:%d)", p);
241 giacomo 393
  #endif
394
 
395
  /* a task is removed from execution for some reasons. It must be
396
     that it is the first in its budget queue (only the first task in
397
     a budget queue is put into execution!) */
398
 
399
  /* remove the task from execution (or from the ready queue) */
400
  if (lev->b[lev->tb[p]].current == p) {
401
 
253 giacomo 402
   GRUBSTAR_account_capacity(lev,p);
241 giacomo 403
    /* remove the task from the master module */
404
    level_table[ lev->scheduling_level ]->
405
      private_extract(lev->scheduling_level, p);
406
 
407
    /* check if the buffer has someone else to schedule */
408
    if (iq_query_first(&lev->b[lev->tb[p]].tasks) == NIL) {
409
      /* the buffer has no tasks! */
410
      lev->b[lev->tb[p]].current = NIL;
411
    }
412
    else if (lev->b[lev->tb[p]].flags) {
413
      /* if so, insert the new task into the master module */
414
      PID n;
415
      struct timespec t;
416
 
417
      kern_gettime(&t);
418
      n = iq_getfirst(&lev->b[lev->tb[p]].tasks);
253 giacomo 419
      GRUBSTAR_activation(lev,n,&t);  // it modifies b[lev->tb[p]].current
241 giacomo 420
    }
421
    else
422
      lev->b[lev->tb[p]].current=NIL;
423
 
424
  }
425
  else  {
426
    iq_extract(p, &lev->b[lev->tb[p]].tasks);
427
  }
428
}
429
 
253 giacomo 430
static void GRUBSTAR_private_dispatch(LEVEL l, PID p, int nostop)
241 giacomo 431
{
253 giacomo 432
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 433
  struct timespec ty;
434
 
253 giacomo 435
  #ifdef GRUBSTAR_DEBUG
436
    kern_printf("(GS:Dsp:%d)", p);
241 giacomo 437
  #endif
438
 
439
  /* the current task (that is the only one inserted in the master module
440
     for the corresponding budget) is dispatched. Note that the current
441
     task is not inserted in any FIFO queue, so the task does not have to
442
     be extracted! */
443
 
444
  /* ... then, we dispatch it to the master level */
445
  level_table[ lev->scheduling_level ]->
446
    private_dispatch(lev->scheduling_level,p,nostop);
447
 
448
  /* ...and finally, we have to post a capacity event */
449
  if (!nostop) {
450
    TIMESPEC_ASSIGN(&ty, &schedule_time);
280 giacomo 451
    TIMESPEC_ASSIGN(&lev->cap_lasttime, &schedule_time);
241 giacomo 452
    ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty);
453
    lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
454
  }
455
 
456
}
457
 
253 giacomo 458
static void GRUBSTAR_private_epilogue(LEVEL l, PID p)
241 giacomo 459
{
253 giacomo 460
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 461
  struct budget_struct *b = &lev->b[lev->tb[p]];
462
 
253 giacomo 463
  #ifdef GRUBSTAR_DEBUG
254 giacomo 464
    kern_printf("(GS:Epi:%d)",p);
241 giacomo 465
  #endif
466
 
467
  if (p==b->current)  {
468
 
253 giacomo 469
    GRUBSTAR_account_capacity(lev,p);
241 giacomo 470
 
471
    // L'evento di capacità va cancellato perchè sarà ripristinato nella successiva dispatch
472
    /* we have to check if the capacity is still available */
473
    if (b->flags)  {
276 giacomo 474
 
241 giacomo 475
      /* there is capacity available, maybe it is simply a preemption;
476
         the task have to return to the ready queue */
477
      level_table[ lev->scheduling_level ]->
478
        private_epilogue(lev->scheduling_level,p);
479
 
480
    } else {
481
      /* we kill the current activation */
482
      level_table[ lev->scheduling_level ]->
483
        private_extract(lev->scheduling_level, p);    
484
 
485
      iq_insertfirst(p, &b->tasks);
486
      b->current = NIL;
487
 
488
    }
489
 
490
  }
491
 
492
}
493
 
267 giacomo 494
static int GRUBSTAR_public_message(LEVEL l, PID p, void *m)
495
{
496
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
497
  struct budget_struct *b = &lev->b[lev->tb[p]];
498
 
499
  switch((long)(m)) {
500
 
501
    case (long)(NULL):
502
 
503
      if (b->current == NIL && iq_query_first(&(b->tasks)) == NIL && b->flags != GRUBSTAR_RECLAIMING) {
504
        b->flags = GRUBSTAR_RECLAIMING;
277 giacomo 505
        lev->Uf -= b->Ub;
267 giacomo 506
      }
507
 
508
      break;
509
 
510
    case 1:
511
 
512
      break;
513
 
514
  }
515
 
516
  return 0;
517
 
518
}
519
 
241 giacomo 520
/* Registration functions }*/
521
 
253 giacomo 522
LEVEL GRUBSTAR_register_level(int n, LEVEL master)
241 giacomo 523
{
524
  LEVEL l;            /* the level that we register */
253 giacomo 525
  GRUBSTAR_level_des *lev;  /* for readableness only */
241 giacomo 526
  PID i;              /* a counter */
527
 
253 giacomo 528
  printk("GRUBSTAR_register_level\n");
241 giacomo 529
 
530
  /* request an entry in the level_table */
253 giacomo 531
  l = level_alloc_descriptor(sizeof(GRUBSTAR_level_des));
241 giacomo 532
 
253 giacomo 533
  lev = (GRUBSTAR_level_des *)level_table[l];
241 giacomo 534
 
535
  /* fill the standard descriptor */
253 giacomo 536
  lev->l.private_insert   = GRUBSTAR_private_insert;
537
  lev->l.private_extract  = GRUBSTAR_private_extract;
538
  lev->l.private_eligible = GRUBSTAR_private_eligible;
539
  lev->l.private_dispatch = GRUBSTAR_private_dispatch;
540
  lev->l.private_epilogue = GRUBSTAR_private_epilogue;
241 giacomo 541
 
253 giacomo 542
  lev->l.public_guarantee = GRUBSTAR_public_guarantee;
267 giacomo 543
  lev->l.public_message = GRUBSTAR_public_message;
241 giacomo 544
 
545
  lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
546
 
547
  for (i=0; i<n; i++) {
548
    lev->b[i].Q = 0;
549
    lev->b[i].T = 0;
277 giacomo 550
    lev->b[i].Ub = 0;
241 giacomo 551
    NULL_TIMESPEC(&lev->b[i].dline);
552
    lev->b[i].dline_timer = NIL;
253 giacomo 553
    lev->b[i].vtimer=NIL;
241 giacomo 554
    lev->b[i].avail = 0;
555
    lev->b[i].current = -1;
253 giacomo 556
    lev->b[i].flags = GRUBSTAR_ACTIVE;
276 giacomo 557
    lev->b[i].l = l;
558
    lev->b[i].last_reclaiming = 0;
253 giacomo 559
    iq_init(&lev->b[i].tasks, NULL, 0);
241 giacomo 560
  }
561
 
562
  lev->n = n;
563
  lev->freebudgets = 0;
564
 
565
  for (i=0; i<MAX_PROC; i++)
566
    lev->tb[i] = NIL;
567
 
568
  lev->U = 0;
569
  lev->Uf = 0;
570
  lev->cap_lev = NIL;
279 giacomo 571
  NULL_TIMESPEC(&lev->cap_lasttime);
241 giacomo 572
  lev->scheduling_level = master;
573
 
574
  return l;
575
 
576
}
577
 
253 giacomo 578
int GRUBSTAR_setbudget(LEVEL l, TIME Q, TIME T, LEVEL local_scheduler_level, int scheduler_id)
241 giacomo 579
{
253 giacomo 580
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 581
  int r;
582
 
253 giacomo 583
  #ifdef GRUBSTAR_DEBUG
584
    kern_printf("(GS:SetBud)");
241 giacomo 585
  #endif
586
 
587
  for (r = 0; r < lev->n; r++)
588
    if (lev->b[r].Q == 0) break;
589
 
590
  if (r != lev->n) {
591
    bandwidth_t b;
592
    b = (MAX_BANDWIDTH / T) * Q;
593
 
594
    /* really update lev->U, checking an overflow... */
595
    if (Q< T && MAX_BANDWIDTH - lev->U > b) {
596
 
597
      lev->U += b;
598
      lev->Uf += b;
599
      lev->freebudgets++;
600
 
601
      lev->b[r].Q = Q;
602
      lev->b[r].T = T;
277 giacomo 603
      lev->b[r].Ub = b;
241 giacomo 604
      lev->b[r].avail = Q;
253 giacomo 605
      lev->b[r].flags = GRUBSTAR_ACTIVE;
241 giacomo 606
      lev->b[r].loc_sched_id = scheduler_id;
607
      lev->b[r].loc_sched_level = local_scheduler_level;
276 giacomo 608
      lev->b[r].last_reclaiming = 0;  
609
 
241 giacomo 610
      return r;
611
    }
612
    else
613
      return -2;
614
  }
615
  else
616
    return -1;
617
}
618
 
253 giacomo 619
int GRUBSTAR_removebudget(LEVEL l, int budget)
241 giacomo 620
{
621
 
253 giacomo 622
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 623
 
624
  bandwidth_t b;
625
 
626
  b = (MAX_BANDWIDTH / lev->b[budget].T) * lev->b[budget].Q;
627
 
628
  lev->U -= b;
629
 
630
  lev->b[budget].Q = 0;
631
  lev->b[budget].T = 0;
277 giacomo 632
  lev->b[budget].Ub = 0;
241 giacomo 633
  NULL_TIMESPEC(&lev->b[budget].dline);
634
  lev->b[budget].dline_timer = NIL;
635
  lev->b[budget].avail = 0;
636
  lev->b[budget].current = -1;
253 giacomo 637
  lev->b[budget].flags = GRUBSTAR_ACTIVE;
277 giacomo 638
  lev->b[budget].last_reclaiming = 0;
241 giacomo 639
 
640
  return 0;
641
 
642
}
643
 
253 giacomo 644
int GRUBSTAR_adjust_budget(LEVEL l, TIME Q, TIME T, int budget)
241 giacomo 645
{
646
 
253 giacomo 647
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 648
 
649
  lev->b[budget].Q = Q;
650
  lev->b[budget].T = T;
277 giacomo 651
  lev->b[budget].Ub = (MAX_BANDWIDTH / T) * Q;
241 giacomo 652
 
653
  return 0;
654
 
655
}
656
 
253 giacomo 657
int GRUBSTAR_getbudgetinfo(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
  *Q = lev->b[budget].Q;
663
  *T = lev->b[budget].T;
664
 
665
  return 0;
666
 
667
}
668
 
276 giacomo 669
int GRUBSTAR_get_last_reclaiming(LEVEL l, PID p)
267 giacomo 670
{
671
 
672
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
673
 
276 giacomo 674
  return lev->b[lev->tb[p]].last_reclaiming;
267 giacomo 675
 
676
}
677
 
253 giacomo 678
int GRUBSTAR_is_active(LEVEL l, int budget)
241 giacomo 679
{
253 giacomo 680
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 681
 
682
  return lev->b[budget].flags;
683
 
684
}
685
 
253 giacomo 686
int GRUBSTAR_get_local_scheduler_level_from_budget(LEVEL l, int budget)
241 giacomo 687
{
253 giacomo 688
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 689
 
690
  return lev->b[budget].loc_sched_level;
691
 
692
}
693
 
253 giacomo 694
int GRUBSTAR_get_local_scheduler_level_from_pid(LEVEL l, PID p)
241 giacomo 695
{
253 giacomo 696
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 697
 
698
  return lev->b[lev->tb[p]].loc_sched_level;
699
 
700
}
701
 
253 giacomo 702
int GRUBSTAR_get_local_scheduler_id_from_budget(LEVEL l, int budget)
241 giacomo 703
{
253 giacomo 704
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 705
 
706
  return lev->b[budget].loc_sched_id;
707
 
708
}
709
 
253 giacomo 710
int GRUBSTAR_get_local_scheduler_id_from_pid(LEVEL l, PID p)
241 giacomo 711
{
253 giacomo 712
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 713
 
714
  return lev->b[lev->tb[p]].loc_sched_id;
715
 
716
}
717