Subversion Repositories shark

Rev

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

Rev Author Line No. Line
2 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
 ------------
23
 CVS :        $Id: cbs.c,v 1.1.1.1 2002-03-29 14:12:52 pj Exp $
24
 
25
 File:        $File$
26
 Revision:    $Revision: 1.1.1.1 $
27
 Last update: $Date: 2002-03-29 14:12:52 $
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 <modules/cbs.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
#include <kernel/trace.h>
64
 
65
/*+ 4 debug purposes +*/
66
#undef CBS_TEST
67
#undef CBS_COUNTER
68
 
69
#ifdef TESTG
70
#include "drivers/glib.h"
71
TIME x,oldx;
72
extern TIME starttime;
73
#endif
74
 
75
 
76
/*+ Status used in the level +*/
77
#define CBS_IDLE          APER_STATUS_BASE   /*+ waiting the activation +*/
78
#define CBS_ZOMBIE        APER_STATUS_BASE+1 /*+ waiting the period end +*/
79
#define CBS_DELAY         APER_STATUS_BASE+2 /*+ waiting the delay end  +*/
80
 
81
/*+ task flags +*/
82
#define CBS_SAVE_ARRIVALS 1
83
#define CBS_APERIODIC     2
84
 
85
/*+ the level redefinition for the Total Bandwidth Server level +*/
86
typedef struct {
87
  level_des l;     /*+ the standard level descriptor          +*/
88
 
89
  /* The wcet are stored in the task descriptor, but we need
90
     an array for the deadlines. We can't use the timespec_priority
91
     field because it is used by the master level!!!...
92
     Notice that however the use of the timespec_priority field
93
     does not cause any problem...                     */
94
 
95
  struct timespec cbs_dline[MAX_PROC]; /*+ CBS deadlines      +*/
96
 
97
  TIME period[MAX_PROC]; /*+ CBS activation period            +*/
98
 
99
  struct timespec reactivation_time[MAX_PROC];
100
        /*+ the time at witch  the reactivation timer is post +*/
101
  int reactivation_timer[MAX_PROC];
102
                                   /*+ the recativation timer +*/
103
 
104
  int nact[MAX_PROC]; /*+ number of pending activations       +*/
105
 
106
  BYTE flag[MAX_PROC]; /*+ task flags                         +*/
107
 
108
  int flags;       /*+ the init flags...                      +*/
109
 
110
  bandwidth_t U;   /*+ the used bandwidth by the server       +*/
111
 
112
  LEVEL scheduling_level;
113
 
114
} CBS_level_des;
115
 
116
#ifdef CBS_COUNTER
117
int cbs_counter=0;
118
int cbs_counter2=0;
119
#endif
120
 
121
 
122
static void CBS_activation(CBS_level_des *lev,
123
                           PID p,
124
                           struct timespec *acttime)
125
{
126
  JOB_TASK_MODEL job;
127
 
128
  /* we have to check if the deadline and the wcet are correct before
129
     activating a new task or an old task... */
130
 
131
  /* check 1: if the deadline is before than the actual scheduling time */
132
 
133
  /* check 2: if ( avail_time >= (cbs_dline - acttime)* (wcet/period) )
134
     (rule 7 in the CBS article!) */
135
  TIME t;
136
  struct timespec t2,t3;
137
 
138
  t = (lev->period[p] * proc_table[p].avail_time) / proc_table[p].wcet;
139
  t3.tv_sec = t / 1000000;
140
  t3.tv_nsec = (t % 1000000) * 1000;
141
 
142
  SUBTIMESPEC(&lev->cbs_dline[p], acttime, &t2);
143
 
144
  if (/* 1 */ TIMESPEC_A_LT_B(&lev->cbs_dline[p], acttime) ||
145
      /* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
146
/*    if (TIMESPEC_A_LT_B(&lev->cbs_dline[p], acttime) )
147
      kern_printf("$");
148
    else
149
      kern_printf("(Ûdline%d.%d act%d.%d wcet%d per%d avail%dÛ)",
150
                  lev->cbs_dline[p].tv_sec,lev->cbs_dline[p].tv_nsec/1000,
151
                  acttime->tv_sec, acttime->tv_nsec/1000,
152
                  proc_table[p].wcet, lev->period[p], proc_table[p].avail_time);
153
*/  /* we modify the deadline ... */
154
    TIMESPEC_ASSIGN(&lev->cbs_dline[p], acttime);
155
    ADDUSEC2TIMESPEC(lev->period[p], &lev->cbs_dline[p]);
156
 
157
    /* and the capacity */
158
    proc_table[p].avail_time = proc_table[p].wcet;
159
  }
160
 
161
#ifdef TESTG
162
      if (starttime && p == 3) {
163
      oldx = x;
164
      x = ((lev->cbs_dline[p].tv_sec*1000000+lev->cbs_dline[p].tv_nsec/1000)/5000 - starttime) + 20;
165
//      kern_printf("(a%d)",lev->cbs_dline[p].tv_sec*1000000+lev->cbs_dline[p].tv_nsec/1000);
166
      if (oldx > x) sys_end();
167
      if (x<640)
168
        grx_plot(x, 15, 8);
169
      }
170
#endif
171
 
172
  /* and, finally, we reinsert the task in the master level */
173
  job_task_default_model(job, lev->cbs_dline[p]);
174
  job_task_def_noexc(job);
175
  level_table[ lev->scheduling_level ]->
176
    guest_create(lev->scheduling_level, p, (TASK_MODEL *)&job);
177
  level_table[ lev->scheduling_level ]->
178
    guest_activate(lev->scheduling_level, p);
179
 
180
}
181
 
182
 
183
static char *CBS_status_to_a(WORD status)
184
{
185
  if (status < MODULE_STATUS_BASE)
186
    return status_to_a(status);
187
 
188
  switch (status) {
189
    case CBS_IDLE   : return "CBS_Idle";
190
    case CBS_ZOMBIE : return "CBS_Zombie";
191
    case CBS_DELAY  : return "CBS_Delay";
192
    default         : return "CBS_Unknown";
193
  }
194
}
195
 
196
static void CBS_avail_time_check(CBS_level_des *lev, PID p)
197
{
198
  /* there is a while because if the wcet is << than the system tick
199
     we need to postpone the deadline many times */
200
  while (proc_table[p].avail_time <= 0) {
201
    ADDUSEC2TIMESPEC(lev->period[p], &lev->cbs_dline[p]);
202
    proc_table[p].avail_time += proc_table[p].wcet;
203
 
204
#ifdef TESTG
205
    if (starttime && p == 3) {
206
    oldx = x;
207
    x = ((lev->cbs_dline[p].tv_sec*1000000+lev->cbs_dline[p].tv_nsec/1000)/5000 - starttime) + 20;
208
//      kern_printf("(e%d avail%d)",lev->cbs_dline[p].tv_sec*1000000+lev->cbs_dline[p].tv_nsec/1000,proc_table[p].avail_time);
209
    if (oldx > x) sys_end();
210
    if (x<640)
211
      grx_plot(x, 15, 2);
212
    }
213
#endif
214
  }
215
}
216
 
217
 
218
/* this is the periodic reactivation of the task... it is posted only
219
   if the task is a periodic task */
220
static void CBS_timer_reactivate(void *par)
221
{
222
  PID p = (PID) par;
223
  CBS_level_des *lev;
224
 
225
  lev = (CBS_level_des *)level_table[proc_table[p].task_level];
226
 
227
  #ifdef CBS_COUNTER
228
    if (p==5) cbs_counter++;
229
  #endif
230
 
231
  if (proc_table[p].status == CBS_IDLE) {
232
    /* the task has finished the current activation and must be
233
       reactivated */
234
    CBS_activation(lev,p,&lev->reactivation_time[p]);
235
 
236
    event_need_reschedule();
237
  }
238
  else if (lev->flag[p] & CBS_SAVE_ARRIVALS)
239
    /* the task has not completed the current activation, so we save
240
       the activation incrementing nact... */
241
    lev->nact[p]++;
242
 
243
  /* repost the event at the next period end... */
244
  ADDUSEC2TIMESPEC(lev->period[p], &lev->reactivation_time[p]);
245
  lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
246
                                               CBS_timer_reactivate,
247
                                               (void *)p);
248
  #ifdef CBS_COUNTER
249
    if (p==5) cbs_counter2++;
250
  #endif
251
  /* tracer stuff */
252
  trc_logevent(TRC_INTACTIVATION,&p);
253
 
254
}
255
 
256
/*+ this function is called when a task finish his delay +*/
257
static void CBS_timer_delay(void *par)
258
{
259
  PID p = (PID) par;
260
  CBS_level_des *lev;
261
 
262
  lev = (CBS_level_des *)level_table[proc_table[p].task_level];
263
 
264
  CBS_activation(lev,p,&proc_table[p].timespec_priority);
265
 
266
  event_need_reschedule();
267
}
268
 
269
 
270
/*+ this function is called when a killed or ended task reach the
271
    period end +*/
272
static void CBS_timer_zombie(void *par)
273
{
274
  PID p = (PID) par;
275
  CBS_level_des *lev;
276
 
277
  lev = (CBS_level_des *)level_table[proc_table[p].task_level];
278
 
279
  /* we finally put the task in the ready queue */
280
  proc_table[p].status = FREE;
281
  q_insertfirst(p,&freedesc);
282
 
283
  /* and free the allocated bandwidth */
284
  lev->U -= (MAX_BANDWIDTH/lev->period[p]) * proc_table[p].wcet;
285
 
286
}
287
 
288
 
289
static int CBS_level_accept_task_model(LEVEL l, TASK_MODEL *m)
290
{
291
  if (m->pclass == SOFT_PCLASS || m->pclass == (SOFT_PCLASS | l)) {
292
    SOFT_TASK_MODEL *s = (SOFT_TASK_MODEL *)m;
293
    if (s->met && s->period)
294
      return 0;
295
  }
296
 
297
  return -1;
298
}
299
 
300
static int CBS_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
301
{
302
  return -1;
303
}
304
 
305
static char *onoff(int i)
306
{
307
  if (i)
308
    return "On ";
309
  else
310
    return "Off";
311
}
312
 
313
static void CBS_level_status(LEVEL l)
314
{
315
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
316
  PID p;
317
 
318
  kern_printf("On-line guarantee : %s\n",
319
            onoff(lev->flags & CBS_ENABLE_GUARANTEE));
320
  kern_printf("Used Bandwidth    : %u/%u\n",
321
            lev->U, MAX_BANDWIDTH);
322
 
323
  for (p=0; p<MAX_PROC; p++)
324
    if (proc_table[p].task_level == l && proc_table[p].status != FREE )
325
      kern_printf("Pid: %2d Name: %10s Period: %9ld Dline: %9ld.%6ld Stat: %s\n",
326
                p,
327
                proc_table[p].name,
328
                lev->period[p],
329
                lev->cbs_dline[p].tv_sec,
330
                lev->cbs_dline[p].tv_nsec/1000,
331
                CBS_status_to_a(proc_table[p].status));
332
}
333
 
334
static PID CBS_level_scheduler(LEVEL l)
335
{
336
  /* the CBS don't schedule anything...
337
     it's an EDF level or similar that do it! */
338
  return NIL;
339
}
340
 
341
/* The on-line guarantee is enabled only if the appropriate flag is set... */
342
static int CBS_level_guarantee(LEVEL l, bandwidth_t *freebandwidth)
343
{
344
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
345
 
346
  if (lev->flags & CBS_FAILED_GUARANTEE) {
347
    *freebandwidth = 0;
348
    return 0;
349
  }
350
  else
351
    if (*freebandwidth >= lev->U) {
352
      *freebandwidth -= lev->U;
353
      return 1;
354
    }
355
    else
356
      return 0;
357
}
358
 
359
static int CBS_task_create(LEVEL l, PID p, TASK_MODEL *m)
360
{
361
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
362
 
363
  /* if the CBS_task_create is called, then the pclass must be a
364
     valid pclass. */
365
  SOFT_TASK_MODEL *soft = (SOFT_TASK_MODEL *)m;
366
 
367
  /* Enable wcet check */
368
  proc_table[p].avail_time = soft->met;
369
  proc_table[p].wcet       = soft->met;
370
  proc_table[p].control   |= CONTROL_CAP;
371
 
372
  lev->nact[p] = 0;
373
  lev->period[p] = soft->period;
374
  NULL_TIMESPEC(&lev->cbs_dline[p]);
375
 
376
  if (soft->periodicity == APERIODIC)
377
    lev->flag[p] = CBS_APERIODIC;
378
  else
379
    lev->flag[p] = 0;
380
 
381
  if (soft->arrivals == SAVE_ARRIVALS)
382
    lev->flag[p] |= CBS_SAVE_ARRIVALS;
383
 
384
  /* update the bandwidth... */
385
  if (lev->flags & CBS_ENABLE_GUARANTEE) {
386
    bandwidth_t b;
387
    b = (MAX_BANDWIDTH / soft->period) * soft->met;
388
 
389
    /* really update lev->U, checking an overflow... */
390
    if (MAX_BANDWIDTH - lev->U > b)
391
      lev->U += b;
392
    else
393
      /* The task can NOT be guaranteed (U>MAX_BANDWIDTH)...
394
         (see EDF.c) */
395
      lev->flags |= CBS_FAILED_GUARANTEE;
396
  }
397
 
398
 
399
  return 0; /* OK, also if the task cannot be guaranteed... */
400
}
401
 
402
static void CBS_task_detach(LEVEL l, PID p)
403
{
404
  /* the CBS level doesn't introduce any dinamic allocated new field.
405
     we have only to reset the NO_GUARANTEE FIELD and decrement the allocated
406
     bandwidth */
407
 
408
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
409
 
410
  if (lev->flags & CBS_FAILED_GUARANTEE)
411
    lev->flags &= ~CBS_FAILED_GUARANTEE;
412
  else
413
    lev->U -= (MAX_BANDWIDTH / lev->period[p]) * proc_table[p].wcet;
414
}
415
 
416
static int CBS_task_eligible(LEVEL l, PID p)
417
{
418
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
419
  JOB_TASK_MODEL job;
420
 
421
  /* we have to check if the deadline and the wcet are correct...
422
     if the CBS level schedules in background with respect to others
423
     levels, there can be the case in witch a task is scheduled by
424
     schedule_time > CBS_deadline; in this case (not covered in the
425
     article because if there is only the standard scheduling policy
426
     this never apply) we reassign the deadline */
427
 
428
  if ( TIMESPEC_A_LT_B(&lev->cbs_dline[p], &schedule_time) ) {
429
    /* we kill the current activation */
430
    level_table[ lev->scheduling_level ]->
431
      guest_end(lev->scheduling_level, p);
432
 
433
    /* we modify the deadline ... */
434
    TIMESPEC_ASSIGN(&lev->cbs_dline[p], &schedule_time);
435
    ADDUSEC2TIMESPEC(lev->period[p], &lev->cbs_dline[p]);
436
 
437
    /* and the capacity */
438
    proc_table[p].avail_time = proc_table[p].wcet;
439
 
440
    /* and, finally, we reinsert the task in the master level */
441
    job_task_default_model(job, lev->cbs_dline[p]);
442
    job_task_def_noexc(job);
443
    level_table[ lev->scheduling_level ]->
444
      guest_create(lev->scheduling_level, p, (TASK_MODEL *)&job);
445
    level_table[ lev->scheduling_level ]->
446
      guest_activate(lev->scheduling_level, p);
447
 
448
    return -1;
449
  }
450
 
451
  return 0;
452
}
453
 
454
#ifdef __TEST1__
455
extern int testactive;
456
extern struct timespec s_stime[];
457
extern TIME s_curr[];
458
extern TIME s_PID[];
459
extern int useds;
460
#endif
461
 
462
static void CBS_task_dispatch(LEVEL l, PID p, int nostop)
463
{
464
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
465
  level_table[ lev->scheduling_level ]->
466
    guest_dispatch(lev->scheduling_level,p,nostop);
467
 
468
  #ifdef __TEST1__
469
  if (testactive)
470
  {
471
    TIMESPEC_ASSIGN(&s_stime[useds], &schedule_time);
472
    s_curr[useds] = proc_table[p].avail_time;
473
    s_PID[useds]  = p;
474
    useds++;
475
  }
476
  #endif
477
}
478
 
479
static void CBS_task_epilogue(LEVEL l, PID p)
480
{
481
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
482
  JOB_TASK_MODEL job;
483
 
484
  /* check if the wcet is finished... */
485
  if ( proc_table[p].avail_time <= 0) {
486
    /* we kill the current activation */
487
    level_table[ lev->scheduling_level ]->
488
      guest_end(lev->scheduling_level, p);
489
 
490
    /* we modify the deadline according to rule 4 ... */
491
    CBS_avail_time_check(lev, p);
492
 
493
    /* and, finally, we reinsert the task in the master level */
494
    job_task_default_model(job, lev->cbs_dline[p]);
495
    job_task_def_noexc(job);
496
    level_table[ lev->scheduling_level ]->
497
      guest_create(lev->scheduling_level, p, (TASK_MODEL *)&job);
498
    level_table[ lev->scheduling_level ]->
499
      guest_activate(lev->scheduling_level, p);
500
//    kern_printf("epil : dl %d per %d p %d |\n",
501
//              lev->cbs_dline[p].tv_nsec/1000,lev->period[p],p);
502
 
503
  }
504
  else
505
    /* the task has been preempted. it returns into the ready queue by
506
       calling the guest_epilogue... */
507
    level_table[ lev->scheduling_level ]->
508
      guest_epilogue(lev->scheduling_level,p);
509
}
510
 
511
static void CBS_task_activate(LEVEL l, PID p)
512
{
513
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
514
 
515
  /* save activation (only if needed... */
516
  if (proc_table[p].status != SLEEP) {
517
    if (lev->flag[p] & CBS_SAVE_ARRIVALS)
518
      lev->nact[p]++;
519
    return;
520
  }
521
 
522
  ll_gettime(TIME_EXACT, &proc_table[p].request_time);
523
 
524
  CBS_activation(lev, p, &proc_table[p].request_time);
525
 
526
  /* Set the reactivation timer */
527
  if (!(lev->flag[p] & CBS_APERIODIC))
528
  {
529
    /* we cannot use the deadline computed by CBS_activation because
530
       the deadline may be != from actual_time + period
531
       (if we call the task_activate after a task_sleep, and the
532
       deadline was postponed a lot...) */
533
    TIMESPEC_ASSIGN(&lev->reactivation_time[p], &proc_table[p].request_time);
534
    ADDUSEC2TIMESPEC(lev->period[p], &lev->reactivation_time[p]);
535
//    TIMESPEC_ASSIGN(&lev->reactivation_time[p], &lev->cbs_dline[p]);
536
    lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
537
                                                 CBS_timer_reactivate,
538
                                                 (void *)p);
539
    #ifdef CBS_COUNTER
540
      if (p==5) cbs_counter2++;
541
    #endif
542
  }
543
//  kern_printf("act : %d %d |",lev->cbs_dline[p].tv_nsec/1000,p);
544
}
545
 
546
static void CBS_task_insert(LEVEL l, PID p)
547
{
548
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
549
  struct timespec acttime;
550
 
551
  ll_gettime(TIME_EXACT, &acttime);
552
 
553
  CBS_activation(lev,p,&acttime);
554
}
555
 
556
static void CBS_task_extract(LEVEL l, PID p)
557
{
558
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
559
 
560
  /* check if the wcet is finished... */
561
  CBS_avail_time_check(lev, p);
562
 
563
  level_table[ lev->scheduling_level ]->
564
    guest_end(lev->scheduling_level,p);
565
}
566
 
567
static void CBS_task_endcycle(LEVEL l, PID p)
568
{
569
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
570
 
571
  /* check if the wcet is finished... */
572
  CBS_avail_time_check(lev, p);
573
 
574
  if (lev->nact[p]) {
575
    /* continue!!!! */
576
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
577
    lev->nact[p]--;
578
    level_table[ lev->scheduling_level ]->
579
      guest_epilogue(lev->scheduling_level,p);
580
  }
581
  else {
582
    level_table[ lev->scheduling_level ]->
583
      guest_end(lev->scheduling_level,p);
584
 
585
    if (lev->flag[p] & CBS_APERIODIC)
586
      proc_table[p].status = SLEEP;
587
    else  /* the task is soft_periodic */
588
      proc_table[p].status = CBS_IDLE;
589
 
590
  }
591
}
592
 
593
static void CBS_task_end(LEVEL l, PID p)
594
{
595
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
596
 
597
  /* check if the wcet is finished... */
598
  CBS_avail_time_check(lev, p);
599
 
600
  level_table[ lev->scheduling_level ]->
601
    guest_end(lev->scheduling_level,p);
602
 
603
  /* we delete the reactivation timer */
604
  if (!(lev->flag[p] & CBS_APERIODIC)) {
605
    event_delete(lev->reactivation_timer[p]);
606
    lev->reactivation_timer[p] = -1;
607
  }
608
 
609
  /* Finally, we post the zombie event. when the end period is reached,
610
     the task descriptor and banwidth are freed */
611
  proc_table[p].status = CBS_ZOMBIE;
612
  lev->reactivation_timer[p] = kern_event_post(&lev->cbs_dline[p],
613
                                               CBS_timer_zombie,
614
                                               (void *)p);
615
}
616
 
617
static void CBS_task_sleep(LEVEL l, PID p)
618
{
619
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
620
 
621
  /* check if the wcet is finished... */
622
  CBS_avail_time_check(lev, p);
623
 
624
  /* a task activation is finished, but we are using a JOB_TASK_MODEL
625
     that implements a single activation, so we have to call
626
     the guest_end, that representsa single activation... */
627
  level_table[ lev->scheduling_level ]->
628
    guest_end(lev->scheduling_level,p);
629
 
630
  /* we delete the reactivation timer */
631
  if (!(lev->flag[p] & CBS_APERIODIC)) {
632
    event_delete(lev->reactivation_timer[p]);
633
    lev->reactivation_timer[p] = -1;
634
  }
635
 
636
  proc_table[p].status = SLEEP;
637
 
638
  /* the sleep forgets pending activations... */
639
  lev->nact[p] = 0;
640
}
641
 
642
static void CBS_task_delay(LEVEL l, PID p, TIME usdelay)
643
{
644
  struct timespec wakeuptime;
645
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
646
 
647
  /* check if the wcet is finished... */
648
  CBS_avail_time_check(lev, p);
649
 
650
  level_table[ lev->scheduling_level ]->
651
    guest_end(lev->scheduling_level,p);
652
 
653
  proc_table[p].status = CBS_DELAY;
654
 
655
  /* we need to delete this event if we kill the task while it is sleeping */
656
  ll_gettime(TIME_EXACT, &wakeuptime);
657
  ADDUSEC2TIMESPEC(usdelay, &wakeuptime);
658
 
659
  /* the timespec_priority field is used to store the time at witch the delay
660
     timer raises */
661
  TIMESPEC_ASSIGN(&proc_table[p].timespec_priority, &wakeuptime);
662
  proc_table[p].delay_timer = kern_event_post(&wakeuptime,
663
                                              CBS_timer_delay,
664
                                              (void *)p);
665
}
666
 
667
 
668
static int CBS_guest_create(LEVEL l, PID p, TASK_MODEL *m)
669
{ kern_raise(XUNVALID_GUEST,exec_shadow); return 0; }
670
 
671
static void CBS_guest_detach(LEVEL l, PID p)
672
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
673
 
674
static void CBS_guest_dispatch(LEVEL l, PID p, int nostop)
675
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
676
 
677
static void CBS_guest_epilogue(LEVEL l, PID p)
678
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
679
 
680
static void CBS_guest_activate(LEVEL l, PID p)
681
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
682
 
683
static void CBS_guest_insert(LEVEL l, PID p)
684
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
685
 
686
static void CBS_guest_extract(LEVEL l, PID p)
687
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
688
 
689
static void CBS_guest_endcycle(LEVEL l, PID p)
690
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
691
 
692
static void CBS_guest_end(LEVEL l, PID p)
693
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
694
 
695
static void CBS_guest_sleep(LEVEL l, PID p)
696
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
697
 
698
static void CBS_guest_delay(LEVEL l, PID p,DWORD tickdelay)
699
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
700
 
701
 
702
 
703
 
704
/* Registration functions */
705
 
706
/*+ Registration function:
707
    int flags                 the init flags ... see CBS.h +*/
708
void CBS_register_level(int flags, LEVEL master)
709
{
710
  LEVEL l;            /* the level that we register */
711
  CBS_level_des *lev;  /* for readableness only */
712
  PID i;              /* a counter */
713
 
714
  printk("CBS_register_level\n");
715
 
716
  /* request an entry in the level_table */
717
  l = level_alloc_descriptor();
718
 
719
  printk("    alloco descrittore %d %d\n",l,(int)sizeof(CBS_level_des));
720
 
721
  /* alloc the space needed for the CBS_level_des */
722
  lev = (CBS_level_des *)kern_alloc(sizeof(CBS_level_des));
723
 
724
  printk("    lev=%d\n",(int)lev);
725
 
726
  /* update the level_table with the new entry */
727
  level_table[l] = (level_des *)lev;
728
 
729
  /* fill the standard descriptor */
730
  strncpy(lev->l.level_name,  CBS_LEVELNAME, MAX_LEVELNAME);
731
  lev->l.level_code               = CBS_LEVEL_CODE;
732
  lev->l.level_version            = CBS_LEVEL_VERSION;
733
 
734
  lev->l.level_accept_task_model  = CBS_level_accept_task_model;
735
  lev->l.level_accept_guest_model = CBS_level_accept_guest_model;
736
  lev->l.level_status             = CBS_level_status;
737
  lev->l.level_scheduler          = CBS_level_scheduler;
738
 
739
  if (flags & CBS_ENABLE_GUARANTEE)
740
    lev->l.level_guarantee        = CBS_level_guarantee;
741
  else
742
    lev->l.level_guarantee        = NULL;
743
 
744
  lev->l.task_create              = CBS_task_create;
745
  lev->l.task_detach              = CBS_task_detach;
746
  lev->l.task_eligible            = CBS_task_eligible;
747
  lev->l.task_dispatch            = CBS_task_dispatch;
748
  lev->l.task_epilogue            = CBS_task_epilogue;
749
  lev->l.task_activate            = CBS_task_activate;
750
  lev->l.task_insert              = CBS_task_insert;
751
  lev->l.task_extract             = CBS_task_extract;
752
  lev->l.task_endcycle            = CBS_task_endcycle;
753
  lev->l.task_end                 = CBS_task_end;
754
  lev->l.task_sleep               = CBS_task_sleep;
755
  lev->l.task_delay               = CBS_task_delay;
756
 
757
  lev->l.guest_create             = CBS_guest_create;
758
  lev->l.guest_detach             = CBS_guest_detach;
759
  lev->l.guest_dispatch           = CBS_guest_dispatch;
760
  lev->l.guest_epilogue           = CBS_guest_epilogue;
761
  lev->l.guest_activate           = CBS_guest_activate;
762
  lev->l.guest_insert             = CBS_guest_insert;
763
  lev->l.guest_extract            = CBS_guest_extract;
764
  lev->l.guest_endcycle           = CBS_guest_endcycle;
765
  lev->l.guest_end                = CBS_guest_end;
766
  lev->l.guest_sleep              = CBS_guest_sleep;
767
  lev->l.guest_delay              = CBS_guest_delay;
768
 
769
  /* fill the CBS descriptor part */
770
  for (i=0; i<MAX_PROC; i++) {
771
     NULL_TIMESPEC(&lev->cbs_dline[i]);
772
     lev->period[i] = 0;
773
     NULL_TIMESPEC(&lev->reactivation_time[i]);
774
     lev->reactivation_timer[i] = -1;
775
     lev->nact[i] = 0;
776
     lev->flag[i] = 0;
777
  }
778
 
779
 
780
  lev->U = 0;
781
 
782
  lev->scheduling_level = master;
783
 
784
  lev->flags = flags & 0x01;
785
}
786
 
787
bandwidth_t CBS_usedbandwidth(LEVEL l)
788
{
789
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
790
  if (lev->l.level_code    == CBS_LEVEL_CODE &&
791
      lev->l.level_version == CBS_LEVEL_VERSION)
792
    return lev->U;
793
  else
794
    return 0;
795
}
796
 
797
int CBS_get_nact(LEVEL l, PID p)
798
{
799
  CBS_level_des *lev = (CBS_level_des *)(level_table[l]);
800
 
801
  return lev->nact[p];
802
}
803