Subversion Repositories shark

Rev

Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
11
 *   Luca Abeni          <luca@gandalf.sssup.it>
12
 *   (see the web pages for full authors list)
13
 *
14
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
15
 *
16
 * http://www.sssup.it
17
 * http://retis.sssup.it
18
 * http://shark.sssup.it
19
 */
20
 
21
/**
22
 ------------
14 pj 23
 CVS :        $Id: ps.c,v 1.2 2002-10-28 07:55:55 pj Exp $
2 pj 24
 
25
 File:        $File$
14 pj 26
 Revision:    $Revision: 1.2 $
27
 Last update: $Date: 2002-10-28 07:55:55 $
2 pj 28
 ------------
29
 
30
 This file contains the aperiodic server PS (Polling Server)
31
 
32
 when scheduling in background  the flags field has the PS_BACKGROUND bit set
33
 
34
 when scheduling a task because it is pointed by another task via shadows,
35
 the task have to be extracted from the wait queue or the master level. To
36
 check this we have to look at the activated field; it is != NIL if a task
37
 is inserted into the master level. Only a task at a time can be inserted
38
 into the master level.
39
 
40
 The capacity of the server must be updated
41
 - when scheduling a task normally
42
 - when scheduling a task because it is pointed by a shadow
43
 but not when scheduling in background.
44
 
45
 When a task is extracted from the system no scheduling has to be done
46
 until the task reenter into the system. to implement this, when a task
47
 is extracted we block the background scheduling (the scheduling with the
48
 master level is already blocked because the activated field is not
49
 reset to NIL) using the PS_BACKGROUNDBLOCK bit.
50
 
51
 nact[p] is -1 if the task set the activations to SKIP, >= 0 otherwise
52
 
53
 Note that if the period event fires and there aren't any task to schedule,
54
 the server capacity is set to 0. This is correct, but there is a subtle
55
 variant: the server capacity may be set to 0 later because if at the
56
 period end the running task have priority > than the server, the capacity
57
 may be set to zero the first time the server become the highest priority
58
 running task and there aren't task to serve. The second implementation
59
 is more efficient but more complicated, because normally we don't know the
60
 priority of the running task.
61
 
62
 An implementation can be done in this way: when there are not task to
63
 schedule, we does not set the lev->activated field to nil, but to a "dummy"
64
 task that is inserted into the master level queue.
65
 When the master level scheduler try to schedule the "dummy" task (this is
66
 the situation in witch there are not task to schedule and the PS is the
67
 task with greater priority), it calls the PS_task_eligible, that set the
68
 server capacity to 0, remove the dummy task from the queue with a guest_end
69
 and ask to reschedule.
70
 
71
 Because this implementation is more complex than the first, I don't
72
 implement it... see (*), near line 169, 497 and 524
73
 
74
 
75
 Read PS.h for further details.
76
 
77
**/
78
 
79
/*
80
 * Copyright (C) 2000 Paolo Gai
81
 *
82
 * This program is free software; you can redistribute it and/or modify
83
 * it under the terms of the GNU General Public License as published by
84
 * the Free Software Foundation; either version 2 of the License, or
85
 * (at your option) any later version.
86
 *
87
 * This program is distributed in the hope that it will be useful,
88
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
89
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
90
 * GNU General Public License for more details.
91
 *
92
 * You should have received a copy of the GNU General Public License
93
 * along with this program; if not, write to the Free Software
94
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
95
 *
96
 */
97
 
98
 
99
#include <modules/ps.h>
100
#include <ll/stdio.h>
101
#include <ll/string.h>
102
#include <kernel/model.h>
103
#include <kernel/descr.h>
104
#include <kernel/var.h>
105
#include <kernel/func.h>
106
 
107
/*+ Status used in the level +*/
108
#define PS_WAIT          APER_STATUS_BASE    /*+ waiting the service   +*/
109
 
110
/*+ the level redefinition for the Total Bandwidth Server level +*/
111
typedef struct {
112
  level_des l;     /*+ the standard level descriptor          +*/
113
 
114
  /* The wcet are stored in the task descriptor's priority
115
     field, so no other fields are needed                      */
116
 
117
  int nact[MAX_PROC]; /*+ number of pending activations       +*/
118
 
119
  struct timespec lastdline; /*+ the last deadline assigned to
120
                                 a PS task                    +*/
121
 
122
  int Cs;          /*+ server capacity                        +*/
123
  int availCs;     /*+ server avail time                      +*/
124
 
125
  QQUEUE wait;      /*+ the wait queue of the PS              +*/
126
  PID activated;   /*+ the task inserted in another queue     +*/
127
 
128
  int flags;       /*+ the init flags...                      +*/
129
 
130
  bandwidth_t U;   /*+ the used bandwidth by the server       +*/
131
  int period;
132
 
133
  LEVEL scheduling_level;
134
 
135
} PS_level_des;
136
 
137
/* This static function activates the task pointed by lev->activated) */
138
static __inline__ void PS_activation(PS_level_des *lev)
139
{
140
    PID p;                     /* for readableness    */
141
    JOB_TASK_MODEL j;          /* the guest model     */
142
    LEVEL m;                   /* the master level... only for readableness*/
143
 
144
    p = lev->activated;
145
    m = lev->scheduling_level;
146
    job_task_default_model(j,lev->lastdline);
147
    job_task_def_period(j,lev->period);
148
    level_table[m]->guest_create(m,p,(TASK_MODEL *)&j);
149
    level_table[m]->guest_activate(m,p);
150
//    kern_printf("(%d %d)",lev->lastdline.tv_sec,lev->lastdline.tv_nsec);
151
}
152
 
153
static void PS_deadline_timer(void *a)
154
{
155
  PS_level_des *lev = (PS_level_des *)(level_table[(LEVEL)a]);
156
 
157
  ADDUSEC2TIMESPEC(lev->period, &lev->lastdline);
158
 
159
//  kern_printf("(%d:%d %d)",lev->lastdline.tv_sec,lev->lastdline.tv_nsec, lev->period);
160
  if (lev->availCs >= 0)
161
    lev->availCs = lev->Cs;
162
  else
163
    lev->availCs += lev->Cs;
164
 
165
  /* availCs may be <0 because a task executed via a shadow fo many time
166
     lev->activated == NIL only if the prec task was finished and there
167
     was not any other task to be put in the ready queue
168
     ... we are now activating the next task */
169
  if (lev->availCs > 0 && lev->activated == NIL) {
170
      if (qq_queryfirst(&lev->wait) != NIL) {
171
        lev->activated = qq_getfirst(&lev->wait);
172
        PS_activation(lev);
173
        event_need_reschedule();
174
      }
175
      else
176
        lev->availCs = 0; /* see note (*) at the begin of the file */
177
  }
178
 
179
  kern_event_post(&lev->lastdline, PS_deadline_timer, a);
180
//  kern_printf("!");
181
}
182
 
183
static char *PS_status_to_a(WORD status)
184
{
185
  if (status < MODULE_STATUS_BASE)
186
    return status_to_a(status);
187
 
188
  switch (status) {
189
    case PS_WAIT         : return "PS_Wait";
190
    default              : return "PS_Unknown";
191
  }
192
}
193
 
194
 
195
static int PS_level_accept_task_model(LEVEL l, TASK_MODEL *m)
196
{
197
  if (m->pclass == SOFT_PCLASS || m->pclass == (SOFT_PCLASS | l) ) {
198
    SOFT_TASK_MODEL *s = (SOFT_TASK_MODEL *)m;
199
 
200
    if (s->periodicity == APERIODIC)
201
      return 0;
202
  }
203
  return -1;
204
}
205
 
206
static int PS_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
207
{
208
  return -1;
209
}
210
 
211
static char *onoff(int i)
212
{
213
  if (i)
214
    return "On ";
215
  else
216
    return "Off";
217
}
218
 
219
static void PS_level_status(LEVEL l)
220
{
221
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
222
  PID p = qq_queryfirst(&lev->wait);
223
 
224
  kern_printf("On-line guarantee : %s\n",
225
            onoff(lev->flags & PS_ENABLE_GUARANTEE_EDF ||
226
                  lev->flags & PS_ENABLE_GUARANTEE_RM  ));
227
  kern_printf("Used Bandwidth    : %u/%u\n",
228
            lev->U, MAX_BANDWIDTH);
229
 
230
  if (lev->activated != -1)
231
    kern_printf("Activated: Pid: %2d Name: %10s Dl: %ld.%ld Nact: %d Stat: %s\n",
232
              lev->activated,
233
              proc_table[lev->activated].name,
234
              proc_table[lev->activated].timespec_priority.tv_sec,
235
              proc_table[lev->activated].timespec_priority.tv_nsec,
236
              lev->nact[lev->activated],
237
              PS_status_to_a(proc_table[lev->activated].status));
238
 
239
  while (p != NIL) {
240
    kern_printf("Pid: %2d Name: %10s Stat: %s\n",
241
              p,
242
              proc_table[p].name,
243
              PS_status_to_a(proc_table[p].status));
244
    p = proc_table[p].next;
245
  }
246
}
247
 
248
static PID PS_level_scheduler(LEVEL l)
249
{
250
  /* the PS don't schedule anything...
251
     it's an EDF level or similar that do it! */
252
  return NIL;
253
}
254
 
255
static PID PS_level_schedulerbackground(LEVEL l)
256
{
257
  /* the PS catch the background time to exec aperiodic activities */
258
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
259
 
260
  lev->flags |= PS_BACKGROUND;
261
 
262
  if (lev->flags & PS_BACKGROUND_BLOCK)
263
    return NIL;
264
  else
265
    return qq_queryfirst(&lev->wait);
266
}
267
 
268
/* The on-line guarantee is enabled only if the appropriate flag is set... */
269
static int PS_level_guaranteeEDF(LEVEL l, bandwidth_t *freebandwidth)
270
{
271
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
272
 
273
  if (*freebandwidth >= lev->U) {
274
    *freebandwidth -= lev->U;
275
    return 1;
276
  }
277
  else
278
    return 0;
279
}
280
 
281
static int PS_level_guaranteeRM(LEVEL l, bandwidth_t *freebandwidth)
282
{
283
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
284
 
285
  if (*freebandwidth > lev->U + RM_MINFREEBANDWIDTH) {
286
    *freebandwidth -= lev->U;
287
    return 1;
288
  }
289
  else
290
    return 0;
291
}
292
 
293
static int PS_task_create(LEVEL l, PID p, TASK_MODEL *m)
294
{
295
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
296
 
297
  /* if the PS_task_create is called, then the pclass must be a
298
     valid pclass. */
299
  SOFT_TASK_MODEL *s = (SOFT_TASK_MODEL *)m;
300
 
301
  if (s->arrivals == SAVE_ARRIVALS)
302
    lev->nact[p] = 0;
303
  else
304
    lev->nact[p] = -1;
305
 
306
  return 0; /* OK, also if the task cannot be guaranteed... */
307
}
308
 
309
static void PS_task_detach(LEVEL l, PID p)
310
{
311
  /* the PS level doesn't introduce any dinamic allocated new field. */
312
}
313
 
314
static int PS_task_eligible(LEVEL l, PID p)
315
{
316
  return 0; /* if the task p is chosen, it is always eligible */
317
}
318
 
319
#ifdef __TEST1__
320
extern int testactive;
321
extern struct timespec s_stime[];
322
extern TIME s_curr[];
323
extern TIME s_PID[];
324
extern int useds;
325
#endif
326
 
327
static void PS_task_dispatch(LEVEL l, PID p, int nostop)
328
{
329
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
330
  struct timespec ty;
331
 
332
//  if (nostop) kern_printf("NOSTOP!!!!!!!!!!!!");
333
  /* there is at least one task ready inserted in an EDF or similar
334
     level note that we can't check the status because the scheduler set it
335
     to exe before calling task_dispatch. we have to check
336
     lev->activated != p instead */
337
  if (lev->activated != p) {
338
    qq_extract(p, &lev->wait);
339
    //kern_printf("#%d#",p);
340
  }
341
  else {
342
    //if (nostop) kern_printf("(gd status=%d)",proc_table[p].status);
343
    level_table[ lev->scheduling_level ]->
344
      guest_dispatch(lev->scheduling_level,p,nostop);
345
  }
346
 
347
  /* set the capacity timer */
348
  if (!nostop) {
349
    TIMESPEC_ASSIGN(&ty, &schedule_time);
350
    ADDUSEC2TIMESPEC(lev->availCs,&ty);
351
    cap_timer = kern_event_post(&ty, capacity_timer, NULL);
352
  }
353
 
354
//  kern_printf("(disp %d %d)",ty.tv_sec, ty.tv_nsec);
355
 
356
  #ifdef __TEST1__
357
  if (testactive)
358
  {
359
    TIMESPEC_ASSIGN(&s_stime[useds], &schedule_time);
360
    s_curr[useds] = proc_table[p].avail_time;
361
    s_PID[useds]  = p;
362
    useds++;
363
  }
364
  #endif
365
}
366
 
367
static void PS_task_epilogue(LEVEL l, PID p)
368
{
369
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
370
  struct timespec ty;
371
  TIME tx;
372
 
373
  /* update the server capacity */
374
  if (lev->flags & PS_BACKGROUND)
375
    lev->flags &= ~PS_BACKGROUND;
376
  else {
377
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
378
    tx = TIMESPEC2USEC(&ty);
379
    lev->availCs -= tx;
380
  }
381
 
382
//  kern_printf("(epil %d %d)",lev->availCs, proc_table[p].avail_time);
383
 
384
  /* check if the server capacity is finished... */
385
  if (lev->availCs < 0) {
386
//    kern_printf("(epil Cs%d %d:%d act%d p%d)",
387
//              lev->availCs,proc_table[p].timespec_priority.tv_sec,
388
//              proc_table[p].timespec_priority.tv_nsec,
389
//              lev->activated,p);
390
    /* the server slice has finished... do the task_end!!!
391
       a first version of the module used the task_endcycle, but it was
392
       not conceptually correct because the task didn't stop because it
393
       finished all the work but because the server didn't have budget!
394
       So, if the task_endcycle is called, the task remain into the
395
       master level, and we can't wake him up if, for example, another
396
       task point the shadow to it!!!*/
397
    if (lev->activated == p)
398
      level_table[ lev->scheduling_level ]->
399
        guest_end(lev->scheduling_level,p);
400
    qq_insertfirst(p, &lev->wait);
401
    proc_table[p].status = PS_WAIT;
402
    lev->activated = NIL;
403
  }
404
  else
405
    /* the task has been preempted. it returns into the ready queue or to the
406
       wait queue by calling the guest_epilogue... */
407
    if (lev->activated == p) {//kern_printf("Û1");
408
      level_table[ lev->scheduling_level ]->
409
        guest_epilogue(lev->scheduling_level,p);
410
    } else { //kern_printf("Û2");
411
      qq_insertfirst(p, &lev->wait);
412
      proc_table[p].status = PS_WAIT;
413
    }
414
}
415
 
416
static void PS_task_activate(LEVEL l, PID p)
417
{
418
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
419
 
420
  if (lev->activated == p || proc_table[p].status == PS_WAIT) {
421
    if (lev->nact[p] != -1)
422
      lev->nact[p]++;
423
  }
424
  else if (proc_table[p].status == SLEEP) {
425
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
426
 
427
    if (lev->activated == NIL && lev->availCs > 0) {
428
      lev->activated = p;
429
      PS_activation(lev);
430
    }
431
    else {
432
      qq_insertlast(p, &lev->wait);
433
      proc_table[p].status = PS_WAIT;
434
    }
435
  }
436
  else
437
  {  kern_printf("PS_REJ%d %d %d %d ",p, proc_table[p].status, lev->activated, lev->wait.first);
438
     return; }
439
 
440
}
441
 
442
static void PS_task_insert(LEVEL l, PID p)
443
{
444
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
445
 
446
  lev->flags &= ~PS_BACKGROUND_BLOCK;
447
 
448
  lev->activated = -1;
449
 
450
  /* when we reinsert the task into the system, the server capacity
451
     is always 0 because nobody executes with the PS before... */
452
  qq_insertfirst(p, &lev->wait);
453
  proc_table[p].status = PS_WAIT;
454
}
455
 
456
static void PS_task_extract(LEVEL l, PID p)
457
{
458
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
459
 
460
  /* update the server capacity */
461
  lev->availCs = 0;
462
 
463
  lev->flags |= PS_BACKGROUND_BLOCK;
464
 
465
  if (lev->activated == p)
466
    level_table[ lev->scheduling_level ]->
467
      guest_end(lev->scheduling_level,p);
468
}
469
 
470
static void PS_task_endcycle(LEVEL l, PID p)
471
{
472
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
473
  struct timespec ty;
474
  TIME tx;
475
 
476
  /* update the server capacity */
477
  if (lev->flags & PS_BACKGROUND)
478
    lev->flags &= ~PS_BACKGROUND;
479
  else {
480
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
481
    tx = TIMESPEC2USEC(&ty);
482
    lev->availCs -= tx;
483
  }
484
 
485
  if (lev->activated == p)
486
    level_table[ lev->scheduling_level ]->
487
      guest_end(lev->scheduling_level,p);
488
  else
489
    qq_extract(p, &lev->wait);
490
 
491
  if (lev->nact[p] > 0)
492
  {
493
    lev->nact[p]--;
494
    qq_insertlast(p, &lev->wait);
495
    proc_table[p].status = PS_WAIT;
496
  }
497
  else
498
    proc_table[p].status = SLEEP;
499
 
500
  lev->activated = qq_getfirst(&lev->wait);
501
  if (lev->activated == NIL)
502
    lev->availCs = 0; /* see note (*) at the begin of the file */
503
  else
504
    PS_activation(lev);
505
}
506
 
507
static void PS_task_end(LEVEL l, PID p)
508
{
509
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
510
  struct timespec ty;
511
  TIME tx;
512
 
513
  /* update the server capacity */
514
  if (lev->flags & PS_BACKGROUND)
515
    lev->flags &= ~PS_BACKGROUND;
516
  else {
517
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
518
    tx = TIMESPEC2USEC(&ty);
519
    lev->availCs -= tx;
520
  }
521
 
522
  if (lev->activated == p)
523
    level_table[ lev->scheduling_level ]->
524
      guest_end(lev->scheduling_level,p);
525
 
526
  proc_table[p].status = FREE;
527
  q_insertfirst(p,&freedesc);
528
 
529
  lev->activated = qq_getfirst(&lev->wait);
530
  if (lev->activated == NIL)
531
    lev->availCs = 0; /* see note (*) at the begin of the file */
532
  else
533
    PS_activation(lev);
534
}
535
 
536
static void PS_task_sleep(LEVEL l, PID p)
537
{
538
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
539
  struct timespec ty;
540
  TIME tx;
541
 
542
  /* update the server capacity */
543
  if (lev->flags & PS_BACKGROUND)
544
    lev->flags &= ~PS_BACKGROUND;
545
  else {
546
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
547
    tx = TIMESPEC2USEC(&ty);
548
    lev->availCs -= tx;
549
  }
550
 
551
  if (lev->nact[p] >= 0) lev->nact[p] = 0;
552
 
553
  if (lev->activated == p)
554
    level_table[ lev->scheduling_level ]->
555
      guest_end(lev->scheduling_level,p);
556
  else
557
    qq_extract(p, &lev->wait);
558
 
559
  proc_table[p].status = SLEEP;
560
 
561
  lev->activated = qq_getfirst(&lev->wait);
562
  if (lev->activated == NIL)
563
    lev->availCs = 0; /* see note (*) at the begin of the file */
564
  else
565
    PS_activation(lev);
566
}
567
static void PS_task_delay(LEVEL l, PID p, TIME usdelay)
568
{
569
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
570
  struct timespec ty;
571
  TIME tx;
572
 
573
  /* update the server capacity */
574
  if (lev->flags & PS_BACKGROUND)
575
    lev->flags &= ~PS_BACKGROUND;
576
  else {
577
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
578
    tx = TIMESPEC2USEC(&ty);
579
    lev->availCs -= tx;
580
  }
581
 
582
  /* I hope no delay when owning a mutex... */
583
  if (lev->activated == p)
584
    level_table[ lev->scheduling_level ]->
585
      guest_delay(lev->scheduling_level,p,usdelay);
586
}
587
 
588
 
589
static int PS_guest_create(LEVEL l, PID p, TASK_MODEL *m)
14 pj 590
{ kern_raise(XINVALID_GUEST,exec_shadow); return 0; }
2 pj 591
 
592
static void PS_guest_detach(LEVEL l, PID p)
14 pj 593
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 594
 
595
static void PS_guest_dispatch(LEVEL l, PID p, int nostop)
14 pj 596
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 597
 
598
static void PS_guest_epilogue(LEVEL l, PID p)
14 pj 599
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 600
 
601
static void PS_guest_activate(LEVEL l, PID p)
14 pj 602
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 603
 
604
static void PS_guest_insert(LEVEL l, PID p)
14 pj 605
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 606
 
607
static void PS_guest_extract(LEVEL l, PID p)
14 pj 608
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 609
 
610
static void PS_guest_endcycle(LEVEL l, PID p)
14 pj 611
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 612
 
613
static void PS_guest_end(LEVEL l, PID p)
14 pj 614
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 615
 
616
static void PS_guest_sleep(LEVEL l, PID p)
14 pj 617
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 618
 
619
static void PS_guest_delay(LEVEL l, PID p,DWORD tickdelay)
14 pj 620
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 621
 
622
 
623
 
624
 
625
/* Registration functions */
626
 
627
 
628
/*+ This init function install the PS deadline timer
629
    +*/
630
static void PS_dline_install(void *l)
631
{
632
  PS_level_des *lev = (PS_level_des *)(level_table[(LEVEL)l]);
633
 
634
  ll_gettime(TIME_EXACT,&lev->lastdline);
635
  ADDUSEC2TIMESPEC(lev->period, &lev->lastdline);
636
 
637
  kern_event_post(&lev->lastdline, PS_deadline_timer, l);
638
}
639
 
640
 
641
 
642
/*+ Registration function:
643
    int flags                 the init flags ... see PS.h +*/
644
void PS_register_level(int flags, LEVEL master, int Cs, int per)
645
{
646
  LEVEL l;            /* the level that we register */
647
  PS_level_des *lev;  /* for readableness only */
648
  PID i;              /* a counter */
649
 
650
  printk("PS_register_level\n");
651
 
652
  /* request an entry in the level_table */
653
  l = level_alloc_descriptor();
654
 
655
  printk("    alloco descrittore %d %d\n",l,(int)sizeof(PS_level_des));
656
 
657
  /* alloc the space needed for the PS_level_des */
658
  lev = (PS_level_des *)kern_alloc(sizeof(PS_level_des));
659
 
660
  printk("    lev=%d\n",(int)lev);
661
 
662
  /* update the level_table with the new entry */
663
  level_table[l] = (level_des *)lev;
664
 
665
  /* fill the standard descriptor */
666
  strncpy(lev->l.level_name,  PS_LEVELNAME, MAX_LEVELNAME);
667
  lev->l.level_code               = PS_LEVEL_CODE;
668
  lev->l.level_version            = PS_LEVEL_VERSION;
669
 
670
  lev->l.level_accept_task_model  = PS_level_accept_task_model;
671
  lev->l.level_accept_guest_model = PS_level_accept_guest_model;
672
  lev->l.level_status             = PS_level_status;
673
 
674
  if (flags & PS_ENABLE_BACKGROUND)
675
    lev->l.level_scheduler          = PS_level_schedulerbackground;
676
  else
677
    lev->l.level_scheduler          = PS_level_scheduler;
678
 
679
  if (flags & PS_ENABLE_GUARANTEE_EDF)
680
    lev->l.level_guarantee        = PS_level_guaranteeEDF;
681
  else if (flags & PS_ENABLE_GUARANTEE_RM)
682
    lev->l.level_guarantee        = PS_level_guaranteeRM;
683
  else
684
    lev->l.level_guarantee        = NULL;
685
 
686
  lev->l.task_create              = PS_task_create;
687
  lev->l.task_detach              = PS_task_detach;
688
  lev->l.task_eligible            = PS_task_eligible;
689
  lev->l.task_dispatch            = PS_task_dispatch;
690
  lev->l.task_epilogue            = PS_task_epilogue;
691
  lev->l.task_activate            = PS_task_activate;
692
  lev->l.task_insert              = PS_task_insert;
693
  lev->l.task_extract             = PS_task_extract;
694
  lev->l.task_endcycle            = PS_task_endcycle;
695
  lev->l.task_end                 = PS_task_end;
696
  lev->l.task_sleep               = PS_task_sleep;
697
  lev->l.task_delay               = PS_task_delay;
698
 
699
  lev->l.guest_create             = PS_guest_create;
700
  lev->l.guest_detach             = PS_guest_detach;
701
  lev->l.guest_dispatch           = PS_guest_dispatch;
702
  lev->l.guest_epilogue           = PS_guest_epilogue;
703
  lev->l.guest_activate           = PS_guest_activate;
704
  lev->l.guest_insert             = PS_guest_insert;
705
  lev->l.guest_extract            = PS_guest_extract;
706
  lev->l.guest_endcycle           = PS_guest_endcycle;
707
  lev->l.guest_end                = PS_guest_end;
708
  lev->l.guest_sleep              = PS_guest_sleep;
709
  lev->l.guest_delay              = PS_guest_delay;
710
 
711
  /* fill the PS descriptor part */
712
 
713
  for (i=0; i<MAX_PROC; i++)
714
     lev->nact[i] = -1;
715
 
716
  lev->Cs = Cs;
717
  lev->availCs = 0;
718
 
719
  lev->period = per;
720
 
721
  qq_init(&lev->wait);
722
  lev->activated = NIL;
723
 
724
  lev->U = (MAX_BANDWIDTH / per) * Cs;
725
 
726
  lev->scheduling_level = master;
727
 
728
  lev->flags = flags & 0x07;
729
 
730
  sys_atrunlevel(PS_dline_install,(void *) l, RUNLEVEL_INIT);
731
}
732
 
733
bandwidth_t PS_usedbandwidth(LEVEL l)
734
{
735
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
736
  if (lev->l.level_code    == PS_LEVEL_CODE &&
737
      lev->l.level_version == PS_LEVEL_VERSION)
738
    return lev->U;
739
  else
740
    return 0;
741
}
742