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>
30 #ifdef AFS_PTHREAD_ENV
31 #include <afs/afs_assert.h>
32 /* can't include this in lwp, rx hasn't built yet */
46 Lock_Init(struct Lock *lock)
48 lock->readers_reading = 0;
49 lock->excl_locked = 0;
50 lock->wait_states = 0;
51 lock->num_waiting = 0;
52 #ifdef AFS_PTHREAD_ENV
53 MUTEX_INIT(&lock->mutex, "lock", MUTEX_DEFAULT, 0);
54 CV_INIT(&lock->read_cv, "read", CV_DEFAULT, 0);
55 CV_INIT(&lock->write_cv, "write", CV_DEFAULT, 0);
56 #endif /* AFS_PTHREAD_ENV */
60 Lock_Destroy(struct Lock *lock)
62 #ifdef AFS_PTHREAD_ENV
63 MUTEX_DESTROY(&lock->mutex);
64 CV_DESTROY(&lock->read_cv);
65 CV_DESTROY(&lock->write_cv);
66 #endif /* AFS_PTHREAD_ENV */
70 Afs_Lock_Obtain(struct Lock *lock, int how)
77 lock->wait_states |= READ_LOCK;
78 #ifdef AFS_PTHREAD_ENV
79 CV_WAIT(&lock->read_cv, &lock->mutex);
80 #else /* AFS_PTHREAD_ENV */
81 LWP_WaitProcess(&lock->readers_reading);
82 #endif /* AFS_PTHREAD_ENV */
83 } while (lock->excl_locked & WRITE_LOCK);
85 lock->readers_reading++;
91 lock->wait_states |= WRITE_LOCK;
92 #ifdef AFS_PTHREAD_ENV
93 CV_WAIT(&lock->write_cv, &lock->mutex);
94 #else /* AFS_PTHREAD_ENV */
95 LWP_WaitProcess(&lock->excl_locked);
96 #endif /* AFS_PTHREAD_ENV */
97 } while (lock->excl_locked || lock->readers_reading);
99 lock->excl_locked = WRITE_LOCK;
105 lock->wait_states |= SHARED_LOCK;
106 #ifdef AFS_PTHREAD_ENV
107 CV_WAIT(&lock->write_cv, &lock->mutex);
108 #else /* AFS_PTHREAD_ENV */
109 LWP_WaitProcess(&lock->excl_locked);
110 #endif /* AFS_PTHREAD_ENV */
111 } while (lock->excl_locked);
113 lock->excl_locked = SHARED_LOCK;
119 lock->wait_states |= WRITE_LOCK;
120 #ifdef AFS_PTHREAD_ENV
121 CV_WAIT(&lock->write_cv, &lock->mutex);
122 #else /* AFS_PTHREAD_ENV */
123 LWP_WaitProcess(&lock->excl_locked);
124 #endif /* AFS_PTHREAD_ENV */
125 } while (lock->readers_reading);
127 lock->excl_locked = WRITE_LOCK;
131 printf("Can't happen, bad LOCK type: %d\n", how);
136 /* wake up readers waiting for this lock */
138 Afs_Lock_WakeupR(struct Lock *lock)
140 if (lock->wait_states & READ_LOCK) {
141 lock->wait_states &= ~READ_LOCK;
142 #ifdef AFS_PTHREAD_ENV
143 CV_BROADCAST(&lock->read_cv);
144 #else /* AFS_PTHREAD_ENV */
145 LWP_NoYieldSignal(&lock->readers_reading);
146 #endif /* AFS_PTHREAD_ENV */
150 /* release a lock, giving preference to new readers */
152 Afs_Lock_ReleaseR(struct Lock *lock)
154 if (lock->wait_states & READ_LOCK) {
155 lock->wait_states &= ~READ_LOCK;
156 #ifdef AFS_PTHREAD_ENV
157 CV_BROADCAST(&lock->read_cv);
158 #else /* AFS_PTHREAD_ENV */
159 LWP_NoYieldSignal(&lock->readers_reading);
160 #endif /* AFS_PTHREAD_ENV */
162 lock->wait_states &= ~EXCL_LOCKS;
163 #ifdef AFS_PTHREAD_ENV
164 CV_BROADCAST(&lock->write_cv);
165 #else /* AFS_PTHREAD_ENV */
166 LWP_NoYieldSignal(&lock->excl_locked);
167 #endif /* AFS_PTHREAD_ENV */
171 /* release a lock, giving preference to new writers */
173 Afs_Lock_ReleaseW(struct Lock *lock)
175 if (lock->wait_states & EXCL_LOCKS) {
176 lock->wait_states &= ~EXCL_LOCKS;
177 #ifdef AFS_PTHREAD_ENV
178 CV_BROADCAST(&lock->write_cv);
179 #else /* AFS_PTHREAD_ENV */
180 LWP_NoYieldSignal(&lock->excl_locked);
181 #endif /* AFS_PTHREAD_ENV */
183 lock->wait_states &= ~READ_LOCK;
184 #ifdef AFS_PTHREAD_ENV
185 CV_BROADCAST(&lock->read_cv);
186 #else /* AFS_PTHREAD_ENV */
187 LWP_NoYieldSignal(&lock->readers_reading);
188 #endif /* AFS_PTHREAD_ENV */
192 #ifndef AFS_PTHREAD_ENV
193 /* These next guys exist to provide an interface to drop a lock atomically with
194 * blocking. They're trivial to do in a non-preemptive LWP environment.
197 /* release a write lock and sleep on an address, atomically */
199 LWP_WaitProcessR(void *addr, struct Lock *alock)
201 ReleaseReadLock(alock);
202 LWP_WaitProcess(addr);
205 /* release a write lock and sleep on an address, atomically */
207 LWP_WaitProcessW(void *addr, struct Lock *alock)
209 ReleaseWriteLock(alock);
210 LWP_WaitProcess(addr);
213 /* release a write lock and sleep on an address, atomically */
215 LWP_WaitProcessS(void *addr, struct Lock *alock)
217 ReleaseSharedLock(alock);
218 LWP_WaitProcess(addr);
220 #endif /* AFS_PTHREAD_ENV */