Subversion Repositories shark

Rev

Rev 3 | Go to most recent revision | 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: srp.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
 Stack Resource Policy. see srp.h for general details...
31
 
32
 
33
 HOW the shadows are managed in this module
34
 ------------------------------------------
35
 
36
 All the task that use SRP are inserted in an ordered list, called tasklist.
37
 
38
 when a task lock a mutex and change the system ceiling, all the shadows
39
 of the tasks with preemption level <= are set to the locking task, and
40
 viceversa when a mutex is unlocked.
41
 
42
 The real algorithm is slightly different: for example consider a task set
43
 of 8 tasks. We represent each task here as (PID, shadow, preemption level).
44
 
45
 There is also a field, current, used to scan the tasklist.
46
 
47
 When the system starts, the situation is as follows:
48
 
49
 system ceiling = 0, current = NIL
50
 (a,a,1) (b,b,2) (c,c,2) (d,d,2) (e,e,3) (f,f,4) (g,g,4) (h,h,5)
51
 
52
 for example, task a is scheduled, and lock a mutex that cause the system
53
 ceiling to become 2. The situation will be the following:
54
 
55
 system ceiling = 2, current = d
56
 (a,a,1) (b,a,2) (c,a,2) (d,a,2) (e,e,3) (f,f,4) (g,g,4) (h,h,5)
57
 
58
 Now suppose that task f preempts on task a. (no change to the shadows)
59
 
60
 Then the task f locks a mutex and the system ceiling become 4. The shadows
61
 will be set as follows:
62
 
63
 system ceiling = 4, current = g
64
 (a,f,1) (b,a,2) (c,a,2) (d,a,2) (e,f,3) (f,f,4) (g,f,4) (h,h,5)
65
 
66
 The system maintains a stack of the locked mutexes. each mutex has in the
67
 descriptor the space for implementing a stack, useful in the unlock()
68
 function to undo the modify done whith the last lock()...
69
 
70
 This approach minimizes the number of shadows to be set, so minimizes
71
 the complexity of the lock/unlock operations.
72
 
73
 Unfortunately, it creates a tree in the shadows (i.e., when sys_ceiling=4,
74
 task c points to task a that points to task f, and so on....). This may
75
 cause a performance a little worse with respect to a one-jump shadow set.
76
 This is not a big problem because when a task is preempted it is very
77
 difficult (if not impossible!) that it may be rescheduled before the end
78
 of another high priority task.
79
 
80
 Dynamic creation and termination of tasks
81
 -----------------------------------------
82
 This module allows dynamic creation and termination of tasks.
83
 
84
 To be correct the system have to really activate the task only when the
85
 system ceiling is 0.
86
 
87
 To implement this there is a list, the lobbylist, that contains that tasks.
88
 
89
 When a task is created and the system ceiling is > 0, the task is inserted
90
 on the top of the list, and his activation are frozen via a call to
91
 task_block_activations.
92
 
93
 When the system_ceiling returns to 0, the lobby list is purged and for each
94
 task in that list the task_unblock_activations is called. if the function
95
 return a number >0, a task call task_activate is done on the task.
96
 
97
 the tasks are inserted into the lobby list using only the next field.
98
 
99
 
100
 
101
 When a mutex is destryed or a task is created or killed, the ceiling
102
 have to be recalculated. The recalc is made when the system ceiling go down
103
 to 0. to know whitch are the mutexes that need the operation they are
104
 inserted into the srp_recalc list.
105
 
106
 
107
 The SRP_usemutex function (see srp.h) is used to declare the used mutexes
108
 of a task. Why this and how it works?
109
 In this way, a task can insert directly the list of the mutexes that it uses
110
 without allocating others resource models, but using directly the mutexes
111
 that MUST be (in any case) initialized before the task creation...
112
 This is done in a simple way, inheriting the SRP_mutex_t from the RES_MODEL.
113
 When a task registers a mutex, the SRP module receive the pointer to that
114
 mutex, so it can do all the stuffs with the needed data structures.
115
 
116
**/
117
 
118
/*
119
 * Copyright (C) 2000 Paolo Gai
120
 *
121
 * This program is free software; you can redistribute it and/or modify
122
 * it under the terms of the GNU General Public License as published by
123
 * the Free Software Foundation; either version 2 of the License, or
124
 * (at your option) any later version.
125
 *
126
 * This program is distributed in the hope that it will be useful,
127
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
128
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
129
 * GNU General Public License for more details.
130
 *
131
 * You should have received a copy of the GNU General Public License
132
 * along with this program; if not, write to the Free Software
133
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
134
 *
135
 */
136
 
137
 
138
#include <modules/srp.h>
139
 
140
#include <ll/ll.h>
141
#include <ll/string.h>
142
#include <ll/stdio.h>
143
#include <kernel/const.h>
144
#include <modules/codes.h>
145
#include <sys/types.h>
146
#include <kernel/descr.h>
147
#include <kernel/var.h>
148
#include <kernel/func.h>
149
 
150
typedef struct SRP_mutexstruct_t SRP_mutex_t;
151
 
152
/* The SRP resource level descriptor */
153
typedef struct {
154
  mutex_resource_des m;   /*+ the mutex interface +*/
155
 
156
  int nlocked[MAX_PROC];  /*+ how many mutex a task currently locks +*/
157
 
158
  struct {
159
    DWORD preempt;
160
    PID next;
161
    PID prev;
162
  } proc_preempt[MAX_PROC]; /*+ the preemption level of each task in the
163
                                system; if a task don't use SRP its value
164
                                is 0; if a task use SRP the field preempt
165
                                is != 0 and the item is enqueued in the
166
                                ordered list tasklist +*/
167
 
168
  PID tasklist;             /*+ A list of all the task that can use SRP,
169
                                ordered by the preemption level of each
170
                                task.                  +*/
171
  PID current;              /*+ A pointer used to set shadows +*/
172
 
173
  PID lobbylist;            /*+ A list for all the new tasks created when
174
                                the system ceiling is != 0. These tasks
175
                                will be inserted into tasklist when the
176
                                ceiling return to 0. +*/
177
  SRP_mutex_t *srpstack;    /*+ this is the stack where we store the system
178
                                ceiling +*/
179
 
180
  SRP_mutex_t *srprecalc;   /*+ the list of all mutexes that need a ceiling
181
                                recalc +*/
182
 
183
  SRP_mutex_t *srplist;     /*+ an unordered list of all created SRP
184
                                mutexes +*/
185
 
186
} SRP_mutex_resource_des;
187
 
188
 
189
/* this is the structure normally pointed by the opt field in the
190
   mutex_t structure */
191
struct SRP_mutexstruct_t {
192
  RES_MODEL r;  /*+ This little trick make possible the use of
193
                    SRP_usemutex                                +*/
194
 
195
  /* because the number of mutexes that can be created is not limited,
196
     the stack normally used to store the system ceiling is implemented
197
     through these two fields in the mutex descriptor. Note that the mutex
198
     are mono-resource, so when we alloc space for a mutex descriptor we
199
     alloc also the needed space for the stack... */
200
  DWORD sysceiling; /*+ The system ceiling; this field contains
201
                        - a meaningless value if the struct is not inserted
202
                          into the srpstack
203
                        - the system ceiling if the struct is on the top of
204
                          the srpstack
205
                        - a "frozen" system ceiling if the struct is not on
206
                          the top of the srpstack.
207
                        when a mutex is locked, it is inserted into srpstack
208
                        updating the system ceiling automatically
209
                        +*/
210
  SRP_mutex_t *srpstack_next; /*+ the next entry on the srpstack +*/
211
 
212
 
213
 
214
  BYTE use[MAX_PROC]; /*+ use[p]==1 if the task p declared that it uses the
215
                          mutex +*/
216
 
217
  DWORD ceiling;      /*+ max premption level of the tasks that use the mutex +*/
218
 
219
  PID owner;          /*+ the task that owns the mutex, NIL otherwise +*/
220
 
221
  int in_recalc_list; /*+ a flag: 1 if the mutex is in the recalc list +*/
222
  SRP_mutex_t *srprecalc_next; /*+ the next item in the recalc list +*/
223
  SRP_mutex_t *srprecalc_prev; /*+ the prev item; useful in extractions +*/
224
 
225
  SRP_mutex_t *srplist_next; /*+ the next item in the srplist list +*/
226
  SRP_mutex_t *srplist_prev; /*+ the prev item; useful in extractions+*/
227
};
228
 
229
 
230
 
231
 
232
 
233
 
234
 
235
 
236
 
237
 
238
 
239
/* -----------------------------------------------------------------------
240
   LISTS HANDLING
241
   ----------------------------------------------------------------------- */
242
 
243
/*+ this function inserts a task into the tasklist ordered list +*/
244
static void SRP_insert_tasklist(SRP_mutex_resource_des *m, PID t)
245
{
246
   PID p,q;
247
 
248
   p = NIL;
249
   q = m->tasklist;
250
 
251
   while ((q != NIL) &&
252
          (m->proc_preempt[t].preempt >= m->proc_preempt[q].preempt)) {
253
        p = q;
254
        q = m->proc_preempt[q].next;
255
   }
256
 
257
   if (p != NIL)
258
     m->proc_preempt[p].next = t;
259
   else
260
     m->tasklist = t;
261
 
262
   if (q != NIL) m->proc_preempt[q].prev = t;
263
 
264
   m->proc_preempt[t].next = q;
265
   m->proc_preempt[t].prev = p;
266
}
267
 
268
/*+ this function extracts a task from the tasklist +*/
269
static void SRP_extract_tasklist(SRP_mutex_resource_des *m, PID i)
270
{
271
    PID p,q;
272
 
273
    p = m->proc_preempt[i].prev;
274
    q = m->proc_preempt[i].next;
275
 
276
    if (p == NIL) m->tasklist = q;
277
    else m->proc_preempt[p].next = m->proc_preempt[i].next;
278
 
279
    if (q != NIL) m->proc_preempt[q].prev = m->proc_preempt[i].prev;
280
}
281
 
282
 
283
/*+ this function inserts a task into the lobbylist (in an unordered way) +*/
284
static void SRP_insertfirst_lobbylist(SRP_mutex_resource_des *m, PID p)
285
{
286
  m->proc_preempt[p].next = m->lobbylist;
287
  m->proc_preempt[p].prev = NIL;
288
 
289
  m->proc_preempt[m->lobbylist].prev = p;
290
  m->lobbylist = p;
291
}
292
 
293
/*+ this function extract the first task from the lobbylist
294
    the lobbylist must be not-empty!!!! +*/
295
static __inline__ PID SRP_extractfirst_lobbylist(SRP_mutex_resource_des *m)
296
{
297
  PID lobby = m->lobbylist;
298
  m->lobbylist = m->proc_preempt[m->lobbylist].next;
299
  return lobby;
300
}
301
 
302
 
303
 
304
/*+ This function insert a mutex into the recalc list ONLY if the mutex
305
    isn't already in that list... +*/
306
static void SRP_insertfirst_recalclist(SRP_mutex_resource_des *m,
307
                                      SRP_mutex_t *mut)
308
{
309
  if (!mut->in_recalc_list) {
310
    mut->srprecalc_next = m->srprecalc;
311
    mut->srprecalc_prev = NULL;
312
    if (m->srprecalc) m->srprecalc->srprecalc_prev = mut;
313
    m->srprecalc = mut;
314
 
315
    mut->in_recalc_list = 1;
316
  }
317
}
318
 
319
/*+ this function extracts mut from the list l. +*/
320
static void SRP_extract_recalclist(SRP_mutex_resource_des *m,
321
                                   SRP_mutex_t *mut)
322
{
323
  SRP_mutex_t *p, *q;
324
 
325
  p = mut->srprecalc_prev;
326
  q = mut->srprecalc_next;
327
 
328
  if (p)
329
    p->srprecalc_next = mut->srprecalc_next;
330
  else
331
    m->srprecalc = q;
332
 
333
  if (q) q->srprecalc_prev = mut->srprecalc_prev;
334
}
335
 
336
/*+ this function extracts mut from the list l. +*/
337
static void SRP_extract_srplist(SRP_mutex_resource_des *m,
338
                                SRP_mutex_t *mut)
339
{
340
  SRP_mutex_t *p, *q;
341
 
342
  p = mut->srplist_prev;
343
  q = mut->srplist_next;
344
 
345
  if (p)
346
    p->srplist_next = mut->srplist_next;
347
  else
348
    m->srplist = q;
349
 
350
  if (q) q->srplist_prev = mut->srplist_prev;
351
}
352
 
353
 
354
 
355
/* -----------------------------------------------------------------------
356
   End of LISTS HANDLING
357
   ----------------------------------------------------------------------- */
358
 
359
 
360
 
361
 
362
/*+ This funcyion returns the actual system ceiling +*/
363
static __inline__ DWORD sysceiling(SRP_mutex_resource_des *m)
364
{
365
  if (m->srpstack)
366
    return m->srpstack->sysceiling;
367
  else
368
    return 0;
369
}
370
 
371
/*+ this function recalc the mutex ceiling basing on the preemption levels
372
    stored in the mevel m +*/
373
static void SRP_recalc_ceiling_value(SRP_mutex_resource_des *m,
374
                                     SRP_mutex_t *mut)
375
{
376
  PID p;
377
  int ceiling;
378
 
379
  ceiling = 0;
380
  for (p = 0; p < MAX_PROC; p++)
381
    if (mut->use[p] && ceiling < m->proc_preempt[p].preempt)
382
      ceiling = m->proc_preempt[p].preempt;
383
 
384
  mut->ceiling = ceiling;
385
}
386
 
387
 
388
/*+ print resource protocol statistics...+*/
389
static void SRP_resource_status(RLEVEL r)
390
{
391
  kern_printf("SRP status not implemented yet");
392
}
393
 
394
 
395
static int SRP_level_accept_resource_model(RLEVEL l, RES_MODEL *r)
396
{
397
  if (r->rclass == SRP_RCLASS  || r->rclass == (SRP_RCLASS | l) ||
398
      r->rclass == SRP2_RCLASS || r->rclass == (SRP2_RCLASS | l))
399
    return 0;
400
  else
401
    return -1;
402
}
403
 
404
static void SRP_res_register(RLEVEL l, PID p, RES_MODEL *r)
405
{
406
  SRP_mutex_resource_des *m = (SRP_mutex_resource_des *)(resource_table[l]);
407
 
408
  if (r->rclass == SRP_RCLASS  || r->rclass == (SRP_RCLASS | l)) {
409
    /* SRP_RES_MODEL resource model */
410
//  kern_printf("!%d %d",((SRP_RES_MODEL *)r)->preempt,p);
411
 
412
    if (m->proc_preempt[p].preempt == 0) {
413
      /* only the first SRP_RES_MODEL is considered */
414
      SRP_RES_MODEL *srp = (SRP_RES_MODEL *)r;
415
 
416
      m->proc_preempt[p].preempt = srp->preempt;
417
//      kern_printf("res_register: preempt=%d, p=%d\n",srp->preempt,p);
418
 
419
      /* insert the new task in the ordered list tasklist or in the lobby
420
         list */
421
      if (m->srpstack) {
422
        SRP_insertfirst_lobbylist(m,p);
423
        /* we have also to freeze the activations... */
424
        task_block_activation(p);
425
//        kern_printf("LOBBY!!!");
426
      }
427
      else
428
        SRP_insert_tasklist(m,p);
429
    }
430
 
431
    m->nlocked[p] = 0;
432
  }
433
  else {
434
    /* a mutex passed via SRP_useres() */
435
    SRP_mutex_t *mut = (SRP_mutex_t *)r;
436
 
437
    if (mut->use[p])
438
      /* the mutex is already registered, do nothing! */
439
      return;
440
 
441
    /* register the mutex for the task */
442
    mut->use[p] = 1;
443
 
444
    if (m->srpstack)
445
      SRP_insertfirst_recalclist(m,mut);
446
    else {
447
      /* we recalc the mutex ceiling */
448
      if (mut->ceiling < m->proc_preempt[p].preempt)
449
        mut->ceiling = m->proc_preempt[p].preempt;
450
 
451
    }
452
  }
453
}
454
 
455
static void SRP_res_detach(RLEVEL l, PID p)
456
{
457
  SRP_mutex_resource_des *m = (SRP_mutex_resource_des *)(resource_table[l]);
458
  SRP_mutex_t *mut;
459
 
460
  if (m->proc_preempt[p].preempt == 0)
461
    return;
462
 
463
  if (m->nlocked[p])
464
    kern_raise(XMUTEX_OWNER_KILLED, p);
465
  else
466
    m->nlocked[p] = 0;
467
 
468
  for (mut = m->srplist; mut; mut = mut->srplist_next)
469
  {
470
    if (!mut->use[p])
471
      /* the mutex is not registered, do nothing! */
472
      continue;
473
 
474
    /* unregister the mutex for the task */
475
    mut->use[p] = 0;
476
 
477
    if (m->srpstack)
478
      SRP_insertfirst_recalclist(m,mut);
479
    else
480
      SRP_recalc_ceiling_value(m,mut);
481
  }
482
 
483
  /* check if current points to the task being killed */
484
  if (m->current == p)
485
    m->current = m->proc_preempt[m->current].prev;
486
 
487
  /* remove the task from the tasklist */
488
  SRP_extract_tasklist(m, p);
489
}
490
 
491
static int SRP_level_accept_mutexattr(RLEVEL l, const mutexattr_t *a)
492
{
493
  if (a->mclass == SRP_MCLASS || a->mclass == (SRP_MCLASS | l) )
494
    return 0;
495
  else
496
    return -1;
497
}
498
 
499
static int SRP_init(RLEVEL l, mutex_t *m, const mutexattr_t *a)
500
{
501
  SRP_mutex_resource_des *lev = (SRP_mutex_resource_des *)(resource_table[l]);
502
  SRP_mutex_t *p;
503
  PID x;
504
 
505
  p = (SRP_mutex_t *) kern_alloc(sizeof(SRP_mutex_t));
506
 
507
  /* control if there is enough memory; no control on init on a
508
     non- destroyed mutex */
509
 
510
  if (!p)
511
    return (ENOMEM);
512
 
513
  res_default_model(p->r, SRP2_RCLASS);
514
  p->sysceiling    = 0;     /* dummy value :-) */
515
  p->srpstack_next = NULL;  /* dummy value :-) */
516
 
517
  for (x = 0; x < MAX_PROC; x++)
518
    p->use[x] = 0;
519
 
520
  p->ceiling = 0;
521
  p->owner = NIL;
522
 
523
  p->in_recalc_list = 0;
524
  p->srprecalc_next = NULL; /* dummy value :-) */
525
  p->srprecalc_prev = NULL; /* dummy value :-) */
526
 
527
  p->srplist_next = lev->srplist;
528
  p->srplist_prev = NULL;
529
  if (lev->srplist) lev->srplist->srplist_prev = p;
530
  lev->srplist = p;
531
 
532
  m->mutexlevel = l;
533
  m->opt = (void *)p;
534
 
535
  return 0;
536
}
537
 
538
 
539
static int SRP_destroy(RLEVEL l, mutex_t *m)
540
{
541
  SRP_mutex_resource_des *lev = (SRP_mutex_resource_des *)(resource_table[l]);
542
  SRP_mutex_t *mut;
543
 
544
  mut = m->opt;
545
 
546
  if (mut->owner != NIL)
547
    return (EBUSY);
548
 
549
  kern_cli();
550
 
551
  /* the mutex isn't in the srpstack, because it is not busy */
552
 
553
  /* check srprecalc list */
554
  if (mut->in_recalc_list)
555
    SRP_extract_recalclist(lev, mut);
556
 
557
  /* extract from srplist */
558
  SRP_extract_srplist(lev, mut);
559
 
560
  if (m->opt) {
561
    kern_free(m->opt,sizeof(SRP_mutex_t));
562
    m->opt = NULL;
563
  }
564
  kern_sti();
565
 
566
  return 0;
567
}
568
 
569
static int SRP_lock(RLEVEL l, mutex_t *m)
570
{
571
  SRP_mutex_resource_des *lev = (SRP_mutex_resource_des *)(resource_table[l]);
572
  SRP_mutex_t *mut;
573
  DWORD oldsysceiling;
574
 
575
  kern_cli();
576
 
577
  mut = (SRP_mutex_t *)m->opt;
578
  if (!mut) {
579
    /* if the mutex is not initialized */
580
    kern_sti();
581
    return (EINVAL);
582
  }
583
 
584
  if (mut->owner == exec_shadow) {
585
    /* the task already owns the mutex */
586
    kern_sti();
587
    return (EDEADLK);
588
  }
589
 
590
  if (!mut->use[exec_shadow] ||
591
      lev->proc_preempt[exec_shadow].preempt == 0 ||
592
      mut->owner != NIL)
593
  {
594
//    kern_printf("SRP:lev =%d owner=%d use=%d preempt=%d exec_shadow=%d\n",
595
//    lev, mut->owner,
596
//    mut->use[exec_shadow],
597
//    lev->proc_preempt[exec_shadow].preempt,exec_shadow);
14 pj 598
    kern_raise(XSRP_INVALID_LOCK, exec_shadow);
2 pj 599
    kern_sti();
600
    return (EINVAL);
601
  }
602
 
603
  /* we know that:
604
     - the task use the SRP protocol and the mutex that it wants to lock
605
     - the mutex is free
606
     => the task can lock now the mutex
607
  */
608
 
609
  lev->nlocked[exec_shadow]++;
610
  mut->owner = exec_shadow;
611
 
612
  oldsysceiling = sysceiling(lev);
613
 
614
  /* update the system ceiling */
615
  mut->sysceiling = (oldsysceiling>mut->ceiling) ?
616
                    oldsysceiling : mut->ceiling;
617
 
618
  /* update the srpstack */
619
  mut->srpstack_next = lev->srpstack;
620
  lev->srpstack = mut;
621
 
622
  /* if the system ceiling is changed we have to change the shadows
623
     Note that mut->sysceiling is the NEW sysceiling */
624
  if (oldsysceiling != mut->sysceiling) {
625
    /* we set the shadow of the last task that did a lock */
626
    if (mut->srpstack_next)
627
      proc_table[mut->srpstack_next->owner].shadow = exec_shadow;
628
 
629
    /* now we set the shadow field of the remainig tasks */
630
 
631
    /* first, get the first task to manage */
632
    if (lev->current == NIL)
633
      lev->current = lev->tasklist;
634
    else
635
      /* Note that because the sysceiling is increased by the lock, currrent
636
         can't be at the end of the tasklist, so the operation is legal */
637
      lev->current = lev->proc_preempt[lev->current].next;
638
 
639
    for (;;) {
640
      PID x;  /* for readablenesss only :-) */
641
 
642
      proc_table[lev->current].shadow = exec_shadow;
643
 
644
      /* test if we have to touch the next task in the tasklist */
645
      x = lev->proc_preempt[lev->current].next;
646
      if (x == NIL ||
647
          lev->proc_preempt[x].preempt > mut->sysceiling)
648
        break;
649
 
650
      /* look at the next task ! */
651
      lev->current = lev->proc_preempt[lev->current].next;
652
    }
653
  }
654
 
655
  kern_sti();
656
 
657
  return 0;
658
}
659
 
660
/* SRP_trylock is equal to SRP_lock because the SRP_lock don't block !!! */
661
 
662
static int SRP_unlock(RLEVEL l, mutex_t *m)
663
{
664
  SRP_mutex_resource_des *lev;
665
  SRP_mutex_t *mut;
666
  DWORD newsysceiling;
667
 
668
  lev = (SRP_mutex_resource_des *)(resource_table[l]);
669
  mut = (SRP_mutex_t *)m->opt;
670
 
671
  if (!mut)
672
    return (EINVAL);
673
 
674
  if (mut->owner != exec_shadow) {
675
    /* the mutex is owned by another task!!! */
676
    kern_sti();
677
    return (EPERM);
678
  }
679
 
680
  if (!lev->srpstack || lev->srpstack != mut) {
681
    /* the mutex is not the top of the stack!!! (erroneous nesting!) */
682
    kern_sti();
683
    return (EINVAL);
684
  }
685
 
686
  proc_table[exec_shadow].context = kern_context_save();
687
 
688
  /* the mutex is mine and it is at the top of the stack */
689
  lev->nlocked[exec_shadow]--;
690
 
691
  mut->owner = NIL;
692
//  kern_printf("Ûnlocked=%dÛ",lev->nlocked[exec_shadow]);
693
 
694
  /* extract the top of the stack */
695
  lev->srpstack = lev->srpstack->srpstack_next;
696
 
697
  /* if the sysceiling decreases, we update the shadows */
698
  newsysceiling = sysceiling(lev);
699
  if (newsysceiling < mut->sysceiling) {
700
    do {
701
      proc_table[lev->current].shadow = lev->current;
702
      lev->current = lev->proc_preempt[lev->current].prev;
703
    } while (lev->current != NIL &&
704
             lev->proc_preempt[lev->current].preempt > newsysceiling);
705
 
706
    if (lev->srpstack)
707
      /* this is the stack that owns the mutex with the current sysceiling*/
708
      proc_table[lev->srpstack->owner].shadow = lev->srpstack->owner;
709
  }
710
 
711
  /* if it is the last mutex in the stack, handle lobbylist and srprecalc */
712
  if (!lev->srpstack) {
713
//    kern_printf("UNLOBBY:");
714
    while (lev->lobbylist != NIL) {
715
      PID x = SRP_extractfirst_lobbylist(lev);
716
//      kern_printf("x=%d - ",x);
717
      SRP_insert_tasklist(lev, x);
718
 
719
      /* activate the task if it was activated while in lobby list! */
720
      if (task_unblock_activation(x)) {
721
        LEVEL sl = proc_table[x].task_level;
722
        level_table[sl]->task_activate(sl,x);
723
//        kern_printf("activate it!!!");
724
      }
725
    }
726
 
727
    while (lev->srprecalc) {
728
      SRP_recalc_ceiling_value(lev, lev->srprecalc);
729
      SRP_extract_recalclist(lev, lev->srprecalc);
730
    }
731
  }
732
 
733
  scheduler();
734
  kern_context_load(proc_table[exec_shadow].context);
735
 
736
  return 0;
737
}
738
 
739
void SRP_register_module(void)
740
{
741
  RLEVEL l;                  /* the level that we register */
742
  SRP_mutex_resource_des *m;  /* for readableness only */
743
  PID i;                     /* a counter */
744
 
745
  printk("SRP_register_module\n");
746
 
747
  /* request an entry in the level_table */
748
  l = resource_alloc_descriptor();
749
 
750
  /* alloc the space needed for the EDF_level_des */
751
  m = (SRP_mutex_resource_des *)kern_alloc(sizeof(SRP_mutex_resource_des));
752
 
753
  /* update the level_table with the new entry */
754
  resource_table[l] = (resource_des *)m;
755
 
756
  /* fill the resource_des descriptor */
757
  strncpy(m->m.r.res_name, SRP_MODULENAME, MAX_MODULENAME);
758
  m->m.r.res_code                    = SRP_MODULE_CODE;
759
  m->m.r.res_version                 = SRP_MODULE_VERSION;
760
 
761
  m->m.r.rtype                       = MUTEX_RTYPE;
762
 
763
  m->m.r.resource_status             = SRP_resource_status;
764
  m->m.r.level_accept_resource_model = SRP_level_accept_resource_model;
765
  m->m.r.res_register                = SRP_res_register;
766
 
767
  m->m.r.res_detach                  = SRP_res_detach;
768
 
769
  /* fill the mutex_resource_des descriptor */
770
  m->m.level_accept_mutexattr        = SRP_level_accept_mutexattr;
771
  m->m.init                          = SRP_init;
772
  m->m.destroy                       = SRP_destroy;
773
  m->m.lock                          = SRP_lock;
774
  m->m.trylock                       = SRP_lock;  /* equal!!! */
775
  m->m.unlock                        = SRP_unlock;
776
 
777
  /* fill the SRP_mutex_resource_des descriptor */
778
  for (i=0; i<MAX_PROC; i++) {
779
    m->nlocked[i]=0;
780
    m->proc_preempt[i].preempt = 0;
781
    m->proc_preempt[i].next = NIL;
782
    m->proc_preempt[i].prev = NIL;
783
  }
784
 
785
  m->tasklist = NIL;
786
  m->current = NIL;
787
  m->lobbylist = NIL;
788
 
789
  m->srpstack = NULL;
790
  m->srprecalc = NULL;
791
  m->srplist = NULL;
792
}
793