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"
28
RCSID("$Header: /afs/sipb.mit.edu/project/openafs/debian/cvs/openafs/src/afs/afs_lock.c,v 1.1.1.4 2001/07/14 22:19:22 hartmans Exp $");
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 */