Subversion Repositories shark

Rev

Rev 14 | 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
 ------------
38 pj 23
 CVS :        $Id: srp.c,v 1.3 2003-01-07 17:07:51 pj Exp $
2 pj 24
 
25
 File:        $File$
38 pj 26
 Revision:    $Revision: 1.3 $
27
 Last update: $Date: 2003-01-07 17:07:51 $
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 <sys/types.h>
145
#include <kernel/descr.h>
146
#include <kernel/var.h>
147
#include <kernel/func.h>
148
 
149
typedef struct SRP_mutexstruct_t SRP_mutex_t;
150
 
151
/* The SRP resource level descriptor */
152
typedef struct {
153
  mutex_resource_des m;   /*+ the mutex interface +*/
154
 
155
  int nlocked[MAX_PROC];  /*+ how many mutex a task currently locks +*/
156
 
157
  struct {
158
    DWORD preempt;
159
    PID next;
160
    PID prev;
161
  } proc_preempt[MAX_PROC]; /*+ the preemption level of each task in the
162
                                system; if a task don't use SRP its value
163
                                is 0; if a task use SRP the field preempt
164
                                is != 0 and the item is enqueued in the
165
                                ordered list tasklist +*/
166
 
167
  PID tasklist;             /*+ A list of all the task that can use SRP,
168
                                ordered by the preemption level of each
169
                                task.                  +*/
170
  PID current;              /*+ A pointer used to set shadows +*/
171
 
172
  PID lobbylist;            /*+ A list for all the new tasks created when
173
                                the system ceiling is != 0. These tasks
174
                                will be inserted into tasklist when the
175
                                ceiling return to 0. +*/
176
  SRP_mutex_t *srpstack;    /*+ this is the stack where we store the system
177
                                ceiling +*/
178
 
179
  SRP_mutex_t *srprecalc;   /*+ the list of all mutexes that need a ceiling
180
                                recalc +*/
181
 
182
  SRP_mutex_t *srplist;     /*+ an unordered list of all created SRP
183
                                mutexes +*/
184
 
185
} SRP_mutex_resource_des;
186
 
187
 
188
/* this is the structure normally pointed by the opt field in the
189
   mutex_t structure */
190
struct SRP_mutexstruct_t {
191
  RES_MODEL r;  /*+ This little trick make possible the use of
192
                    SRP_usemutex                                +*/
193
 
194
  /* because the number of mutexes that can be created is not limited,
195
     the stack normally used to store the system ceiling is implemented
196
     through these two fields in the mutex descriptor. Note that the mutex
197
     are mono-resource, so when we alloc space for a mutex descriptor we
198
     alloc also the needed space for the stack... */
199
  DWORD sysceiling; /*+ The system ceiling; this field contains
200
                        - a meaningless value if the struct is not inserted
201
                          into the srpstack
202
                        - the system ceiling if the struct is on the top of
203
                          the srpstack
204
                        - a "frozen" system ceiling if the struct is not on
205
                          the top of the srpstack.
206
                        when a mutex is locked, it is inserted into srpstack
207
                        updating the system ceiling automatically
208
                        +*/
209
  SRP_mutex_t *srpstack_next; /*+ the next entry on the srpstack +*/
210
 
211
 
212
 
213
  BYTE use[MAX_PROC]; /*+ use[p]==1 if the task p declared that it uses the
214
                          mutex +*/
215
 
216
  DWORD ceiling;      /*+ max premption level of the tasks that use the mutex +*/
217
 
218
  PID owner;          /*+ the task that owns the mutex, NIL otherwise +*/
219
 
220
  int in_recalc_list; /*+ a flag: 1 if the mutex is in the recalc list +*/
221
  SRP_mutex_t *srprecalc_next; /*+ the next item in the recalc list +*/
222
  SRP_mutex_t *srprecalc_prev; /*+ the prev item; useful in extractions +*/
223
 
224
  SRP_mutex_t *srplist_next; /*+ the next item in the srplist list +*/
225
  SRP_mutex_t *srplist_prev; /*+ the prev item; useful in extractions+*/
226
};
227
 
228
 
229
 
230
 
231
 
232
 
233
 
234
 
235
 
236
 
237
 
238
/* -----------------------------------------------------------------------
239
   LISTS HANDLING
240
   ----------------------------------------------------------------------- */
241
 
242
/*+ this function inserts a task into the tasklist ordered list +*/
243
static void SRP_insert_tasklist(SRP_mutex_resource_des *m, PID t)
244
{
245
   PID p,q;
246
 
247
   p = NIL;
248
   q = m->tasklist;
249
 
250
   while ((q != NIL) &&
251
          (m->proc_preempt[t].preempt >= m->proc_preempt[q].preempt)) {
252
        p = q;
253
        q = m->proc_preempt[q].next;
254
   }
255
 
256
   if (p != NIL)
257
     m->proc_preempt[p].next = t;
258
   else
259
     m->tasklist = t;
260
 
261
   if (q != NIL) m->proc_preempt[q].prev = t;
262
 
263
   m->proc_preempt[t].next = q;
264
   m->proc_preempt[t].prev = p;
265
}
266
 
267
/*+ this function extracts a task from the tasklist +*/
268
static void SRP_extract_tasklist(SRP_mutex_resource_des *m, PID i)
269
{
270
    PID p,q;
271
 
272
    p = m->proc_preempt[i].prev;
273
    q = m->proc_preempt[i].next;
274
 
275
    if (p == NIL) m->tasklist = q;
276
    else m->proc_preempt[p].next = m->proc_preempt[i].next;
277
 
278
    if (q != NIL) m->proc_preempt[q].prev = m->proc_preempt[i].prev;
279
}
280
 
281
 
282
/*+ this function inserts a task into the lobbylist (in an unordered way) +*/
283
static void SRP_insertfirst_lobbylist(SRP_mutex_resource_des *m, PID p)
284
{
285
  m->proc_preempt[p].next = m->lobbylist;
286
  m->proc_preempt[p].prev = NIL;
287
 
288
  m->proc_preempt[m->lobbylist].prev = p;
289
  m->lobbylist = p;
290
}
291
 
292
/*+ this function extract the first task from the lobbylist
293
    the lobbylist must be not-empty!!!! +*/
294
static __inline__ PID SRP_extractfirst_lobbylist(SRP_mutex_resource_des *m)
295
{
296
  PID lobby = m->lobbylist;
297
  m->lobbylist = m->proc_preempt[m->lobbylist].next;
298
  return lobby;
299
}
300
 
301
 
302
 
303
/*+ This function insert a mutex into the recalc list ONLY if the mutex
304
    isn't already in that list... +*/
305
static void SRP_insertfirst_recalclist(SRP_mutex_resource_des *m,
306
                                      SRP_mutex_t *mut)
307
{
308
  if (!mut->in_recalc_list) {
309
    mut->srprecalc_next = m->srprecalc;
310
    mut->srprecalc_prev = NULL;
311
    if (m->srprecalc) m->srprecalc->srprecalc_prev = mut;
312
    m->srprecalc = mut;
313
 
314
    mut->in_recalc_list = 1;
315
  }
316
}
317
 
318
/*+ this function extracts mut from the list l. +*/
319
static void SRP_extract_recalclist(SRP_mutex_resource_des *m,
320
                                   SRP_mutex_t *mut)
321
{
322
  SRP_mutex_t *p, *q;
323
 
324
  p = mut->srprecalc_prev;
325
  q = mut->srprecalc_next;
326
 
327
  if (p)
328
    p->srprecalc_next = mut->srprecalc_next;
329
  else
330
    m->srprecalc = q;
331
 
332
  if (q) q->srprecalc_prev = mut->srprecalc_prev;
333
}
334
 
335
/*+ this function extracts mut from the list l. +*/
336
static void SRP_extract_srplist(SRP_mutex_resource_des *m,
337
                                SRP_mutex_t *mut)
338
{
339
  SRP_mutex_t *p, *q;
340
 
341
  p = mut->srplist_prev;
342
  q = mut->srplist_next;
343
 
344
  if (p)
345
    p->srplist_next = mut->srplist_next;
346
  else
347
    m->srplist = q;
348
 
349
  if (q) q->srplist_prev = mut->srplist_prev;
350
}
351
 
352
 
353
 
354
/* -----------------------------------------------------------------------
355
   End of LISTS HANDLING
356
   ----------------------------------------------------------------------- */
357
 
358
 
359
 
360
 
361
/*+ This funcyion returns the actual system ceiling +*/
362
static __inline__ DWORD sysceiling(SRP_mutex_resource_des *m)
363
{
364
  if (m->srpstack)
365
    return m->srpstack->sysceiling;
366
  else
367
    return 0;
368
}
369
 
370
/*+ this function recalc the mutex ceiling basing on the preemption levels
371
    stored in the mevel m +*/
372
static void SRP_recalc_ceiling_value(SRP_mutex_resource_des *m,
373
                                     SRP_mutex_t *mut)
374
{
375
  PID p;
376
  int ceiling;
377
 
378
  ceiling = 0;
379
  for (p = 0; p < MAX_PROC; p++)
380
    if (mut->use[p] && ceiling < m->proc_preempt[p].preempt)
381
      ceiling = m->proc_preempt[p].preempt;
382
 
383
  mut->ceiling = ceiling;
384
}
385
 
386
 
38 pj 387
static int SRP_res_register(RLEVEL l, PID p, RES_MODEL *r)
2 pj 388
{
38 pj 389
  SRP_mutex_resource_des *m = (SRP_mutex_resource_des *)(resource_table[l]);
2 pj 390
 
38 pj 391
  if (r->level && r->level !=l)
2 pj 392
    return -1;
393
 
38 pj 394
  if (r->rclass == SRP_RCLASS) {
2 pj 395
    /* SRP_RES_MODEL resource model */
396
//  kern_printf("!%d %d",((SRP_RES_MODEL *)r)->preempt,p);
397
 
398
    if (m->proc_preempt[p].preempt == 0) {
399
      /* only the first SRP_RES_MODEL is considered */
400
      SRP_RES_MODEL *srp = (SRP_RES_MODEL *)r;
401
 
402
      m->proc_preempt[p].preempt = srp->preempt;
403
//      kern_printf("res_register: preempt=%d, p=%d\n",srp->preempt,p);
404
 
405
      /* insert the new task in the ordered list tasklist or in the lobby
406
         list */
407
      if (m->srpstack) {
408
        SRP_insertfirst_lobbylist(m,p);
409
        /* we have also to freeze the activations... */
410
        task_block_activation(p);
411
//        kern_printf("LOBBY!!!");
412
      }
413
      else
414
        SRP_insert_tasklist(m,p);
415
    }
416
 
417
    m->nlocked[p] = 0;
38 pj 418
    return 0;
2 pj 419
  }
38 pj 420
  else if (r->rclass == SRP2_RCLASS) {
2 pj 421
    /* a mutex passed via SRP_useres() */
422
    SRP_mutex_t *mut = (SRP_mutex_t *)r;
423
 
424
    if (mut->use[p])
425
      /* the mutex is already registered, do nothing! */
38 pj 426
      return -1;
2 pj 427
 
428
    /* register the mutex for the task */
429
    mut->use[p] = 1;
430
 
431
    if (m->srpstack)
432
      SRP_insertfirst_recalclist(m,mut);
433
    else {
434
      /* we recalc the mutex ceiling */
435
      if (mut->ceiling < m->proc_preempt[p].preempt)
436
        mut->ceiling = m->proc_preempt[p].preempt;
437
 
438
    }
38 pj 439
    return 0;
2 pj 440
  }
38 pj 441
  else
442
    return -1;
2 pj 443
}
444
 
445
static void SRP_res_detach(RLEVEL l, PID p)
446
{
447
  SRP_mutex_resource_des *m = (SRP_mutex_resource_des *)(resource_table[l]);
448
  SRP_mutex_t *mut;
449
 
450
  if (m->proc_preempt[p].preempt == 0)
451
    return;
452
 
453
  if (m->nlocked[p])
454
    kern_raise(XMUTEX_OWNER_KILLED, p);
455
  else
456
    m->nlocked[p] = 0;
457
 
458
  for (mut = m->srplist; mut; mut = mut->srplist_next)
459
  {
460
    if (!mut->use[p])
461
      /* the mutex is not registered, do nothing! */
462
      continue;
463
 
464
    /* unregister the mutex for the task */
465
    mut->use[p] = 0;
466
 
467
    if (m->srpstack)
468
      SRP_insertfirst_recalclist(m,mut);
469
    else
470
      SRP_recalc_ceiling_value(m,mut);
471
  }
472
 
473
  /* check if current points to the task being killed */
474
  if (m->current == p)
475
    m->current = m->proc_preempt[m->current].prev;
476
 
477
  /* remove the task from the tasklist */
478
  SRP_extract_tasklist(m, p);
479
}
480
 
481
static int SRP_init(RLEVEL l, mutex_t *m, const mutexattr_t *a)
482
{
483
  SRP_mutex_resource_des *lev = (SRP_mutex_resource_des *)(resource_table[l]);
484
  SRP_mutex_t *p;
485
  PID x;
486
 
38 pj 487
  if (a->mclass != SRP_MCLASS)
488
    return -1;
489
 
2 pj 490
  p = (SRP_mutex_t *) kern_alloc(sizeof(SRP_mutex_t));
491
 
492
  /* control if there is enough memory; no control on init on a
493
     non- destroyed mutex */
494
 
495
  if (!p)
496
    return (ENOMEM);
497
 
498
  res_default_model(p->r, SRP2_RCLASS);
499
  p->sysceiling    = 0;     /* dummy value :-) */
500
  p->srpstack_next = NULL;  /* dummy value :-) */
501
 
502
  for (x = 0; x < MAX_PROC; x++)
503
    p->use[x] = 0;
504
 
505
  p->ceiling = 0;
506
  p->owner = NIL;
507
 
508
  p->in_recalc_list = 0;
509
  p->srprecalc_next = NULL; /* dummy value :-) */
510
  p->srprecalc_prev = NULL; /* dummy value :-) */
511
 
512
  p->srplist_next = lev->srplist;
513
  p->srplist_prev = NULL;
514
  if (lev->srplist) lev->srplist->srplist_prev = p;
515
  lev->srplist = p;
516
 
517
  m->mutexlevel = l;
518
  m->opt = (void *)p;
519
 
520
  return 0;
521
}
522
 
523
 
524
static int SRP_destroy(RLEVEL l, mutex_t *m)
525
{
526
  SRP_mutex_resource_des *lev = (SRP_mutex_resource_des *)(resource_table[l]);
527
  SRP_mutex_t *mut;
528
 
529
  mut = m->opt;
530
 
531
  if (mut->owner != NIL)
532
    return (EBUSY);
533
 
534
  kern_cli();
535
 
536
  /* the mutex isn't in the srpstack, because it is not busy */
537
 
538
  /* check srprecalc list */
539
  if (mut->in_recalc_list)
540
    SRP_extract_recalclist(lev, mut);
541
 
542
  /* extract from srplist */
543
  SRP_extract_srplist(lev, mut);
544
 
545
  if (m->opt) {
546
    kern_free(m->opt,sizeof(SRP_mutex_t));
547
    m->opt = NULL;
548
  }
549
  kern_sti();
550
 
551
  return 0;
552
}
553
 
554
static int SRP_lock(RLEVEL l, mutex_t *m)
555
{
556
  SRP_mutex_resource_des *lev = (SRP_mutex_resource_des *)(resource_table[l]);
557
  SRP_mutex_t *mut;
558
  DWORD oldsysceiling;
559
 
560
  kern_cli();
561
 
562
  mut = (SRP_mutex_t *)m->opt;
563
  if (!mut) {
564
    /* if the mutex is not initialized */
565
    kern_sti();
566
    return (EINVAL);
567
  }
568
 
569
  if (mut->owner == exec_shadow) {
570
    /* the task already owns the mutex */
571
    kern_sti();
572
    return (EDEADLK);
573
  }
574
 
575
  if (!mut->use[exec_shadow] ||
576
      lev->proc_preempt[exec_shadow].preempt == 0 ||
577
      mut->owner != NIL)
578
  {
579
//    kern_printf("SRP:lev =%d owner=%d use=%d preempt=%d exec_shadow=%d\n",
580
//    lev, mut->owner,
581
//    mut->use[exec_shadow],
582
//    lev->proc_preempt[exec_shadow].preempt,exec_shadow);
14 pj 583
    kern_raise(XSRP_INVALID_LOCK, exec_shadow);
2 pj 584
    kern_sti();
585
    return (EINVAL);
586
  }
587
 
588
  /* we know that:
589
     - the task use the SRP protocol and the mutex that it wants to lock
590
     - the mutex is free
591
     => the task can lock now the mutex
592
  */
593
 
594
  lev->nlocked[exec_shadow]++;
595
  mut->owner = exec_shadow;
596
 
597
  oldsysceiling = sysceiling(lev);
598
 
599
  /* update the system ceiling */
600
  mut->sysceiling = (oldsysceiling>mut->ceiling) ?
601
                    oldsysceiling : mut->ceiling;
602
 
603
  /* update the srpstack */
604
  mut->srpstack_next = lev->srpstack;
605
  lev->srpstack = mut;
606
 
607
  /* if the system ceiling is changed we have to change the shadows
608
     Note that mut->sysceiling is the NEW sysceiling */
609
  if (oldsysceiling != mut->sysceiling) {
610
    /* we set the shadow of the last task that did a lock */
611
    if (mut->srpstack_next)
612
      proc_table[mut->srpstack_next->owner].shadow = exec_shadow;
613
 
614
    /* now we set the shadow field of the remainig tasks */
615
 
616
    /* first, get the first task to manage */
617
    if (lev->current == NIL)
618
      lev->current = lev->tasklist;
619
    else
620
      /* Note that because the sysceiling is increased by the lock, currrent
621
         can't be at the end of the tasklist, so the operation is legal */
622
      lev->current = lev->proc_preempt[lev->current].next;
623
 
624
    for (;;) {
625
      PID x;  /* for readablenesss only :-) */
626
 
627
      proc_table[lev->current].shadow = exec_shadow;
628
 
629
      /* test if we have to touch the next task in the tasklist */
630
      x = lev->proc_preempt[lev->current].next;
631
      if (x == NIL ||
632
          lev->proc_preempt[x].preempt > mut->sysceiling)
633
        break;
634
 
635
      /* look at the next task ! */
636
      lev->current = lev->proc_preempt[lev->current].next;
637
    }
638
  }
639
 
640
  kern_sti();
641
 
642
  return 0;
643
}
644
 
645
/* SRP_trylock is equal to SRP_lock because the SRP_lock don't block !!! */
646
 
647
static int SRP_unlock(RLEVEL l, mutex_t *m)
648
{
649
  SRP_mutex_resource_des *lev;
650
  SRP_mutex_t *mut;
651
  DWORD newsysceiling;
652
 
653
  lev = (SRP_mutex_resource_des *)(resource_table[l]);
654
  mut = (SRP_mutex_t *)m->opt;
655
 
656
  if (!mut)
657
    return (EINVAL);
658
 
659
  if (mut->owner != exec_shadow) {
660
    /* the mutex is owned by another task!!! */
661
    kern_sti();
662
    return (EPERM);
663
  }
664
 
665
  if (!lev->srpstack || lev->srpstack != mut) {
666
    /* the mutex is not the top of the stack!!! (erroneous nesting!) */
667
    kern_sti();
668
    return (EINVAL);
669
  }
670
 
671
  proc_table[exec_shadow].context = kern_context_save();
672
 
673
  /* the mutex is mine and it is at the top of the stack */
674
  lev->nlocked[exec_shadow]--;
675
 
676
  mut->owner = NIL;
677
//  kern_printf("Ûnlocked=%dÛ",lev->nlocked[exec_shadow]);
678
 
679
  /* extract the top of the stack */
680
  lev->srpstack = lev->srpstack->srpstack_next;
681
 
682
  /* if the sysceiling decreases, we update the shadows */
683
  newsysceiling = sysceiling(lev);
684
  if (newsysceiling < mut->sysceiling) {
685
    do {
686
      proc_table[lev->current].shadow = lev->current;
687
      lev->current = lev->proc_preempt[lev->current].prev;
688
    } while (lev->current != NIL &&
689
             lev->proc_preempt[lev->current].preempt > newsysceiling);
690
 
691
    if (lev->srpstack)
692
      /* this is the stack that owns the mutex with the current sysceiling*/
693
      proc_table[lev->srpstack->owner].shadow = lev->srpstack->owner;
694
  }
695
 
696
  /* if it is the last mutex in the stack, handle lobbylist and srprecalc */
697
  if (!lev->srpstack) {
698
//    kern_printf("UNLOBBY:");
699
    while (lev->lobbylist != NIL) {
700
      PID x = SRP_extractfirst_lobbylist(lev);
701
//      kern_printf("x=%d - ",x);
702
      SRP_insert_tasklist(lev, x);
703
 
704
      /* activate the task if it was activated while in lobby list! */
705
      if (task_unblock_activation(x)) {
706
        LEVEL sl = proc_table[x].task_level;
38 pj 707
        level_table[sl]->public_activate(sl,x);
2 pj 708
//        kern_printf("activate it!!!");
709
      }
710
    }
711
 
712
    while (lev->srprecalc) {
713
      SRP_recalc_ceiling_value(lev, lev->srprecalc);
714
      SRP_extract_recalclist(lev, lev->srprecalc);
715
    }
716
  }
717
 
718
  scheduler();
719
  kern_context_load(proc_table[exec_shadow].context);
720
 
721
  return 0;
722
}
723
 
38 pj 724
RLEVEL SRP_register_module(void)
2 pj 725
{
726
  RLEVEL l;                  /* the level that we register */
727
  SRP_mutex_resource_des *m;  /* for readableness only */
728
  PID i;                     /* a counter */
729
 
730
  printk("SRP_register_module\n");
731
 
732
  /* request an entry in the level_table */
733
  l = resource_alloc_descriptor();
734
 
735
  /* alloc the space needed for the EDF_level_des */
736
  m = (SRP_mutex_resource_des *)kern_alloc(sizeof(SRP_mutex_resource_des));
737
 
738
  /* update the level_table with the new entry */
739
  resource_table[l] = (resource_des *)m;
740
 
741
  /* fill the resource_des descriptor */
742
  m->m.r.rtype                       = MUTEX_RTYPE;
743
  m->m.r.res_register                = SRP_res_register;
744
  m->m.r.res_detach                  = SRP_res_detach;
745
 
746
  /* fill the mutex_resource_des descriptor */
747
  m->m.init                          = SRP_init;
748
  m->m.destroy                       = SRP_destroy;
749
  m->m.lock                          = SRP_lock;
750
  m->m.trylock                       = SRP_lock;  /* equal!!! */
751
  m->m.unlock                        = SRP_unlock;
752
 
753
  /* fill the SRP_mutex_resource_des descriptor */
754
  for (i=0; i<MAX_PROC; i++) {
755
    m->nlocked[i]=0;
756
    m->proc_preempt[i].preempt = 0;
757
    m->proc_preempt[i].next = NIL;
758
    m->proc_preempt[i].prev = NIL;
759
  }
760
 
761
  m->tasklist = NIL;
762
  m->current = NIL;
763
  m->lobbylist = NIL;
764
 
765
  m->srpstack = NULL;
766
  m->srprecalc = NULL;
767
  m->srplist = NULL;
38 pj 768
 
769
  return l;
2 pj 770
}
771