From 46ae637c4ef03a921d4a06baf99219c6149a7d20 Mon Sep 17 00:00:00 2001 From: rpj Date: Sun, 15 May 2005 15:28:24 +0000 Subject: '' --- ChangeLog | 32 ++++++++++++ NEWS | 18 +++++++ pthread.h | 51 +++++++++++-------- pthread_detach.c | 65 +++++++++++++++++++----- pthread_join.c | 103 ++++++--------------------------------- pthread_win32_attach_detach_np.c | 23 +++++++-- ptw32_threadDestroy.c | 19 +------- ptw32_threadStart.c | 55 +++++++++------------ ptw32_throw.c | 4 ++ sem_init.c | 4 +- sem_post.c | 2 +- sem_post_multiple.c | 2 +- tests/Bmakefile | 5 +- tests/ChangeLog | 10 ++++ tests/GNUmakefile | 8 +-- tests/Makefile | 10 ++-- tests/Wmakefile | 7 ++- tests/create3.c | 2 +- tests/join0.c | 5 -- tests/join1.c | 9 +--- tests/join2.c | 4 -- tests/join3.c | 4 -- 22 files changed, 229 insertions(+), 213 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11b5560..524f674 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2005-05-13 Ross Johnson + + * 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 + + * 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 * ptw32_callUserDestroyRoutines.c: Run destructor process (i.e. diff --git a/NEWS b/NEWS index 8bc2823..74c8bd0 100644 --- a/NEWS +++ b/NEWS @@ -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) diff --git a/pthread.h b/pthread.h index e347a24..64f21b9 100644 --- a/pthread.h +++ b/pthread.h @@ -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; } @@ -146,20 +96,24 @@ pthread_join (pthread_t thread, void **value_ptr) result = EINVAL; } 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 diff --git a/sem_init.c b/sem_init.c index 647ba18..27d8cbb 100644 --- a/sem_init.c +++ b/sem_init.c @@ -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; } diff --git a/sem_post.c b/sem_post.c index 2edaecf..91f9755 100644 --- a/sem_post.c +++ b/sem_post.c @@ -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 + + * 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 * 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. */ -- cgit v1.2.3