Subversion Repositories shark

Rev

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