Subversion Repositories shark

Rev

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