]>
git.saurik.com Git - apple/libc.git/blob - pthreads/pthread_rwlock.c
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1998 Alex Nash
27 * All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
38 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * $FreeBSD: src/lib/libc_r/uthread/uthread_rwlock.c,v 1.6 2001/04/10 04:19:20 deischen Exp $
54 * POSIX Pthread Library
55 * -- Read Write Lock support
60 #include "pthread_internals.h"
62 /* maximum number of times a read lock may be obtained */
63 #define MAX_READ_LOCKS (INT_MAX - 1)
66 pthread_rwlock_destroy(pthread_rwlock_t
*rwlock
)
69 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
) {
72 pthread_mutex_destroy(&rwlock
->lock
);
73 pthread_cond_destroy(&rwlock
->read_signal
);
74 pthread_cond_destroy(&rwlock
->write_signal
);
75 rwlock
->sig
= _PTHREAD_NO_SIG
;
81 pthread_rwlock_init(pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
85 /* initialize the lock */
86 if ((ret
= pthread_mutex_init(&rwlock
->lock
, NULL
)) != 0)
89 /* initialize the read condition signal */
90 ret
= pthread_cond_init(&rwlock
->read_signal
, NULL
);
93 pthread_mutex_destroy(&rwlock
->lock
);
96 /* initialize the write condition signal */
97 ret
= pthread_cond_init(&rwlock
->write_signal
, NULL
);
100 pthread_cond_destroy(&rwlock
->read_signal
);
101 pthread_mutex_destroy(&rwlock
->lock
);
106 rwlock
->blocked_writers
= 0;
107 rwlock
->sig
= _PTHREAD_RWLOCK_SIG
;
115 pthread_rwlock_rdlock(pthread_rwlock_t
*rwlock
)
119 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
120 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
125 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
127 /* grab the monitor lock */
128 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
131 /* give writers priority over readers */
132 while (rwlock
->blocked_writers
|| rwlock
->state
< 0) {
133 ret
= pthread_cond_wait(&rwlock
->read_signal
, &rwlock
->lock
);
136 /* can't do a whole lot if this fails */
137 pthread_mutex_unlock(&rwlock
->lock
);
142 /* check lock count */
143 if (rwlock
->state
== MAX_READ_LOCKS
)
146 ++rwlock
->state
; /* indicate we are locked for reading */
149 * Something is really wrong if this call fails. Returning
150 * error won't do because we've already obtained the read
151 * lock. Decrementing 'state' is no good because we probably
152 * don't have the monitor lock.
154 pthread_mutex_unlock(&rwlock
->lock
);
160 pthread_rwlock_tryrdlock(pthread_rwlock_t
*rwlock
)
164 /* check for static initialization */
165 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
166 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
171 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
173 /* grab the monitor lock */
174 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
177 /* give writers priority over readers */
178 if (rwlock
->blocked_writers
|| rwlock
->state
< 0)
180 else if (rwlock
->state
== MAX_READ_LOCKS
)
181 ret
= EAGAIN
; /* too many read locks acquired */
183 ++rwlock
->state
; /* indicate we are locked for reading */
185 /* see the comment on this in pthread_rwlock_rdlock */
186 pthread_mutex_unlock(&rwlock
->lock
);
192 pthread_rwlock_trywrlock(pthread_rwlock_t
*rwlock
)
196 /* check for static initialization */
197 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
198 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
203 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
205 /* grab the monitor lock */
206 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
209 if (rwlock
->state
!= 0)
212 /* indicate we are locked for writing */
215 /* see the comment on this in pthread_rwlock_rdlock */
216 pthread_mutex_unlock(&rwlock
->lock
);
222 pthread_rwlock_unlock(pthread_rwlock_t
*rwlock
)
226 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
228 /* grab the monitor lock */
229 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
232 if (rwlock
->state
> 0) {
233 if (--rwlock
->state
== 0 && rwlock
->blocked_writers
)
234 ret
= pthread_cond_signal(&rwlock
->write_signal
);
235 } else if (rwlock
->state
< 0) {
238 if (rwlock
->blocked_writers
)
239 ret
= pthread_cond_signal(&rwlock
->write_signal
);
241 ret
= pthread_cond_broadcast(&rwlock
->read_signal
);
245 /* see the comment on this in pthread_rwlock_rdlock */
246 pthread_mutex_unlock(&rwlock
->lock
);
252 pthread_rwlock_wrlock(pthread_rwlock_t
*rwlock
)
256 /* check for static initialization */
257 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
258 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
263 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
265 /* grab the monitor lock */
266 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
269 while (rwlock
->state
!= 0) {
270 ++rwlock
->blocked_writers
;
272 ret
= pthread_cond_wait(&rwlock
->write_signal
, &rwlock
->lock
);
275 --rwlock
->blocked_writers
;
276 pthread_mutex_unlock(&rwlock
->lock
);
280 --rwlock
->blocked_writers
;
283 /* indicate we are locked for writing */
286 /* see the comment on this in pthread_rwlock_rdlock */
287 pthread_mutex_unlock(&rwlock
->lock
);
293 pthread_rwlockattr_init(pthread_rwlockattr_t
*attr
)
295 attr
->sig
= _PTHREAD_RWLOCK_ATTR_SIG
;
296 attr
->pshared
= PTHREAD_PROCESS_PRIVATE
;
301 pthread_rwlockattr_destroy(pthread_rwlockattr_t
*attr
)
303 attr
->sig
= _PTHREAD_NO_SIG
; /* Uninitialized */
309 pthread_rwlockattr_getpshared(const pthread_rwlockattr_t
*attr
,
312 if (attr
->sig
== _PTHREAD_RWLOCK_ATTR_SIG
)
314 /* *pshared = (int)attr->pshared; */
315 *pshared
= (int)PTHREAD_PROCESS_PRIVATE
;
319 return (EINVAL
); /* Not an initialized 'attribute' structure */
325 pthread_rwlockattr_setpshared(pthread_rwlockattr_t
* attr
, int pshared
)
327 if (attr
->sig
== _PTHREAD_RWLOCK_ATTR_SIG
)
329 if ( pshared
== PTHREAD_PROCESS_PRIVATE
)
331 attr
->pshared
= pshared
;
335 return (EINVAL
); /* Invalid parameter */
339 return (EINVAL
); /* Not an initialized 'attribute' structure */