~ubuntu-branches/ubuntu/warty/openafs/warty

« back to all changes in this revision

Viewing changes to src/afs/afs_lock.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2004-01-10 16:37:33 UTC
  • Revision ID: james.westby@ubuntu.com-20040110163733-jvr0n1uahshlb1uu
Tags: upstream-1.2.11
ImportĀ upstreamĀ versionĀ 1.2.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2000, International Business Machines Corporation and others.
 
3
 * All Rights Reserved.
 
4
 * 
 
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
 
8
 */
 
9
 
 
10
/*******************************************************************\
 
11
*                                                                   *
 
12
*       Information Technology Center                               *
 
13
*       Carnegie-Mellon University                                  *
 
14
*                                                                   *
 
15
*                                                                   *
 
16
*                                                                   *
 
17
\*******************************************************************/
 
18
 
 
19
 
 
20
/*
 
21
        Locking routines for Vice.
 
22
 
 
23
*/
 
24
 
 
25
#include <afsconfig.h>
 
26
#include "../afs/param.h"
 
27
 
 
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 $");
 
29
 
 
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 */
 
33
 
 
34
 
 
35
#ifndef FALSE
 
36
#define FALSE   0
 
37
#endif
 
38
#ifndef TRUE
 
39
#define TRUE    1
 
40
#endif
 
41
 
 
42
int afs_trclock=0;
 
43
 
 
44
void Lock_Obtain();
 
45
void Lock_ReleaseR();
 
46
void Lock_ReleaseW();
 
47
 
 
48
void Lock_Init(lock)
 
49
    register struct afs_lock *lock;
 
50
{
 
51
 
 
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;
 
59
    lock->pid_writer = 0;
 
60
    lock->src_indicator = 0;
 
61
#endif /* INSTRUMENT_LOCKS */
 
62
    lock->time_waiting.tv_sec = 0;
 
63
    lock->time_waiting.tv_usec = 0;
 
64
}
 
65
 
 
66
void ObtainLock(lock, how, src_indicator)
 
67
    register struct afs_lock *lock;
 
68
    int how;
 
69
    unsigned int src_indicator;
 
70
{
 
71
    switch (how) {
 
72
      case READ_LOCK:           
 
73
        if (!((lock)->excl_locked & WRITE_LOCK))
 
74
            (lock) -> readers_reading++;
 
75
        else
 
76
            Afs_Lock_Obtain(lock, READ_LOCK);
 
77
#if defined(INSTRUMENT_LOCKS)
 
78
        (lock)->pid_last_reader = MyPidxx;
 
79
#endif /* INSTRUMENT_LOCKS */
 
80
        break;
 
81
      case WRITE_LOCK:          
 
82
        if (!(lock)->excl_locked && !(lock)->readers_reading)
 
83
            (lock) -> excl_locked = WRITE_LOCK;
 
84
        else
 
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 */
 
90
        break;
 
91
      case SHARED_LOCK:         
 
92
        if (!(lock)->excl_locked)
 
93
            (lock) -> excl_locked = SHARED_LOCK;
 
94
        else
 
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 */
 
100
        break;
 
101
    }   
 
102
}
 
103
 
 
104
void ReleaseLock(lock, how)
 
105
    register struct afs_lock *lock;
 
106
    int how;
 
107
{
 
108
    if (how == READ_LOCK) {
 
109
        if (!--lock->readers_reading && lock->wait_states)
 
110
        {
 
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); 
 
116
        }
 
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);
 
129
    }
 
130
}
 
131
 
 
132
Afs_Lock_Obtain(lock, how)
 
133
    register struct afs_lock *lock;
 
134
    int how;
 
135
{
 
136
    osi_timeval_t tt1, tt2, et;
 
137
 
 
138
    AFS_STATCNT(Lock_Obtain);
 
139
  
 
140
    AFS_ASSERT_GLOCK();
 
141
    osi_GetuTime(&tt1);
 
142
    
 
143
    switch (how) {
 
144
 
 
145
        case READ_LOCK:         lock->num_waiting++;
 
146
                                do {
 
147
                                    lock -> wait_states |= READ_LOCK;
 
148
                                    afs_osi_Sleep(&lock->readers_reading);
 
149
                                } while (lock->excl_locked & WRITE_LOCK);
 
150
                                lock->num_waiting--;
 
151
                                lock->readers_reading++;
 
152
                                break;
 
153
 
 
154
        case WRITE_LOCK:        lock->num_waiting++;
 
155
                                do {
 
156
                                    lock -> wait_states |= WRITE_LOCK;
 
157
                                    afs_osi_Sleep(&lock->excl_locked);
 
158
                                } while (lock->excl_locked || lock->readers_reading);
 
159
                                lock->num_waiting--;
 
160
                                lock->excl_locked = WRITE_LOCK;
 
161
                                break;
 
162
 
 
163
        case SHARED_LOCK:       lock->num_waiting++;
 
164
                                do {
 
165
                                    lock->wait_states |= SHARED_LOCK;
 
166
                                    afs_osi_Sleep(&lock->excl_locked);
 
167
                                } while (lock->excl_locked);
 
168
                                lock->num_waiting--;
 
169
                                lock->excl_locked = SHARED_LOCK;
 
170
                                break;
 
171
 
 
172
        case BOOSTED_LOCK:      lock->num_waiting++;
 
173
                                do {
 
174
                                    lock->wait_states |= WRITE_LOCK;
 
175
                                    afs_osi_Sleep(&lock->excl_locked);
 
176
                                } while (lock->readers_reading);
 
177
                                lock->num_waiting--;
 
178
                                lock->excl_locked = WRITE_LOCK;
 
179
                                break;
 
180
 
 
181
        default:                osi_Panic("afs locktype");
 
182
    }
 
183
 
 
184
    osi_GetuTime(&tt2);
 
185
    afs_stats_GetDiff(et, tt1, tt2);
 
186
    afs_stats_AddTo((lock->time_waiting), et);
 
187
 
 
188
    if (afs_trclock) {
 
189
        afs_Trace2(afs_iclSetp, CM_TRACE_LOCKSLEPT, ICL_TYPE_POINTER, lock,
 
190
                   ICL_TYPE_INT32, how);
 
191
    }
 
192
}
 
193
 
 
194
/* release a lock, giving preference to new readers */
 
195
Afs_Lock_ReleaseR(lock)
 
196
    register struct afs_lock *lock;
 
197
{
 
198
    AFS_STATCNT(Lock_ReleaseR);
 
199
    AFS_ASSERT_GLOCK();
 
200
    if (lock->wait_states & READ_LOCK) {
 
201
        lock->wait_states &= ~READ_LOCK;
 
202
        afs_osi_Wakeup(&lock->readers_reading);
 
203
    }
 
204
    else {
 
205
        lock->wait_states &= ~EXCL_LOCKS;
 
206
        afs_osi_Wakeup(&lock->excl_locked);
 
207
    }
 
208
}
 
209
 
 
210
/* release a lock, giving preference to new writers */
 
211
Afs_Lock_ReleaseW(lock)
 
212
    register struct afs_lock *lock;
 
213
{
 
214
    AFS_STATCNT(Lock_ReleaseW);
 
215
    AFS_ASSERT_GLOCK();
 
216
    if (lock->wait_states & EXCL_LOCKS) {
 
217
        lock->wait_states &= ~EXCL_LOCKS;
 
218
        afs_osi_Wakeup(&lock->excl_locked);
 
219
    }
 
220
    else {
 
221
        lock->wait_states &= ~READ_LOCK;
 
222
        afs_osi_Wakeup(&lock->readers_reading);
 
223
    }
 
224
}
 
225
 
 
226
/*
 
227
Wait for some change in the lock status.
 
228
Lock_Wait(lock)
 
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);
 
234
    return 0;
 
235
}
 
236
*/
 
237
 
 
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.
 
240
 */
 
241
 
 
242
/* release a write lock and sleep on an address, atomically */
 
243
afs_osi_SleepR(addr, alock)
 
244
register char *addr;
 
245
register struct afs_lock *alock; {
 
246
    AFS_STATCNT(osi_SleepR);
 
247
    ReleaseReadLock(alock);
 
248
    afs_osi_Sleep(addr);
 
249
}
 
250
 
 
251
/* release a write lock and sleep on an address, atomically */
 
252
afs_osi_SleepW(addr, alock)
 
253
register char *addr;
 
254
register struct afs_lock *alock; {
 
255
    AFS_STATCNT(osi_SleepW);
 
256
    ReleaseWriteLock(alock);
 
257
    afs_osi_Sleep(addr);
 
258
}
 
259
 
 
260
/* release a write lock and sleep on an address, atomically */
 
261
afs_osi_SleepS(addr, alock)
 
262
register char *addr;
 
263
register struct afs_lock *alock; {
 
264
    AFS_STATCNT(osi_SleepS);
 
265
    ReleaseSharedLock(alock);
 
266
    afs_osi_Sleep(addr);
 
267
}
 
268
 
 
269
 
 
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)
 
275
struct vcache *avc;
 
276
struct afs_bozoLock *alock; {
 
277
    AFS_STATCNT(afs_BozonLock);
 
278
    while (1) {
 
279
        if (alock->count == 0) {
 
280
            /* lock not held, we win */
 
281
#ifdef  AFS_SUN5_ENV
 
282
            alock->proc = (char *) ttoproc(curthread);
 
283
#else
 
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 */
 
290
#endif
 
291
            alock->count = 1;
 
292
            return;
 
293
#ifdef  AFS_SUN5_ENV
 
294
        } else if (alock->proc == (char *) ttoproc(curthread)) {
 
295
#else
 
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 */
 
302
#endif
 
303
            /* lock is held, but by us, so we win anyway */
 
304
            alock->count++;
 
305
            return;
 
306
        }
 
307
        else {
 
308
            /* lock is held, and not by us; we wait */
 
309
            alock->flags |= AFS_BOZONWAITING;
 
310
            afs_osi_Sleep(alock);
 
311
        }
 
312
    }
 
313
}
 
314
 
 
315
/* releasing the same type of lock as defined above */
 
316
void afs_BozonUnlock(alock, avc)
 
317
struct vcache *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);
 
326
        }
 
327
    }
 
328
}
 
329
 
 
330
void afs_BozonInit(alock, avc)
 
331
struct vcache *avc;
 
332
struct afs_bozoLock *alock; {
 
333
    AFS_STATCNT(afs_BozonInit);
 
334
    alock->count = 0;
 
335
    alock->flags = 0;
 
336
    alock->proc = (char *) 0;
 
337
}
 
338
 
 
339
afs_CheckBozonLock(alock)
 
340
struct afs_bozoLock *alock; {
 
341
    AFS_STATCNT(afs_CheckBozonLock);
 
342
    if (alock->count || (alock->flags & AFS_BOZONWAITING))
 
343
        return 1;
 
344
    return 0;
 
345
}
 
346
 
 
347
afs_CheckBozonLockBlocking(alock)
 
348
struct afs_bozoLock *alock; {
 
349
    AFS_STATCNT(afs_CheckBozonLockBlocking);
 
350
    if (alock->count || (alock->flags & AFS_BOZONWAITING))
 
351
#ifdef AFS_SUN5_ENV
 
352
        if (alock->proc != (char *) ttoproc(curthread))
 
353
#else
 
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 */
 
360
#endif
 
361
            return 1;
 
362
    return 0;
 
363
}
 
364
#endif