2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Get a shared lock on a semaphore.
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 /*****************************************************************************/
23 #include <proto/exec.h>
25 AROS_LH1(void, ObtainSemaphoreShared
,
28 AROS_LHA(struct SignalSemaphore
*, sigSem
, A0
),
31 struct ExecBase
*, SysBase
, 113, Exec
)
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
41 sigSem - Pointer to semaphore structure
46 This function preserves all registers.
57 *****************************************************************************/
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,
74 ASSERT_VALID_PTR(sigSem
);
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
);
86 /* Arbitrate for the semaphore structure */
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
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.
164 } /* ObtainSemaphoreShared */