Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / rom / exec / obtainsemaphoreshared.c
blob53e9ed681425ea3030bad796eedba595af76e06a
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Get a shared lock on 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>
12 #include <proto/exec.h>
14 #define CHECK_INITSEM 1
16 /*****************************************************************************/
17 #undef Exec
18 #ifdef UseExecstubs
19 # define Exec _Exec
20 #endif
22 /* NAME */
23 #include <proto/exec.h>
25 AROS_LH1(void, ObtainSemaphoreShared,
27 /* SYNOPSIS */
28 AROS_LHA(struct SignalSemaphore *, sigSem, A0),
30 /* LOCATION */
31 struct ExecBase *, SysBase, 113, Exec)
33 /* FUNCTION
34 Get a shared lock on a semaphore. If the lock cannot be obtained
35 immediately this function waits. There may be more than one shared
36 locks at the same time but only one exclusive one. An exclusive
37 lock prevents shared locks. Shared locks are released with
38 ReleaseSemaphore().
40 INPUTS
41 sigSem - Pointer to semaphore structure
43 RESULT
45 NOTES
46 This function preserves all registers.
48 EXAMPLE
50 BUGS
52 SEE ALSO
53 ReleaseSemaphore()
55 INTERNALS
57 *****************************************************************************/
59 #undef Exec
61 AROS_LIBFUNC_INIT
63 /* Get pointer to current task */
64 struct Task *me = SysBase->ThisTask;
67 * If there's no ThisTask, the function is called from within memory
68 * allocator in exec's pre-init code. We are already single-threaded,
69 * just return. :)
71 if (!me)
72 return;
74 ASSERT_VALID_PTR(sigSem);
76 #if CHECK_INITSEM
77 if (sigSem->ss_Link.ln_Type != NT_SIGNALSEM)
79 kprintf("\n\nObtainSemaphoreShared called on a not intialized semaphore!!! "
80 "sem = %x task = %x (%s)\n\n", sigSem, me, me->tc_Node.ln_Name);
82 Alert(AN_SemCorrupt);
84 #endif
86 /* Arbitrate for the semaphore structure */
87 Forbid();
90 ss_QueueCount == -1 indicates that the semaphore is
91 free, so we increment this straight away. If it then
92 equals 0, then we are the first to allocate this semaphore.
94 Note: This will need protection for SMP machines.
96 sigSem->ss_QueueCount++;
98 if( sigSem->ss_QueueCount == 0 )
101 We now own the semaphore. This is quick.
102 A shared semaphore does not have an owner, so we
103 mark the semaphore as shared by ss_Owner == NULL
105 sigSem->ss_Owner = NULL;
106 sigSem->ss_NestCount++;
110 The semaphore is in use, but it could be shared. if it is,
111 ss_Owner == NULL. Or it could already be exclusively owned
112 by me. if it is, ss_Owner == me.
114 else if( (sigSem->ss_Owner == me) || ( sigSem->ss_Owner == NULL ) )
116 /* Yes, just increase the nesting count */
117 sigSem->ss_NestCount++;
121 Otherwise it is an exclusive semaphore owned by someone else,
122 and we have to wait for it. This is pretty simple, we simply do
123 the same as for ObtainSemaphore(), but set that this is a
124 shared semaphore.
126 else
129 We need a node to mark our semaphore request. Lets use some
130 stack memory. This is nasty, but to mark that this is a
131 shared waiter we mark the ss_Waiter field with an odd
132 address. This is valid simply because we never run on an
133 architecture where an odd address is a valid task structure.
135 struct SemaphoreRequest sr;
137 sr.sr_Waiter = (struct Task *) ((UBYTE *) me + 1);
139 D(bug("Task = %8lx, Waiter = %8lx\n", me, sr.sr_Waiter));
142 Have to clear the signal to make sure that we don't
143 return immediately. We then add the SemReq to the
144 waiters list of the semaphore. We were the last to
145 request, so we must be the last to get the semaphore.
148 /* WARNING: this must be atomic! */
149 AROS_ATOMIC_AND(me->tc_SigRecvd, ~SIGF_SINGLE);
151 AddTail((struct List *)&sigSem->ss_WaitQueue, (struct Node *)&sr);
154 Finally, we simply wait, ReleaseSemaphore() will fill in
155 who owns the semaphore.
157 Wait(SIGF_SINGLE);
160 /* All Done! */
161 Permit();
163 AROS_LIBFUNC_EXIT
164 } /* ObtainSemaphoreShared */