Subversion Repositories shark

Rev

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