Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1663 pj 1
/*
2
 * Copyright (C) 2000 Paolo Gai
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 2 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 */
19
 
20
#include "edf.h"
21
#include "valmodel.h"
22
#include <ll/stdio.h>
23
#include <ll/string.h>
24
#include <kernel/model.h>
25
#include <kernel/descr.h>
26
#include <kernel/var.h>
27
#include <kernel/func.h>
28
#include <kernel/trace.h>
29
 
30
//#define edf_printf kern_printf
31
#define edf_printf printk
32
 
33
/*+ Status used in the level +*/
34
#define EDF_READY         MODULE_STATUS_BASE    /*+ - Ready status        +*/
35
#define EDF_DELAY         MODULE_STATUS_BASE+1  /*+ - Delay status        +*/
36
#define EDF_WCET_VIOLATED MODULE_STATUS_BASE+2  /*+ when wcet is finished +*/
37
#define EDF_WAIT          MODULE_STATUS_BASE+3  /*+ to wait the deadline  +*/
38
#define EDF_IDLE          MODULE_STATUS_BASE+4  /*+ to wait the deadline  +*/
39
#define EDF_ZOMBIE        MODULE_STATUS_BASE+5  /*+ to wait the free time +*/
40
 
41
 
42
/* For group create */
43
#define EDF_NOTYET_GUARANTEED 1
44
#define EDF_GUARANTEED 2
45
#define EDF_REJECTED 3
46
 
47
/*+ flags +*/
48
#define EDF_FLAG_SPORADIC    1
49
#define EDF_FLAG_NORAISEEXC  2
50
#define EDF_FLAG_APERIODIC   3
51
 
52
static LEVEL ModuleLevel;  //Ugling to save the level we r registered at.
53
 
54
/*+ the level redefinition for the Earliest Deadline First level +*/
55
typedef struct{
56
  level_des l;     /*+ the standard level descriptor          +*/
57
 
58
  TIME period[MAX_PROC]; /*+ The task periods; the deadlines are
59
                       stored in the priority field           +*/
60
  int deadline_timer[MAX_PROC];
61
                   /*+ The task deadline timers               +*/
62
 
63
  int flag[MAX_PROC];  /*+ used to manage the JOB_TASK_MODEL and the
64
                       periodicity                            +*/
65
 
66
  QUEUE ready;     /*+ the ready queue                        +*/
67
 
68
  int flags;       /*+ the init flags...                      +*/
69
 
70
  bandwidth_t U;   /*+ the used bandwidth                     +*/
71
 
72
  int guarantee_status[MAX_PROC]; /* for the group create */
73
 
74
  QUEUE arrived;                  /* for all the tasks that arrive */
75
 
76
 
77
  /* VALUE_TASK specific data */
78
  long accumulatedValue;                     /* The accumulated system value */
79
 
80
  TIME dline[MAX_PROC];
81
 
82
  int value[MAX_PROC];
83
  int penalty[MAX_PROC];
84
 
85
} EDF_level_des;
86
 
87
 
88
static char *EDF_status_to_a(WORD status)
89
{
90
  if (status < MODULE_STATUS_BASE)
91
    return status_to_a(status);
92
 
93
  switch (status) {
94
    case EDF_READY        : return "EDF_Ready";
95
    case EDF_DELAY        : return "EDF_Delay";
96
    case EDF_WCET_VIOLATED: return "EDF_Wcet_Violated";
97
    case EDF_WAIT         : return "EDF_Sporadic_Wait";
98
    case EDF_IDLE         : return "EDF_Idle";
99
    case EDF_ZOMBIE       : return "EDF_Zombie";
100
    default               : return "EDF_Unknown";
101
  }
102
}
103
 
104
static void EDF_timer_deadline(void *par)
105
{
106
  PID p = (PID) par;
107
  EDF_level_des *lev;
108
 
109
  edf_printf("$");
110
 
111
  lev = (EDF_level_des *)level_table[proc_table[p].task_level];
112
 
113
  switch (proc_table[p].status) {
114
    case EDF_ZOMBIE:
115
      /* we finally put the task in the ready queue */
116
      proc_table[p].status = FREE;
117
      q_insertfirst(p,&freedesc);
118
      /* and free the allocated bandwidth */
119
      if(lev->flag[p] == EDF_FLAG_APERIODIC){
120
          //!!!!!  FRIG™R den allokerade bandbredden h„r!!!!
121
          // kanske n†ge mera
122
      }else{
123
            /* SPORADIC, could be removed. (we do not use them)*/
124
 
125
        lev->U -= (MAX_BANDWIDTH/lev->period[p]) * proc_table[p].wcet;
126
      }
127
      break;
128
 
129
    case EDF_IDLE:
130
      /* tracer stuff */
131
      trc_logevent(TRC_INTACTIVATION,&p);
132
      /* similar to EDF_task_activate */
133
      TIMESPEC_ASSIGN(&proc_table[p].request_time,
134
                      &proc_table[p].timespec_priority);
135
      ADDUSEC2TIMESPEC(lev->period[p], &proc_table[p].timespec_priority);
136
      proc_table[p].status = EDF_READY;
137
      q_timespec_insert(p,&lev->ready);
138
      lev->deadline_timer[p] = kern_event_post(&proc_table[p].timespec_priority,
139
                                               EDF_timer_deadline,
140
                                               (void *)p);
141
      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);
142
      //printk("(d%d idle priority set to %d)",p,proc_table[p].priority );
143
      event_need_reschedule();
144
      printk("el%d|",p);
145
      break;
146
 
147
    case EDF_WAIT:
148
      /* Without this, the task cannot be reactivated!!! */
149
      proc_table[p].status = SLEEP;
150
      break;
151
 
152
    default:
153
      /* else, a deadline miss occurred!!! */
154
      edf_printf("\nstatus %d\n", (int)proc_table[p].status);
155
      edf_printf("timer_deadline:AAARRRGGGHHH!!!");
156
      kern_raise(XDEADLINE_MISS,p);
157
  }
158
}
159
 
160
 
161
/*+ this function is called when a task finish his delay +*/
162
static void EDF_timer_delay(void *par)
163
{
164
  PID p = (PID) par;
165
  EDF_level_des *lev;
166
 
167
  lev = (EDF_level_des *)level_table[proc_table[p].task_level];
168
 
169
  proc_table[p].status = EDF_READY;
170
  q_timespec_insert(p,&lev->ready);
171
 
172
  proc_table[p].delay_timer = NIL;  /* Paranoia */
173
 
174
  event_need_reschedule();
175
}
176
 
177
 
178
static int EDF_level_accept_task_model(LEVEL l, TASK_MODEL *m)
179
{
180
  if(m->pclass == VALUE_PCLASS){
181
    /* VALUE_TASK_MODEL */
182
    VALUE_TASK_MODEL *v = (VALUE_TASK_MODEL *)m;
183
 
184
    if(v->wcet && v->dline && v->value && v->penalty){
185
      if(v->dline >= v->wcet && v->value <= 100 && v->penalty <= 100)
186
         return 0;
187
    }
188
  }else if (m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l)) {
189
    /* HARD_TASK_MODEL */
190
 
191
    HARD_TASK_MODEL *h = (HARD_TASK_MODEL *)m;
192
 
193
    if (h->wcet && h->mit)
194
      return 0;
195
  }
196
 
197
 
198
  return -1;
199
}
200
 
201
/* We do not accept any guest calls and models */
202
static int EDF_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
203
{  return -1; }
204
 
205
 
206
static char *onoff(int i)
207
{
208
  if (i)
209
    return "On ";
210
  else
211
    return "Off";
212
}
213
 
214
static void EDF_level_status(LEVEL l)
215
{
216
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
217
  PID p = lev->ready;
218
 
219
  kern_printf("Wcet     Check    : %s\n",
220
            onoff(lev->flags & EDF_ENABLE_WCET_CHECK));
221
  kern_printf("On-line guarantee : %s\n",
222
            onoff(lev->flags & EDF_ENABLE_GUARANTEE));
223
  kern_printf("Used Bandwidth    : %u/%u\n",
224
            lev->U, MAX_BANDWIDTH);
225
 
226
  while (p != NIL) {
227
    if ((proc_table[p].pclass) == JOB_PCLASS)
228
      kern_printf("Pid: %2d (GUEST)\n", p);
229
    else
230
      kern_printf("Pid: %2d Name: %10s %s: %9ld Dline: %9ld.%6ld Stat: %s\n",
231
              p,
232
              proc_table[p].name,
233
              lev->flag[p] & EDF_FLAG_SPORADIC ? "MinITime" : "Period  ",
234
              lev->period[p],
235
              proc_table[p].timespec_priority.tv_sec,
236
              proc_table[p].timespec_priority.tv_nsec/1000,
237
              EDF_status_to_a(proc_table[p].status));
238
    p = proc_table[p].next;
239
  }
240
 
241
  for (p=0; p<MAX_PROC; p++)
242
    if (proc_table[p].task_level == l && proc_table[p].status != EDF_READY
243
        && proc_table[p].status != FREE )
244
      kern_printf("Pid: %2d Name: %10s %s: %9ld Dline: %9ld.%6ld Stat: %s\n",
245
                p,
246
                proc_table[p].name,
247
                lev->flag[p] & EDF_FLAG_SPORADIC ? "MinITime" : "Period  ",
248
                lev->period[p],
249
                proc_table[p].timespec_priority.tv_sec,
250
                proc_table[p].timespec_priority.tv_nsec/1000,
251
                EDF_status_to_a(proc_table[p].status));
252
}
253
 
254
/* The scheduler only gets the first task in the queue */
255
static PID EDF_level_scheduler(LEVEL l)
256
{
257
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
258
 
259
/*  {  // print 4 dbg the ready queue
260
    PID p= lev->ready;
261
    kern_printf("(s");
262
    while (p != NIL) {
263
      kern_printf("%d ",p);
264
      p = proc_table[p].next;
265
    }
266
    kern_printf(") ");
267
  }
268
  */
269
  return (PID)lev->ready;
270
}
271
 
272
/* The on-line guarantee is enabled only if the appropriate flag is set... */
273
static int EDF_level_guarantee(LEVEL l, bandwidth_t *freebandwidth)
274
{
275
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
276
  PID p;
277
 
278
 
279
  //om flaggan sattes i task_create,
280
  //kanske inte ska vara h„r men det fungerar just nu i alla fall.
281
  if (lev->flags & EDF_FAILED_GUARANTEE) {
282
    *freebandwidth = 0;
283
    return 0;
284
  }
285
 
286
 
287
  /*check all the arrived tasks, guarantee them or not */
288
  while(lev->arrived != NIL){
289
    p = q_getfirst(&lev->arrived);
290
 
291
    if(lev->flag[p] == EDF_FLAG_APERIODIC){
292
 
293
        //!!!! h„r ska v†rat acceptans test f”r value task ligga
294
 
295
        lev->guarantee_status[p] = EDF_GUARANTEED;
296
    }else{
297
        /* Accept all the periodic tasks */
298
        lev->guarantee_status[p] = EDF_GUARANTEED;
299
    }
300
  }
301
 
302
 
303
  if (*freebandwidth >= lev->U) {
304
     *freebandwidth -= lev->U;
305
     return 1;
306
  }else
307
     return 0;
308
 
309
}
310
 
311
static int EDF_task_create(LEVEL l, PID p, TASK_MODEL *m)
312
{
313
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
314
 
315
 
316
  /* if the EDF_task_create is called, then the pclass must be a
317
     valid pclass. */
318
 
319
 
320
  if(m->pclass == VALUE_PCLASS){
321
    /* VALUE_TASK_MODEL */
322
 
323
        //!!!!!!!!!!!! Kan vara smart att sortera value task i kön efter priority fältet !!!!!!!!!
324
 
325
 
326
    VALUE_TASK_MODEL *v = (VALUE_TASK_MODEL *)m;
327
 
328
 
329
    lev->value[p] = v->value;
330
    lev->penalty[p] = v->penalty;
331
    lev->dline[p] = v->dline;
332
 
333
 
334
    /* Mark that this is a value task (aperiodic)*/
335
    lev->flag[p] = EDF_FLAG_APERIODIC;
336
 
337
    /* Enable wcet check */
338
    if (lev->flags & EDF_ENABLE_WCET_CHECK) {
339
       proc_table[p].avail_time = v->wcet;
340
       proc_table[p].wcet       = v->wcet;
341
       proc_table[p].control |= CONTROL_CAP;
342
    }
343
  }else{
344
    /* HARD_TASK_MODEL */
345
 
346
    HARD_TASK_MODEL *h = (HARD_TASK_MODEL *)m;
347
 
348
    lev->period[p] = h->mit;
349
 
350
    if (h->periodicity == APERIODIC)
351
       lev->flag[p] = EDF_FLAG_SPORADIC;
352
    else
353
       lev->flag[p] = 0;
354
 
355
    lev->deadline_timer[p] = -1;
356
 
357
 
358
    /* Enable wcet check */
359
    if (lev->flags & EDF_ENABLE_WCET_CHECK) {
360
       proc_table[p].avail_time = h->wcet;
361
       proc_table[p].wcet       = h->wcet;
362
       proc_table[p].control |= CONTROL_CAP;
363
    }
364
  }
365
 
366
 
367
  //detta test kan/SKA man g”ra i level_guarantee, kanske tom i v†rat
368
  //acceptans test. H„r m†ste man ju „nd† alltid returnera ok (0)
369
 
370
  /* update the bandwidth... */
371
//  if (lev->flags & EDF_ENABLE_GUARANTEE) {
372
//    bandwidth_t b;
373
//    b = (MAX_BANDWIDTH / h->mit) * h->wcet;
374
 
375
    /* really update lev->U, checking an overflow... */
376
//    if (MAX_BANDWIDTH - lev->U > b)
377
//      lev->U += b;
378
//    else
379
      /* The task can NOT be guaranteed (U>MAX_BANDWIDTH)...
380
         in this case, we don't raise an exception... in fact, after the
381
         EDF_task_create the task_create will call level_guarantee that return
382
         -1... return -1 in EDF_task_create isn't correct, because:
383
           . generally, the guarantee must be done when also the resources
384
             are registered
385
           . returning -1 will cause the task_create to return with an errno
386
             ETASK_CREATE instead of ENO_GUARANTEE!!!
387
 
388
         Why I use the flag??? because if the lev->U overflows, if i.e. I set
389
         it to MAX_BANDWIDTH, I lose the correct allocated bandwidth...
390
      */
391
//      lev->flags |= EDF_FAILED_GUARANTEE;
392
//  }
393
 
394
 
395
 
396
  /* Insert the tasks in the arrived QUEUE to enable group_create */
397
  q_insert(p, &lev->arrived);
398
  lev->guarantee_status[p] = EDF_NOTYET_GUARANTEED;
399
 
400
 
401
 
402
  return 0; /* OK, also if the task cannot be guaranteed... */
403
}
404
 
405
/* Called if task creation did'nt work */
406
static void EDF_task_detach(LEVEL l, PID p)
407
{
408
  /* the EDF level doesn't introduce any dinamic allocated new field.
409
     we have only to reset the NO_GUARANTEE FIELD and decrement the allocated
410
     bandwidth */
411
 
412
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
413
 
414
  if (lev->flags & EDF_FAILED_GUARANTEE)
415
    lev->flags &= ~EDF_FAILED_GUARANTEE;
416
  else
417
    lev->U -= (MAX_BANDWIDTH / lev->period[p]) * proc_table[p].wcet;
418
 
419
 
420
  //extract the arrived task from the Q
421
  q_extract(p, &lev->arrived);
422
  lev->guarantee_status[p] = EDF_NOTYET_GUARANTEED;
423
 
424
}
425
 
426
static int EDF_task_eligible(LEVEL l, PID p)
427
{
428
  return 0; /* if the task p is chosen, it is always eligible */
429
}
430
 
431
#ifdef __TEST1__
432
extern int testactive;
433
extern struct timespec s_stime[];
434
extern TIME s_curr[];
435
extern TIME s_PID[];
436
extern int useds;
437
#endif
438
 
439
static void EDF_task_dispatch(LEVEL l, PID p, int nostop)
440
{
441
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
442
 
443
  edf_printf("(disp p%d %d.%d)",(int)p,(int)schedule_time.tv_sec,(int)schedule_time.tv_nsec/1000);
444
 
445
  /* the task state is set EXE by the scheduler()
446
     we extract the task from the ready queue
447
     NB: we can't assume that p is the first task in the queue!!! */
448
  q_extract(p, &lev->ready);
449
 
450
  #ifdef __TEST1__
451
  if (testactive)
452
  {
453
    TIMESPEC_ASSIGN(&s_stime[useds], &schedule_time);
454
    s_curr[useds] = proc_table[p].avail_time;
455
    s_PID[useds]  = p;
456
    useds++;
457
  }
458
  #endif
459
}
460
 
461
static void EDF_task_epilogue(LEVEL l, PID p)
462
{
463
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
464
 
465
  edf_printf("(epil p%d %d.%d)",p,(int)schedule_time.tv_sec,(int)schedule_time.tv_nsec/1000);
466
 
467
  /* check if the wcet is finished... */
468
  if ((lev->flags & EDF_ENABLE_WCET_CHECK) && proc_table[p].avail_time <= 0) {
469
    /* if it is, raise a XWCET_VIOLATION exception */
470
    kern_raise(XWCET_VIOLATION,p);
471
    proc_table[p].status = EDF_WCET_VIOLATED;
472
  }
473
  else {
474
    /* the task has been preempted. it returns into the ready queue... */
475
    q_timespec_insert(p,&lev->ready);
476
    proc_table[p].status = EDF_READY;
477
  }
478
}
479
 
480
static void EDF_task_activate(LEVEL l, PID p)
481
{
482
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
483
 
484
  if (proc_table[p].status == EDF_WAIT) {
485
    kern_raise(XACTIVATION,p);
486
    return;
487
  }
488
 
489
  /* Test if we are trying to activate a non sleeping task    */
490
  /* Ignore this; the task is already active                  */
491
  if (proc_table[p].status != SLEEP &&
492
      proc_table[p].status != EDF_WCET_VIOLATED)
493
    return;
494
 
495
 
496
  /* Set the deadline for the task*/
497
  if(lev->flag[p] == EDF_FLAG_APERIODIC ){
498
        /* VALUE_TASK */
499
 
500
        ll_gettime(TIME_EXACT, &proc_table[p].request_time);
501
 
502
        TIMESPEC_ASSIGN(&proc_table[p].timespec_priority,
503
                  &proc_table[p].request_time);
504
        ADDUSEC2TIMESPEC(lev->dline[p], &proc_table[p].timespec_priority);
505
  }else{
506
        /* HARD_TASK */
507
 
508
        /* see also EDF_timer_deadline */
509
        /* e.g. set a new deadline for the hard periodic task */
510
        ll_gettime(TIME_EXACT, &proc_table[p].request_time);
511
 
512
        TIMESPEC_ASSIGN(&proc_table[p].timespec_priority,
513
                  &proc_table[p].request_time);
514
        ADDUSEC2TIMESPEC(lev->period[p], &proc_table[p].timespec_priority);
515
  }
516
 
517
  /* Insert task in the correct position */
518
  proc_table[p].status = EDF_READY;
519
  q_timespec_insert(p,&lev->ready);
520
 
521
  /* Set the deadline timer */
522
  lev->deadline_timer[p] = kern_event_post(&proc_table[p].timespec_priority,
523
                                           EDF_timer_deadline,
524
                                           (void *)p);
525
  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);
526
 
527
}
528
 
529
static void EDF_task_insert(LEVEL l, PID p)
530
{
531
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
532
 
533
  /* Similar to EDF_task_activate, but we don't check in what state
534
     the task is and we don't set the request_time*/
535
 
536
  /* Insert task in the coEDFect position */
537
  proc_table[p].status = EDF_READY;
538
  q_timespec_insert(p,&lev->ready);
539
}
540
 
541
static void EDF_task_extract(LEVEL l, PID p)
542
{
543
  /* Extract the running task from the level
544
     . we have already extract it from the ready queue at the dispatch time.
545
     . the capacity event have to be removed by the generic kernel
546
     . the wcet don't need modification...
547
     . the state of the task is set by the calling function
548
     . the deadline must remain...
549
 
550
     So, we do nothing!!!
551
  */
552
}
553
 
554
static void EDF_task_endcycle(LEVEL l, PID p)
555
{
556
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
557
 
558
  edf_printf("(ecyc p%d %d.%d)",p,(int)schedule_time.tv_sec,(int)schedule_time.tv_nsec/1000);
559
 
560
  /* the task has terminated his job before it consume the wcet. All OK! */
561
  if (lev->flag[p] & EDF_FLAG_SPORADIC)
562
    proc_table[p].status = EDF_WAIT;
563
  else /* pclass = sporadic_pclass */
564
    proc_table[p].status = EDF_IDLE;
565
 
566
  /* we reset the capacity counters... */
567
  if (lev->flags & EDF_ENABLE_WCET_CHECK)
568
    proc_table[p].avail_time = proc_table[p].wcet;
569
 
570
  /* when the deadline timer fire, it recognize the situation and set
571
     correctly all the stuffs (like reactivation, request_time, etc... ) */
572
}
573
 
574
static void EDF_task_end(LEVEL l, PID p)
575
{
576
//  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
577
 
578
  kern_printf("EDF_task_end: %s\n", proc_table[p].name);
579
 
580
  proc_table[p].status = EDF_ZOMBIE;
581
 
582
  /* When the deadline timer fire, it put the task descriptor in
583
     the free queue, and free the allocated bandwidth... */
584
}
585
 
586
static void EDF_task_sleep(LEVEL l, PID p)
587
{
588
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
589
 
590
  /* the task has terminated his job before it consume the wcet. All OK! */
591
  proc_table[p].status = EDF_WAIT;
592
 
593
  /* we reset the capacity counters... */
594
  if (lev->flags & EDF_ENABLE_WCET_CHECK)
595
    proc_table[p].avail_time = proc_table[p].wcet;
596
 
597
  /* when the deadline timer fire, it recognize the situation and set
598
     correctly the task state to sleep... */
599
}
600
 
601
static void EDF_task_delay(LEVEL l, PID p, TIME usdelay)
602
{
603
  struct timespec wakeuptime;
604
//  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
605
 
606
  /* equal to EDF_task_endcycle */
607
  proc_table[p].status = EDF_DELAY;
608
 
609
  /* we need to delete this event if we kill the task while it is sleeping */
610
  ll_gettime(TIME_EXACT, &wakeuptime);
611
  ADDUSEC2TIMESPEC(usdelay, &wakeuptime);
612
  proc_table[p].delay_timer = kern_event_post(&wakeuptime,
613
                                              EDF_timer_delay,
614
                                              (void *)p);
615
}
616
 
617
/* Guest Functions
618
   These functions manages a JOB_TASK_MODEL, that is used to put
619
   a guest task in the EDF ready queue. */
620
 
621
 
622
static void EDF_timer_guest_deadline(void *par)
623
{
624
  kern_raise(XUNVALID_GUEST, exec_shadow);
625
}
626
 
627
static int EDF_guest_create(LEVEL l, PID p, TASK_MODEL *m)
628
{
629
  kern_raise(XUNVALID_GUEST, exec_shadow);
630
  return 0;
631
}
632
 
633
static void EDF_guest_detach(LEVEL l, PID p)
634
{
635
  kern_raise(XUNVALID_GUEST, exec_shadow);
636
}
637
 
638
static void EDF_guest_dispatch(LEVEL l, PID p, int nostop)
639
{
640
  kern_raise(XUNVALID_GUEST, exec_shadow);
641
}
642
 
643
static void EDF_guest_epilogue(LEVEL l, PID p)
644
{
645
  kern_raise(XUNVALID_GUEST, exec_shadow);
646
}
647
 
648
static void EDF_guest_activate(LEVEL l, PID p)
649
{
650
  kern_raise(XUNVALID_GUEST, exec_shadow);
651
}
652
 
653
static void EDF_guest_insert(LEVEL l, PID p)
654
{
655
  kern_raise(XUNVALID_GUEST, exec_shadow);
656
}
657
 
658
static void EDF_guest_extract(LEVEL l, PID p)
659
{
660
  kern_raise(XUNVALID_GUEST, exec_shadow);
661
}
662
 
663
static void EDF_guest_endcycle(LEVEL l, PID p)
664
{
665
  kern_raise(XUNVALID_GUEST, exec_shadow);
666
}
667
static void EDF_guest_end(LEVEL l, PID p)
668
{
669
  kern_raise(XUNVALID_GUEST, exec_shadow);
670
}
671
 
672
static void EDF_guest_sleep(LEVEL l, PID p)
673
{
674
  kern_raise(XUNVALID_GUEST, exec_shadow);
675
}
676
 
677
static void EDF_guest_delay(LEVEL l, PID p, TIME usdelay)
678
{
679
  kern_raise(XUNVALID_GUEST, exec_shadow);
680
}
681
 
682
/* Registration functions */
683
 
684
/*+ Registration function:
685
    int flags                 the init flags ... see edf.h +*/
686
void EDF_register_level(int flags)
687
{
688
  LEVEL l;            /* the level that we register */
689
  EDF_level_des *lev;  /* for readableness only */
690
  PID i;              /* a counter */
691
 
692
  printk("EDF_register_level\n");
693
 
694
  /* request an entry in the level_table */
695
  l = level_alloc_descriptor();
696
 
697
  printk("    alloco descrittore %d %d\n",l,(int)sizeof(EDF_level_des));
698
 
699
  /* alloc the space needed for the EDF_level_des */
700
  lev = (EDF_level_des *)kern_alloc(sizeof(EDF_level_des));
701
 
702
  printk("    lev=%d\n",(int)lev);
703
 
704
  /* update the level_table with the new entry */
705
  level_table[l] = (level_des *)lev;
706
 
707
  /* fill the standard descriptor */
708
  strncpy(lev->l.level_name,  EDF_LEVELNAME, MAX_LEVELNAME);
709
  lev->l.level_code               = EDF_LEVEL_CODE;
710
  lev->l.level_version            = EDF_LEVEL_VERSION;
711
 
712
  lev->l.level_accept_task_model  = EDF_level_accept_task_model;
713
  lev->l.level_accept_guest_model = EDF_level_accept_guest_model;
714
  lev->l.level_status             = EDF_level_status;
715
  lev->l.level_scheduler          = EDF_level_scheduler;
716
 
717
  if (flags & EDF_ENABLE_GUARANTEE)
718
    lev->l.level_guarantee        = EDF_level_guarantee;
719
  else
720
    lev->l.level_guarantee        = NULL;
721
 
722
  lev->l.task_create              = EDF_task_create;
723
  lev->l.task_detach              = EDF_task_detach;
724
  lev->l.task_eligible            = EDF_task_eligible;
725
  lev->l.task_dispatch            = EDF_task_dispatch;
726
  lev->l.task_epilogue            = EDF_task_epilogue;
727
  lev->l.task_activate            = EDF_task_activate;
728
  lev->l.task_insert              = EDF_task_insert;
729
  lev->l.task_extract             = EDF_task_extract;
730
  lev->l.task_endcycle            = EDF_task_endcycle;
731
  lev->l.task_end                 = EDF_task_end;
732
  lev->l.task_sleep               = EDF_task_sleep;
733
  lev->l.task_delay               = EDF_task_delay;
734
 
735
  lev->l.guest_create             = EDF_guest_create;
736
  lev->l.guest_detach             = EDF_guest_detach;
737
  lev->l.guest_dispatch           = EDF_guest_dispatch;
738
  lev->l.guest_epilogue           = EDF_guest_epilogue;
739
  lev->l.guest_activate           = EDF_guest_activate;
740
  lev->l.guest_insert             = EDF_guest_insert;
741
  lev->l.guest_extract            = EDF_guest_extract;
742
  lev->l.guest_endcycle           = EDF_guest_endcycle;
743
  lev->l.guest_end                = EDF_guest_end;
744
  lev->l.guest_sleep              = EDF_guest_sleep;
745
  lev->l.guest_delay              = EDF_guest_delay;
746
 
747
  /* fill the EDF descriptor part */
748
  for(i=0; i<MAX_PROC; i++) {
749
    lev->period[i]         = 0;
750
    lev->deadline_timer[i] = -1;
751
    lev->flag[i]          = 0;
752
    lev->value[i] = -1;
753
    lev->penalty[i] = -1;
754
    lev->dline[i] = -1;
755
  }
756
 
757
  lev->ready = NIL;
758
  lev->flags = flags & 0x07;
759
  lev->U     = 0;
760
  lev->accumulatedValue = 0;
761
}
762
 
763
 
764
int is_accepted(LEVEL l, PID p){
765
    EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
766
 
767
    if(lev->guarantee_status[p] == EDF_GUARANTEED)
768
       return 1;
769
 
770
    return 0;
771
}
772
 
773
 
774
bandwidth_t EDF_usedbandwidth(LEVEL l)
775
{
776
  EDF_level_des *lev = (EDF_level_des *)(level_table[l]);
777
  if (lev->l.level_code    == EDF_LEVEL_CODE &&
778
      lev->l.level_version == EDF_LEVEL_VERSION)
779
    return lev->U;
780
  else
781
    return 0;
782
}
783
 
784
/*+ returns the current total value +*/
785
int GROUP5_getvalue(LEVEL l){
786
    return ((EDF_level_des *)(level_table[l]))->accumulatedValue;
787
}
788
 
789
/* Interface with the crunch application */
790
 
791
void crunch_register_models(struct multiboot_info *mb){
792
  // here you can register your scheduling modules
793
  EDF_register_level(EDF_ENABLE_ALL);           // Level 0
794
}
795
 
796
int crunch_taskaccepted(PID p){
797
  return is_accepted(proc_table[p].task_level, p );
798
}
799
 
800
int crunch_getvalue(/*LEVEL l*/){
801
  // here just return the accumulated value by the modules you used.
802
  // Should call the GROUP5_getvalue(LEVEL l) function.
803
  return GROUP5_getvalue(ModuleLevel);
804
}
805