Subversion Repositories shark

Rev

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