1/* 2 * pthread_rwlock_destroy.c 3 * 4 * Description: 5 * This translation unit implements read/write lock primitives. 6 * 7 * -------------------------------------------------------------------------- 8 * 9 * Pthreads-win32 - POSIX Threads Library for Win32 10 * Copyright(C) 1998 John E. Bossom 11 * Copyright(C) 1999,2005 Pthreads-win32 contributors 12 * 13 * Contact Email: rpj@callisto.canberra.edu.au 14 * 15 * The current list of contributors is contained 16 * in the file CONTRIBUTORS included with the source 17 * code distribution. The list can also be seen at the 18 * following World Wide Web location: 19 * http://sources.redhat.com/pthreads-win32/contributors.html 20 * 21 * This library is free software; you can redistribute it and/or 22 * modify it under the terms of the GNU Lesser General Public 23 * License as published by the Free Software Foundation; either 24 * version 2 of the License, or (at your option) any later version. 25 * 26 * This library is distributed in the hope that it will be useful, 27 * but WITHOUT ANY WARRANTY; without even the implied warranty of 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 29 * Lesser General Public License for more details. 30 * 31 * You should have received a copy of the GNU Lesser General Public 32 * License along with this library in the file COPYING.LIB; 33 * if not, write to the Free Software Foundation, Inc., 34 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 35 */ 36 37#include <limits.h> 38 39#include "pthread.h" 40#include "implement.h" 41 42int 43pthread_rwlock_destroy (pthread_rwlock_t * rwlock) 44{ 45 pthread_rwlock_t rwl; 46 int result = 0, result1 = 0, result2 = 0; 47 48 if (rwlock == NULL || *rwlock == NULL) 49 { 50 return EINVAL; 51 } 52 53 if (*rwlock != PTHREAD_RWLOCK_INITIALIZER) 54 { 55 rwl = *rwlock; 56 57 if (rwl->nMagic != PTW32_RWLOCK_MAGIC) 58 { 59 return EINVAL; 60 } 61 62 if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0) 63 { 64 return result; 65 } 66 67 if ((result = 68 pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) 69 { 70 (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); 71 return result; 72 } 73 74 /* 75 * Check whether any threads own/wait for the lock (wait for ex.access); 76 * report "BUSY" if so. 77 */ 78 if (rwl->nExclusiveAccessCount > 0 79 || rwl->nSharedAccessCount > rwl->nCompletedSharedAccessCount) 80 { 81 result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted)); 82 result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); 83 result2 = EBUSY; 84 } 85 else 86 { 87 rwl->nMagic = 0; 88 89 if ((result = 90 pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) 91 { 92 pthread_mutex_unlock (&rwl->mtxExclusiveAccess); 93 return result; 94 } 95 96 if ((result = 97 pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) != 0) 98 { 99 return result; 100 } 101 102 *rwlock = NULL; /* Invalidate rwlock before anything else */ 103 result = pthread_cond_destroy (&(rwl->cndSharedAccessCompleted)); 104 result1 = pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted)); 105 result2 = pthread_mutex_destroy (&(rwl->mtxExclusiveAccess)); 106 (void) free (rwl); 107 } 108 } 109 else 110 { 111 ptw32_mcs_local_node_t node; 112 /* 113 * See notes in ptw32_rwlock_check_need_init() above also. 114 */ 115 ptw32_mcs_lock_acquire(&ptw32_rwlock_test_init_lock, &node); 116 117 /* 118 * Check again. 119 */ 120 if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) 121 { 122 /* 123 * This is all we need to do to destroy a statically 124 * initialised rwlock that has not yet been used (initialised). 125 * If we get to here, another thread 126 * waiting to initialise this rwlock will get an EINVAL. 127 */ 128 *rwlock = NULL; 129 } 130 else 131 { 132 /* 133 * The rwlock has been initialised while we were waiting 134 * so assume it's in use. 135 */ 136 result = EBUSY; 137 } 138 139 ptw32_mcs_lock_release(&node); 140 } 141 142 return ((result != 0) ? result : ((result1 != 0) ? result1 : result2)); 143} 144