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 #include "../afs/sysincludes.h" /* Standard vendor system headers */
31 #include "../afs/afsincludes.h" /* Afs-based standard headers */
32 #include "../afs/afs_stats.h" /* afs statistics */
49 register struct afs_lock *lock;
52 AFS_STATCNT(Lock_Init);
53 lock -> readers_reading = 0;
54 lock -> excl_locked = 0;
55 lock -> wait_states = 0;
56 lock -> num_waiting = 0;
57 #if defined(INSTRUMENT_LOCKS)
58 lock->pid_last_reader = 0;
60 lock->src_indicator = 0;
61 #endif /* INSTRUMENT_LOCKS */
62 lock->time_waiting.tv_sec = 0;
63 lock->time_waiting.tv_usec = 0;
66 void ObtainLock(lock, how, src_indicator)
67 register struct afs_lock *lock;
69 unsigned int src_indicator;
73 if (!((lock)->excl_locked & WRITE_LOCK))
74 (lock) -> readers_reading++;
76 Afs_Lock_Obtain(lock, READ_LOCK);
77 #if defined(INSTRUMENT_LOCKS)
78 (lock)->pid_last_reader = MyPidxx;
79 #endif /* INSTRUMENT_LOCKS */
82 if (!(lock)->excl_locked && !(lock)->readers_reading)
83 (lock) -> excl_locked = WRITE_LOCK;
85 Afs_Lock_Obtain(lock, WRITE_LOCK);
86 #if defined(INSTRUMENT_LOCKS)
87 (lock)->pid_writer = MyPidxx;
88 (lock)->src_indicator = src_indicator;
89 #endif /* INSTRUMENT_LOCKS */
92 if (!(lock)->excl_locked)
93 (lock) -> excl_locked = SHARED_LOCK;
95 Afs_Lock_Obtain(lock, SHARED_LOCK);
96 #if defined(INSTRUMENT_LOCKS)
97 (lock)->pid_writer = MyPidxx;
98 (lock)->src_indicator = src_indicator;
99 #endif /* INSTRUMENT_LOCKS */
104 void ReleaseLock(lock, how)
105 register struct afs_lock *lock;
108 if (how == READ_LOCK) {
109 if (!--lock->readers_reading && lock->wait_states)
111 #if defined(INSTRUMENT_LOCKS)
112 if ( lock->pid_last_reader == MyPidxx )
113 lock->pid_last_reader = 0;
114 #endif /* INSTRUMENT_LOCKS */
115 Afs_Lock_ReleaseW(lock);
117 } else if (how == WRITE_LOCK) {
118 lock->excl_locked &= ~WRITE_LOCK;
119 #if defined(INSTRUMENT_LOCKS)
120 lock->pid_writer = 0;
121 #endif /* INSTRUMENT_LOCKS */
122 if (lock->wait_states) Afs_Lock_ReleaseR(lock);
123 } else if (how == SHARED_LOCK) {
124 lock->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);
125 #if defined(INSTRUMENT_LOCKS)
126 lock->pid_writer = 0;
127 #endif /* INSTRUMENT_LOCKS */
128 if (lock->wait_states) Afs_Lock_ReleaseR(lock);
132 Afs_Lock_Obtain(lock, how)
133 register struct afs_lock *lock;
136 osi_timeval_t tt1, tt2, et;
138 AFS_STATCNT(Lock_Obtain);
145 case READ_LOCK: lock->num_waiting++;
147 lock -> wait_states |= READ_LOCK;
148 afs_osi_Sleep(&lock->readers_reading);
149 } while (lock->excl_locked & WRITE_LOCK);
151 lock->readers_reading++;
154 case WRITE_LOCK: lock->num_waiting++;
156 lock -> wait_states |= WRITE_LOCK;
157 afs_osi_Sleep(&lock->excl_locked);
158 } while (lock->excl_locked || lock->readers_reading);
160 lock->excl_locked = WRITE_LOCK;
163 case SHARED_LOCK: lock->num_waiting++;
165 lock->wait_states |= SHARED_LOCK;
166 afs_osi_Sleep(&lock->excl_locked);
167 } while (lock->excl_locked);
169 lock->excl_locked = SHARED_LOCK;
172 case BOOSTED_LOCK: lock->num_waiting++;
174 lock->wait_states |= WRITE_LOCK;
175 afs_osi_Sleep(&lock->excl_locked);
176 } while (lock->readers_reading);
178 lock->excl_locked = WRITE_LOCK;
181 default: osi_Panic("afs locktype");
185 afs_stats_GetDiff(et, tt1, tt2);
186 afs_stats_AddTo((lock->time_waiting), et);
189 afs_Trace2(afs_iclSetp, CM_TRACE_LOCKSLEPT, ICL_TYPE_POINTER, lock,
190 ICL_TYPE_INT32, how);
194 /* release a lock, giving preference to new readers */
195 Afs_Lock_ReleaseR(lock)
196 register struct afs_lock *lock;
198 AFS_STATCNT(Lock_ReleaseR);
200 if (lock->wait_states & READ_LOCK) {
201 lock->wait_states &= ~READ_LOCK;
202 afs_osi_Wakeup(&lock->readers_reading);
205 lock->wait_states &= ~EXCL_LOCKS;
206 afs_osi_Wakeup(&lock->excl_locked);
210 /* release a lock, giving preference to new writers */
211 Afs_Lock_ReleaseW(lock)
212 register struct afs_lock *lock;
214 AFS_STATCNT(Lock_ReleaseW);
216 if (lock->wait_states & EXCL_LOCKS) {
217 lock->wait_states &= ~EXCL_LOCKS;
218 afs_osi_Wakeup(&lock->excl_locked);
221 lock->wait_states &= ~READ_LOCK;
222 afs_osi_Wakeup(&lock->readers_reading);
227 Wait for some change in the lock status.
229 register struct afs_lock *lock; {
230 AFS_STATCNT(Lock_Wait);
231 if (lock->readers_reading || lock->excl_locked) return 1;
232 lock->wait_states |= READ_LOCK;
233 afs_osi_Sleep(&lock->readers_reading);
238 /* These next guys exist to provide an interface to drop a lock atomically with
239 * blocking. They're trivial to do in a non-preemptive LWP environment.
242 /* release a write lock and sleep on an address, atomically */
243 afs_osi_SleepR(addr, alock)
245 register struct afs_lock *alock; {
246 AFS_STATCNT(osi_SleepR);
247 ReleaseReadLock(alock);
251 /* release a write lock and sleep on an address, atomically */
252 afs_osi_SleepW(addr, alock)
254 register struct afs_lock *alock; {
255 AFS_STATCNT(osi_SleepW);
256 ReleaseWriteLock(alock);
260 /* release a write lock and sleep on an address, atomically */
261 afs_osi_SleepS(addr, alock)
263 register struct afs_lock *alock; {
264 AFS_STATCNT(osi_SleepS);
265 ReleaseSharedLock(alock);
270 #ifndef AFS_NOBOZO_LOCK
271 /* operations on locks that don't mind if we lock the same thing twice. I'd like to dedicate
272 this function to Sun Microsystems' Version 4.0 virtual memory system, without
273 which this wouldn't have been necessary */
274 void afs_BozonLock(alock, avc)
276 struct afs_bozoLock *alock; {
277 AFS_STATCNT(afs_BozonLock);
279 if (alock->count == 0) {
280 /* lock not held, we win */
282 alock->proc = (char *) ttoproc(curthread);
284 #ifdef AFS_64BITPOINTER_ENV
285 /* To shut up SGI compiler on remark(1413) warnings. */
286 alock->proc = (char *) (long)MyPidxx;
287 #else /* AFS_64BITPOINTER_ENV */
288 alock->proc = (char *) MyPidxx;
289 #endif /* AFS_64BITPOINTER_ENV */
294 } else if (alock->proc == (char *) ttoproc(curthread)) {
296 #ifdef AFS_64BITPOINTER_ENV
297 /* To shut up SGI compiler on remark(1413) warnings. */
298 } else if (alock->proc == (char *) (long)MyPidxx) {
299 #else /* AFS_64BITPOINTER_ENV */
300 } else if (alock->proc == (char *) MyPidxx) {
301 #endif /* AFS_64BITPOINTER_ENV */
303 /* lock is held, but by us, so we win anyway */
308 /* lock is held, and not by us; we wait */
309 alock->flags |= AFS_BOZONWAITING;
310 afs_osi_Sleep(alock);
315 /* releasing the same type of lock as defined above */
316 void afs_BozonUnlock(alock, avc)
318 struct afs_bozoLock *alock; {
319 AFS_STATCNT(afs_BozonUnlock);
320 if (alock->count <= 0)
321 osi_Panic("BozoUnlock");
322 if ((--alock->count) == 0) {
323 if (alock->flags & AFS_BOZONWAITING) {
324 alock->flags &= ~AFS_BOZONWAITING;
325 afs_osi_Wakeup(alock);
330 void afs_BozonInit(alock, avc)
332 struct afs_bozoLock *alock; {
333 AFS_STATCNT(afs_BozonInit);
336 alock->proc = (char *) 0;
339 afs_CheckBozonLock(alock)
340 struct afs_bozoLock *alock; {
341 AFS_STATCNT(afs_CheckBozonLock);
342 if (alock->count || (alock->flags & AFS_BOZONWAITING))
347 afs_CheckBozonLockBlocking(alock)
348 struct afs_bozoLock *alock; {
349 AFS_STATCNT(afs_CheckBozonLockBlocking);
350 if (alock->count || (alock->flags & AFS_BOZONWAITING))
352 if (alock->proc != (char *) ttoproc(curthread))
354 #ifdef AFS_64BITPOINTER_ENV
355 /* To shut up SGI compiler on remark(1413) warnings. */
356 if (alock->proc != (char *) (long)MyPidxx)
357 #else /* AFS_64BITPOINTER_ENV */
358 if (alock->proc != (char *) MyPidxx)
359 #endif /* AFS_64BITPOINTER_ENV */