diff options
| -rw-r--r-- | ChangeLog | 39 | ||||
| -rw-r--r-- | GNUmakefile | 13 | ||||
| -rw-r--r-- | Makefile | 20 | ||||
| -rw-r--r-- | config.h | 20 | ||||
| -rw-r--r-- | config.h.in | 20 | ||||
| -rw-r--r-- | implement.h | 1 | ||||
| -rw-r--r-- | mutex.c | 4 | ||||
| -rw-r--r-- | private.c | 57 | ||||
| -rw-r--r-- | pthread.h | 6 | ||||
| -rw-r--r-- | semaphore.h | 23 | ||||
| -rw-r--r-- | sync.c | 4 | ||||
| -rw-r--r-- | tests/ChangeLog | 17 | ||||
| -rw-r--r-- | tests/GNUmakefile | 5 | ||||
| -rw-r--r-- | tests/Makefile | 3 | ||||
| -rw-r--r-- | tests/condvar8.c | 8 | ||||
| -rw-r--r-- | tests/exception3.c | 72 | ||||
| -rw-r--r-- | tests/eyal1.c | 12 | ||||
| -rw-r--r-- | tests/mutex4.c | 34 | ||||
| -rw-r--r-- | tsd.c | 2 | 
19 files changed, 228 insertions, 132 deletions
| @@ -1,5 +1,44 @@ +2000-12-29  Ross Johnson  <rpj@special.ise.canberra.edu.au> + +	* Makefile: Back-out "for" loops which don't work. + +	* GNUmakefile: Remove the fake.a target; add the "realclean" +	target; don't remove built libs under the "clean" target. + +	* config.h: Add a guard against multiple inclusion. + +	* semaphore.h: Add some defines from config.h to make +	semaphore.h independent of config.h when building apps. + +	* pthread.h (_errno): Back-out previous fix until we know how to +	fix it properly. + +	* implement.h (lockCount): Add missing element to pthread_mutex_t_. + +	* sync.c (pthread_join): Spelling fix in comment. + +	* private.c (ptw32_threadStart): Reset original termination +	function (C++). +	(ptw32_threadStart): Cleanup detached threads early in case +	the library is statically linked. +	(ptw32_callUserDestroyRoutines): Remove [SEH] __try block from +	destructor call so that unhandled exceptions will be passed through +	to the 	system; call terminate() from [C++] try block for the same +	reason. + +	* tsd.c (pthread_getspecific): Add comment. + +	* mutex.c (pthread_mutex_init): Initialise new elements in +	pthread_mutex_t. +	(pthread_mutex_unlock): Invert "pthread_equal()" test. +  2000-12-28  Ross Johnson  <rpj@special.ise.canberra.edu.au> +	* semaphore.c (mode_t): Use ifndef HAVE_MODE_T to include definition. + +	* config.h.in (HAVE_MODE_T): Added. +	(_UWIN): Start adding defines for the UWIN package. +  	* private.c (ptw32_threadStart): Unhandled exceptions are  	now passed through to the system to deal with. This is consistent  	with normal Windows behaviour. C++ applications may use diff --git a/GNUmakefile b/GNUmakefile index 9ad6119..a7d13b3 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -52,12 +52,6 @@ LIBS	= libpthreadw32.a  all:	$(LIBS) -fake.a: -	@ $(CP) pthreadVCE.dll $(DLL) -	dlltool --def pthread.def --output-lib $@ --dllname $(DLL) -	@-$(RM) $(LIBS) -	$(MV) fake.a $(LIBS) -  $(LIBS): $(DLL)  	dlltool --def pthread.def --output-lib $@ --dllname $(DLL) @@ -78,10 +72,11 @@ $(DLL): $(OBJS)  clean:  	-$(RM) *~ -	-$(RM) $(LIBS)  	-$(RM) *.o   	-$(RM) *.exe -	-$(RM) $(DLL)   	-$(RM) $(DLL:.dll=.base)  	-$(RM) $(DLL:.dll=.exp) -	-$(RM) fake.a + +realclean: +	-$(RM) $(LIBS) +	-$(RM) $(DLL)  @@ -53,21 +53,15 @@ VSE:  	@ nmake /nologo EHFLAGS="$(VSEFLAGS)" pthreadVSE.dll
  realclean: clean
 -	@ for %%ext in (dll lib) do \
 -		if exist *.%%ext del *.%%ext
 -
 -#	del *.dll
 -#	del *.lib
 +	if exist *.dll del *.dll
 +	if exit *.lib del *.lib
  clean:
 -	@ for %%ext in (obj ilk pdb exp o) do \
 -		if exist *.%%ext del *.%%ext
 -
 -#	if exist *.obj del *.obj
 -#	if exist *.ilk del *.ilk
 -#	if exist *.pdb del *.pdb
 -#	if exist *.exp del *.exp
 -#	if exist *.o del *.o
 +	if exist *.obj del *.obj
 +	if exist *.ilk del *.ilk
 +	if exist *.pdb del *.pdb
 +	if exist *.exp del *.exp
 +	if exist *.o del *.o
  install: $(DLLS)
 @@ -1,5 +1,8 @@  /* config.h.in.  Generated automatically from configure.in by autoheader.  */ +#ifndef PTW32_CONFIG_H +#define PTW32_CONFIG_H +  /* Do we know about the C type sigset_t? */  #undef HAVE_SIGSET_T @@ -27,6 +30,12 @@  /* Define if you need to convert string parameters to unicode. (eg. WinCE)  */  #undef NEED_UNICODE_CONSTS +/* Do we know about type mode_t? */ +#undef HAVE_MODE_T + +/* Define if you have the timespec struct */ +#undef HAVE_STRUCT_TIMESPEC +  /*    * Target specific groups    */ @@ -39,3 +48,14 @@  #define NEED_SEM  #define NEED_UNICODE_CONSTS  #endif + +#ifdef _UWIN +#define HAVE_MODE_T +#define HAVE_STRUCT_TIMESPEC +#endif + +#ifdef __MINGW32__ +#define HAVE_MODE_T +#endif + +#endif
\ No newline at end of file diff --git a/config.h.in b/config.h.in index acea758..75e0338 100644 --- a/config.h.in +++ b/config.h.in @@ -1,5 +1,8 @@  /* config.h.in.  Generated automatically from configure.in by autoheader.  */ +#ifndef PTW32_CONFIG_H +#define PTW32_CONFIG_H +  /* Do we know about the C type sigset_t? */  #undef HAVE_SIGSET_T @@ -27,6 +30,12 @@  /* Define if you need to convert string parameters to unicode. (eg. WinCE)  */  #undef NEED_UNICODE_CONSTS +/* Do we know about type mode_t? */ +#undef HAVE_MODE_T + +/* Define if you have the timespec struct */ +#undef HAVE_STRUCT_TIMESPEC +  /*    * Target specific groups    */ @@ -39,3 +48,14 @@  #define NEED_SEM  #define NEED_UNICODE_CONSTS  #endif + +#ifdef _UWIN +#define HAVE_MODE_T +#define HAVE_STRUCT_TIMESPEC +#endif + +#ifdef __MINGW32__ +#define HAVE_MODE_T +#endif + +#endif
\ No newline at end of file diff --git a/implement.h b/implement.h index 9c74bb4..c6f535e 100644 --- a/implement.h +++ b/implement.h @@ -124,6 +124,7 @@ struct pthread_attr_t_ {  struct pthread_mutex_t_ {    HANDLE mutex;    CRITICAL_SECTION cs; +  int lockCount;    pthread_t ownerThread;  }; @@ -105,6 +105,8 @@ pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)      }    mx->mutex = 0; +  mx->lockCount = 0; +  mx->ownerThread = NULL;    if (attr != NULL        && *attr != NULL @@ -586,7 +588,7 @@ pthread_mutex_unlock(pthread_mutex_t *mutex)      {        pthread_t self = pthread_self(); -      if (pthread_equal(mx->ownerThread, self) == 0) +      if (pthread_equal(mx->ownerThread, self))  	{  	  int oldCount = mx->lockCount;  	  pthread_t oldOwner = mx->ownerThread; @@ -240,7 +240,7 @@ ptw32_threadStart (ThreadParms * threadParms)    void *(*start) (void *);    void *arg; -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__cplusplus)    DWORD ei[] = {0,0,0};  #endif @@ -354,6 +354,7 @@ ptw32_threadStart (ThreadParms * threadParms)         */        status = self->exitStatus = PTHREAD_CANCELED;        (void) pthread_mutex_destroy(&self->cancelLock); +      (void) set_terminate(ptw32_oldTerminate);        ptw32_callUserDestroyRoutines(self);        throw; @@ -362,6 +363,8 @@ ptw32_threadStart (ThreadParms * threadParms)         */      } +  (void) set_terminate(ptw32_oldTerminate); +  #else /* __cplusplus */    /* @@ -375,7 +378,32 @@ ptw32_threadStart (ThreadParms * threadParms)  #endif /* _MSC_VER */    (void) pthread_mutex_destroy(&self->cancelLock); -  ptw32_callUserDestroyRoutines(self); + +#if 1 +  if (self->detachState == PTHREAD_CREATE_DETACHED) +    { +      /* +       * We need to cleanup the pthread now in case we have +       * been statically linked, in which case the cleanup +       * in dllMain won't get done. Joinable threads will +       * be cleaned up by pthread_join(). +       * +       * Note that implicitly created pthreads (those created +       * for Win32 threads which have called pthreads routines) +       * must be cleaned up explicitly by the application  +       * (by calling pthread_win32_thread_detach_np()) if +       * this library has been statically linked. For the dll, +       * dllMain will do the cleanup automatically. +       */ +      (void) pthread_win32_thread_detach_np (); +    } +  else +    { +      ptw32_callUserDestroyRoutines (self); +    } +#else +  ptw32_callUserDestroyRoutines (self); +#endif  #if ! defined (__MINGW32__) || defined (__MSVCRT__)    _endthreadex ((unsigned) status); @@ -611,21 +639,15 @@ ptw32_callUserDestroyRoutines (pthread_t thread)  #if defined(_MSC_VER) && !defined(__cplusplus) -		      __try -		      {  			/*  			 * Run the caller's cleanup routine. +			 * +			 * If an exception occurs we let the system handle it +			 * as an unhandled exception. Since we are leaving the +			 * thread we should not get any internal pthreads +			 * exceptions.  			 */  			(*(k->destructor)) (value); -		      } -		      __except (EXCEPTION_EXECUTE_HANDLER) -		      { -			/* -			 * A system unexpected exception had occurred -			 * running the user's destructor. -			 * We get control back within this block. -			 */ -		      }  #else  /* _MSC_VER && !__cplusplus */  #ifdef __cplusplus @@ -640,10 +662,15 @@ ptw32_callUserDestroyRoutines (pthread_t thread)  		      catch (...)  		      {  			/* -			 * A system unexpected exception had occurred +			 * A system unexpected exception has occurred  			 * running the user's destructor. -			 * We get control back within this block. +			 * We get control back within this block in case +			 * the application has set up it's own terminate +			 * handler. Since we are leaving the thread we +			 * should not get any internal pthreads +			 * exceptions.  			 */ +			terminate();  		      }  #else  /* __cplusplus */ @@ -941,6 +941,11 @@ int pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout);  /*   * Thread-Safe C Runtime Library Mappings.   */ +#if 1 +#if (! defined(NEED_ERRNO)) || (! defined( _REENTRANT ) && (! defined( _MT ) || ! defined( _MD ))) +int * _errno( void ); +#endif +#else  #if (! defined(NEED_ERRNO)) || (! defined( _REENTRANT ) && (! defined( _MT ) || ! defined( _MD )))  #if defined(PTW32_BUILD)  __declspec( dllexport ) int * _errno( void ); @@ -948,6 +953,7 @@ __declspec( dllexport ) int * _errno( void );  int * _errno( void );  #endif  #endif +#endif  /*   * WIN32 C runtime library had been made thread-safe diff --git a/semaphore.h b/semaphore.h index 8af8be8..bc66e35 100644 --- a/semaphore.h +++ b/semaphore.h @@ -28,7 +28,26 @@  #if !defined( SEMAPHORE_H )  #define SEMAPHORE_H -#ifdef NEED_ERRNO +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +#  if defined(WINCE) +#    define NEED_ERRNO +#    define NEED_SEM +#  endif +#  if defined(_UWIN) || defined(__MINGW32__) +#    define HAVE_MODE_T +#  endif +#endif + +/* + * + */ + +#ifdef NEED_SEM  #include "need_errno.h"  #else  #include <errno.h> @@ -41,7 +60,7 @@ extern "C"  {  #endif                          /* __cplusplus */ -#if defined(_MSC_VER) +#ifndef HAVE_MODE_T  typedef unsigned int mode_t;  #endif @@ -131,10 +131,10 @@ pthread_join (pthread_t thread, void **value_ptr)      {        /*         * Pthread_join is a cancelation point. -       * If we are cancelled then our target thread must not be +       * If we are canceled then our target thread must not be         * detached (destroyed). This is guarranteed because         * pthreadCancelableWait will not return if we -       * are cancelled. +       * are canceled.         */        result = pthreadCancelableWait(thread->threadH); diff --git a/tests/ChangeLog b/tests/ChangeLog index db66602..92fca1b 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,20 @@ +2000-12-29  Ross Johnson  <rpj@special.ise.canberra.edu.au> + +	* GNUmakefile: Add mutex4 test; ensure libpthreadw32.a is +	removed for "clean" target. +	* Makefile: Add mutex4 test. + +	* exception3.c: Remove SEH code; automatically pass the test +	under SEH (which is an N/A environment). + +	* mutex4.c: New test. + +	* eyal1.c (do_work_unit): Add a dummy "if" to force the +	optimiser to retain code; reduce thread work loads. + +	* condvar8.c (main): Add an additional "assert" for debugging; +	increase pthread_cond_signal timeout. +  2000-12-28  Ross Johnson  <rpj@special.ise.canberra.edu.au>  	* eyal1.c: Increase thread work loads. diff --git a/tests/GNUmakefile b/tests/GNUmakefile index 7b4fd64..33de3ac 100644 --- a/tests/GNUmakefile +++ b/tests/GNUmakefile @@ -32,7 +32,7 @@ COPYFILES	= $(HDR) $(LIB) $(DLL)  TESTS	= loadfree \  	  mutex1 condvar1 condvar2 exit1 create1 equal1 \  	  exit2 exit3 \ -	  join0 join1 join2 mutex2 mutex3 \ +	  join0 join1 join2 mutex2 mutex3 mutex4 \  	  count1 once1 tsd1 self1 self2 cancel1 cancel2 eyal1 \  	  condvar3 condvar4 condvar5 condvar6 condvar7 condvar8 condvar9 \  	  errno1 \ @@ -57,6 +57,7 @@ create1.pass: mutex2.pass  cancel1.pass: create1.pass  cancel2.pass: cancel1.pass  mutex3.pass: create1.pass +mutex4.pass: mutex3.pass  equal1.pass: create1.pass  exit2.pass: create1.pass  exit3.pass: create1.pass @@ -122,7 +123,7 @@ clean:  	- $(RM) pthread.h  	- $(RM) semaphore.h  	- $(RM) sched.h -	- $(RM) *.a +	- $(RM) libpthreadw32.a  	- $(RM) *.e  	- $(RM) *.obj  	- $(RM) *.pdb diff --git a/tests/Makefile b/tests/Makefile index 208b438..281cd50 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -33,7 +33,7 @@ EHFLAGS	=  # stop.
  PASSES= loadfree.pass \
 -	  mutex1.pass  mutex2.pass  mutex3.pass \
 +	  mutex1.pass  mutex2.pass  mutex3.pass mutex4.pass \
  	  condvar1.pass  condvar2.pass  \
  	  exit1.pass  create1.pass  equal1.pass  \
  	  exit2.pass  exit3.pass  \
 @@ -112,6 +112,7 @@ create1.pass: mutex2.pass  cancel1.pass: create1.pass
  cancel2.pass: cancel1.pass
  mutex3.pass: create1.pass
 +mutex4.pass: mutex3.pass
  equal1.pass: create1.pass
  exit2.pass: create1.pass
  exit3.pass: create1.pass
 diff --git a/tests/condvar8.c b/tests/condvar8.c index 9e63b79..ff893c7 100644 --- a/tests/condvar8.c +++ b/tests/condvar8.c @@ -93,10 +93,6 @@ mythread(void * arg)    assert(pthread_mutex_lock(&cvthing.lock) == 0); -  /* -   * pthread_cond_timedwait is a cancelation point and we -   * going to cancel one deliberately. -   */    pthread_cleanup_push(pthread_mutex_unlock, (void *) &cvthing.lock);    while (! (cvthing.shared > 0)) @@ -135,7 +131,7 @@ main()    abstime.tv_sec = currSysTime.time;    abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; -  abstime.tv_sec += 5; +  abstime.tv_sec += 10;    assert((t[0] = pthread_self()) != NULL); @@ -179,6 +175,8 @@ main()         * Give threads time to complete.         */        Sleep(1000); + +      assert(awoken == (i - 1));      } diff --git a/tests/exception3.c b/tests/exception3.c index b820b4b..66f4173 100644 --- a/tests/exception3.c +++ b/tests/exception3.c @@ -39,17 +39,16 @@   * - Process returns non-zero exit status.   */ +#include "test.h" + +#if defined(__cplusplus) -#if defined(_MSC_VER) && defined(__cplusplus) +#if defined(_MSC_VER)  #include <eh.h>  #else  #include <new.h>  #endif -#if defined(_MSC_VER) || defined(__cplusplus) - -#include "test.h" -  /*   * Create NUMTHREADS threads in addition to the Main thread.   */ @@ -60,28 +59,12 @@ enum {  int caught = 0;  pthread_mutex_t caughtLock = PTHREAD_MUTEX_INITIALIZER; -#if defined(_MSC_VER) && !defined(__cplusplus) - -LONG unhandledExceptionFilter (EXCEPTION_POINTERS *ep) -{ -  if (ep->ExceptionRecord->ExceptionCode == 0x1) -    { -      pthread_mutex_lock(&caughtLock); -      caught++; -      pthread_mutex_unlock(&caughtLock); -    } - -  return EXCEPTION_CONTINUE_EXECUTION; -} - -#elif defined(__cplusplus) -  void  terminateFunction ()  {    pthread_mutex_lock(&caughtLock);    caught++; -#if 1 +#if 0    {       FILE * fp = fopen("pthread.log", "a");       fprintf(fp, "Caught = %d\n", caught); @@ -92,28 +75,15 @@ terminateFunction ()    pthread_exit((void *) 0);  } -#endif -  void *  exceptionedThread(void * arg)  {    int dummy = 0x1; -  { -#if defined(_MSC_VER) && !defined(__cplusplus) +  (void) set_terminate(&terminateFunction); +  throw dummy; -    RaiseException(dummy, 0, 0, NULL); - -#elif defined(__cplusplus) - -    (void) set_terminate(&terminateFunction); - -    throw dummy; - -#endif -  } - -  return (void *) 100; +  return (void *) 0;  }  int @@ -125,25 +95,13 @@ main()    assert((mt = pthread_self()) != NULL); -  { -#if defined(_MSC_VER) && !defined(__cplusplus) -    LPTOP_LEVEL_EXCEPTION_FILTER oldHandler; -    oldHandler = SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) unhandledExceptionFilter); -#endif - -    for (i = 0; i < NUMTHREADS; i++) -      { -        assert(pthread_create(&et[i], NULL, exceptionedThread, NULL) == 0); -      } - -#if defined(_MSC_VER) && !defined(__cplusplus) -    (void) SetUnhandledExceptionFilter(oldHandler); -#endif +  for (i = 0; i < NUMTHREADS; i++) +    { +      assert(pthread_create(&et[i], NULL, exceptionedThread, NULL) == 0); +    } -    Sleep(30000); -  } +  Sleep(10000); -  printf("Caught = %d\n", caught);    assert(caught == NUMTHREADS);    /* @@ -152,7 +110,7 @@ main()    return 0;  } -#else /* defined(_MSC_VER) || defined(__cplusplus) */ +#else /* defined(__cplusplus) */  int  main() @@ -161,4 +119,4 @@ main()    return 0;  } -#endif /* defined(_MSC_VER) || defined(__cplusplus) */ +#endif /* defined(__cplusplus) */ diff --git a/tests/eyal1.c b/tests/eyal1.c index a9ba909..6954c3b 100644 --- a/tests/eyal1.c +++ b/tests/eyal1.c @@ -63,7 +63,7 @@ typedef struct thread_control	TC;  static TC		*tcs = NULL;  static int		nthreads = 10; -static int		nwork = 1000; +static int		nwork = 100;  static int		quiet = 0;  static int		todo = -1; @@ -86,7 +86,7 @@ die (int ret)  } -static void +static double  waste_time (int n)  {    int		i; @@ -98,6 +98,7 @@ waste_time (int n)      {        f = 2 * f * f / (f * f);      } +  return f;  }  static int @@ -105,6 +106,7 @@ do_work_unit (int who, int n)  {    int		i;    static int	nchars = 0; +  double	f = 0.0;    if (quiet)      i = 0; @@ -131,7 +133,11 @@ do_work_unit (int who, int n)    }    n = rand () % 10000;	/* ignore incoming 'n' */ -  waste_time (n); +  f = waste_time (n); + +  /* This prevents the statement above from being optimised out */ +  if (f > 0.0) +    return(n);    return (n);  } diff --git a/tests/mutex4.c b/tests/mutex4.c index 5290f2a..7b989d0 100644 --- a/tests/mutex4.c +++ b/tests/mutex4.c @@ -10,35 +10,32 @@   */  #include "test.h" -  -pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t locker_done = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t unlocker_done = PTHREAD_MUTEX_INITIALIZER; -static int washere = 0; +static int wasHere = 0; + +static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;  void * locker(void * arg)  { -  assert(pthread_mutex_lock(&locker_start) == 0); +  wasHere++;    assert(pthread_mutex_lock(&mutex1) == 0); -  assert(pthread_mutex_unlock(&locker_start) == 0); - -  /* Wait for unlocker to finish */ -  assert(pthread_mutex_lock(&unlocker_end) == 0); +  Sleep(1000);    assert(pthread_mutex_unlock(&mutex1) == 0); +  wasHere++;    return 0;  }  void * unlocker(void * arg)  { +  wasHere++; +    /* Wait for locker to lock mutex1 */ -  assert(pthread_mutex_lock(&unlocker_start) == 0); +  Sleep(500);    assert(pthread_mutex_unlock(&mutex1) == EPERM); -  assert(pthread_mutex_unlock(&unlocker_start) == 0); - +  wasHere++;    return 0;  } @@ -47,16 +44,11 @@ main()  {    pthread_t t; -  assert(pthread_mutex_lock(&locker_start) == 0); -  assert(pthread_mutex_lock(&unlocker_start) == 0); -    assert(pthread_create(&t, NULL, locker, NULL) == 0); -  assert(pthread_mutex_unlock(&locker_start) == 0); -  Sleep(0); -    assert(pthread_create(&t, NULL, unlocker, NULL) == 0); -  assert(pthread_mutex_unlock(&unlocker_start) == 0); -  Sleep(0); +  Sleep(2000); + +  assert(wasHere == 4);    return 0;  } @@ -317,7 +317,7 @@ pthread_getspecific (pthread_key_t key)        *      the thread, NULL is returned.        *        * RESULTS -      *              key value +      *              key value or NULL on failure        *        * ------------------------------------------------------        */ | 
