Subversion Repositories shark

Rev

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