From 9e61bc0571b4812381cf89dd6f4bcbe3931f6acd Mon Sep 17 00:00:00 2001 From: rpj Date: Fri, 22 Dec 2006 02:36:40 +0000 Subject: '' --- sem_destroy.c | 62 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 32 deletions(-) (limited to 'sem_destroy.c') diff --git a/sem_destroy.c b/sem_destroy.c index 96734d1..6c98e80 100644 --- a/sem_destroy.c +++ b/sem_destroy.c @@ -82,54 +82,52 @@ sem_destroy (sem_t * sem) else { s = *sem; - *sem = NULL; - if ((result = pthread_mutex_trylock (&s->lock)) == 0) + if ((result = pthread_mutex_lock (&s->lock)) == 0) { - if (s->value >= 0) + if (s->value < 0) { (void) pthread_mutex_unlock (&s->lock); + result = EBUSY; + } + else + { + /* There are no threads currently blocked on this semaphore. */ if (!CloseHandle (s->sem)) { - *sem = s; + (void) pthread_mutex_unlock (&s->lock); result = EINVAL; } - else if ((result = pthread_mutex_destroy (&s->lock)) != 0) - { + else + { + /* + * Invalidate the semaphore handle when we have the lock. + * Other sema operations should test this after acquiring the lock + * to check that the sema is still valid, i.e. before performing any + * operations. This may only be necessary before the sema op routine + * returns so that the routine can return EINVAL - e.g. if setting + * s->value to SEM_VALUE_MAX below does force a fall-through. + */ + *sem = NULL; + + /* Prevent anyone else actually waiting on or posting this sema. + */ + s->value = SEM_VALUE_MAX; -#ifdef NEED_SEM - s->sem = CreateEvent (NULL, - PTW32_FALSE, /* manual reset is false */ - PTW32_FALSE, /* initial state is unset */ - NULL); -#else - s->sem = CreateSemaphore (NULL, /* Always NULL */ - (long) 0, /* Force threads to wait */ - (long) _POSIX_SEM_VALUE_MAX, /* Maximum value */ - NULL); /* Name */ -#endif + (void) pthread_mutex_unlock (&s->lock); - if (s->sem == 0) + do { - /* We just have to pretend that we've destroyed the semaphore - * even though we're leaving a mutex around. + /* Give other threads a chance to run and exit any sema op + * routines. Due to the SEM_VALUE_MAX value, if sem_post or + * sem_wait were blocked by us they should fall through. */ - result = 0; - } - else - { - *sem = s; - if (result != EBUSY) - result = EINVAL; + Sleep(0); } + while (pthread_mutex_destroy (&s->lock) == EBUSY); } } - else - { - (void) pthread_mutex_unlock (&s->lock); - result = EBUSY; - } } } -- cgit v1.2.3