]>
git.saurik.com Git - apple/libc.git/blob - pthreads/pthread_rwlock.c
e78cc3c24377b171b6484d84cc21d5dbbff4cd5d
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1998 Alex Nash
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
36 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
37 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
42 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * $FreeBSD: src/lib/libc_r/uthread/uthread_rwlock.c,v 1.6 2001/04/10 04:19:20 deischen Exp $
52 * POSIX Pthread Library
53 * -- Read Write Lock support
58 #include "pthread_internals.h"
60 /* maximum number of times a read lock may be obtained */
61 #define MAX_READ_LOCKS (INT_MAX - 1)
64 pthread_rwlock_destroy(pthread_rwlock_t
*rwlock
)
67 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
) {
70 pthread_mutex_destroy(&rwlock
->lock
);
71 pthread_cond_destroy(&rwlock
->read_signal
);
72 pthread_cond_destroy(&rwlock
->write_signal
);
73 rwlock
->sig
= _PTHREAD_NO_SIG
;
79 pthread_rwlock_init(pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
83 /* initialize the lock */
84 if ((ret
= pthread_mutex_init(&rwlock
->lock
, NULL
)) != 0)
87 /* initialize the read condition signal */
88 ret
= pthread_cond_init(&rwlock
->read_signal
, NULL
);
91 pthread_mutex_destroy(&rwlock
->lock
);
94 /* initialize the write condition signal */
95 ret
= pthread_cond_init(&rwlock
->write_signal
, NULL
);
98 pthread_cond_destroy(&rwlock
->read_signal
);
99 pthread_mutex_destroy(&rwlock
->lock
);
104 rwlock
->blocked_writers
= 0;
105 rwlock
->sig
= _PTHREAD_RWLOCK_SIG
;
113 pthread_rwlock_rdlock(pthread_rwlock_t
*rwlock
)
117 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
118 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
123 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
125 /* grab the monitor lock */
126 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
129 /* give writers priority over readers */
130 while (rwlock
->blocked_writers
|| rwlock
->state
< 0) {
131 ret
= pthread_cond_wait(&rwlock
->read_signal
, &rwlock
->lock
);
134 /* can't do a whole lot if this fails */
135 pthread_mutex_unlock(&rwlock
->lock
);
140 /* check lock count */
141 if (rwlock
->state
== MAX_READ_LOCKS
)
144 ++rwlock
->state
; /* indicate we are locked for reading */
147 * Something is really wrong if this call fails. Returning
148 * error won't do because we've already obtained the read
149 * lock. Decrementing 'state' is no good because we probably
150 * don't have the monitor lock.
152 pthread_mutex_unlock(&rwlock
->lock
);
158 pthread_rwlock_tryrdlock(pthread_rwlock_t
*rwlock
)
162 /* check for static initialization */
163 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
164 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
169 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
171 /* grab the monitor lock */
172 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
175 /* give writers priority over readers */
176 if (rwlock
->blocked_writers
|| rwlock
->state
< 0)
178 else if (rwlock
->state
== MAX_READ_LOCKS
)
179 ret
= EAGAIN
; /* too many read locks acquired */
181 ++rwlock
->state
; /* indicate we are locked for reading */
183 /* see the comment on this in pthread_rwlock_rdlock */
184 pthread_mutex_unlock(&rwlock
->lock
);
190 pthread_rwlock_trywrlock(pthread_rwlock_t
*rwlock
)
194 /* check for static initialization */
195 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
196 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
201 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
203 /* grab the monitor lock */
204 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
207 if (rwlock
->state
!= 0)
210 /* indicate we are locked for writing */
213 /* see the comment on this in pthread_rwlock_rdlock */
214 pthread_mutex_unlock(&rwlock
->lock
);
220 pthread_rwlock_unlock(pthread_rwlock_t
*rwlock
)
224 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
226 /* grab the monitor lock */
227 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
230 if (rwlock
->state
> 0) {
231 if (--rwlock
->state
== 0 && rwlock
->blocked_writers
)
232 ret
= pthread_cond_signal(&rwlock
->write_signal
);
233 } else if (rwlock
->state
< 0) {
236 if (rwlock
->blocked_writers
)
237 ret
= pthread_cond_signal(&rwlock
->write_signal
);
239 ret
= pthread_cond_broadcast(&rwlock
->read_signal
);
243 /* see the comment on this in pthread_rwlock_rdlock */
244 pthread_mutex_unlock(&rwlock
->lock
);
250 pthread_rwlock_wrlock(pthread_rwlock_t
*rwlock
)
254 /* check for static initialization */
255 if (rwlock
->sig
== _PTHREAD_RWLOCK_SIG_init
) {
256 if ((ret
= pthread_rwlock_init(rwlock
, NULL
)) != 0) {
261 if (rwlock
->sig
!= _PTHREAD_RWLOCK_SIG
)
263 /* grab the monitor lock */
264 if ((ret
= pthread_mutex_lock(&rwlock
->lock
)) != 0)
267 while (rwlock
->state
!= 0) {
268 ++rwlock
->blocked_writers
;
270 ret
= pthread_cond_wait(&rwlock
->write_signal
, &rwlock
->lock
);
273 --rwlock
->blocked_writers
;
274 pthread_mutex_unlock(&rwlock
->lock
);
278 --rwlock
->blocked_writers
;
281 /* indicate we are locked for writing */
284 /* see the comment on this in pthread_rwlock_rdlock */
285 pthread_mutex_unlock(&rwlock
->lock
);
291 pthread_rwlockattr_init(pthread_rwlockattr_t
*attr
)
293 attr
->sig
= _PTHREAD_RWLOCK_ATTR_SIG
;
294 attr
->pshared
= PTHREAD_PROCESS_PRIVATE
;
299 pthread_rwlockattr_destroy(pthread_rwlockattr_t
*attr
)
301 attr
->sig
= _PTHREAD_NO_SIG
; /* Uninitialized */
307 pthread_rwlockattr_getpshared(const pthread_rwlockattr_t
*attr
,
310 if (attr
->sig
== _PTHREAD_RWLOCK_ATTR_SIG
)
312 /* *pshared = (int)attr->pshared; */
313 *pshared
= (int)PTHREAD_PROCESS_PRIVATE
;
317 return (EINVAL
); /* Not an initialized 'attribute' structure */
323 pthread_rwlockattr_setpshared(pthread_rwlockattr_t
* attr
, int pshared
)
325 if (attr
->sig
== _PTHREAD_RWLOCK_ATTR_SIG
)
327 if ( pshared
== PTHREAD_PROCESS_PRIVATE
)
329 attr
->pshared
= pshared
;
333 return (EINVAL
); /* Invalid parameter */
337 return (EINVAL
); /* Not an initialized 'attribute' structure */