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/assert.h>
32 #else /* AFS_PTHREAD_ENV */
34 #endif /* AFS_PTHRED_ENV */
42 void 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)==0);
50 assert(pthread_cond_init(&lock->read_cv, (const pthread_condattr_t*)0)==0);
51 assert(pthread_cond_init(&lock->write_cv, (const pthread_condattr_t*)0)==0);
52 #endif /* AFS_PTHRED_ENV */
55 void Lock_Destroy(struct Lock *lock)
57 #ifdef AFS_PTHREAD_ENV
58 assert(pthread_mutex_destroy(&lock->mutex) == 0);
59 assert(pthread_cond_destroy(&lock->read_cv) == 0);
60 assert(pthread_cond_destroy(&lock->write_cv) == 0);
61 #endif /* AFS_PTHRED_ENV */
64 void Afs_Lock_Obtain(struct Lock * lock, int how)
68 case READ_LOCK: lock->num_waiting++;
70 lock -> wait_states |= READ_LOCK;
71 #ifdef AFS_PTHREAD_ENV
72 assert(pthread_cond_wait(&lock->read_cv,
74 #else /* AFS_PTHREAD_ENV */
75 LWP_WaitProcess(&lock->readers_reading);
76 #endif /* AFS_PTHREAD_ENV */
77 } while (lock->excl_locked & WRITE_LOCK);
79 lock->readers_reading++;
82 case WRITE_LOCK: lock->num_waiting++;
84 lock -> wait_states |= WRITE_LOCK;
85 #ifdef AFS_PTHREAD_ENV
86 assert(pthread_cond_wait(&lock->write_cv,
88 #else /* AFS_PTHREAD_ENV */
89 LWP_WaitProcess(&lock->excl_locked);
90 #endif /* AFS_PTHREAD_ENV */
91 } while (lock->excl_locked || lock->readers_reading);
93 lock->excl_locked = WRITE_LOCK;
96 case SHARED_LOCK: lock->num_waiting++;
98 lock->wait_states |= SHARED_LOCK;
99 #ifdef AFS_PTHREAD_ENV
100 assert(pthread_cond_wait(&lock->write_cv,
102 #else /* AFS_PTHREAD_ENV */
103 LWP_WaitProcess(&lock->excl_locked);
104 #endif /* AFS_PTHREAD_ENV */
105 } while (lock->excl_locked);
107 lock->excl_locked = SHARED_LOCK;
110 case BOOSTED_LOCK: lock->num_waiting++;
112 lock->wait_states |= WRITE_LOCK;
113 #ifdef AFS_PTHREAD_ENV
114 assert(pthread_cond_wait(&lock->write_cv,
116 #else /* AFS_PTHREAD_ENV */
117 LWP_WaitProcess(&lock->excl_locked);
118 #endif /* AFS_PTHREAD_ENV */
119 } while (lock->readers_reading);
121 lock->excl_locked = WRITE_LOCK;
124 default: printf("Can't happen, bad LOCK type: %d\n", how);
129 /* wake up readers waiting for this lock */
130 void 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 assert(pthread_cond_broadcast(&lock->read_cv) == 0);
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 */
143 void Afs_Lock_ReleaseR(struct Lock *lock)
145 if (lock->wait_states & READ_LOCK) {
146 lock->wait_states &= ~READ_LOCK;
147 #ifdef AFS_PTHREAD_ENV
148 assert(pthread_cond_broadcast(&lock->read_cv) == 0);
149 #else /* AFS_PTHREAD_ENV */
150 LWP_NoYieldSignal(&lock->readers_reading);
151 #endif /* AFS_PTHREAD_ENV */
154 lock->wait_states &= ~EXCL_LOCKS;
155 #ifdef AFS_PTHREAD_ENV
156 assert(pthread_cond_broadcast(&lock->write_cv) == 0);
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 */
164 void Afs_Lock_ReleaseW(struct Lock * lock)
166 if (lock->wait_states & EXCL_LOCKS) {
167 lock->wait_states &= ~EXCL_LOCKS;
168 #ifdef AFS_PTHREAD_ENV
169 assert(pthread_cond_broadcast(&lock->write_cv) == 0);
170 #else /* AFS_PTHREAD_ENV */
171 LWP_NoYieldSignal(&lock->excl_locked);
172 #endif /* AFS_PTHREAD_ENV */
175 lock->wait_states &= ~READ_LOCK;
176 #ifdef AFS_PTHREAD_ENV
177 assert(pthread_cond_broadcast(&lock->read_cv) == 0);
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 */
190 void LWP_WaitProcessR(addr, alock)
192 register struct Lock *alock; {
193 ReleaseReadLock(alock);
194 LWP_WaitProcess(addr);
197 /* release a write lock and sleep on an address, atomically */
198 void LWP_WaitProcessW(addr, alock)
200 register struct Lock *alock; {
201 ReleaseWriteLock(alock);
202 LWP_WaitProcess(addr);
205 /* release a write lock and sleep on an address, atomically */
206 void LWP_WaitProcessS(addr, alock)
208 register struct Lock *alock; {
209 ReleaseSharedLock(alock);
210 LWP_WaitProcess(addr);
212 #endif /* AFS_PTHREAD_ENV */