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>
29 #ifndef AFS_PTHREAD_ENV
30 #include <afs/afs_assert.h>
31 #else /* AFS_PTHREAD_ENV */
33 #endif /* AFS_PTHRED_ENV */
42 Lock_Init(struct Lock *lock)
44 lock->readers_reading = 0;
45 lock->excl_locked = 0;
46 lock->wait_states = 0;
47 lock->num_waiting = 0;
48 #ifdef AFS_PTHREAD_ENV
49 assert(pthread_mutex_init(&lock->mutex, (const pthread_mutexattr_t *)0) ==
51 assert(pthread_cond_init(&lock->read_cv, (const pthread_condattr_t *)0) ==
53 assert(pthread_cond_init(&lock->write_cv, (const pthread_condattr_t *)0)
55 #endif /* AFS_PTHRED_ENV */
59 Lock_Destroy(struct Lock *lock)
61 #ifdef AFS_PTHREAD_ENV
62 assert(pthread_mutex_destroy(&lock->mutex) == 0);
63 assert(pthread_cond_destroy(&lock->read_cv) == 0);
64 assert(pthread_cond_destroy(&lock->write_cv) == 0);
65 #endif /* AFS_PTHRED_ENV */
69 Afs_Lock_Obtain(struct Lock *lock, int how)
76 lock->wait_states |= READ_LOCK;
77 #ifdef AFS_PTHREAD_ENV
78 assert(pthread_cond_wait(&lock->read_cv, &lock->mutex) == 0);
79 #else /* AFS_PTHREAD_ENV */
80 LWP_WaitProcess(&lock->readers_reading);
81 #endif /* AFS_PTHREAD_ENV */
82 } while (lock->excl_locked & WRITE_LOCK);
84 lock->readers_reading++;
90 lock->wait_states |= WRITE_LOCK;
91 #ifdef AFS_PTHREAD_ENV
92 assert(pthread_cond_wait(&lock->write_cv, &lock->mutex) == 0);
93 #else /* AFS_PTHREAD_ENV */
94 LWP_WaitProcess(&lock->excl_locked);
95 #endif /* AFS_PTHREAD_ENV */
96 } while (lock->excl_locked || lock->readers_reading);
98 lock->excl_locked = WRITE_LOCK;
104 lock->wait_states |= SHARED_LOCK;
105 #ifdef AFS_PTHREAD_ENV
106 assert(pthread_cond_wait(&lock->write_cv, &lock->mutex) == 0);
107 #else /* AFS_PTHREAD_ENV */
108 LWP_WaitProcess(&lock->excl_locked);
109 #endif /* AFS_PTHREAD_ENV */
110 } while (lock->excl_locked);
112 lock->excl_locked = SHARED_LOCK;
118 lock->wait_states |= WRITE_LOCK;
119 #ifdef AFS_PTHREAD_ENV
120 assert(pthread_cond_wait(&lock->write_cv, &lock->mutex) == 0);
121 #else /* AFS_PTHREAD_ENV */
122 LWP_WaitProcess(&lock->excl_locked);
123 #endif /* AFS_PTHREAD_ENV */
124 } while (lock->readers_reading);
126 lock->excl_locked = WRITE_LOCK;
130 printf("Can't happen, bad LOCK type: %d\n", how);
135 /* wake up readers waiting for this lock */
137 Afs_Lock_WakeupR(struct Lock *lock)
139 if (lock->wait_states & READ_LOCK) {
140 lock->wait_states &= ~READ_LOCK;
141 #ifdef AFS_PTHREAD_ENV
142 assert(pthread_cond_broadcast(&lock->read_cv) == 0);
143 #else /* AFS_PTHREAD_ENV */
144 LWP_NoYieldSignal(&lock->readers_reading);
145 #endif /* AFS_PTHREAD_ENV */
149 /* release a lock, giving preference to new readers */
151 Afs_Lock_ReleaseR(struct Lock *lock)
153 if (lock->wait_states & READ_LOCK) {
154 lock->wait_states &= ~READ_LOCK;
155 #ifdef AFS_PTHREAD_ENV
156 assert(pthread_cond_broadcast(&lock->read_cv) == 0);
157 #else /* AFS_PTHREAD_ENV */
158 LWP_NoYieldSignal(&lock->readers_reading);
159 #endif /* AFS_PTHREAD_ENV */
161 lock->wait_states &= ~EXCL_LOCKS;
162 #ifdef AFS_PTHREAD_ENV
163 assert(pthread_cond_broadcast(&lock->write_cv) == 0);
164 #else /* AFS_PTHREAD_ENV */
165 LWP_NoYieldSignal(&lock->excl_locked);
166 #endif /* AFS_PTHREAD_ENV */
170 /* release a lock, giving preference to new writers */
172 Afs_Lock_ReleaseW(struct Lock *lock)
174 if (lock->wait_states & EXCL_LOCKS) {
175 lock->wait_states &= ~EXCL_LOCKS;
176 #ifdef AFS_PTHREAD_ENV
177 assert(pthread_cond_broadcast(&lock->write_cv) == 0);
178 #else /* AFS_PTHREAD_ENV */
179 LWP_NoYieldSignal(&lock->excl_locked);
180 #endif /* AFS_PTHREAD_ENV */
182 lock->wait_states &= ~READ_LOCK;
183 #ifdef AFS_PTHREAD_ENV
184 assert(pthread_cond_broadcast(&lock->read_cv) == 0);
185 #else /* AFS_PTHREAD_ENV */
186 LWP_NoYieldSignal(&lock->readers_reading);
187 #endif /* AFS_PTHREAD_ENV */
191 #ifndef AFS_PTHREAD_ENV
192 /* These next guys exist to provide an interface to drop a lock atomically with
193 * blocking. They're trivial to do in a non-preemptive LWP environment.
196 /* release a write lock and sleep on an address, atomically */
198 LWP_WaitProcessR(void *addr, struct Lock *alock)
200 ReleaseReadLock(alock);
201 LWP_WaitProcess(addr);
204 /* release a write lock and sleep on an address, atomically */
206 LWP_WaitProcessW(void *addr, struct Lock *alock)
208 ReleaseWriteLock(alock);
209 LWP_WaitProcess(addr);
212 /* release a write lock and sleep on an address, atomically */
214 LWP_WaitProcessS(void *addr, struct Lock *alock)
216 ReleaseSharedLock(alock);
217 LWP_WaitProcess(addr);
219 #endif /* AFS_PTHREAD_ENV */