2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
5 Desc: Lock all semaphores in the list at once.
8 #include "exec_intern.h"
9 #include "semaphores.h"
10 #include <exec/semaphores.h>
11 #include <proto/exec.h>
13 /*****************************************************************************
17 AROS_LH1(void, ObtainSemaphoreList
,
20 AROS_LHA(struct List
*, sigSem
, A0
),
23 struct ExecBase
*, SysBase
, 97, Exec
)
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
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.
37 sigSem - pointer to list full of semaphores
40 The entire semaphore list will be locked.
52 *****************************************************************************/
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
65 * If we succeed in locking them all, we can return successfully,
66 * otherwise we must wait for the remaining semaphores to become
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.
78 ForeachNode(sigSem
, ss
)
80 /* QueueCount == -1 means unlocked */
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
;
95 (struct List
*)&ss
->ss_WaitQueue
,
96 (struct Node
*)&ss
->ss_MultipleLink
102 /* Already locked by ThisTask */
110 ss
->ss_Owner
= ThisTask
;
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.
131 /* We got it, go on to the next one */
132 ss
= (struct SignalSemaphore
*)ss
->ss_Link
.ln_Succ
;
138 #ifndef NO_CONSISTENCY_CHECKS
139 if(failedObtain
!= 0)
141 kprintf("\n\nObtainSemaList: Obtained count mismatch %d\n", failedObtain
);
142 Alert(AN_BadSemaphore
);
149 } /* ObtainSemaphoreList */