Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2000, International Business Machines Corporation and others. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This software has been released under the terms of the IBM Public | |
6 | * License. For details, see the LICENSE file in the top-level source | |
7 | * directory or online at http://www.openafs.org/dl/license10.html | |
8 | */ | |
9 | ||
10 | /*******************************************************************\ | |
11 | * * | |
12 | * Information Technology Center * | |
13 | * Carnegie-Mellon University * | |
14 | * * | |
15 | * * | |
16 | * * | |
17 | \*******************************************************************/ | |
18 | ||
19 | /* | |
20 | Include file for using Vice locking routines. | |
21 | */ | |
22 | ||
23 | #ifndef LOCK_H | |
24 | #define LOCK_H | |
25 | ||
26 | #ifdef KERNEL | |
27 | #error Do not include lwp/lock.h for kernel code. Use afs/lock.h instead. | |
28 | #endif | |
29 | ||
30 | ||
31 | /* The following macros allow multi statement macros to be defined safely, i.e. | |
32 | - the multi statement macro can be the object of an if statement; | |
33 | - the call to the multi statement macro may be legally followed by a semi-colon. | |
34 | BEGINMAC and ENDMAC have been tested with both the portable C compiler and | |
35 | Hi-C. Both compilers were from the Palo Alto 4.2BSD software releases, and | |
36 | both optimized out the constant loop code. For an example of the use | |
37 | of BEGINMAC and ENDMAC, see the definition for ReleaseWriteLock, below. | |
38 | An alternative to this, using "if(1)" for BEGINMAC is not used because it | |
39 | may generate worse code with pcc, and may generate warning messages with hi-C. | |
40 | */ | |
41 | ||
42 | #define BEGINMAC do { | |
43 | #define ENDMAC } while (0) | |
44 | ||
45 | #ifdef AFS_PTHREAD_ENV | |
46 | #include <afs/opr.h> | |
47 | #include <opr/lock.h> | |
48 | #define LOCK_LOCK(A) opr_mutex_enter(&(A)->mutex) | |
49 | #define LOCK_UNLOCK(A) opr_mutex_exit(&(A)->mutex) | |
50 | #else /* AFS_PTHREAD_ENV */ | |
51 | #define LOCK_LOCK(A) | |
52 | #define LOCK_UNLOCK(A) | |
53 | #endif /* AFS_PTHREAD_ENV */ | |
54 | ||
55 | /* all locks wait on excl_locked except for READ_LOCK, which waits on readers_reading */ | |
56 | struct Lock { | |
57 | unsigned char wait_states; /* type of lockers waiting */ | |
58 | unsigned char excl_locked; /* anyone have boosted, shared or write lock? */ | |
59 | unsigned char readers_reading; /* # readers actually with read locks */ | |
60 | unsigned char num_waiting; /* probably need this soon */ | |
61 | #ifdef AFS_PTHREAD_ENV | |
62 | pthread_mutex_t mutex; /* protects this structure */ | |
63 | pthread_cond_t read_cv; /* wait for read locks */ | |
64 | pthread_cond_t write_cv; /* wait for write/shared locks */ | |
65 | #endif /* AFS_PTHREAD_ENV */ | |
66 | }; | |
67 | ||
68 | extern void Afs_Lock_Obtain(struct Lock *lock, int how); | |
69 | extern void Afs_Lock_ReleaseR(struct Lock *lock); | |
70 | extern void Afs_Lock_ReleaseW(struct Lock *lock); | |
71 | extern void Afs_Lock_WakeupR(struct Lock *lock); | |
72 | void Lock_Init(struct Lock *lock); | |
73 | void Lock_Destroy(struct Lock *lock); | |
74 | ||
75 | #define READ_LOCK 1 | |
76 | #define WRITE_LOCK 2 | |
77 | #define SHARED_LOCK 4 | |
78 | /* this next is not a flag, but rather a parameter to Afs_Lock_Obtain */ | |
79 | #define BOOSTED_LOCK 6 | |
80 | ||
81 | /* next defines wait_states for which we wait on excl_locked */ | |
82 | #define EXCL_LOCKS (WRITE_LOCK|SHARED_LOCK) | |
83 | ||
84 | #define ObtainReadLock(lock)\ | |
85 | BEGINMAC \ | |
86 | LOCK_LOCK(lock); \ | |
87 | if (!((lock)->excl_locked & WRITE_LOCK) && !(lock)->wait_states)\ | |
88 | (lock) -> readers_reading++;\ | |
89 | else\ | |
90 | Afs_Lock_Obtain(lock, READ_LOCK); \ | |
91 | LOCK_UNLOCK(lock); \ | |
92 | ENDMAC | |
93 | ||
94 | #define ObtainReadLockNoBlock(lock, code)\ | |
95 | BEGINMAC \ | |
96 | LOCK_LOCK(lock); \ | |
97 | if (!((lock)->excl_locked & WRITE_LOCK) && !(lock)->wait_states) {\ | |
98 | (lock) -> readers_reading++;\ | |
99 | code = 0;\ | |
100 | }\ | |
101 | else\ | |
102 | code = -1; \ | |
103 | LOCK_UNLOCK(lock); \ | |
104 | ENDMAC | |
105 | ||
106 | #define ObtainWriteLock(lock)\ | |
107 | BEGINMAC \ | |
108 | LOCK_LOCK(lock); \ | |
109 | if (!(lock)->excl_locked && !(lock)->readers_reading)\ | |
110 | (lock) -> excl_locked = WRITE_LOCK;\ | |
111 | else\ | |
112 | Afs_Lock_Obtain(lock, WRITE_LOCK); \ | |
113 | LOCK_UNLOCK(lock); \ | |
114 | ENDMAC | |
115 | ||
116 | #define ObtainWriteLockNoBlock(lock, code)\ | |
117 | BEGINMAC \ | |
118 | LOCK_LOCK(lock); \ | |
119 | if (!(lock)->excl_locked && !(lock)->readers_reading) {\ | |
120 | (lock) -> excl_locked = WRITE_LOCK;\ | |
121 | code = 0;\ | |
122 | }\ | |
123 | else\ | |
124 | code = -1; \ | |
125 | LOCK_UNLOCK(lock); \ | |
126 | ENDMAC | |
127 | ||
128 | #define ObtainSharedLock(lock)\ | |
129 | BEGINMAC \ | |
130 | LOCK_LOCK(lock); \ | |
131 | if (!(lock)->excl_locked && !(lock)->wait_states)\ | |
132 | (lock) -> excl_locked = SHARED_LOCK;\ | |
133 | else\ | |
134 | Afs_Lock_Obtain(lock, SHARED_LOCK); \ | |
135 | LOCK_UNLOCK(lock); \ | |
136 | ENDMAC | |
137 | ||
138 | #define ObtainSharedLockNoBlock(lock, code)\ | |
139 | BEGINMAC \ | |
140 | LOCK_LOCK(lock); \ | |
141 | if (!(lock)->excl_locked && !(lock)->wait_states) {\ | |
142 | (lock) -> excl_locked = SHARED_LOCK;\ | |
143 | code = 0;\ | |
144 | }\ | |
145 | else\ | |
146 | code = -1; \ | |
147 | LOCK_UNLOCK(lock); \ | |
148 | ENDMAC | |
149 | ||
150 | #define BoostSharedLock(lock)\ | |
151 | BEGINMAC \ | |
152 | LOCK_LOCK(lock); \ | |
153 | if (!(lock)->readers_reading)\ | |
154 | (lock)->excl_locked = WRITE_LOCK;\ | |
155 | else\ | |
156 | Afs_Lock_Obtain(lock, BOOSTED_LOCK); \ | |
157 | LOCK_UNLOCK(lock); \ | |
158 | ENDMAC | |
159 | ||
160 | /* this must only be called with a WRITE or boosted SHARED lock! */ | |
161 | #define UnboostSharedLock(lock)\ | |
162 | BEGINMAC\ | |
163 | LOCK_LOCK(lock); \ | |
164 | (lock)->excl_locked = SHARED_LOCK; \ | |
165 | if((lock)->wait_states) \ | |
166 | Afs_Lock_ReleaseR(lock); \ | |
167 | LOCK_UNLOCK(lock); \ | |
168 | ENDMAC | |
169 | ||
170 | #ifdef notdef | |
171 | /* this is what UnboostSharedLock looked like before the hi-C compiler */ | |
172 | /* this must only be called with a WRITE or boosted SHARED lock! */ | |
173 | #define UnboostSharedLock(lock)\ | |
174 | ((lock)->excl_locked = SHARED_LOCK,\ | |
175 | ((lock)->wait_states ?\ | |
176 | Afs_Lock_ReleaseR(lock) : 0)) | |
177 | #endif /* notdef */ | |
178 | ||
179 | #define ReleaseReadLock(lock)\ | |
180 | BEGINMAC\ | |
181 | LOCK_LOCK(lock); \ | |
182 | if (!--(lock)->readers_reading && (lock)->wait_states)\ | |
183 | Afs_Lock_ReleaseW(lock) ; \ | |
184 | LOCK_UNLOCK(lock); \ | |
185 | ENDMAC | |
186 | ||
187 | ||
188 | #ifdef notdef | |
189 | /* This is what the previous definition should be, but the hi-C compiler generates | |
190 | a warning for each invocation */ | |
191 | #define ReleaseReadLock(lock)\ | |
192 | (!--(lock)->readers_reading && (lock)->wait_states ?\ | |
193 | Afs_Lock_ReleaseW(lock) :\ | |
194 | 0) | |
195 | #endif /* notdef */ | |
196 | ||
197 | #define ReleaseWriteLock(lock)\ | |
198 | BEGINMAC\ | |
199 | LOCK_LOCK(lock); \ | |
200 | (lock)->excl_locked &= ~WRITE_LOCK;\ | |
201 | if ((lock)->wait_states) Afs_Lock_ReleaseR(lock);\ | |
202 | LOCK_UNLOCK(lock); \ | |
203 | ENDMAC | |
204 | ||
205 | #ifdef notdef | |
206 | /* This is what the previous definition should be, but the hi-C compiler generates | |
207 | a warning for each invocation */ | |
208 | #define ReleaseWriteLock(lock)\ | |
209 | ((lock)->excl_locked &= ~WRITE_LOCK,\ | |
210 | ((lock)->wait_states ?\ | |
211 | Afs_Lock_ReleaseR(lock) : 0)) | |
212 | #endif /* notdef */ | |
213 | ||
214 | /* can be used on shared or boosted (write) locks */ | |
215 | #define ReleaseSharedLock(lock)\ | |
216 | BEGINMAC\ | |
217 | LOCK_LOCK(lock); \ | |
218 | (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);\ | |
219 | if ((lock)->wait_states) Afs_Lock_ReleaseR(lock);\ | |
220 | LOCK_UNLOCK(lock); \ | |
221 | ENDMAC | |
222 | ||
223 | #ifdef notdef | |
224 | /* This is what the previous definition should be, but the hi-C compiler generates | |
225 | a warning for each invocation */ | |
226 | /* can be used on shared or boosted (write) locks */ | |
227 | #define ReleaseSharedLock(lock)\ | |
228 | ((lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK),\ | |
229 | ((lock)->wait_states ?\ | |
230 | Afs_Lock_ReleaseR(lock) : 0)) | |
231 | #endif /* notdef */ | |
232 | ||
233 | /* convert a write lock to a read lock */ | |
234 | #define ConvertWriteToReadLock(lock)\ | |
235 | BEGINMAC\ | |
236 | LOCK_LOCK(lock); \ | |
237 | (lock)->excl_locked &= ~WRITE_LOCK;\ | |
238 | (lock)->readers_reading++;\ | |
239 | if ((lock)->wait_states & READ_LOCK) \ | |
240 | Afs_Lock_WakeupR(lock) ; \ | |
241 | LOCK_UNLOCK(lock); \ | |
242 | ENDMAC | |
243 | ||
244 | /* I added this next macro to make sure it is safe to nuke a lock -- Mike K. */ | |
245 | #define LockWaiters(lock)\ | |
246 | ((int) ((lock)->num_waiting)) | |
247 | ||
248 | #define CheckLock(lock)\ | |
249 | ((lock)->excl_locked? (int) -1 : (int) (lock)->readers_reading) | |
250 | ||
251 | #define WriteLocked(lock)\ | |
252 | ((lock)->excl_locked & WRITE_LOCK) | |
253 | ||
254 | #define SharedLocked(lock)\ | |
255 | ((lock)->excl_locked & SHARED_LOCK) | |
256 | ||
257 | #endif /* LOCK_H */ |