Subversion Repositories shark

Rev

Rev 1100 | Rev 1123 | 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: rmstar.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 "rmstar.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 into the kernel */
1089 pj 59
 
60
/* for BUDGET_TASK_MODEL */
61
#include "cbsstar.h"
62
 
63
/*
64
 * DEBUG stuffs begin
65
 */
66
 
67
//#define RMSTAR_DEBUG
68
 
69
#ifdef RMSTAR_DEBUF
70
 
71
static __inline__ fake_printf(char *fmt, ...) {}
72
 
73
#define rmstar_printf fake_printf
74
#define rmstar_printf2 fake_printf
75
#define rmstar_printf3 fake_printf
76
 
77
//#define rmstar_printf kern_printf
78
//#define rmstar_printf2 kern_printf
79
//#define rmstar_printf3 kern_printf
80
#endif
81
 
82
/*
83
 * DEBUG stuffs end
84
 */
85
 
86
/* Status used in the level */
87
#define RMSTAR_READY         MODULE_STATUS_BASE    /* - Ready status        */
88
#define RMSTAR_IDLE          MODULE_STATUS_BASE+4  /* to wait the deadline  */
89
 
90
/* flags */
91
#define RMSTAR_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
} RMSTAR_level_des;
122
 
123
static void RMSTAR_check_preemption(RMSTAR_level_des *lev)
124
{
125
  PID first;
126
 
127
#ifdef RMSTAR_DEBUG
128
  rmstar_printf("(E:chk)");
129
#endif
130
 
1116 pj 131
  if ((first = iq_query_first(&lev->ready)) != lev->activated) {
1089 pj 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 RMSTAR_timer_deadline(void *par);
149
 
150
static void RMSTAR_internal_activate(RMSTAR_level_des *lev, PID p)
151
{
152
  struct timespec temp;
153
 
154
#ifdef RMSTAR_DEBUG
155
  rmstar_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 = RMSTAR_READY;
166
  iq_priority_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
  RMSTAR_check_preemption(lev);
173
}
174
 
175
static char *RMSTAR_status_to_a(WORD status)
176
{
177
  if (status < MODULE_STATUS_BASE)
178
    return status_to_a(status);
179
 
180
  switch (status) {
181
    case RMSTAR_READY    : return "RMSTAR_Ready";
182
    case RMSTAR_IDLE     : return "RMSTAR_Idle";
183
    default               : return "RMSTAR_Unknown";
184
  }
185
}
186
 
187
static void RMSTAR_timer_deadline(void *par)
188
{
189
  PID p = (PID) par;
190
  RMSTAR_level_des *lev;
191
 
192
#ifdef RMSTAR_DEBUG
193
//  rmstar_printf("(E:tdl ");
194
#endif
195
 
196
  lev = (RMSTAR_level_des *)level_table[proc_table[p].task_level];
197
 
198
  switch (proc_table[p].status) {
199
    case RMSTAR_IDLE:
200
#ifdef RMSTAR_DEBUG
201
//      rmstar_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
      RMSTAR_internal_activate(lev,p);
207
 
208
      event_need_reschedule();
209
      break;
210
 
211
    default:
212
#ifdef RMSTAR_DEBUG
213
//      rmstar_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
                                           RMSTAR_timer_deadline,
228
                                           (void *)p);
229
 
230
#ifdef RMSTAR_DEBUG
231
//  rmstar_printf(")");
232
#endif
233
}
234
 
235
static void RMSTAR_timer_guest_deadline(void *par)
236
{
237
  PID p = (PID) par;
238
 
239
#ifdef RMSTAR_DEBUG
240
  rmstar_printf("(E:gdl)");
241
#endif
242
 
243
  kern_raise(XDEADLINE_MISS,p);
244
}
245
 
246
static int RMSTAR_level_accept_task_model(LEVEL l, TASK_MODEL *m)
247
{
248
#ifdef RMSTAR_DEBUG
249
  rmstar_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 RMSTAR_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
263
{
264
#ifdef RMSTAR_DEBUG
265
  rmstar_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 RMSTAR_level_status(LEVEL l)
284
{
285
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
1116 pj 286
  PID p = iq_query_first(&lev->ready);
1089 pj 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
                  RMSTAR_status_to_a(proc_table[p].status));
1116 pj 307
      p = iq_query_next(p, &lev->ready);
1089 pj 308
    }
309
  }
310
 
311
  for (p=0; p<MAX_PROC; p++)
312
    if (proc_table[p].task_level == l
313
        && proc_table[p].status != RMSTAR_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
                  RMSTAR_status_to_a(proc_table[p].status));
325
    }
326
}
327
 
328
/* The scheduler only gets the first task in the queue */
329
static PID RMSTAR_level_scheduler(LEVEL l)
330
{
331
  //RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
332
 
333
  return NIL;
334
}
335
 
336
static int RMSTAR_task_create(LEVEL l, PID p, TASK_MODEL *m)
337
{
338
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
339
 
340
  /* if the RMSTAR_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 RMSTAR_DEBUG
345
  rmstar_printf("(E:tcr)");
346
#endif
347
 
348
  lev->period[p] = h->mit;
349
  *iq_query_priority(p, &lev->ready) = h->mit;
350
 
351
  lev->flag[p] = 0;
352
  lev->deadline_timer[p] = -1;
353
  lev->dline_miss[p]     = 0;
354
  lev->wcet_miss[p]      = 0;
355
  lev->nact[p]           = 0;
356
 
357
  /* Enable wcet check */
358
  proc_table[p].avail_time = h->wcet;
359
  proc_table[p].wcet       = h->wcet;
360
  proc_table[p].control |= CONTROL_CAP;
361
 
362
  return 0; /* OK, also if the task cannot be guaranteed... */
363
}
364
 
365
static void RMSTAR_task_detach(LEVEL l, PID p)
366
{
367
#ifdef RMSTAR_DEBUG
368
  rmstar_printf2("(E:tdt)");
369
#endif
370
}
371
 
372
static int RMSTAR_task_eligible(LEVEL l, PID p)
373
{
374
#ifdef RMSTAR_DEBUG
375
  rmstar_printf2("(E:eli)");
376
#endif
377
 
378
  return 0; /* if the task p is chosen, it is always eligible */
379
}
380
 
381
static void RMSTAR_task_dispatch(LEVEL l, PID p, int nostop)
382
{
383
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
384
 
385
#ifdef RMSTAR_DEBUG
386
  rmstar_printf("(E:dis)");
387
 
388
  rmstar_printf3("(%d %d)",
389
                  iq_query_timespec(p, &lev->ready)->tv_nsec/1000000,
390
                  schedule_time.tv_nsec/1000000);
391
#endif
392
 
393
  level_table[ lev->scheduling_level ]->
394
    guest_dispatch(lev->scheduling_level,p,nostop);
395
}
396
 
397
static void RMSTAR_task_epilogue(LEVEL l, PID p)
398
{
399
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
400
 
401
#ifdef RMSTAR_DEBUG
402
  rmstar_printf("(E:epi ");
403
#endif
404
 
405
  /* check if the wcet is finished... */
406
  if (proc_table[p].avail_time <= 0 && proc_table[p].control&CONTROL_CAP) {
407
    /* wcet finished: disable wcet event and count wcet miss */
408
#ifdef RMSTAR_DEBUG
409
    rmstar_printf2("W%d",p);
410
#endif
411
    proc_table[p].control &= ~CONTROL_CAP;
412
    lev->wcet_miss[p]++;
413
  }
414
#ifdef RMSTAR_DEBUG
415
  rmstar_printf(")");
416
#endif
417
 
418
  level_table[ lev->scheduling_level ]->
419
    guest_epilogue(lev->scheduling_level,p);
420
 
421
  proc_table[p].status = RMSTAR_READY;
422
}
423
 
424
static void RMSTAR_task_activate(LEVEL l, PID p)
425
{
426
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
427
 
428
#ifdef RMSTAR_DEBUG
429
  rmstar_printf("(E:act)");
430
#endif
431
 
432
  /* Test if we are trying to activate a non sleeping task    */
433
  /* save activation (only if needed... */
434
  if (proc_table[p].status != SLEEP) {
435
    /* a periodic task cannot be activated when it is already active */
436
    kern_raise(XACTIVATION,p);
437
    return;
438
  }
439
 
440
  ll_gettime(TIME_EXACT, &proc_table[p].request_time);
441
 
442
  RMSTAR_internal_activate(lev,p);
443
 
444
  /* Set the deadline timer */
445
  lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
446
                                           RMSTAR_timer_deadline,
447
                                           (void *)p);
448
 
449
}
450
 
451
static void RMSTAR_task_insert(LEVEL l, PID p)
452
{
453
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
454
 
455
#ifdef RMSTAR_DEBUG
456
  rmstar_printf("(E:ins)");
457
#endif
458
 
459
  /* Insert task in the correct position */
460
  proc_table[p].status = RMSTAR_READY;
461
  iq_priority_insert(p,&lev->ready);
462
 
463
  /* and check for preemption! */
464
  RMSTAR_check_preemption(lev);
465
}
466
 
467
static void RMSTAR_task_extract(LEVEL l, PID p)
468
{
469
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
470
 
471
#ifdef RMSTAR_DEBUG
472
  rmstar_printf("(E:ext)");
473
#endif
474
 
475
  /* the task is blocked on a synchronization primitive. we have to
476
     remove it from the master module -and- from the local queue! */
477
  iq_extract(p,&lev->ready);
478
 
479
  /* and finally, a preemption check! (it will also call guest_end) */
480
  RMSTAR_check_preemption(lev);
481
}
482
 
483
static void RMSTAR_task_endcycle(LEVEL l, PID p)
484
{
485
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
486
  struct timespec temp;
487
 
488
#ifdef RMSTAR_DEBUG
489
  rmstar_printf("(E:ecy ");
490
#endif
491
 
492
  /* we call guest_end directly here because the same task may
493
     be reinserted in the queue before calling the preemption check! */
494
  level_table[ lev->scheduling_level ]->
495
    guest_end(lev->scheduling_level,p);
496
  lev->activated = NIL;
497
 
498
  iq_extract(p,&lev->ready);
499
 
500
  /* we reset the capacity counters... */
501
  proc_table[p].avail_time = proc_table[p].wcet;
502
 
503
  if (lev->nact[p] > 0) {
504
#ifdef RMSTAR_DEBUG
505
    rmstar_printf2("E%d",p);
506
#endif
507
 
508
    /* Pending activation: reactivate the thread!!! */
509
    lev->nact[p]--;
510
 
511
    /* see also RMSTAR_timer_deadline */
512
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
513
 
514
    RMSTAR_internal_activate(lev,p);
515
 
516
    /* check if the deadline has already expired */
517
    temp = *iq_query_timespec(p, &lev->ready);
518
    if (TIMESPEC_A_LT_B(&temp, &schedule_time)) {
519
      /* count the deadline miss */
520
      lev->dline_miss[p]++;
521
      event_delete(lev->deadline_timer[p]);
522
    }
523
 
524
  }
525
  else {
526
#ifdef RMSTAR_DEBUG
527
    rmstar_printf("e%d",p);
528
#endif
529
 
530
    /* the task has terminated his job before it consume the wcet. All OK! */
531
    proc_table[p].status = RMSTAR_IDLE;
532
 
533
    /* and finally, a preemption check! */
534
    RMSTAR_check_preemption(lev);
535
 
536
    /* when the deadline timer fire, it recognize the situation and set
537
       correctly all the stuffs (like reactivation, request_time, etc... ) */
538
  }
539
#ifdef RMSTAR_DEBUG
540
  rmstar_printf(")");
541
#endif
542
}
543
 
544
static void RMSTAR_task_end(LEVEL l, PID p)
545
{
546
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
547
 
548
#ifdef RMSTAR_DEBUG
549
  rmstar_printf("(E:end)");
550
#endif
551
 
552
  iq_extract(p,&lev->ready);
553
 
554
  /* we finally put the task in the ready queue */
555
  proc_table[p].status = FREE;
556
 
1116 pj 557
  iq_insertfirst(p,&freedesc);
1089 pj 558
 
559
  if (lev->deadline_timer[p] != -1) {
560
    event_delete(lev->deadline_timer[p]);
561
  }
562
 
563
  /* and finally, a preemption check! (it will also call guest_end) */
564
  RMSTAR_check_preemption(lev);
565
}
566
 
567
static void RMSTAR_task_sleep(LEVEL l, PID p)
1100 pj 568
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 569
 
570
 
571
/* Guest Functions
572
   These functions manages a JOB_TASK_MODEL, that is used to put
573
   a guest task in the RMSTAR ready queue. */
574
 
575
static int RMSTAR_guest_create(LEVEL l, PID p, TASK_MODEL *m)
576
{
577
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
578
  JOB_TASK_MODEL *job = (JOB_TASK_MODEL *)m;
579
 
580
  /* if the RMSTAR_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] = RMSTAR_FLAG_NORAISEEXC;
592
  else
593
    lev->flag[p] = 0;
594
 
595
  lev->period[p] = job->period;
596
  *iq_query_priority(p, &lev->ready) = 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 RMSTAR_guest_detach(LEVEL l, PID p)
605
{
606
  /* the RMSTAR 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 RMSTAR_guest_dispatch(LEVEL l, PID p, int nostop)
612
{
613
  RMSTAR_level_des *lev = (RMSTAR_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 RMSTAR_guest_epilogue(LEVEL l, PID p)
620
{
621
  RMSTAR_level_des *lev = (RMSTAR_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 = RMSTAR_READY;
628
}
629
 
630
static void RMSTAR_guest_activate(LEVEL l, PID p)
631
{
632
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
633
 
634
  /* Insert task in the correct position */
635
  iq_priority_insert(p,&lev->ready);
636
  proc_table[p].status = RMSTAR_READY;
637
 
638
  /* check for preemption */
639
  RMSTAR_check_preemption(lev);
640
 
641
  /* Set the deadline timer */
642
  if (!(lev->flag[p] & RMSTAR_FLAG_NORAISEEXC))
643
    lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
644
                                             RMSTAR_timer_guest_deadline,
645
                                             (void *)p);
646
 
647
}
648
 
649
static void RMSTAR_guest_insert(LEVEL l, PID p)
650
{
651
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
652
 
653
  /* Insert task in the correct position */
654
  iq_priority_insert(p,&lev->ready);
655
  proc_table[p].status = RMSTAR_READY;
656
 
657
  /* and check for preemption! */
658
  RMSTAR_check_preemption(lev);
659
}
660
 
661
static void RMSTAR_guest_extract(LEVEL l, PID p)
662
{
663
  RMSTAR_level_des *lev = (RMSTAR_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
  RMSTAR_check_preemption(lev);
671
}
672
 
673
static void RMSTAR_guest_end(LEVEL l, PID p)
674
{
675
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
676
 
677
#ifdef RMSTAR_DEBUG
678
  //kern_printf("RMSTAR_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 RMSTAR_DEBUG
686
//    kern_printf("RMSTAR_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
  RMSTAR_check_preemption(lev);
694
}
695
 
696
static void RMSTAR_guest_endcycle(LEVEL l, PID p)
1100 pj 697
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 698
 
699
static void RMSTAR_guest_sleep(LEVEL l, PID p)
1100 pj 700
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 701
 
702
/* Registration functions */
703
 
704
/* Registration function:
705
    int flags                 the init flags ... see RMSTAR.h */
706
LEVEL RMSTAR_register_level(int budget, int master)
707
{
708
  LEVEL l;            /* the level that we register */
709
  RMSTAR_level_des *lev;  /* for readableness only */
710
  PID i;              /* a counter */
711
 
712
#ifdef RMSTAR_DEBUG
713
  printk("RMSTAR_register_level\n");
714
#endif
715
 
716
  /* request an entry in the level_table */
717
  l = level_alloc_descriptor();
718
 
719
#ifdef RMSTAR_DEBUG
720
  printk("    alloco descrittore %d %d\n",l,(int)sizeof(RMSTAR_level_des));
721
#endif
722
 
723
  /* alloc the space needed for the RMSTAR_level_des */
724
  lev = (RMSTAR_level_des *)kern_alloc(sizeof(RMSTAR_level_des));
725
 
726
#ifdef RMSTAR_DEBUG
727
  printk("    lev=%d\n",(int)lev);
728
#endif
729
 
730
  /* update the level_table with the new entry */
731
  level_table[l] = (level_des *)lev;
732
 
733
  /* fill the standard descriptor */
734
  strncpy(lev->l.level_name,  RMSTAR_LEVELNAME, MAX_LEVELNAME);
735
  lev->l.level_code               = RMSTAR_LEVEL_CODE;
736
  lev->l.level_version            = RMSTAR_LEVEL_VERSION;
737
 
738
  lev->l.level_accept_task_model  = RMSTAR_level_accept_task_model;
739
  lev->l.level_accept_guest_model = RMSTAR_level_accept_guest_model;
740
  lev->l.level_status             = RMSTAR_level_status;
741
  lev->l.level_scheduler          = RMSTAR_level_scheduler;
742
  lev->l.level_guarantee          = NULL;
743
  lev->l.task_create              = RMSTAR_task_create;
744
  lev->l.task_detach              = RMSTAR_task_detach;
745
  lev->l.task_eligible            = RMSTAR_task_eligible;
746
  lev->l.task_dispatch            = RMSTAR_task_dispatch;
747
  lev->l.task_epilogue            = RMSTAR_task_epilogue;
748
  lev->l.task_activate            = RMSTAR_task_activate;
749
  lev->l.task_insert              = RMSTAR_task_insert;
750
  lev->l.task_extract             = RMSTAR_task_extract;
751
  lev->l.task_endcycle            = RMSTAR_task_endcycle;
752
  lev->l.task_end                 = RMSTAR_task_end;
753
  lev->l.task_sleep               = RMSTAR_task_sleep;
754
 
755
  lev->l.guest_create             = RMSTAR_guest_create;
756
  lev->l.guest_detach             = RMSTAR_guest_detach;
757
  lev->l.guest_dispatch           = RMSTAR_guest_dispatch;
758
  lev->l.guest_epilogue           = RMSTAR_guest_epilogue;
759
  lev->l.guest_activate           = RMSTAR_guest_activate;
760
  lev->l.guest_insert             = RMSTAR_guest_insert;
761
  lev->l.guest_extract            = RMSTAR_guest_extract;
762
  lev->l.guest_endcycle           = RMSTAR_guest_endcycle;
763
  lev->l.guest_end                = RMSTAR_guest_end;
764
  lev->l.guest_sleep              = RMSTAR_guest_sleep;
765
 
766
  /* fill the RMSTAR descriptor part */
767
  for(i=0; i<MAX_PROC; i++) {
768
    lev->period[i]         = 0;
769
    lev->deadline_timer[i] = -1;
770
    lev->flag[i]           = 0;
771
    lev->dline_miss[i]     = 0;
772
    lev->wcet_miss[i]      = 0;
773
    lev->nact[i]           = 0;
774
  }
775
 
776
  iq_init(&lev->ready, NULL, 0);
777
  lev->activated = NIL;
778
 
779
  lev->budget = budget;
780
  lev->scheduling_level = master;
781
 
782
  return l;
783
}
784
 
785
int RMSTAR_get_dline_miss(PID p)
786
{
787
  LEVEL l = proc_table[p].task_level;
788
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
789
  if (lev->l.level_code    == RMSTAR_LEVEL_CODE &&
790
      lev->l.level_version == RMSTAR_LEVEL_VERSION)
791
    return lev->dline_miss[p];
792
  else
793
    return -1;
794
}
795
 
796
int RMSTAR_get_wcet_miss(PID p)
797
{
798
  LEVEL l = proc_table[p].task_level;
799
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
800
  if (lev->l.level_code    == RMSTAR_LEVEL_CODE &&
801
      lev->l.level_version == RMSTAR_LEVEL_VERSION)
802
    return lev->wcet_miss[p];
803
  else
804
    return -1;
805
}
806
 
807
int RMSTAR_get_nact(PID p)
808
{
809
  LEVEL l = proc_table[p].task_level;
810
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
811
  if (lev->l.level_code    == RMSTAR_LEVEL_CODE &&
812
      lev->l.level_version == RMSTAR_LEVEL_VERSION)
813
    return lev->nact[p];
814
  else
815
    return -1;
816
}
817
 
818
int RMSTAR_reset_dline_miss(PID p)
819
{
820
  LEVEL l = proc_table[p].task_level;
821
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
822
  if (lev->l.level_code    == RMSTAR_LEVEL_CODE &&
823
      lev->l.level_version == RMSTAR_LEVEL_VERSION)
824
  {
825
    lev->dline_miss[p] = 0;
826
    return 0;
827
  }
828
  else
829
    return -1;
830
}
831
 
832
int RMSTAR_reset_wcet_miss(PID p)
833
{
834
  LEVEL l = proc_table[p].task_level;
835
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
836
  if (lev->l.level_code    == RMSTAR_LEVEL_CODE &&
837
      lev->l.level_version == RMSTAR_LEVEL_VERSION)
838
  {
839
    lev->wcet_miss[p] = 0;
840
    return 0;
841
  }
842
  else
843
    return -1;
844
}
845