From a378d97dc9d9eadaef00a9f01816948db5f3a796 Mon Sep 17 00:00:00 2001 From: rpj Date: Tue, 4 Jan 2000 10:19:28 +0000 Subject: Main changes (see ChangeLog diff for details and attributions):- - asynchronous cancellation added - attempt to hide internal exceptions from applications - kernel32 load/free problem fixed - new tests - changes only to comments in some tests --- tests/ChangeLog | 19 +++++ tests/Makefile | 11 ++- tests/cancel2.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/cancel3.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++ tests/cancel4.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++ tests/ccl.bat | 6 ++ tests/condvar2.c | 4 -- tests/condvar3.c | 4 -- tests/condvar4.c | 4 -- tests/condvar5.c | 4 -- tests/condvar6.c | 4 -- tests/condvar7.c | 4 -- tests/condvar8.c | 4 -- tests/condvar9.c | 4 -- tests/context1.c | 110 ++++++++++++++++++++++++++++ tests/count1.c | 4 ++ tests/join2.c | 4 ++ tests/loadfree.c | 38 ++++++++++ tests/runall.bat | 5 ++ tests/test.h | 35 +++++---- 20 files changed, 794 insertions(+), 49 deletions(-) create mode 100644 tests/cancel2.c create mode 100644 tests/cancel3.c create mode 100644 tests/cancel4.c create mode 100644 tests/context1.c create mode 100644 tests/loadfree.c (limited to 'tests') diff --git a/tests/ChangeLog b/tests/ChangeLog index 5e8fca9..cd155f8 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,22 @@ +2000-01-04 Ross Johnson + + * cancel4.c: New; Test cancelation does not occur in deferred + cancelation threads with no cancelation points. + + * cancel3.c: New; Test asynchronous cancelation. + + * context1.c: New; Test context switching method for async + cancelation. + +1999-11-23 Ross Johnson + + * test.h: Add header includes; include local header versions rather + than system versions; rearrange the assert macro defines. + +1999-11-07 Ross Johnson + + * loadfree.c: New. Test loading and freeing the library (DLL). + 1999-10-30 Ross Johnson * cancel1.c: New. Test pthread_setcancelstate and diff --git a/tests/Makefile b/tests/Makefile index 7056d2b..8820aac 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -40,9 +40,10 @@ TESTS = mutex1 condvar1 condvar2 exit1 create1 equal1 \ exit2 exit3 \ join1 join2 mutex2 mutex3 \ count1 once1 tsd1 self1 self2 cancel1 eyal1 \ - condvar3 condvar4 condvar5 condvar6 condvar7 condvar8 \ + condvar3 condvar4 condvar5 condvar6 condvar7 condvar8 condvar9 \ errno1 \ - rwlock1 rwlock2 rwlock3 rwlock4 rwlock5 rwlock6 + rwlock1 rwlock2 rwlock3 rwlock4 rwlock5 rwlock6 \ + context1 cancel3 cancel4 PASSES = $(TESTS:%=%.pass) @@ -73,6 +74,7 @@ condvar5.pass: condvar4.pass condvar6.pass: condvar5.pass condvar7.pass: condvar6.pass condvar8.pass: condvar6.pass +condvar9.pass: condvar6.pass errno1.pass: mutex3.pass rwlock1.pass: condvar6.pass rwlock2.pass: rwlock1.pass @@ -80,6 +82,9 @@ rwlock3.pass: rwlock2.pass rwlock4.pass: rwlock3.pass rwlock5.pass: rwlock4.pass rwlock6.pass: rwlock5.pass +context1.pass: cancel2.pass +cancel3.pass: context1.pass +cancel4.pass: cancel3.pass %.pass: %.exe $(LIB) $(DLL) $(HDR) $* @@ -99,5 +104,7 @@ clean: - $(RM) semaphore.h - $(RM) sched.h - $(RM) *.a + - $(RM) *.e - $(RM) *.exe - $(RM) *.pass + diff --git a/tests/cancel2.c b/tests/cancel2.c new file mode 100644 index 0000000..1a10c64 --- /dev/null +++ b/tests/cancel2.c @@ -0,0 +1,216 @@ +/* + * File: cancel2.c + * + * Test Synopsis: Test SEH or C++ cancel exception handling within + * application exception blocks. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#if defined(_MSC_VER) || defined(__cplusplus) + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +static pthread_mutex_t waitLock = PTHREAD_MUTEX_INITIALIZER; + +void * +mythread(void * arg) +{ + int result = 0; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + switch (bag->threadnum % 2) + { + case 0: + assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + result = 0; + break; + case 1: + assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0); + result = 1; + break; + } + +#ifdef _MSC_VER + __try +#else + try +#endif + { + /* Wait for go from main */ + assert(pthread_mutex_lock(&waitLock) == 0); + assert(pthread_mutex_unlock(&waitLock) == 0); + sched_yield(); + + for (;;) + { + pthread_testcancel(); + } + } +#ifdef _MSC_VER + __except(EXCEPTION_EXECUTE_HANDLER) +#else + catch(...) +#endif + { + /* + * Should not get into here. + */ + printf("SEH code=%x, MyCode=%x\n", GetExceptionCode(), _pthread_get_exception_services_code()); + result += 100; + } + + /* + * Should not get to here either. + */ + result += 1000; + + return (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + assert((t[0] = pthread_self()) != NULL); + assert(pthread_mutex_lock(&waitLock) == 0); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + assert(pthread_mutex_unlock(&waitLock) == 0); + + Sleep(500); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_cancel(t[i]) == 0); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + assert(pthread_join(t[i], (void *) &result) == 0); + fail = (result != (int) PTHREAD_CANCELED); + if (fail) + { + fprintf(stderr, "Thread %d: started %d: location %d: cancel type %s\n", + i, + threadbag[i].started, + result, + ((result % 2) == 0) ? "ASYNCHRONOUS" : "DEFERRED"); + } + failed |= fail; + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} + +#else /* defined(_MSC_VER) || defined(__cplusplus) */ + +int +main() +{ + return 0; +} + +#endif /* defined(_MSC_VER) || defined(__cplusplus) */ diff --git a/tests/cancel3.c b/tests/cancel3.c new file mode 100644 index 0000000..ff1d286 --- /dev/null +++ b/tests/cancel3.c @@ -0,0 +1,180 @@ +/* + * File: cancel3.c + * + * Test Synopsis: Test asynchronous cancelation. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#if defined(_MSC_VER) || defined(__cplusplus) + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +static pthread_mutex_t waitLock = PTHREAD_MUTEX_INITIALIZER; + +void * +mythread(void * arg) +{ + int result = 0; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + + /* + * We wait up to 10 seconds, waking every 0.1 seconds, + * for a cancelation to be applied to us. + */ + for (bag->count = 0; bag->count < 100; bag->count++) + Sleep(100); + + return result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + assert((t[0] = pthread_self()) != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_cancel(t[i]) == 0); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + /* + * The thread does not contain any cancelation points, so + * a return value of PTHREAD_CANCELED confirms that async + * cancelation succeeded. + */ + assert(pthread_join(t[i], (void *) &result) == 0); + + fail = (result != (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: count %d\n", + i, + threadbag[i].started, + threadbag[i].count); + } + failed = (failed || fail); + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} + +#else /* defined(_MSC_VER) || defined(__cplusplus) */ + +int +main() +{ + return 0; +} + +#endif /* defined(_MSC_VER) || defined(__cplusplus) */ diff --git a/tests/cancel4.c b/tests/cancel4.c new file mode 100644 index 0000000..9ce6880 --- /dev/null +++ b/tests/cancel4.c @@ -0,0 +1,183 @@ +/* + * File: cancel4.c + * + * Test Synopsis: Test cancelation does not occur in deferred + * cancelation threads with no cancelation points. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - pthread_create + * pthread_self + * pthread_cancel + * pthread_join + * pthread_setcancelstate + * pthread_setcanceltype + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#if defined(_MSC_VER) || defined(__cplusplus) + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +void * +mythread(void * arg) +{ + int result = 0; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0); + + /* + * We wait up to 10 seconds, waking every 0.1 seconds, + * for a cancelation to be applied to us. + */ + for (bag->count = 0; bag->count < 100; bag->count++) + Sleep(100); + + return result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + assert((t[0] = pthread_self()) != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_cancel(t[i]) == 0); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + /* + * The thread does not contain any cancelation points, so + * a return value of PTHREAD_CANCELED indicates that async + * cancelation occurred. + */ + assert(pthread_join(t[i], (void *) &result) == 0); + + fail = (result == (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: count %d\n", + i, + threadbag[i].started, + threadbag[i].count); + } + failed = (failed || fail); + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} + +#else /* defined(_MSC_VER) || defined(__cplusplus) */ + +int +main() +{ + return 0; +} + +#endif /* defined(_MSC_VER) || defined(__cplusplus) */ diff --git a/tests/ccl.bat b/tests/ccl.bat index 9dc72d9..473ff42 100644 --- a/tests/ccl.bat +++ b/tests/ccl.bat @@ -1,3 +1,9 @@ +REM Generate preprocessor output +REM cl /E /W3 /MT /nologo /Yd /Zi -I. -D_WIN32_WINNT=0x400 -DSTDCALL=_stdcall -c ..\%1.c > ..\%1.e + +REM Generate object file cl /W3 /MT /nologo /Yd /Zi -I. -D_WIN32_WINNT=0x400 -DSTDCALL=_stdcall -c ..\%1.c + +REM Generate executable cl /Feaout.exe /Zi %1.obj .\pthread.lib del %1.obj > nul: diff --git a/tests/condvar2.c b/tests/condvar2.c index b636a62..beae323 100644 --- a/tests/condvar2.c +++ b/tests/condvar2.c @@ -51,11 +51,7 @@ int main() { struct timespec abstime = { 0, 0 }; -#if defined(__MINGW32__) - struct timeb currSysTime; -#else struct _timeb currSysTime; -#endif const DWORD NANOSEC_PER_MILLISEC = 1000000; assert(pthread_cond_init(&cv, NULL) == 0); diff --git a/tests/condvar3.c b/tests/condvar3.c index ab1080e..deb130a 100644 --- a/tests/condvar3.c +++ b/tests/condvar3.c @@ -75,11 +75,7 @@ main() { pthread_t t[NUMTHREADS]; struct timespec abstime = { 0, 0 }; -#if defined(__MINGW32__) - struct timeb currSysTime; -#else struct _timeb currSysTime; -#endif const DWORD NANOSEC_PER_MILLISEC = 1000000; assert((t[0] = pthread_self()) != NULL); diff --git a/tests/condvar4.c b/tests/condvar4.c index ecb5e2d..3feaebb 100644 --- a/tests/condvar4.c +++ b/tests/condvar4.c @@ -82,11 +82,7 @@ main() { pthread_t t[NUMTHREADS]; struct timespec abstime = { 0, 0 }; -#if defined(__MINGW32__) - struct timeb currSysTime; -#else struct _timeb currSysTime; -#endif const DWORD NANOSEC_PER_MILLISEC = 1000000; cvthing.shared = 0; diff --git a/tests/condvar5.c b/tests/condvar5.c index e3b5e94..d406a2b 100644 --- a/tests/condvar5.c +++ b/tests/condvar5.c @@ -81,11 +81,7 @@ main() { pthread_t t[NUMTHREADS]; struct timespec abstime = { 0, 0 }; -#if defined(__MINGW32__) - struct timeb currSysTime; -#else struct _timeb currSysTime; -#endif const DWORD NANOSEC_PER_MILLISEC = 1000000; cvthing.shared = 0; diff --git a/tests/condvar6.c b/tests/condvar6.c index 7518ca6..6acc666 100644 --- a/tests/condvar6.c +++ b/tests/condvar6.c @@ -112,11 +112,7 @@ main() int i; pthread_t t[NUMTHREADS + 1]; -#if defined(__MINGW32__) - struct timeb currSysTime; -#else struct _timeb currSysTime; -#endif const DWORD NANOSEC_PER_MILLISEC = 1000000; cvthing.shared = 0; diff --git a/tests/condvar7.c b/tests/condvar7.c index d81dd78..ae51a10 100644 --- a/tests/condvar7.c +++ b/tests/condvar7.c @@ -116,11 +116,7 @@ main() int i; pthread_t t[NUMTHREADS + 1]; -#if defined(__MINGW32__) - struct timeb currSysTime; -#else struct _timeb currSysTime; -#endif const DWORD NANOSEC_PER_MILLISEC = 1000000; cvthing.shared = 0; diff --git a/tests/condvar8.c b/tests/condvar8.c index 65da040..3522546 100644 --- a/tests/condvar8.c +++ b/tests/condvar8.c @@ -121,11 +121,7 @@ main() int first, last; pthread_t t[NUMTHREADS + 1]; -#if defined(__MINGW32__) - struct timeb currSysTime; -#else struct _timeb currSysTime; -#endif const DWORD NANOSEC_PER_MILLISEC = 1000000; assert((t[0] = pthread_self()) != NULL); diff --git a/tests/condvar9.c b/tests/condvar9.c index 49a8cab..9b4f2f8 100644 --- a/tests/condvar9.c +++ b/tests/condvar9.c @@ -123,11 +123,7 @@ main() int canceledThreads = 0; pthread_t t[NUMTHREADS + 1]; -#if defined(__MINGW32__) - struct timeb currSysTime; -#else struct _timeb currSysTime; -#endif const DWORD NANOSEC_PER_MILLISEC = 1000000; assert((t[0] = pthread_self()) != NULL); diff --git a/tests/context1.c b/tests/context1.c new file mode 100644 index 0000000..8f615e1 --- /dev/null +++ b/tests/context1.c @@ -0,0 +1,110 @@ +/* + * File: context1.c + * + * Test Synopsis: Test context switching method. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - pthread_create + * pthread_exit + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" +#include "../implement.h" + +static int washere = 0; + +static void * func(void * arg) +{ + washere = 1; + + Sleep(1000); + + return 0; +} + +static void +anotherEnding () +{ + /* + * Switched context + */ + washere++; + + pthread_exit(0); +} + +int +main() +{ + pthread_t t; + HANDLE hThread; + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + hThread = t->threadH; + + Sleep(500); + + SuspendThread(hThread); + + if (WaitForSingleObject(hThread, 0) == WAIT_TIMEOUT) + { + /* + * Ok, thread did not exit before we got to it. + */ + CONTEXT context; + + context.ContextFlags = CONTEXT_CONTROL; + + GetThreadContext(hThread, &context); + /* + *_x86 only!!! + */ + context.Eip = (DWORD) anotherEnding; + SetThreadContext(hThread, &context); + ResumeThread(hThread); + } + else + { + printf("Exited early\n"); + fflush(stdout); + } + + Sleep(1000); + + assert(washere == 2); + + return 0; +} + diff --git a/tests/count1.c b/tests/count1.c index 9783fcc..e88a955 100644 --- a/tests/count1.c +++ b/tests/count1.c @@ -7,7 +7,11 @@ #include "test.h" +#if ! defined (__MINGW32__) || defined (__MSVCRT__) #define NUMTHREADS (60) +#else +#define NUMTHREADS (59) +#endif static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static pthread_t threads[NUMTHREADS]; diff --git a/tests/join2.c b/tests/join2.c index 281a0df..8b1636c 100644 --- a/tests/join2.c +++ b/tests/join2.c @@ -29,7 +29,11 @@ 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/loadfree.c b/tests/loadfree.c new file mode 100644 index 0000000..3aba61b --- /dev/null +++ b/tests/loadfree.c @@ -0,0 +1,38 @@ +/* + * From: Todd Owen + * To: pthreads-win32@sourceware.cygnus.com + * Subject: invalid page fault when using LoadLibrary/FreeLibrary + * + * hi, + * for me, pthread.dll consistently causes an "invalid page fault in + * kernel32.dll" when I load it "explicitly"...to be precise, loading (with + * LoadLibrary) isn't a problem, it gives the error when I call FreeLibrary. + * I guess that the dll's cleanup must be causing the error. + * + * Implicit linkage of the dll has never given me this problem. Here's a + * program (console application) that gives me the error. + * + * I compile with: mingw32 (gcc-2.95 release), with the MSVCRT add-on (not + * that the compiler should make much difference in this case). + * PTHREAD.DLL: is the precompiled 1999-11-02 one (I tried an older one as + * well, with the same result). + * + * Fascinatingly, if you have your own dll (mycode.dll) which implicitly + * loads pthread.dll, and then do LoadLibrary/FreeLibrary on _this_ dll, the + * same thing happens. + * + */ + +#include "test.h" + +int main() { + HINSTANCE hinst; + + assert((hinst = LoadLibrary("pthread")) != 0); + + Sleep(100); + + FreeLibrary(hinst); + return 0; +} + diff --git a/tests/runall.bat b/tests/runall.bat index 5c2d783..d8336c3 100644 --- a/tests/runall.bat +++ b/tests/runall.bat @@ -24,6 +24,7 @@ call runtest cl once1 create1 call runtest cl tsd1 join1 call runtest cl self2 create1 call runtest cl cancel1 self2 +call runtest cl cancel2 cancel1 call runtest cl eyal1 tsd1 call runtest cl condvar3 create1 call runtest cl condvar4 create1 @@ -39,6 +40,10 @@ call runtest cl rwlock3 rwlock2 call runtest cl rwlock4 rwlock3 call runtest cl rwlock5 rwlock4 call runtest cl rwlock6 rwlock5 +call runtest cl context1 cancel2 +call runtest cl cancel3 context1 +call runtest cl cancel4 cancel3 +call runtest cl loadfree _ if NOT EXIST *.notrun goto skip1 echo The following tests did not run (because prerequisite didn't pass?): diff --git a/tests/test.h b/tests/test.h index 36dc397..ffb8180 100644 --- a/tests/test.h +++ b/tests/test.h @@ -7,7 +7,9 @@ #ifndef _PTHREAD_TEST_H_ #define _PTHREAD_TEST_H_ -#include +#include "pthread.h" +#include "sched.h" +#include "semaphore.h" #include char * error_string[] = { @@ -61,28 +63,31 @@ char * error_string[] = { * which pops up a dialog. We want to run in batch mode so * we define our own assert macro. */ +#ifdef assert +# undef assert +#endif + #ifdef NDEBUG -#define assert(e) ((void)0) +# define assert(e) ((void)0) #else /* NDEBUG */ -#ifdef assert -# undef assert -#endif - #ifndef ASSERT_TRACE -#define ASSERT_TRACE 0 +# define ASSERT_TRACE 0 +#else +# undef ASSERT_TRACE +# define ASSERT_TRACE 1 #endif -#define assert(e) \ - ((e) ? ((ASSERT_TRACE) ? fprintf(stderr, \ - "Assertion succeeded: (%s), file %s, line %d\n", \ - #e, __FILE__, (int) __LINE__), \ - fflush(stderr) : \ - (void) 0) : \ - (fprintf(stderr, "Assertion failed: (%s), file %s, line %d\n", \ - #e, __FILE__, (int) __LINE__), exit(1))) +# define assert(e) \ + ((e) ? ((ASSERT_TRACE) ? fprintf(stderr, \ + "Assertion succeeded: (%s), file %s, line %d\n", \ + #e, __FILE__, (int) __LINE__), \ + fflush(stderr) : \ + (void) 0) : \ + (fprintf(stderr, "Assertion failed: (%s), file %s, line %d\n", \ + #e, __FILE__, (int) __LINE__), exit(1))) #endif /* NDEBUG */ -- cgit v1.2.3