Subversion Repositories shark

Rev

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