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>
38 Lock_Init(struct Lock
*lock
)
40 lock
->readers_reading
= 0;
41 lock
->excl_locked
= 0;
42 lock
->wait_states
= 0;
43 lock
->num_waiting
= 0;
44 #ifdef AFS_PTHREAD_ENV
45 opr_mutex_init(&lock
->mutex
);
46 opr_cv_init(&lock
->read_cv
);
47 opr_cv_init(&lock
->write_cv
);
48 #endif /* AFS_PTHREAD_ENV */
52 Lock_Destroy(struct Lock
*lock
)
54 #ifdef AFS_PTHREAD_ENV
55 opr_mutex_destroy(&lock
->mutex
);
56 opr_cv_destroy(&lock
->read_cv
);
57 opr_cv_destroy(&lock
->write_cv
);
58 #endif /* AFS_PTHREAD_ENV */
62 Afs_Lock_Obtain(struct Lock
*lock
, int how
)
69 lock
->wait_states
|= READ_LOCK
;
70 #ifdef AFS_PTHREAD_ENV
71 opr_cv_wait(&lock
->read_cv
, &lock
->mutex
);
72 #else /* AFS_PTHREAD_ENV */
73 LWP_WaitProcess(&lock
->readers_reading
);
74 #endif /* AFS_PTHREAD_ENV */
75 } while (lock
->excl_locked
& WRITE_LOCK
);
77 lock
->readers_reading
++;
83 lock
->wait_states
|= WRITE_LOCK
;
84 #ifdef AFS_PTHREAD_ENV
85 opr_cv_wait(&lock
->write_cv
, &lock
->mutex
);
86 #else /* AFS_PTHREAD_ENV */
87 LWP_WaitProcess(&lock
->excl_locked
);
88 #endif /* AFS_PTHREAD_ENV */
89 } while (lock
->excl_locked
|| lock
->readers_reading
);
91 lock
->excl_locked
= WRITE_LOCK
;
97 lock
->wait_states
|= SHARED_LOCK
;
98 #ifdef AFS_PTHREAD_ENV
99 opr_cv_wait(&lock
->write_cv
, &lock
->mutex
);
100 #else /* AFS_PTHREAD_ENV */
101 LWP_WaitProcess(&lock
->excl_locked
);
102 #endif /* AFS_PTHREAD_ENV */
103 } while (lock
->excl_locked
);
105 lock
->excl_locked
= SHARED_LOCK
;
111 lock
->wait_states
|= WRITE_LOCK
;
112 #ifdef AFS_PTHREAD_ENV
113 opr_cv_wait(&lock
->write_cv
, &lock
->mutex
);
114 #else /* AFS_PTHREAD_ENV */
115 LWP_WaitProcess(&lock
->excl_locked
);
116 #endif /* AFS_PTHREAD_ENV */
117 } while (lock
->readers_reading
);
119 lock
->excl_locked
= WRITE_LOCK
;
123 printf("Can't happen, bad LOCK type: %d\n", how
);
128 /* wake up readers waiting for this lock */
130 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 opr_cv_broadcast(&lock
->read_cv
);
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 */
144 Afs_Lock_ReleaseR(struct Lock
*lock
)
146 if (lock
->wait_states
& READ_LOCK
) {
147 lock
->wait_states
&= ~READ_LOCK
;
148 #ifdef AFS_PTHREAD_ENV
149 opr_cv_broadcast(&lock
->read_cv
);
150 #else /* AFS_PTHREAD_ENV */
151 LWP_NoYieldSignal(&lock
->readers_reading
);
152 #endif /* AFS_PTHREAD_ENV */
154 lock
->wait_states
&= ~EXCL_LOCKS
;
155 #ifdef AFS_PTHREAD_ENV
156 opr_cv_broadcast(&lock
->write_cv
);
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 */
165 Afs_Lock_ReleaseW(struct Lock
*lock
)
167 if (lock
->wait_states
& EXCL_LOCKS
) {
168 lock
->wait_states
&= ~EXCL_LOCKS
;
169 #ifdef AFS_PTHREAD_ENV
170 opr_cv_broadcast(&lock
->write_cv
);
171 #else /* AFS_PTHREAD_ENV */
172 LWP_NoYieldSignal(&lock
->excl_locked
);
173 #endif /* AFS_PTHREAD_ENV */
175 lock
->wait_states
&= ~READ_LOCK
;
176 #ifdef AFS_PTHREAD_ENV
177 opr_cv_broadcast(&lock
->read_cv
);
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 */
191 LWP_WaitProcessR(void *addr
, struct Lock
*alock
)
193 ReleaseReadLock(alock
);
194 LWP_WaitProcess(addr
);
197 /* release a write lock and sleep on an address, atomically */
199 LWP_WaitProcessW(void *addr
, struct Lock
*alock
)
201 ReleaseWriteLock(alock
);
202 LWP_WaitProcess(addr
);
205 /* release a write lock and sleep on an address, atomically */
207 LWP_WaitProcessS(void *addr
, struct Lock
*alock
)
209 ReleaseSharedLock(alock
);
210 LWP_WaitProcess(addr
);
212 #endif /* AFS_PTHREAD_ENV */