diff options
| -rw-r--r-- | ChangeLog | 20 | ||||
| -rw-r--r-- | create.c | 34 | ||||
| -rw-r--r-- | exit.c | 15 | ||||
| -rw-r--r-- | implement.h | 2 | ||||
| -rw-r--r-- | private.c | 1 | ||||
| -rw-r--r-- | sync.c | 2 | 
6 files changed, 61 insertions, 13 deletions
| @@ -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. @@ -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); @@ -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; @@ -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; @@ -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))      { | 
