]>
git.saurik.com Git - apple/libc.git/blob - pthreads/pthread_rwlock.c
978ed80fbf78b3a7d377b42ad9e1502cdd12f39b
2 * Copyright (c) 1998 Alex Nash
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/lib/libc_r/uthread/uthread_rwlock.c,v 1.6 2001/04/10 04:19:20 deischen Exp $
30 * POSIX Pthread Library
31 * -- Read Write Lock support
36 #include "pthread_internals.h"
38 /* maximum number of times a read lock may be obtained */
39 #define MAX_READ_LOCKS (INT_MAX - 1)
42 pthread_rwlock_destroy(pthread_rwlock_t
*rwlock
)
45 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
) {
48 pthread_mutex_destroy(&rwlock
->lock
);
49 pthread_cond_destroy(&rwlock
->read_signal
);
50 pthread_cond_destroy(&rwlock
->write_signal
);
51 rwlock
->sig
= _PTHREAD_NO_SIG
;
57 pthread_rwlock_init(pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
61 /* initialize the lock */
62 if ((ret
= pthread_mutex_init(&rwlock
->lock
, NULL
)) != 0)
65 /* initialize the read condition signal */
66 ret
= pthread_cond_init(&rwlock
->read_signal
, NULL
);
69 pthread_mutex_destroy(&rwlock
->lock
);
72 /* initialize the write condition signal */
73 ret
= pthread_cond_init(&rwlock
->write_signal
, NULL
);
76 pthread_cond_destroy(&rwlock
->read_signal
);
77 pthread_mutex_destroy(&rwlock
->lock
);
82 rwlock
->blocked_writers
= 0;
83 rwlock
->sig
= _PTHREAD_RWLOCK_SIG
;
91 pthread_rwlock_rdlock(pthread_rwlock_t
*rwlock
)
95 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
96 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
101 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
103 /* grab the monitor lock */
104 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
107 /* give writers priority over readers */
108 while (rwlock
->blocked_writers
|| rwlock
->state
< 0) {
109 ret
= pthread_cond_wait(&rwlock
->read_signal
, &rwlock
->lock
);
112 /* can't do a whole lot if this fails */
113 pthread_mutex_unlock(&rwlock
->lock
);
118 /* check lock count */
119 if (rwlock
->state
== MAX_READ_LOCKS
)
122 ++rwlock
->state
; /* indicate we are locked for reading */
125 * Something is really wrong if this call fails. Returning
126 * error won't do because we've already obtained the read
127 * lock. Decrementing 'state' is no good because we probably
128 * don't have the monitor lock.
130 pthread_mutex_unlock(&rwlock
->lock
);
136 pthread_rwlock_tryrdlock(pthread_rwlock_t
*rwlock
)
140 /* check for static initialization */
141 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
142 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
147 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
149 /* grab the monitor lock */
150 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
153 /* give writers priority over readers */
154 if (rwlock
->blocked_writers
|| rwlock
->state
< 0)
156 else if (rwlock
->state
== MAX_READ_LOCKS
)
157 ret
= EAGAIN
; /* too many read locks acquired */
159 ++rwlock
->state
; /* indicate we are locked for reading */
161 /* see the comment on this in pthread_rwlock_rdlock */
162 pthread_mutex_unlock(&rwlock
->lock
);
168 pthread_rwlock_trywrlock(pthread_rwlock_t
*rwlock
)
172 /* check for static initialization */
173 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
174 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
179 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
181 /* grab the monitor lock */
182 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
185 if (rwlock
->state
!= 0)
188 /* indicate we are locked for writing */
191 /* see the comment on this in pthread_rwlock_rdlock */
192 pthread_mutex_unlock(&rwlock
->lock
);
198 pthread_rwlock_unlock(pthread_rwlock_t
*rwlock
)
202 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
204 /* grab the monitor lock */
205 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
208 if (rwlock
->state
> 0) {
209 if (--rwlock
->state
== 0 && rwlock
->blocked_writers
)
210 ret
= pthread_cond_signal(&rwlock
->write_signal
);
211 } else if (rwlock
->state
< 0) {
214 if (rwlock
->blocked_writers
)
215 ret
= pthread_cond_signal(&rwlock
->write_signal
);
217 ret
= pthread_cond_broadcast(&rwlock
->read_signal
);
221 /* see the comment on this in pthread_rwlock_rdlock */
222 pthread_mutex_unlock(&rwlock
->lock
);
228 pthread_rwlock_wrlock(pthread_rwlock_t
*rwlock
)
232 /* check for static initialization */
233 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
234 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
239 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
241 /* grab the monitor lock */
242 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
245 while (rwlock
->state
!= 0) {
246 ++rwlock
->blocked_writers
;
248 ret
= pthread_cond_wait(&rwlock
->write_signal
, &rwlock
->lock
);
251 --rwlock
->blocked_writers
;
252 pthread_mutex_unlock(&rwlock
->lock
);
256 --rwlock
->blocked_writers
;
259 /* indicate we are locked for writing */
262 /* see the comment on this in pthread_rwlock_rdlock */
263 pthread_mutex_unlock(&rwlock
->lock
);
269 pthread_rwlockattr_init(pthread_rwlockattr_t
*attr
)
271 attr
->sig
= _PTHREAD_RWLOCK_ATTR_SIG
;
272 attr
->pshared
= PTHREAD_PROCESS_PRIVATE
;
277 pthread_rwlockattr_destroy(pthread_rwlockattr_t
*attr
)
279 attr
->sig
= _PTHREAD_NO_SIG
; /* Uninitialized */
285 pthread_rwlockattr_getpshared(const pthread_rwlockattr_t
*attr
,
288 if (attr
->sig
== _PTHREAD_RWLOCK_ATTR_SIG
)
290 /* *pshared = (int)attr->pshared; */
291 *pshared
= (int)PTHREAD_PROCESS_PRIVATE
;
295 return (EINVAL
); /* Not an initialized 'attribute' structure */
301 pthread_rwlockattr_setpshared(pthread_rwlockattr_t
* attr
, int pshared
)
303 if (attr
->sig
== _PTHREAD_RWLOCK_ATTR_SIG
)
305 if ( pshared
== PTHREAD_PROCESS_PRIVATE
)
307 attr
->pshared
= pshared
;
311 return (EINVAL
); /* Invalid parameter */
315 return (EINVAL
); /* Not an initialized 'attribute' structure */