Subversion Repositories shark

Rev

Rev 340 | Rev 342 | 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
 
339 giacomo 188
  #ifdef GRUBSTAR_DEBUG
189
    kern_printf("(GS:Act %d)",p);
190
  #endif
338 giacomo 191
 
275 trimarchi 192
  if (b->vtimer!=NIL) kern_event_delete(b->vtimer);
193
  b->vtimer=NIL;
194
 
253 giacomo 195
  SUBTIMESPEC(&b->dline, acttime, &t2);
196
  if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) ||
241 giacomo 197
       /* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
198
       TIMESPEC_ASSIGN(&b->dline, acttime);
199
       ADDUSEC2TIMESPEC(b->T, &b->dline);
200
       b->avail=b->Q;
276 giacomo 201
  }
202
 
278 giacomo 203
  if (b->flags==GRUBSTAR_RECLAIMING)
277 giacomo 204
    lev->Uf += b->Ub;
241 giacomo 205
 
276 giacomo 206
  b->flags=GRUBSTAR_ACTIVE;
241 giacomo 207
 
208
  /* record the current task inserted in the master module */
209
  b->current = p;
275 trimarchi 210
 
241 giacomo 211
  job_task_default_model(job, b->dline);
212
  job_task_def_noexc(job);
213
  level_table[ lev->scheduling_level ]->
214
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
215
 
216
}
217
 
253 giacomo 218
static void GRUBSTAR_account_capacity(GRUBSTAR_level_des *lev, PID p)
241 giacomo 219
{
220
  struct timespec ty;
221
  TIME tx;
222
  struct budget_struct *b = &lev->b[lev->tb[p]];
276 giacomo 223
  TIME t;
224
  struct timespec t2,t3;
241 giacomo 225
 
276 giacomo 226
 
227
  if (b->vtimer!=NIL) kern_event_delete(b->vtimer);
228
  b->vtimer=NIL;
229
 
296 trimarchi 230
  if (lev->cap_lev != NIL) {
241 giacomo 231
    kern_event_delete(lev->cap_lev);
232
    lev->cap_lev = NIL;
233
  }
234
 
279 giacomo 235
  SUBTIMESPEC(&schedule_time, &lev->cap_lasttime, &ty);
241 giacomo 236
  tx = TIMESPEC2USEC(&ty);
237
 
276 giacomo 238
  b->last_reclaiming = (unsigned int)((long long)(tx) * (long long)(lev->U - lev->Uf)/MAX_BANDWIDTH);
266 trimarchi 239
 
276 giacomo 240
  b->avail -= tx - b->last_reclaiming;
267 giacomo 241
 
253 giacomo 242
  #ifdef GRUBSTAR_DEBUG
298 giacomo 243
    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 244
  #endif
245
 
253 giacomo 246
  if (b->avail <= 0) b->flags = GRUBSTAR_NOACTIVE;
241 giacomo 247
 
248
  if (TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
249
    /* we modify the deadline ... */
250
    TIMESPEC_ASSIGN(&b->dline, &schedule_time);
251
    ADDUSEC2TIMESPEC(b->T, &b->dline);
252
  }
253
 
253 giacomo 254
  if (b->flags == GRUBSTAR_NOACTIVE && b->dline_timer == NIL)  {
255
    b->dline_timer=kern_event_post(&b->dline, GRUBSTAR_deadline_timer_hardreservation, b);
276 giacomo 256
  } else {
257
    t = (b->T * b->avail) / b->Q;
258
    t3.tv_sec = t / 1000000;
259
    t3.tv_nsec = (t % 1000000) * 1000;
260
    SUBTIMESPEC(&b->dline, &t3, &t2);
261
    b->vtimer = kern_event_post(&t2, GRUBSTAR_ANC, b);
241 giacomo 262
  }
263
}
264
 
265
static void capacity_handler(void *l)
266
{
267
 
253 giacomo 268
  GRUBSTAR_level_des *lev = l;
241 giacomo 269
  lev->cap_lev = NIL;
298 giacomo 270
  #ifdef GRUBSTAR_DEBUG
271
    kern_printf("(*)");
272
  #endif  
241 giacomo 273
  event_need_reschedule();
274
 
275
}
276
 
253 giacomo 277
static int GRUBSTAR_private_eligible(LEVEL l, PID p)
241 giacomo 278
{
253 giacomo 279
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
296 trimarchi 280
  struct budget_struct *b=&lev->b[lev->tb[p]];
298 giacomo 281
  JOB_TASK_MODEL job;
282
 
283
  if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
284
      #ifdef GRUBSTAR_DEBUG 
288 giacomo 285
        kern_printf("(GS:Eli:%d)",p);
298 giacomo 286
      #endif
241 giacomo 287
      if (lev->cap_lev!=NIL) {
288
        kern_event_delete(lev->cap_lev);
289
        lev->cap_lev=NIL;
290
      }
291
 
292
      /* we kill the current activation */
293
      level_table[ lev->scheduling_level ]->
294
        private_extract(lev->scheduling_level, p);
295
      /* we modify the deadline ... */
298 giacomo 296
      kern_gettime(&b->dline);
241 giacomo 297
      ADDUSEC2TIMESPEC(b->T, &b->dline);
298
 
299
      /* and the capacity */
300
      b->avail = b->Q;
276 giacomo 301
 
302
      if (b->flags == GRUBSTAR_RECLAIMING) {
277 giacomo 303
        lev->Uf += b->Ub;
276 giacomo 304
      }
305
 
253 giacomo 306
      b->flags = GRUBSTAR_ACTIVE;
241 giacomo 307
 
308
      if (b->dline_timer!=NIL)  {
309
        kern_event_delete(b->dline_timer);
310
        b->dline_timer=NIL;
311
      }
275 trimarchi 312
 
313
      if (b->vtimer!=NIL)  {
314
            kern_event_delete(b->vtimer);
315
            b->vtimer=NIL;
316
      }
317
 
241 giacomo 318
 
319
      /* and, finally, we reinsert the task in the master level */
320
      job_task_default_model(job, b->dline);
321
      job_task_def_noexc(job);
322
      level_table[ lev->scheduling_level ]->
323
        private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
324
 
325
      return -1;
326
 
296 trimarchi 327
  }  
241 giacomo 328
 
329
  return 0;
330
 
331
}
332
 
253 giacomo 333
static void GRUBSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
241 giacomo 334
{
253 giacomo 335
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 336
  BUDGET_TASK_MODEL *budget;
337
 
338
  if (m->pclass != BUDGET_PCLASS ||
339
      (m->level != 0 && m->level != l)) {
340
    kern_raise(XINVALID_TASK, p);
341
    return;
342
  }
343
  budget = (BUDGET_TASK_MODEL *)m;
344
 
339 giacomo 345
  #ifdef GRUBSTAR_DEBUG
253 giacomo 346
    kern_printf("(GS:PriIns:%d:%d", p, budget->b);
339 giacomo 347
  #endif
241 giacomo 348
 
349
  if (budget->b == -1)
350
    return;
351
 
352
  lev->tb[p] = budget->b;
353
 
354
  if (lev->b[budget->b].current == NIL && lev->b[budget->b].flags ) {
355
    /* This is the first task in the budget,
356
       the task have to be inserted into the master module */
357
    struct timespec t;
358
    kern_gettime(&t);
253 giacomo 359
    GRUBSTAR_activation(lev,p,&t);
241 giacomo 360
  } else {
361
    /* The budget is not empty, another task is already into the
362
       master module, so the task is inserted at the end of the budget
363
       queue */
364
    iq_insertlast(p,&lev->b[budget->b].tasks);
365
  }
366
 
339 giacomo 367
  #ifdef GRUBSTAR_DEBUG
253 giacomo 368
    kern_printf(")");
339 giacomo 369
  #endif
241 giacomo 370
 
371
}
372
 
253 giacomo 373
static void GRUBSTAR_private_extract(LEVEL l, PID p)
241 giacomo 374
{
253 giacomo 375
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 376
 
339 giacomo 377
  #ifdef GRUBSTAR_DEBUG
253 giacomo 378
    kern_printf("(GS:Ext:%d)", p);
339 giacomo 379
  #endif
241 giacomo 380
 
381
  /* a task is removed from execution for some reasons. It must be
382
     that it is the first in its budget queue (only the first task in
383
     a budget queue is put into execution!) */
384
 
385
  /* remove the task from execution (or from the ready queue) */
386
  if (lev->b[lev->tb[p]].current == p) {
387
 
253 giacomo 388
   GRUBSTAR_account_capacity(lev,p);
241 giacomo 389
    /* remove the task from the master module */
390
    level_table[ lev->scheduling_level ]->
391
      private_extract(lev->scheduling_level, p);
392
 
393
    /* check if the buffer has someone else to schedule */
394
    if (iq_query_first(&lev->b[lev->tb[p]].tasks) == NIL) {
395
      /* the buffer has no tasks! */
396
      lev->b[lev->tb[p]].current = NIL;
397
    }
398
    else if (lev->b[lev->tb[p]].flags) {
399
      /* if so, insert the new task into the master module */
400
      PID n;
401
      struct timespec t;
338 giacomo 402
 
241 giacomo 403
      kern_gettime(&t);
404
      n = iq_getfirst(&lev->b[lev->tb[p]].tasks);
253 giacomo 405
      GRUBSTAR_activation(lev,n,&t);  // it modifies b[lev->tb[p]].current
241 giacomo 406
    }
407
    else
408
      lev->b[lev->tb[p]].current=NIL;
409
 
410
  }
411
  else  {
412
    iq_extract(p, &lev->b[lev->tb[p]].tasks);
413
  }
414
}
415
 
253 giacomo 416
static void GRUBSTAR_private_dispatch(LEVEL l, PID p, int nostop)
241 giacomo 417
{
253 giacomo 418
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 419
  struct timespec ty;
420
 
253 giacomo 421
  #ifdef GRUBSTAR_DEBUG
422
    kern_printf("(GS:Dsp:%d)", p);
241 giacomo 423
  #endif
424
 
425
  /* the current task (that is the only one inserted in the master module
426
     for the corresponding budget) is dispatched. Note that the current
427
     task is not inserted in any FIFO queue, so the task does not have to
428
     be extracted! */
429
 
430
  /* ... then, we dispatch it to the master level */
296 trimarchi 431
  if (!nostop)
432
        level_table[ lev->scheduling_level ]->
433
                private_dispatch(lev->scheduling_level,p,nostop);
241 giacomo 434
 
296 trimarchi 435
  TIMESPEC_ASSIGN(&ty, &schedule_time);
436
  TIMESPEC_ASSIGN(&lev->cap_lasttime, &schedule_time);
437
 
241 giacomo 438
  /* ...and finally, we have to post a capacity event */
296 trimarchi 439
 
440
  ADDUSEC2TIMESPEC(lev->b[lev->tb[exec]].avail,&ty);
441
  lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
442
 
241 giacomo 443
 
444
}
445
 
253 giacomo 446
static void GRUBSTAR_private_epilogue(LEVEL l, PID p)
241 giacomo 447
{
253 giacomo 448
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
296 trimarchi 449
  struct budget_struct *b;
450
  int skip_epilog;
451
  skip_epilog=0;
452
 
253 giacomo 453
  #ifdef GRUBSTAR_DEBUG
296 trimarchi 454
     kern_printf("(GS:Epi:%d)",p);
241 giacomo 455
  #endif
456
 
296 trimarchi 457
  if (p==exec) b = &lev->b[lev->tb[p]];
458
     else if (lev->tb[exec]!=NIL)  {
459
          b = &lev->b[lev->tb[exec]];
460
          p=exec;
461
          skip_epilog=1;
462
       }
463
       else return;    
241 giacomo 464
 
465
 
298 giacomo 466
    GRUBSTAR_account_capacity(lev,p);
241 giacomo 467
    if (b->flags)  {
276 giacomo 468
 
241 giacomo 469
      /* there is capacity available, maybe it is simply a preemption;
470
         the task have to return to the ready queue */
296 trimarchi 471
      if (!skip_epilog)
472
        level_table[ lev->scheduling_level ]->
473
          private_epilogue(lev->scheduling_level,p); //else kern_printf("(SP)");
241 giacomo 474
 
475
    } else {
476
      /* we kill the current activation */
298 giacomo 477
      #ifdef GRUBSTAR_DEBUG
478
        kern_printf("(GS:HRExt:%d",p);
479
      #endif      
241 giacomo 480
      level_table[ lev->scheduling_level ]->
296 trimarchi 481
          private_extract(lev->scheduling_level, p);    
241 giacomo 482
 
483
      iq_insertfirst(p, &b->tasks);
484
      b->current = NIL;
485
 
486
    }
487
 
488
}
489
 
267 giacomo 490
static int GRUBSTAR_public_message(LEVEL l, PID p, void *m)
491
{
492
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
493
  struct budget_struct *b = &lev->b[lev->tb[p]];
494
 
495
  switch((long)(m)) {
496
 
497
    case (long)(NULL):
338 giacomo 498
 
339 giacomo 499
      #ifdef GRUBSTAR_DEBUG
338 giacomo 500
        kern_printf("(GS:EndCycle:%d:%d)",p,lev->tb[p]);
339 giacomo 501
      #endif     
267 giacomo 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
 
298 giacomo 542
  lev->l.public_guarantee = NULL;
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;
298 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
 
339 giacomo 583
  #ifdef GRUBSTAR_DEBUG
253 giacomo 584
    kern_printf("(GS:SetBud)");
339 giacomo 585
  #endif
241 giacomo 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]);
298 giacomo 648
  bandwidth_t b;
241 giacomo 649
 
298 giacomo 650
  b = (MAX_BANDWIDTH / lev->b[budget].T) * lev->b[budget].Q;
651
 
652
  lev->U -= b;
653
 
241 giacomo 654
  lev->b[budget].Q = Q;
655
  lev->b[budget].T = T;
277 giacomo 656
  lev->b[budget].Ub = (MAX_BANDWIDTH / T) * Q;
341 giacomo 657
  lev->b[budget].avail = Q;
298 giacomo 658
  lev->U += lev->b[budget].Ub;
241 giacomo 659
 
660
  return 0;
661
 
662
}
663
 
253 giacomo 664
int GRUBSTAR_getbudgetinfo(LEVEL l, TIME *Q, TIME *T, int budget)
241 giacomo 665
{
666
 
253 giacomo 667
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 668
 
669
  *Q = lev->b[budget].Q;
670
  *T = lev->b[budget].T;
671
 
672
  return 0;
673
 
674
}
675
 
276 giacomo 676
int GRUBSTAR_get_last_reclaiming(LEVEL l, PID p)
267 giacomo 677
{
678
 
679
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
680
 
276 giacomo 681
  return lev->b[lev->tb[p]].last_reclaiming;
267 giacomo 682
 
683
}
684
 
253 giacomo 685
int GRUBSTAR_is_active(LEVEL l, int budget)
241 giacomo 686
{
253 giacomo 687
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 688
 
689
  return lev->b[budget].flags;
690
 
691
}
692
 
340 giacomo 693
int GRUBSTAR_get_remain_capacity(LEVEL l, int budget)
694
{
695
 
696
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
697
 
698
  return lev->b[budget].avail;
699
 
700
}
701
 
253 giacomo 702
int GRUBSTAR_get_local_scheduler_level_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_level;
707
 
708
}
709
 
253 giacomo 710
int GRUBSTAR_get_local_scheduler_level_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_level;
715
 
716
}
717
 
253 giacomo 718
int GRUBSTAR_get_local_scheduler_id_from_budget(LEVEL l, int budget)
241 giacomo 719
{
253 giacomo 720
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 721
 
722
  return lev->b[budget].loc_sched_id;
723
 
724
}
725
 
253 giacomo 726
int GRUBSTAR_get_local_scheduler_id_from_pid(LEVEL l, PID p)
241 giacomo 727
{
253 giacomo 728
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 729
 
730
  return lev->b[lev->tb[p]].loc_sched_id;
731
 
732
}
733