diff options
| author | rpj <rpj> | 2005-05-15 15:28:24 +0000 | 
|---|---|---|
| committer | rpj <rpj> | 2005-05-15 15:28:24 +0000 | 
| commit | 46ae637c4ef03a921d4a06baf99219c6149a7d20 (patch) | |
| tree | ca25c87f4285954f598d6f9b11b906d74b24750d | |
| parent | d4a22be21479c3b52e0ba2d3cfb150a98c426422 (diff) | |
''
| -rw-r--r-- | ChangeLog | 32 | ||||
| -rw-r--r-- | NEWS | 18 | ||||
| -rw-r--r-- | pthread.h | 51 | ||||
| -rw-r--r-- | pthread_detach.c | 65 | ||||
| -rw-r--r-- | pthread_join.c | 103 | ||||
| -rw-r--r-- | pthread_win32_attach_detach_np.c | 23 | ||||
| -rw-r--r-- | ptw32_threadDestroy.c | 19 | ||||
| -rw-r--r-- | ptw32_threadStart.c | 55 | ||||
| -rw-r--r-- | ptw32_throw.c | 4 | ||||
| -rw-r--r-- | sem_init.c | 4 | ||||
| -rw-r--r-- | sem_post.c | 2 | ||||
| -rw-r--r-- | sem_post_multiple.c | 2 | ||||
| -rw-r--r-- | tests/Bmakefile | 5 | ||||
| -rw-r--r-- | tests/ChangeLog | 10 | ||||
| -rw-r--r-- | tests/GNUmakefile | 8 | ||||
| -rw-r--r-- | tests/Makefile | 10 | ||||
| -rw-r--r-- | tests/Wmakefile | 7 | ||||
| -rw-r--r-- | tests/create3.c | 2 | ||||
| -rw-r--r-- | tests/join0.c | 5 | ||||
| -rw-r--r-- | tests/join1.c | 9 | ||||
| -rw-r--r-- | tests/join2.c | 4 | ||||
| -rw-r--r-- | tests/join3.c | 4 | 
22 files changed, 229 insertions, 213 deletions
| @@ -1,3 +1,35 @@ +2005-05-13  Ross Johnson  <ross at callisto.canberra.edu.au> + +	* pthread_win32_attach_detach_np.c (pthread_win32_thread_detach_np): +	Move on-exit-only stuff from ptw32_threadDestroy() to here. +	* ptw32_threadDestroy.c: It's purpose is now only to reclaim thread +	resources for detached threads, or via pthread_join() or +	pthread_detach() on joinable threads. +	* ptw32_threadStart.c: Calling user destruct routines has moved to +	pthread_win32_thread_detach_np(); call pthread_win32_thread_detach_np() +	directly if statically linking, otherwise do so via dllMain; store +	thread return value in thread struct for all cases, including +	cancellation and exception exits; thread abnormal exits	go via +	pthread_win32_thread_detach_np. +	* pthread_join.c (pthread_join): Don't try to get return code from +	Win32 thread - always get it from he thread struct. +	* pthread_detach.c (pthread_detach): reduce extent of the thread +	existence check since we now don't care if the Win32 thread HANDLE has +	been closed; reclaim thread resources if the thread has exited already. +	* ptw32_throw.c (ptw32_throw): For Win32 threads that are not implicit, +	only Call thread cleanup if statically linking, otherwise leave it to +	dllMain. +	* sem_post.c (_POSIX_SEM_VALUE_MAX): Change to SEM_VALUE_MAX. +	* sem_post_multiple.c: Likewise. +	* sem_init.c: Likewise. + +2005-05-10  Ross Johnson  <ross at callisto.canberra.edu.au> + +	* pthread_join.c (pthread_join): Add missing check for thread ID +	reference count in thread existence test; reduce extent of the +	existence test since we don't care if the Win32 thread HANDLE has +	been closed. +  2005-05-09  Ross Johnson  <ross at callisto.canberra.edu.au>  	* ptw32_callUserDestroyRoutines.c: Run destructor process (i.e. @@ -1,3 +1,21 @@ +RELEASE 2.6.0 +------------- +(Not released yet) + +Bugs fixed +---------- + +* pthread_detach() now reclaims remaining thread resources when called after +the target thread has terminated. Previously, this thread did nothing in +this case. + +New tests +--------- + +* detach1.c - tests that pthread_detach properly invalidates the target +thread, which indicates that the thread resources have been reclaimed. + +  RELEASE 2.5.0  -------------  (2005-05-09) @@ -37,8 +37,8 @@   * See the README file for an explanation of the pthreads-win32 version   * numbering scheme and how the DLL is named etc.   */ -#define PTW32_VERSION 2,5,0,0 -#define PTW32_VERSION_STRING "2, 5, 0, 0\0" +#define PTW32_VERSION 2,6,0,0 +#define PTW32_VERSION_STRING "2, 6, 0, 0\0"  /* There are three implementations of cancel cleanup.   * Note that pthread.h is included in both application @@ -510,40 +510,49 @@ extern "C"   *                      Maximum number of threads supported per   *                      process (must be at least 64).   * - * _POSIX_SEM_NSEMS_MAX - *      The maximum number of semaphores a process can have. - *      (only defined if not already defined) + * SEM_NSEMS_MAX + *                      The maximum number of semaphores a process can have. + *                      (must be at least 256)   * - * _POSIX_SEM_VALUE_MAX - *      The maximum value a semaphore can have. - *      (only defined if not already defined) + * SEM_VALUE_MAX + *                      The maximum value a semaphore can have. + *                      (must be at least 32767)   *   */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS     4 +  #undef PTHREAD_DESTRUCTOR_ITERATIONS -#define PTHREAD_DESTRUCTOR_ITERATIONS                          4 +#define PTHREAD_DESTRUCTOR_ITERATIONS           _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX                  128  #undef PTHREAD_KEYS_MAX -#define PTHREAD_KEYS_MAX                        64 +#define PTHREAD_KEYS_MAX                        _POSIX_THREAD_KEYS_MAX  #undef PTHREAD_STACK_MIN -#define PTHREAD_STACK_MIN                        0 - -#if PTW32_LEVEL < 2 -  /* Arbitrary value */ -#  undef PTHREAD_THREADS_MAX -#  define PTHREAD_THREADS_MAX                   2019 -#endif +#define PTHREAD_STACK_MIN                       0 -  /* Arbitrary value */  #undef _POSIX_THREAD_THREADS_MAX -#define _POSIX_THREAD_THREADS_MAX               2019 +#define _POSIX_THREAD_THREADS_MAX               64    /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX                     2019 +  #undef _POSIX_SEM_NSEMS_MAX -#define _POSIX_SEM_NSEMS_MAX                    1024 +#define _POSIX_SEM_NSEMS_MAX                    256 + +  /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX                           1024  #undef _POSIX_SEM_VALUE_MAX -#define _POSIX_SEM_VALUE_MAX                    (INT_MAX/2) +#define _POSIX_SEM_VALUE_MAX                    32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX                           INT_MAX  #if __GNUC__ && ! defined (__declspec) diff --git a/pthread_detach.c b/pthread_detach.c index d8a7650..01f1d40 100644 --- a/pthread_detach.c +++ b/pthread_detach.c @@ -58,12 +58,10 @@ pthread_detach (pthread_t thread)        *        *        * 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. +      *      This function detaches the given thread. You may use it to +      *      detach the main thread or to detach a joinable thread. +      *      NOTE:   detached threads cannot be joined; +      *              storage is freed immediately on termination.        *        * RESULTS        *              0               successfully detached the thread, @@ -75,23 +73,66 @@ pthread_detach (pthread_t thread)        */  {    int result; +  BOOL destroyIt = PTW32_FALSE;    ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; -  result = pthread_kill (thread, 0); +  EnterCriticalSection (&ptw32_thread_reuse_lock); -  if (0 != result) +  if (NULL == tp +      || thread.x != tp->ptHandle.x)      { -      return result; +      result = ESRCH;      } - -  if (tp->detachState == PTHREAD_CREATE_DETACHED) +  else if (PTHREAD_CREATE_DETACHED == tp->detachState)      {        result = EINVAL;      }    else      { +      /* +       * Joinable ptw32_thread_t structs are not scavenged until +       * a join or detach is done. The thread may have exited already, +       * but all of the state and locks etc are still there. +       */        result = 0; -      tp->detachState = PTHREAD_CREATE_DETACHED; + +      if (pthread_mutex_lock (&tp->cancelLock) == 0) +	{ +	  if (tp->state != PThreadStateLast) +	    { +	      tp->detachState = PTHREAD_CREATE_DETACHED; +	    } +	  else if (tp->detachState != PTHREAD_CREATE_DETACHED) +	    { +	      /* +	       * Thread is joinable and has exited or is exiting. +	       */ +	      destroyIt = PTW32_TRUE; +	    } +	  (void) pthread_mutex_unlock (&tp->cancelLock); +	} +      else +	{ +	  /* cancelLock shouldn't fail, but if it does ... */ +	  result = ESRCH; +	} +    } + +  LeaveCriticalSection (&ptw32_thread_reuse_lock); + +  if (result == 0) +    { +      /* Thread is joinable */ + +      if (destroyIt) +	{ +	  /* The thread has exited or is exiting but has not been joined or +	   * detached. Need to wait if it's still running - shouldn't have +	   * to wait long. +	   */ +	  (void) WaitForSingleObject(tp->threadH, INFINITE); +	  ptw32_threadDestroy (thread); +	}      }    return (result); diff --git a/pthread_join.c b/pthread_join.c index 56ed0ba..8237b6c 100644 --- a/pthread_join.c +++ b/pthread_join.c @@ -84,60 +84,10 @@ pthread_join (pthread_t thread, void **value_ptr)    pthread_t self;    ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; -  /* -   * Possibilities for the target thread on entry to pthread_join(): -   * -   * 1) the target thread is detached, in which case it could be destroyed and -   * it's thread id (struct) reused before we get the reuse lock; -   * 2) the target thread is joinable, in which case it will not be destroyed -   * until it has been joined, and it's thread id cannot be reused before we -   * get access to it. -   * -   * Only (1) is a potential race condition. -   * While (1) is possibly an application programming error, pthread_join is -   * required to handle it with an error. -   * If an application attempts to join a detached thread that exits before we -   * get the reuse lock, it's thread struct could be reused for a new joinable -   * thread before we get the reuse_lock and we will then be joining the wrong -   * thread. -   * -   * To fix this properly would require a reuse count as part of the thread id -   * so that we could confirm that we are working with the same thread. This -   * option will require a major change to the API, forcing recompilation of -   * applications that use the library. -   * -   * Cheaper alternatives that do not change the API are: -   * - separate reuse stacks could be used for detached and joinable -   * threads. Threads which detach themselves will not present a race condition -   * because they will be placed on a different stack to that which provides -   * reusable structs to new joinable threads. -   * The problem with this solution is that, an application that creates -   * joinable threads which then detach themselves can cause the detach reuse -   * stack to grow indefinitely. -   * -   * - maintain a sufficiently large reuse pool and manage it as a FIFO -   * queue. This would prevent the immediate reuse of thread structs, but this -   * only provides a statistical safeguard, not a deterministic one. -   * -   * - include an entry point array at the start of each thread struct so that -   * each reuse (modulo N) returns a different thread id (pointer to the thread -   * struct). Offset 0 from this pointer will contain a validity field and an -   * offset value field (subtracted from the pointer to obtain the address of -   * thread struct). This option is similar to including a reuse counter with -   * the thread id but maintains the thread id as a simple pointer. -   * -   * As at 03/11/2004, the reuse count option has been implemented. -   */ -    EnterCriticalSection (&ptw32_thread_reuse_lock); -  /* -   * The first test is the same as pthread_kill(thread, 0), duplicated here -   * so that we can use the reuse_lock to ensure the thread isn't destroyed -   * and reused before we've finished with the POSIX thread struct. -   */ -  if (tp == NULL -      || NULL == tp->threadH -      || THREAD_PRIORITY_ERROR_RETURN == GetThreadPriority (tp->threadH)) + +  if (NULL == tp +      || thread.x != tp->ptHandle.x)      {        result = ESRCH;      } @@ -147,19 +97,23 @@ pthread_join (pthread_t thread, void **value_ptr)      }    else      { +      result = 0; +    } + +  LeaveCriticalSection (&ptw32_thread_reuse_lock); + +  if (result == 0) +    {        /*          * The target thread is joinable and can't be reused before we join it.         */ - -      LeaveCriticalSection (&ptw32_thread_reuse_lock); -        self = pthread_self();        if (NULL == self.p)  	{  	  result = ENOENT;  	} -      else if (0 != pthread_equal (self, thread)) +      else if (pthread_equal (self, thread))  	{  	  result = EDEADLK;  	} @@ -176,29 +130,6 @@ pthread_join (pthread_t thread, void **value_ptr)  	  if (0 == result)  	    { - -#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) - -	      if (value_ptr != NULL -		  && !GetExitCodeThread (tp->threadH, (LPDWORD) value_ptr)) -		{ -		  result = ESRCH; -		} -	      else -		{ -		  /* -		   * The result of making multiple simultaneous calls to -		   * pthread_join() specifying the same target is undefined. -		   */ -		  ptw32_threadDestroy (thread); -		} - -#else /* __MINGW32__ && ! __MSVCRT__ */ - -	      /* -	       * If using CRTDLL, the thread may have exited, and endthread -	       * will have closed the handle. -	       */  	      if (value_ptr != NULL)  		{  		  *value_ptr = tp->exitStatus; @@ -206,24 +137,18 @@ pthread_join (pthread_t thread, void **value_ptr)  	      /*  	       * The result of making multiple simultaneous calls to -	       * pthread_join() specifying the same target is undefined. +	       * pthread_join() or pthread_detach() specifying the same +	       * target is undefined.  	       */ -	      ptw32_threadDestroy (thread); - -#endif /* __MINGW32__ && ! __MSVCRT__ */ - +	      result = pthread_detach (thread);  	    }  	  else  	    {  	      result = ESRCH;  	    }  	} - -      goto FAIL0;      } -  LeaveCriticalSection (&ptw32_thread_reuse_lock); -FAIL0:    return (result);  }				/* pthread_join */ diff --git a/pthread_win32_attach_detach_np.c b/pthread_win32_attach_detach_np.c index 6947080..191b0b0 100644 --- a/pthread_win32_attach_detach_np.c +++ b/pthread_win32_attach_detach_np.c @@ -261,15 +261,32 @@ pthread_win32_thread_detach_np ()         */        ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); -      if (sp != NULL) +      if (sp != NULL) // otherwise Win32 thread with no implicit POSIX handle.  	{ +	  ptw32_callUserDestroyRoutines (sp->ptHandle); + +	  (void) pthread_mutex_lock (&sp->cancelLock); +	  sp->state = PThreadStateLast;  	  /* -	   * Detached threads have their resources automatically -	   * cleaned up upon exit (others must be 'joined'). +	   * If the thread is joinable at this point then it MUST be joined +	   * or detached explicitly by the application.  	   */ +	  (void) pthread_mutex_unlock (&sp->cancelLock); +  	  if (sp->detachState == PTHREAD_CREATE_DETACHED)  	    {  	      ptw32_threadDestroy (sp->ptHandle); + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) +	      /* +	       * See documentation for endthread vs endthreadex. +	       */ +	      if (sp->threadH != 0) +	        { +	          CloseHandle (sp->threadH); +	        } +#endif +  	      TlsSetValue (ptw32_selfThreadKey->key, NULL);  	    }  	} diff --git a/ptw32_threadDestroy.c b/ptw32_threadDestroy.c index b88e5d9..aa95e2c 100644 --- a/ptw32_threadDestroy.c +++ b/ptw32_threadDestroy.c @@ -47,12 +47,6 @@ ptw32_threadDestroy (pthread_t thread)    if (tp != NULL)      { -      (void) pthread_mutex_lock (&tp->cancelLock); -      tp->state = PThreadStateLast; -      (void) pthread_mutex_unlock (&tp->cancelLock); - -      ptw32_callUserDestroyRoutines (thread); -        /*         * Copy thread state so that the thread can be atomically NULLed.         */ @@ -72,17 +66,6 @@ ptw32_threadDestroy (pthread_t thread)        (void) pthread_mutex_destroy(&threadCopy.cancelLock);        (void) pthread_mutex_destroy(&threadCopy.threadLock); - -#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) -      /* -       * See documentation for endthread vs endthreadex. -       */ -      if (threadCopy.threadH != 0) -	{ -	  CloseHandle (threadCopy.threadH); -	} -#endif -      } -  }				/* ptw32_threadDestroy */ + diff --git a/ptw32_threadStart.c b/ptw32_threadStart.c index b7c5748..5c0fe0e 100644 --- a/ptw32_threadStart.c +++ b/ptw32_threadStart.c @@ -109,12 +109,8 @@ static terminate_function  void  ptw32_terminate ()  { -  pthread_t self = pthread_self (); -  ptw32_thread_t * sp = (ptw32_thread_t *) self.p; -    set_terminate (ptw32_oldTerminate); -  (void) pthread_mutex_destroy (&sp->cancelLock); -  ptw32_callUserDestroyRoutines (self); +  (void) pthread_win32_thread_detach_np ();    terminate ();  } @@ -193,7 +189,7 @@ ptw32_threadStart (void *vthreadParms)      switch (ei[0])        {        case PTW32_EPS_CANCEL: -	status = PTHREAD_CANCELED; +	status = sp->exitStatus = PTHREAD_CANCELED;  #ifdef _UWIN  	if (--pthread_count <= 0)  	  exit (0); @@ -203,7 +199,7 @@ ptw32_threadStart (void *vthreadParms)  	status = sp->exitStatus;  	break;        default: -	status = PTHREAD_CANCELED; +	status = sp->exitStatus = PTHREAD_CANCELED;  	break;        }    } @@ -227,13 +223,13 @@ ptw32_threadStart (void *vthreadParms)        switch (setjmp_rc)  	{  	case PTW32_EPS_CANCEL: -	  status = PTHREAD_CANCELED; +	  status = sp->exitStatus = PTHREAD_CANCELED;  	  break;  	case PTW32_EPS_EXIT:  	  status = sp->exitStatus;  	  break;  	default: -	  status = PTHREAD_CANCELED; +	  status = sp->exitStatus = PTHREAD_CANCELED;  	  break;  	}      } @@ -310,9 +306,8 @@ ptw32_threadStart (void *vthreadParms)      (void) pthread_mutex_lock (&sp->cancelLock);      sp->state = PThreadStateException;      (void) pthread_mutex_unlock (&sp->cancelLock); -    (void) pthread_mutex_destroy (&sp->cancelLock); +    (void) pthread_win32_thread_detach_np ();      (void) set_terminate (ptw32_oldTerminate); -    ptw32_callUserDestroyRoutines (self);      throw;      /* @@ -330,27 +325,23 @@ ptw32_threadStart (void *vthreadParms)  #endif /* __CLEANUP_C */  #endif /* __CLEANUP_SEH */ -  if (sp->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); -    } +#if defined(PTW32_STATIC_LIB) +  /* +   * We need to cleanup the pthread now if we have +   * been statically linked, in which case the cleanup +   * in dllMain won't get done. Joinable threads will +   * only be partially cleaned up and must be fully cleaned +   * up by pthread_join() or pthread_detach(). +   * +   * Note: if this library has been statically linked, +   * 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()). +   * For the dll, dllMain will do the cleanup automatically. +   */ +  (void) pthread_win32_thread_detach_np (); +#endif  #if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__)    _endthreadex ((unsigned) status); diff --git a/ptw32_throw.c b/ptw32_throw.c index 57814e9..493f4e4 100644 --- a/ptw32_throw.c +++ b/ptw32_throw.c @@ -85,8 +85,12 @@ ptw32_throw (DWORD exception)  	  break;  	} +#if defined(PTW32_STATIC_LIB) +        pthread_win32_thread_detach_np (); +#endif +  #if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__)        _endthreadex (exitCode);  #else @@ -73,7 +73,7 @@ sem_init (sem_t * sem, int pshared, unsigned int value)        *              -1              failed, error in errno        * ERRNO        *              EINVAL          'sem' is not a valid semaphore, or -      *                              'value' >= _POSIX_SEM_VALUE_MAX +      *                              'value' >= SEM_VALUE_MAX        *              ENOMEM          out of memory,        *              ENOSPC          a required resource has been exhausted,        *              ENOSYS          semaphores are not supported, @@ -93,7 +93,7 @@ sem_init (sem_t * sem, int pshared, unsigned int value)         */        result = EPERM;      } -  else if (value > (unsigned int)_POSIX_SEM_VALUE_MAX) +  else if (value > (unsigned int)SEM_VALUE_MAX)      {        result = EINVAL;      } @@ -82,7 +82,7 @@ sem_post (sem_t * sem)      }    else if ((result = pthread_mutex_lock (&s->lock)) == 0)      { -      if (s->value < _POSIX_SEM_VALUE_MAX) +      if (s->value < SEM_VALUE_MAX)  	{  #ifdef NEED_SEM  	  if (++s->value <= 0 diff --git a/sem_post_multiple.c b/sem_post_multiple.c index 42ea2f4..fa950bd 100644 --- a/sem_post_multiple.c +++ b/sem_post_multiple.c @@ -86,7 +86,7 @@ sem_post_multiple (sem_t * sem, int count)      }    else if ((result = pthread_mutex_lock (&s->lock)) == 0)      { -      if (s->value <= (_POSIX_SEM_VALUE_MAX - count)) +      if (s->value <= (SEM_VALUE_MAX - count))  	{  	  waiters = -s->value;  	  s->value += count; diff --git a/tests/Bmakefile b/tests/Bmakefile index 81b79db..682e956 100644 --- a/tests/Bmakefile +++ b/tests/Bmakefile @@ -86,7 +86,7 @@ PASSES=   loadfree.pass \  	  exit1.pass  create1.pass  create2.pass  reuse1.pass  reuse2.pass  equal1.pass  \  	  kill1.pass  valid1.pass  valid2.pass  \  	  exit2.pass  exit3.pass  exit4.pass  exit5.pass  \ -	  join0.pass  join1.pass  join2.pass join3.pass  \ +	  join0.pass  join1.pass  detach1.pass  join2.pass join3.pass  \  	  mutex4.pass  mutex6.pass  mutex6n.pass  mutex6e.pass  mutex6r.pass  \  	  mutex6s.pass  mutex6es.pass  mutex6rs.pass  \  	  mutex7.pass  mutex7n.pass  mutex7e.pass  mutex7r.pass  \ @@ -261,6 +261,7 @@ create2.pass: create1.pass  create3.pass:  delay1.pass:  delay2.pass: delay1.pass +detach1.pass: join0.pass  equal1.pass: create1.pass  errno1.pass: mutex3.pass  exception1.pass: cancel4.pass @@ -340,7 +341,7 @@ spin1.pass:  spin2.pass: spin1.pass  spin3.pass: spin2.pass  spin4.pass: spin3.pass -stress1.pass: barrier5.pass +stress1.pass:  tsd1.pass: barrier5.pass join1.pass  tsd2.pass: tsd1.pass  valid1.pass: join1.pass diff --git a/tests/ChangeLog b/tests/ChangeLog index 3cd189f..bbd29f7 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,13 @@ +2005-05-15  Ross Johnson  <rpj@callisto.canberra.edu.au> + +	* detach1.c: New test. +	* join1.c: Reduce sleep times. +	* join0.c: Remove MSVCRT conditional compile - join should always +	return the thread exit code. +	* join1.c: Likewise. +	* join2.c: Likewise. +	* join3.c: Likewise. +  2005-04-18  Ross Johnson  <rpj@callisto.canberra.edu.au>  	* condvar3.c: Remove locks from around signalling calls - should not diff --git a/tests/GNUmakefile b/tests/GNUmakefile index 806a82c..fb28a53 100644 --- a/tests/GNUmakefile +++ b/tests/GNUmakefile @@ -81,7 +81,7 @@ TESTS	= sizes loadfree \  	  create1 create2 reuse1 reuse2 equal1 \  	  kill1 valid1 valid2 \  	  exit2 exit3 exit4 exit5 \ -	  join0 join1 join2 join3 \ +	  join0 join1 detach1 join2 join3 \  	  mutex2 mutex2r mutex2e mutex3 mutex3r mutex3e \  	  mutex4 mutex6 mutex6n mutex6e mutex6r \  	  mutex6s mutex6es mutex6rs \ @@ -102,7 +102,7 @@ TESTS	= sizes loadfree \  	  priority1 priority2 inherit1 \  	  spin1 spin2 spin3 spin4 \  	  exception1 exception2 exception3 \ -	  cancel9 create3 +	  cancel9 create3 stress1  STRESSTESTS = \  	stress1 @@ -184,8 +184,6 @@ benchtest3.bench:  benchtest4.bench:  benchtest5.bench: -stress1.pass: -  barrier1.pass: semaphore4.pass  barrier2.pass: barrier1.pass  barrier3.pass: barrier2.pass @@ -228,6 +226,7 @@ create2.pass: create1.pass  create3.pass:  delay1.pass: cancel2.pass  delay2.pass: delay1.pass +detach1.pass: join0.pass  equal1.pass: create1.pass  errno1.pass: mutex3.pass  exception1.pass: cancel4.pass @@ -307,6 +306,7 @@ spin1.pass:  spin2.pass: spin1.pass  spin3.pass: spin2.pass  spin4.pass: spin3.pass +stress1.pass:  tsd1.pass: barrier5.pass join1.pass  tsd2.pass: tsd1.pass  valid1.pass: join1.pass diff --git a/tests/Makefile b/tests/Makefile index 8c5c937..6dc222e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -90,7 +90,7 @@ PASSES= sizes.pass  loadfree.pass \  	  exit1.pass  create1.pass  create2.pass  reuse1.pass  reuse2.pass  equal1.pass  \  	  kill1.pass  valid1.pass  valid2.pass  \  	  exit2.pass  exit3.pass  exit4.pass  exit5.pass  \ -	  join0.pass  join1.pass  join2.pass join3.pass  \ +	  join0.pass  join1.pass  detach1.pass  join2.pass join3.pass  \  	  mutex4.pass  mutex6.pass  mutex6n.pass  mutex6e.pass  mutex6r.pass  \  	  mutex6s.pass  mutex6es.pass  mutex6rs.pass  \  	  mutex7.pass  mutex7n.pass  mutex7e.pass  mutex7r.pass  \ @@ -115,13 +115,13 @@ PASSES= sizes.pass  loadfree.pass \  	  priority1.pass priority2.pass inherit1.pass  \  	  spin1.pass  spin2.pass  spin3.pass  spin4.pass  \  	  exception1.pass  exception2.pass  exception3.pass  \ -	  cancel9.pass  create3.pass +	  cancel9.pass  create3.pass  stress1.pass  BENCHRESULTS = \  	  benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench  STRESSRESULTS = \ -	  stress1.pass +	  stress1.stress  STATICRESULTS = \  	  self1.pass @@ -274,8 +274,6 @@ benchtest3.bench:  benchtest4.bench:  benchtest5.bench: -stress1.pass: -  barrier1.pass: semaphore4.pass  barrier2.pass: barrier1.pass  barrier3.pass: barrier2.pass @@ -317,6 +315,7 @@ create2.pass: create1.pass  create3.pass:  delay1.pass:  delay2.pass: delay1.pass +detach1.pass: join0.pass  equal1.pass: create1.pass  errno1.pass: mutex3.pass  exception1.pass: cancel4.pass @@ -396,6 +395,7 @@ spin1.pass:  spin2.pass: spin1.pass  spin3.pass: spin2.pass  spin4.pass: spin3.pass +stress1.pass: condvar9.pass barrier5.pass  tsd1.pass: barrier5.pass join1.pass  tsd2.pass: tsd1.pass  valid1.pass: join1.pass diff --git a/tests/Wmakefile b/tests/Wmakefile index 4f003df..fa11dc5 100644 --- a/tests/Wmakefile +++ b/tests/Wmakefile @@ -86,7 +86,7 @@ PASSES	= sizes.pass  loadfree.pass &  	  exit1.pass  create1.pass  create2.pass  reuse1.pass  reuse2.pass  equal1.pass  &  	  kill1.pass  valid1.pass  valid2.pass  &  	  exit2.pass  exit3.pass  exit4  exit5  & -	  join0.pass  join1.pass  join2.pass join3.pass  & +	  join0.pass  join1.pass  detach1.pass  join2.pass join3.pass  &  	  mutex4.pass  mutex6.pass  mutex6n.pass  mutex6e.pass  mutex6r.pass  &  	  mutex6s.pass  mutex6es.pass  mutex6rs.pass  &  	  mutex7.pass  mutex7n.pass  mutex7e.pass  mutex7r.pass  & @@ -111,7 +111,7 @@ PASSES	= sizes.pass  loadfree.pass &  	  spin1.pass  spin2.pass  spin3.pass  spin4.pass  &  	  barrier1.pass  barrier2.pass  barrier3.pass  barrier4.pass  barrier5.pass  &  	  exception1.pass  exception2.pass  exception3.pass  & -	  cancel9.pass +	  cancel9.pass  create3.pass  stress1.pass  BENCHRESULTS = &  	  benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench @@ -255,8 +255,10 @@ context1.pass: cancel2.pass  count1.pass: join1.pass  create1.pass: mutex2.pass  create2.pass: create1.pass +create3.pass:  delay1.pass:  delay2.pass: delay1.pass +detach1.pass: join0.pass  equal1.pass: create1.pass  errno1.pass: mutex3.pass  exception1.pass: cancel4.pass @@ -335,6 +337,7 @@ spin1.pass:  spin2.pass: spin1.pass  spin3.pass: spin2.pass  spin4.pass: spin3.pass +stress1.pass:  tsd1.pass: join1.pass  valid1.pass: join1.pass  valid2.pass: valid1.pass diff --git a/tests/create3.c b/tests/create3.c index 530a2f1..98bd520 100644 --- a/tests/create3.c +++ b/tests/create3.c @@ -92,7 +92,7 @@ threadFunc(void * arg)  }  int -main(int argc, char argv[]) +main(int argc, char * argv[])  {    int i;    pthread_t mt; diff --git a/tests/join0.c b/tests/join0.c index bece19c..a6cb25d 100644 --- a/tests/join0.c +++ b/tests/join0.c @@ -60,12 +60,7 @@ main(int argc, char * argv[])    assert(pthread_join(id, (void **) &result) == 0); -#if ! defined (__MINGW32__) || defined (__MSVCRT__)    assert(result == 123); -#else -# warning pthread_join not fully supported in this configuration. -  assert(result == 0); -#endif    /* Success. */    return 0; diff --git a/tests/join1.c b/tests/join1.c index 8f52ae7..8b11e95 100644 --- a/tests/join1.c +++ b/tests/join1.c @@ -43,7 +43,7 @@ func(void * arg)  {      int i = (int) arg; -    Sleep(i * 500); +    Sleep(i * 100);      pthread_exit(arg); @@ -65,17 +65,12 @@ main(int argc, char * argv[])  	  }  	/* Some threads will finish before they are joined, some after. */ -	Sleep(1000); +	Sleep(2 * 100 + 50);  	for (i = 0; i < 4; i++)  	  {  	    assert(pthread_join(id[i], (void **) &result) == 0); -#if ! defined (__MINGW32__) || defined (__MSVCRT__)  	    assert(result == i); -#else -# warning pthread_join not fully supported in this configuration. -	    assert(result == 0); -#endif  	  }  	/* Success. */ diff --git a/tests/join2.c b/tests/join2.c index 89a3633..4fa3012 100644 --- a/tests/join2.c +++ b/tests/join2.c @@ -61,11 +61,7 @@ main(int argc, char * argv[])  	for (i = 0; i < 4; i++)  	  {  	    assert(pthread_join(id[i], (void **) &result) == 0); -#if ! defined (__MINGW32__) || defined (__MSVCRT__) -	    /* CRTDLL _beginthread doesn't support return value, so -	       the assertion is guaranteed to fail. */  	    assert(result == i); -#endif  	  }  	/* Success. */ diff --git a/tests/join3.c b/tests/join3.c index ccc13dd..70cf3e9 100644 --- a/tests/join3.c +++ b/tests/join3.c @@ -67,11 +67,7 @@ main(int argc, char * argv[])  	for (i = 0; i < 4; i++)  	  {  	    assert(pthread_join(id[i], (void **) &result) == 0); -#if ! defined (__MINGW32__) || defined (__MSVCRT__) -	    /* CRTDLL _beginthread doesn't support return value, so -	       the assertion is guaranteed to fail. */  	    assert(result == i); -#endif  	  }  	/* Success. */ | 
