2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
5 Desc: Release a semaphore.
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 /*****************************************************************************/
23 #include <proto/exec.h>
25 AROS_LH1(void, ReleaseSemaphore
,
28 AROS_LHA(struct SignalSemaphore
*, sigSem
, A0
),
31 struct ExecBase
*, SysBase
, 95, Exec
)
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().
40 sigSem - pointer to semaphore structure
45 This function preserves all registers.
55 *****************************************************************************/
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
);
69 /* Protect the semaphore srtucture from multiple access. */
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()
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
);
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
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
);
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 */
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
);
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. */
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
);
200 } /* ReleaseSemaphore */