Subversion Repositories shark

Rev

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