2 * Copyright 2000, International Business Machines Corporation and others.
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
10 /*******************************************************************\
12 * Information Technology Center *
13 * Carnegie-Mellon University *
17 \*******************************************************************/
21 Locking routines for Vice.
25 #include <afsconfig.h>
26 #include <afs/param.h>
38 Lock_Init(struct Lock *lock)
40 lock->readers_reading = 0;
41 lock->excl_locked = 0;
42 lock->wait_states = 0;
43 lock->num_waiting = 0;
44 #ifdef AFS_PTHREAD_ENV
45 opr_mutex_init(&lock->mutex);
46 opr_cv_init(&lock->read_cv);
47 opr_cv_init(&lock->write_cv);
48 #endif /* AFS_PTHREAD_ENV */
52 Lock_Destroy(struct Lock *lock)
54 #ifdef AFS_PTHREAD_ENV
55 opr_mutex_destroy(&lock->mutex);
56 opr_cv_destroy(&lock->read_cv);
57 opr_cv_destroy(&lock->write_cv);
58 #endif /* AFS_PTHREAD_ENV */
62 Afs_Lock_Obtain(struct Lock *lock, int how)
69 lock->wait_states |= READ_LOCK;
70 #ifdef AFS_PTHREAD_ENV
71 opr_cv_wait(&lock->read_cv, &lock->mutex);
72 #else /* AFS_PTHREAD_ENV */
73 LWP_WaitProcess(&lock->readers_reading);
74 #endif /* AFS_PTHREAD_ENV */
75 } while (lock->excl_locked & WRITE_LOCK);
77 lock->readers_reading++;
83 lock->wait_states |= WRITE_LOCK;
84 #ifdef AFS_PTHREAD_ENV
85 opr_cv_wait(&lock->write_cv, &lock->mutex);
86 #else /* AFS_PTHREAD_ENV */
87 LWP_WaitProcess(&lock->excl_locked);
88 #endif /* AFS_PTHREAD_ENV */
89 } while (lock->excl_locked || lock->readers_reading);
91 lock->excl_locked = WRITE_LOCK;
97 lock->wait_states |= SHARED_LOCK;
98 #ifdef AFS_PTHREAD_ENV
99 opr_cv_wait(&lock->write_cv, &lock->mutex);
100 #else /* AFS_PTHREAD_ENV */
101 LWP_WaitProcess(&lock->excl_locked);
102 #endif /* AFS_PTHREAD_ENV */
103 } while (lock->excl_locked);
105 lock->excl_locked = SHARED_LOCK;
111 lock->wait_states |= WRITE_LOCK;
112 #ifdef AFS_PTHREAD_ENV
113 opr_cv_wait(&lock->write_cv, &lock->mutex);
114 #else /* AFS_PTHREAD_ENV */
115 LWP_WaitProcess(&lock->excl_locked);
116 #endif /* AFS_PTHREAD_ENV */
117 } while (lock->readers_reading);
119 lock->excl_locked = WRITE_LOCK;
123 printf("Can't happen, bad LOCK type: %d\n", how);
128 /* wake up readers waiting for this lock */
130 Afs_Lock_WakeupR(struct Lock *lock)
132 if (lock->wait_states & READ_LOCK) {
133 lock->wait_states &= ~READ_LOCK;
134 #ifdef AFS_PTHREAD_ENV
135 opr_cv_broadcast(&lock->read_cv);
136 #else /* AFS_PTHREAD_ENV */
137 LWP_NoYieldSignal(&lock->readers_reading);
138 #endif /* AFS_PTHREAD_ENV */
142 /* release a lock, giving preference to new readers */
144 Afs_Lock_ReleaseR(struct Lock *lock)
146 if (lock->wait_states & READ_LOCK) {
147 lock->wait_states &= ~READ_LOCK;
148 #ifdef AFS_PTHREAD_ENV
149 opr_cv_broadcast(&lock->read_cv);
150 #else /* AFS_PTHREAD_ENV */
151 LWP_NoYieldSignal(&lock->readers_reading);
152 #endif /* AFS_PTHREAD_ENV */
154 lock->wait_states &= ~EXCL_LOCKS;
155 #ifdef AFS_PTHREAD_ENV
156 opr_cv_broadcast(&lock->write_cv);
157 #else /* AFS_PTHREAD_ENV */
158 LWP_NoYieldSignal(&lock->excl_locked);
159 #endif /* AFS_PTHREAD_ENV */
163 /* release a lock, giving preference to new writers */
165 Afs_Lock_ReleaseW(struct Lock *lock)
167 if (lock->wait_states & EXCL_LOCKS) {
168 lock->wait_states &= ~EXCL_LOCKS;
169 #ifdef AFS_PTHREAD_ENV
170 opr_cv_broadcast(&lock->write_cv);
171 #else /* AFS_PTHREAD_ENV */
172 LWP_NoYieldSignal(&lock->excl_locked);
173 #endif /* AFS_PTHREAD_ENV */
175 lock->wait_states &= ~READ_LOCK;
176 #ifdef AFS_PTHREAD_ENV
177 opr_cv_broadcast(&lock->read_cv);
178 #else /* AFS_PTHREAD_ENV */
179 LWP_NoYieldSignal(&lock->readers_reading);
180 #endif /* AFS_PTHREAD_ENV */
184 #ifndef AFS_PTHREAD_ENV
185 /* These next guys exist to provide an interface to drop a lock atomically with
186 * blocking. They're trivial to do in a non-preemptive LWP environment.
189 /* release a write lock and sleep on an address, atomically */
191 LWP_WaitProcessR(void *addr, struct Lock *alock)
193 ReleaseReadLock(alock);
194 LWP_WaitProcess(addr);
197 /* release a write lock and sleep on an address, atomically */
199 LWP_WaitProcessW(void *addr, struct Lock *alock)
201 ReleaseWriteLock(alock);
202 LWP_WaitProcess(addr);
205 /* release a write lock and sleep on an address, atomically */
207 LWP_WaitProcessS(void *addr, struct Lock *alock)
209 ReleaseSharedLock(alock);
210 LWP_WaitProcess(addr);
212 #endif /* AFS_PTHREAD_ENV */