2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Release a semaphore.
9 #include <exec/semaphores.h>
10 #include <proto/exec.h>
12 #include "exec_intern.h"
13 #include "exec_util.h"
14 #include "semaphores.h"
16 #define CHECK_TASK 0 /* it seems to be legal to call ObtainSemaphore in one task and ReleaseSemaphore in another */
18 /*****************************************************************************/
25 #include <proto/exec.h>
27 AROS_LH1(void, ReleaseSemaphore
,
30 AROS_LHA(struct SignalSemaphore
*, sigSem
, A0
),
33 struct ExecBase
*, SysBase
, 95, Exec
)
36 Releases a lock on a semaphore obtained with either ObtainSemaphore(),
37 ObtainSemaphoreShared(), AttemptSemaphore or AttemptSemaphoreShared().
38 Each call to one of those functions must be accompanied with one
39 call to ReleasSemaphore().
42 sigSem - pointer to semaphore structure
47 This function preserves all registers.
57 *****************************************************************************/
63 struct TraceLocation tp
= CURRENT_LOCATION("ReleaseSemaphore");
64 struct Task
*me
= FindTask(NULL
);
66 /* We can be called from within exec's pre-init code. It's okay. */
70 if (me
->tc_State
== TS_REMOVED
)
73 if (!CheckSemaphore(sigSem
, &tp
, SysBase
))
76 /* Protect the semaphore structure from multiple access. */
79 /* Release one on the nest count */
80 sigSem
->ss_NestCount
--;
81 sigSem
->ss_QueueCount
--;
83 if(sigSem
->ss_NestCount
== 0)
86 There are two cases here. Either we are a shared
87 semaphore, or not. If we are not, make sure that the
88 correct Task is calling ReleaseSemaphore()
92 if (sigSem
->ss_Owner
!= NULL
&& sigSem
->ss_Owner
!= me
)
95 If it is not, there is a chance that the semaphore
96 is corrupt. It will be afterwards anyway :-)
98 Alert( AN_SemCorrupt
);
103 Do not try and wake anything unless there are a number
104 of tasks waiting. We do both the tests, this is another
105 opportunity to throw an alert if there is an error.
108 sigSem
->ss_QueueCount
>= 0
109 && sigSem
->ss_WaitQueue
.mlh_Head
->mln_Succ
!= NULL
112 struct SemaphoreRequest
*sr
, *srn
;
115 Look at the first node, but only to see whether it
118 sr
= (struct SemaphoreRequest
*)sigSem
->ss_WaitQueue
.mlh_Head
;
121 A node is shared if the ln_Name/sr_Waiter field is
122 odd (ie it has bit 1 set).
124 If the sr_Waiter field is != NULL, then this is a
125 task waiting, otherwise it is a message.
127 if( ((IPTR
)sr
->sr_Waiter
& SM_SHARED
) == SM_SHARED
)
129 /* This is a shared lock, so ss_Owner == NULL */
130 sigSem
->ss_Owner
= NULL
;
132 /* Go through all the nodes to find the shared ones */
133 ForeachNodeSafe( &sigSem
->ss_WaitQueue
, sr
, srn
)
135 srn
= (struct SemaphoreRequest
*)sr
->sr_Link
.mln_Succ
;
137 if( ((IPTR
)sr
->sr_Waiter
& SM_SHARED
) == SM_SHARED
)
139 Remove((struct Node
*)sr
);
141 /* Clear the bit, and update the owner count */
142 sr
->sr_Waiter
= (APTR
)((IPTR
)sr
->sr_Waiter
& ~1);
143 sigSem
->ss_NestCount
++;
145 if(sr
->sr_Waiter
!= NULL
)
147 /* This is a task, signal it */
148 Signal(sr
->sr_Waiter
, SIGF_SINGLE
);
152 /* This is a message, send it back to its owner */
153 ((struct SemaphoreMessage
*)sr
)->ssm_Semaphore
= sigSem
;
154 ReplyMsg((struct Message
*)sr
);
160 /* This is an exclusive lock - awaken first node */
164 struct SemaphoreMessage
*sm
= (struct SemaphoreMessage
*)sr
;
166 /* Only awaken the first of the nodes */
167 Remove((struct Node
*)sr
);
168 sigSem
->ss_NestCount
++;
170 if(sr
->sr_Waiter
!= NULL
)
172 sigSem
->ss_Owner
= sr
->sr_Waiter
;
173 Signal(sr
->sr_Waiter
, SIGF_SINGLE
);
177 sigSem
->ss_Owner
= (struct Task
*)sm
->ssm_Semaphore
;
178 sm
->ssm_Semaphore
= sigSem
;
179 ReplyMsg((struct Message
*)sr
);
182 } /* there are waiters */
184 /* Otherwise, there are not tasks waiting. */
187 sigSem
->ss_Owner
= NULL
;
188 sigSem
->ss_QueueCount
= -1;
190 D(bug("ReleaseSemaphore(): No tasks - ss_NestCount == %ld\n",
191 sigSem
->ss_NestCount
));
194 else if(sigSem
->ss_NestCount
< 0)
197 This can't happen. It means that somebody has released
198 more times than they have obtained.
200 Alert( AN_SemCorrupt
);
207 } /* ReleaseSemaphore */