1 /*
2  * -------------------------------------------------------------
3  *
4  * Module: sem_destroy.c
5  *
6  * Purpose:
7  *	Semaphores aren't actually part of the PThreads standard.
8  *	They are defined by the POSIX Standard:
9  *
10  *		POSIX 1003.1b-1993	(POSIX.1b)
11  *
12  * -------------------------------------------------------------
13  *
14  * --------------------------------------------------------------------------
15  *
16  *      Pthreads-win32 - POSIX Threads Library for Win32
17  *      Copyright(C) 1998 John E. Bossom
18  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
19  *
20  *      Contact Email: rpj@callisto.canberra.edu.au
21  *
22  *      The current list of contributors is contained
23  *      in the file CONTRIBUTORS included with the source
24  *      code distribution. The list can also be seen at the
25  *      following World Wide Web location:
26  *      http://sources.redhat.com/pthreads-win32/contributors.html
27  *
28  *      This library is free software; you can redistribute it and/or
29  *      modify it under the terms of the GNU Lesser General Public
30  *      License as published by the Free Software Foundation; either
31  *      version 2 of the License, or (at your option) any later version.
32  *
33  *      This library is distributed in the hope that it will be useful,
34  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
35  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
36  *      Lesser General Public License for more details.
37  *
38  *      You should have received a copy of the GNU Lesser General Public
39  *      License along with this library in the file COPYING.LIB;
40  *      if not, write to the Free Software Foundation, Inc.,
41  *      51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
42  */
43 
44 #include "pthread.h"
45 #include "semaphore.h"
46 #include "implement.h"
47 
48 
49 int
sem_destroy(sem_t * sem)50 sem_destroy (sem_t * sem)
51      /*
52       * ------------------------------------------------------
53       * DOCPUBLIC
54       *      This function destroys an unnamed semaphore.
55       *
56       * PARAMETERS
57       *      sem
58       *              pointer to an instance of sem_t
59       *
60       * DESCRIPTION
61       *      This function destroys an unnamed semaphore.
62       *
63       * RESULTS
64       *              0               successfully destroyed semaphore,
65       *              -1              failed, error in errno
66       * ERRNO
67       *              EINVAL          'sem' is not a valid semaphore,
68       *              ENOSYS          semaphores are not supported,
69       *              EBUSY           threads (or processes) are currently
70       *                                      blocked on 'sem'
71       *
72       * ------------------------------------------------------
73       */
74 {
75   int result = 0;
76   sem_t s = NULL;
77 
78   if (sem == NULL || *sem == NULL)
79     {
80       result = EINVAL;
81     }
82   else
83     {
84       s = *sem;
85 
86       if ((result = pthread_mutex_lock (&s->lock)) == 0)
87         {
88           if (s->value < 0)
89             {
90               (void) pthread_mutex_unlock (&s->lock);
91               result = EBUSY;
92             }
93           else
94             {
95               /* There are no threads currently blocked on this semaphore. */
96 
97               if (!CloseHandle (s->sem))
98 	        {
99                   (void) pthread_mutex_unlock (&s->lock);
100 	          result = EINVAL;
101 	        }
102 	      else
103 	        {
104                   /*
105                    * Invalidate the semaphore handle when we have the lock.
106                    * Other sema operations should test this after acquiring the lock
107                    * to check that the sema is still valid, i.e. before performing any
108                    * operations. This may only be necessary before the sema op routine
109                    * returns so that the routine can return EINVAL - e.g. if setting
110                    * s->value to SEM_VALUE_MAX below does force a fall-through.
111                    */
112                   *sem = NULL;
113 
114                   /* Prevent anyone else actually waiting on or posting this sema.
115                    */
116                   s->value = SEM_VALUE_MAX;
117 
118                   (void) pthread_mutex_unlock (&s->lock);
119 
120                   do
121                     {
122                       /* Give other threads a chance to run and exit any sema op
123                        * routines. Due to the SEM_VALUE_MAX value, if sem_post or
124                        * sem_wait were blocked by us they should fall through.
125                        */
126                       Sleep(0);
127                     }
128                   while (pthread_mutex_destroy (&s->lock) == EBUSY);
129                 }
130             }
131         }
132     }
133 
134   if (result != 0)
135     {
136       errno = result;
137       return -1;
138     }
139 
140   free (s);
141 
142   return 0;
143 
144 }				/* sem_destroy */
145