Subversion Repositories shark

Rev

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