Subversion Repositories shark

Rev

Rev 288 | Rev 298 | 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
 
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
 
296 trimarchi 226
  if (lev->cap_lev != NIL) {
241 giacomo 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
296 trimarchi 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;
296 trimarchi 284
#ifdef GRUBSTAR_DEBUG
285
  kern_printf("(*)");
286
#endif  
241 giacomo 287
  event_need_reschedule();
288
 
289
}
290
 
253 giacomo 291
static int GRUBSTAR_private_eligible(LEVEL l, PID p)
241 giacomo 292
{
253 giacomo 293
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
296 trimarchi 294
  struct budget_struct *b=&lev->b[lev->tb[p]];
241 giacomo 295
  JOB_TASK_MODEL job;
296 trimarchi 296
 
297
 if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
288 giacomo 298
 
299
        kern_printf("(GS:Eli:%d)",p);
300
 
241 giacomo 301
      if (lev->cap_lev!=NIL) {
302
        kern_event_delete(lev->cap_lev);
303
        lev->cap_lev=NIL;
304
      }
305
 
306
      /* we kill the current activation */
307
      level_table[ lev->scheduling_level ]->
308
        private_extract(lev->scheduling_level, p);
309
      /* we modify the deadline ... */
310
      TIMESPEC_ASSIGN(&b->dline, &schedule_time);
311
      ADDUSEC2TIMESPEC(b->T, &b->dline);
312
 
313
      /* and the capacity */
314
      b->avail = b->Q;
276 giacomo 315
 
316
      if (b->flags == GRUBSTAR_RECLAIMING) {
277 giacomo 317
        lev->Uf += b->Ub;
276 giacomo 318
      }
319
 
253 giacomo 320
      b->flags = GRUBSTAR_ACTIVE;
241 giacomo 321
 
322
      if (b->dline_timer!=NIL)  {
323
        kern_event_delete(b->dline_timer);
324
        b->dline_timer=NIL;
325
      }
275 trimarchi 326
 
327
      if (b->vtimer!=NIL)  {
328
            kern_event_delete(b->vtimer);
329
            b->vtimer=NIL;
330
      }
331
 
241 giacomo 332
 
333
      /* and, finally, we reinsert the task in the master level */
334
      job_task_default_model(job, b->dline);
335
      job_task_def_noexc(job);
336
      level_table[ lev->scheduling_level ]->
337
        private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
338
 
339
      return -1;
340
 
296 trimarchi 341
  }  
241 giacomo 342
 
343
  return 0;
344
 
345
}
346
 
253 giacomo 347
static void GRUBSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
241 giacomo 348
{
253 giacomo 349
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 350
  BUDGET_TASK_MODEL *budget;
351
 
352
  if (m->pclass != BUDGET_PCLASS ||
353
      (m->level != 0 && m->level != l)) {
354
    kern_raise(XINVALID_TASK, p);
355
    return;
356
  }
357
  budget = (BUDGET_TASK_MODEL *)m;
358
 
253 giacomo 359
  #ifdef GRUBSTAR_DEBUG
360
    kern_printf("(GS:PriIns:%d:%d", p, budget->b);
241 giacomo 361
  #endif
362
 
363
  if (budget->b == -1)
364
    return;
365
 
366
  lev->tb[p] = budget->b;
367
 
368
  if (lev->b[budget->b].current == NIL && lev->b[budget->b].flags ) {
369
    /* This is the first task in the budget,
370
       the task have to be inserted into the master module */
371
    struct timespec t;
372
    kern_gettime(&t);
253 giacomo 373
    GRUBSTAR_activation(lev,p,&t);
241 giacomo 374
  } else {
375
    /* The budget is not empty, another task is already into the
376
       master module, so the task is inserted at the end of the budget
377
       queue */
378
    iq_insertlast(p,&lev->b[budget->b].tasks);
379
  }
380
 
253 giacomo 381
  #ifdef GRUBSTAR_DEBUG
382
    kern_printf(")");
241 giacomo 383
  #endif
384
 
385
}
386
 
253 giacomo 387
static void GRUBSTAR_private_extract(LEVEL l, PID p)
241 giacomo 388
{
253 giacomo 389
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 390
 
253 giacomo 391
  #ifdef GRUBSTAR_DEBUG
392
    kern_printf("(GS:Ext:%d)", p);
241 giacomo 393
  #endif
394
 
395
  /* a task is removed from execution for some reasons. It must be
396
     that it is the first in its budget queue (only the first task in
397
     a budget queue is put into execution!) */
398
 
399
  /* remove the task from execution (or from the ready queue) */
400
  if (lev->b[lev->tb[p]].current == p) {
401
 
253 giacomo 402
   GRUBSTAR_account_capacity(lev,p);
241 giacomo 403
    /* remove the task from the master module */
404
    level_table[ lev->scheduling_level ]->
405
      private_extract(lev->scheduling_level, p);
406
 
407
    /* check if the buffer has someone else to schedule */
408
    if (iq_query_first(&lev->b[lev->tb[p]].tasks) == NIL) {
409
      /* the buffer has no tasks! */
410
      lev->b[lev->tb[p]].current = NIL;
411
    }
412
    else if (lev->b[lev->tb[p]].flags) {
413
      /* if so, insert the new task into the master module */
414
      PID n;
415
      struct timespec t;
416
 
417
      kern_gettime(&t);
418
      n = iq_getfirst(&lev->b[lev->tb[p]].tasks);
253 giacomo 419
      GRUBSTAR_activation(lev,n,&t);  // it modifies b[lev->tb[p]].current
241 giacomo 420
    }
421
    else
422
      lev->b[lev->tb[p]].current=NIL;
423
 
424
  }
425
  else  {
426
    iq_extract(p, &lev->b[lev->tb[p]].tasks);
427
  }
428
}
429
 
253 giacomo 430
static void GRUBSTAR_private_dispatch(LEVEL l, PID p, int nostop)
241 giacomo 431
{
253 giacomo 432
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 433
  struct timespec ty;
434
 
253 giacomo 435
  #ifdef GRUBSTAR_DEBUG
436
    kern_printf("(GS:Dsp:%d)", p);
241 giacomo 437
  #endif
438
 
439
  /* the current task (that is the only one inserted in the master module
440
     for the corresponding budget) is dispatched. Note that the current
441
     task is not inserted in any FIFO queue, so the task does not have to
442
     be extracted! */
443
 
444
  /* ... then, we dispatch it to the master level */
296 trimarchi 445
  if (!nostop)
446
        level_table[ lev->scheduling_level ]->
447
                private_dispatch(lev->scheduling_level,p,nostop);
241 giacomo 448
 
296 trimarchi 449
  TIMESPEC_ASSIGN(&ty, &schedule_time);
450
  TIMESPEC_ASSIGN(&lev->cap_lasttime, &schedule_time);
451
 
241 giacomo 452
  /* ...and finally, we have to post a capacity event */
296 trimarchi 453
 
454
  ADDUSEC2TIMESPEC(lev->b[lev->tb[exec]].avail,&ty);
455
  lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
456
 
241 giacomo 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]);
296 trimarchi 463
  struct budget_struct *b;
464
  int skip_epilog;
465
  skip_epilog=0;
466
 
253 giacomo 467
  #ifdef GRUBSTAR_DEBUG
296 trimarchi 468
     kern_printf("(GS:Epi:%d)",p);
241 giacomo 469
  #endif
470
 
296 trimarchi 471
  if (p==exec) b = &lev->b[lev->tb[p]];
472
     else if (lev->tb[exec]!=NIL)  {
473
          b = &lev->b[lev->tb[exec]];
474
#ifdef GRUBSTAR_DEBUG
475
          kern_printf("(ex%d, c%d)***************************", exec, p);
476
#endif    
477
          p=exec;
478
          skip_epilog=1;
479
       }
480
       else return;    
241 giacomo 481
 
482
 
296 trimarchi 483
   GRUBSTAR_account_capacity(lev,p);
241 giacomo 484
    // L'evento di capacità va cancellato perchè sarà ripristinato nella successiva dispatch
485
    /* we have to check if the capacity is still available */
486
    if (b->flags)  {
276 giacomo 487
 
241 giacomo 488
      /* there is capacity available, maybe it is simply a preemption;
489
         the task have to return to the ready queue */
296 trimarchi 490
      if (!skip_epilog)
491
        level_table[ lev->scheduling_level ]->
492
          private_epilogue(lev->scheduling_level,p); //else kern_printf("(SP)");
241 giacomo 493
 
494
    } else {
495
      /* we kill the current activation */
296 trimarchi 496
#ifdef GRUBSTAR_DEBUG
497
      kern_printf("(GS:HRExt:%d",p);
498
#endif      
241 giacomo 499
      level_table[ lev->scheduling_level ]->
296 trimarchi 500
          private_extract(lev->scheduling_level, p);    
241 giacomo 501
 
502
      iq_insertfirst(p, &b->tasks);
503
      b->current = NIL;
504
 
505
    }
506
 
507
}
508
 
267 giacomo 509
static int GRUBSTAR_public_message(LEVEL l, PID p, void *m)
510
{
511
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
512
  struct budget_struct *b = &lev->b[lev->tb[p]];
513
 
514
  switch((long)(m)) {
515
 
516
    case (long)(NULL):
517
 
518
      if (b->current == NIL && iq_query_first(&(b->tasks)) == NIL && b->flags != GRUBSTAR_RECLAIMING) {
519
        b->flags = GRUBSTAR_RECLAIMING;
277 giacomo 520
        lev->Uf -= b->Ub;
267 giacomo 521
      }
522
 
523
      break;
524
 
525
    case 1:
526
 
527
      break;
528
 
529
  }
530
 
531
  return 0;
532
 
533
}
534
 
241 giacomo 535
/* Registration functions }*/
536
 
253 giacomo 537
LEVEL GRUBSTAR_register_level(int n, LEVEL master)
241 giacomo 538
{
539
  LEVEL l;            /* the level that we register */
253 giacomo 540
  GRUBSTAR_level_des *lev;  /* for readableness only */
241 giacomo 541
  PID i;              /* a counter */
542
 
253 giacomo 543
  printk("GRUBSTAR_register_level\n");
241 giacomo 544
 
545
  /* request an entry in the level_table */
253 giacomo 546
  l = level_alloc_descriptor(sizeof(GRUBSTAR_level_des));
241 giacomo 547
 
253 giacomo 548
  lev = (GRUBSTAR_level_des *)level_table[l];
241 giacomo 549
 
550
  /* fill the standard descriptor */
253 giacomo 551
  lev->l.private_insert   = GRUBSTAR_private_insert;
552
  lev->l.private_extract  = GRUBSTAR_private_extract;
553
  lev->l.private_eligible = GRUBSTAR_private_eligible;
554
  lev->l.private_dispatch = GRUBSTAR_private_dispatch;
555
  lev->l.private_epilogue = GRUBSTAR_private_epilogue;
241 giacomo 556
 
253 giacomo 557
  lev->l.public_guarantee = GRUBSTAR_public_guarantee;
267 giacomo 558
  lev->l.public_message = GRUBSTAR_public_message;
241 giacomo 559
 
560
  lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
561
 
562
  for (i=0; i<n; i++) {
563
    lev->b[i].Q = 0;
564
    lev->b[i].T = 0;
277 giacomo 565
    lev->b[i].Ub = 0;
241 giacomo 566
    NULL_TIMESPEC(&lev->b[i].dline);
567
    lev->b[i].dline_timer = NIL;
253 giacomo 568
    lev->b[i].vtimer=NIL;
241 giacomo 569
    lev->b[i].avail = 0;
570
    lev->b[i].current = -1;
253 giacomo 571
    lev->b[i].flags = GRUBSTAR_ACTIVE;
276 giacomo 572
    lev->b[i].l = l;
573
    lev->b[i].last_reclaiming = 0;
253 giacomo 574
    iq_init(&lev->b[i].tasks, NULL, 0);
241 giacomo 575
  }
576
 
577
  lev->n = n;
578
  lev->freebudgets = 0;
579
 
580
  for (i=0; i<MAX_PROC; i++)
581
    lev->tb[i] = NIL;
582
 
583
  lev->U = 0;
584
  lev->Uf = 0;
585
  lev->cap_lev = NIL;
279 giacomo 586
  NULL_TIMESPEC(&lev->cap_lasttime);
241 giacomo 587
  lev->scheduling_level = master;
588
 
589
  return l;
590
 
591
}
592
 
253 giacomo 593
int GRUBSTAR_setbudget(LEVEL l, TIME Q, TIME T, LEVEL local_scheduler_level, int scheduler_id)
241 giacomo 594
{
253 giacomo 595
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 596
  int r;
597
 
253 giacomo 598
  #ifdef GRUBSTAR_DEBUG
599
    kern_printf("(GS:SetBud)");
241 giacomo 600
  #endif
601
 
602
  for (r = 0; r < lev->n; r++)
603
    if (lev->b[r].Q == 0) break;
604
 
605
  if (r != lev->n) {
606
    bandwidth_t b;
607
    b = (MAX_BANDWIDTH / T) * Q;
608
 
609
    /* really update lev->U, checking an overflow... */
610
    if (Q< T && MAX_BANDWIDTH - lev->U > b) {
611
 
612
      lev->U += b;
613
      lev->Uf += b;
614
      lev->freebudgets++;
615
 
616
      lev->b[r].Q = Q;
617
      lev->b[r].T = T;
277 giacomo 618
      lev->b[r].Ub = b;
241 giacomo 619
      lev->b[r].avail = Q;
253 giacomo 620
      lev->b[r].flags = GRUBSTAR_ACTIVE;
241 giacomo 621
      lev->b[r].loc_sched_id = scheduler_id;
622
      lev->b[r].loc_sched_level = local_scheduler_level;
276 giacomo 623
      lev->b[r].last_reclaiming = 0;  
624
 
241 giacomo 625
      return r;
626
    }
627
    else
628
      return -2;
629
  }
630
  else
631
    return -1;
632
}
633
 
253 giacomo 634
int GRUBSTAR_removebudget(LEVEL l, int budget)
241 giacomo 635
{
636
 
253 giacomo 637
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 638
 
639
  bandwidth_t b;
640
 
641
  b = (MAX_BANDWIDTH / lev->b[budget].T) * lev->b[budget].Q;
642
 
643
  lev->U -= b;
644
 
645
  lev->b[budget].Q = 0;
646
  lev->b[budget].T = 0;
277 giacomo 647
  lev->b[budget].Ub = 0;
241 giacomo 648
  NULL_TIMESPEC(&lev->b[budget].dline);
649
  lev->b[budget].dline_timer = NIL;
650
  lev->b[budget].avail = 0;
651
  lev->b[budget].current = -1;
253 giacomo 652
  lev->b[budget].flags = GRUBSTAR_ACTIVE;
277 giacomo 653
  lev->b[budget].last_reclaiming = 0;
241 giacomo 654
 
655
  return 0;
656
 
657
}
658
 
253 giacomo 659
int GRUBSTAR_adjust_budget(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
  lev->b[budget].Q = Q;
665
  lev->b[budget].T = T;
277 giacomo 666
  lev->b[budget].Ub = (MAX_BANDWIDTH / T) * Q;
241 giacomo 667
 
668
  return 0;
669
 
670
}
671
 
253 giacomo 672
int GRUBSTAR_getbudgetinfo(LEVEL l, TIME *Q, TIME *T, int budget)
241 giacomo 673
{
674
 
253 giacomo 675
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 676
 
677
  *Q = lev->b[budget].Q;
678
  *T = lev->b[budget].T;
679
 
680
  return 0;
681
 
682
}
683
 
276 giacomo 684
int GRUBSTAR_get_last_reclaiming(LEVEL l, PID p)
267 giacomo 685
{
686
 
687
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
688
 
276 giacomo 689
  return lev->b[lev->tb[p]].last_reclaiming;
267 giacomo 690
 
691
}
692
 
253 giacomo 693
int GRUBSTAR_is_active(LEVEL l, int budget)
241 giacomo 694
{
253 giacomo 695
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 696
 
697
  return lev->b[budget].flags;
698
 
699
}
700
 
253 giacomo 701
int GRUBSTAR_get_local_scheduler_level_from_budget(LEVEL l, int budget)
241 giacomo 702
{
253 giacomo 703
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 704
 
705
  return lev->b[budget].loc_sched_level;
706
 
707
}
708
 
253 giacomo 709
int GRUBSTAR_get_local_scheduler_level_from_pid(LEVEL l, PID p)
241 giacomo 710
{
253 giacomo 711
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 712
 
713
  return lev->b[lev->tb[p]].loc_sched_level;
714
 
715
}
716
 
253 giacomo 717
int GRUBSTAR_get_local_scheduler_id_from_budget(LEVEL l, int budget)
241 giacomo 718
{
253 giacomo 719
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 720
 
721
  return lev->b[budget].loc_sched_id;
722
 
723
}
724
 
253 giacomo 725
int GRUBSTAR_get_local_scheduler_id_from_pid(LEVEL l, PID p)
241 giacomo 726
{
253 giacomo 727
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 728
 
729
  return lev->b[lev->tb[p]].loc_sched_id;
730
 
731
}
732