Subversion Repositories shark

Rev

Rev 502 | 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
 ------------
657 anton 23
 CVS :        $Id: edf.c,v 1.14 2004-05-17 15:03:51 anton Exp $
2 pj 24
 
25
 File:        $File$
657 anton 26
 Revision:    $Revision: 1.14 $
27
 Last update: $Date: 2004-05-17 15:03:51 $
2 pj 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
/*
38 pj 37
 * Copyright (C) 2000,2002 Paolo Gai
2 pj 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>
353 giacomo 63
#include <tracer.h>
64
 
240 giacomo 65
//#define EDF_DEBUG
38 pj 66
#define edf_printf kern_printf
2 pj 67
 
657 anton 68
#ifdef EDF_DEBUG
69
char *pnow() {
70
  static char buf[40];
71
  struct timespec t;
72
  sys_gettime(&t);
73
  sprintf(buf, "%ld.%06ld", t.tv_sec, t.tv_nsec/1000);
74
  return buf;
75
}
76
char *ptime1(struct timespec *t) {
77
  static char buf[40];
78
  sprintf(buf, "%ld.%06ld", t->tv_sec, t->tv_nsec/1000);
79
  return buf;
80
}
81
char *ptime2(struct timespec *t) {
82
  static char buf[40];
83
  sprintf(buf, "%ld.%06ld", t->tv_sec, t->tv_nsec/1000);
84
  return buf;
85
}
86
#endif
2 pj 87
 
657 anton 88
/* statuses used in the level */
89
#define EDF_READY      MODULE_STATUS_BASE    /* ready */
90
#define EDF_IDLE       MODULE_STATUS_BASE+1  /* idle, waiting for offset/eop */
91
#define EDF_WAIT       MODULE_STATUS_BASE+2  /* to sleep, waiting for eop */
92
#define EDF_ZOMBIE     MODULE_STATUS_BASE+3  /* zombie, waiting for eop */
2 pj 93
 
657 anton 94
/* task flags */
95
#define EDF_FLAG_SPORADIC    1   /* the task is sporadic */
96
#define EDF_FLAG_SPOR_LATE   2   /* sporadic task with period overrun */ 
2 pj 97
 
98
 
657 anton 99
/* the level redefinition for the Earliest Deadline First level      */
100
typedef struct {
101
  level_des l;                 /* standard level descriptor          */
102
  IQUEUE ready;                /* the ready queue                    */
103
  int flags;                   /* level flags                        */
104
  bandwidth_t U;               /* used bandwidth                     */
2 pj 105
 
657 anton 106
  int taskflags[MAX_PROC];     /* task flags                         */
107
  TIME period[MAX_PROC];       /* task period                        */
108
  TIME rdeadline[MAX_PROC];    /* task relative deadlines            */
109
  TIME offset[MAX_PROC];       /* task release offsets               */
110
  struct timespec release[MAX_PROC];   /* release time of the task   */
111
  struct timespec adeadline[MAX_PROC]; /* latest assigned deadline
112
       (needed to correctly assign deadlines to queued activations)  */
113
  int dl_timer[MAX_PROC];      /* deadline overrun timer             */
114
  int eop_timer[MAX_PROC];     /* end of period timer                */
115
  int dl_miss[MAX_PROC];       /* deadline miss counter              */
116
  int wcet_miss[MAX_PROC];     /* WCET miss counter                  */
117
  int nact[MAX_PROC];          /* number of pending periodic jobs    */
118
  int nskip[MAX_PROC];         /* number of skipped sporadic jobs    */
119
} EDF_level_des;
2 pj 120
 
121
 
657 anton 122
static void EDF_timer_endperiod(void *par);
2 pj 123
 
124
 
657 anton 125
/* This function is called when a task misses its deadline */
2 pj 126
 
127
static void EDF_timer_deadline(void *par)
128
{
129
  PID p = (PID) par;
130
  EDF_level_des *lev;
657 anton 131
  lev = (EDF_level_des *)level_table[proc_table[p].task_level];
132
 
133
  TRACER_LOGEVENT(FTrace_EVT_task_deadline_miss,(unsigned short int)proc_table[p].context,0);
2 pj 134
 
657 anton 135
  if (lev->flags & EDF_ENABLE_DL_EXCEPTION) {
136
    kern_raise(XDEADLINE_MISS,p);
137
  } else {
138
    lev->dl_miss[p]++;
139
  }
140
}
141
 
142
 
143
/* Release (or queue) task, post deadline and endperiod timers.
144
   The release time is stored in lev->release[p]. */
145
 
146
static void EDF_intern_release(PID p, EDF_level_des *lev)
147
{
148
  struct timespec temp;
149
 
150
  /* post deadline timer */
151
  if (lev->flags & EDF_ENABLE_DL_CHECK) {
152
    temp = lev->release[p];
153
    ADDUSEC2TIMESPEC(lev->rdeadline[p], &temp);
154
    lev->dl_timer[p] = kern_event_post(&temp,EDF_timer_deadline,(void *)p);
155
  }
156
 
157
  /* release or queue next job */
158
  if (proc_table[p].status == EDF_IDLE) {
159
    /* assign deadline, insert task in the ready queue */
160
    proc_table[p].status = EDF_READY;
161
    *iq_query_timespec(p,&lev->ready) = lev->adeadline[p];
162
    iq_timespec_insert(p,&lev->ready);
163
#ifdef EDF_DEBUG
164
    edf_printf("At %s: releasing %s with deadline %s\n", pnow(),
165
       proc_table[p].name, ptime1(&lev->adeadline[p]));
166
#endif
167
    /* increase assigned deadline */
168
    ADDUSEC2TIMESPEC(lev->period[p], &lev->adeadline[p]);
169
    /* reschedule */
170
    event_need_reschedule();
171
  } else {
172
    /* queue */
173
    lev->nact[p]++;
174
  }
175
 
176
  /* increase release time */
177
  ADDUSEC2TIMESPEC(lev->period[p],&lev->release[p]);
178
  /* post end of period timer */
179
  lev->eop_timer[p] = kern_event_post(&lev->release[p],
180
                                      EDF_timer_endperiod,(void *)p);
181
 
182
  TRACER_LOGEVENT(FTrace_EVT_task_timer,(unsigned short int)proc_table[p].context,(unsigned int)proc_table[p].task_level);
183
}
184
 
185
 
186
/* Release after an offset  */
187
 
188
static void EDF_timer_offset(void *par)
189
{
190
  PID p = (PID) par;
191
  EDF_level_des *lev;
2 pj 192
  lev = (EDF_level_des *)level_table[proc_table[p].task_level];
193
 
657 anton 194
  EDF_intern_release(p, lev);
195
}
240 giacomo 196
 
2 pj 197
 
657 anton 198
/* This function is called at the end of the period */
2 pj 199
 
657 anton 200
static void EDF_timer_endperiod(void *par)
201
{
202
  PID p = (PID) par;
203
  EDF_level_des *lev;
204
  lev = (EDF_level_des *)level_table[proc_table[p].task_level];
212 giacomo 205
 
657 anton 206
  lev->eop_timer[p] = -1;
212 giacomo 207
 
657 anton 208
  if (proc_table[p].status == EDF_ZOMBIE) {
209
    /* put the task in the FREE state */
210
    proc_table[p].status = FREE;
211
    iq_insertfirst(p,&freedesc);
212
    /* free the allocated bandwidth */
213
    lev->U -= (MAX_BANDWIDTH/lev->rdeadline[p]) * proc_table[p].wcet;
214
    return;
215
  }
2 pj 216
 
657 anton 217
  if (proc_table[p].status == EDF_WAIT) {
218
    proc_table[p].status = SLEEP;
219
    return;
2 pj 220
  }
657 anton 221
 
222
  if (!(lev->taskflags[p] & EDF_FLAG_SPORADIC)) {
223
    /* if the task is periodic, rerelease it (now or later) */
224
    EDF_intern_release(p, lev);
225
  } else {
226
    /* the sporadic task is still busy. mark it as late */
227
    lev->taskflags[p] |= EDF_FLAG_SPOR_LATE;
228
  }
2 pj 229
}
230
 
657 anton 231
 
232
/* This function is called when a guest task misses its deadline */
233
 
2 pj 234
static void EDF_timer_guest_deadline(void *par)
235
{
236
  PID p = (PID) par;
502 giacomo 237
  TRACER_LOGEVENT(FTrace_EVT_task_deadline_miss,(unsigned short int)proc_table[p].context,0);
2 pj 238
  kern_raise(XDEADLINE_MISS,p);
239
}
240
 
38 pj 241
/* The scheduler only gets the first task in the queue */
242
static PID EDF_public_scheduler(LEVEL l)
2 pj 243
{
244
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
29 pj 245
  return iq_query_first(&lev->ready);
2 pj 246
}
247
 
248
/* The on-line guarantee is enabled only if the appropriate flag is set... */
38 pj 249
static int EDF_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
2 pj 250
{
251
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
252
 
159 pj 253
  if (*freebandwidth >= lev->U) {
254
    *freebandwidth -= lev->U;
255
    return 1;
2 pj 256
  }
257
  else
159 pj 258
    return 0;
2 pj 259
}
260
 
38 pj 261
static int EDF_public_create(LEVEL l, PID p, TASK_MODEL *m)
2 pj 262
{
263
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
38 pj 264
  HARD_TASK_MODEL *h;
2 pj 265
 
38 pj 266
  if (m->pclass != HARD_PCLASS) return -1;
267
  if (m->level != 0 && m->level != l) return -1;
268
  h = (HARD_TASK_MODEL *)m;
269
  if (!h->wcet || !h->mit) return -1;
657 anton 270
  if (h->drel > h->mit) return -1;  /* only D <= T supported */
159 pj 271
 
657 anton 272
  if (!h->drel) {
273
    lev->rdeadline[p] = h->mit;
274
  } else {
275
    lev->rdeadline[p] = h->drel;
276
  }
277
 
159 pj 278
  /* check the free bandwidth... */
279
  if (lev->flags & EDF_ENABLE_GUARANTEE) {
280
    bandwidth_t b;
657 anton 281
    b = (MAX_BANDWIDTH / lev->rdeadline[p]) * h->wcet;
159 pj 282
 
283
    /* really update lev->U, checking an overflow... */
657 anton 284
    if (MAX_BANDWIDTH - lev->U > b) {
159 pj 285
      lev->U += b;
657 anton 286
    } else {
159 pj 287
      return -1;
657 anton 288
    }
159 pj 289
  }
290
 
657 anton 291
  if (lev->flags & EDF_ENABLE_WCET_EXCEPTION) {
292
    lev->flags |= EDF_ENABLE_WCET_CHECK;
293
  }
294
  if (lev->flags & EDF_ENABLE_DL_EXCEPTION) {
295
    lev->flags |= EDF_ENABLE_DL_CHECK;
296
  }
2 pj 297
 
298
  lev->period[p] = h->mit;
657 anton 299
  if (lev->rdeadline[p] == lev->period[p]) {
300
    /* Ensure that D <= T-eps to make dl_timer trigger before rel_timer */
301
    lev->rdeadline[p] = lev->period[p] - 1;
302
  }
212 giacomo 303
 
657 anton 304
  lev->taskflags[p] = 0;
2 pj 305
 
306
  if (h->periodicity == APERIODIC)
657 anton 307
    lev->taskflags[p] |= EDF_FLAG_SPORADIC;
212 giacomo 308
 
657 anton 309
  lev->dl_timer[p] = -1;
310
  lev->eop_timer[p] = -1;
2 pj 311
 
312
  /* Enable wcet check */
313
  if (lev->flags & EDF_ENABLE_WCET_CHECK) {
314
    proc_table[p].avail_time = h->wcet;
315
    proc_table[p].wcet       = h->wcet;
657 anton 316
    proc_table[p].control |= CONTROL_CAP; /* turn on measurement */
2 pj 317
  }
318
 
657 anton 319
  lev->offset[p] = h->offset;
320
 
321
  NULL_TIMESPEC(&lev->release[p]);
322
 
2 pj 323
  return 0; /* OK, also if the task cannot be guaranteed... */
324
}
325
 
38 pj 326
static void EDF_public_detach(LEVEL l, PID p)
2 pj 327
{
328
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
329
 
159 pj 330
  if (lev->flags & EDF_ENABLE_GUARANTEE) {
657 anton 331
    lev->U -= (MAX_BANDWIDTH / lev->rdeadline[p]) * proc_table[p].wcet;
159 pj 332
  }
2 pj 333
}
334
 
38 pj 335
static void EDF_public_dispatch(LEVEL l, PID p, int nostop)
2 pj 336
{
337
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
29 pj 338
  iq_extract(p, &lev->ready);
2 pj 339
}
340
 
38 pj 341
static void EDF_public_epilogue(LEVEL l, PID p)
2 pj 342
{
343
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
344
 
345
  /* check if the wcet is finished... */
657 anton 346
  if (lev->flags & EDF_ENABLE_WCET_CHECK) {
347
    if (proc_table[p].avail_time <= 0) {
348
      TRACER_LOGEVENT(FTrace_EVT_task_wcet_violation,(unsigned short int)proc_table[p].context,0);
349
      if (lev->flags & EDF_ENABLE_WCET_EXCEPTION) {
350
        kern_raise(XWCET_VIOLATION,p);
351
      } else {
352
        proc_table[p].control &= ~CONTROL_CAP;
353
        lev->wcet_miss[p]++;
354
      }
355
    }
2 pj 356
  }
657 anton 357
 
358
  /* the task returns to the ready queue */
359
  iq_timespec_insert(p,&lev->ready);
360
  proc_table[p].status = EDF_READY;
361
 
2 pj 362
}
363
 
657 anton 364
static void EDF_public_activate(LEVEL l, PID p, struct timespec *t)
2 pj 365
{
657 anton 366
  struct timespec clocktime;
2 pj 367
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
368
 
657 anton 369
  kern_gettime(&clocktime);
38 pj 370
 
657 anton 371
  /* check if we are not in the SLEEP state */
372
  if (proc_table[p].status != SLEEP) {
373
    if (lev->flags & EDF_ENABLE_ACT_EXCEPTION) {
374
      /* too frequent or wrongful activation: raise exception */
375
      kern_raise(XACTIVATION,p);
376
    } else {
377
      /* skip the sporadic job, but increase a counter */
378
#ifdef EDF_DEBUG
379
      edf_printf("At %s: activation of %s skipped\n", pnow(), proc_table[p].name);
380
#endif
381
      lev->nskip[p]++;
382
    }
212 giacomo 383
    return;
384
  }
385
 
657 anton 386
  /* set the release time to the activation time + offset */
387
  lev->release[p] = *t;
388
  ADDUSEC2TIMESPEC(lev->offset[p], &lev->release[p]);
2 pj 389
 
657 anton 390
  /* set the absolute deadline to the activation time + offset + rdeadline */
391
  lev->adeadline[p] = lev->release[p];
392
  ADDUSEC2TIMESPEC(lev->rdeadline[p], &lev->adeadline[p]);
2 pj 393
 
657 anton 394
  /* Check if release > clocktime. If so, release it later,
395
     otherwise release it now. */
2 pj 396
 
657 anton 397
  proc_table[p].status = EDF_IDLE;
2 pj 398
 
657 anton 399
  if (TIMESPEC_A_GT_B(&lev->release[p], &clocktime)) {
400
    /* release later */
401
    kern_event_post(&lev->release[p],EDF_timer_offset,(void *)p);
402
  } else {
403
    /* release now */
404
    EDF_intern_release(p, lev);
405
  }
2 pj 406
}
407
 
38 pj 408
static void EDF_public_unblock(LEVEL l, PID p)
2 pj 409
{
410
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
411
 
657 anton 412
  /* Insert task in the correct position */
2 pj 413
  proc_table[p].status = EDF_READY;
29 pj 414
  iq_timespec_insert(p,&lev->ready);
2 pj 415
}
416
 
38 pj 417
static void EDF_public_block(LEVEL l, PID p)
2 pj 418
{
419
  /* Extract the running task from the level
420
     . we have already extract it from the ready queue at the dispatch time.
421
     . the capacity event have to be removed by the generic kernel
422
     . the wcet don't need modification...
423
     . the state of the task is set by the calling function
424
     . the deadline must remain...
425
 
426
     So, we do nothing!!!
427
  */
428
}
429
 
38 pj 430
static int EDF_public_message(LEVEL l, PID p, void *m)
2 pj 431
{
432
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
433
 
212 giacomo 434
  switch((long)(m)) {
657 anton 435
    /* task_endcycle() */
436
  case 0:
437
    /* if there are no pending jobs */
438
    if (lev->nact[p] == 0) {
439
      /* remove deadline timer, if any */
440
      if (lev->dl_timer[p] != -1) {
441
        kern_event_delete(lev->dl_timer[p]);
442
        lev->dl_timer[p] = -1;
443
      }
444
      if (lev->taskflags[p] & EDF_FLAG_SPORADIC) {
445
        /* sporadic task */
446
        if (!(lev->taskflags[p] & EDF_FLAG_SPOR_LATE)) {
447
          proc_table[p].status = EDF_WAIT;
448
        } else {
449
          /* it's late, move it directly to SLEEP */
450
          proc_table[p].status = SLEEP;
451
          lev->taskflags[p] &= ~EDF_FLAG_SPOR_LATE;
452
        }
453
      } else {
454
        /* periodic task */
455
        proc_table[p].status = EDF_IDLE;
456
      }
457
    } else {
458
      /* we are late / there are pending jobs */
459
      lev->nact[p]--;
460
      /* compute and assign absolute deadline */
461
      *iq_query_timespec(p,&lev->ready) = lev->adeadline[p];
462
      iq_timespec_insert(p,&lev->ready);
463
      /* increase assigned deadline */
464
      ADDUSEC2TIMESPEC(lev->period[p], &lev->adeadline[p]);
465
#ifdef EDF_DEBUG
466
      edf_printf("(Late) At %s: releasing %s with deadline %s\n",
467
         pnow(),proc_table[p].name,ptime1(&lev->adeadline[p]));
468
#endif
469
    }
470
    break;
471
 
472
    /* task_sleep() */
473
  case 1:
474
    /* remove deadline timer, if any */
475
    if (lev->dl_timer[p] != -1) {
476
      kern_event_delete(lev->dl_timer[p]);
477
      lev->dl_timer[p] = -1;
478
    }
479
    if (lev->taskflags[p] & EDF_FLAG_SPORADIC) {
480
      /* sporadic task */
481
      if (!(lev->taskflags[p] & EDF_FLAG_SPOR_LATE)) {
212 giacomo 482
        proc_table[p].status = EDF_WAIT;
657 anton 483
      } else {
484
        /* it's late, move it directly to SLEEP */
485
        proc_table[p].status = SLEEP;
486
        lev->taskflags[p] &= ~EDF_FLAG_SPOR_LATE;
487
      }
488
    } else {
489
      /* periodic task */
490
      if (!(lev->nact[p] > 0)) {
491
        /* we are on time. go to the EDF_WAIT state */
492
        proc_table[p].status = EDF_WAIT;
493
      } else {
494
        /* we are late. delete pending activations and go to SLEEP */
495
        lev->nact[p] = 0;
496
        proc_table[p].status = SLEEP;
497
        /* remove end of period timer */
498
        if (lev->eop_timer[p] != -1) {
499
          kern_event_delete(lev->eop_timer[p]);
500
          lev->eop_timer[p] = -1;
501
        }
502
      }
503
    }
504
    break;
505
  }
212 giacomo 506
 
657 anton 507
  if (lev->flags & EDF_ENABLE_WCET_CHECK) {
508
    proc_table[p].control |= CONTROL_CAP;
212 giacomo 509
  }
657 anton 510
  proc_table[p].avail_time = proc_table[p].wcet;
511
  jet_update_endcycle(); /* Update the Jet data... */
512
  TRACER_LOGEVENT(FTrace_EVT_task_end_cycle,(unsigned short int)proc_table[p].context,(unsigned int)l);
513
 
38 pj 514
  return 0;
212 giacomo 515
 
2 pj 516
}
517
 
38 pj 518
static void EDF_public_end(LEVEL l, PID p)
2 pj 519
{
657 anton 520
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
2 pj 521
 
657 anton 522
  if (!(lev->taskflags[p] & EDF_FLAG_SPOR_LATE)) {
523
    /* remove the deadline timer (if any) */
524
    if (lev->dl_timer[p] != -1) {
525
      kern_event_delete(lev->dl_timer[p]);
526
      lev->dl_timer[p] = -1;
527
    }
528
    proc_table[p].status = EDF_ZOMBIE;
529
  } else {
530
    /* no endperiod timer will be fired, free the task now! */
531
    proc_table[p].status = FREE;
532
    iq_insertfirst(p,&freedesc);
533
    /* free the allocated bandwidth */
534
    lev->U -= (MAX_BANDWIDTH/lev->rdeadline[p]) * proc_table[p].wcet;
535
  }
2 pj 536
}
537
 
38 pj 538
static void EDF_private_insert(LEVEL l, PID p, TASK_MODEL *m)
2 pj 539
{
540
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
38 pj 541
  JOB_TASK_MODEL *job;
2 pj 542
 
38 pj 543
  if (m->pclass != JOB_PCLASS || (m->level != 0 && m->level != l) ) {
544
    kern_raise(XINVALID_TASK, p);
545
    return;
546
  }
2 pj 547
 
38 pj 548
  job = (JOB_TASK_MODEL *)m;
2 pj 549
 
38 pj 550
  /* Insert task in the correct position */
29 pj 551
  *iq_query_timespec(p, &lev->ready) = job->deadline;
38 pj 552
  iq_timespec_insert(p,&lev->ready);
553
  proc_table[p].status = EDF_READY;
2 pj 554
 
657 anton 555
  lev->dl_timer[p] = -1;
2 pj 556
 
38 pj 557
  lev->period[p] = job->period;
558
 
657 anton 559
  if (!job->noraiseexc) {
560
    lev->dl_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
561
                                       EDF_timer_guest_deadline,(void *)p);
38 pj 562
  }
2 pj 563
}
564
 
38 pj 565
static void EDF_private_dispatch(LEVEL l, PID p, int nostop)
2 pj 566
{
567
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
568
 
569
  /* the task state is set to EXE by the scheduler()
570
     we extract the task from the ready queue
571
     NB: we can't assume that p is the first task in the queue!!! */
29 pj 572
  iq_extract(p, &lev->ready);
2 pj 573
}
574
 
38 pj 575
static void EDF_private_epilogue(LEVEL l, PID p)
2 pj 576
{
577
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
578
 
579
  /* the task has been preempted. it returns into the ready queue... */
29 pj 580
  iq_timespec_insert(p,&lev->ready);
2 pj 581
  proc_table[p].status = EDF_READY;
582
}
583
 
38 pj 584
static void EDF_private_extract(LEVEL l, PID p)
2 pj 585
{
586
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
587
 
588
  if (proc_table[p].status == EDF_READY)
29 pj 589
    iq_extract(p, &lev->ready);
2 pj 590
 
591
  /* we remove the deadline timer, because the slice is finished */
657 anton 592
  if (lev->dl_timer[p] != -1) {
593
    kern_event_delete(lev->dl_timer[p]);
594
    lev->dl_timer[p] = -1;
2 pj 595
  }
596
 
597
}
598
 
599
 
657 anton 600
/* Registration function:
601
    int flags                 the init flags ... see edf.h */
38 pj 602
LEVEL EDF_register_level(int flags)
2 pj 603
{
604
  LEVEL l;            /* the level that we register */
605
  EDF_level_des *lev;  /* for readableness only */
606
  PID i;              /* a counter */
607
 
608
  printk("EDF_register_level\n");
609
 
610
  /* request an entry in the level_table */
38 pj 611
  l = level_alloc_descriptor(sizeof(EDF_level_des));
2 pj 612
 
38 pj 613
  lev = (EDF_level_des *)level_table[l];
2 pj 614
 
615
  /* fill the standard descriptor */
38 pj 616
  lev->l.private_insert   = EDF_private_insert;
617
  lev->l.private_extract  = EDF_private_extract;
618
  lev->l.private_dispatch = EDF_private_dispatch;
619
  lev->l.private_epilogue = EDF_private_epilogue;
2 pj 620
 
38 pj 621
  lev->l.public_scheduler = EDF_public_scheduler;
2 pj 622
  if (flags & EDF_ENABLE_GUARANTEE)
38 pj 623
    lev->l.public_guarantee = EDF_public_guarantee;
2 pj 624
  else
38 pj 625
    lev->l.public_guarantee = NULL;
2 pj 626
 
38 pj 627
  lev->l.public_create    = EDF_public_create;
628
  lev->l.public_detach    = EDF_public_detach;
629
  lev->l.public_end       = EDF_public_end;
630
  lev->l.public_dispatch  = EDF_public_dispatch;
631
  lev->l.public_epilogue  = EDF_public_epilogue;
632
  lev->l.public_activate  = EDF_public_activate;
633
  lev->l.public_unblock   = EDF_public_unblock;
634
  lev->l.public_block     = EDF_public_block;
635
  lev->l.public_message   = EDF_public_message;
2 pj 636
 
637
  /* fill the EDF descriptor part */
638
  for(i=0; i<MAX_PROC; i++) {
657 anton 639
    lev->period[i]    = 0;
640
    lev->dl_timer[i]  = -1;
641
    lev->eop_timer[i] = -1;
642
    lev->taskflags[i] = 0;
643
    lev->dl_miss[i]   = 0;
644
    lev->wcet_miss[i] = 0;
645
    lev->nact[i]      = 0;
646
    lev->nskip[i]     = 0;
2 pj 647
  }
648
 
29 pj 649
  iq_init(&lev->ready, &freedesc, 0);
159 pj 650
  lev->flags = flags;
2 pj 651
  lev->U     = 0;
38 pj 652
 
653
  return l;
2 pj 654
}
655
 
656
bandwidth_t EDF_usedbandwidth(LEVEL l)
657
{
658
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
38 pj 659
 
660
  return lev->U;
2 pj 661
}
662
 
657 anton 663
int EDF_get_nact(PID p)
664
{
665
  LEVEL l = proc_table[p].task_level;
666
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
667
 
668
  return lev->nact[p];
669
}
670
 
671
int EDF_get_dl_miss(PID p)
672
{
673
  LEVEL l = proc_table[p].task_level;
674
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
675
 
676
  return lev->dl_miss[p];
677
}
678
 
679
int EDF_get_wcet_miss(PID p)
680
{
681
  LEVEL l = proc_table[p].task_level;
682
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
683
 
684
  return lev->wcet_miss[p];
685
}
686
 
687
int EDF_get_nskip(PID p)
688
{
689
  LEVEL l = proc_table[p].task_level;
690
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
691
 
692
  return lev->nskip[p];
693
}
694