Subversion Repositories shark

Rev

Rev 665 | Rev 804 | 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
665 giacomo 131
 
132
        kern_gettime(&b->replenish);
664 trimarchi 133
        TIMESPEC_ASSIGN(&b->dline, &b->replenish);
661 giacomo 134
        ADDUSEC2TIMESPEC(b->D, &b->dline);
664 trimarchi 135
        ADDUSEC2TIMESPEC(b->T, &b->replenish);
241 giacomo 136
 
664 trimarchi 137
 
241 giacomo 138
        b->current = p;
139
 
140
        job_task_default_model(job, b->dline);
784 giacomo 141
        job_task_def_noexc(job);
241 giacomo 142
        level_table[ lev->scheduling_level ]->
143
          private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
144
 
145
        event_need_reschedule();
146
 
147
    }
148
  }
149
 
253 giacomo 150
  if (b->flags == GRUBSTAR_NOACTIVE) {
661 giacomo 151
    kern_gettime(&b->replenish);
152
    ADDUSEC2TIMESPEC(b->T, &b->replenish);
241 giacomo 153
 
661 giacomo 154
    b->replenish_timer=kern_event_post(&b->replenish, GRUBSTAR_timer_hardreservation, b);
241 giacomo 155
  }
156
 
253 giacomo 157
  #ifdef GRUBSTAR_DEBUG
158
    kern_printf(")");
241 giacomo 159
  #endif
160
 
161
}
162
 
253 giacomo 163
void GRUBSTAR_ANC(void *arg)
241 giacomo 164
{
165
  struct budget_struct *b = arg;
253 giacomo 166
  GRUBSTAR_level_des *lev=(GRUBSTAR_level_des *)level_table[b->l];
241 giacomo 167
 
253 giacomo 168
  #ifdef GRUBSTAR_DEBUG
343 giacomo 169
    kern_printf("(GS:Rec:");
241 giacomo 170
  #endif
171
 
172
  b->vtimer = NIL;
287 trimarchi 173
 
267 giacomo 174
  if (b->current == NIL && iq_query_first(&(b->tasks)) == NIL && b->flags != GRUBSTAR_RECLAIMING) {
396 giacomo 175
     event_need_reschedule();
502 giacomo 176
     TRACER_LOGEVENT(FTrace_EVT_server_reclaiming,0,(unsigned int)b);
277 giacomo 177
     b->flags = GRUBSTAR_RECLAIMING;
178
     lev->Uf -= b->Ub;
241 giacomo 179
  }
180
 
253 giacomo 181
  #ifdef GRUBSTAR_DEBUG
182
    kern_printf(")");
241 giacomo 183
  #endif
184
 
185
 
186
}
187
 
253 giacomo 188
static void GRUBSTAR_activation(GRUBSTAR_level_des *lev,
241 giacomo 189
                           PID p,
190
                           struct timespec *acttime)
191
{
192
  JOB_TASK_MODEL job;
193
  struct budget_struct *b = &lev->b[lev->tb[p]];
253 giacomo 194
  TIME t;
195
  struct timespec t2,t3;
241 giacomo 196
 
661 giacomo 197
  mul32div32to32(b->D,b->avail,b->Q,t);
253 giacomo 198
  t3.tv_sec = t / 1000000;
199
  t3.tv_nsec = (t % 1000000) * 1000;
241 giacomo 200
 
339 giacomo 201
  #ifdef GRUBSTAR_DEBUG
202
    kern_printf("(GS:Act %d)",p);
203
  #endif
338 giacomo 204
 
502 giacomo 205
  TRACER_LOGEVENT(FTrace_EVT_server_active,0,(unsigned int)b);
382 giacomo 206
 
275 trimarchi 207
  if (b->vtimer!=NIL) kern_event_delete(b->vtimer);
208
  b->vtimer=NIL;
209
 
253 giacomo 210
  SUBTIMESPEC(&b->dline, acttime, &t2);
211
  if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) ||
241 giacomo 212
       /* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
661 giacomo 213
       TIMESPEC_ASSIGN(&b->replenish, acttime);
214
       ADDUSEC2TIMESPEC(b->T, &b->replenish);
241 giacomo 215
       TIMESPEC_ASSIGN(&b->dline, acttime);
661 giacomo 216
       ADDUSEC2TIMESPEC(b->D, &b->dline);
396 giacomo 217
       b->avail = b->Q;
218
       b->last_reclaiming = 0;
276 giacomo 219
  }
220
 
278 giacomo 221
  if (b->flags==GRUBSTAR_RECLAIMING)
388 giacomo 222
    if (lev->Uf < lev->U) lev->Uf += b->Ub;
241 giacomo 223
 
276 giacomo 224
  b->flags=GRUBSTAR_ACTIVE;
241 giacomo 225
 
226
  /* record the current task inserted in the master module */
227
  b->current = p;
275 trimarchi 228
 
241 giacomo 229
  job_task_default_model(job, b->dline);
784 giacomo 230
  job_task_def_noexc(job);
241 giacomo 231
  level_table[ lev->scheduling_level ]->
232
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
233
 
234
}
235
 
253 giacomo 236
static void GRUBSTAR_account_capacity(GRUBSTAR_level_des *lev, PID p)
241 giacomo 237
{
238
  struct timespec ty;
239
  TIME tx;
240
  struct budget_struct *b = &lev->b[lev->tb[p]];
276 giacomo 241
  TIME t;
242
  struct timespec t2,t3;
241 giacomo 243
 
276 giacomo 244
  if (b->vtimer!=NIL) kern_event_delete(b->vtimer);
245
  b->vtimer=NIL;
246
 
296 trimarchi 247
  if (lev->cap_lev != NIL) {
241 giacomo 248
    kern_event_delete(lev->cap_lev);
249
    lev->cap_lev = NIL;
250
  }
251
 
279 giacomo 252
  SUBTIMESPEC(&schedule_time, &lev->cap_lasttime, &ty);
241 giacomo 253
  tx = TIMESPEC2USEC(&ty);
254
 
402 giacomo 255
  b->avail -= tx;
266 trimarchi 256
 
253 giacomo 257
  #ifdef GRUBSTAR_DEBUG
402 giacomo 258
    kern_printf("(GS:Cap p%d av=%d tx=%d)", p, b->avail,(int)tx);
241 giacomo 259
  #endif
260
 
382 giacomo 261
  if (b->avail <= 0) {
502 giacomo 262
    TRACER_LOGEVENT(FTrace_EVT_server_exhaust,0,(unsigned int)(b));
382 giacomo 263
    b->flags = GRUBSTAR_NOACTIVE;
264
  }
241 giacomo 265
 
266
  if (TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
267
    /* we modify the deadline ... */
268
    TIMESPEC_ASSIGN(&b->dline, &schedule_time);
661 giacomo 269
    ADDUSEC2TIMESPEC(b->D, &b->dline);
270
    TIMESPEC_ASSIGN(&b->replenish, &schedule_time);
271
    ADDUSEC2TIMESPEC(b->T, &b->replenish);
241 giacomo 272
  }
273
 
661 giacomo 274
  if (b->flags == GRUBSTAR_NOACTIVE && b->replenish_timer == NIL)  {
275
    b->replenish_timer=kern_event_post(&b->replenish, GRUBSTAR_timer_hardreservation, b);
276 giacomo 276
  } else {
661 giacomo 277
    mul32div32to32(b->D,b->avail,b->Q,t);
276 giacomo 278
    t3.tv_sec = t / 1000000;
279
    t3.tv_nsec = (t % 1000000) * 1000;
280
    SUBTIMESPEC(&b->dline, &t3, &t2);
281
    b->vtimer = kern_event_post(&t2, GRUBSTAR_ANC, b);
241 giacomo 282
  }
283
}
284
 
285
static void capacity_handler(void *l)
286
{
287
 
253 giacomo 288
  GRUBSTAR_level_des *lev = l;
241 giacomo 289
  lev->cap_lev = NIL;
298 giacomo 290
  #ifdef GRUBSTAR_DEBUG
291
    kern_printf("(*)");
292
  #endif  
241 giacomo 293
  event_need_reschedule();
294
 
295
}
296
 
253 giacomo 297
static int GRUBSTAR_private_eligible(LEVEL l, PID p)
241 giacomo 298
{
253 giacomo 299
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
296 trimarchi 300
  struct budget_struct *b=&lev->b[lev->tb[p]];
298 giacomo 301
  JOB_TASK_MODEL job;
302
 
303
  if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
304
      #ifdef GRUBSTAR_DEBUG 
288 giacomo 305
        kern_printf("(GS:Eli:%d)",p);
298 giacomo 306
      #endif
241 giacomo 307
      if (lev->cap_lev!=NIL) {
308
        kern_event_delete(lev->cap_lev);
309
        lev->cap_lev=NIL;
310
      }
311
 
312
      /* we kill the current activation */
313
      level_table[ lev->scheduling_level ]->
314
        private_extract(lev->scheduling_level, p);
665 giacomo 315
 
241 giacomo 316
      /* we modify the deadline ... */
665 giacomo 317
      kern_gettime(&b->replenish);
318
      TIMESPEC_ASSIGN(&b->dline, &b->replenish);
661 giacomo 319
      ADDUSEC2TIMESPEC(b->D, &b->dline);
665 giacomo 320
      ADDUSEC2TIMESPEC(b->T, &b->replenish);      
241 giacomo 321
 
322
      /* and the capacity */
323
      b->avail = b->Q;
396 giacomo 324
      b->last_reclaiming = 0;
382 giacomo 325
 
326
      /* Tracer */
502 giacomo 327
      TRACER_LOGEVENT(FTrace_EVT_server_replenish,0,(unsigned int)(b));
276 giacomo 328
 
329
      if (b->flags == GRUBSTAR_RECLAIMING) {
388 giacomo 330
        if (lev->Uf < lev->U) lev->Uf += b->Ub;
276 giacomo 331
      }
332
 
253 giacomo 333
      b->flags = GRUBSTAR_ACTIVE;
241 giacomo 334
 
661 giacomo 335
      if (b->replenish_timer!=NIL)  {
336
        kern_event_delete(b->replenish_timer);
337
        b->replenish_timer=NIL;
241 giacomo 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);
784 giacomo 348
      job_task_def_noexc(job);
241 giacomo 349
      level_table[ lev->scheduling_level ]->
350
        private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
351
 
352
      return -1;
353
 
296 trimarchi 354
  }  
241 giacomo 355
 
356
  return 0;
357
 
358
}
359
 
253 giacomo 360
static void GRUBSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
241 giacomo 361
{
253 giacomo 362
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 363
  BUDGET_TASK_MODEL *budget;
364
 
365
  if (m->pclass != BUDGET_PCLASS ||
366
      (m->level != 0 && m->level != l)) {
367
    kern_raise(XINVALID_TASK, p);
368
    return;
369
  }
370
  budget = (BUDGET_TASK_MODEL *)m;
371
 
339 giacomo 372
  #ifdef GRUBSTAR_DEBUG
253 giacomo 373
    kern_printf("(GS:PriIns:%d:%d", p, budget->b);
339 giacomo 374
  #endif
241 giacomo 375
 
376
  if (budget->b == -1)
377
    return;
378
 
379
  lev->tb[p] = budget->b;
380
 
381
  if (lev->b[budget->b].current == NIL && lev->b[budget->b].flags ) {
382
    /* This is the first task in the budget,
383
       the task have to be inserted into the master module */
384
    struct timespec t;
385
    kern_gettime(&t);
253 giacomo 386
    GRUBSTAR_activation(lev,p,&t);
241 giacomo 387
  } else {
388
    /* The budget is not empty, another task is already into the
389
       master module, so the task is inserted at the end of the budget
390
       queue */
391
    iq_insertlast(p,&lev->b[budget->b].tasks);
392
  }
393
 
339 giacomo 394
  #ifdef GRUBSTAR_DEBUG
253 giacomo 395
    kern_printf(")");
339 giacomo 396
  #endif
241 giacomo 397
 
398
}
399
 
253 giacomo 400
static void GRUBSTAR_private_extract(LEVEL l, PID p)
241 giacomo 401
{
253 giacomo 402
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 403
 
339 giacomo 404
  #ifdef GRUBSTAR_DEBUG
253 giacomo 405
    kern_printf("(GS:Ext:%d)", p);
339 giacomo 406
  #endif
241 giacomo 407
 
408
  /* a task is removed from execution for some reasons. It must be
409
     that it is the first in its budget queue (only the first task in
410
     a budget queue is put into execution!) */
411
 
412
  /* remove the task from execution (or from the ready queue) */
413
  if (lev->b[lev->tb[p]].current == p) {
414
 
253 giacomo 415
   GRUBSTAR_account_capacity(lev,p);
241 giacomo 416
    /* remove the task from the master module */
417
    level_table[ lev->scheduling_level ]->
418
      private_extract(lev->scheduling_level, p);
419
 
420
    /* check if the buffer has someone else to schedule */
421
    if (iq_query_first(&lev->b[lev->tb[p]].tasks) == NIL) {
422
      /* the buffer has no tasks! */
423
      lev->b[lev->tb[p]].current = NIL;
424
    }
425
    else if (lev->b[lev->tb[p]].flags) {
426
      /* if so, insert the new task into the master module */
427
      PID n;
428
      struct timespec t;
338 giacomo 429
 
241 giacomo 430
      kern_gettime(&t);
431
      n = iq_getfirst(&lev->b[lev->tb[p]].tasks);
253 giacomo 432
      GRUBSTAR_activation(lev,n,&t);  // it modifies b[lev->tb[p]].current
241 giacomo 433
    }
434
    else
435
      lev->b[lev->tb[p]].current=NIL;
436
 
437
  }
438
  else  {
439
    iq_extract(p, &lev->b[lev->tb[p]].tasks);
440
  }
441
}
442
 
253 giacomo 443
static void GRUBSTAR_private_dispatch(LEVEL l, PID p, int nostop)
241 giacomo 444
{
253 giacomo 445
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 446
  struct timespec ty;
402 giacomo 447
  int temp;
241 giacomo 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 */
296 trimarchi 459
  if (!nostop)
460
        level_table[ lev->scheduling_level ]->
461
                private_dispatch(lev->scheduling_level,p,nostop);
241 giacomo 462
 
296 trimarchi 463
  TIMESPEC_ASSIGN(&ty, &schedule_time);
464
  TIMESPEC_ASSIGN(&lev->cap_lasttime, &schedule_time);
465
 
241 giacomo 466
  /* ...and finally, we have to post a capacity event */
296 trimarchi 467
 
402 giacomo 468
  /* Reclaiming Computation */
469
 
470
  if ((lev->U - lev->Uf) < 0) {
471
    cprintf("GRUBSTAR Error: Bad Reclaiming Computation\n");
472
    sys_end();
473
  }
474
 
475
  mul32div32to32(lev->b[lev->tb[exec]].avail,(lev->U-lev->Uf),MAX_BANDWIDTH,lev->b[lev->tb[exec]].last_reclaiming);
476
 
477
  if (lev->b[lev->tb[exec]].last_reclaiming > 0)
502 giacomo 478
    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 479
 
480
  temp = lev->b[lev->tb[exec]].avail + lev->b[lev->tb[exec]].last_reclaiming;
481
 
482
  ADDUSEC2TIMESPEC(temp,&ty);
483
 
296 trimarchi 484
  lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
241 giacomo 485
 
486
}
487
 
253 giacomo 488
static void GRUBSTAR_private_epilogue(LEVEL l, PID p)
241 giacomo 489
{
253 giacomo 490
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
296 trimarchi 491
  struct budget_struct *b;
492
  int skip_epilog;
493
  skip_epilog=0;
494
 
253 giacomo 495
  #ifdef GRUBSTAR_DEBUG
296 trimarchi 496
     kern_printf("(GS:Epi:%d)",p);
241 giacomo 497
  #endif
498
 
296 trimarchi 499
  if (p==exec) b = &lev->b[lev->tb[p]];
500
     else if (lev->tb[exec]!=NIL)  {
501
          b = &lev->b[lev->tb[exec]];
502
          p=exec;
503
          skip_epilog=1;
504
       }
505
       else return;    
241 giacomo 506
 
507
 
298 giacomo 508
    GRUBSTAR_account_capacity(lev,p);
241 giacomo 509
    if (b->flags)  {
276 giacomo 510
 
241 giacomo 511
      /* there is capacity available, maybe it is simply a preemption;
512
         the task have to return to the ready queue */
296 trimarchi 513
      if (!skip_epilog)
514
        level_table[ lev->scheduling_level ]->
515
          private_epilogue(lev->scheduling_level,p); //else kern_printf("(SP)");
241 giacomo 516
 
517
    } else {
518
      /* we kill the current activation */
298 giacomo 519
      #ifdef GRUBSTAR_DEBUG
663 giacomo 520
        kern_printf("(GS:HRExt:%d)",p);
298 giacomo 521
      #endif      
241 giacomo 522
      level_table[ lev->scheduling_level ]->
296 trimarchi 523
          private_extract(lev->scheduling_level, p);    
241 giacomo 524
 
525
      iq_insertfirst(p, &b->tasks);
526
      b->current = NIL;
527
 
528
    }
529
 
530
}
531
 
267 giacomo 532
static int GRUBSTAR_public_message(LEVEL l, PID p, void *m)
533
{
534
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
535
  struct budget_struct *b = &lev->b[lev->tb[p]];
536
 
537
  switch((long)(m)) {
538
 
539
    case (long)(NULL):
338 giacomo 540
 
339 giacomo 541
      #ifdef GRUBSTAR_DEBUG
338 giacomo 542
        kern_printf("(GS:EndCycle:%d:%d)",p,lev->tb[p]);
339 giacomo 543
      #endif     
267 giacomo 544
 
545
      if (b->current == NIL && iq_query_first(&(b->tasks)) == NIL && b->flags != GRUBSTAR_RECLAIMING) {
342 giacomo 546
 
547
        if (b->vtimer!=NIL)  {
548
            kern_event_delete(b->vtimer);
549
            b->vtimer=NIL;
550
        }
551
 
502 giacomo 552
        TRACER_LOGEVENT(FTrace_EVT_server_reclaiming,0,(unsigned int)(b));
267 giacomo 553
        b->flags = GRUBSTAR_RECLAIMING;
277 giacomo 554
        lev->Uf -= b->Ub;
342 giacomo 555
 
267 giacomo 556
      }
557
 
558
      break;
559
 
560
    case 1:
561
 
562
      break;
563
 
564
  }
565
 
566
  return 0;
567
 
568
}
569
 
241 giacomo 570
/* Registration functions }*/
571
 
253 giacomo 572
LEVEL GRUBSTAR_register_level(int n, LEVEL master)
241 giacomo 573
{
574
  LEVEL l;            /* the level that we register */
253 giacomo 575
  GRUBSTAR_level_des *lev;  /* for readableness only */
241 giacomo 576
  PID i;              /* a counter */
577
 
253 giacomo 578
  printk("GRUBSTAR_register_level\n");
241 giacomo 579
 
580
  /* request an entry in the level_table */
253 giacomo 581
  l = level_alloc_descriptor(sizeof(GRUBSTAR_level_des));
241 giacomo 582
 
253 giacomo 583
  lev = (GRUBSTAR_level_des *)level_table[l];
241 giacomo 584
 
585
  /* fill the standard descriptor */
253 giacomo 586
  lev->l.private_insert   = GRUBSTAR_private_insert;
587
  lev->l.private_extract  = GRUBSTAR_private_extract;
588
  lev->l.private_eligible = GRUBSTAR_private_eligible;
589
  lev->l.private_dispatch = GRUBSTAR_private_dispatch;
590
  lev->l.private_epilogue = GRUBSTAR_private_epilogue;
241 giacomo 591
 
298 giacomo 592
  lev->l.public_guarantee = NULL;
267 giacomo 593
  lev->l.public_message = GRUBSTAR_public_message;
241 giacomo 594
 
595
  lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
596
 
597
  for (i=0; i<n; i++) {
598
    lev->b[i].Q = 0;
599
    lev->b[i].T = 0;
661 giacomo 600
    lev->b[i].D = 0;
277 giacomo 601
    lev->b[i].Ub = 0;
241 giacomo 602
    NULL_TIMESPEC(&lev->b[i].dline);
661 giacomo 603
    NULL_TIMESPEC(&lev->b[i].replenish);
604
    lev->b[i].replenish_timer = NIL;
298 giacomo 605
    lev->b[i].vtimer = NIL;
241 giacomo 606
    lev->b[i].avail = 0;
607
    lev->b[i].current = -1;
253 giacomo 608
    lev->b[i].flags = GRUBSTAR_ACTIVE;
276 giacomo 609
    lev->b[i].l = l;
610
    lev->b[i].last_reclaiming = 0;
253 giacomo 611
    iq_init(&lev->b[i].tasks, NULL, 0);
241 giacomo 612
  }
613
 
614
  lev->n = n;
615
  lev->freebudgets = 0;
616
 
617
  for (i=0; i<MAX_PROC; i++)
618
    lev->tb[i] = NIL;
619
 
620
  lev->U = 0;
621
  lev->Uf = 0;
622
  lev->cap_lev = NIL;
279 giacomo 623
  NULL_TIMESPEC(&lev->cap_lasttime);
241 giacomo 624
  lev->scheduling_level = master;
625
 
626
  return l;
627
 
628
}
629
 
661 giacomo 630
int GRUBSTAR_setbudget(LEVEL l, TIME Q, TIME T, TIME D, LEVEL local_scheduler_level, int scheduler_id)
241 giacomo 631
{
253 giacomo 632
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 633
  int r;
634
 
339 giacomo 635
  #ifdef GRUBSTAR_DEBUG
253 giacomo 636
    kern_printf("(GS:SetBud)");
339 giacomo 637
  #endif
241 giacomo 638
 
639
  for (r = 0; r < lev->n; r++)
640
    if (lev->b[r].Q == 0) break;
641
 
642
  if (r != lev->n) {
643
    bandwidth_t b;
343 giacomo 644
    mul32div32to32(MAX_BANDWIDTH,Q,T,b);
241 giacomo 645
 
646
    /* really update lev->U, checking an overflow... */
407 giacomo 647
    if (Q< T /* && MAX_BANDWIDTH - lev->U > b */) {
241 giacomo 648
 
649
      lev->U += b;
396 giacomo 650
      //lev->Uf += b; Start in Reclaiming
241 giacomo 651
      lev->freebudgets++;
652
 
653
      lev->b[r].Q = Q;
654
      lev->b[r].T = T;
661 giacomo 655
      lev->b[r].D = D;
277 giacomo 656
      lev->b[r].Ub = b;
241 giacomo 657
      lev->b[r].avail = Q;
396 giacomo 658
      lev->b[r].flags = GRUBSTAR_RECLAIMING;
241 giacomo 659
      lev->b[r].loc_sched_id = scheduler_id;
660
      lev->b[r].loc_sched_level = local_scheduler_level;
382 giacomo 661
      lev->b[r].last_reclaiming = 0;
662
 
241 giacomo 663
      return r;
664
    }
665
    else
666
      return -2;
667
  }
668
  else
669
    return -1;
670
}
671
 
253 giacomo 672
int GRUBSTAR_removebudget(LEVEL l, int budget)
241 giacomo 673
{
674
 
253 giacomo 675
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 676
 
677
  bandwidth_t b;
678
 
343 giacomo 679
  mul32div32to32(MAX_BANDWIDTH,lev->b[budget].Q,lev->b[budget].T,b);
241 giacomo 680
 
681
  lev->U -= b;
396 giacomo 682
  if (lev->b[budget].flags != GRUBSTAR_RECLAIMING) lev->Uf -= b;
241 giacomo 683
 
684
  lev->b[budget].Q = 0;
685
  lev->b[budget].T = 0;
661 giacomo 686
  lev->b[budget].D = 0;
277 giacomo 687
  lev->b[budget].Ub = 0;
241 giacomo 688
  NULL_TIMESPEC(&lev->b[budget].dline);
661 giacomo 689
  NULL_TIMESPEC(&lev->b[budget].replenish);
690
  lev->b[budget].replenish_timer = NIL;
241 giacomo 691
  lev->b[budget].avail = 0;
692
  lev->b[budget].current = -1;
396 giacomo 693
  lev->b[budget].flags = GRUBSTAR_RECLAIMING;
277 giacomo 694
  lev->b[budget].last_reclaiming = 0;
241 giacomo 695
 
696
  return 0;
697
 
698
}
699
 
402 giacomo 700
/* Change Q and T parameters of a budget
701
 * It returns the time to wait before the change is effective
702
 */
661 giacomo 703
int GRUBSTAR_adjust_budget(LEVEL l, TIME Q, TIME T, TIME D, int budget)
241 giacomo 704
{
705
 
253 giacomo 706
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
298 giacomo 707
  bandwidth_t b;
403 trimarchi 708
  TIME OldPeriod =  TIMESPEC2USEC(&lev->b[budget].dline);
241 giacomo 709
 
343 giacomo 710
  mul32div32to32(MAX_BANDWIDTH,lev->b[budget].Q,lev->b[budget].T,b);
298 giacomo 711
 
712
  lev->U -= b;
396 giacomo 713
  if (lev->b[budget].flags != GRUBSTAR_RECLAIMING) lev->Uf -= b;
298 giacomo 714
 
241 giacomo 715
  lev->b[budget].Q = Q;
716
  lev->b[budget].T = T;
661 giacomo 717
  lev->b[budget].D = D;
665 giacomo 718
 
719
  cprintf("[%d:Q=%d:T=%d:D=%d]",budget,(int)Q,(int)T,(int)D);
720
 
343 giacomo 721
  mul32div32to32(MAX_BANDWIDTH,Q,T,lev->b[budget].Ub);
342 giacomo 722
 
298 giacomo 723
  lev->U += lev->b[budget].Ub;
396 giacomo 724
  if (lev->b[budget].flags != GRUBSTAR_RECLAIMING) lev->Uf += lev->b[budget].Ub;  
241 giacomo 725
 
402 giacomo 726
  if (lev->b[budget].flags == GRUBSTAR_NOACTIVE)
727
    return 0;
728
  if (lev->b[budget].flags == GRUBSTAR_RECLAIMING)
729
    return 0;
730
 
731
  return OldPeriod;
241 giacomo 732
 
733
}
734
 
661 giacomo 735
int GRUBSTAR_getbudgetinfo(LEVEL l, TIME *Q, TIME *T, TIME *D, int budget)
241 giacomo 736
{
737
 
253 giacomo 738
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 739
 
740
  *Q = lev->b[budget].Q;
741
  *T = lev->b[budget].T;
661 giacomo 742
  *D = lev->b[budget].D;
241 giacomo 743
 
744
  return 0;
745
 
746
}
747
 
276 giacomo 748
int GRUBSTAR_get_last_reclaiming(LEVEL l, PID p)
267 giacomo 749
{
750
 
751
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
752
 
276 giacomo 753
  return lev->b[lev->tb[p]].last_reclaiming;
267 giacomo 754
 
755
}
756
 
253 giacomo 757
int GRUBSTAR_is_active(LEVEL l, int budget)
241 giacomo 758
{
253 giacomo 759
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 760
 
761
  return lev->b[budget].flags;
762
 
763
}
764
 
340 giacomo 765
int GRUBSTAR_get_remain_capacity(LEVEL l, int budget)
766
{
767
 
768
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
769
 
770
  return lev->b[budget].avail;
771
 
772
}
773
 
253 giacomo 774
int GRUBSTAR_get_local_scheduler_level_from_budget(LEVEL l, int budget)
241 giacomo 775
{
253 giacomo 776
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 777
 
778
  return lev->b[budget].loc_sched_level;
779
 
780
}
781
 
253 giacomo 782
int GRUBSTAR_get_local_scheduler_level_from_pid(LEVEL l, PID p)
241 giacomo 783
{
253 giacomo 784
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 785
 
786
  return lev->b[lev->tb[p]].loc_sched_level;
787
 
788
}
789
 
253 giacomo 790
int GRUBSTAR_get_local_scheduler_id_from_budget(LEVEL l, int budget)
241 giacomo 791
{
253 giacomo 792
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 793
 
794
  return lev->b[budget].loc_sched_id;
795
 
796
}
797
 
403 trimarchi 798
/* return the sum of servers bandwith */
799
bandwidth_t GRUBSTAR_return_bandwidth(LEVEL l) {
800
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
801
 
802
  return lev->U;
803
}
804
 
253 giacomo 805
int GRUBSTAR_get_local_scheduler_id_from_pid(LEVEL l, PID p)
241 giacomo 806
{
253 giacomo 807
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 808
 
809
  return lev->b[lev->tb[p]].loc_sched_id;
810
 
811
}
812