Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / rom / exec / obtainsemaphore.c
blob376aaa44ce7954e7fbf8fa376e93c1ebf94a9c19
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Lock a semaphore.
6 Lang: english
7 */
8 #include "exec_intern.h"
9 #include "semaphores.h"
10 #include <exec/semaphores.h>
11 #include <aros/atomic.h>
13 #include <proto/exec.h>
15 #define CHECK_INITSEM 1
17 /*****************************************************************************/
18 #undef Exec
19 #ifdef UseExecstubs
20 # define Exec _Exec
21 #endif
23 /* NAME */
24 #include <proto/exec.h>
26 AROS_LH1(void, ObtainSemaphore,
28 /* SYNOPSIS */
29 AROS_LHA(struct SignalSemaphore *, sigSem, A0),
31 /* LOCATION */
32 struct ExecBase *, SysBase, 94, Exec)
34 /* FUNCTION
35 Obtain an exclusive lock on a semaphore. If the semaphore is already
36 in use by another task this function will wait until the semaphore
37 becomes free.
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
52 ReleaseSemaphore()
54 INTERNALS
56 *****************************************************************************/
58 #undef Exec
60 AROS_LIBFUNC_INIT
62 struct Task *me;
64 /* Get pointer to current task */
65 me=SysBase->ThisTask;
68 * If there's no ThisTask, the function is called from within memory
69 * allocator in exec's pre-init code. We are already single-threaded,
70 * just return. :)
72 if (!me)
73 return;
75 #if CHECK_INITSEM
76 if (sigSem->ss_Link.ln_Type != NT_SIGNALSEM)
78 kprintf("\n\nObtainSemaphore called on a not intialized semaphore!!! "
79 "sem = %x task = %x (%s)\n\n", sigSem, me, me->tc_Node.ln_Name);
80 Alert(AN_SemCorrupt);
82 #endif
84 /* Arbitrate for the semaphore structure */
85 Forbid();
88 ss_QueueCount == -1 indicates that the semaphore is
89 free, so we increment this straight away. If it then
90 equals 0, then we are the first to allocate this semaphore.
92 Note: This will need protection for SMP machines.
94 sigSem->ss_QueueCount++;
95 if( sigSem->ss_QueueCount == 0 )
97 /* We now own the semaphore. This is quick. */
98 sigSem->ss_Owner = me;
99 sigSem->ss_NestCount++;
102 /* The semaphore was in use, but was it by us? */
103 else if( sigSem->ss_Owner == me )
105 /* Yes, just increase the nesting count */
106 sigSem->ss_NestCount++;
110 Else, some other task must own it. We have
111 to set a waiting request here.
113 else
116 We need a node to mark our semaphore request. Lets use some
117 stack memory.
119 struct SemaphoreRequest sr;
120 sr.sr_Waiter = me;
123 Have to clear the signal to make sure that we don't
124 return immediately. We then add the SemReq to the
125 waiters list of the semaphore. We were the last to
126 request, so we must be the last to get the semaphore.
129 /* This must be atomic! */
130 AROS_ATOMIC_AND(me->tc_SigRecvd, ~SIGF_SINGLE);
132 AddTail((struct List *)&sigSem->ss_WaitQueue, (struct Node *)&sr);
135 Finally, we simply wait, ReleaseSemaphore() will fill in
136 who owns the semaphore.
138 Wait(SIGF_SINGLE);
141 /* All Done! */
142 Permit();
144 AROS_LIBFUNC_EXIT
145 } /* ObtainSemaphore */