Subversion Repositories shark

Rev

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