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