Subversion Repositories shark

Rev

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