Subversion Repositories shark

Rev

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