Subversion Repositories shark

Rev

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