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
12 /*******************************************************************\
14 * Information Technology Center *
15 * Carnegie-Mellon University *
19 \*******************************************************************/
23 Locking routines for Vice.
27 #include <afs/param.h>
28 #ifdef AFS_PTHREAD_ENV
29 #include <afs/assert.h>
30 #else /* AFS_PTHREAD_ENV */
32 #endif /* AFS_PTHRED_ENV */
40 void Lock_Init(struct Lock *lock)
42 lock -> readers_reading = 0;
43 lock -> excl_locked = 0;
44 lock -> wait_states = 0;
45 lock -> num_waiting = 0;
46 #ifdef AFS_PTHREAD_ENV
47 assert(pthread_mutex_init(&lock->mutex, (const pthread_mutexattr_t*)0)==0);
48 assert(pthread_cond_init(&lock->read_cv, (const pthread_condattr_t*)0)==0);
49 assert(pthread_cond_init(&lock->write_cv, (const pthread_condattr_t*)0)==0);
50 #endif /* AFS_PTHRED_ENV */
53 void Lock_Destroy(struct Lock *lock)
55 #ifdef AFS_PTHREAD_ENV
56 assert(pthread_mutex_destroy(&lock->mutex) == 0);
57 assert(pthread_cond_destroy(&lock->read_cv) == 0);
58 assert(pthread_cond_destroy(&lock->write_cv) == 0);
59 #endif /* AFS_PTHRED_ENV */
62 void Afs_Lock_Obtain(struct Lock * lock, int how)
66 case READ_LOCK: lock->num_waiting++;
68 lock -> wait_states |= READ_LOCK;
69 #ifdef AFS_PTHREAD_ENV
70 assert(pthread_cond_wait(&lock->read_cv,
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++;
80 case WRITE_LOCK: lock->num_waiting++;
82 lock -> wait_states |= WRITE_LOCK;
83 #ifdef AFS_PTHREAD_ENV
84 assert(pthread_cond_wait(&lock->write_cv,
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;
94 case SHARED_LOCK: lock->num_waiting++;
96 lock->wait_states |= SHARED_LOCK;
97 #ifdef AFS_PTHREAD_ENV
98 assert(pthread_cond_wait(&lock->write_cv,
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;
108 case BOOSTED_LOCK: lock->num_waiting++;
110 lock->wait_states |= WRITE_LOCK;
111 #ifdef AFS_PTHREAD_ENV
112 assert(pthread_cond_wait(&lock->write_cv,
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;
122 default: printf("Can't happen, bad LOCK type: %d\n", how);
127 /* wake up readers waiting for this lock */
128 void Afs_Lock_WakeupR(struct Lock *lock)
130 if (lock->wait_states & READ_LOCK) {
131 lock->wait_states &= ~READ_LOCK;
132 #ifdef AFS_PTHREAD_ENV
133 assert(pthread_cond_broadcast(&lock->read_cv) == 0);
134 #else /* AFS_PTHREAD_ENV */
135 LWP_NoYieldSignal(&lock->readers_reading);
136 #endif /* AFS_PTHREAD_ENV */
140 /* release a lock, giving preference to new readers */
141 void Afs_Lock_ReleaseR(struct Lock *lock)
143 if (lock->wait_states & READ_LOCK) {
144 lock->wait_states &= ~READ_LOCK;
145 #ifdef AFS_PTHREAD_ENV
146 assert(pthread_cond_broadcast(&lock->read_cv) == 0);
147 #else /* AFS_PTHREAD_ENV */
148 LWP_NoYieldSignal(&lock->readers_reading);
149 #endif /* AFS_PTHREAD_ENV */
152 lock->wait_states &= ~EXCL_LOCKS;
153 #ifdef AFS_PTHREAD_ENV
154 assert(pthread_cond_broadcast(&lock->write_cv) == 0);
155 #else /* AFS_PTHREAD_ENV */
156 LWP_NoYieldSignal(&lock->excl_locked);
157 #endif /* AFS_PTHREAD_ENV */
161 /* release a lock, giving preference to new writers */
162 void Afs_Lock_ReleaseW(struct Lock * lock)
164 if (lock->wait_states & EXCL_LOCKS) {
165 lock->wait_states &= ~EXCL_LOCKS;
166 #ifdef AFS_PTHREAD_ENV
167 assert(pthread_cond_broadcast(&lock->write_cv) == 0);
168 #else /* AFS_PTHREAD_ENV */
169 LWP_NoYieldSignal(&lock->excl_locked);
170 #endif /* AFS_PTHREAD_ENV */
173 lock->wait_states &= ~READ_LOCK;
174 #ifdef AFS_PTHREAD_ENV
175 assert(pthread_cond_broadcast(&lock->read_cv) == 0);
176 #else /* AFS_PTHREAD_ENV */
177 LWP_NoYieldSignal(&lock->readers_reading);
178 #endif /* AFS_PTHREAD_ENV */
182 #ifndef AFS_PTHREAD_ENV
183 /* These next guys exist to provide an interface to drop a lock atomically with
184 * blocking. They're trivial to do in a non-preemptive LWP environment.
187 /* release a write lock and sleep on an address, atomically */
188 void LWP_WaitProcessR(addr, alock)
190 register struct Lock *alock; {
191 ReleaseReadLock(alock);
192 LWP_WaitProcess(addr);
195 /* release a write lock and sleep on an address, atomically */
196 void LWP_WaitProcessW(addr, alock)
198 register struct Lock *alock; {
199 ReleaseWriteLock(alock);
200 LWP_WaitProcess(addr);
203 /* release a write lock and sleep on an address, atomically */
204 void LWP_WaitProcessS(addr, alock)
206 register struct Lock *alock; {
207 ReleaseSharedLock(alock);
208 LWP_WaitProcess(addr);
210 #endif /* AFS_PTHREAD_ENV */