Subversion Repositories shark

Rev

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