Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1624 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     :
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
 ------------
23
 CVS :        $Id: cash.c,v 1.1.1.1 2004-05-24 17:54:49 giacomo Exp $
24
 
25
 File:        $File$
26
 Revision:    $Revision: 1.1.1.1 $
27
 Last update: $Date: 2004-05-24 17:54:49 $
28
 ------------
29
 
30
 This file contains the aperiodic server CBS (Total Bandwidth Server)
31
 
32
 Read CBS.h for further details.
33
 
34
**/
35
 
36
/*
37
 * Copyright (C) 2000 Paolo Gai
38
 *
39
 * This program is free software; you can redistribute it and/or modify
40
 * it under the terms of the GNU General Public License as published by
41
 * the Free Software Foundation; either version 2 of the License, or
42
 * (at your option) any later version.
43
 *
44
 * This program is distributed in the hope that it will be useful,
45
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
46
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
47
 * GNU General Public License for more details.
48
 *
49
 * You should have received a copy of the GNU General Public License
50
 * along with this program; if not, write to the Free Software
51
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
52
 *
53
 */
54
 
55
 
56
#include "cash.h"
57
#include <ll/stdio.h>
58
#include <ll/string.h>
59
#include <kernel/model.h>
60
#include <kernel/descr.h>
61
#include <kernel/var.h>
62
#include <kernel/func.h>
63
 
64
/*+ Status used in the level +*/
65
#define CBSGHD_IDLE          APER_STATUS_BASE   /*+ waiting the activation +*/
66
#define CBSGHD_ZOMBIE        APER_STATUS_BASE+1 /*+ waiting the period end +*/
67
 
68
/* structure of an element of the capacity queue  */
69
struct cap_queue {
70
  int              cap;
71
  struct timespec  dead;
72
  struct cap_queue *next;
73
};
74
 
75
/*+ the level redefinition for the CBS_HD level +*/
76
typedef struct {
77
  level_des l;     /*+ the standard level descriptor          +*/
78
 
79
  /* The wcet are stored in the task descriptor, but we need
80
     an array for the deadlines. We can't use the timespec_priority
81
     field because it is used by the master level!!!...
82
     Notice that however the use of the timespec_priority field
83
     does not cause any problem...                     */
84
 
85
  struct timespec cbsghd_dline[MAX_PROC]; /*+ CBSGHD deadlines      +*/
86
 
87
  TIME period[MAX_PROC]; /*+ CBSGHD activation period            +*/
88
 
89
  TIME maxperiod[MAX_PROC]; /*+ maximum period of each elastic task    +*/
90
 
91
  int cremaining[MAX_PROC]; /*+ instance remaining computation time +*/
92
 
93
  TIME act_period[MAX_PROC]; /*+ actual period of each elastic task: it
94
                               must be less than maxperiod!!!        +*/
95
 
96
  struct timespec request_time[MAX_PROC]; /* used for the response time */
97
  TIME last_response_time[MAX_PROC]; /* response time of the last instance */
98
 
99
  TIME cnormal[MAX_PROC]; /*+ CBSGHD normal computation time    +*/
100
 
101
  struct timespec reactivation_time[MAX_PROC];
102
        /*+ the time at witch  the reactivation timer is post +*/
103
  int reactivation_timer[MAX_PROC];
104
                                   /*+ the recativation timer +*/
105
 
106
  struct cap_queue *queue;         /* pointer to the spare capacity queue */
107
 
108
  int flags;       /*+ the init flags...                      +*/
109
 
110
  bandwidth_t U;   /*+ the used bandwidth by the server       +*/
111
 
112
  int idle;         /* the idle flag...  */
113
 
114
  struct timespec start_idle; /*gives the start time of the last idle period */
115
 
116
  LEVEL scheduling_level;
117
 
118
} CBSGHD_level_des;
119
 
120
 
121
/* insert a capacity in the queue capacity ordering by deadline */
122
 
123
static int c_insert(struct timespec dead, int cap, struct cap_queue **que,
124
                     PID p)
125
{
126
  struct cap_queue *prev, *n, *new;
127
 
128
    prev = NULL;
129
    n = *que;
130
 
131
    while ((n != NULL) &&
132
           !TIMESPEC_A_LT_B(&dead, &n->dead)) {
133
        prev = n;
134
        n = n->next;
135
    }
136
 
137
 
138
    new = (struct cap_queue *)kern_alloc(sizeof(struct cap_queue));
139
    if (new == NULL) {
140
      kern_printf("\nNew cash_queue element failed\n");
141
      kern_raise(XINVALID_TASK, p);
142
      return -1;
143
    }
144
    new->next = NULL;
145
    new->cap = cap;
146
    new->dead = dead;
147
 
148
    if (prev != NULL)
149
      prev->next = new;
150
    else
151
      *que = new;
152
 
153
    if (n != NULL)
154
      new->next = n;
155
    return 0;
156
}
157
 
158
/* extract the first element from the capacity queue */
159
 
160
static int c_extractfirst(struct cap_queue **que)
161
{
162
    struct cap_queue *p = *que;
163
 
164
 
165
    if (*que == NULL) return(-1);
166
 
167
    *que = (*que)->next;
168
 
169
    kern_free(p, sizeof(struct cap_queue));
170
    return(1);
171
}
172
 
173
/* read data of the first element from the capacity queue */
174
 
175
static void c_readfirst(struct timespec *d, int *c, struct cap_queue *que)
176
{
177
    *d = que->dead;
178
    *c = que->cap;
179
}
180
 
181
/* write data of the first element from the capacity queue */
182
 
183
static void c_writefirst(struct timespec dead, int cap, struct cap_queue *que)
184
{
185
    que->dead = dead;
186
    que->cap = cap;
187
}
188
 
189
 
190
static void CBSGHD_activation(CBSGHD_level_des *lev,
191
                             PID p,
192
                             struct timespec *acttime)
193
{
194
  JOB_TASK_MODEL job;
195
 
196
 
197
  /* This rule is used when we recharge the budget at initial task activation
198
     and each time a new task instance must be activated  */
199
 
200
  if (TIMESPEC_A_GT_B(acttime, &lev->cbsghd_dline[p])) {
201
    /* we modify the deadline ... */
202
    TIMESPEC_ASSIGN(&lev->cbsghd_dline[p], acttime);
203
  }
204
 
205
  lev->act_period[p] = 0;
206
 
207
  if (proc_table[p].avail_time > 0)
208
    proc_table[p].avail_time = 0;
209
 
210
 
211
 
212
 
213
  /* there is a while because if the wcet is << than the system tick
214
     we need to postpone the deadline many times */
215
  while (proc_table[p].avail_time <= 0) {
216
 
217
    /* A spare capacity is inserted in the capacity queue!! */
218
    ADDUSEC2TIMESPEC(lev->period[p], &lev->cbsghd_dline[p]);
219
    lev->act_period[p] += lev->period[p];
220
    c_insert(lev->cbsghd_dline[p], lev->cnormal[p], &lev->queue, p);
221
 
222
 
223
    /* it exploits available capacities from the capacity queue */
224
    while (proc_table[p].avail_time < (int)lev->cnormal[p] &&
225
           lev->queue != NULL) {
226
      struct timespec dead;
227
      int             cap, delta;
228
      delta = lev->cnormal[p] - proc_table[p].avail_time;
229
      c_readfirst(&dead, &cap, lev->queue);
230
      if (!TIMESPEC_A_GT_B(&dead, &lev->cbsghd_dline[p])) {
231
        if (cap > delta) {
232
          proc_table[p].avail_time += delta;
233
          c_writefirst(dead, cap - delta, lev->queue);
234
        }
235
        else {
236
          proc_table[p].avail_time += cap;
237
          c_extractfirst(&lev->queue);
238
        }
239
      }
240
      else
241
        break;
242
    }
243
  }
244
 
245
  lev->cremaining[p] = proc_table[p].wcet - proc_table[p].avail_time;
246
 
247
 
248
#ifdef TESTG
249
  if (starttime && p == 3) {
250
    oldx = x;
251
    x = ((lev->cbsghd_dline[p].tv_sec*1000000+lev->cbsghd_dline[p].tv_nsec/1000)/5000 - starttime) + 20;
252
    //      kern_printf("(a%d)",lev->cbsghd_dline[p].tv_sec*1000000+lev->cbsghd_dline[p].tv_nsec/1000);
253
    if (oldx > x) sys_end();
254
    if (x<640)
255
      grx_plot(x, 15, 8);
256
  }
257
#endif
258
 
259
  /* and, finally, we reinsert the task in the master level */
260
  job_task_default_model(job, lev->cbsghd_dline[p]);
261
  job_task_def_yesexc(job);
262
  level_table[ lev->scheduling_level ]->
263
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
264
}
265
 
266
 
267
/* this is the periodic reactivation of the task... */
268
static void CBSGHD_timer_reactivate(void *par)
269
{
270
  PID p = (PID) par;
271
  CBSGHD_level_des *lev;
272
 
273
  lev = (CBSGHD_level_des *)level_table[proc_table[p].task_level];
274
 
275
  if (proc_table[p].status == CBSGHD_IDLE) {
276
    /* the task has finished the current activation and must be
277
       reactivated */
278
 
279
    /* request_time represents the time of the last instance release!! */
280
    TIMESPEC_ASSIGN(&lev->request_time[p], &lev->reactivation_time[p]);
281
 
282
    /* If idle=1, then we have to discharge the capacities stored in
283
       the capacity queue up to the length of the idle interval */
284
    if (lev->idle == 1) {
285
      TIME interval;
286
      struct timespec delta;
287
      lev->idle = 0;
288
      SUBTIMESPEC(&lev->request_time[p], &lev->start_idle, &delta);
289
      /* length of the idle interval expressed in usec! */
290
      interval = TIMESPEC2NANOSEC(&delta) / 1000;
291
 
292
      /* it discharge the available capacities from the capacity queue */
293
      while (interval > 0 && lev->queue != NULL) {
294
        struct timespec dead;
295
        int             cap;
296
        c_readfirst(&dead, &cap, lev->queue);
297
        if (cap > interval) {
298
          c_writefirst(dead, cap - interval, lev->queue);
299
          interval = 0;
300
        }
301
        else {
302
          interval -= cap;
303
          c_extractfirst(&lev->queue);
304
        }      
305
      }
306
    }
307
 
308
    CBSGHD_activation(lev,p,&lev->reactivation_time[p]);
309
 
310
    /* check the constraint on the maximum period permitted... */
311
    if (lev->act_period[p] > lev->maxperiod[p]) {
312
      kern_printf("Deadline miss(timer_react.! process:%d act_period:%lu maxperiod:%lu\n",
313
                  p, lev->act_period[p], lev->maxperiod[p]);
314
      kern_raise(XDEADLINE_MISS,p);
315
    }
316
 
317
 
318
    /* Set the reactivation timer */
319
    TIMESPEC_ASSIGN(&lev->reactivation_time[p], &lev->cbsghd_dline[p]);
320
    lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
321
                                                 CBSGHD_timer_reactivate,
322
                                                 (void *)p);
323
    event_need_reschedule();
324
  }
325
  else {
326
    /* this situation cannot occur */
327
    kern_printf("Trying to reactivate a task which is not IDLE!!!/n");
328
    kern_raise(XINVALID_TASK,p);
329
  }
330
}
331
 
332
 
333
 
334
 
335
 
336
static void CBSGHD_avail_time_check(CBSGHD_level_des *lev, PID p)
337
{
338
 
339
  /*+ if the capacity became negative the remaining computation time
340
    is diminuished.... +*/
341
  /* if (p==4)
342
    kern_printf("(old dead:%d av_time:%d crem:%d)\n",
343
                lev->cbsghd_dline[p].tv_sec*1000000+
344
                lev->cbsghd_dline[p].tv_nsec/1000, proc_table[p].avail_time,
345
                lev->cremaining[p]);  */
346
 
347
 
348
  if (proc_table[p].avail_time < 0)
349
    lev->cremaining[p] += proc_table[p].avail_time;
350
 
351
  if (lev->cremaining[p] <= 0) {
352
    kern_printf("Task:%d   WCET violation \n", p);
353
    kern_raise(XWCET_VIOLATION, p);
354
    ll_abort(666);
355
  }
356
 
357
 
358
  /* there is a while because if the wcet is << than the system tick
359
     we need to postpone the deadline many times */
360
  while (proc_table[p].avail_time <= 0) {
361
    /* it exploits available capacities from the capacity queue */
362
    while (proc_table[p].avail_time < lev->cremaining[p]
363
           && lev->queue != NULL) {
364
      struct timespec dead;
365
      int             cap, delta;
366
      delta = lev->cremaining[p] - proc_table[p].avail_time;
367
      c_readfirst(&dead, &cap, lev->queue);
368
      if (!TIMESPEC_A_GT_B(&dead, &lev->cbsghd_dline[p])) {
369
        if (cap > delta) {
370
          proc_table[p].avail_time += delta;
371
          c_writefirst(dead, cap - delta, lev->queue);
372
        }
373
        else {
374
          proc_table[p].avail_time += cap;
375
          c_extractfirst(&lev->queue);
376
        }
377
      }
378
      else
379
        break;
380
    }
381
 
382
    /* if (p==5 && proc_table[p].avail_time <= 0 &&
383
       lev->cremaining[p] > lev->cnormal[p])
384
       kern_printf("(inter dead:%d av_time:%d crem:%d)\n",
385
       lev->cbsghd_dline[p].tv_sec*1000000+
386
       lev->cbsghd_dline[p].tv_nsec/1000, proc_table[p].avail_time,
387
       lev->cremaining[p]); */
388
 
389
 
390
    /* The remaining computation time is modified according
391
       to the new budget! */
392
    if (proc_table[p].avail_time > 0)
393
      lev->cremaining[p] -= proc_table[p].avail_time;
394
    else {
395
      /* the CBSGHD rule for recharging the capacity:  */
396
      if (lev->cremaining[p] > lev->cnormal[p]) {
397
        ADDUSEC2TIMESPEC(lev->period[p], &lev->cbsghd_dline[p]);
398
        lev->act_period[p] += lev->period[p];
399
        /* A spare capacity is inserted in the capacity queue!! */
400
        c_insert(lev->cbsghd_dline[p], lev->cnormal[p], &lev->queue, p);
401
      }
402
      else {
403
        TIME t;
404
        t = (lev->cremaining[p] * lev->period[p]) / lev->cnormal[p];
405
        ADDUSEC2TIMESPEC(t, &lev->cbsghd_dline[p]);
406
        lev->act_period[p] += t;
407
        /* A spare capacity is inserted in the capacity queue!! */
408
        c_insert(lev->cbsghd_dline[p], lev->cremaining[p], &lev->queue, p);
409
      }
410
    }
411
  }
412
 
413
  /*  if (p==4)
414
    kern_printf("n dead:%d av_time:%d crem:%d)\n",
415
                lev->cbsghd_dline[p].tv_sec*1000000+
416
                lev->cbsghd_dline[p].tv_nsec/1000, proc_table[p].avail_time,
417
                lev->cremaining[p]);  */
418
 
419
  /* check the constraint on the maximum period permitted... */
420
  if (lev->act_period[p] > lev->maxperiod[p]) {
421
    /*kern_printf("n dead:%d av_time:%d crem:%d)\n",
422
                lev->cbsghd_dline[p].tv_sec*1000000+
423
                lev->cbsghd_dline[p].tv_nsec/1000, proc_table[p].avail_time,
424
                lev->cremaining[p]);  */
425
    kern_printf("Deadline miss(av.time_check! process:%d act_period:%lu maxperiod:%lu\n",
426
                p, lev->act_period[p], lev->maxperiod[p]);
427
    kern_raise(XDEADLINE_MISS,p);
428
  }
429
 
430
 
431
 
432
  if (TIMESPEC_A_LT_B(&lev->reactivation_time[p], &lev->cbsghd_dline[p])) {
433
    /* we delete the reactivation timer */
434
    kern_event_delete(lev->reactivation_timer[p]);
435
    /* repost the event at the next instance deadline... */
436
    lev->reactivation_time[p] = lev->cbsghd_dline[p];
437
    lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
438
                                                 CBSGHD_timer_reactivate,
439
                                                 (void *)p);
440
  }
441
 
442
#ifdef TESTG
443
  if (starttime && p == 3) {
444
    oldx = x;
445
    x = ((lev->cbsghd_dline[p].tv_sec*1000000+
446
          lev->cbsghd_dline[p].tv_nsec/1000)/5000 - starttime) + 20;
447
    //      kern_printf("(e%d avail%d)",lev->cbsghd_dline[p].tv_sec*1000000+
448
                        lev->cbsghd_dline[p].tv_nsec/1000,proc_table[p].avail_time);
449
    if (oldx > x) sys_end();
450
    if (x<640)
451
      grx_plot(x, 15, 2);
452
  }
453
#endif
454
 
455
}
456
 
457
 
458
/*+ this function is called when a killed or ended task reach the
459
  period end +*/
460
static void CBSGHD_timer_zombie(void *par)
461
{
462
  PID p = (PID) par;
463
  CBSGHD_level_des *lev;
464
 
465
  lev = (CBSGHD_level_des *)level_table[proc_table[p].task_level];
466
 
467
  /* we finally put the task in the FREE status */
468
  proc_table[p].status = FREE;
469
  iq_insertfirst(p,&freedesc);
470
 
471
  /* and free the allocated bandwidth */
472
  lev->U -= (MAX_BANDWIDTH/lev->period[p]) * lev->cnormal[p];
473
 
474
}
475
 
476
static PID CBSGHD_public_scheduler(LEVEL l)
477
{
478
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
479
 
480
  /* it stores the actual time and set the IDLE flag in order to handle
481
     the capacity queue discharging!!! */
482
  lev->idle = 1;
483
  kern_gettime(&lev->start_idle);
484
 
485
 
486
  /* the CBSGHD don't schedule anything...
487
     it's an EDF level or similar that do it! */
488
  return NIL;
489
}
490
 
491
/* The on-line guarantee is enabled only if the appropriate flag is set... */
492
static int CBSGHD_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
493
{
494
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
495
 
496
  if (lev->flags & CBSGHD_FAILED_GUARANTEE) {
497
    *freebandwidth = 0;
498
    //kern_printf("guarantee :garanzia fallita!!!!!!\n");
499
    return 0;
500
  }
501
  else if (*freebandwidth >= lev->U) {
502
    *freebandwidth -= lev->U;
503
    return 1;
504
  }
505
  else {
506
    //kern_printf("guarantee :garanzia fallita per mancanza di banda!!!!!!\n");
507
    //kern_printf("freeband: %d request band: %d", *freebandwidth, lev->U);
508
    return 0;
509
  }
510
}
511
 
512
static int CBSGHD_public_create(LEVEL l, PID p, TASK_MODEL *m)
513
{
514
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
515
  ELASTIC_HARD_TASK_MODEL *s;
516
  bandwidth_t b1, b2;
517
 
518
  if (m->pclass != ELASTIC_HARD_PCLASS) return -1;
519
  if (m->level != 0 && m->level != l) return -1;
520
  s = (ELASTIC_HARD_TASK_MODEL *)m;
521
 
522
  /*  kern_printf("accept :ELASTIC TASK found!!!!!!\n"); */
523
  b1 = (MAX_BANDWIDTH / s->period) * s->cnormal;
524
  b2 = (MAX_BANDWIDTH / s->maxperiod) * s->wcet;
525
  if (!(s->wcet && s->cnormal && s->period && s->maxperiod &&
526
        s->wcet >= s->cnormal && b1 >= b2) )
527
    return -1;
528
  /*  kern_printf("period: %d maxperiod: %d cnormal: %d wcet: %d, b1: %d b2:
529
      %d\n", s->period, s->maxperiod, s->cnormal, s->wcet, b1, b2); */
530
 
531
  /* now we know that m is a valid model */
532
 
533
 
534
  /* Enable wcet check */
535
  proc_table[p].avail_time = 0;
536
  proc_table[p].wcet       = s->wcet;
537
  proc_table[p].control   |= CONTROL_CAP;
538
 
539
  lev->period[p] = s->period;
540
  lev->maxperiod[p] = s->maxperiod;
541
  lev->cnormal[p] = s->cnormal;
542
  NULL_TIMESPEC(&lev->cbsghd_dline[p]);
543
  NULL_TIMESPEC(&lev->request_time[p]);
544
 
545
 
546
  /* update the bandwidth... */
547
  if (lev->flags & CBSGHD_ENABLE_GUARANTEE) {
548
    bandwidth_t b;
549
    b = (MAX_BANDWIDTH / s->period) * s->cnormal;
550
 
551
    /* really update lev->U, checking an overflow... */
552
    if (MAX_BANDWIDTH - lev->U > b)
553
      lev->U += b;
554
    else
555
      /* The task can NOT be guaranteed (U>MAX_BANDWIDTH)...
556
         (see EDF.c) */
557
      lev->flags |= CBSGHD_FAILED_GUARANTEE;
558
  }
559
 
560
 
561
 
562
  return 0; /* OK, also if the task cannot be guaranteed... */
563
}
564
 
565
static void CBSGHD_public_detach(LEVEL l, PID p)
566
{
567
  /* the CBSGHD level doesn't introduce any dinamic allocated new field.
568
     we have only to reset the NO_GUARANTEE FIELD and decrement the allocated
569
     bandwidth */
570
 
571
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
572
 
573
  if (lev->flags & CBSGHD_FAILED_GUARANTEE)
574
    lev->flags &= ~CBSGHD_FAILED_GUARANTEE;
575
  else
576
    lev->U -= (MAX_BANDWIDTH / lev->period[p]) * lev->cnormal[p];
577
 
578
 
579
}
580
 
581
static void CBSGHD_public_dispatch(LEVEL l, PID p, int nostop)
582
{
583
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
584
  level_table[ lev->scheduling_level ]->
585
    private_dispatch(lev->scheduling_level,p,nostop);
586
 
587
}
588
 
589
static void CBSGHD_public_epilogue(LEVEL l, PID p)
590
{
591
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
592
  JOB_TASK_MODEL job;
593
 
594
  /* check if the budget is finished... */
595
  if ( proc_table[p].avail_time <= 0) {
596
    /* we kill the current activation */
597
    level_table[ lev->scheduling_level ]->
598
      private_extract(lev->scheduling_level, p);
599
 
600
    /* we modify the deadline */
601
    CBSGHD_avail_time_check(lev, p);
602
 
603
    /* and, finally, we reinsert the task in the master level */
604
    job_task_default_model(job, lev->cbsghd_dline[p]);
605
    job_task_def_yesexc(job);
606
    level_table[ lev->scheduling_level ]->
607
      private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
608
    //    kern_printf("epil : dl %d per %d p %d |\n",
609
                      //              lev->cbsghd_dline[p].tv_nsec/1000,lev->period[p],p);
610
 
611
  }
612
  else
613
    /* the task has been preempted. it returns into the ready queue by
614
       calling the guest_epilogue... */
615
    level_table[ lev->scheduling_level ]->
616
      private_epilogue(lev->scheduling_level,p);
617
}
618
 
619
static void CBSGHD_public_activate(LEVEL l, PID p)
620
{
621
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
622
 
623
  kern_gettime(&lev->request_time[p]);
624
 
625
  /* If idle=1, then we have to discharge the capacities stored in
626
     the capacity queue up to the length of the idle interval */
627
  if (lev->idle == 1) {
628
    TIME interval;
629
    struct timespec delta;
630
    lev->idle = 0;
631
    SUBTIMESPEC(&lev->request_time[p], &lev->start_idle, &delta);
632
    /* length of the idle interval expressed in usec! */
633
    interval = TIMESPEC2NANOSEC(&delta) / 1000;
634
 
635
    /* it discharge the available capacities from the capacity queue */
636
    while (interval > 0 && lev->queue != NULL) {
637
      struct timespec dead;
638
      int             cap;
639
      c_readfirst(&dead, &cap, lev->queue);
640
      if (cap > interval) {
641
        c_writefirst(dead, cap - interval, lev->queue);
642
        interval = 0;
643
      }
644
      else {
645
        interval -= cap;
646
        c_extractfirst(&lev->queue);
647
      }
648
    }
649
  }
650
 
651
  CBSGHD_activation(lev, p, &lev->request_time[p]);
652
 
653
 
654
  /* check the constraint on the maximum period permitted... */
655
  if (lev->act_period[p] > lev->maxperiod[p]) {
656
      kern_printf("Deadline miss(task_activ.! process:%d act_period:%lu maxperiod:%lu\n",
657
                  p, lev->act_period[p], lev->maxperiod[p]);
658
    kern_raise(XDEADLINE_MISS,p);
659
  }
660
 
661
  /* Set the reactivation timer */
662
  TIMESPEC_ASSIGN(&lev->reactivation_time[p], &lev->cbsghd_dline[p]);
663
  lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
664
                                                   CBSGHD_timer_reactivate,
665
                                                   (void *)p);
666
 
667
  //  kern_printf("act : %d %d |",lev->cbsghd_dline[p].tv_nsec/1000,p);
668
}
669
 
670
static void CBSGHD_public_unblock(LEVEL l, PID p)
671
{
672
  printk("CBSGHD_task_insert\n");
673
  kern_raise(XINVALID_TASK,p);
674
}
675
 
676
static void CBSGHD_public_block(LEVEL l, PID p)
677
{
678
  printk("CBSGHD_task_extract\n");
679
  kern_raise(XINVALID_TASK,p);
680
}
681
 
682
static int CBSGHD_public_message(LEVEL l, PID p, void *m)
683
{
684
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
685
  struct timespec act_time, res;
686
 
687
  /* It computes the response time of the current instance... */
688
  kern_gettime(&act_time);
689
  SUBTIMESPEC(&act_time, &lev->request_time[p], &res);
690
  /* response time expressed in usec! */
691
  lev->last_response_time[p] = TIMESPEC2NANOSEC(&res) / 1000;
692
 
693
  level_table[ lev->scheduling_level ]->
694
    private_extract(lev->scheduling_level,p);
695
 
696
 
697
  /* A spare capacity is inserted in the capacity queue!! */
698
  if (proc_table[p].avail_time > 0) {
699
    c_insert(lev->cbsghd_dline[p], proc_table[p].avail_time, &lev->queue, p);
700
    proc_table[p].avail_time = 0;
701
  }  
702
 
703
 
704
  proc_table[p].status = CBSGHD_IDLE;
705
 
706
  jet_update_endcycle(); /* Update the Jet data... */
707
 
708
  return 0;
709
}
710
 
711
static void CBSGHD_public_end(LEVEL l, PID p)
712
{
713
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
714
 
715
  /* check if the capacity became negative... */
716
  /* there is a while because if the wcet is << than the system tick
717
     we need to postpone the deadline many times */
718
  while (proc_table[p].avail_time < 0) {
719
    /* the CBSGHD rule for recharging the capacity */
720
    proc_table[p].avail_time += lev->cnormal[p];
721
    ADDUSEC2TIMESPEC(lev->period[p], &lev->cbsghd_dline[p]);
722
  }
723
 
724
  level_table[ lev->scheduling_level ]->
725
    private_extract(lev->scheduling_level,p);
726
 
727
  /* we delete the reactivation timer */
728
  kern_event_delete(lev->reactivation_timer[p]);
729
  lev->reactivation_timer[p] = -1;
730
 
731
 
732
  /* Finally, we post the zombie event. when the end period is reached,
733
     the task descriptor and banwidth are freed */
734
  proc_table[p].status = CBSGHD_ZOMBIE;
735
  lev->reactivation_timer[p] = kern_event_post(&lev->cbsghd_dline[p],
736
                                               CBSGHD_timer_zombie,
737
                                               (void *)p);
738
}
739
 
740
/* Registration functions */
741
 
742
/*+ Registration function:
743
    int flags                 the init flags ... see CBS.h +*/
744
LEVEL CBSGHD_register_level(int flags, LEVEL master)
745
{
746
  LEVEL l;            /* the level that we register */
747
  CBSGHD_level_des *lev;  /* for readableness only */
748
  PID i;              /* a counter */
749
 
750
  printk("CBSGHD_register_level\n");
751
 
752
  /* request an entry in the level_table */
753
  l = level_alloc_descriptor(sizeof(CBSGHD_level_des));
754
 
755
  lev = (CBSGHD_level_des *)level_table[l];
756
 
757
  printk("    lev=%d\n",(int)lev);
758
 
759
  /* fill the standard descriptor */
760
  lev->l.public_scheduler = CBSGHD_public_scheduler;
761
 
762
  if (flags & CBSGHD_ENABLE_GUARANTEE)
763
    lev->l.public_guarantee = CBSGHD_public_guarantee;
764
  else
765
    lev->l.public_guarantee = NULL;
766
 
767
  lev->l.public_create    = CBSGHD_public_create;
768
  lev->l.public_detach    = CBSGHD_public_detach;
769
  lev->l.public_end       = CBSGHD_public_end;
770
  lev->l.public_dispatch  = CBSGHD_public_dispatch;
771
  lev->l.public_epilogue  = CBSGHD_public_epilogue;
772
  lev->l.public_activate  = CBSGHD_public_activate;
773
  lev->l.public_unblock   = CBSGHD_public_unblock;
774
  lev->l.public_block     = CBSGHD_public_block;
775
  lev->l.public_message   = CBSGHD_public_message;
776
 
777
  /* fill the CBSGHD descriptor part */
778
  for (i=0; i<MAX_PROC; i++) {
779
     NULL_TIMESPEC(&lev->cbsghd_dline[i]);
780
     lev->period[i] = 0;
781
     NULL_TIMESPEC(&lev->request_time[i]);
782
     lev->last_response_time[i] = 0;
783
     NULL_TIMESPEC(&lev->reactivation_time[i]);
784
     lev->reactivation_timer[i] = -1;
785
  }
786
 
787
 
788
  lev->U = 0;
789
  lev->idle = 0;
790
  lev->queue = NULL;
791
 
792
  lev->scheduling_level = master;
793
 
794
  lev->flags = flags & 0x07;
795
 
796
  return l;
797
}
798
 
799
 
800
int CBSGHD_get_response_time(LEVEL l, PID p)
801
{
802
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
803
 
804
  return lev->last_response_time[p];
805
}
806
 
807
 
808
bandwidth_t CBSGHD_usedbandwidth(LEVEL l)
809
{
810
  CBSGHD_level_des *lev = (CBSGHD_level_des *)(level_table[l]);
811
 
812
  return lev->U;
813
}
814