Support rastport clipping rectangle for layerless rastports
[tangerine.git] / rom / exec / obtainsemaphoreshared.c
blob2dab1413fb519afe79b63d8d17b63bb4c2ee2a78
1 /*
2 Copyright © 1995-2001, 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
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;
69 #if CHECK_INITSEM
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);
75 Alert(AN_SemCorrupt);
77 #endif
79 /* Arbitrate for the semaphore structure */
80 Forbid();
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
117 shared semaphore.
119 else
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.
150 Wait(SIGF_SINGLE);
153 /* All Done! */
154 Permit();
156 AROS_LIBFUNC_EXIT
157 } /* ObtainSemaphoreShared */