Subversion Repositories shark

Rev

Rev 273 | Rev 276 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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