Subversion Repositories shark

Rev

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