diff options
| -rw-r--r-- | ChangeLog | 49 | ||||
| -rw-r--r-- | Makefile.in | 6 | ||||
| -rw-r--r-- | attr.c | 3 | ||||
| -rw-r--r-- | cancel.c | 17 | ||||
| -rw-r--r-- | cleanup.c | 20 | ||||
| -rw-r--r-- | condvar.c | 2 | ||||
| -rw-r--r-- | create.c | 2 | ||||
| -rw-r--r-- | dll.c | 4 | ||||
| -rw-r--r-- | exit.c | 2 | ||||
| -rw-r--r-- | global.c | 6 | ||||
| -rw-r--r-- | implement.h | 16 | ||||
| -rw-r--r-- | misc.c | 23 | ||||
| -rw-r--r-- | mutex.c | 2 | ||||
| -rw-r--r-- | private.c | 62 | ||||
| -rw-r--r-- | pthread.def | 17 | ||||
| -rw-r--r-- | pthread.h | 152 | ||||
| -rw-r--r-- | semaphore.c | 2 | ||||
| -rw-r--r-- | tsd.c | 2 | 
18 files changed, 304 insertions, 83 deletions
| @@ -1,10 +1,59 @@ +Sun Jan 24 01:34:52 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au> + +	* semaphore.c (sem_wait): Remove second arg to  +	pthreadCancelableWait() call. +  Sat Jan 23 17:36:40 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au> +	* pthread.def: Add new functions to export list. +  	* pthread.h (PTHREAD_MUTEX_AUTO_CS_NP): New.  	(PTHREAD_MUTEX_FORCE_CS_NP): New.  	* README: Updated. +Fri Jan 22 14:31:59 1999  Ross Johnson  <rpj@swan.canberra.edu.au> + +	* Makefile.in (CFLAGS): Remove -fhandle-exceptions. Not needed +	with egcs. Add -g for debugging. + +	* create.c (pthread_create): Replace __stdcall with PT_STDCALL +	macro. This is a hack and must be fixed. + +	* misc.c (CancelableWait): Remove redundant statement. + +	* mutex.c (pthread_mutexattr_init): Cast calloc return value. + +	* misc.c (CancelableWait): Add cast. +	(pthread_self): Add cast. + +	* exit.c (pthread_exit): Add cast. + +	* condvar.c (pthread_condattr_init): Cast calloc return value. + +	* cleanup.c: Reorganise conditional compilation. + +	* attr.c (pthread_attr_init): Remove unused 'result'. +	Cast malloc return value. + +	* private.c (_pthread_callUserDestroyRoutines): Redo conditional +	compilation. + +	* misc.c (CancelableWait): C++ version uses 'throw'. + +	* cancel.c (pthread_testcancel): Ditto. + +	* implement.h (class pthread_exception): Define for C++. + +	* pthread.h: Fix C, C++, and Win32 SEH condition compilation +	mayhem around pthread_cleanup_* defines. C++ version now uses John +	Bossom's cleanup handlers. +	(pthread_attr_t): Make 'valid' unsigned. +	Define '_timeb' as 'timeb' for Ming32. +	Define PT_STDCALL as nothing for Mingw32. May be temporary. + +	* cancel.c (pthread_testcancel): Cast return value. +  Wed Jan 20 09:31:28 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>  	* pthread.h (pthread_mutexattr_t): Changed to a pointer. diff --git a/Makefile.in b/Makefile.in index 89c72fe..a5dea55 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,6 +1,10 @@  CC	= g++ -CFLAGS	= -fhandle-exceptions -I. -DHAVE_CONFIG_H -Wall +# Mingw32 +CFLAGS	= -g -I. -DHAVE_CONFIG_H -Wall + +# Cygwin G++ +#CFLAGS	= -fhandle-exceptions -I. -DHAVE_CONFIG_H -Wall  OBJS	= attr.o cancel.o cleanup.o condvar.o create.o dll.o \  	  exit.o fork.o global.o misc.o mutex.o private.o sched.o \ @@ -292,7 +292,6 @@ pthread_attr_init(pthread_attr_t *attr)        */  {    pthread_attr_t attr_result; -  int result = 0;    if (attr == NULL)      { @@ -300,7 +299,7 @@ pthread_attr_init(pthread_attr_t *attr)        return EINVAL;      } -  attr_result = malloc (sizeof (*attr_result)); +  attr_result = (pthread_attr_t) malloc (sizeof (*attr_result));    if (attr_result == NULL)      { @@ -163,7 +163,8 @@ pthread_testcancel (void)  {    pthread_t self; -  if ((self = pthread_getspecific (_pthread_selfThreadKey)) != NULL) +  if ((self = (pthread_t) pthread_getspecific (_pthread_selfThreadKey))  +      != NULL)      {        if (self->cancelState == PTHREAD_CANCEL_ENABLE) @@ -175,6 +176,9 @@ pthread_testcancel (void)  	      /*  	       * Canceling!  	       */ + +#ifdef _MSC_VER +  	      DWORD exceptionInformation[3];  	      exceptionInformation[0] = (DWORD) (0); @@ -185,6 +189,17 @@ pthread_testcancel (void)  			       0,  			       3,  			       exceptionInformation); + +#else /* _MSC_VER */ + +#ifdef __cplusplus + +	      throw pthread_exception; + +#endif /* __cplusplus */ + +#endif /* _MSC_VER */ +  	    }  	}      } @@ -44,14 +44,14 @@ _pthread_pop_cleanup (int execute)  {    _pthread_cleanup_t *cleanup; -  cleanup = pthread_getspecific (_pthread_cleanupKey); +  cleanup = (_pthread_cleanup_t *) pthread_getspecific (_pthread_cleanupKey);    if (cleanup != NULL)      {        if (execute && (cleanup->routine != NULL))          { -#ifdef _WIN32 +#ifdef _MSC_VER            __try  	    { @@ -69,7 +69,7 @@ _pthread_pop_cleanup (int execute)  	       */  	    } -#else /* _WIN32 */ +#else /* _MSC_VER */  #ifdef __cplusplus @@ -91,7 +91,7 @@ _pthread_pop_cleanup (int execute)  #else /* __cplusplus */ -#if defined(__CYGWIN__) || defined(__CYGWIN32__) +#if defined(__GNUC__)  #warning Compile __FILE__ as C++ or thread cancellation will not work properly.  #endif @@ -102,15 +102,16 @@ _pthread_pop_cleanup (int execute)  #endif /* __cplusplus */ -#endif /* _WIN32 */ +#endif /* _MSC_VER */          } -#if !defined(_WIN32) && !defined(__cplusplus) +#if !defined(_MSC_VER) && !defined(__cplusplus) -      pthread_setspecific (_pthread_cleanupKey, cleanup->prev); +      pthread_setspecific (_pthread_cleanupKey, (void *) cleanup->prev);  #endif +      }    return (cleanup); @@ -165,9 +166,9 @@ _pthread_push_cleanup (_pthread_cleanup_t * cleanup,    cleanup->routine = routine;    cleanup->arg = arg; -#if !defined(_WIN32) && !defined(__cplusplus) +#if !defined(_MSC_VER) && !defined(__cplusplus) -  cleanup->prev = pthread_getspecific (_pthread_cleanupKey); +  cleanup->prev = (_pthread_cleanup_t *) pthread_getspecific (_pthread_cleanupKey);  #endif @@ -177,4 +178,3 @@ _pthread_push_cleanup (_pthread_cleanup_t * cleanup,  /* </JEB> */ - @@ -48,7 +48,7 @@ pthread_condattr_init (pthread_condattr_t * attr)    pthread_condattr_t attr_result;    int result = 0; -  attr_result = calloc (1, sizeof (*attr_result)); +  attr_result = (pthread_condattr_t) calloc (1, sizeof (*attr_result));    if (attr_result == NULL)      { @@ -108,7 +108,7 @@ pthread_create (pthread_t * tid,      _beginthreadex (  		     (void *) NULL,	/* No security info             */  		     (unsigned) stackSize,	/* default stack size   */ -		     (unsigned (__stdcall *) (void *)) _pthread_threadStart, +		     (unsigned (PT_STDCALL *) (void *)) _pthread_threadStart,  		     parms,  		     (unsigned) run ? 0 : CREATE_SUSPENDED,  		     (unsigned *) &(thread->thread)); @@ -50,8 +50,8 @@ DllMain (        /* Load KERNEL32 and try to get address of TryEnterCriticalSection */        _pthread_h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL"));        _pthread_try_enter_critical_section = -	(void *) GetProcAddress(_pthread_h_kernel32, -				"TryEnterCriticalSection"); +	GetProcAddress(_pthread_h_kernel32, +		       (LPCSTR) "TryEnterCriticalSection");        break;      case DLL_THREAD_ATTACH: @@ -37,7 +37,7 @@ pthread_exit (void *value_ptr)        * ------------------------------------------------------        */  { -  _pthread_callUserDestroyRoutines(pthread_getspecific(_pthread_selfThreadKey)); +  _pthread_callUserDestroyRoutines((pthread_t) pthread_getspecific(_pthread_selfThreadKey));    _endthreadex ((unsigned) value_ptr); @@ -14,6 +14,12 @@ int _pthread_processInitialized = FALSE;  pthread_key_t _pthread_selfThreadKey = NULL;  pthread_key_t _pthread_cleanupKey = NULL; +#if !defined(_MSC_VER) && defined(__cplusplus) + +Pthread_exception pthread_exception; + +#endif +  /*   * Global lock for testing internal state of PTHREAD_MUTEX_INITIALIZER   * created mutexes. diff --git a/implement.h b/implement.h index f897033..75ca6f6 100644 --- a/implement.h +++ b/implement.h @@ -84,6 +84,7 @@ struct ThreadKeyAssoc {  }; +#ifdef _MSC_VER  /*   * --------------------------------------------------------------   * MAKE_SOFTWARE_EXCEPTION @@ -127,6 +128,21 @@ struct ThreadKeyAssoc {  #define PTHREAD_SERVICES_FACILITY		0xBAD  #define PTHREAD_SERVICES_ERROR			0xDEED +#else + +#ifdef __cplusplus + +class Pthread_exception {}; + +extern Pthread_exception pthread_exception; + +#else /* __cplusplus */ + +#warning File __FILE__, Line __LINE__: Cancellation not supported under C. + +#endif /* __cplusplus */ + +#endif /* _MSC_VER */  /* Function pointer to TryEnterCriticalSection if it exists; otherwise NULL */  extern BOOL (WINAPI *_pthread_try_enter_critical_section)(LPCRITICAL_SECTION); @@ -71,7 +71,8 @@ pthread_self (void)     * need to ensure there always is a self     */ -  if ((self = pthread_getspecific (_pthread_selfThreadKey)) == NULL) +  if ((self = (pthread_t) pthread_getspecific (_pthread_selfThreadKey))  +      == NULL)      {        /*         * Need to create an implicit 'self' for the currently @@ -153,7 +154,8 @@ CancelableWait (HANDLE waitHandle, DWORD timeout)    handles[0] = waitHandle; -  if ((self = pthread_getspecific (_pthread_selfThreadKey)) != NULL) +  if ((self = (pthread_t) pthread_getspecific (_pthread_selfThreadKey))  +      != NULL)      {        /*         * Get cancelEvent handle @@ -219,6 +221,9 @@ CancelableWait (HANDLE waitHandle, DWORD timeout)                /*                 * Thread started with pthread_create                 */ + +#ifdef _MSC_VER +                DWORD exceptionInformation[3];                exceptionInformation[0] = (DWORD) (0); @@ -229,10 +234,20 @@ CancelableWait (HANDLE waitHandle, DWORD timeout)                                 0,                                 3,                                 exceptionInformation); -            } +#else /* _MSC_VER */ + +#ifdef __cplusplus + +	      throw pthread_exception; + +#endif /* __cplusplus */ + +#endif /* _MSC_VER */ +            } -          ((void *) -1); +	  /* Should never get to here. */ +	  result = EINVAL;            break;          default: @@ -223,7 +223,7 @@ pthread_mutexattr_init (pthread_mutexattr_t * attr)    pthread_mutexattr_t attr_result;    int result = 0; -  attr_result = calloc (1, sizeof (*attr_result)); +  attr_result = (pthread_mutexattr_t) calloc (1, sizeof (*attr_result));    result = (attr_result == NULL)      ? ENOMEM @@ -6,11 +6,11 @@   * the implementation and may be used throughout it.   */ +#include <sys/timeb.h> +  #include "pthread.h"  #include "implement.h" -#include <sys/timeb.h> -  /*   * Code contributed by John E. Bossom <JEB>.   */ @@ -133,7 +133,7 @@ _pthread_threadStart (ThreadParms * threadParms)    pthread_setspecific (_pthread_selfThreadKey, tid); -#ifdef _WIN32 +#ifdef _MSC_VER    __try    { @@ -152,7 +152,7 @@ _pthread_threadStart (ThreadParms * threadParms)      status = -1;    } -#else /* _WIN32 */ +#else /* _MSC_VER */  #ifdef __cplusplus @@ -164,19 +164,26 @@ _pthread_threadStart (ThreadParms * threadParms)      (*start) (arg);      status = 0;    } +  catch (Pthread_exception) +    { +      /* +       * Thread was cancelled. +       */ +      status = -1; +    }    catch (...) -  { -    /* -     * A system unexpected exception had occurred running the user's -     * routine. We get control back within this block. -     */ -    status = -1; -  } +    { +      /* +       * A system unexpected exception had occurred running the user's +       * routine. We get control back within this block. +       */ +      status = -1; +    }  #else /* __cplusplus */  #if defined(__CYGWIN__) || defined(__CYGWIN32__) -#warning Compile __FILE__ as C++ or thread cancellation will not work properly. +#warning File __FILE__, Line __LINE__: Cancelation not supported under C.  #endif    /* @@ -407,6 +414,8 @@ _pthread_callUserDestroyRoutines (pthread_t thread)  		  if (value != NULL && k->destructor != NULL)  		    { +#ifdef _MSC_VER +  		      __try  		      {  			/* @@ -422,6 +431,35 @@ _pthread_callUserDestroyRoutines (pthread_t thread)  			 * We get control back within this block.  			 */  		      } + +#else  /* _MSC_VER */ +#ifdef __cplusplus + +		      try +		      { +			/* +			 * Run the caller's cleanup routine. +			 */ +			(*(k->destructor)) (value); +		      } +		      catch (...) +		      { +			/* +			 * A system unexpected exception had occurred +			 * running the user's destructor. +			 * We get control back within this block. +			 */ +		      } + +#else  /* __cplusplus */ + +			/* +			 * Run the caller's cleanup routine. +			 */ +			(*(k->destructor)) (value); + +#endif /* __cplusplus */ +#endif /* _MSC_VER */  		    }  		} diff --git a/pthread.def b/pthread.def index 3f68e5c..d8f950f 100644 --- a/pthread.def +++ b/pthread.def @@ -1,5 +1,5 @@  ; pthread.def -; Last updated: $Date: 1999/01/12 14:48:59 $ +; Last updated: $Date: 1999/01/23 06:59:02 $  ; Currently unimplemented functions are commented out. @@ -49,11 +49,11 @@ pthread_key_delete  pthread_mutexattr_destroy  ;pthread_mutexattr_getprioceiling  ;pthread_mutexattr_getprotocol -;phtread_mutexattr_getpshared +pthread_mutexattr_getpshared  pthread_mutexattr_init  ;pthread_mutexattr_setprioceiling  ;pthread_mutexattr_setprotocol -;pthread_mutexattr_setpshared +pthread_mutexattr_setpshared  pthread_mutexattr_destroy  pthread_mutex_init  pthread_mutex_destroy @@ -68,3 +68,14 @@ pthread_setschedparam  pthread_setspecific  ;pthread_sigmask  pthread_testcancel +; +; Non-portable but useful +; +pthread_mutexattr_setforcecs_np +pthreadCancelableWait +pthreadCancelableTimedWait +; +; Needed if !defined(_MSC_VER) && !defined(__cplusplus) +; +_pthread_push_cleanup +_pthread_pop_cleanup @@ -205,6 +205,8 @@  #include <signal.h>  #endif /* HAVE_SIGNAL_H */ +#include <malloc.h> +  #ifndef HAVE_STRUCT_TIMESPEC  struct timespec {  	int tv_sec; @@ -248,8 +250,22 @@ struct timespec {  #include <semaphore.h> -/* #include <sched.h> /**/ +/* #include <sched.h> */ + +#ifdef __MINGW32__ +#define PT_STDCALL +#else +#define PT_STDCALL __stdcall +#endif +/*  + * This should perhaps be in autoconf or  + * possibly fixed in Mingw32 to + * correspond to the Windows headers. + */ +#ifdef __MINGW32__ +#define _timeb timeb +#endif  #ifdef __cplusplus  extern "C" @@ -562,7 +578,7 @@ struct pthread_t_ {  #define _PTHREAD_ATTR_VALID 0xC4C0FFEE  struct pthread_attr_t_ { -  long valid; +  unsigned long valid;    void *stackaddr;    size_t stacksize;    int detachstate; @@ -647,27 +663,24 @@ struct pthread_once_t_ {  /* There are three implementations of cancel cleanup.   * + *   WIN32 SEH   *   C - *   C++ (as per Cygwin32 or Mingw32) - *   WIN32 SEH or C++ + *   C++   */ -  typedef struct _pthread_cleanup_t _pthread_cleanup_t; - -  struct _pthread_cleanup_t -    { -      void (*routine) (void *); -      void *arg; -#if !defined(_WIN32) && !defined(__cplusplus) -      _pthread_cleanup_t *prev; -#endif -    }; - -#ifdef _WIN32 +#ifdef _MSC_VER  	/*  	 * WIN32 SEH version of cancel cleanup.  	 */ +  typedef struct _pthread_cleanup_t _pthread_cleanup_t; + +  struct _pthread_cleanup_t +  { +    void (*routine) (void *); +    void *arg; +  }; +  #define pthread_cleanup_push( _rout, _arg ) \  	{ \  	    _pthread_cleanup_t	_cleanup; \ @@ -688,7 +701,7 @@ struct pthread_once_t_ {  		} \  	} -#else /* _WIN32 */ +#else /* _MSC_VER */  #ifndef __cplusplus @@ -696,6 +709,15 @@ struct pthread_once_t_ {  	 * C implementation of PThreads cancel cleanup  	 */ +  typedef struct _pthread_cleanup_t _pthread_cleanup_t; + +  struct _pthread_cleanup_t +  { +    void (*routine) (void *); +    void *arg; +    _pthread_cleanup_t *prev; +  }; +  #define pthread_cleanup_push( _rout, _arg ) \  	{ \  	    _pthread_cleanup_t	_cleanup; \ @@ -709,39 +731,85 @@ struct pthread_once_t_ {  #else /* !__cplusplus */  	/* -	 * C++ (ie. Cygwin32 or Mingw32) version of cancel cleanup. +	 * C++ version of cancel cleanup. +	 * - John E. Bossom.  	 *  	 * Emulate try-finally behaviour.  	 */ +	class PThreadCleanup { +	  /* +	   * PThreadCleanup +	   * +	   * Purpose +	   *      This class is a C++ helper class that is +	   *      used to implement pthread_cleanup_push/ +	   *      pthread_cleanup_pop. +	   *      The destructor of this class automatically +	   *      pops the pushed cleanup routine regardless +	   *      of how the code exits the scope +	   *      (i.e. such as by an exception) +	   */ +	  void            (*cleanUpRout)( void * ); +	  void    *       obj; +	  int             executeIt; + +	public: +	  PThreadCleanup() : +	    cleanUpRout( NULL ), +	    obj( NULL ), +	    executeIt( 0 ) +	    /* +	     * No cleanup performed +	     */ +	    { +	    } + +	  PThreadCleanup( +			 void            (*routine)( void * ), +			 void    *       arg ) : +	    cleanUpRout( routine ), +	    obj( arg ), +	    executeIt( 1 ) +	    /* +             * Registers a cleanup routine for 'arg' +             */ +	    { +	    } + +	  ~PThreadCleanup() +	    { +	      if ( executeIt && cleanUpRout != NULL ) +		{ +		  (*cleanUpRout)( obj ); +		} +	    } + +	  void execute( int exec ) +	    { +	      executeIt = exec; +	    } +	}; + +	/* +	 * C++ implementation of PThreads cancel cleanup; +	 * This implementation takes advantage of a helper +	 * class who's destructor automatically calls the +	 * cleanup routine if we exit our scope weirdly +	 */  #define pthread_cleanup_push( _rout, _arg ) \ -	{ \ -	    _pthread_cleanup_t	_cleanup; \ -	    \ -            _cleanup.routine	= (_rout); \ -	    _cleanup.arg	= (_arg); \ -	    try \ -	      { \ +        { \ +	    PThreadCleanup  cleanup((void (PT_STDCALL *)(void *))(_rout), \ +				    (void *) (_arg) );  #define pthread_cleanup_pop( _execute ) \ -	      } \ -	    catch(...) \ -	      { \ -		  (*(_cleanup.routine))( _cleanup.arg ); \ -		  \ -		  throw; \ -	      } \ -              \ -	      if (_execute) \ -		{ \ -		    (*(_cleanup.routine))( _cleanup.arg ); \ -		} \ -      	} - -#endif /* _WIN32 */ +	    cleanup.execute( _execute ); \ +	}  #endif /* !__cplusplus */ +#endif /* _MSC_VER */ +  /*   * ===============   * =============== @@ -797,7 +865,7 @@ pthread_t pthread_self (void);  int pthread_cancel (pthread_t thread); -#if !defined(__cplusplus) && !defined(_WIN32) +#if !defined(__cplusplus) && !defined(_MSC_VER)  _pthread_cleanup_t *_pthread_pop_cleanup (int execute); @@ -805,7 +873,7 @@ void _pthread_push_cleanup (_pthread_cleanup_t * cleanup,  			   void (*routine) (void *),  			   void *arg); -#endif /* !__cplusplus && ! _WIN32 */ +#endif /* !__cplusplus && ! _MSC_VER */  int pthread_setcancelstate (int state,  			    int *oldstate); diff --git a/semaphore.c b/semaphore.c index 9200cdd..9645379 100644 --- a/semaphore.c +++ b/semaphore.c @@ -212,7 +212,7 @@ sem_wait (sem_t * sem)    return ((sem == NULL)  	  ? EINVAL -	  : pthreadCancelableWait (*sem, INFINITE) +	  : pthreadCancelableWait (*sem)      );  }				/* sem_wait */ @@ -215,7 +215,7 @@ pthread_setspecific (pthread_key_t key, const void *value)         * Resolve catch-22 of registering thread with threadSelf         * key         */ -      self = pthread_getspecific (_pthread_selfThreadKey); +      self = (pthread_t) pthread_getspecific (_pthread_selfThreadKey);        if (self == NULL)          {            self = (pthread_t) value; | 
