Subversion Repositories shark

Rev

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