5 #if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
9 ****************************************************************************
10 * Copyright IBM Corporation 1988, 1989 - All Rights Reserved *
12 * Permission to use, copy, modify, and distribute this software and its *
13 * documentation for any purpose and without fee is hereby granted, *
14 * provided that the above copyright notice appear in all copies and *
15 * that both that copyright notice and this permission notice appear in *
16 * supporting documentation, and that the name of IBM not be used in *
17 * advertising or publicity pertaining to distribution of the software *
18 * without specific, written prior permission. *
20 * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL *
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM *
22 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY *
23 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER *
24 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING *
25 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
26 ****************************************************************************
29 /*******************************************************************\
31 * Information Technology Center *
32 * Carnegie-Mellon University *
36 \*******************************************************************/
39 Include file for using Vice locking routines.
42 /* The following macros allow multi statement macros to be defined safely, i.e.
43 - the multi statement macro can be the object of an if statement;
44 - the call to the multi statement macro may be legally followed by a semi-colon.
45 BEGINMAC and ENDMAC have been tested with both the portable C compiler and
46 Hi-C. Both compilers were from the Palo Alto 4.2BSD software releases, and
47 both optimized out the constant loop code. For an example of the use
48 of BEGINMAC and ENDMAC, see the definition for ReleaseWriteLock, below.
49 An alternative to this, using "if(1)" for BEGINMAC is not used because it
50 may generate worse code with pcc, and may generate warning messages with hi-C.
54 #define ENDMAC } while (0)
56 #ifdef AFS_PTHREAD_ENV
59 #define LOCK_LOCK(A) assert(pthread_mutex_lock(&(A)->mutex) == 0);
60 #define LOCK_UNLOCK(A) assert(pthread_mutex_unlock(&(A)->mutex) == 0);
61 #else /* AFS_PTHREAD_ENV */
63 #define LOCK_UNLOCK(A)
64 #endif /* AFS_PTHREAD_ENV */
66 /* all locks wait on excl_locked except for READ_LOCK, which waits on readers_reading */
68 unsigned char wait_states; /* type of lockers waiting */
69 unsigned char excl_locked; /* anyone have boosted, shared or write lock? */
70 unsigned char readers_reading; /* # readers actually with read locks */
71 unsigned char num_waiting; /* probably need this soon */
72 #ifdef AFS_PTHREAD_ENV
73 pthread_mutex_t mutex; /* protects this structure */
74 pthread_cond_t read_cv; /* wait for read locks */
75 pthread_cond_t write_cv; /* wait for write/shared locks */
76 #endif /* AFS_PTHREAD_ENV */
79 extern void Afs_Lock_Obtain(struct Lock * lock, int how);
80 extern void Afs_Lock_ReleaseR(struct Lock *lock);
81 extern void Afs_Lock_ReleaseW(struct Lock * lock);
82 void Lock_Init(struct Lock *lock);
83 void Lock_Destroy(struct Lock *lock);
88 /* this next is not a flag, but rather a parameter to Afs_Lock_Obtain */
89 #define BOOSTED_LOCK 6
91 /* next defines wait_states for which we wait on excl_locked */
92 #define EXCL_LOCKS (WRITE_LOCK|SHARED_LOCK)
94 #define ObtainReadLock(lock)\
97 if (!((lock)->excl_locked & WRITE_LOCK) && !(lock)->wait_states)\
98 (lock) -> readers_reading++;\
100 Afs_Lock_Obtain(lock, READ_LOCK); \
104 #define ObtainWriteLock(lock)\
107 if (!(lock)->excl_locked && !(lock)->readers_reading)\
108 (lock) -> excl_locked = WRITE_LOCK;\
110 Afs_Lock_Obtain(lock, WRITE_LOCK); \
114 #define ObtainSharedLock(lock)\
117 if (!(lock)->excl_locked && !(lock)->wait_states)\
118 (lock) -> excl_locked = SHARED_LOCK;\
120 Afs_Lock_Obtain(lock, SHARED_LOCK); \
124 #define BoostSharedLock(lock)\
127 if (!(lock)->readers_reading)\
128 (lock)->excl_locked = WRITE_LOCK;\
130 Afs_Lock_Obtain(lock, BOOSTED_LOCK); \
134 /* this must only be called with a WRITE or boosted SHARED lock! */
135 #define UnboostSharedLock(lock)\
138 (lock)->excl_locked = SHARED_LOCK; \
139 if((lock)->wait_states) \
140 Afs_Lock_ReleaseR(lock); \
145 /* this is what UnboostSharedLock looked like before the hi-C compiler */
146 /* this must only be called with a WRITE or boosted SHARED lock! */
147 #define UnboostSharedLock(lock)\
148 ((lock)->excl_locked = SHARED_LOCK,\
149 ((lock)->wait_states ?\
150 Afs_Lock_ReleaseR(lock) : 0))
153 #define ReleaseReadLock(lock)\
156 if (!--(lock)->readers_reading && (lock)->wait_states)\
157 Afs_Lock_ReleaseW(lock) ; \
163 /* This is what the previous definition should be, but the hi-C compiler generates
164 a warning for each invocation */
165 #define ReleaseReadLock(lock)\
166 (!--(lock)->readers_reading && (lock)->wait_states ?\
167 Afs_Lock_ReleaseW(lock) :\
171 #define ReleaseWriteLock(lock)\
174 (lock)->excl_locked &= ~WRITE_LOCK;\
175 if ((lock)->wait_states) Afs_Lock_ReleaseR(lock);\
180 /* This is what the previous definition should be, but the hi-C compiler generates
181 a warning for each invocation */
182 #define ReleaseWriteLock(lock)\
183 ((lock)->excl_locked &= ~WRITE_LOCK,\
184 ((lock)->wait_states ?\
185 Afs_Lock_ReleaseR(lock) : 0))
188 /* can be used on shared or boosted (write) locks */
189 #define ReleaseSharedLock(lock)\
192 (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);\
193 if ((lock)->wait_states) Afs_Lock_ReleaseR(lock);\
198 /* This is what the previous definition should be, but the hi-C compiler generates
199 a warning for each invocation */
200 /* can be used on shared or boosted (write) locks */
201 #define ReleaseSharedLock(lock)\
202 ((lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK),\
203 ((lock)->wait_states ?\
204 Afs_Lock_ReleaseR(lock) : 0))
207 /* convert a write lock to a read lock */
208 #define ConvertWriteToReadLock(lock)\
211 (lock)->excl_locked &= ~WRITE_LOCK;\
212 (lock)->readers_reading++;\
213 if ((lock)->wait_states & READ_LOCK) \
214 Afs_Lock_WakeupR(lock) ; \
218 /* I added this next macro to make sure it is safe to nuke a lock -- Mike K. */
219 #define LockWaiters(lock)\
220 ((int) ((lock)->num_waiting))
222 #define CheckLock(lock)\
223 ((lock)->excl_locked? (int) -1 : (int) (lock)->readers_reading)
225 #define WriteLocked(lock)\
226 ((lock)->excl_locked & WRITE_LOCK)