Subversion Repositories shark

Rev

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