Subversion Repositories shark

Rev

Rev 897 | Rev 960 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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