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: posix.c,v 1.2 2002-10-28 07:55:54 pj Exp $
2 pj 24
 
25
 File:        $File$
14 pj 26
 Revision:    $Revision: 1.2 $
27
 Last update: $Date: 2002-10-28 07:55:54 $
2 pj 28
 ------------
29
 
30
 This file contains the scheduling module compatible with POSIX
31
 specifications
32
 
33
 Read posix.h for further details.
34
 
35
 RR tasks have the CONTROL_CAP bit set
36
 
37
**/
38
 
39
/*
40
 * Copyright (C) 2000 Paolo Gai
41
 *
42
 * This program is free software; you can redistribute it and/or modify
43
 * it under the terms of the GNU General Public License as published by
44
 * the Free Software Foundation; either version 2 of the License, or
45
 * (at your option) any later version.
46
 *
47
 * This program is distributed in the hope that it will be useful,
48
 * but WITHOUT ANY WARR2ANTY; without even the implied waRR2anty of
49
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
50
 * GNU General Public License for more details.
51
 *
52
 * You should have received a copy of the GNU General Public License
53
 * along with this program; if not, write to the Free Software
54
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
55
 *
56
 */
57
 
58
 
59
#include <modules/posix.h>
60
#include <ll/stdio.h>
61
#include <ll/string.h>
62
#include <kernel/model.h>
63
#include <kernel/descr.h>
64
#include <kernel/var.h>
65
#include <kernel/func.h>
66
 
67
/*+ Status used in the level +*/
68
#define POSIX_READY   MODULE_STATUS_BASE
69
#define POSIX_DELAY   MODULE_STATUS_BASE+1
70
 
71
/*+ the level redefinition for the Round Robin level +*/
72
typedef struct {
73
  level_des l;          /*+ the standard level descriptor          +*/
74
 
75
  int nact[MAX_PROC];   /*+ number of pending activations          +*/
76
 
77
  QQUEUE *ready;        /*+ the ready queue array                  +*/
78
 
79
  int slice;            /*+ the level's time slice                 +*/
80
 
81
  struct multiboot_info *multiboot; /*+ used if the level have to insert
82
                                        the main task +*/
83
  int maxpriority;      /*+ the priority are from 0 to maxpriority
84
                            (i.e 0 to 31)                          +*/
85
 
86
  int yielding;         /*+ equal to 1 when a sched_yield is called +*/
87
 
88
} POSIX_level_des;
89
 
90
static char *POSIX_status_to_a(WORD status)
91
{
92
  if (status < MODULE_STATUS_BASE)
93
    return status_to_a(status);
94
 
95
  switch (status) {
96
    case POSIX_READY: return "POSIX_Ready";
97
    case POSIX_DELAY: return "POSIX_Delay";
98
    default         : return "POSIX_Unknown";
99
  }
100
}
101
 
102
/*+ this function is called when a task finish his delay +*/
103
static void POSIX_timer_delay(void *par)
104
{
105
  PID p = (PID) par;
106
  POSIX_level_des *lev;
107
 
108
  lev = (POSIX_level_des *)level_table[proc_table[p].task_level];
109
 
110
  proc_table[p].status = POSIX_READY;
111
  qq_insertlast(p,&lev->ready[proc_table[p].priority]);
112
 
113
  proc_table[p].delay_timer = NIL;  /* Paranoia */
114
 
115
//  kern_printf(" DELAY TIMER %d ", p);
116
 
117
  event_need_reschedule();
118
}
119
 
120
 
121
static int POSIX_level_accept_task_model(LEVEL l, TASK_MODEL *m)
122
{
123
  if (m->pclass == NRT_PCLASS || m->pclass == (NRT_PCLASS | l))
124
    return 0;
125
  else
126
    return -1;
127
}
128
 
129
static int POSIX_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
130
{
131
    return -1;
132
}
133
 
134
static void POSIX_level_status(LEVEL l)
135
{
136
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
137
  PID p;
138
 
139
  kern_printf("Slice: %d \n", lev->slice);
140
 
141
  for (p=0; p<MAX_PROC; p++)
142
    if (proc_table[p].task_level == l && proc_table[p].status != POSIX_READY
143
        && proc_table[p].status != FREE )
144
      kern_printf("Pid: %d\t Name: %20s Prio: %3ld Status: %s\n",
145
                  p,proc_table[p].name,
146
                  proc_table[p].priority,
147
                  POSIX_status_to_a(proc_table[p].status));
148
 
149
}
150
 
151
 
152
/* This is not efficient but very fair :-)
153
   The need of all this stuff is because if a task execute a long time
154
   due to (shadow!) priority inheritance, then the task shall go to the
155
   tail of the queue many times... */
156
static PID POSIX_level_scheduler(LEVEL l)
157
{
158
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
159
 
160
  PID p;
161
 
162
  int prio;
163
 
164
  prio = lev->maxpriority;
165
 
166
  for (;;) {
167
    p = qq_queryfirst(&lev->ready[prio]);
168
    if (p == NIL) {
169
      if (prio) {
170
        prio--;
171
        continue;
172
      }
173
      else
174
        return NIL;
175
    }
176
 
177
    if ((proc_table[p].control & CONTROL_CAP) &&
178
        (proc_table[p].avail_time <= 0)) {
179
      proc_table[p].avail_time += proc_table[p].wcet;
180
      qq_extract(p,&lev->ready[prio]);
181
      qq_insertlast(p,&lev->ready[prio]);
182
    }
183
    else
184
      return p;
185
  }
186
}
187
 
188
static int POSIX_level_guarantee(LEVEL l, bandwidth_t *freebandwidth)
189
{
190
  /* the POSIX level always guarantee... the function is defined because
191
     there can be an aperiodic server at a level with less priority than
192
     the POSIX that need guarantee (e.g., a TBS server) */
193
  return 1;
194
}
195
 
196
 
197
static int POSIX_task_create(LEVEL l, PID p, TASK_MODEL *m)
198
{
199
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
200
  NRT_TASK_MODEL *nrt = (NRT_TASK_MODEL *)m;
201
 
202
  /* the task state is set at SLEEP by the general task_create */
203
 
204
  /* I used the wcet field because using wcet can account if a task
205
     consume more than the timeslice... */
206
 
207
  if (nrt->inherit == NRT_INHERIT_SCHED &&
208
      proc_table[exec_shadow].task_level == l) {
209
    /* We inherit the scheduling properties if the scheduling level
210
       *is* the same */
211
    proc_table[p].priority = proc_table[exec_shadow].priority;
212
 
213
    proc_table[p].avail_time = proc_table[exec_shadow].avail_time;
214
    proc_table[p].wcet       = proc_table[exec_shadow].wcet;
215
 
216
    proc_table[p].control = (proc_table[p].control & ~CONTROL_CAP) |
217
                            (proc_table[exec_shadow].control & CONTROL_CAP);
218
 
219
    lev->nact[p] = (lev->nact[exec_shadow] == -1) ? -1 : 0;
220
  }
221
  else {
222
    proc_table[p].priority = nrt->weight;
223
 
224
    if (nrt->slice) {
225
      proc_table[p].avail_time = nrt->slice;
226
      proc_table[p].wcet       = nrt->slice;
227
    }
228
    else {
229
      proc_table[p].avail_time = lev->slice;
230
      proc_table[p].wcet       = lev->slice;
231
    }
232
 
233
    if (nrt->policy == NRT_RR_POLICY)
234
      proc_table[p].control   |= CONTROL_CAP;
235
 
236
    if (nrt->arrivals == SAVE_ARRIVALS)
237
      lev->nact[p] = 0;
238
    else
239
      lev->nact[p] = -1;
240
  }
241
 
242
  return 0; /* OK */
243
}
244
 
245
static void POSIX_task_detach(LEVEL l, PID p)
246
{
247
  /* the POSIX level doesn't introduce any new field in the TASK_MODEL
248
     so, all detach stuffs are done by the task_create
249
     The task state is set at FREE by the general task_create */
250
}
251
 
252
static int POSIX_task_eligible(LEVEL l, PID p)
253
{
254
  return 0; /* if the task p is chosen, it is always eligible */
255
}
256
 
257
#ifdef __TEST1__
258
extern int testactive;
259
extern struct timespec s_stime[];
260
extern TIME s_curr[];
261
extern TIME s_PID[];
262
extern int useds;
263
#endif
264
 
265
static void POSIX_task_dispatch(LEVEL l, PID p, int nostop)
266
{
267
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
268
 
269
  /* the task state is set EXE by the scheduler()
270
     we extract the task from the ready queue
271
     NB: we can't assume that p is the first task in the queue!!! */
272
  qq_extract(p, &lev->ready[proc_table[p].priority]);
273
 
274
 
275
  #ifdef __TEST1__
276
  if (testactive)
277
  {
278
    TIMESPEC_ASSIGN(&s_stime[useds],&schedule_time);
279
    s_curr[useds] = proc_table[p].avail_time;
280
    s_PID[useds]  = p;
281
    useds++;
282
  }
283
  #endif
284
}
285
 
286
static void POSIX_task_epilogue(LEVEL l, PID p)
287
{
288
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
289
 
290
  if (lev->yielding) {
291
    lev->yielding = 0;
292
    qq_insertlast(p,&lev->ready[proc_table[p].priority]);
293
  }
294
  /* check if the slice is finished and insert the task in the coPOSIXect
295
     qqueue position */
296
  else if (proc_table[p].control & CONTROL_CAP &&
297
           proc_table[p].avail_time <= 0) {
298
    proc_table[p].avail_time += proc_table[p].wcet;
299
    qq_insertlast(p,&lev->ready[proc_table[p].priority]);
300
  }
301
  else
302
    qq_insertfirst(p,&lev->ready[proc_table[p].priority]);
303
 
304
  proc_table[p].status = POSIX_READY;
305
}
306
 
307
static void POSIX_task_activate(LEVEL l, PID p)
308
{
309
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
310
 
311
  /* Test if we are trying to activate a non sleeping task    */
312
  /* save activation (only if needed...) */
313
  if (proc_table[p].status != SLEEP) {
314
    if (lev->nact[p] != -1)
315
      lev->nact[p]++;
316
    return;
317
  }
318
 
319
  ll_gettime(TIME_EXACT, &proc_table[p].request_time);
320
 
321
  /* Insert task in the correct position */
322
  proc_table[p].status = POSIX_READY;
323
  qq_insertlast(p,&lev->ready[proc_table[p].priority]);
324
}
325
 
326
static void POSIX_task_insert(LEVEL l, PID p)
327
{
328
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
329
 
330
  /* Similar to POSIX_task_activate, but we don't check in what state
331
     the task is and we don't set the request_time */
332
 
333
  /* Insert task in the coPOSIXect position */
334
  proc_table[p].status = POSIX_READY;
335
  qq_insertlast(p,&lev->ready[proc_table[p].priority]);
336
}
337
 
338
static void POSIX_task_extract(LEVEL l, PID p)
339
{
340
  /* Extract the running task from the level
341
     . we have already extract it from the ready queue at the dispatch time.
342
     . the capacity event have to be removed by the generic kernel
343
     . the wcet don't need modification...
344
     . the state of the task is set by the calling function
345
 
346
     So, we do nothing!!!
347
  */
348
}
349
 
350
static void POSIX_task_endcycle(LEVEL l, PID p)
351
{
352
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
353
 
354
  if (lev->nact[p] > 0) {
355
    /* continue!!!! */
356
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
357
    lev->nact[p]--;
358
    qq_insertfirst(p,&lev->ready[proc_table[p].priority]);
359
    proc_table[p].status = POSIX_READY;
360
  }
361
  else
362
    proc_table[p].status = SLEEP;
363
}
364
 
365
static void POSIX_task_end(LEVEL l, PID p)
366
{
367
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
368
 
369
  lev->nact[p] = -1;
370
 
371
  /* then, we insert the task in the free queue */
372
  proc_table[p].status = FREE;
373
  q_insert(p,&freedesc);
374
}
375
 
376
static void POSIX_task_sleep(LEVEL l, PID p)
377
{
378
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
379
  lev->nact[p] = 0;
380
  proc_table[p].status = SLEEP;
381
}
382
 
383
static void POSIX_task_delay(LEVEL l, PID p, TIME usdelay)
384
{
385
//  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
386
  struct timespec wakeuptime;
387
 
388
  /* equal to POSIX_task_endcycle */
389
  proc_table[p].status = POSIX_DELAY;
390
 
391
  /* we need to delete this event if we kill the task while it is sleeping */
392
  ll_gettime(TIME_EXACT,&wakeuptime);
393
  ADDUSEC2TIMESPEC(usdelay,&wakeuptime);
394
  proc_table[p].delay_timer = kern_event_post(&wakeuptime,
395
                                              POSIX_timer_delay,
396
                                              (void *)p);
397
}
398
 
399
 
400
static int POSIX_guest_create(LEVEL l, PID p, TASK_MODEL *m)
14 pj 401
{ kern_raise(XINVALID_GUEST,exec_shadow); return 0; }
2 pj 402
 
403
static void POSIX_guest_detach(LEVEL l, PID p)
14 pj 404
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 405
 
406
static void POSIX_guest_dispatch(LEVEL l, PID p, int nostop)
14 pj 407
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 408
 
409
static void POSIX_guest_epilogue(LEVEL l, PID p)
14 pj 410
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 411
 
412
static void POSIX_guest_activate(LEVEL l, PID p)
14 pj 413
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 414
 
415
static void POSIX_guest_insert(LEVEL l, PID p)
14 pj 416
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 417
 
418
static void POSIX_guest_extract(LEVEL l, PID p)
14 pj 419
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 420
 
421
static void POSIX_guest_endcycle(LEVEL l, PID p)
14 pj 422
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 423
 
424
static void POSIX_guest_end(LEVEL l, PID p)
14 pj 425
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 426
 
427
static void POSIX_guest_sleep(LEVEL l, PID p)
14 pj 428
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 429
 
430
static void POSIX_guest_delay(LEVEL l, PID p,DWORD tickdelay)
14 pj 431
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 432
 
433
 
434
 
435
 
436
/* Registration functions */
437
 
438
/*+ This init function install the "main" task +*/
439
static void POSIX_call_main(void *l)
440
{
441
  LEVEL lev;
442
  PID p;
443
  NRT_TASK_MODEL m;
444
  void *mb;
445
 
446
  lev = (LEVEL)l;
447
 
448
  nrt_task_default_model(m);
449
  nrt_task_def_level(m,lev); /* with this we are sure that the task aPOSIXives
450
                                to the coPOSIXect level */
451
 
452
  mb = ((POSIX_level_des *)level_table[lev])->multiboot;
453
  nrt_task_def_arg(m,mb);
454
  nrt_task_def_usemath(m);
455
  nrt_task_def_nokill(m);
456
  nrt_task_def_ctrl_jet(m);
457
  nrt_task_def_weight(m,0);
458
  nrt_task_def_policy(m,NRT_RR_POLICY);
459
  nrt_task_def_inherit(m,NRT_EXPLICIT_SCHED);
460
 
461
  p = task_create("Main", __init__, (TASK_MODEL *)&m, NULL);
462
 
463
  if (p == NIL)
464
    printk("\nPanic!!! can't create main task...\n");
465
 
466
  POSIX_task_activate(lev,p);
467
}
468
 
469
 
470
/*+ Registration function:
471
    TIME slice                the slice for the Round Robin queue
472
    int createmain            1 if the level creates the main task 0 otherwise
473
    struct multiboot_info *mb used if createmain specified   +*/
474
void POSIX_register_level(TIME slice,
475
                       int createmain,
476
                       struct multiboot_info *mb,
477
                       int prioritylevels)
478
{
479
  LEVEL l;            /* the level that we register */
480
  POSIX_level_des *lev;  /* for readableness only */
481
  PID i;              /* a counter */
482
  int x;              /* a counter */
483
 
484
  printk("POSIX_register_level\n");
485
 
486
  /* request an entry in the level_table */
487
  l = level_alloc_descriptor();
488
 
489
  printk("    alloco descrittore %d %d\n",l,(int)sizeof(POSIX_level_des));
490
 
491
  /* alloc the space needed for the POSIX_level_des */
492
  lev = (POSIX_level_des *)kern_alloc(sizeof(POSIX_level_des));
493
 
494
  printk("    lev=%d\n",(int)lev);
495
 
496
  /* update the level_table with the new entry */
497
  level_table[l] = (level_des *)lev;
498
 
499
  /* fill the standard descriptor */
500
  strncpy(lev->l.level_name,  POSIX_LEVELNAME, MAX_LEVELNAME);
501
  lev->l.level_code               = POSIX_LEVEL_CODE;
502
  lev->l.level_version            = POSIX_LEVEL_VERSION;
503
 
504
  lev->l.level_accept_task_model  = POSIX_level_accept_task_model;
505
  lev->l.level_accept_guest_model = POSIX_level_accept_guest_model;
506
  lev->l.level_status             = POSIX_level_status;
507
  lev->l.level_scheduler          = POSIX_level_scheduler;
508
  lev->l.level_guarantee          = POSIX_level_guarantee;
509
 
510
  lev->l.task_create              = POSIX_task_create;
511
  lev->l.task_detach              = POSIX_task_detach;
512
  lev->l.task_eligible            = POSIX_task_eligible;
513
  lev->l.task_dispatch            = POSIX_task_dispatch;
514
  lev->l.task_epilogue            = POSIX_task_epilogue;
515
  lev->l.task_activate            = POSIX_task_activate;
516
  lev->l.task_insert              = POSIX_task_insert;
517
  lev->l.task_extract             = POSIX_task_extract;
518
  lev->l.task_endcycle            = POSIX_task_endcycle;
519
  lev->l.task_end                 = POSIX_task_end;
520
  lev->l.task_sleep               = POSIX_task_sleep;
521
  lev->l.task_delay               = POSIX_task_delay;
522
 
523
  lev->l.guest_create             = POSIX_guest_create;
524
  lev->l.guest_detach             = POSIX_guest_detach;
525
  lev->l.guest_dispatch           = POSIX_guest_dispatch;
526
  lev->l.guest_epilogue           = POSIX_guest_epilogue;
527
  lev->l.guest_activate           = POSIX_guest_activate;
528
  lev->l.guest_insert             = POSIX_guest_insert;
529
  lev->l.guest_extract            = POSIX_guest_extract;
530
  lev->l.guest_endcycle           = POSIX_guest_endcycle;
531
  lev->l.guest_end                = POSIX_guest_end;
532
  lev->l.guest_sleep              = POSIX_guest_sleep;
533
  lev->l.guest_delay              = POSIX_guest_delay;
534
 
535
  /* fill the POSIX descriptor part */
536
  for (i = 0; i < MAX_PROC; i++)
537
    lev->nact[i] = -1;
538
 
539
  lev->maxpriority = prioritylevels -1;
540
 
541
  lev->ready = (QQUEUE *)kern_alloc(sizeof(QQUEUE) * prioritylevels);
542
 
543
  for (x = 0; x < prioritylevels; x++)
544
    qq_init(&lev->ready[x]);
545
 
546
  if (slice < POSIX_MINIMUM_SLICE) slice = POSIX_MINIMUM_SLICE;
547
  if (slice > POSIX_MAXIMUM_SLICE) slice = POSIX_MAXIMUM_SLICE;
548
  lev->slice      = slice;
549
 
550
  lev->multiboot  = mb;
551
 
552
  if (createmain)
553
    sys_atrunlevel(POSIX_call_main,(void *) l, RUNLEVEL_INIT);
554
}
555
 
556
/*+ this function forces the running task to go to his queue tail;
557
    (it works only on the POSIX level) +*/
558
int POSIX_sched_yield(LEVEL l)
559
{
560
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
561
 
562
  if (l < 0 || l >= sched_levels)
563
    return -1;
564
 
565
  if (level_table[l]->level_code    != POSIX_LEVEL_CODE    ||
566
      level_table[l]->level_version != POSIX_LEVEL_VERSION )
567
    return -1;
568
 
569
  if (proc_table[exec_shadow].task_level != l)
570
    return -1;
571
 
572
  proc_table[exec_shadow].context = kern_context_save();
573
  lev->yielding = 1;
574
  scheduler();
575
  kern_context_load(proc_table[exec_shadow].context);
576
  return 0;
577
}
578
 
579
/*+ this function returns the maximum level allowed for the POSIX level +*/
580
int POSIX_get_priority_max(LEVEL l)
581
{
582
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
583
  return lev->maxpriority;
584
}
585
 
586
/*+ this function returns the default timeslice for the POSIX level +*/
587
int POSIX_rr_get_interval(LEVEL l)
588
{
589
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
590
  return lev->slice;
591
}
592
 
593
/*+ this functions returns some paramaters of a task;
594
    policy must be NRT_RR_POLICY or NRT_FIFO_POLICY;
595
    priority must be in the range [0..prioritylevels]
596
    returns ENOSYS or ESRCH if there are problems +*/
597
int POSIX_getschedparam(LEVEL l, PID p, int *policy, int *priority)
598
{
599
  if (l < 0 || l >= sched_levels)
600
    return ENOSYS;
601
 
602
  if (level_table[l]->level_code    != POSIX_LEVEL_CODE    ||
603
      level_table[l]->level_version != POSIX_LEVEL_VERSION )
604
    return ENOSYS;
605
 
606
  if (p<0 || p>= MAX_PROC || proc_table[p].status == FREE)
607
    return ESRCH;
608
 
609
  if (proc_table[p].task_level != l)
610
    return ENOSYS;
611
 
612
  if (proc_table[p].control & CONTROL_CAP)
613
    *policy = NRT_RR_POLICY;
614
  else
615
    *policy = NRT_FIFO_POLICY;
616
 
617
  *priority = proc_table[p].priority;
618
 
619
  return 0;
620
}
621
 
622
/*+ this functions sets paramaters of a task +*/
623
int POSIX_setschedparam(LEVEL l, PID p, int policy, int priority)
624
{
625
  POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
626
 
627
  if (l < 0 || l >= sched_levels)
628
    return ENOSYS;
629
 
630
  if (level_table[l]->level_code    != POSIX_LEVEL_CODE    ||
631
      level_table[l]->level_version != POSIX_LEVEL_VERSION )
632
    return ENOSYS;
633
 
634
  if (p<0 || p>= MAX_PROC || proc_table[p].status == FREE)
635
    return ESRCH;
636
 
637
  if (proc_table[p].task_level != l)
638
    return ENOSYS;
639
 
640
  if (policy == SCHED_RR)
641
    proc_table[p].control |= CONTROL_CAP;
642
  else if (policy == SCHED_FIFO)
643
    proc_table[p].control &= ~CONTROL_CAP;
644
  else
645
    return EINVAL;
646
 
647
  if (proc_table[p].priority != priority) {
648
    if (proc_table[p].status == POSIX_READY) {
649
      qq_extract(p,&lev->ready[proc_table[p].priority]);
650
      proc_table[p].priority = priority;
651
      qq_insertlast(p,&lev->ready[priority]);
652
    }
653
    else
654
      proc_table[p].priority = priority;
655
  }
656
 
657
  return 0;
658
}
659
 
660
 
661