Subversion Repositories shark

Rev

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