Subversion Repositories shark

Rev

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