]>
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 */