summaryrefslogtreecommitdiff
path: root/pthread_barrier_destroy.c
diff options
context:
space:
mode:
authorrpj <rpj>2010-06-20 03:31:18 +0000
committerrpj <rpj>2010-06-20 03:31:18 +0000
commita3ea0b24409b89bd08c0a2268dbae834724734df (patch)
tree4629fd085756226f0cee8beba4faf66466ef0410 /pthread_barrier_destroy.c
parent135d6f060c5e5232311af77bd0d0f500e861290c (diff)
See ChangeLogs: preparing for new release.
Diffstat (limited to 'pthread_barrier_destroy.c')
-rw-r--r--pthread_barrier_destroy.c48
1 files changed, 42 insertions, 6 deletions
diff --git a/pthread_barrier_destroy.c b/pthread_barrier_destroy.c
index 9302ba7..baed212 100644
--- a/pthread_barrier_destroy.c
+++ b/pthread_barrier_destroy.c
@@ -37,31 +37,67 @@
#include "pthread.h"
#include "implement.h"
-
int
pthread_barrier_destroy (pthread_barrier_t * barrier)
{
int result = 0;
pthread_barrier_t b;
+ ptw32_mcs_local_node_t node;
if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
{
return EINVAL;
}
+ if (0 != ptw32_mcs_lock_try_acquire((ptw32_mcs_lock_t *)&(*barrier)->lock, &node))
+ {
+ return EBUSY;
+ }
+
b = *barrier;
- *barrier = NULL;
- if (0 == (result = sem_destroy (&(b->semBarrierBreeched[0]))))
+ if (b->nCurrentBarrierHeight < b->nInitialBarrierHeight)
{
- if (0 == (result = sem_destroy (&(b->semBarrierBreeched[1]))))
+ result = EBUSY;
+ }
+ else
{
+ if (0 == (result = sem_destroy (&(b->semBarrierBreeched))))
+ {
+ *barrier = (pthread_barrier_t) PTW32_OBJECT_INVALID;
+ /*
+ * Release the lock before freeing b.
+ *
+ * FIXME: There may be successors which, when we release the lock,
+ * will be linked into b->lock, which will be corrupted at some
+ * point with undefined results for the application. To fix this
+ * will require changing pthread_barrier_t from a pointer to
+ * pthread_barrier_t_ to an instance. This is a change to the ABI
+ * and will require a major version number increment.
+ */
+ ptw32_mcs_lock_release(&node);
(void) free (b);
return 0;
}
- (void) sem_init (&(b->semBarrierBreeched[0]), b->pshared, 0);
+ else
+ {
+ /*
+ * This should not ever be reached.
+ * Restore the barrier to working condition before returning.
+ */
+ (void) sem_init (&(b->semBarrierBreeched), b->pshared, 0);
+ }
+
+ if (result != 0)
+ {
+ /*
+ * The barrier still exists and is valid
+ * in the event of any error above.
+ */
+ result = EBUSY;
+ }
}
- *barrier = b;
+ ptw32_mcs_lock_release(&node);
return (result);
}