2 Copyright © 1995-2001, 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 *****************************************************************************/
62 AROS_LIBBASE_EXT_DECL(struct ExecBase
*,SysBase
)
64 ASSERT_VALID_PTR(sigSem
);
66 /* Get pointer to current task */
67 struct Task
*me
= SysBase
->ThisTask
;
70 if (sigSem
->ss_Link
.ln_Type
!= NT_SIGNALSEM
)
72 kprintf("\n\nObtainSemaphoreShared called on a not intialized semaphore!!! "
73 "sem = %x task = %x (%s)\n\n", sigSem
, me
, me
->tc_Node
.ln_Name
);
79 /* Arbitrate for the semaphore structure */
83 ss_QueueCount == -1 indicates that the semaphore is
84 free, so we increment this straight away. If it then
85 equals 0, then we are the first to allocate this semaphore.
87 Note: This will need protection for SMP machines.
89 sigSem
->ss_QueueCount
++;
91 if( sigSem
->ss_QueueCount
== 0 )
94 We now own the semaphore. This is quick.
95 A shared semaphore does not have an owner, so we
96 mark the semaphore as shared by ss_Owner == NULL
98 sigSem
->ss_Owner
= NULL
;
99 sigSem
->ss_NestCount
++;
103 The semaphore is in use, but it could be shared. if it is,
104 ss_Owner == NULL. Or it could already be exclusively owned
105 by me. if it is, ss_Owner == me.
107 else if( (sigSem
->ss_Owner
== me
) || ( sigSem
->ss_Owner
== NULL
) )
109 /* Yes, just increase the nesting count */
110 sigSem
->ss_NestCount
++;
114 Otherwise it is an exclusive semaphore owned by someone else,
115 and we have to wait for it. This is pretty simple, we simply do
116 the same as for ObtainSemaphore(), but set that this is a
122 We need a node to mark our semaphore request. Lets use some
123 stack memory. This is nasty, but to mark that this is a
124 shared waiter we mark the ss_Waiter field with an odd
125 address. This is valid simply because we never run on an
126 architecture where an odd address is a valid task structure.
128 struct SemaphoreRequest sr
;
130 sr
.sr_Waiter
= (struct Task
*) ((UBYTE
*) me
+ 1);
132 bug("Task = %8lx, Waiter = %8lx\n", me
, sr
.sr_Waiter
);
135 Have to clear the signal to make sure that we don't
136 return immediately. We then add the SemReq to the
137 waiters list of the semaphore. We were the last to
138 request, so we must be the last to get the semaphore.
141 #warning this must be atomic
142 AROS_ATOMIC_AND(me
->tc_SigRecvd
, ~SIGF_SINGLE
);
144 AddTail((struct List
*)&sigSem
->ss_WaitQueue
, (struct Node
*)&sr
);
147 Finally, we simply wait, ReleaseSemaphore() will fill in
148 who owns the semaphore.
157 } /* ObtainSemaphoreShared */