summaryrefslogtreecommitdiff
path: root/sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'sync.c')
-rw-r--r--sync.c243
1 files changed, 91 insertions, 152 deletions
diff --git a/sync.c b/sync.c
index 069d10a..57f56b8 100644
--- a/sync.c
+++ b/sync.c
@@ -6,183 +6,122 @@
* synchronisation.
*/
-#include <errno.h>
-
-/* POSIX STANDARD: A thread may pass a value pointer to some data via
- pthread_exit(). That pointer will be stored in a location supplied
- as an argument to pthread_join().
-
- IMPLEMENTATION: The value_ptr is stored in the thread entry. When
- pthread_join() wakes up after waiting, or immediately if the target
- thread has already terminated but is not detached, the value
- pointer from pthread_exit() will be copied to *value_ptr.
-
- If the target thread does not become detached in the mean time, all
- waiting joins on that thread will get the value pointer. The last
- waiting join will delete the target thread entry.
-
- ----
-
- POSIX STANDARD: The results of multiple simultaneous calls to
- pthread_join() specifying the same target thread are undefined.
-
- IMPLEMENTATION: Any such join that occurs before the first such
- join wakes up, or the thread is otherwise detached (by a call to
- pthread_detach), will return successfully with the value that was
- passed to pthread_exit(). After the last such join returns, the
- target thread will have be detached and it's entry removed from the
- thread table.
-
- Until the target thread entry is deleted it will be counted against
- {PTHREAD_COUNT_MAX}.
-
- ----
-
- ----
-
- POSIX STANDARD: It is unspecified whether a thread that has exited
- but remains unjoined counts against {PTHREAD_COUNT_MAX}.
-
- IMPLEMENTATION: A thread that has exited but remains unjoined will
- be counted against {PTHREAD_COUNT_MAX}. The first call to
- pthread_join() or pthread_detach() will remove the target thread's
- table entry and decrement the count.
-
- ---- */
-
-#include <windows.h>
#include "pthread.h"
#include "implement.h"
+/*
+ * Code contributed by John E. Bossom <JEB>.
+ */
+
int
-pthread_join(pthread_t thread, void ** valueptr)
+pthread_detach (pthread_t tid)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function detaches the given thread.
+ *
+ * PARAMETERS
+ * thread
+ * an instance of a pthread_t
+ *
+ *
+ * DESCRIPTION
+ * This function detaches the given thread. You may
+ * detach the main thread or to detach a joinable thread
+ * (You should have used pthread_attr_t to create the
+ * thread as detached!)
+ * NOTE: detached threads cannot be joined nor canceled;
+ * storage is freed immediately on termination.
+ *
+ * RESULTS
+ * 0 successfully detached the thread,
+ * EINVAL thread is not a joinable thread,
+ * ENOSPC a required resource has been exhausted,
+ * ESRCH no thread could be found for 'thread',
+ *
+ * ------------------------------------------------------
+ */
{
- int detachstate;
+ int result;
- /* First check if we are trying to join to ourselves. */
- if (thread == pthread_self())
+ if (tid == NULL ||
+ tid->detachState == PTHREAD_CREATE_DETACHED)
{
- return EDEADLK;
- }
-
- if (thread != NULL)
- {
- int ret;
-
- /* CRITICAL SECTION */
- pthread_mutex_lock(&_pthread_table_mutex);
-
- /* If the thread is in DETACHED state, then join will return
- immediately. */
-
- if (pthread_attr_getdetachstate(&(thread->attr), &detachstate) != 0
- || detachstate == PTHREAD_CREATE_DETACHED)
- {
- return EINVAL;
- }
-
- thread->join_count++;
-
- pthread_mutex_unlock(&_pthread_table_mutex);
- /* END CRITICAL SECTION */
-
- /* CANCELATION POINT */
- pthread_testcancel();
- /* Wait on the kernel thread object. */
- switch (WaitForSingleObject(thread->win32handle, INFINITE))
- {
- case WAIT_FAILED:
- /* The thread does not exist. */
- return ESRCH;
- case WAIT_OBJECT_0:
- /* The thread has finished. */
- break;
- default:
- /* This should never happen. */
- break;
- }
-
- /* We know the target thread entry still exists at this point
- because we incremented join_count above after checking. The
- thread entry will not be removed until join_count == 0 again,
- ie. when the last waiting join has passed through the
- following critical section. */
-
- /* CRITICAL SECTION */
- pthread_mutex_lock(&_pthread_table_mutex);
-
- /* Collect the value pointer passed to pthread_exit(). If
- another thread detaches our target thread while we're
- waiting, then we report a deadlock as it likely that storage
- pointed to by thread->joinvalueptr has been freed or
- otherwise no longer valid. */
-
- if (pthread_attr_getdetachstate(&(thread->attr), &detachstate) != 0
- || detachstate == PTHREAD_CREATE_DETACHED)
- {
- ret = EDEADLK;
- }
- else
- {
- *valueptr = thread->joinvalueptr;
- ret = 0;
- }
-
- thread->join_count--;
-
- /* If we're the last join to return then we are responsible for
- removing the target thread's table entry. */
- if (thread->join_count == 0)
- {
- ret = _pthread_delete_thread(thread);
- }
+ result = EINVAL;
- pthread_mutex_unlock(&_pthread_table_mutex);
- /* END CRITICAL SECTION */
-
- return ret;
}
+ else
+ {
+ result = 0;
+ tid->detachState = PTHREAD_CREATE_DETACHED;
+ }
+
+ return (result);
- /* Thread not found. */
- return ESRCH;
-}
+} /* pthread_detach */
int
-pthread_detach(pthread_t thread)
+pthread_join (pthread_t thread, void **value_ptr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function waits for 'thread' to terminate and
+ * returns the thread's exit value if 'value_ptr' is not
+ * NULL. This also detaches the thread on successful
+ * completion.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ *
+ * DESCRIPTION
+ * This function waits for 'thread' to terminate and
+ * returns the thread's exit value if 'value_ptr' is not
+ * NULL. This also detaches the thread on successful
+ * completion.
+ * NOTE: detached threads cannot be joined or canceled
+ *
+ * RESULTS
+ * 0 'thread' has completed
+ * EINVAL thread is not a joinable thread,
+ * ESRCH no thread could be found with ID 'thread',
+ * EDEADLK attempt to join thread with self
+ *
+ * ------------------------------------------------------
+ */
{
- int detachstate;
- int ret;
+ int result = 0;
+ pthread_t self;
- /* CRITICAL SECTION */
- pthread_mutex_lock(&_pthread_table_mutex);
+ self = pthread_self ();
- if (thread == NULL)
+ if (pthread_equal (self, thread) == 0)
{
- ret = ESRCH;
+ result = EDEADLK;
+
}
else
{
- /* Check that we can detach this thread. */
- if (pthread_attr_getdetachstate(&(thread->attr), &detachstate) != 0
- || detachstate == PTHREAD_CREATE_DETACHED)
+ DWORD stat;
+
+ stat = WaitForSingleObject (thread->threadH, INFINITE);
+
+ if (stat != WAIT_OBJECT_0 &&
+ !GetExitCodeThread (thread->threadH, (LPDWORD) value_ptr))
{
- ret = EINVAL;
+ result = ESRCH;
}
else
{
- /* This is all we do here - the rest is done either when the
- thread exits or when pthread_join() exits. Once this is
- set it will never be unset. */
- pthread_attr_setdetachstate(&(thread->attr),
- PTHREAD_CREATE_DETACHED);
-
- ret = 0;
+ _pthread_threadDestroy (thread);
}
}
- pthread_mutex_unlock(&_pthread_table_mutex);
- /* END CRITICAL SECTION */
+ return (result);
+
+} /* pthread_join */
+
+/* </JEB> */
- return ret;
-}