Subversion Repositories shark

Rev

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