Subversion Repositories shark

Rev

Rev 1176 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1089 pj 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     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
11
 *   Luca Abeni          <luca@gandalf.sssup.it>
12
 *   (see the web pages for full authors list)
13
 *
14
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
15
 *
16
 * http://www.sssup.it
17
 * http://retis.sssup.it
18
 * http://shark.sssup.it
19
 */
20
 
21
/*
22
 ------------
1180 trimarchi 23
 CVS :        $Id: cbsstar.c,v 1.6 2003-08-01 13:20:38 trimarchi Exp $
1089 pj 24
 
25
 File:        $File$
1180 trimarchi 26
 Revision:    $Revision: 1.6 $
27
 Last update: $Date: 2003-08-01 13:20:38 $
1089 pj 28
 ------------
29
 
30
 Read CBSSTAR.h for general details.
31
 
32
 Basically, a budget can be in 2 states:
33
 - Active -> the budget queue is not empty
34
 - Idle   -> the budget queue is empty
35
 
36
 The fact that a task into a budget is inserted into the master module depends
37
 on the value of the remaining time the tasks can spend in the period.
38
 
39
 The module does handle only one oslib event, used to enforce the
40
 temporal isolation between buffers. Note that all is implemented
41
 without using the CONTROL_CAP field.
42
 
43
 Basically, for each budget there can be at most one task inserted
44
 into the master level. Its deadline is modified according to the
45
 usage of its capacity, that is, when a budget is exausted its
46
 deadline is postponed.
47
 
48
*/
49
 
50
/*
51
 * Copyright (C) 2002 Paolo Gai
52
 *
53
 * This program is free software; you can redistribute it and/or modify
54
 * it under the terms of the GNU General Public License as published by
55
 * the Free Software Foundation; either version 2 of the License, or
56
 * (at your option) any later version.
57
 *
58
 * This program is distributed in the hope that it will be useful,
59
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
60
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
61
 * GNU General Public License for more details.
62
 *
63
 * You should have received a copy of the GNU General Public License
64
 * along with this program; if not, write to the Free Software
65
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
66
 *
67
 */
68
 
69
 
70
#include "cbsstar.h"
71
#include <ll/string.h>
72
 
1180 trimarchi 73
#define ACTIVE 1
74
#define NOACTIVE 0
75
#define INIT 2
1089 pj 76
 
1180 trimarchi 77
#define CBSSTAR_IDLE APER_STATUS_BASE
1089 pj 78
/*
79
 * DEBUG stuffs begin
80
 */
81
 
1180 trimarchi 82
//#define CBSSTAR_DEBUG
83
int event_monitor;
84
#ifdef CBSSTAR_DEBUG
1089 pj 85
 
1180 trimarchi 86
 
1089 pj 87
static __inline__ void fake_printf(char *fmt, ...) {}
88
 
89
//#define cbsstar_printf kern_printf
90
//#define cbsstar_printf2 kern_printf
91
//#define cbsstar_printf3 kern_printf
92
 
93
#define cbsstar_printf fake_printf
94
#define cbsstar_printf2 fake_printf
95
#define cbsstar_printf3 fake_printf
96
 
1180 trimarchi 97
#if 0
98
void cbsstar_printq(QQUEUE *q)
1089 pj 99
{
100
  PID p;
101
  kern_printf("[");
102
  p = q->first;
103
  kern_printf("->%d",p);
104
  while (p != NIL) {
105
    p = proc_table[p].next;
106
    kern_printf("->%d",p);
107
  }
108
  kern_printf("]");
109
}
110
#else
111
static __inline__ void cbsstar_printq(QQUEUE *q) {}
112
#endif
113
 
1180 trimarchi 114
#if 0
1089 pj 115
static __inline__ void cbsstar_printblob(int x) { if (x) cputc('▒'); else cputc('█'); }
116
#else
117
static __inline__ void cbsstar_printblob(int x) {}
118
#endif
119
 
120
#endif
121
 
122
/*
123
 * DEBUG stuffs end
124
 */
1180 trimarchi 125
/*+ Status used in the level +*/
126
#define CBSSTAR_WAIT          APER_STATUS_BASE    /*+ waiting the service   +*/
1089 pj 127
 
128
/* this structure contains the status for a single budget */
129
struct budget_struct {
130
  TIME Q;                 /* budget */
131
  TIME T;                 /* period */
1180 trimarchi 132
 
1089 pj 133
  struct timespec dline;  /* deadline */
134
  int dline_timer;        /* oslib event for budget reactivation*/
135
  int avail;              /* current budget */
136
 
137
  PID current;            /* the task currently put in execution */
1180 trimarchi 138
 
139
  int flags;
140
 
1116 pj 141
  IQUEUE tasks;           /* a FIFO queue for the tasks handled
1089 pj 142
                             using the budget */
143
};
144
 
145
typedef struct {
146
  level_des l;               /* the standard level descriptor */
147
 
148
  struct budget_struct *b;   /* the budgets! */
149
  int n;                     /* the maximum index for the budgets */
150
  int freebudgets;           /* number of free budgets; starts from n */
151
 
152
  int tb[MAX_PROC];          /* link task->budget (used in guest_end) */
153
 
154
  bandwidth_t U;   /*+ the used bandwidth by the server       +*/
1180 trimarchi 155
 
1176 trimarchi 156
  int cap_lev;
1089 pj 157
 
1180 trimarchi 158
  PID on_shadow;
159
 
1089 pj 160
  LEVEL scheduling_level;
161
 
162
} CBSSTAR_level_des;
163
 
164
 
1180 trimarchi 165
static void CBSSTAR_deadline_timer_hardreservation(void *a)
166
{
167
  struct budget_struct *b = a;
168
  struct timespec t;
169
 
170
  //kern_printf("*********** %d", b->dline_timer);
171
  b->dline_timer=NIL;
172
    /* we modify the deadline according to rule 4 ... */
173
    /* there is a while because if the wcet is << than the system tick
174
      we need to postpone the deadline many times */
175
  if (b->avail<=0) {
176
    b->avail += b->Q;
177
    if (b->avail>b->Q) b->avail=b->Q;
178
 
179
    //kern_printf("budget recharge %d", b);
180
  }
181
 
182
  if (b->avail>0) b->flags=ACTIVE;
183
 
184
  /* avail may be <0 because a task executed via a shadow fo many time
185
     b->current == NIL only if the prec task was finished and there
186
     was not any other task to be put in the ready queue
187
     ... we are now activating the next task */
188
  if (b->current == NIL && b->flags) {
189
      if (iq_query_first(&(b->tasks)) != NIL) {
190
        //struct timespec t;
191
        CBSSTAR_level_des *lev;
192
        PID p;
193
        JOB_TASK_MODEL job;
194
        //kern_gettime(&t);
195
        //TIMESPEC_ASSIGN(&b->dline, &schedule_time);
196
        //ADDUSEC2TIMESPEC(b->T, &b->dline);
197
        kern_gettime(&t);
198
        TIMESPEC_ASSIGN(&b->dline, &t);
199
        ADDUSEC2TIMESPEC(b->T, &b->dline);
200
 
201
        p = iq_getfirst(&(b->tasks));
202
        b->current=p;
203
        lev = (CBSSTAR_level_des *)(level_table[proc_table[p].task_level]);
204
        //kern_printf("reinsert task p = %d lev = %d ",p,proc_table[p].task_level); 
205
        /* and, finally, we reinsert the task in the master level */
206
        job_task_default_model(job, b->dline);
207
        job_task_def_noexc(job);
208
        //kern_printf("(CR:iact p%d %ld.%ld av=%d)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
209
        //kern_printf("**");
210
        level_table[ lev->scheduling_level ]->
211
          private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
212
 
213
        event_need_reschedule();
214
      }
215
  } else
216
    if (b->current !=NIL && b->avail>0) {
217
      kern_printf("(cap&nil ");
218
    }
219
  if (b->flags==NOACTIVE && b->dline_timer!=NIL){
220
    kern_gettime(&t);
221
    TIMESPEC_ASSIGN(&b->dline, &t);
222
    ADDUSEC2TIMESPEC(b->T, &b->dline);
223
 
224
    b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
225
    event_monitor=b->dline_timer;
226
    //kern_printf("(dline hard %ld.%ld ev %d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->dline_timer);
227
 }
228
}
1089 pj 229
static void CBSSTAR_activation(CBSSTAR_level_des *lev,
230
                           PID p,
231
                           struct timespec *acttime)
232
{
233
  JOB_TASK_MODEL job;
234
  struct budget_struct *b = &lev->b[lev->tb[p]];
235
  /* we have to check if the deadline and the wcet are correct before
236
     activating a new task or an old task... */
237
 
238
  /* check 1: if the deadline is before than the actual scheduling time */
239
 
240
  /* check 2: if ( avail_time >= (cbs_dline - acttime)* (wcet/period) )
241
     (rule 7 in the CBS article!) */
242
  TIME t;
243
  struct timespec t2,t3;
244
 
245
  t = (b->T * b->avail) / b->Q;
246
  t3.tv_sec = t / 1000000;
247
  t3.tv_nsec = (t % 1000000) * 1000;
248
 
249
  SUBTIMESPEC(&b->dline, acttime, &t2);
250
  if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) ||
251
      /* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
252
    TIMESPEC_ASSIGN(&b->dline, acttime);
253
    ADDUSEC2TIMESPEC(b->T, &b->dline);
1180 trimarchi 254
  }  
255
 
256
  /* and the capacity */
257
  if (b->flags==INIT) {
1089 pj 258
    b->avail = b->Q;
1180 trimarchi 259
    b->flags=ACTIVE;
260
  }  
1089 pj 261
 
1176 trimarchi 262
 
1089 pj 263
#ifdef CBSSTAR_DEBUG
264
    cbsstar_printf3("▒%d▒",lev->tb[p]);
265
    cbsstar_printblob(lev->tb[p]);
266
#endif
1180 trimarchi 267
    //}
268
  //#endif
1089 pj 269
 
270
  /* record the current task inserted in the master module */
271
  b->current = p;
272
 
1180 trimarchi 273
  //#ifdef CBSSTAR_DEBUG
274
  //kern_printf("(CA:iact p%d %ld.%ld av=%d at=%ld.%ld)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail, acttime->tv_sec, acttime->tv_nsec/1000);
275
  //#endif
1089 pj 276
  /* and, finally, we reinsert the task in the master level */
277
  job_task_default_model(job, b->dline);
278
  job_task_def_noexc(job);
279
  level_table[ lev->scheduling_level ]->
1123 pj 280
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
1180 trimarchi 281
  //b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
1089 pj 282
}
283
 
284
static void CBSSTAR_account_capacity(CBSSTAR_level_des *lev, PID p)
285
{
286
  struct timespec ty;
287
  TIME tx;
1180 trimarchi 288
  struct budget_struct *b = &lev->b[lev->tb[p]];
289
  TIME t;
290
  struct timespec t2,t3, acttime;
1089 pj 291
 
1180 trimarchi 292
  if (lev->cap_lev!=NIL && b->current==p) {
293
    kern_event_delete(lev->cap_lev);
294
    lev->cap_lev=NIL;
295
  }
296
 
297
  kern_gettime(&acttime);
298
  t = (b->T * b->avail) / b->Q;
299
  t3.tv_sec = t / 1000000;
300
  t3.tv_nsec = (t % 1000000) * 1000;
301
 
302
  SUBTIMESPEC(&b->dline, &acttime, &t2);
303
 
1089 pj 304
  SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
305
  tx = TIMESPEC2USEC(&ty);
306
  lev->b[lev->tb[p]].avail -= tx;
307
 
308
#ifdef CBSSTAR_DEBUG
309
  cbsstar_printf2("(C:cap p%d av=%d)", p, lev->b[lev->tb[p]].avail);
310
#endif
1180 trimarchi 311
  if (lev->b[lev->tb[p]].avail<=0 || TIMESPEC_A_GT_B(&t3, &t2)) lev->b[lev->tb[p]].flags=NOACTIVE;
312
 
313
  if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time) ) {
314
 
315
    /* we modify the deadline ... */
316
    TIMESPEC_ASSIGN(&b->dline, &schedule_time);
317
    ADDUSEC2TIMESPEC(b->T, &b->dline);
318
  }
319
 
320
  //if (b->flags==NOACTIVE && b->dline_timer!=NIL)
321
  //  kern_printf("flags %d, dline_timer %d", b->flags, b->dline_timer);
322
 
323
  if (b->flags==NOACTIVE && b->dline_timer==NIL)  {
324
    b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
325
    event_monitor=b->dline_timer;
326
    //kern_printf("(dline %ld.%ld ev %d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->dline_timer);
327
  }
328
 
329
 
1089 pj 330
}
331
 
332
 
333
/* The on-line guarantee is enabled only if the appropriate flag is set... */
1123 pj 334
static int CBSSTAR_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
1089 pj 335
{
336
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
337
 
338
#ifdef CBSSTAR_DEBUG
339
  cbsstar_printf("(C:gua)");
340
#endif
341
 
342
  if (*freebandwidth >= lev->U) {
343
    *freebandwidth -= lev->U;
344
    return 1;
345
  }
346
  else
347
    return 0;
348
}
349
 
1180 trimarchi 350
static void capacity_handler(void *l)
351
{
352
  //kern_printf("!"); 
353
  CBSSTAR_level_des *lev =l;
354
  lev->cap_lev=NIL;
355
  event_need_reschedule();
356
 
357
}
358
 
1123 pj 359
static int CBSSTAR_private_eligible(LEVEL l, PID p)
1089 pj 360
{
361
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
362
  struct budget_struct *b = &lev->b[lev->tb[p]];
363
  JOB_TASK_MODEL job;
364
 
365
#ifdef CBSSTAR_DEBUG
1180 trimarchi 366
  //kern_printf("(C:eli %d",p);
1089 pj 367
#endif
368
 
369
  /* we have to check if the deadline and the wcet are correct...
370
     if the CBSSTAR level schedules in background with respect to others
371
     levels, there can be the case in witch a task is scheduled by
372
     schedule_time > CBSSTAR_deadline; in this case (not covered in the
373
     article because if there is only the standard scheduling policy
374
     this never apply) we reassign the deadline */
1180 trimarchi 375
  if (b->current==p) {
376
  if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
377
    if (lev->cap_lev!=NIL) {
378
        kern_event_delete(lev->cap_lev);
379
        lev->cap_lev=NIL;
380
    }
381
 
1089 pj 382
    /* we kill the current activation */
383
    level_table[ lev->scheduling_level ]->
1123 pj 384
      private_extract(lev->scheduling_level, p);
1180 trimarchi 385
   /* we modify the deadline ... */
1089 pj 386
    TIMESPEC_ASSIGN(&b->dline, &schedule_time);
387
    ADDUSEC2TIMESPEC(b->T, &b->dline);
388
 
389
    /* and the capacity */
390
    b->avail = b->Q;
1180 trimarchi 391
    b->flags=ACTIVE;
1089 pj 392
 
1180 trimarchi 393
    if (b->dline_timer!=NIL)  {
394
            kern_event_delete(b->dline_timer);
395
            b->dline_timer=NIL;
396
    }
397
 
398
    //#ifdef CBSSTAR_DEBUG
399
    //kern_printf(" %ld.%ld av=%d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->Q);
400
    //cbsstar_printf3("▒%d▒",lev->tb[p]);
401
    //cbsstar_printblob(lev->tb[p]);
402
    //#endif
403
 
1089 pj 404
    /* and, finally, we reinsert the task in the master level */
405
    job_task_default_model(job, b->dline);
406
    job_task_def_noexc(job);
1180 trimarchi 407
    //kern_printf("(CE:iact p%d %ld.%ld av=%d)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
1089 pj 408
    level_table[ lev->scheduling_level ]->
1123 pj 409
      private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
1180 trimarchi 410
    //kern_printf("task %d, avail %d", p, b->avail);
1089 pj 411
    return -1;
1180 trimarchi 412
  }  
413
}
1089 pj 414
#ifdef CBSSTAR_DEBUG
415
  cbsstar_printf(")");
416
#endif
417
 
418
  return 0;
419
}
420
 
1123 pj 421
static void CBSSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
1089 pj 422
{
423
  /* A task has been activated for some reason. Basically, the task is
424
  inserted in the queue if the queue is empty, otherwise the task is
425
  inserted into the master module, and an oslib event is posted. */
426
 
427
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
1123 pj 428
  BUDGET_TASK_MODEL *budget;
1089 pj 429
 
1123 pj 430
  if (m->pclass != BUDGET_PCLASS ||
431
      (m->level != 0 && m->level != l)) {
432
    kern_raise(XINVALID_TASK, p);
433
    return;
434
  }
435
  budget = (BUDGET_TASK_MODEL *)m;
436
 
1089 pj 437
#ifdef CBSSTAR_DEBUG
438
  cbsstar_printf("(C:gcr %d b%d", p, budget->b);
439
#endif
440
 
441
  lev->tb[p] = budget->b;
442
 
1180 trimarchi 443
  if (lev->b[budget->b].current == NIL && lev->b[budget->b].flags ) {
1089 pj 444
    /* This is the first task in the budget,
445
       the task have to be inserted into the master module */
446
    struct timespec t;
1123 pj 447
    kern_gettime(&t);
1089 pj 448
    CBSSTAR_activation(lev,p,&t);
449
  } else {
450
    /* The budget is not empty, another task is already into the
451
       master module, so the task is inserted at the end of the budget
452
       queue */
1116 pj 453
    iq_insertlast(p,&lev->b[budget->b].tasks);
1180 trimarchi 454
//#ifdef CBSSTAR_DEBUG
455
    //kern_printf(" ilast flag %d task %d",lev->b[budget->b].flags,lev->b[budget->b].current);
456
 //   cbsstar_printq(&lev->b[budget->b].tasks);
457
//#endif
1089 pj 458
  }
459
#ifdef CBSSTAR_DEBUG
460
  cbsstar_printf(")");
461
#endif
462
}
463
 
1123 pj 464
static void CBSSTAR_private_extract(LEVEL l, PID p)
1089 pj 465
{
466
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
467
 
1180 trimarchi 468
//#ifdef CBSSTAR_DEBUG
469
  //kern_printf("(C:gend p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
470
  //cbsstar_printq(&lev->b[lev->tb[p]].tasks);
471
//#endif
1089 pj 472
 
473
  /* a task is removed from execution for some reasons. It must be
474
     that it is the first in its budget queue (only the first task in
475
     a budget queue is put into execution!) */
476
 
477
  /* remove the task from execution (or from the ready queue) */
478
  if (lev->b[lev->tb[p]].current == p) {
1180 trimarchi 479
 
480
   CBSSTAR_account_capacity(lev,p);
1089 pj 481
    /* remove the task from the master module */
482
    level_table[ lev->scheduling_level ]->
1123 pj 483
      private_extract(lev->scheduling_level, p);
1089 pj 484
 
485
#ifdef CBSSTAR_DEBUG
486
    cbsstar_printq(&lev->b[lev->tb[p]].tasks);
487
#endif
488
 
489
    /* check if the buffer has someone else to schedule */
1116 pj 490
    if (iq_query_first(&lev->b[lev->tb[p]].tasks) == NIL) {
1089 pj 491
      /* the buffer has no tasks! */
492
      lev->b[lev->tb[p]].current = NIL;
493
    }
1180 trimarchi 494
    else if (lev->b[lev->tb[p]].flags) {
1089 pj 495
      /* if so, insert the new task into the master module */
496
      PID n;
497
      struct timespec t;
498
 
1123 pj 499
      kern_gettime(&t);
1116 pj 500
      n = iq_getfirst(&lev->b[lev->tb[p]].tasks);
1180 trimarchi 501
//#ifdef CBSSTAR_DEBUG
502
      //kern_printf("{p%d n%d}",p,n);
503
//#endif
1089 pj 504
      CBSSTAR_activation(lev,n,&t);  // it modifies b[lev->tb[p]].current
505
    }
1180 trimarchi 506
    else
507
        lev->b[lev->tb[p]].current=NIL;
508
 
1089 pj 509
  }
1180 trimarchi 510
  else  {
1116 pj 511
    iq_extract(p, &lev->b[lev->tb[p]].tasks);
1180 trimarchi 512
  }
1089 pj 513
}
514
 
1123 pj 515
static void CBSSTAR_private_dispatch(LEVEL l, PID p, int nostop)
1089 pj 516
{
517
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
518
  struct timespec ty;
519
 
1180 trimarchi 520
//#ifdef CBSSTAR_DEBUG
521
  //kern_printf("(C:gdisp p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
522
//  cbsstar_printq(&lev->b[lev->tb[p]].tasks);
523
//#endif
1089 pj 524
 
525
  /* the current task (that is the only one inserted in the master module
526
     for the corresponding budget) is dispatched. Note that the current
527
     task is not inserted in any FIFO queue, so the task does not have to
528
     be extracted! */
529
 
530
  /* ... then, we dispatch it to the master level */
531
  level_table[ lev->scheduling_level ]->
1123 pj 532
    private_dispatch(lev->scheduling_level,p,nostop);
1089 pj 533
 
534
  /* ...and finally, we have to post a capacity event */
535
  if (!nostop) {
536
    TIMESPEC_ASSIGN(&ty, &schedule_time);
537
    ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty);
1180 trimarchi 538
    lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
1176 trimarchi 539
  }
1180 trimarchi 540
 
1089 pj 541
}
542
 
1123 pj 543
static void CBSSTAR_private_epilogue(LEVEL l, PID p)
1089 pj 544
{
545
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
546
  struct budget_struct *b = &lev->b[lev->tb[p]];
547
 
548
 
1180 trimarchi 549
  //#ifdef CBSSTAR_DEBUG
550
  //kern_printf("(C:gepi %d %d",p, b->current);
551
  //#endif
1089 pj 552
 
1180 trimarchi 553
  if (p==b->current)  {
554
 
555
 CBSSTAR_account_capacity(lev,p);
1176 trimarchi 556
 
1180 trimarchi 557
    // L'evento di capacitÓ va cancellato perchŔ sarÓ ripristinato nella successiva dispatch
558
    /* we have to check if the capacity is still available */
559
    if (b->flags)  {
560
      /* there is capacity available, maybe it is simply a preemption;
561
         the task have to return to the ready queue */
562
      level_table[ lev->scheduling_level ]->
563
        private_epilogue(lev->scheduling_level,p);
564
#ifdef CBSSTAR_DEBUG
565
      //kern_printf("(ep *av=%d", b->avail);
566
#endif
567
 
568
 
569
    } else {
570
      /* we kill the current activation */
571
      level_table[ lev->scheduling_level ]->
572
        private_extract(lev->scheduling_level, p);
573
      //kern_printf("extract");
574
      iq_insertfirst(p, &b->tasks);
575
      proc_table[p].status = CBSSTAR_IDLE;
576
      b->current = NIL;
577
 
578
      //kern_printf("budget finish %d", b);
1089 pj 579
    }
580
#ifdef CBSSTAR_DEBUG
1180 trimarchi 581
    cbsstar_printf(")");
1089 pj 582
#endif
1180 trimarchi 583
   }
584
 
1089 pj 585
}
586
 
1180 trimarchi 587
/* Registration functions }*/
1089 pj 588
 
589
/*+ Registration function:
590
    int flags                 the init flags ... see CBSSTAR.h +*/
591
LEVEL CBSSTAR_register_level(int n, LEVEL master)
592
{
593
  LEVEL l;            /* the level that we register */
594
  CBSSTAR_level_des *lev;  /* for readableness only */
595
  PID i;              /* a counter */
596
 
597
#ifdef CBSSTAR_DEBUG
598
  cbsstar_printf("CBSSTAR_register_level\n");
599
#endif
600
 
601
  /* request an entry in the level_table */
1123 pj 602
  l = level_alloc_descriptor(sizeof(CBSSTAR_level_des));
1089 pj 603
 
1123 pj 604
  lev = (CBSSTAR_level_des *)level_table[l];
1089 pj 605
 
1123 pj 606
  printk("    lev=%d\n",(int)lev);
1089 pj 607
 
608
  /* fill the standard descriptor */
1123 pj 609
  lev->l.private_insert   = CBSSTAR_private_insert;
610
  lev->l.private_extract  = CBSSTAR_private_extract;
611
  lev->l.private_eligible = CBSSTAR_private_eligible;
612
  lev->l.private_dispatch = CBSSTAR_private_dispatch;
613
  lev->l.private_epilogue = CBSSTAR_private_epilogue;
1089 pj 614
 
1123 pj 615
  lev->l.public_guarantee = CBSSTAR_public_guarantee;
1089 pj 616
 
617
  /* fill the CBSSTAR descriptor part */
618
  lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
619
 
620
  for (i=0; i<n; i++) {
621
    lev->b[i].Q = 0;
622
    lev->b[i].T = 0;
623
    NULL_TIMESPEC(&lev->b[i].dline);
1180 trimarchi 624
    lev->b[i].dline_timer = NIL;
1089 pj 625
    lev->b[i].avail = 0;
626
    lev->b[i].current = -1;
1180 trimarchi 627
    lev->b[i].flags=INIT;
1116 pj 628
    iq_init(&lev->b[i].tasks, &freedesc, 0);
1089 pj 629
  }
630
 
631
  lev->n = n;
632
  lev->freebudgets = 0;
1180 trimarchi 633
 
1089 pj 634
  for (i=0; i<MAX_PROC; i++)
635
    lev->tb[i] = NIL;
636
 
637
  lev->U = 0;
1176 trimarchi 638
  lev->cap_lev=NIL;
1089 pj 639
  lev->scheduling_level = master;
1180 trimarchi 640
  lev->on_shadow=NIL;
1089 pj 641
 
642
  return l;
643
}
644
 
645
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T)
646
{
647
  CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
648
 
649
#ifdef CBSSTAR_DEBUG
650
  cbsstar_printf("(C:sbud)");
651
#endif
652
 
1123 pj 653
  if (lev->freebudgets != lev->n) {
654
    bandwidth_t b;
655
    b = (MAX_BANDWIDTH / T) * Q;
656
 
657
    /* really update lev->U, checking an overflow... */
658
    if (Q< T && MAX_BANDWIDTH - lev->U > b) {
659
      int r = lev->freebudgets;  // the return value
1089 pj 660
 
1123 pj 661
      lev->U += b;
662
      lev->freebudgets++;
663
 
664
      lev->b[r].Q = Q;
665
      lev->b[r].T = T;
666
 
667
      return r;
1089 pj 668
    }
669
    else
1123 pj 670
      return -2;
1089 pj 671
  }
672
  else
1123 pj 673
    return -1;
1089 pj 674
}