Subversion Repositories shark

Rev

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