Unification of "SEE ALSO" for exec.library
[cake.git] / rom / exec / releasesemaphore.c
blobb9a3cd9ad7c2720698aa9e95b7f19b5de750ea73
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Release a semaphore.
6 Lang: english
7 */
8 #include "exec_intern.h"
9 #include "semaphores.h"
10 #include <exec/semaphores.h>
11 #include <proto/exec.h>
13 #define CHECK_INITSEM 1
14 #define CHECK_TASK 0 /* it seems to be legal to call ObtainSemaphore in one task and ReleaseSemaphore in another */
16 /*****************************************************************************/
17 #undef Exec
18 #ifdef UseExecstubs
19 # define Exec _Exec
20 #endif
22 /* NAME */
23 #include <proto/exec.h>
25 AROS_LH1(void, ReleaseSemaphore,
27 /* SYNOPSIS */
28 AROS_LHA(struct SignalSemaphore *, sigSem, A0),
30 /* LOCATION */
31 struct ExecBase *, SysBase, 95, Exec)
33 /* FUNCTION
34 Releases a lock on a semaphore obtained with either ObtainSemaphore(),
35 ObtainSemaphoreShared(), AttemptSemaphore or AttemptSemaphoreShared().
36 Each call to one of those functions must be accompanied with one
37 call to ReleasSemaphore().
39 INPUTS
40 sigSem - pointer to semaphore structure
42 RESULT
44 NOTES
45 This function preserves all registers.
47 EXAMPLE
49 BUGS
51 SEE ALSO
53 INTERNALS
55 *****************************************************************************/
57 #undef Exec
59 AROS_LIBFUNC_INIT
61 #if CHECK_INITSEM
62 if (sigSem->ss_Link.ln_Type != NT_SIGNALSEM)
64 kprintf("\n\nReleaseSemaphore called on an unintialized semaphore!!! "
65 "sem = %x task = %x (%s)\n\n", sigSem, FindTask(0), FindTask(0)->tc_Node.ln_Name);
67 #endif
69 /* Protect the semaphore srtucture from multiple access. */
70 Forbid();
72 /* Release one on the nest count */
73 sigSem->ss_NestCount--;
74 sigSem->ss_QueueCount--;
76 if(sigSem->ss_NestCount == 0)
79 There are two cases here. Either we are a shared
80 semaphore, or not. If we are not, make sure that the
81 correct Task is calling ReleaseSemaphore()
84 #if CHECK_TASK
85 if( sigSem->ss_Owner != NULL && sigSem->ss_Owner != FindTask(NULL) )
88 If it is not, there is a chance that the semaphore
89 is corrupt. It will be afterwards anyway :-)
91 Alert( AN_SemCorrupt );
93 #endif
96 Do not try and wake anything unless there are a number
97 of tasks waiting. We do both the tests, this is another
98 opportunity to throw an alert if there is an error.
101 sigSem->ss_QueueCount >= 0
102 && sigSem->ss_WaitQueue.mlh_Head->mln_Succ != NULL
105 struct SemaphoreRequest *sr, *srn;
108 Look at the first node, but only to see whether it
109 is shared or not.
111 sr = (struct SemaphoreRequest *)sigSem->ss_WaitQueue.mlh_Head;
114 A node is shared if the ln_Name/sr_Waiter field is
115 odd (ie it has bit 1 set).
117 If the sr_Waiter field is != NULL, then this is a
118 task waiting, otherwise it is a message.
120 if( ((IPTR)sr->sr_Waiter & SM_SHARED) == SM_SHARED )
122 /* This is a shared lock, so ss_Owner == NULL */
123 sigSem->ss_Owner = NULL;
125 /* Go through all the nodes to find the shared ones */
126 ForeachNodeSafe( &sigSem->ss_WaitQueue, sr, srn)
128 srn = (struct SemaphoreRequest *)sr->sr_Link.mln_Succ;
130 if( ((IPTR)sr->sr_Waiter & SM_SHARED) == SM_SHARED )
132 Remove((struct Node *)sr);
134 /* Clear the bit, and update the owner count */
135 sr->sr_Waiter = (APTR)((IPTR)sr->sr_Waiter & ~1);
136 sigSem->ss_NestCount++;
138 if(sr->sr_Waiter != NULL)
140 /* This is a task, signal it */
141 Signal(sr->sr_Waiter, SIGF_SINGLE);
143 else
145 /* This is a message, send it back to its owner */
146 ((struct SemaphoreMessage *)sr)->ssm_Semaphore = sigSem;
147 ReplyMsg((struct Message *)sr);
153 /* This is an exclusive lock - awaken first node */
154 else
156 /* Save typing */
157 struct SemaphoreMessage *sm = (struct SemaphoreMessage *)sr;
159 /* Only awaken the first of the nodes */
160 Remove((struct Node *)sr);
161 sigSem->ss_NestCount++;
163 if(sr->sr_Waiter != NULL)
165 sigSem->ss_Owner = sr->sr_Waiter;
166 Signal(sr->sr_Waiter, SIGF_SINGLE);
168 else
170 sigSem->ss_Owner = (struct Task *)sm->ssm_Semaphore;
171 sm->ssm_Semaphore = sigSem;
172 ReplyMsg((struct Message *)sr);
175 } /* there are waiters */
177 /* Otherwise, there are not tasks waiting. */
178 else
180 sigSem->ss_Owner = NULL;
181 sigSem->ss_QueueCount = -1;
183 D(bug("ReleaseSemaphore(): No tasks - ss_NestCount == %ld\n",
184 sigSem->ss_NestCount));
187 else if(sigSem->ss_NestCount < 0)
190 This can't happen. It means that somebody has released
191 more times than they have obtained.
193 Alert( AN_SemCorrupt );
196 /* All done. */
197 Permit();
199 AROS_LIBFUNC_EXIT
200 } /* ReleaseSemaphore */