Subversion Repositories shark

Rev

Rev 663 | Rev 665 | 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 {
661 giacomo 47
  TIME Q;                 /* Budget */
48
  TIME T;                 /* Period */
49
  TIME D;                 /* Deadline */
50
  bandwidth_t Ub;         /* Bandwidth */
241 giacomo 51
 
661 giacomo 52
  struct timespec dline;     /* deadline */
53
  struct timespec replenish; /* server period */
54
  int replenish_timer;
241 giacomo 55
  int vtimer;
56
  int avail;              /* current budget */
57
 
253 giacomo 58
  LEVEL l;                /* Current GRUBSTAR level */
241 giacomo 59
  int loc_sched_id;       /* Local scheduler id */
60
  LEVEL loc_sched_level;  /* Local scheduler level */
276 giacomo 61
 
62
  int last_reclaiming;
241 giacomo 63
 
64
  PID current;            /* the task currently put in execution */
65
  int flags;
66
 
67
  IQUEUE tasks;           /* a FIFO queue for the tasks handled
68
                             using the budget */
69
 
70
};
71
 
253 giacomo 72
#define GRUBSTAR_NOACTIVE   0
73
#define GRUBSTAR_ACTIVE     1
74
#define GRUBSTAR_RECLAIMING 2
241 giacomo 75
 
76
typedef struct {
77
  level_des l;               /* the standard level descriptor */
78
 
79
  struct budget_struct *b;   /* the budgets! */
80
  int n;                     /* the maximum index for the budgets */
81
  int freebudgets;           /* number of free budgets; starts from n */
82
 
83
  int tb[MAX_PROC];          /* link task->budget (used in guest_end) */
84
 
267 giacomo 85
  bandwidth_t U;             /*+ the used bandwidth by the server       +*/
86
  bandwidth_t Uf;            /*+ the actual used bandwidth by the server       +*/
241 giacomo 87
 
88
  int cap_lev;
279 giacomo 89
  struct timespec cap_lasttime;
241 giacomo 90
 
91
  LEVEL scheduling_level;
92
 
253 giacomo 93
} GRUBSTAR_level_des;
241 giacomo 94
 
95
 
661 giacomo 96
static void GRUBSTAR_timer_hardreservation(void *a)
241 giacomo 97
{
98
  struct budget_struct *b = a;
99
  PID p;
253 giacomo 100
  GRUBSTAR_level_des *lev;
101
 
102
  lev = (GRUBSTAR_level_des *)(level_table[b->l]);
103
 
104
  #ifdef GRUBSTAR_DEBUG
105
    kern_printf("(GS:HrdRes:");  
241 giacomo 106
  #endif
107
 
661 giacomo 108
  b->replenish_timer = NIL;
241 giacomo 109
 
396 giacomo 110
  b->last_reclaiming = 0;
241 giacomo 111
  b->avail += b->Q;
112
  if (b->avail > b->Q) b->avail = b->Q;
664 trimarchi 113
 
114
  if (b->avail > 0) b->flags = GRUBSTAR_ACTIVE;
382 giacomo 115
 
116
  /* Tracer */
502 giacomo 117
  TRACER_LOGEVENT(FTrace_EVT_server_replenish,0,(unsigned int)(b));
382 giacomo 118
 
278 giacomo 119
  if (b->flags==GRUBSTAR_RECLAIMING && b->avail>0)
388 giacomo 120
    if (lev->Uf < lev->U) lev->Uf += b->Ub;
241 giacomo 121
 
122
  if (b->current == NIL && b->flags) {
123
      if (iq_query_first(&(b->tasks)) != NIL) {
124
        JOB_TASK_MODEL job;
276 giacomo 125
 
241 giacomo 126
        p = iq_getfirst(&b->tasks);
127
 
253 giacomo 128
        #ifdef GRUBSTAR_DEBUG
129
          kern_printf("%d",p);
241 giacomo 130
        #endif
664 trimarchi 131
        TIMESPEC_ASSIGN(&b->dline, &b->replenish);
661 giacomo 132
        ADDUSEC2TIMESPEC(b->D, &b->dline);
664 trimarchi 133
        ADDUSEC2TIMESPEC(b->T, &b->replenish);
241 giacomo 134
 
664 trimarchi 135
 
241 giacomo 136
        b->current = p;
137
 
138
        job_task_default_model(job, b->dline);
661 giacomo 139
        //job_task_def_noexc(job);
241 giacomo 140
        level_table[ lev->scheduling_level ]->
141
          private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
142
 
143
        event_need_reschedule();
144
 
145
    }
146
  }
147
 
253 giacomo 148
  if (b->flags == GRUBSTAR_NOACTIVE) {
661 giacomo 149
    kern_gettime(&b->replenish);
150
    ADDUSEC2TIMESPEC(b->T, &b->replenish);
241 giacomo 151
 
661 giacomo 152
    b->replenish_timer=kern_event_post(&b->replenish, GRUBSTAR_timer_hardreservation, b);
241 giacomo 153
  }
154
 
253 giacomo 155
  #ifdef GRUBSTAR_DEBUG
156
    kern_printf(")");
241 giacomo 157
  #endif
158
 
159
}
160
 
253 giacomo 161
void GRUBSTAR_ANC(void *arg)
241 giacomo 162
{
163
  struct budget_struct *b = arg;
253 giacomo 164
  GRUBSTAR_level_des *lev=(GRUBSTAR_level_des *)level_table[b->l];
241 giacomo 165
 
253 giacomo 166
  #ifdef GRUBSTAR_DEBUG
343 giacomo 167
    kern_printf("(GS:Rec:");
241 giacomo 168
  #endif
169
 
170
  b->vtimer = NIL;
287 trimarchi 171
 
267 giacomo 172
  if (b->current == NIL && iq_query_first(&(b->tasks)) == NIL && b->flags != GRUBSTAR_RECLAIMING) {
396 giacomo 173
     event_need_reschedule();
502 giacomo 174
     TRACER_LOGEVENT(FTrace_EVT_server_reclaiming,0,(unsigned int)b);
277 giacomo 175
     b->flags = GRUBSTAR_RECLAIMING;
176
     lev->Uf -= b->Ub;
241 giacomo 177
  }
178
 
253 giacomo 179
  #ifdef GRUBSTAR_DEBUG
180
    kern_printf(")");
241 giacomo 181
  #endif
182
 
183
 
184
}
185
 
253 giacomo 186
static void GRUBSTAR_activation(GRUBSTAR_level_des *lev,
241 giacomo 187
                           PID p,
188
                           struct timespec *acttime)
189
{
190
  JOB_TASK_MODEL job;
191
  struct budget_struct *b = &lev->b[lev->tb[p]];
253 giacomo 192
  TIME t;
193
  struct timespec t2,t3;
241 giacomo 194
 
661 giacomo 195
  mul32div32to32(b->D,b->avail,b->Q,t);
253 giacomo 196
  t3.tv_sec = t / 1000000;
197
  t3.tv_nsec = (t % 1000000) * 1000;
241 giacomo 198
 
339 giacomo 199
  #ifdef GRUBSTAR_DEBUG
200
    kern_printf("(GS:Act %d)",p);
201
  #endif
338 giacomo 202
 
502 giacomo 203
  TRACER_LOGEVENT(FTrace_EVT_server_active,0,(unsigned int)b);
382 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) ) {
661 giacomo 211
       TIMESPEC_ASSIGN(&b->replenish, acttime);
212
       ADDUSEC2TIMESPEC(b->T, &b->replenish);
241 giacomo 213
       TIMESPEC_ASSIGN(&b->dline, acttime);
661 giacomo 214
       ADDUSEC2TIMESPEC(b->D, &b->dline);
396 giacomo 215
       b->avail = b->Q;
216
       b->last_reclaiming = 0;
276 giacomo 217
  }
218
 
278 giacomo 219
  if (b->flags==GRUBSTAR_RECLAIMING)
388 giacomo 220
    if (lev->Uf < lev->U) lev->Uf += b->Ub;
241 giacomo 221
 
276 giacomo 222
  b->flags=GRUBSTAR_ACTIVE;
241 giacomo 223
 
224
  /* record the current task inserted in the master module */
225
  b->current = p;
275 trimarchi 226
 
241 giacomo 227
  job_task_default_model(job, b->dline);
661 giacomo 228
  //job_task_def_noexc(job);
241 giacomo 229
  level_table[ lev->scheduling_level ]->
230
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
231
 
232
}
233
 
253 giacomo 234
static void GRUBSTAR_account_capacity(GRUBSTAR_level_des *lev, PID p)
241 giacomo 235
{
236
  struct timespec ty;
237
  TIME tx;
238
  struct budget_struct *b = &lev->b[lev->tb[p]];
276 giacomo 239
  TIME t;
240
  struct timespec t2,t3;
241 giacomo 241
 
276 giacomo 242
  if (b->vtimer!=NIL) kern_event_delete(b->vtimer);
243
  b->vtimer=NIL;
244
 
296 trimarchi 245
  if (lev->cap_lev != NIL) {
241 giacomo 246
    kern_event_delete(lev->cap_lev);
247
    lev->cap_lev = NIL;
248
  }
249
 
279 giacomo 250
  SUBTIMESPEC(&schedule_time, &lev->cap_lasttime, &ty);
241 giacomo 251
  tx = TIMESPEC2USEC(&ty);
252
 
402 giacomo 253
  b->avail -= tx;
266 trimarchi 254
 
253 giacomo 255
  #ifdef GRUBSTAR_DEBUG
402 giacomo 256
    kern_printf("(GS:Cap p%d av=%d tx=%d)", p, b->avail,(int)tx);
241 giacomo 257
  #endif
258
 
382 giacomo 259
  if (b->avail <= 0) {
502 giacomo 260
    TRACER_LOGEVENT(FTrace_EVT_server_exhaust,0,(unsigned int)(b));
382 giacomo 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);
661 giacomo 267
    ADDUSEC2TIMESPEC(b->D, &b->dline);
268
    TIMESPEC_ASSIGN(&b->replenish, &schedule_time);
269
    ADDUSEC2TIMESPEC(b->T, &b->replenish);
241 giacomo 270
  }
271
 
661 giacomo 272
  if (b->flags == GRUBSTAR_NOACTIVE && b->replenish_timer == NIL)  {
273
    b->replenish_timer=kern_event_post(&b->replenish, GRUBSTAR_timer_hardreservation, b);
276 giacomo 274
  } else {
661 giacomo 275
    mul32div32to32(b->D,b->avail,b->Q,t);
276 giacomo 276
    t3.tv_sec = t / 1000000;
277
    t3.tv_nsec = (t % 1000000) * 1000;
278
    SUBTIMESPEC(&b->dline, &t3, &t2);
279
    b->vtimer = kern_event_post(&t2, GRUBSTAR_ANC, b);
241 giacomo 280
  }
281
}
282
 
283
static void capacity_handler(void *l)
284
{
285
 
253 giacomo 286
  GRUBSTAR_level_des *lev = l;
241 giacomo 287
  lev->cap_lev = NIL;
298 giacomo 288
  #ifdef GRUBSTAR_DEBUG
289
    kern_printf("(*)");
290
  #endif  
241 giacomo 291
  event_need_reschedule();
292
 
293
}
294
 
253 giacomo 295
static int GRUBSTAR_private_eligible(LEVEL l, PID p)
241 giacomo 296
{
253 giacomo 297
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
296 trimarchi 298
  struct budget_struct *b=&lev->b[lev->tb[p]];
298 giacomo 299
  JOB_TASK_MODEL job;
300
 
301
  if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
302
      #ifdef GRUBSTAR_DEBUG 
288 giacomo 303
        kern_printf("(GS:Eli:%d)",p);
298 giacomo 304
      #endif
241 giacomo 305
      if (lev->cap_lev!=NIL) {
306
        kern_event_delete(lev->cap_lev);
307
        lev->cap_lev=NIL;
308
      }
309
 
310
      /* we kill the current activation */
311
      level_table[ lev->scheduling_level ]->
312
        private_extract(lev->scheduling_level, p);
313
      /* we modify the deadline ... */
298 giacomo 314
      kern_gettime(&b->dline);
661 giacomo 315
      ADDUSEC2TIMESPEC(b->D, &b->dline);
241 giacomo 316
 
317
      /* and the capacity */
318
      b->avail = b->Q;
396 giacomo 319
      b->last_reclaiming = 0;
382 giacomo 320
 
321
      /* Tracer */
502 giacomo 322
      TRACER_LOGEVENT(FTrace_EVT_server_replenish,0,(unsigned int)(b));
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
 
661 giacomo 330
      if (b->replenish_timer!=NIL)  {
331
        kern_event_delete(b->replenish_timer);
332
        b->replenish_timer=NIL;
241 giacomo 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);
661 giacomo 343
      //job_task_def_noexc(job);
241 giacomo 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;
402 giacomo 442
  int temp;
241 giacomo 443
 
253 giacomo 444
  #ifdef GRUBSTAR_DEBUG
445
    kern_printf("(GS:Dsp:%d)", p);
241 giacomo 446
  #endif
447
 
448
  /* the current task (that is the only one inserted in the master module
449
     for the corresponding budget) is dispatched. Note that the current
450
     task is not inserted in any FIFO queue, so the task does not have to
451
     be extracted! */
452
 
453
  /* ... then, we dispatch it to the master level */
296 trimarchi 454
  if (!nostop)
455
        level_table[ lev->scheduling_level ]->
456
                private_dispatch(lev->scheduling_level,p,nostop);
241 giacomo 457
 
296 trimarchi 458
  TIMESPEC_ASSIGN(&ty, &schedule_time);
459
  TIMESPEC_ASSIGN(&lev->cap_lasttime, &schedule_time);
460
 
241 giacomo 461
  /* ...and finally, we have to post a capacity event */
296 trimarchi 462
 
402 giacomo 463
  /* Reclaiming Computation */
464
 
465
  if ((lev->U - lev->Uf) < 0) {
466
    cprintf("GRUBSTAR Error: Bad Reclaiming Computation\n");
467
    sys_end();
468
  }
469
 
470
  mul32div32to32(lev->b[lev->tb[exec]].avail,(lev->U-lev->Uf),MAX_BANDWIDTH,lev->b[lev->tb[exec]].last_reclaiming);
471
 
472
  if (lev->b[lev->tb[exec]].last_reclaiming > 0)
502 giacomo 473
    TRACER_LOGEVENT(FTrace_EVT_server_using_rec,(unsigned short int)lev->b[lev->tb[exec]].last_reclaiming,(unsigned int)(&lev->b[lev->tb[exec]]));
402 giacomo 474
 
475
  temp = lev->b[lev->tb[exec]].avail + lev->b[lev->tb[exec]].last_reclaiming;
476
 
477
  ADDUSEC2TIMESPEC(temp,&ty);
478
 
296 trimarchi 479
  lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
241 giacomo 480
 
481
}
482
 
253 giacomo 483
static void GRUBSTAR_private_epilogue(LEVEL l, PID p)
241 giacomo 484
{
253 giacomo 485
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
296 trimarchi 486
  struct budget_struct *b;
487
  int skip_epilog;
488
  skip_epilog=0;
489
 
253 giacomo 490
  #ifdef GRUBSTAR_DEBUG
296 trimarchi 491
     kern_printf("(GS:Epi:%d)",p);
241 giacomo 492
  #endif
493
 
296 trimarchi 494
  if (p==exec) b = &lev->b[lev->tb[p]];
495
     else if (lev->tb[exec]!=NIL)  {
496
          b = &lev->b[lev->tb[exec]];
497
          p=exec;
498
          skip_epilog=1;
499
       }
500
       else return;    
241 giacomo 501
 
502
 
298 giacomo 503
    GRUBSTAR_account_capacity(lev,p);
241 giacomo 504
    if (b->flags)  {
276 giacomo 505
 
241 giacomo 506
      /* there is capacity available, maybe it is simply a preemption;
507
         the task have to return to the ready queue */
296 trimarchi 508
      if (!skip_epilog)
509
        level_table[ lev->scheduling_level ]->
510
          private_epilogue(lev->scheduling_level,p); //else kern_printf("(SP)");
241 giacomo 511
 
512
    } else {
513
      /* we kill the current activation */
298 giacomo 514
      #ifdef GRUBSTAR_DEBUG
663 giacomo 515
        kern_printf("(GS:HRExt:%d)",p);
298 giacomo 516
      #endif      
241 giacomo 517
      level_table[ lev->scheduling_level ]->
296 trimarchi 518
          private_extract(lev->scheduling_level, p);    
241 giacomo 519
 
520
      iq_insertfirst(p, &b->tasks);
521
      b->current = NIL;
522
 
523
    }
524
 
525
}
526
 
267 giacomo 527
static int GRUBSTAR_public_message(LEVEL l, PID p, void *m)
528
{
529
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
530
  struct budget_struct *b = &lev->b[lev->tb[p]];
531
 
532
  switch((long)(m)) {
533
 
534
    case (long)(NULL):
338 giacomo 535
 
339 giacomo 536
      #ifdef GRUBSTAR_DEBUG
338 giacomo 537
        kern_printf("(GS:EndCycle:%d:%d)",p,lev->tb[p]);
339 giacomo 538
      #endif     
267 giacomo 539
 
540
      if (b->current == NIL && iq_query_first(&(b->tasks)) == NIL && b->flags != GRUBSTAR_RECLAIMING) {
342 giacomo 541
 
542
        if (b->vtimer!=NIL)  {
543
            kern_event_delete(b->vtimer);
544
            b->vtimer=NIL;
545
        }
546
 
502 giacomo 547
        TRACER_LOGEVENT(FTrace_EVT_server_reclaiming,0,(unsigned int)(b));
267 giacomo 548
        b->flags = GRUBSTAR_RECLAIMING;
277 giacomo 549
        lev->Uf -= b->Ub;
342 giacomo 550
 
267 giacomo 551
      }
552
 
553
      break;
554
 
555
    case 1:
556
 
557
      break;
558
 
559
  }
560
 
561
  return 0;
562
 
563
}
564
 
241 giacomo 565
/* Registration functions }*/
566
 
253 giacomo 567
LEVEL GRUBSTAR_register_level(int n, LEVEL master)
241 giacomo 568
{
569
  LEVEL l;            /* the level that we register */
253 giacomo 570
  GRUBSTAR_level_des *lev;  /* for readableness only */
241 giacomo 571
  PID i;              /* a counter */
572
 
253 giacomo 573
  printk("GRUBSTAR_register_level\n");
241 giacomo 574
 
575
  /* request an entry in the level_table */
253 giacomo 576
  l = level_alloc_descriptor(sizeof(GRUBSTAR_level_des));
241 giacomo 577
 
253 giacomo 578
  lev = (GRUBSTAR_level_des *)level_table[l];
241 giacomo 579
 
580
  /* fill the standard descriptor */
253 giacomo 581
  lev->l.private_insert   = GRUBSTAR_private_insert;
582
  lev->l.private_extract  = GRUBSTAR_private_extract;
583
  lev->l.private_eligible = GRUBSTAR_private_eligible;
584
  lev->l.private_dispatch = GRUBSTAR_private_dispatch;
585
  lev->l.private_epilogue = GRUBSTAR_private_epilogue;
241 giacomo 586
 
298 giacomo 587
  lev->l.public_guarantee = NULL;
267 giacomo 588
  lev->l.public_message = GRUBSTAR_public_message;
241 giacomo 589
 
590
  lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
591
 
592
  for (i=0; i<n; i++) {
593
    lev->b[i].Q = 0;
594
    lev->b[i].T = 0;
661 giacomo 595
    lev->b[i].D = 0;
277 giacomo 596
    lev->b[i].Ub = 0;
241 giacomo 597
    NULL_TIMESPEC(&lev->b[i].dline);
661 giacomo 598
    NULL_TIMESPEC(&lev->b[i].replenish);
599
    lev->b[i].replenish_timer = NIL;
298 giacomo 600
    lev->b[i].vtimer = NIL;
241 giacomo 601
    lev->b[i].avail = 0;
602
    lev->b[i].current = -1;
253 giacomo 603
    lev->b[i].flags = GRUBSTAR_ACTIVE;
276 giacomo 604
    lev->b[i].l = l;
605
    lev->b[i].last_reclaiming = 0;
253 giacomo 606
    iq_init(&lev->b[i].tasks, NULL, 0);
241 giacomo 607
  }
608
 
609
  lev->n = n;
610
  lev->freebudgets = 0;
611
 
612
  for (i=0; i<MAX_PROC; i++)
613
    lev->tb[i] = NIL;
614
 
615
  lev->U = 0;
616
  lev->Uf = 0;
617
  lev->cap_lev = NIL;
279 giacomo 618
  NULL_TIMESPEC(&lev->cap_lasttime);
241 giacomo 619
  lev->scheduling_level = master;
620
 
621
  return l;
622
 
623
}
624
 
661 giacomo 625
int GRUBSTAR_setbudget(LEVEL l, TIME Q, TIME T, TIME D, LEVEL local_scheduler_level, int scheduler_id)
241 giacomo 626
{
253 giacomo 627
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 628
  int r;
629
 
339 giacomo 630
  #ifdef GRUBSTAR_DEBUG
253 giacomo 631
    kern_printf("(GS:SetBud)");
339 giacomo 632
  #endif
241 giacomo 633
 
634
  for (r = 0; r < lev->n; r++)
635
    if (lev->b[r].Q == 0) break;
636
 
637
  if (r != lev->n) {
638
    bandwidth_t b;
343 giacomo 639
    mul32div32to32(MAX_BANDWIDTH,Q,T,b);
241 giacomo 640
 
641
    /* really update lev->U, checking an overflow... */
407 giacomo 642
    if (Q< T /* && MAX_BANDWIDTH - lev->U > b */) {
241 giacomo 643
 
644
      lev->U += b;
396 giacomo 645
      //lev->Uf += b; Start in Reclaiming
241 giacomo 646
      lev->freebudgets++;
647
 
648
      lev->b[r].Q = Q;
649
      lev->b[r].T = T;
661 giacomo 650
      lev->b[r].D = D;
277 giacomo 651
      lev->b[r].Ub = b;
241 giacomo 652
      lev->b[r].avail = Q;
396 giacomo 653
      lev->b[r].flags = GRUBSTAR_RECLAIMING;
241 giacomo 654
      lev->b[r].loc_sched_id = scheduler_id;
655
      lev->b[r].loc_sched_level = local_scheduler_level;
382 giacomo 656
      lev->b[r].last_reclaiming = 0;
657
 
241 giacomo 658
      return r;
659
    }
660
    else
661
      return -2;
662
  }
663
  else
664
    return -1;
665
}
666
 
253 giacomo 667
int GRUBSTAR_removebudget(LEVEL l, int budget)
241 giacomo 668
{
669
 
253 giacomo 670
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 671
 
672
  bandwidth_t b;
673
 
343 giacomo 674
  mul32div32to32(MAX_BANDWIDTH,lev->b[budget].Q,lev->b[budget].T,b);
241 giacomo 675
 
676
  lev->U -= b;
396 giacomo 677
  if (lev->b[budget].flags != GRUBSTAR_RECLAIMING) lev->Uf -= b;
241 giacomo 678
 
679
  lev->b[budget].Q = 0;
680
  lev->b[budget].T = 0;
661 giacomo 681
  lev->b[budget].D = 0;
277 giacomo 682
  lev->b[budget].Ub = 0;
241 giacomo 683
  NULL_TIMESPEC(&lev->b[budget].dline);
661 giacomo 684
  NULL_TIMESPEC(&lev->b[budget].replenish);
685
  lev->b[budget].replenish_timer = NIL;
241 giacomo 686
  lev->b[budget].avail = 0;
687
  lev->b[budget].current = -1;
396 giacomo 688
  lev->b[budget].flags = GRUBSTAR_RECLAIMING;
277 giacomo 689
  lev->b[budget].last_reclaiming = 0;
241 giacomo 690
 
691
  return 0;
692
 
693
}
694
 
402 giacomo 695
/* Change Q and T parameters of a budget
696
 * It returns the time to wait before the change is effective
697
 */
661 giacomo 698
int GRUBSTAR_adjust_budget(LEVEL l, TIME Q, TIME T, TIME D, int budget)
241 giacomo 699
{
700
 
253 giacomo 701
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
298 giacomo 702
  bandwidth_t b;
403 trimarchi 703
  TIME OldPeriod =  TIMESPEC2USEC(&lev->b[budget].dline);
241 giacomo 704
 
343 giacomo 705
  mul32div32to32(MAX_BANDWIDTH,lev->b[budget].Q,lev->b[budget].T,b);
298 giacomo 706
 
707
  lev->U -= b;
396 giacomo 708
  if (lev->b[budget].flags != GRUBSTAR_RECLAIMING) lev->Uf -= b;
298 giacomo 709
 
241 giacomo 710
  lev->b[budget].Q = Q;
711
  lev->b[budget].T = T;
661 giacomo 712
  lev->b[budget].D = D;
343 giacomo 713
  mul32div32to32(MAX_BANDWIDTH,Q,T,lev->b[budget].Ub);
342 giacomo 714
 
298 giacomo 715
  lev->U += lev->b[budget].Ub;
396 giacomo 716
  if (lev->b[budget].flags != GRUBSTAR_RECLAIMING) lev->Uf += lev->b[budget].Ub;  
241 giacomo 717
 
402 giacomo 718
  if (lev->b[budget].flags == GRUBSTAR_NOACTIVE)
719
    return 0;
720
  if (lev->b[budget].flags == GRUBSTAR_RECLAIMING)
721
    return 0;
722
 
723
  return OldPeriod;
241 giacomo 724
 
725
}
726
 
661 giacomo 727
int GRUBSTAR_getbudgetinfo(LEVEL l, TIME *Q, TIME *T, TIME *D, int budget)
241 giacomo 728
{
729
 
253 giacomo 730
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 731
 
732
  *Q = lev->b[budget].Q;
733
  *T = lev->b[budget].T;
661 giacomo 734
  *D = lev->b[budget].D;
241 giacomo 735
 
736
  return 0;
737
 
738
}
739
 
276 giacomo 740
int GRUBSTAR_get_last_reclaiming(LEVEL l, PID p)
267 giacomo 741
{
742
 
743
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
744
 
276 giacomo 745
  return lev->b[lev->tb[p]].last_reclaiming;
267 giacomo 746
 
747
}
748
 
253 giacomo 749
int GRUBSTAR_is_active(LEVEL l, int budget)
241 giacomo 750
{
253 giacomo 751
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 752
 
753
  return lev->b[budget].flags;
754
 
755
}
756
 
340 giacomo 757
int GRUBSTAR_get_remain_capacity(LEVEL l, int budget)
758
{
759
 
760
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
761
 
762
  return lev->b[budget].avail;
763
 
764
}
765
 
253 giacomo 766
int GRUBSTAR_get_local_scheduler_level_from_budget(LEVEL l, int budget)
241 giacomo 767
{
253 giacomo 768
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 769
 
770
  return lev->b[budget].loc_sched_level;
771
 
772
}
773
 
253 giacomo 774
int GRUBSTAR_get_local_scheduler_level_from_pid(LEVEL l, PID p)
241 giacomo 775
{
253 giacomo 776
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 777
 
778
  return lev->b[lev->tb[p]].loc_sched_level;
779
 
780
}
781
 
253 giacomo 782
int GRUBSTAR_get_local_scheduler_id_from_budget(LEVEL l, int budget)
241 giacomo 783
{
253 giacomo 784
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 785
 
786
  return lev->b[budget].loc_sched_id;
787
 
788
}
789
 
403 trimarchi 790
/* return the sum of servers bandwith */
791
bandwidth_t GRUBSTAR_return_bandwidth(LEVEL l) {
792
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
793
 
794
  return lev->U;
795
}
796
 
253 giacomo 797
int GRUBSTAR_get_local_scheduler_id_from_pid(LEVEL l, PID p)
241 giacomo 798
{
253 giacomo 799
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 800
 
801
  return lev->b[lev->tb[p]].loc_sched_id;
802
 
803
}
804