Subversion Repositories shark

Rev

Rev 2 | 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: edf2.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 scheduling module EDF (Earliest Deadline First)
31
 
32
 Read edf.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/edf.h>
57
 
58
/*+ Status used in the level +*/
59
#define EDF_READY         MODULE_STATUS_BASE    /*+ - Ready status        +*/
60
#define EDF_DELAY         MODULE_STATUS_BASE+1  /*+ - Delay status        +*/
61
#define EDF_WCET_VIOLATED MODULE_STATUS_BASE+2  /*+ when wcet is finished +*/
62
#define EDF_WAIT          MODULE_STATUS_BASE+3  /*+ to wait the deadline  +*/
63
#define EDF_IDLE          MODULE_STATUS_BASE+4  /*+ to wait the deadline  +*/
64
#define EDF_ZOMBIE        MODULE_STATUS_BASE+5  /*+ to wait the free time +*/
65
 
66
/*+ the level redefinition for the Earliest Deadline First level +*/
67
typedef struct {
68
  level_des l;     /*+ the standard level descriptor          +*/
69
 
70
  TIME period[MAX_PROC]; /*+ The task periods; the deadlines are
71
                       stored in the priority field           +*/
72
  int deadline_timer[MAX_PROC];
73
                   /*+ The task deadline timers               +*/
74
 
75
  int noraiseexc[MAX_PROC];
76
                   /*+ used to manage the JOB_TASK_MODEL      +*/
77
 
78
  QUEUE ready;     /*+ the ready queue                        +*/
79
 
80
  int flags;       /*+ the init flags...                      +*/
81
 
82
  bandwidth_t U;   /*+ the used bandwidth                     +*/
83
 
84
} EDF_level_des;
85
 
86
 
87
static char *EDF_status_to_a(WORD status)
88
{
89
  if (status < MODULE_STATUS_BASE)
90
    return status_to_a(status);
91
 
92
  switch (status) {
93
    case EDF_READY        : return "EDF_Ready";
94
    case EDF_DELAY        : return "EDF_Delay";
95
    case EDF_WCET_VIOLATED: return "EDF_Wcet_Violated";
96
    case EDF_WAIT         : return "EDF_Sporadic_Wait";
97
    case EDF_IDLE         : return "EDF_Idle";
98
    case EDF_ZOMBIE       : return "EDF_Zombie";
99
    default               : return "EDF_Unknown";
100
  }
101
}
102
 
103
static void EDF_timer_deadline(void *par)
104
{
105
  PID p = (PID) par;
106
  EDF_level_des *lev;
107
 
108
 
109
  lev = (EDF_level_des *)level_table[proc_table[p].task_level];
110
 
111
  switch (proc_table[p].status) {
112
    case EDF_ZOMBIE:
113
      /* we finally put the task in the ready queue */
114
      proc_table[p].status = FREE;
115
      q_insertfirst(p,&freedesc);
116
      /* and free the allocated bandwidth */
117
      lev->U -= (MAX_BANDWIDTH/lev->period[p]) * proc_table[p].wcet;
118
      break;
119
 
120
    case EDF_IDLE:
121
      /* similar to EDF_task_activate */
122
      TIMESPEC_ASSIGN(&proc_table[p].request_time,
123
                      &proc_table[p].timespec_priority);
124
      ADDUSEC2TIMESPEC(lev->period[p], &proc_table[p].timespec_priority);
125
      proc_table[p].status = EDF_READY;
126
      q_timespec_insert(p,&lev->ready);
127
      lev->deadline_timer[p] = kern_event_post(&proc_table[p].timespec_priority,
128
                                               EDF_timer_deadline,
129
                                               (void *)p);
130
      //printk("(d%d idle priority set to %d)",p,proc_table[p].priority );
131
      event_need_reschedule();
132
      printk("el%d|",p);
133
      break;
134
 
135
    case EDF_WAIT:
136
      /* Without this, the task cannot be reactivated!!! */
137
      proc_table[p].status = SLEEP;
138
      break;
139
 
140
    default:
141
      /* else, a deadline miss occurred!!! */
142
      kern_raise(XDEADLINE_MISS,p);
143
      kern_printf("avail_time %d\n\n",proc_table[p].avail_time);
144
  }
145
}
146
 
147
/*+ this function is called when a task finish his delay +*/
148
static void EDF_timer_delay(void *par)
149
{
150
  PID p = (PID) par;
151
  EDF_level_des *lev;
152
 
153
  lev = (EDF_level_des *)level_table[proc_table[p].task_level];
154
 
155
  proc_table[p].status = EDF_READY;
156
  q_timespec_insert(p,&lev->ready);
157
 
158
  proc_table[p].delay_timer = NIL;  /* Paranoia */
159
 
160
  event_need_reschedule();
161
}
162
 
163
 
164
static int EDF_level_accept_task_model(LEVEL l, TASK_MODEL *m)
165
{
166
  if (m->pclass == PERIODIC_PCLASS || m->pclass == (PERIODIC_PCLASS | l) ||
167
      m->pclass == SPORADIC_PCLASS || m->pclass == (SPORADIC_PCLASS | l))
168
    return 0;
169
  else
170
    return -1;
171
}
172
 
173
static int EDF_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
174
{
175
  if (m->pclass == JOB_PCLASS || m->pclass == (JOB_PCLASS | l) )
176
    return 0;
177
  else
178
    return -1;
179
}
180
 
181
 
182
static char *onoff(int i)
183
{
184
  if (i)
185
    return "On ";
186
  else
187
    return "Off";
188
}
189
 
190
static void EDF_level_status(LEVEL l)
191
{
192
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
193
  PID p = lev->ready;
194
 
195
  kern_printf("Wcet     Check    : %s\n",
196
            onoff(lev->flags & EDF_ENABLE_WCET_CHECK));
197
  kern_printf("On-line guarantee : %s\n",
198
            onoff(lev->flags & EDF_ENABLE_GUARANTEE));
199
  kern_printf("Used Bandwidth    : %u/%u\n",
200
            lev->U, MAX_BANDWIDTH);
201
 
202
  while (p != NIL) {
203
    if ((proc_table[p].pclass & 0xFF00) == JOB_PCLASS)
204
      kern_printf("Pid: %2d (GUEST)\n", p);
205
    else
206
      kern_printf("Pid: %2d Name: %10s %s: %9d Dline: %9d.%6d Stat: %s\n",
207
              p,
208
              proc_table[p].name,
209
              (proc_table[p].pclass == PERIODIC_PCLASS) ? "Period  " : "MinITime",
210
              lev->period[p],
211
              proc_table[p].timespec_priority.tv_sec,
212
              proc_table[p].timespec_priority.tv_nsec/1000,
213
              EDF_status_to_a(proc_table[p].status));
214
    p = proc_table[p].next;
215
  }
216
 
217
  for (p=0; p<MAX_PROC; p++)
218
    if (proc_table[p].task_level == l && proc_table[p].status != EDF_READY
219
        && proc_table[p].status != FREE )
220
      kern_printf("Pid: %2d Name: %10s %s: %9d Dline: %9d.%6d Stat: %s\n",
221
                p,
222
                proc_table[p].name,
223
                (proc_table[p].pclass == PERIODIC_PCLASS) ? "Period  " : "MinITime",
224
                lev->period[p],
225
                proc_table[p].timespec_priority.tv_sec,
226
                proc_table[p].timespec_priority.tv_nsec/1000,
227
                EDF_status_to_a(proc_table[p].status));
228
}
229
 
230
/* The scheduler only gets the first task in the queue */
231
static PID EDF_level_scheduler(LEVEL l)
232
{
233
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
234
 
235
/*  {  // print 4 dbg the ready queue
236
    PID p= lev->ready;
237
    kern_printf("(s");
238
    while (p != NIL) {
239
      kern_printf("%d ",p);
240
      p = proc_table[p].next;
241
    }
242
    kern_printf(") ");
243
  }
244
  */
245
  return (PID)lev->ready;
246
}
247
 
248
/* The on-line guarantee is enabled only if the appropriate flag is set... */
249
static int EDF_level_guarantee(LEVEL l, bandwidth_t *freebandwidth)
250
{
251
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
252
 
253
  if (lev->flags & EDF_FAILED_GUARANTEE) {
254
    *freebandwidth = 0;
255
    return 0;
256
  }
257
  else
258
    if (*freebandwidth >= lev->U) {
259
      *freebandwidth -= lev->U;
260
      return 1;
261
    }
262
    else
263
      return 0;
264
 
265
}
266
 
267
static int EDF_task_create(LEVEL l, PID p, TASK_MODEL *m)
268
{
269
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
270
 
271
  /* if the EDF_task_create is called, then the pclass must be a
272
     valid pclass.
273
     Warning!! PERIODIC_PCLASS and SPORADIC_PCLASS have the same fields
274
     so the code is the same...
275
     ... In fact, if the sporadic model will change in the future,
276
     we have to check this code!!!... */
277
 
278
  /* PERIODIC_TASK_MODEL handling; SPORADIC_TASK_MODEL works with the same
279
     code... */
280
  PERIODIC_TASK_MODEL *per = (PERIODIC_TASK_MODEL *)m;
281
 
282
  lev->period[p] = per->period;
283
 
284
  lev->noraiseexc[p] = 0;
285
  lev->deadline_timer[p] = -1;
286
 
287
  /* Enable wcet check */
288
  if (lev->flags & EDF_ENABLE_WCET_CHECK) {
289
    proc_table[p].avail_time = per->wcet;
290
    proc_table[p].wcet       = per->wcet;
291
    proc_table[p].control |= CONTROL_CAP;
292
  }
293
 
294
  /* update the bandwidth... */
295
  if (lev->flags & EDF_ENABLE_GUARANTEE) {
296
    bandwidth_t b;
297
    b = (MAX_BANDWIDTH / per->period) * per->wcet;
298
 
299
    /* really update lev->U, checking an overflow... */
300
    if (MAX_BANDWIDTH - lev->U > b)
301
      lev->U += b;
302
    else
303
      /* The task can NOT be guaranteed (U>MAX_BANDWIDTH)...
304
         in this case, we don't raise an exception... in fact, after the
305
         EDF_task_create the task_create will call level_guarantee that return
306
         -1... return -1 in EDF_task_create isn't correct, because:
307
           . generally, the guarantee must be done when also the resources
308
             are registered
309
           . returning -1 will cause the task_create to return with an errno
310
             ETASK_CREATE instead of ENO_GUARANTEE!!!
311
 
312
         Why I use the flag??? because if the lev->U overflows, if i.e. I set
313
         it to MAX_BANDWIDTH, I lose the correct allocated bandwidth...
314
      */
315
      lev->flags |= EDF_FAILED_GUARANTEE;
316
  }
317
 
318
  return 0; /* OK, also if the task cannot be guaranteed... */
319
}
320
 
321
static void EDF_task_detach(LEVEL l, PID p)
322
{
323
  /* the EDF level doesn't introduce any dinamic allocated new field.
324
     we have only to reset the NO_GUARANTEE FIELD and decrement the allocated
325
     bandwidth */
326
 
327
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
328
 
329
  if (lev->flags & EDF_FAILED_GUARANTEE)
330
    lev->flags &= ~EDF_FAILED_GUARANTEE;
331
  else
332
    lev->U -= (MAX_BANDWIDTH / lev->period[p]) * proc_table[p].wcet;
333
}
334
 
335
static int EDF_task_eligible(LEVEL l, PID p)
336
{
337
  return 0; /* if the task p is chosen, it is always eligible */
338
}
339
 
340
#ifdef __TEST1__
341
extern int testactive;
342
extern struct timespec s_stime[];
343
extern TIME s_curr[];
344
extern TIME s_PID[];
345
extern int useds;
346
#endif
347
 
348
static void EDF_task_dispatch(LEVEL l, PID p, int nostop)
349
{
350
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
351
 
352
//  kern_printf("(disp %d)",p);
353
 
354
  /* the task state is set EXE by the scheduler()
355
     we extract the task from the ready queue
356
     NB: we can't assume that p is the first task in the queue!!! */
357
  q_extract(p, &lev->ready);
358
 
359
  #ifdef __TEST1__
360
  if (testactive)
361
  {
362
    TIMESPEC_ASSIGN(&s_stime[useds], &schedule_time);
363
    s_curr[useds] = proc_table[p].avail_time;
364
    s_PID[useds]  = p;
365
    useds++;
366
  }
367
  #endif
368
}
369
 
370
static void EDF_task_epilogue(LEVEL l, PID p)
371
{
372
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
373
 
374
//  kern_printf("(epil %d)",p);
375
 
376
  /* check if the wcet is finished... */
377
  if ((lev->flags & EDF_ENABLE_WCET_CHECK) && proc_table[p].avail_time <= 0) {
378
    /* if it is, raise a XWCET_VIOLATION exception */
379
    kern_raise(XWCET_VIOLATION,p);
380
    proc_table[p].status = EDF_WCET_VIOLATED;
381
  }
382
  else {
383
    /* the task has been preempted. it returns into the ready queue... */
384
    q_timespec_insert(p,&lev->ready);
385
    proc_table[p].status = EDF_READY;
386
  }
387
}
388
 
389
static void EDF_task_activate(LEVEL l, PID p)
390
{
391
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
392
 
393
  if (proc_table[p].status == EDF_WAIT) {
394
    kern_raise(XACTIVATION,p);
395
    return;
396
  }
397
 
398
  /* Test if we are trying to activate a non sleeping task    */
399
  /* Ignore this; the task is already active                  */
400
  if (proc_table[p].status != SLEEP &&
401
      proc_table[p].status != EDF_WCET_VIOLATED)
402
    return;
403
 
404
 
405
  /* see also EDF_timer_deadline */
406
  ll_gettime(TIME_EXACT, &proc_table[p].request_time);
407
 
408
  TIMESPEC_ASSIGN(&proc_table[p].timespec_priority,
409
                  &proc_table[p].request_time);
410
  ADDUSEC2TIMESPEC(lev->period[p], &proc_table[p].timespec_priority);
411
 
412
  /* Insert task in the correct position */
413
  proc_table[p].status = EDF_READY;
414
  q_timespec_insert(p,&lev->ready);
415
 
416
  /* Set the deadline timer */
417
  lev->deadline_timer[p] = kern_event_post(&proc_table[p].timespec_priority,
418
                                           EDF_timer_deadline,
419
                                           (void *)p);
420
}
421
 
422
static void EDF_task_insert(LEVEL l, PID p)
423
{
424
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
425
 
426
  /* Similar to EDF_task_activate, but we don't check in what state
427
     the task is and we don't set the request_time*/
428
 
429
  /* Insert task in the coEDFect position */
430
  proc_table[p].status = EDF_READY;
431
  q_timespec_insert(p,&lev->ready);
432
}
433
 
434
static void EDF_task_extract(LEVEL l, PID p)
435
{
436
  /* Extract the running task from the level
437
     . we have already extract it from the ready queue at the dispatch time.
438
     . the capacity event have to be removed by the generic kernel
439
     . the wcet don't need modification...
440
     . the state of the task is set by the calling function
441
     . the deadline must remain...
442
 
443
     So, we do nothing!!!
444
  */
445
}
446
 
447
static void EDF_task_endcycle(LEVEL l, PID p)
448
{
449
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
450
 
451
  /* the task has terminated his job before it consume the wcet. All OK! */
452
  if (proc_table[p].pclass = PERIODIC_PCLASS)
453
    proc_table[p].status = EDF_IDLE;
454
  else /* pclass = sporadic_pclass */
455
    proc_table[p].status = EDF_WAIT;
456
 
457
  /* we reset the capacity counters... */
458
  if (lev->flags & EDF_ENABLE_WCET_CHECK)
459
    proc_table[p].avail_time = proc_table[p].wcet;
460
 
461
  /* when the deadline timer fire, it recognize the situation and set
462
     correctly all the stuffs (like reactivation, request_time, etc... ) */
463
}
464
 
465
static void EDF_task_end(LEVEL l, PID p)
466
{
467
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
468
 
469
  if (proc_table[p].status == EDF_READY)
470
    q_extract(p, &lev->ready);
471
  else if (proc_table[p].status == EDF_DELAY) {
472
    event_delete(proc_table[p].delay_timer);
473
    proc_table[p].delay_timer = NIL;    /* paranoia */
474
  }
475
 
476
  proc_table[p].status = EDF_ZOMBIE;
477
 
478
  /* When the deadline timer fire, it put the task descriptor in
479
     the free queue, and free the allocated bandwidth... */
480
}
481
 
482
static void EDF_task_sleep(LEVEL l, PID p)
483
{
484
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
485
 
486
  /* the task has terminated his job before it consume the wcet. All OK! */
487
  proc_table[p].status = EDF_WAIT;
488
 
489
  /* we reset the capacity counters... */
490
  if (lev->flags & EDF_ENABLE_WCET_CHECK)
491
    proc_table[p].avail_time = proc_table[p].wcet;
492
 
493
  /* when the deadline timer fire, it recognize the situation and set
494
     correctly the task state to sleep... */
495
}
496
 
497
static void EDF_task_delay(LEVEL l, PID p, TIME usdelay)
498
{
499
  struct timespec wakeuptime;
500
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
501
 
502
  /* equal to EDF_task_endcycle */
503
  proc_table[p].status = EDF_DELAY;
504
 
505
  /* we need to delete this event if we kill the task while it is sleeping */
506
  ll_gettime(TIME_EXACT, &wakeuptime);
507
  ADDUSEC2TIMESPEC(usdelay, &wakeuptime);
508
  proc_table[p].delay_timer = kern_event_post(&wakeuptime,
509
                                              EDF_timer_delay,
510
                                              (void *)p);
511
}
512
 
513
/* Guest Functions
514
   These functions manages a JOB_TASK_MODEL, that is used to put
515
   a guest task in the EDF ready queue. */
516
 
517
 
518
 
519
static int EDF_guest_create(LEVEL l, PID p, TASK_MODEL *m)
520
{
521
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
522
 
523
  /* if the EDF_guest_create is called, then the pclass must be a
524
     valid pclass. */
525
 
526
  JOB_TASK_MODEL *job = (JOB_TASK_MODEL *)m;
527
 
528
  proc_table[p].guest_pclass = m->pclass;
529
 
530
  TIMESPEC_ASSIGN(&proc_table[p].timespec_priority, &job->deadline);
531
 
532
  lev->deadline_timer[p] = -1;
533
  lev->noraiseexc[p] = job->noraiseexc;
534
 
535
  /* there is no bandwidth guarantee at this level, it is performed
536
     by the level that inserts guest tasks... */
537
 
538
  return 0; /* OK, also if the task cannot be guaranteed... */
539
}
540
 
541
static void EDF_guest_detach(LEVEL l, PID p)
542
{
543
  /* the EDF level doesn't introduce any dinamic allocated new field.
544
     No guarantee is performed on guest tasks... so we don't have to reset
545
     the NO_GUARANTEE FIELD */
546
}
547
 
548
static void EDF_guest_dispatch(LEVEL l, PID p, int nostop)
549
{
550
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
551
 
552
  /* the task state is set to EXE by the scheduler()
553
     we extract the task from the ready queue
554
     NB: we can't assume that p is the first task in the queue!!! */
555
  q_extract(p, &lev->ready);
556
}
557
 
558
static void EDF_guest_epilogue(LEVEL l, PID p)
559
{
560
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
561
 
562
  /* the task has been preempted. it returns into the ready queue... */
563
  q_timespec_insert(p,&lev->ready);
564
  proc_table[p].status = EDF_READY;
565
}
566
 
567
static void EDF_guest_activate(LEVEL l, PID p)
568
{
569
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
570
 
571
  /* Insert task in the correct position */
572
  q_timespec_insert(p,&lev->ready);
573
  proc_table[p].status = EDF_READY;
574
 
575
  /* Set the deadline timer */
576
  if (!lev->noraiseexc[p])
577
    lev->deadline_timer[p] = kern_event_post(&proc_table[p].timespec_priority,
578
                                             EDF_timer_deadline,
579
                                             (void *)p);
580
 
581
}
582
 
583
static void EDF_guest_insert(LEVEL l, PID p)
584
{
585
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
586
 
587
  /* Insert task in the correct position */
588
  q_timespec_insert(p,&lev->ready);
589
  proc_table[p].status = EDF_READY;
590
}
591
 
592
static void EDF_guest_extract(LEVEL l, PID p)
593
{
594
  /* Extract the running task from the level
595
     . we have already extract it from the ready queue at the dispatch time.
596
     . the state of the task is set by the calling function
597
     . the deadline must remain...
598
 
599
     So, we do nothing!!!
600
  */
601
}
602
 
603
static void EDF_guest_endcycle(LEVEL l, PID p)
604
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
605
 
606
static void EDF_guest_end(LEVEL l, PID p)
607
{
608
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
609
 
610
  //kern_printf("EDF_guest_end: dline timer %d\n",lev->deadline_timer[p]);
611
  if (proc_table[p].status == EDF_READY)
612
    q_extract(p, &lev->ready);
613
  else if (proc_table[p].status == EDF_DELAY) {
614
    event_delete(proc_table[p].delay_timer);
615
    proc_table[p].delay_timer = NIL;    /* paranoia */
616
  }
617
 
618
  /* we remove the deadline timer, because the slice is finished */
619
  if (lev->deadline_timer[p] != NIL) {
620
    event_delete(lev->deadline_timer[p]);
621
    lev->deadline_timer[p] = NIL;
622
  }
623
 
624
}
625
 
626
static void EDF_guest_sleep(LEVEL l, PID p)
627
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
628
 
629
static void EDF_guest_delay(LEVEL l, PID p, TIME usdelay)
630
{
631
  struct timespec wakeuptime;
632
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
633
 
634
  /* equal to EDF_task_endcycle */
635
  proc_table[p].status = EDF_DELAY;
636
 
637
  /* we need to delete this event if we kill the task while it is sleeping */
638
  ll_gettime(TIME_EXACT, &wakeuptime);
639
  ADDUSEC2TIMESPEC(usdelay, &wakeuptime);
640
  proc_table[p].delay_timer = kern_event_post(&wakeuptime,
641
                                              EDF_timer_delay,
642
                                              (void *)p);
643
}
644
 
645
 
646
 
647
 
648
/* Registration functions */
649
 
650
/*+ Registration function:
651
    int flags                 the init flags ... see edf.h +*/
652
void EDF_register_level(int flags)
653
{
654
  LEVEL l;            /* the level that we register */
655
  EDF_level_des *lev;  /* for readableness only */
656
  PID i;              /* a counter */
657
 
658
  printk("EDF_register_level\n");
659
 
660
  /* request an entry in the level_table */
661
  l = level_alloc_descriptor();
662
 
663
  printk("    alloco descrittore %d %d\n",l,sizeof(EDF_level_des));
664
 
665
  /* alloc the space needed for the EDF_level_des */
666
  lev = (EDF_level_des *)kern_alloc(sizeof(EDF_level_des));
667
 
668
  printk("    lev=%d\n",(int)lev);
669
 
670
  /* update the level_table with the new entry */
671
  level_table[l] = (level_des *)lev;
672
 
673
  /* fill the standard descriptor */
674
  strncpy(lev->l.level_name,  EDF_LEVELNAME, MAX_LEVELNAME);
675
  lev->l.level_code               = EDF_LEVEL_CODE;
676
  lev->l.level_version            = EDF_LEVEL_VERSION;
677
 
678
  lev->l.level_accept_task_model  = EDF_level_accept_task_model;
679
  lev->l.level_accept_guest_model = EDF_level_accept_guest_model;
680
  lev->l.level_status             = EDF_level_status;
681
  lev->l.level_scheduler          = EDF_level_scheduler;
682
 
683
  if (flags & EDF_ENABLE_GUARANTEE)
684
    lev->l.level_guarantee        = EDF_level_guarantee;
685
  else
686
    lev->l.level_guarantee        = NULL;
687
 
688
  lev->l.task_create              = EDF_task_create;
689
  lev->l.task_detach              = EDF_task_detach;
690
  lev->l.task_eligible            = EDF_task_eligible;
691
  lev->l.task_dispatch            = EDF_task_dispatch;
692
  lev->l.task_epilogue            = EDF_task_epilogue;
693
  lev->l.task_activate            = EDF_task_activate;
694
  lev->l.task_insert              = EDF_task_insert;
695
  lev->l.task_extract             = EDF_task_extract;
696
  lev->l.task_endcycle            = EDF_task_endcycle;
697
  lev->l.task_end                 = EDF_task_end;
698
  lev->l.task_sleep               = EDF_task_sleep;
699
  lev->l.task_delay               = EDF_task_delay;
700
 
701
  lev->l.guest_create             = EDF_guest_create;
702
  lev->l.guest_detach             = EDF_guest_detach;
703
  lev->l.guest_dispatch           = EDF_guest_dispatch;
704
  lev->l.guest_epilogue           = EDF_guest_epilogue;
705
  lev->l.guest_activate           = EDF_guest_activate;
706
  lev->l.guest_insert             = EDF_guest_insert;
707
  lev->l.guest_extract            = EDF_guest_extract;
708
  lev->l.guest_endcycle           = EDF_guest_endcycle;
709
  lev->l.guest_end                = EDF_guest_end;
710
  lev->l.guest_sleep              = EDF_guest_sleep;
711
  lev->l.guest_delay              = EDF_guest_delay;
712
 
713
  /* fill the EDF descriptor part */
714
  for(i=0; i<MAX_PROC; i++) {
715
    lev->period[i]         = 0;
716
    lev->deadline_timer[i] = -1;
717
  }
718
 
719
  lev->ready = NIL;
720
  lev->flags = flags & 0x07;
721
  lev->U     = 0;
722
}
723
 
724
bandwidth_t EDF_usedbandwidth(LEVEL l)
725
{
726
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
727
  if (lev->l.level_code    == EDF_LEVEL_CODE &&
728
      lev->l.level_version == EDF_LEVEL_VERSION)
729
    return lev->U;
730
  else
731
    return 0;
732
}
733