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 #include <afs/param.h>
11 #include <sys/types.h>
19 #define UBIK_INTERNALS 1
23 /* Locks hang off of each transaction, with all the transaction hanging off of
24 * the appropriate dbase. This package expects to be used in a two-phase locking
25 * protocol, so it doesn't provide a way to release anything but all of the locks in the
28 * At present, it doesn't support the setting of more than one byte-position lock at a time, that is
29 * the length field must be 1. This doesn't mean that a single transaction can't set more than
32 * It is the responsibility of the user to avoid deadlock by setting locks in a partial order.
34 * EWOULDBLOCK has been replaced in this file by EAGAIN. Many Unix's but not
35 * all (eg. HP) do not replace EWOULDBLOCK with EAGAIN. The bad news is this
36 * goes over the wire. The good news is that the code path is never triggered
37 * as it requires ulock_getLock to be called with await = 0. And ulock_SetLock
38 * isn't even used in this code base. Since NT doesn't have a native
39 * EAGAIN, we are replacing all instances of EWOULDBLOCK with EAGAIN.
43 #define WouldReadBlock(lock)\
44 ((((lock)->excl_locked & WRITE_LOCK) || (lock)->wait_states) ? 0 : 1)
45 #define WouldWriteBlock(lock)\
46 ((((lock)->excl_locked & WRITE_LOCK) || (lock)->readers_reading) ? 0 : 1)
51 /* Set a transaction lock. Atype is LOCKREAD or LOCKWRITE, await is
52 * true if you want to wait for the lock instead of returning
55 * The DBHOLD lock must be held.
57 ulock_getLock(atrans, atype, await)
58 struct ubik_trans *atrans;
61 struct ubik_trans *tt;
62 struct ubik_dbase *dbase=atrans->dbase;
64 /* On first pass, initialize the lock */
70 if ((atype != LOCKREAD) && (atype != LOCKWRITE))
73 if (atrans->flags & TRDONE)
76 if (atrans->locktype != 0) {
77 printf("Ubik: Internal Error: attempted to take lock twice\n");
82 *ubik_print("Ubik: DEBUG: Thread 0x%x request %s lock\n", lwp_cpptr,
83 * ((atype == LOCKREAD) ? "READ" : "WRITE"));
86 /* Check if the lock would would block */
88 if (atype == LOCKREAD) {
89 if (WouldReadBlock(&rwlock)) return EAGAIN;
91 if (WouldWriteBlock(&rwlock)) return EAGAIN;
95 /* Create new lock record and add to spec'd transaction:
96 * locktype. This field also tells us if the thread is
97 * waiting for a lock: It will be equal to LOCKWAIT.
99 atrans->locktype = LOCKWAIT;
101 if (atype == LOCKREAD) {
102 ObtainReadLock(&rwlock);
104 ObtainWriteLock(&rwlock);
107 atrans->locktype = atype;
110 *ubik_print("Ubik: DEBUG: Thread 0x%x took %s lock\n", lwp_cpptr,
111 * ((atype == LOCKREAD) ? "READ" : "WRITE"));
116 /* Release the transaction lock */
117 ulock_relLock(atrans)
118 struct ubik_trans *atrans;
120 if (rwlockinit) return EINVAL;
122 if (atrans->locktype == LOCKREAD) {
123 ReleaseReadLock(&rwlock);
124 } else if (atrans->locktype == LOCKWRITE) {
125 ReleaseWriteLock(&rwlock);
129 *ubik_print("Ubik: DEBUG: Thread 0x%x %s unlock\n", lwp_cpptr,
130 * ((atrans->locktype == LOCKREAD) ? "READ" : "WRITE"));
133 atrans->locktype = 0;
136 /* debugging hooks */
138 struct ubik_debug *aparm;
141 aparm->anyReadLocks = 0;
142 aparm->anyWriteLocks = 0;
144 aparm->anyReadLocks = rwlock.readers_reading;
145 aparm->anyWriteLocks = ((rwlock.excl_locked == WRITE_LOCK) ? 1 : 0);