Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / lwp / lock.h
1
2 #ifndef LOCK_H
3 #define LOCK_H
4
5 #if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
6 #endif
7
8 /*
9 ****************************************************************************
10 *        Copyright IBM Corporation 1988, 1989 - All Rights Reserved        *
11 *                                                                          *
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.                              *
19 *                                                                          *
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 ****************************************************************************
27 */
28
29 /*******************************************************************\
30 *                                                                   *
31 *       Information Technology Center                               *
32 *       Carnegie-Mellon University                                  *
33 *                                                                   *
34 *                                                                   *
35 *                                                                   *
36 \*******************************************************************/
37
38 /*
39         Include file for using Vice locking routines.
40 */
41
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.
51 */
52
53 #define BEGINMAC do {
54 #define ENDMAC   } while (0)
55
56 #ifdef AFS_PTHREAD_ENV
57 #include <assert.h>
58 #include <pthread.h>
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 */
62 #define LOCK_LOCK(A)
63 #define LOCK_UNLOCK(A)
64 #endif /* AFS_PTHREAD_ENV */
65
66 /* all locks wait on excl_locked except for READ_LOCK, which waits on readers_reading */
67 struct Lock {
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 */
77 };
78
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);
84
85 #define READ_LOCK       1
86 #define WRITE_LOCK      2
87 #define SHARED_LOCK     4
88 /* this next is not a flag, but rather a parameter to Afs_Lock_Obtain */
89 #define BOOSTED_LOCK 6
90
91 /* next defines wait_states for which we wait on excl_locked */
92 #define EXCL_LOCKS (WRITE_LOCK|SHARED_LOCK)
93
94 #define ObtainReadLock(lock)\
95         BEGINMAC \
96             LOCK_LOCK(lock) \
97             if (!((lock)->excl_locked & WRITE_LOCK) && !(lock)->wait_states)\
98                 (lock) -> readers_reading++;\
99             else\
100                 Afs_Lock_Obtain(lock, READ_LOCK); \
101             LOCK_UNLOCK(lock) \
102         ENDMAC
103     
104 #define ObtainWriteLock(lock)\
105         BEGINMAC \
106             LOCK_LOCK(lock) \
107             if (!(lock)->excl_locked && !(lock)->readers_reading)\
108                 (lock) -> excl_locked = WRITE_LOCK;\
109             else\
110                 Afs_Lock_Obtain(lock, WRITE_LOCK); \
111             LOCK_UNLOCK(lock) \
112         ENDMAC
113     
114 #define ObtainSharedLock(lock)\
115         BEGINMAC \
116             LOCK_LOCK(lock) \
117             if (!(lock)->excl_locked && !(lock)->wait_states)\
118                 (lock) -> excl_locked = SHARED_LOCK;\
119             else\
120                 Afs_Lock_Obtain(lock, SHARED_LOCK); \
121             LOCK_UNLOCK(lock) \
122         ENDMAC
123
124 #define BoostSharedLock(lock)\
125         BEGINMAC \
126             LOCK_LOCK(lock) \
127             if (!(lock)->readers_reading)\
128                 (lock)->excl_locked = WRITE_LOCK;\
129             else\
130                 Afs_Lock_Obtain(lock, BOOSTED_LOCK); \
131             LOCK_UNLOCK(lock) \
132         ENDMAC
133
134 /* this must only be called with a WRITE or boosted SHARED lock! */
135 #define UnboostSharedLock(lock)\
136         BEGINMAC\
137             LOCK_LOCK(lock) \
138             (lock)->excl_locked = SHARED_LOCK; \
139             if((lock)->wait_states) \
140                 Afs_Lock_ReleaseR(lock); \
141             LOCK_UNLOCK(lock) \
142         ENDMAC
143
144 #ifdef notdef
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))
151 #endif /* notdef */
152
153 #define ReleaseReadLock(lock)\
154         BEGINMAC\
155             LOCK_LOCK(lock) \
156             if (!--(lock)->readers_reading && (lock)->wait_states)\
157                 Afs_Lock_ReleaseW(lock) ; \
158             LOCK_UNLOCK(lock) \
159         ENDMAC
160
161
162 #ifdef notdef
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)    :\
168                 0)
169 #endif /* notdef */
170
171 #define ReleaseWriteLock(lock)\
172         BEGINMAC\
173             LOCK_LOCK(lock) \
174             (lock)->excl_locked &= ~WRITE_LOCK;\
175             if ((lock)->wait_states) Afs_Lock_ReleaseR(lock);\
176             LOCK_UNLOCK(lock) \
177         ENDMAC
178
179 #ifdef notdef
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))
186 #endif /* notdef */
187
188 /* can be used on shared or boosted (write) locks */
189 #define ReleaseSharedLock(lock)\
190         BEGINMAC\
191             LOCK_LOCK(lock) \
192             (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);\
193             if ((lock)->wait_states) Afs_Lock_ReleaseR(lock);\
194             LOCK_UNLOCK(lock) \
195         ENDMAC
196
197 #ifdef notdef
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))
205 #endif /* notdef */
206
207 /* convert a write lock to a read lock */
208 #define ConvertWriteToReadLock(lock)\
209         BEGINMAC\
210             LOCK_LOCK(lock) \
211             (lock)->excl_locked &= ~WRITE_LOCK;\
212             (lock)->readers_reading++;\
213             if ((lock)->wait_states & READ_LOCK) \
214                 Afs_Lock_WakeupR(lock) ; \
215             LOCK_UNLOCK(lock) \
216         ENDMAC
217
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))
221
222 #define CheckLock(lock)\
223         ((lock)->excl_locked? (int) -1 : (int) (lock)->readers_reading)
224
225 #define WriteLocked(lock)\
226         ((lock)->excl_locked & WRITE_LOCK)
227
228 #endif /* LOCK_H */