Updated PCI IDs to latest snapshot.
[tangerine.git] / rom / exec / obtainsemaphoreshared.c
blob598ad2bc74c98db65e3be7b752d62cda91f73fc1
1 /*
2 Copyright © 1995-2007, 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 ASSERT_VALID_PTR(sigSem);
65 /* Get pointer to current task */
66 struct Task *me = SysBase->ThisTask;
68 #if CHECK_INITSEM
69 if (sigSem->ss_Link.ln_Type != NT_SIGNALSEM)
71 kprintf("\n\nObtainSemaphoreShared called on a not intialized semaphore!!! "
72 "sem = %x task = %x (%s)\n\n", sigSem, me, me->tc_Node.ln_Name);
74 Alert(AN_SemCorrupt);
76 #endif
78 /* Arbitrate for the semaphore structure */
79 Forbid();
82 ss_QueueCount == -1 indicates that the semaphore is
83 free, so we increment this straight away. If it then
84 equals 0, then we are the first to allocate this semaphore.
86 Note: This will need protection for SMP machines.
88 sigSem->ss_QueueCount++;
90 if( sigSem->ss_QueueCount == 0 )
93 We now own the semaphore. This is quick.
94 A shared semaphore does not have an owner, so we
95 mark the semaphore as shared by ss_Owner == NULL
97 sigSem->ss_Owner = NULL;
98 sigSem->ss_NestCount++;
102 The semaphore is in use, but it could be shared. if it is,
103 ss_Owner == NULL. Or it could already be exclusively owned
104 by me. if it is, ss_Owner == me.
106 else if( (sigSem->ss_Owner == me) || ( sigSem->ss_Owner == NULL ) )
108 /* Yes, just increase the nesting count */
109 sigSem->ss_NestCount++;
113 Otherwise it is an exclusive semaphore owned by someone else,
114 and we have to wait for it. This is pretty simple, we simply do
115 the same as for ObtainSemaphore(), but set that this is a
116 shared semaphore.
118 else
121 We need a node to mark our semaphore request. Lets use some
122 stack memory. This is nasty, but to mark that this is a
123 shared waiter we mark the ss_Waiter field with an odd
124 address. This is valid simply because we never run on an
125 architecture where an odd address is a valid task structure.
127 struct SemaphoreRequest sr;
129 sr.sr_Waiter = (struct Task *) ((UBYTE *) me + 1);
131 bug("Task = %8lx, Waiter = %8lx\n", me, sr.sr_Waiter);
134 Have to clear the signal to make sure that we don't
135 return immediately. We then add the SemReq to the
136 waiters list of the semaphore. We were the last to
137 request, so we must be the last to get the semaphore.
140 #warning this must be atomic
141 AROS_ATOMIC_AND(me->tc_SigRecvd, ~SIGF_SINGLE);
143 AddTail((struct List *)&sigSem->ss_WaitQueue, (struct Node *)&sr);
146 Finally, we simply wait, ReleaseSemaphore() will fill in
147 who owns the semaphore.
149 Wait(SIGF_SINGLE);
152 /* All Done! */
153 Permit();
155 AROS_LIBFUNC_EXIT
156 } /* ObtainSemaphoreShared */