Subversion Repositories shark

Rev

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

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