Subversion Repositories shark

Rev

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