Subversion Repositories shark

Rev

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