show more relevant debug
[AROS.git] / rom / exec / obtainsemaphorelist.c
blob7a9fe27618440acafc059109ea810c9d9a062006
1 /*
2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Lock all semaphores in the list at once.
6 Lang: english
7 */
8 #include "exec_intern.h"
9 #include "semaphores.h"
10 #include <exec/semaphores.h>
11 #include <proto/exec.h>
13 /*****************************************************************************
15 NAME */
17 AROS_LH1(void, ObtainSemaphoreList,
19 /* SYNOPSIS */
20 AROS_LHA(struct List *, sigSem, A0),
22 /* LOCATION */
23 struct ExecBase *, SysBase, 97, Exec)
25 /* FUNCTION
26 This function takes a list of semaphores and locks all of them at
27 once. It is only possible for one task to attempt to lock all the
28 semaphores at once (since it uses the ss_MultipleLink field), so
29 you will need to protect the entire list (with another semaphore
30 perhaps?).
32 If somebody attempts to lock more than one semaphore on this list
33 with ObtainSemaphore() it is possible for a deadlock to occur due
34 to two tasks waiting for a semaphore that the other has obtained.
36 INPUTS
37 sigSem - pointer to list full of semaphores
39 RESULT
40 The entire semaphore list will be locked.
42 NOTES
44 EXAMPLE
46 BUGS
48 SEE ALSO
50 INTERNALS
52 *****************************************************************************/
54 AROS_LIBFUNC_INIT
56 struct SignalSemaphore *ss;
57 struct Task * const ThisTask = GET_THIS_TASK;
58 WORD failedObtain = 0;
61 * The algorithm here is to attempt to lock all the semaphores in the
62 * list, and if any fail, to post a SemaphoreRequest for the
63 * semaphore.
65 * If we succeed in locking them all, we can return successfully,
66 * otherwise we must wait for the remaining semaphores to become
67 * available.
69 * Note that we sleep on each un-obtained semaphore as we pass through
70 * the list. This way by the time we get to the end of the list we can
71 * be sure that we have obtained all the semaphores. It is possible
72 * that whilst we are waiting for one semaphore, one later in the list
73 * will be granted to us. In that case we do not have to wait for it.
76 Forbid();
78 ForeachNode(sigSem, ss)
80 /* QueueCount == -1 means unlocked */
81 ss->ss_QueueCount++;
82 if(ss->ss_QueueCount != 0)
84 /* sem already locked by ThisTask? */
85 if (ss->ss_Owner != ThisTask)
88 * Locked by someone else, post a wait message. We use the field
89 * ss_MultipleLink, which is why this function requires an
90 * external arbitrator.
92 ss->ss_MultipleLink.sr_Waiter = ThisTask;
93 AddTail
95 (struct List *)&ss->ss_WaitQueue,
96 (struct Node *)&ss->ss_MultipleLink
98 failedObtain++;
100 else
102 /* Already locked by ThisTask */
103 ss->ss_NestCount++;
106 else
108 /* We have it... */
109 ss->ss_NestCount++;
110 ss->ss_Owner = ThisTask;
114 if(failedObtain > 0)
116 ss = (struct SignalSemaphore *)sigSem->lh_Head;
118 while(ss->ss_Link.ln_Succ != NULL)
120 if(ss->ss_Owner != ThisTask)
123 * Somebody else has this one. Wait, then check again.
124 * Check again because the signal could have been for a
125 * different semaphore in the list we are waiting for.
127 Wait(SIGF_SINGLE);
129 else
131 /* We got it, go on to the next one */
132 ss = (struct SignalSemaphore *)ss->ss_Link.ln_Succ;
133 failedObtain--;
138 #ifndef NO_CONSISTENCY_CHECKS
139 if(failedObtain != 0)
141 kprintf("\n\nObtainSemaList: Obtained count mismatch %d\n", failedObtain);
142 Alert(AN_BadSemaphore);
144 #endif
146 Permit();
148 AROS_LIBFUNC_EXIT
149 } /* ObtainSemaphoreList */