Subversion Repositories shark

Rev

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