r4722@vps: verhaegs | 2007-05-06 13:11:19 -0400
[cake.git] / rom / exec / procure.c
blob331322783b0b1b8b92aaa2df42d76809734545eb
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Try to lock a semaphore.
6 Lang: english
7 */
8 #include "exec_intern.h"
9 #include "semaphores.h"
10 #include <exec/semaphores.h>
11 #include <proto/exec.h>
13 /*****************************************************************************
15 NAME */
17 AROS_LH2(ULONG, Procure,
19 /* SYNOPSIS */
20 AROS_LHA(struct SignalSemaphore *, sigSem, A0),
21 AROS_LHA(struct SemaphoreMessage *, bidMsg, A1),
23 /* LOCATION */
24 struct ExecBase *, SysBase, 90, Exec)
26 /* FUNCTION
27 Tries to get a lock on a semaphore in an asynchronous manner.
28 If the semaphore is not free this function will not wait but
29 just post a request to the semaphore. As soon as the semaphore is
30 available the bidMsg will return and make you owner of the semaphore.
32 INPUTS
33 sigSem - pointer to semaphore structure
34 bidMsg - pointer to a struct SemaphoreMessage. This should lie in
35 public or at least shared memory.
37 RESULT
38 Principly none. Don't know. Just ignore it.
40 NOTES
41 Locks obtained with Procure() must be released with Vacate().
43 EXAMPLE
45 BUGS
47 SEE ALSO
48 Vacate()
50 INTERNALS
52 *****************************************************************************/
54 AROS_LIBFUNC_INIT
56 /* Prepare semaphore message to be a sent message */
57 bidMsg->ssm_Message.mn_Length=sizeof(struct SemaphoreMessage);
60 * If ln_Name field of message == 1, then this is a shared message, so
61 * we set the field to NULL. Otherwise, set it to the task requesting
62 * the semaphore. By the end, the ssm_Semaphore field contains the new
63 * owner of the semaphore.
65 if( (IPTR)(bidMsg->ssm_Message.mn_Node.ln_Name) == SM_SHARED )
66 bidMsg->ssm_Semaphore = NULL;
67 else
68 bidMsg->ssm_Semaphore = (struct SignalSemaphore *)FindTask(NULL);
70 /* Arbitrate for the semaphore structure - following like ObtainSema() */
71 Forbid();
73 sigSem->ss_QueueCount++;
75 Check if we own it
77 if( sigSem->ss_QueueCount == 0 )
79 /* No, and neither does anybody else - claim it as ours. */
80 sigSem->ss_Owner = (struct Task *)bidMsg->ssm_Semaphore;
81 sigSem->ss_NestCount++;
82 bidMsg->ssm_Semaphore = sigSem;
83 ReplyMsg((struct Message *)sigSem);
86 Otherwise check if we already own it
88 else if( sigSem->ss_Owner == (struct Task *)bidMsg->ssm_Semaphore )
90 /* Yes we do... */
91 sigSem->ss_NestCount++;
92 bidMsg->ssm_Semaphore = sigSem;
93 ReplyMsg((struct Message *)sigSem);
97 It is owned by somebody else, set up the waiter
99 else
101 struct SemaphoreRequest *sr;
103 * Unholy Hack v1.
105 * Whoever came up with this obviously has a twisted mind. We
106 * pretend that the SemaphoreMessage is really a SemaphoreRequest.
107 * Now, the code in ReleaseSemaphore that deals with this checks
108 * (after clearing bit 0) whether the sr_Waiter field is NULL. If
109 * so then it is really a SemaphoreMessage and should be returned.
111 * Now the bad part about this is what we are doing. There are two
112 * cases, in the Amiga case (bincompat), we are overwriting the
113 * ln_Type, ln_Pri and (half the) ln_Name fields. In the other
114 * case we are overwriting the ln_Name field completely. Now, in
115 * either case this doesn't matter as they do not contain any
116 * useful information that we haven't already claimed.
118 * Thank goodness C is so type unsafe.
120 sr = (struct SemaphoreRequest *)bidMsg;
121 if (bidMsg->ssm_Semaphore != NULL)
122 sr->sr_Waiter = NULL;
123 else
124 sr->sr_Waiter = (APTR)SM_SHARED;
126 AddTail((struct List *)&sigSem->ss_WaitQueue, (struct Node *)bidMsg);
128 /* All done. */
129 Permit();
131 /* Huh? */
132 return 0;
133 AROS_LIBFUNC_EXIT
134 } /* Procure */