Subversion Repositories shark

Rev

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