summaryrefslogtreecommitdiff
path: root/pthread_join.c
diff options
context:
space:
mode:
Diffstat (limited to 'pthread_join.c')
-rw-r--r--pthread_join.c103
1 files changed, 14 insertions, 89 deletions
diff --git a/pthread_join.c b/pthread_join.c
index 56ed0ba..8237b6c 100644
--- a/pthread_join.c
+++ b/pthread_join.c
@@ -84,60 +84,10 @@ pthread_join (pthread_t thread, void **value_ptr)
pthread_t self;
ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
- /*
- * Possibilities for the target thread on entry to pthread_join():
- *
- * 1) the target thread is detached, in which case it could be destroyed and
- * it's thread id (struct) reused before we get the reuse lock;
- * 2) the target thread is joinable, in which case it will not be destroyed
- * until it has been joined, and it's thread id cannot be reused before we
- * get access to it.
- *
- * Only (1) is a potential race condition.
- * While (1) is possibly an application programming error, pthread_join is
- * required to handle it with an error.
- * If an application attempts to join a detached thread that exits before we
- * get the reuse lock, it's thread struct could be reused for a new joinable
- * thread before we get the reuse_lock and we will then be joining the wrong
- * thread.
- *
- * To fix this properly would require a reuse count as part of the thread id
- * so that we could confirm that we are working with the same thread. This
- * option will require a major change to the API, forcing recompilation of
- * applications that use the library.
- *
- * Cheaper alternatives that do not change the API are:
- * - separate reuse stacks could be used for detached and joinable
- * threads. Threads which detach themselves will not present a race condition
- * because they will be placed on a different stack to that which provides
- * reusable structs to new joinable threads.
- * The problem with this solution is that, an application that creates
- * joinable threads which then detach themselves can cause the detach reuse
- * stack to grow indefinitely.
- *
- * - maintain a sufficiently large reuse pool and manage it as a FIFO
- * queue. This would prevent the immediate reuse of thread structs, but this
- * only provides a statistical safeguard, not a deterministic one.
- *
- * - include an entry point array at the start of each thread struct so that
- * each reuse (modulo N) returns a different thread id (pointer to the thread
- * struct). Offset 0 from this pointer will contain a validity field and an
- * offset value field (subtracted from the pointer to obtain the address of
- * thread struct). This option is similar to including a reuse counter with
- * the thread id but maintains the thread id as a simple pointer.
- *
- * As at 03/11/2004, the reuse count option has been implemented.
- */
-
EnterCriticalSection (&ptw32_thread_reuse_lock);
- /*
- * The first test is the same as pthread_kill(thread, 0), duplicated here
- * so that we can use the reuse_lock to ensure the thread isn't destroyed
- * and reused before we've finished with the POSIX thread struct.
- */
- if (tp == NULL
- || NULL == tp->threadH
- || THREAD_PRIORITY_ERROR_RETURN == GetThreadPriority (tp->threadH))
+
+ if (NULL == tp
+ || thread.x != tp->ptHandle.x)
{
result = ESRCH;
}
@@ -147,19 +97,23 @@ pthread_join (pthread_t thread, void **value_ptr)
}
else
{
+ result = 0;
+ }
+
+ LeaveCriticalSection (&ptw32_thread_reuse_lock);
+
+ if (result == 0)
+ {
/*
* The target thread is joinable and can't be reused before we join it.
*/
-
- LeaveCriticalSection (&ptw32_thread_reuse_lock);
-
self = pthread_self();
if (NULL == self.p)
{
result = ENOENT;
}
- else if (0 != pthread_equal (self, thread))
+ else if (pthread_equal (self, thread))
{
result = EDEADLK;
}
@@ -176,29 +130,6 @@ pthread_join (pthread_t thread, void **value_ptr)
if (0 == result)
{
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__)
-
- if (value_ptr != NULL
- && !GetExitCodeThread (tp->threadH, (LPDWORD) value_ptr))
- {
- result = ESRCH;
- }
- else
- {
- /*
- * The result of making multiple simultaneous calls to
- * pthread_join() specifying the same target is undefined.
- */
- ptw32_threadDestroy (thread);
- }
-
-#else /* __MINGW32__ && ! __MSVCRT__ */
-
- /*
- * If using CRTDLL, the thread may have exited, and endthread
- * will have closed the handle.
- */
if (value_ptr != NULL)
{
*value_ptr = tp->exitStatus;
@@ -206,24 +137,18 @@ pthread_join (pthread_t thread, void **value_ptr)
/*
* The result of making multiple simultaneous calls to
- * pthread_join() specifying the same target is undefined.
+ * pthread_join() or pthread_detach() specifying the same
+ * target is undefined.
*/
- ptw32_threadDestroy (thread);
-
-#endif /* __MINGW32__ && ! __MSVCRT__ */
-
+ result = pthread_detach (thread);
}
else
{
result = ESRCH;
}
}
-
- goto FAIL0;
}
- LeaveCriticalSection (&ptw32_thread_reuse_lock);
-FAIL0:
return (result);
} /* pthread_join */