Subversion Repositories shark

Rev

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

Rev Author Line No. Line
1089 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
 *   (see the web pages for full authors list)
11
 *
12
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
13
 *
14
 * http://www.sssup.it
15
 * http://retis.sssup.it
16
 * http://shark.sssup.it
17
 */
18
 
19
/**
20
 ------------
1116 pj 21
 CVS :        $Id: edfstar.c,v 1.3 2002-11-11 08:17:59 pj Exp $
1089 pj 22
 
23
 File:        $File$
1116 pj 24
 Revision:    $Revision: 1.3 $
25
 Last update: $Date: 2002-11-11 08:17:59 $
1089 pj 26
 ------------
27
**/
28
 
29
/*
30
 * Copyright (C) 2001 Paolo Gai
31
 *
32
 * This program is free software; you can redistribute it and/or modify
33
 * it under the terms of the GNU General Public License as published by
34
 * the Free Software Foundation; either version 2 of the License, or
35
 * (at your option) any later version.
36
 *
37
 * This program is distributed in the hope that it will be useful,
38
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40
 * GNU General Public License for more details.
41
 *
42
 * You should have received a copy of the GNU General Public License
43
 * along with this program; if not, write to the Free Software
44
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
45
 *
46
 */
47
 
48
#include "edfstar.h"
49
#include <ll/stdio.h>
50
#include <ll/string.h>
51
#include <kernel/model.h>
52
#include <kernel/descr.h>
53
#include <kernel/var.h>
54
#include <kernel/func.h>
55
#include <kernel/trace.h>
56
 
57
/* for iqueues */
1116 pj 58
/* #include "iqueue.h" Now iqueues are the only queue type available
59
   into the kernel */
60
#include <kernel/iqueue.h>
1089 pj 61
 
62
/* for BUDGET_TASK_MODEL */
63
#include "cbsstar.h"
64
 
65
/*
66
 * DEBUG stuffs begin
67
 */
68
 
69
//#define EDFSTAR_DEBUG
70
 
71
#ifdef EDFSTAR_DEBUF
72
 
73
static __inline__ fake_printf(char *fmt, ...) {}
74
 
75
#define edfstar_printf fake_printf
76
#define edfstar_printf2 fake_printf
77
#define edfstar_printf3 fake_printf
78
 
79
//#define edfstar_printf kern_printf
80
//#define edfstar_printf2 kern_printf
81
//#define edfstar_printf3 kern_printf
82
#endif
83
 
84
/*
85
 * DEBUG stuffs end
86
 */
87
 
88
/* Status used in the level */
89
#define EDFSTAR_READY         MODULE_STATUS_BASE    /* - Ready status        */
90
#define EDFSTAR_IDLE          MODULE_STATUS_BASE+4  /* to wait the deadline  */
91
 
92
/* flags */
93
#define EDFSTAR_FLAG_NORAISEEXC  2
94
 
95
/* the level redefinition for the Earliest Deadline First level */
96
typedef struct {
97
  level_des l;     /* the standard level descriptor          */
98
 
99
  TIME period[MAX_PROC]; /* The task periods; the deadlines are
100
                       stored in the priority field           */
101
  int deadline_timer[MAX_PROC];
102
                   /* The task deadline timers               */
103
 
104
  struct timespec deadline_timespec[MAX_PROC];
105
 
106
  int dline_miss[MAX_PROC]; /* Deadline miss counter */
107
  int wcet_miss[MAX_PROC];  /* Wcet miss counter */
108
 
109
  int nact[MAX_PROC];       /* Wcet miss counter */
110
 
111
  int flag[MAX_PROC];
112
                   /* used to manage the JOB_TASK_MODEL and the
113
                       periodicity                            */
114
 
115
  IQUEUE ready;     /* the ready queue                        */
116
 
117
  PID activated;   /* the task that has been inserted into the
118
                       master module */
119
 
120
  int budget;
121
 
122
  int scheduling_level;
123
} EDFSTAR_level_des;
124
 
125
static void EDFSTAR_check_preemption(EDFSTAR_level_des *lev)
126
{
127
  PID first;
128
 
129
#ifdef EDFSTAR_DEBUG
130
  edfstar_printf("(E:chk)");
131
#endif
132
 
1116 pj 133
  if ((first = iq_query_first(&lev->ready)) != lev->activated) {
1089 pj 134
    if (lev->activated != NIL)
135
      level_table[ lev->scheduling_level ]->
136
        guest_end(lev->scheduling_level, lev->activated);
137
 
138
    lev->activated = first;
139
 
140
    if (first != NIL) {
141
      BUDGET_TASK_MODEL b;
142
      budget_task_default_model(b, lev->budget);
143
 
144
      level_table[ lev->scheduling_level ]->
145
        guest_create(lev->scheduling_level, first, (TASK_MODEL *)&b);
146
    }
147
  }
148
}
149
 
150
static void EDFSTAR_timer_deadline(void *par);
151
 
152
static void EDFSTAR_internal_activate(EDFSTAR_level_des *lev, PID p)
153
{
154
  struct timespec temp;
155
 
156
#ifdef EDFSTAR_DEBUG
157
  edfstar_printf("(E:iact)");
158
#endif
159
 
160
  TIMESPEC_ASSIGN(&temp, &proc_table[p].request_time);
161
  ADDUSEC2TIMESPEC(lev->period[p], &temp);
162
 
163
  *iq_query_timespec(p, &lev->ready) = temp;
164
  lev->deadline_timespec[p] = temp;
165
 
166
  /* Insert task in the correct position */
167
  proc_table[p].status = EDFSTAR_READY;
168
  iq_timespec_insert(p,&lev->ready);
169
 
170
  /* needed because when there is a wcet miss I disable CONTROL_CAP */
171
  proc_table[p].control |= CONTROL_CAP;
172
 
173
  /* check for preemption */
174
  EDFSTAR_check_preemption(lev);
175
}
176
 
177
static char *EDFSTAR_status_to_a(WORD status)
178
{
179
  if (status < MODULE_STATUS_BASE)
180
    return status_to_a(status);
181
 
182
  switch (status) {
183
    case EDFSTAR_READY    : return "EDFSTAR_Ready";
184
    case EDFSTAR_IDLE     : return "EDFSTAR_Idle";
185
    default               : return "EDFSTAR_Unknown";
186
  }
187
}
188
 
189
static void EDFSTAR_timer_deadline(void *par)
190
{
191
  PID p = (PID) par;
192
  EDFSTAR_level_des *lev;
193
 
194
#ifdef EDFSTAR_DEBUG
195
//  edfstar_printf("(E:tdl ");
196
#endif
197
 
198
  lev = (EDFSTAR_level_des *)level_table[proc_table[p].task_level];
199
 
200
  switch (proc_table[p].status) {
201
    case EDFSTAR_IDLE:
202
#ifdef EDFSTAR_DEBUG
203
//      edfstar_printf2("I%d",p);
204
#endif
205
      /* set the request time */
206
      proc_table[p].request_time = *iq_query_timespec(p, &lev->ready);
207
 
208
      EDFSTAR_internal_activate(lev,p);
209
 
210
      event_need_reschedule();
211
      break;
212
 
213
    default:
214
#ifdef EDFSTAR_DEBUG
215
//      edfstar_printf2("D%d",p);
216
#endif
217
      /* else, a deadline miss occurred!!! */
218
      lev->dline_miss[p]++;
219
 
220
      /* the task is into another state */
221
      lev->nact[p]++;
222
 
223
      /* Set the deadline timer */
224
      ADDUSEC2TIMESPEC(lev->period[p], &lev->deadline_timespec[p]);
225
  }
226
 
227
  /* Set the deadline timer */
228
  lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
229
                                           EDFSTAR_timer_deadline,
230
                                           (void *)p);
231
 
232
#ifdef EDFSTAR_DEBUG
233
//  edfstar_printf(")");
234
#endif
235
}
236
 
237
static void EDFSTAR_timer_guest_deadline(void *par)
238
{
239
  PID p = (PID) par;
240
 
241
#ifdef EDFSTAR_DEBUG
242
  edfstar_printf("(E:gdl)");
243
#endif
244
 
245
  kern_raise(XDEADLINE_MISS,p);
246
}
247
 
248
static int EDFSTAR_level_accept_task_model(LEVEL l, TASK_MODEL *m)
249
{
250
#ifdef EDFSTAR_DEBUG
251
  edfstar_printf("(E:lacct)");
252
#endif
253
 
254
  if (m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l)) {
255
    HARD_TASK_MODEL *h = (HARD_TASK_MODEL *)m;
256
 
257
    if (h->wcet && h->mit && h->periodicity == PERIODIC)
258
      return 0;
259
  }
260
 
261
  return -1;
262
}
263
 
264
static int EDFSTAR_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
265
{
266
#ifdef EDFSTAR_DEBUG
267
  edfstar_printf("(E:laccg)");
268
#endif
269
 
270
  if (m->pclass == JOB_PCLASS || m->pclass == (JOB_PCLASS | l))
271
    return 0;
272
  else
273
    return -1;
274
}
275
 
276
 
277
static char *onoff(int i)
278
{
279
  if (i)
280
    return "On ";
281
  else
282
    return "Off";
283
}
284
 
285
static void EDFSTAR_level_status(LEVEL l)
286
{
287
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
1116 pj 288
  PID p = iq_query_first(&lev->ready);
1089 pj 289
  struct timespec temp;
290
 
291
  kern_printf("Budget number     : %u\n", lev->budget);
292
  kern_printf("Master level      : %u\n", lev->scheduling_level);
293
  kern_printf("Active PID        : %u\n", lev->activated);
294
 
295
  while (p != NIL) {
296
    if ((proc_table[p].pclass) == JOB_PCLASS)
297
      kern_printf("Pid: %2d (GUEST)\n", p);
298
    else {
299
      temp = *iq_query_timespec(p, &lev->ready);
300
 
301
      kern_printf("Pid: %2d Name: %10s %s: %9ld Dline: %9ld.%6ld Stat: %s\n",
302
                  p,
303
                  proc_table[p].name,
304
                  "Period  ",
305
                  lev->period[p],
306
                  temp.tv_sec,
307
                  temp.tv_nsec/1000,
308
                  EDFSTAR_status_to_a(proc_table[p].status));
1116 pj 309
      p = iq_query_next(p, &lev->ready);
1089 pj 310
    }
311
  }
312
 
313
  for (p=0; p<MAX_PROC; p++)
314
    if (proc_table[p].task_level == l
315
        && proc_table[p].status != EDFSTAR_READY
316
        && proc_table[p].status != FREE ) {
317
      temp = *iq_query_timespec(p, &lev->ready);
318
 
319
      kern_printf("Pid: %2d Name: %10s %s: %9ld Dline: %9ld.%6ld Stat: %s\n",
320
                  p,
321
                  proc_table[p].name,
322
                  "Period  ",
323
                  lev->period[p],
324
                  temp.tv_sec,
325
                  temp.tv_nsec/1000,
326
                  EDFSTAR_status_to_a(proc_table[p].status));
327
    }
328
}
329
 
330
/* The scheduler only gets the first task in the queue */
331
static PID EDFSTAR_level_scheduler(LEVEL l)
332
{
333
  //EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
334
 
335
  return NIL;
336
}
337
 
338
static int EDFSTAR_task_create(LEVEL l, PID p, TASK_MODEL *m)
339
{
340
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
341
 
342
  /* if the EDFSTAR_task_create is called, then the pclass must be a
343
     valid pclass. */
344
  HARD_TASK_MODEL *h = (HARD_TASK_MODEL *)m;
345
 
346
#ifdef EDFSTAR_DEBUG
347
  edfstar_printf("(E:tcr)");
348
#endif
349
 
350
  lev->period[p] = h->mit;
351
 
352
  lev->flag[p] = 0;
353
  lev->deadline_timer[p] = -1;
354
  lev->dline_miss[p]     = 0;
355
  lev->wcet_miss[p]      = 0;
356
  lev->nact[p]           = 0;
357
 
358
  /* Enable wcet check */
359
  proc_table[p].avail_time = h->wcet;
360
  proc_table[p].wcet       = h->wcet;
361
  proc_table[p].control |= CONTROL_CAP;
362
 
363
  return 0; /* OK, also if the task cannot be guaranteed... */
364
}
365
 
366
static void EDFSTAR_task_detach(LEVEL l, PID p)
367
{
368
#ifdef EDFSTAR_DEBUG
369
  edfstar_printf2("(E:tdt)");
370
#endif
371
}
372
 
373
static int EDFSTAR_task_eligible(LEVEL l, PID p)
374
{
375
#ifdef EDFSTAR_DEBUG
376
  edfstar_printf2("(E:eli)");
377
#endif
378
 
379
  return 0; /* if the task p is chosen, it is always eligible */
380
}
381
 
382
static void EDFSTAR_task_dispatch(LEVEL l, PID p, int nostop)
383
{
384
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
385
 
386
#ifdef EDFSTAR_DEBUG
387
  edfstar_printf("(E:dis)");
388
 
389
  edfstar_printf3("(%d %d)",
390
                  iq_query_timespec(p, &lev->ready)->tv_nsec/1000000,
391
                  schedule_time.tv_nsec/1000000);
392
#endif
393
 
394
  level_table[ lev->scheduling_level ]->
395
    guest_dispatch(lev->scheduling_level,p,nostop);
396
}
397
 
398
static void EDFSTAR_task_epilogue(LEVEL l, PID p)
399
{
400
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
401
 
402
#ifdef EDFSTAR_DEBUG
403
  edfstar_printf("(E:epi ");
404
#endif
405
 
406
  /* check if the wcet is finished... */
407
  if (proc_table[p].avail_time <= 0 && proc_table[p].control&CONTROL_CAP) {
408
    /* wcet finished: disable wcet event and count wcet miss */
409
#ifdef EDFSTAR_DEBUG
410
    edfstar_printf2("W%d",p);
411
#endif
412
    proc_table[p].control &= ~CONTROL_CAP;
413
    lev->wcet_miss[p]++;
414
  }
415
#ifdef EDFSTAR_DEBUG
416
  edfstar_printf(")");
417
#endif
418
 
419
  level_table[ lev->scheduling_level ]->
420
    guest_epilogue(lev->scheduling_level,p);
421
 
422
  proc_table[p].status = EDFSTAR_READY;
423
}
424
 
425
static void EDFSTAR_task_activate(LEVEL l, PID p)
426
{
427
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
428
 
429
#ifdef EDFSTAR_DEBUG
430
  edfstar_printf("(E:act)");
431
#endif
432
 
433
  /* Test if we are trying to activate a non sleeping task    */
434
  /* save activation (only if needed... */
435
  if (proc_table[p].status != SLEEP) {
436
    /* a periodic task cannot be activated when it is already active */
437
    kern_raise(XACTIVATION,p);
438
    return;
439
  }
440
 
441
  ll_gettime(TIME_EXACT, &proc_table[p].request_time);
442
 
443
  EDFSTAR_internal_activate(lev,p);
444
 
445
  /* Set the deadline timer */
446
  lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
447
                                           EDFSTAR_timer_deadline,
448
                                           (void *)p);
449
 
450
}
451
 
452
static void EDFSTAR_task_insert(LEVEL l, PID p)
453
{
454
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
455
 
456
#ifdef EDFSTAR_DEBUG
457
  edfstar_printf("(E:ins)");
458
#endif
459
 
460
  /* Insert task in the correct position */
461
  proc_table[p].status = EDFSTAR_READY;
462
  iq_timespec_insert(p,&lev->ready);
463
 
464
  /* and check for preemption! */
465
  EDFSTAR_check_preemption(lev);
466
}
467
 
468
static void EDFSTAR_task_extract(LEVEL l, PID p)
469
{
470
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
471
 
472
#ifdef EDFSTAR_DEBUG
473
  edfstar_printf("(E:ext)");
474
#endif
475
 
476
  /* the task is blocked on a synchronization primitive. we have to
477
     remove it from the master module -and- from the local queue! */
478
  iq_extract(p,&lev->ready);
479
 
480
  /* and finally, a preemption check! (it will also call guest_end) */
481
  EDFSTAR_check_preemption(lev);
482
}
483
 
484
static void EDFSTAR_task_endcycle(LEVEL l, PID p)
485
{
486
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
487
  struct timespec temp;
488
 
489
#ifdef EDFSTAR_DEBUG
490
  edfstar_printf("(E:ecy ");
491
#endif
492
 
493
  /* we call guest_end directly here because the same task may
494
     be reinserted in the queue before calling the preemption check! */
495
  level_table[ lev->scheduling_level ]->
496
    guest_end(lev->scheduling_level,p);
497
  lev->activated = NIL;
498
 
499
  iq_extract(p,&lev->ready);
500
 
501
  /* we reset the capacity counters... */
502
  proc_table[p].avail_time = proc_table[p].wcet;
503
 
504
  if (lev->nact[p] > 0) {
505
#ifdef EDFSTAR_DEBUG
506
    edfstar_printf2("E%d",p);
507
#endif
508
 
509
    /* Pending activation: reactivate the thread!!! */
510
    lev->nact[p]--;
511
 
512
    /* see also EDFSTAR_timer_deadline */
513
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
514
 
515
    EDFSTAR_internal_activate(lev,p);
516
 
517
    /* check if the deadline has already expired */
518
    temp = *iq_query_timespec(p, &lev->ready);
519
    if (TIMESPEC_A_LT_B(&temp, &schedule_time)) {
520
      /* count the deadline miss */
521
      lev->dline_miss[p]++;
522
      event_delete(lev->deadline_timer[p]);
523
    }
524
 
525
  }
526
  else {
527
#ifdef EDFSTAR_DEBUG
528
    edfstar_printf("e%d",p);
529
#endif
530
 
531
    /* the task has terminated his job before it consume the wcet. All OK! */
532
    proc_table[p].status = EDFSTAR_IDLE;
533
 
534
    /* and finally, a preemption check! */
535
    EDFSTAR_check_preemption(lev);
536
 
537
    /* when the deadline timer fire, it recognize the situation and set
538
       correctly all the stuffs (like reactivation, request_time, etc... ) */
539
  }
540
#ifdef EDFSTAR_DEBUG
541
  edfstar_printf(")");
542
#endif
543
}
544
 
545
static void EDFSTAR_task_end(LEVEL l, PID p)
546
{
547
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
548
 
549
#ifdef EDFSTAR_DEBUG
550
  edfstar_printf("(E:end)");
551
#endif
552
 
553
  iq_extract(p,&lev->ready);
554
 
555
  /* we finally put the task in the ready queue */
556
  proc_table[p].status = FREE;
557
 
1116 pj 558
  iq_insertfirst(p,&freedesc);
1089 pj 559
 
560
  if (lev->deadline_timer[p] != -1) {
561
    event_delete(lev->deadline_timer[p]);
562
  }
563
 
564
  /* and finally, a preemption check! (it will also call guest_end) */
565
  EDFSTAR_check_preemption(lev);
566
}
567
 
568
static void EDFSTAR_task_sleep(LEVEL l, PID p)
1100 pj 569
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 570
 
571
/* Guest Functions
572
   These functions manages a JOB_TASK_MODEL, that is used to put
573
   a guest task in the EDFSTAR ready queue. */
574
 
575
static int EDFSTAR_guest_create(LEVEL l, PID p, TASK_MODEL *m)
576
{
577
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
578
  JOB_TASK_MODEL *job = (JOB_TASK_MODEL *)m;
579
 
580
  /* if the EDFSTAR_guest_create is called, then the pclass must be a
581
     valid pclass. */
582
 
583
  *iq_query_timespec(p, &lev->ready) = job->deadline;
584
 
585
  lev->deadline_timer[p] = -1;
586
  lev->dline_miss[p]     = 0;
587
  lev->wcet_miss[p]      = 0;
588
  lev->nact[p]           = 0;
589
 
590
  if (job->noraiseexc)
591
    lev->flag[p] = EDFSTAR_FLAG_NORAISEEXC;
592
  else
593
    lev->flag[p] = 0;
594
 
595
  lev->period[p] = job->period;
596
 
597
  /* there is no bandwidth guarantee at this level, it is performed
598
     by the level that inserts guest tasks... */
599
 
600
  return 0; /* OK, also if the task cannot be guaranteed... */
601
}
602
 
603
static void EDFSTAR_guest_detach(LEVEL l, PID p)
604
{
605
  /* the EDFSTAR level doesn't introduce any dinamic allocated new field.
606
     No guarantee is performed on guest tasks... so we don't have to reset
607
     the NO_GUARANTEE FIELD */
608
}
609
 
610
static void EDFSTAR_guest_dispatch(LEVEL l, PID p, int nostop)
611
{
612
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
613
 
614
  level_table[ lev->scheduling_level ]->
615
    guest_dispatch(lev->scheduling_level,p,nostop);
616
}
617
 
618
static void EDFSTAR_guest_epilogue(LEVEL l, PID p)
619
{
620
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
621
 
622
  /* the task has been preempted. it returns into the ready queue... */
623
  level_table[ lev->scheduling_level ]->
624
    guest_epilogue(lev->scheduling_level,p);
625
 
626
  proc_table[p].status = EDFSTAR_READY;
627
}
628
 
629
static void EDFSTAR_guest_activate(LEVEL l, PID p)
630
{
631
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
632
 
633
  /* Insert task in the correct position */
634
  iq_timespec_insert(p,&lev->ready);
635
  proc_table[p].status = EDFSTAR_READY;
636
 
637
  /* check for preemption */
638
  EDFSTAR_check_preemption(lev);
639
 
640
  /* Set the deadline timer */
641
  if (!(lev->flag[p] & EDFSTAR_FLAG_NORAISEEXC))
642
    lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
643
                                             EDFSTAR_timer_guest_deadline,
644
                                             (void *)p);
645
 
646
}
647
 
648
static void EDFSTAR_guest_insert(LEVEL l, PID p)
649
{
650
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
651
 
652
  /* Insert task in the correct position */
653
  iq_timespec_insert(p,&lev->ready);
654
  proc_table[p].status = EDFSTAR_READY;
655
 
656
  /* and check for preemption! */
657
  EDFSTAR_check_preemption(lev);
658
}
659
 
660
static void EDFSTAR_guest_extract(LEVEL l, PID p)
661
{
662
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
663
 
664
  /* the task is blocked on a synchronization primitive. we have to
665
     remove it from the master module -and- from the local queue! */
666
  iq_extract(p,&lev->ready);
667
 
668
  /* and finally, a preemption check! (it will also call guest_end() */
669
  EDFSTAR_check_preemption(lev);
670
}
671
 
672
static void EDFSTAR_guest_end(LEVEL l, PID p)
673
{
674
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
675
 
676
#ifdef EDFSTAR_DEBUG
677
  //kern_printf("EDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
678
#endif
679
 
680
  iq_extract(p, &lev->ready);
681
 
682
  /* we remove the deadline timer, because the slice is finished */
683
  if (lev->deadline_timer[p] != NIL) {
684
#ifdef EDFSTAR_DEBUG
685
//    kern_printf("EDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
686
#endif
687
    event_delete(lev->deadline_timer[p]);
688
    lev->deadline_timer[p] = NIL;
689
  }
690
 
691
  /* and finally, a preemption check! (it will also call guest_end() */
692
  EDFSTAR_check_preemption(lev);
693
}
694
 
695
static void EDFSTAR_guest_endcycle(LEVEL l, PID p)
1100 pj 696
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 697
 
698
static void EDFSTAR_guest_sleep(LEVEL l, PID p)
1100 pj 699
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 700
 
701
/* Registration functions */
702
 
703
/* Registration function:
704
    int flags                 the init flags ... see EDFSTAR.h */
705
LEVEL EDFSTAR_register_level(int budget, int master)
706
{
707
  LEVEL l;            /* the level that we register */
708
  EDFSTAR_level_des *lev;  /* for readableness only */
709
  PID i;              /* a counter */
710
 
711
#ifdef EDFSTAR_DEBUG
712
  printk("EDFSTAR_register_level\n");
713
#endif
714
 
715
  /* request an entry in the level_table */
716
  l = level_alloc_descriptor();
717
 
718
#ifdef EDFSTAR_DEBUG
719
  printk("    alloco descrittore %d %d\n",l,(int)sizeof(EDFSTAR_level_des));
720
#endif
721
 
722
  /* alloc the space needed for the EDFSTAR_level_des */
723
  lev = (EDFSTAR_level_des *)kern_alloc(sizeof(EDFSTAR_level_des));
724
 
725
#ifdef EDFSTAR_DEBUG
726
  printk("    lev=%d\n",(int)lev);
727
#endif
728
 
729
  /* update the level_table with the new entry */
730
  level_table[l] = (level_des *)lev;
731
 
732
  /* fill the standard descriptor */
733
  strncpy(lev->l.level_name,  EDFSTAR_LEVELNAME, MAX_LEVELNAME);
734
  lev->l.level_code               = EDFSTAR_LEVEL_CODE;
735
  lev->l.level_version            = EDFSTAR_LEVEL_VERSION;
736
 
737
  lev->l.level_accept_task_model  = EDFSTAR_level_accept_task_model;
738
  lev->l.level_accept_guest_model = EDFSTAR_level_accept_guest_model;
739
  lev->l.level_status             = EDFSTAR_level_status;
740
  lev->l.level_scheduler          = EDFSTAR_level_scheduler;
741
  lev->l.level_guarantee          = NULL;
742
  lev->l.task_create              = EDFSTAR_task_create;
743
  lev->l.task_detach              = EDFSTAR_task_detach;
744
  lev->l.task_eligible            = EDFSTAR_task_eligible;
745
  lev->l.task_dispatch            = EDFSTAR_task_dispatch;
746
  lev->l.task_epilogue            = EDFSTAR_task_epilogue;
747
  lev->l.task_activate            = EDFSTAR_task_activate;
748
  lev->l.task_insert              = EDFSTAR_task_insert;
749
  lev->l.task_extract             = EDFSTAR_task_extract;
750
  lev->l.task_endcycle            = EDFSTAR_task_endcycle;
751
  lev->l.task_end                 = EDFSTAR_task_end;
752
  lev->l.task_sleep               = EDFSTAR_task_sleep;
753
 
754
  lev->l.guest_create             = EDFSTAR_guest_create;
755
  lev->l.guest_detach             = EDFSTAR_guest_detach;
756
  lev->l.guest_dispatch           = EDFSTAR_guest_dispatch;
757
  lev->l.guest_epilogue           = EDFSTAR_guest_epilogue;
758
  lev->l.guest_activate           = EDFSTAR_guest_activate;
759
  lev->l.guest_insert             = EDFSTAR_guest_insert;
760
  lev->l.guest_extract            = EDFSTAR_guest_extract;
761
  lev->l.guest_endcycle           = EDFSTAR_guest_endcycle;
762
  lev->l.guest_end                = EDFSTAR_guest_end;
763
  lev->l.guest_sleep              = EDFSTAR_guest_sleep;
764
 
765
  /* fill the EDFSTAR descriptor part */
766
  for(i=0; i<MAX_PROC; i++) {
767
    lev->period[i]         = 0;
768
    lev->deadline_timer[i] = -1;
769
    lev->flag[i]           = 0;
770
    lev->dline_miss[i]     = 0;
771
    lev->wcet_miss[i]      = 0;
772
    lev->nact[i]           = 0;
773
  }
774
 
775
  iq_init(&lev->ready, NULL, IQUEUE_NO_PRIORITY);
776
  lev->activated = NIL;
777
 
778
  lev->budget = budget;
779
  lev->scheduling_level = master;
780
 
781
  return l;
782
}
783
 
784
int EDFSTAR_get_dline_miss(PID p)
785
{
786
  LEVEL l = proc_table[p].task_level;
787
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
788
  if (lev->l.level_code    == EDFSTAR_LEVEL_CODE &&
789
      lev->l.level_version == EDFSTAR_LEVEL_VERSION)
790
    return lev->dline_miss[p];
791
  else
792
    return -1;
793
}
794
 
795
int EDFSTAR_get_wcet_miss(PID p)
796
{
797
  LEVEL l = proc_table[p].task_level;
798
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
799
  if (lev->l.level_code    == EDFSTAR_LEVEL_CODE &&
800
      lev->l.level_version == EDFSTAR_LEVEL_VERSION)
801
    return lev->wcet_miss[p];
802
  else
803
    return -1;
804
}
805
 
806
int EDFSTAR_get_nact(PID p)
807
{
808
  LEVEL l = proc_table[p].task_level;
809
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
810
  if (lev->l.level_code    == EDFSTAR_LEVEL_CODE &&
811
      lev->l.level_version == EDFSTAR_LEVEL_VERSION)
812
    return lev->nact[p];
813
  else
814
    return -1;
815
}
816
 
817
int EDFSTAR_reset_dline_miss(PID p)
818
{
819
  LEVEL l = proc_table[p].task_level;
820
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
821
  if (lev->l.level_code    == EDFSTAR_LEVEL_CODE &&
822
      lev->l.level_version == EDFSTAR_LEVEL_VERSION)
823
  {
824
    lev->dline_miss[p] = 0;
825
    return 0;
826
  }
827
  else
828
    return -1;
829
}
830
 
831
int EDFSTAR_reset_wcet_miss(PID p)
832
{
833
  LEVEL l = proc_table[p].task_level;
834
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
835
  if (lev->l.level_code    == EDFSTAR_LEVEL_CODE &&
836
      lev->l.level_version == EDFSTAR_LEVEL_VERSION)
837
  {
838
    lev->wcet_miss[p] = 0;
839
    return 0;
840
  }
841
  else
842
    return -1;
843
}
844