summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog20
-rw-r--r--create.c34
-rw-r--r--exit.c15
-rw-r--r--implement.h2
-rw-r--r--private.c1
-rw-r--r--sync.c2
6 files changed, 61 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 102ef6f..29b2289 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
Fri Jul 24 03:00:25 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+ * sync.c (pthread_join): Save valueptr arg in joinvalueptr for
+ pthread_exit() to use.
+
+ * private.c (_pthread_new_thread_entry): Initialise joinvalueptr to
+ NULL.
+
+ * create.c (_pthread_start_call): Rewrite to facilitate joins.
+ pthread_exit() will do a longjmp() back to here. Does appropriate
+ cleanup and exit/return from the thread.
+ (pthread_create): _beginthreadex() now passes a pointer to our
+ thread table entry instead of just the call member of that entry.
+
+ * implement.h (_pthread_threads_thread): New member
+ void ** joinvalueptr.
+ (_pthread_call_t): New member jmpbuf env.
+
+ * exit.c (pthread_exit): Major rewrite to handle joins and handing
+ value pointer to joining thread. Uses longjmp() back to
+ _pthread_start_call().
+
* create.c (pthread_create): Ensure values of new attribute members
are copied to the thread attribute object.
diff --git a/create.c b/create.c
index 498f649..e15a98f 100644
--- a/create.c
+++ b/create.c
@@ -12,26 +12,38 @@
#include "implement.h"
unsigned
-_pthread_start_call(void * call)
+_pthread_start_call(void * thisarg)
{
/* We're now in a running thread. Any local variables here are on
this threads private stack so we're safe to leave data in them
until we leave. */
- _pthread_call_t * this;
+ _pthread_threads_thread__t * this = thisarg;
+ _pthread_call_t * call;
unsigned (*func)(void *);
void * arg;
unsigned ret;
+ int from;
- this = (_pthread_call_t *) call;
- func = call->routine;
- arg = call->arg;
+ func = this->call.routine;
+ arg = this->call.arg;
- ret = (*func)(arg);
+ /* FIXME: Should we be using sigsetjmp() here instead. */
+ from = setjmp(this->call.env);
- /* If we get to here then we're returning naturally and haven't
- been cancelled. We need to cleanup and remove the thread
- from the threads table. */
- _pthread_vacuum();
+ if (from == 0)
+ {
+ ret = (*func)(arg);
+
+ _pthread_vacuum();
+ }
+ else
+ {
+ /* func() called pthread_exit() which called longjmp(). */
+ _pthread_vacuum();
+
+ /* Never returns. */
+ _endthreadex(0);
+ }
return ret;
}
@@ -75,7 +87,7 @@ pthread_create(pthread_t *thread,
handle = (HANDLE) _beginthreadex(security,
attr_copy->stacksize,
_pthread_start_call,
- (void *) &(this->call),
+ (void *) this,
flags,
&threadID);
diff --git a/exit.c b/exit.c
index a9c352c..1e07ccd 100644
--- a/exit.c
+++ b/exit.c
@@ -36,6 +36,17 @@ _pthread_vacuum(void)
void
pthread_exit(void * value)
{
- _pthread_vacuum();
- _endthreadex((DWORD) value);
+ _pthread_threads_thread_t * this;
+
+ this = _PTHREAD_THIS;
+
+ if (this->joinvalueptr != NULL)
+ {
+ *(this->joinvalueptr) = value;
+ }
+
+ /* FIXME: More to do here. IE, if pthread_detach() was called
+ and value != NULL, do we free(value)? */
+
+ longjmp(this->call.env, 1);
}
diff --git a/implement.h b/implement.h
index 14fbdbb..b72e273 100644
--- a/implement.h
+++ b/implement.h
@@ -37,6 +37,7 @@ struct _pthread_handler_node {
typedef struct {
unsigned (*routine)(void *);
void * arg;
+ jmpbuf env;
} _pthread_call_t;
#define _PTHREAD_THIS (_pthread_find_thread_entry(pthread_this()))
@@ -51,6 +52,7 @@ struct _pthread_threads_thread {
pthread_t thread;
pthread_attr_t attr;
_pthread_call_t call;
+ void ** joinvalueptr;
_pthread_handler_node_t * cleanupstack;
_pthread_handler_node_t * destructorstack;
_pthread_handler_node_t * forkpreparestack;
diff --git a/private.c b/private.c
index e65e95e..dc7e111 100644
--- a/private.c
+++ b/private.c
@@ -59,6 +59,7 @@ _pthread_new_thread_entry(pthread_t thread, _pthread_threads_thread_t * entry)
{
this->thread = thread;
pthread_attr_init(&(this->attr));
+ this->joinvalueptr = NULL;
this->cleanupstack = NULL;
this->destructorstack = NULL;
this->forkpreparestack = NULL;
diff --git a/sync.c b/sync.c
index c3bd438..e8262a6 100644
--- a/sync.c
+++ b/sync.c
@@ -37,6 +37,8 @@ pthread_join(pthread_t thread, void ** valueptr)
return EINVAL;
}
+ this->joinvalueptr = valueptr;
+
/* Wait on the kernel thread object. */
switch (WaitForSingleObject(thread, INFINITE))
{