Subversion Repositories shark

Rev

Rev 867 | Rev 877 | 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;
873 trimarchi 663
    lev->b[i].loc_sched_level=-1;
253 giacomo 664
    iq_init(&lev->b[i].tasks, NULL, 0);
241 giacomo 665
  }
666
 
667
  lev->n = n;
668
  lev->freebudgets = 0;
669
 
670
  for (i=0; i<MAX_PROC; i++)
671
    lev->tb[i] = NIL;
672
 
867 trimarchi 673
  lev->negotiation_in_progress=0;
241 giacomo 674
  lev->U = 0;
675
  lev->Uf = 0;
676
  lev->cap_lev = NIL;
279 giacomo 677
  NULL_TIMESPEC(&lev->cap_lasttime);
241 giacomo 678
  lev->scheduling_level = master;
679
 
680
  return l;
681
 
682
}
683
 
661 giacomo 684
int GRUBSTAR_setbudget(LEVEL l, TIME Q, TIME T, TIME D, LEVEL local_scheduler_level, int scheduler_id)
241 giacomo 685
{
253 giacomo 686
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 687
  int r;
688
 
339 giacomo 689
  #ifdef GRUBSTAR_DEBUG
253 giacomo 690
    kern_printf("(GS:SetBud)");
339 giacomo 691
  #endif
241 giacomo 692
 
693
  for (r = 0; r < lev->n; r++)
694
    if (lev->b[r].Q == 0) break;
695
 
696
  if (r != lev->n) {
697
    bandwidth_t b;
343 giacomo 698
    mul32div32to32(MAX_BANDWIDTH,Q,T,b);
241 giacomo 699
 
700
    /* really update lev->U, checking an overflow... */
407 giacomo 701
    if (Q< T /* && MAX_BANDWIDTH - lev->U > b */) {
241 giacomo 702
 
703
      lev->U += b;
396 giacomo 704
      //lev->Uf += b; Start in Reclaiming
241 giacomo 705
      lev->freebudgets++;
706
 
707
      lev->b[r].Q = Q;
708
      lev->b[r].T = T;
661 giacomo 709
      lev->b[r].D = D;
867 trimarchi 710
 
711
      lev->b[r].N_Q = 0;
712
      lev->b[r].N_T = 0;
713
      lev->b[r].N_D = 0;
714
      lev->b[r].negotiation=0;
715
 
277 giacomo 716
      lev->b[r].Ub = b;
241 giacomo 717
      lev->b[r].avail = Q;
396 giacomo 718
      lev->b[r].flags = GRUBSTAR_RECLAIMING;
241 giacomo 719
      lev->b[r].loc_sched_id = scheduler_id;
720
      lev->b[r].loc_sched_level = local_scheduler_level;
867 trimarchi 721
      lev->b[r].last_reclaiming = 0;      
382 giacomo 722
 
241 giacomo 723
      return r;
724
    }
725
    else
726
      return -2;
727
  }
728
  else
729
    return -1;
730
}
731
 
253 giacomo 732
int GRUBSTAR_removebudget(LEVEL l, int budget)
241 giacomo 733
{
734
 
253 giacomo 735
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 736
 
737
  bandwidth_t b;
738
 
343 giacomo 739
  mul32div32to32(MAX_BANDWIDTH,lev->b[budget].Q,lev->b[budget].T,b);
241 giacomo 740
 
741
  lev->U -= b;
396 giacomo 742
  if (lev->b[budget].flags != GRUBSTAR_RECLAIMING) lev->Uf -= b;
241 giacomo 743
 
744
  lev->b[budget].Q = 0;
745
  lev->b[budget].T = 0;
661 giacomo 746
  lev->b[budget].D = 0;
867 trimarchi 747
 
748
  lev->b[budget].N_Q = 0;
749
  lev->b[budget].N_T = 0;
750
  lev->b[budget].N_D = 0;
751
 
752
  lev->b[budget].negotiation=0;
753
 
277 giacomo 754
  lev->b[budget].Ub = 0;
241 giacomo 755
  NULL_TIMESPEC(&lev->b[budget].dline);
661 giacomo 756
  NULL_TIMESPEC(&lev->b[budget].replenish);
757
  lev->b[budget].replenish_timer = NIL;
241 giacomo 758
  lev->b[budget].avail = 0;
759
  lev->b[budget].current = -1;
396 giacomo 760
  lev->b[budget].flags = GRUBSTAR_RECLAIMING;
277 giacomo 761
  lev->b[budget].last_reclaiming = 0;
873 trimarchi 762
  lev->b[budget].loc_sched_level;
241 giacomo 763
 
764
  return 0;
765
 
766
}
767
 
402 giacomo 768
/* Change Q and T parameters of a budget
769
 * It returns the time to wait before the change is effective
770
 */
661 giacomo 771
int GRUBSTAR_adjust_budget(LEVEL l, TIME Q, TIME T, TIME D, int budget)
241 giacomo 772
{
773
 
253 giacomo 774
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
298 giacomo 775
  bandwidth_t b;
403 trimarchi 776
  TIME OldPeriod =  TIMESPEC2USEC(&lev->b[budget].dline);
241 giacomo 777
 
343 giacomo 778
  mul32div32to32(MAX_BANDWIDTH,lev->b[budget].Q,lev->b[budget].T,b);
298 giacomo 779
 
780
  lev->U -= b;
396 giacomo 781
  if (lev->b[budget].flags != GRUBSTAR_RECLAIMING) lev->Uf -= b;
298 giacomo 782
 
867 trimarchi 783
  lev->b[budget].N_Q = Q;
784
  lev->b[budget].N_T = T;
785
  lev->b[budget].N_D = D;
665 giacomo 786
 
867 trimarchi 787
  if (lev->b[budget].current!=NIL) {
788
    lev->b[budget].N_Q = Q;
789
    lev->b[budget].N_T = T;
790
    lev->b[budget].N_D = D;
791
    if (!lev->b[budget].negotiation) {
792
      lev->negotiation_in_progress++;
793
      lev->b[budget].negotiation=1;
794
    }                                                  
795
  } else {
796
    lev->b[budget].Q = Q;
797
    lev->b[budget].T = T;
798
    lev->b[budget].D = D;
799
  }
800
 
343 giacomo 801
  mul32div32to32(MAX_BANDWIDTH,Q,T,lev->b[budget].Ub);
342 giacomo 802
 
298 giacomo 803
  lev->U += lev->b[budget].Ub;
396 giacomo 804
  if (lev->b[budget].flags != GRUBSTAR_RECLAIMING) lev->Uf += lev->b[budget].Ub;  
241 giacomo 805
 
804 giacomo 806
  #ifdef GRUBSTAR_DEBUG
807
    cprintf("[%d:Q=%d:T=%d:D=%d]",budget,(int)Q,(int)T,(int)D);
808
  #endif
809
 
402 giacomo 810
  if (lev->b[budget].flags == GRUBSTAR_NOACTIVE)
811
    return 0;
812
  if (lev->b[budget].flags == GRUBSTAR_RECLAIMING)
813
    return 0;
814
 
815
  return OldPeriod;
241 giacomo 816
 
817
}
818
 
661 giacomo 819
int GRUBSTAR_getbudgetinfo(LEVEL l, TIME *Q, TIME *T, TIME *D, int budget)
241 giacomo 820
{
821
 
253 giacomo 822
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 823
 
867 trimarchi 824
  if (lev->b[budget].Q) {
825
    if (Q) *Q = lev->b[budget].Q;
826
    if (T) *T = lev->b[budget].T;
827
    if (D) *D = lev->b[budget].D;
828
    return 0;
829
  }
241 giacomo 830
 
867 trimarchi 831
  return -1;
832
 
241 giacomo 833
}
834
 
276 giacomo 835
int GRUBSTAR_get_last_reclaiming(LEVEL l, PID p)
267 giacomo 836
{
837
 
838
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
839
 
276 giacomo 840
  return lev->b[lev->tb[p]].last_reclaiming;
267 giacomo 841
 
842
}
843
 
253 giacomo 844
int GRUBSTAR_is_active(LEVEL l, int budget)
241 giacomo 845
{
253 giacomo 846
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 847
 
848
  return lev->b[budget].flags;
849
 
850
}
851
 
340 giacomo 852
int GRUBSTAR_get_remain_capacity(LEVEL l, int budget)
853
{
820 trimarchi 854
  struct timespec actual,ty;
829 giacomo 855
  int    tx;
340 giacomo 856
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
820 trimarchi 857
  kern_gettime(&actual);
829 giacomo 858
  SUBTIMESPEC(&actual, &schedule_time, &ty);
820 trimarchi 859
  tx = TIMESPEC2USEC(&ty);
860
  // the remain capacity is from the first dispatch so is less then
861
  // actual capacity
862
  return (lev->b[budget].avail-tx);
340 giacomo 863
 
864
}
865
 
253 giacomo 866
int GRUBSTAR_get_local_scheduler_level_from_budget(LEVEL l, int budget)
241 giacomo 867
{
253 giacomo 868
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 869
 
870
  return lev->b[budget].loc_sched_level;
871
 
872
}
873
 
253 giacomo 874
int GRUBSTAR_get_local_scheduler_level_from_pid(LEVEL l, PID p)
241 giacomo 875
{
253 giacomo 876
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 877
 
878
  return lev->b[lev->tb[p]].loc_sched_level;
879
 
880
}
881
 
253 giacomo 882
int GRUBSTAR_get_local_scheduler_id_from_budget(LEVEL l, int budget)
241 giacomo 883
{
253 giacomo 884
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 885
 
886
  return lev->b[budget].loc_sched_id;
887
 
888
}
889
 
403 trimarchi 890
/* return the sum of servers bandwith */
891
bandwidth_t GRUBSTAR_return_bandwidth(LEVEL l) {
892
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
893
 
894
  return lev->U;
895
}
896
 
253 giacomo 897
int GRUBSTAR_get_local_scheduler_id_from_pid(LEVEL l, PID p)
241 giacomo 898
{
253 giacomo 899
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
241 giacomo 900
 
901
  return lev->b[lev->tb[p]].loc_sched_id;
902
 
903
}
904
 
808 trimarchi 905
void GRUBSTAR_disable_server(LEVEL l, int budget)
906
{
907
 GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
809 trimarchi 908
 int avail_budget;
909
 int spare;
808 trimarchi 910
 
809 trimarchi 911
 /* force a hard reservation event */
825 trimarchi 912
 avail_budget=lev->b[lev->tb[exec]].avail;
913
 lev->b[lev->tb[exec]].flags = GRUBSTAR_NOACTIVE;
829 giacomo 914
 //kern_printf("(GS DS %d)", exec);
809 trimarchi 915
 /* save the unused capacity */
825 trimarchi 916
 spare=avail_budget+lev->b[lev->tb[exec]].avail;
809 trimarchi 917
 if (spare<=0) spare=0;
918
 
808 trimarchi 919
}
920
 
867 trimarchi 921
int GRUBSTAR_get_renegotiation_status(LEVEL l, int budget)
922
{
923
  GRUBSTAR_level_des *lev = (GRUBSTAR_level_des *)(level_table[l]);
924
  if (lev->negotiation_in_progress) return 1;
925
  else return 0;
926
}
808 trimarchi 927