Subversion Repositories shark

Rev

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