diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/ChangeLog | 19 | ||||
| -rw-r--r-- | tests/Makefile | 11 | ||||
| -rw-r--r-- | tests/cancel2.c | 216 | ||||
| -rw-r--r-- | tests/cancel3.c | 180 | ||||
| -rw-r--r-- | tests/cancel4.c | 183 | ||||
| -rw-r--r-- | tests/ccl.bat | 6 | ||||
| -rw-r--r-- | tests/condvar2.c | 4 | ||||
| -rw-r--r-- | tests/condvar3.c | 4 | ||||
| -rw-r--r-- | tests/condvar4.c | 4 | ||||
| -rw-r--r-- | tests/condvar5.c | 4 | ||||
| -rw-r--r-- | tests/condvar6.c | 4 | ||||
| -rw-r--r-- | tests/condvar7.c | 4 | ||||
| -rw-r--r-- | tests/condvar8.c | 4 | ||||
| -rw-r--r-- | tests/condvar9.c | 4 | ||||
| -rw-r--r-- | tests/context1.c | 110 | ||||
| -rw-r--r-- | tests/count1.c | 4 | ||||
| -rw-r--r-- | tests/join2.c | 4 | ||||
| -rw-r--r-- | tests/loadfree.c | 38 | ||||
| -rw-r--r-- | tests/runall.bat | 5 | ||||
| -rw-r--r-- | tests/test.h | 35 | 
20 files changed, 794 insertions, 49 deletions
| 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  <rpj@special.ise.canberra.edu.au> + +	* 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  <rpj@special.ise.canberra.edu.au> + +	* test.h: Add header includes; include local header versions rather +	than system versions; rearrange the assert macro defines. + +1999-11-07  Ross Johnson  <rpj@ixobrychus.canberra.edu.au> + +	* loadfree.c: New. Test loading and freeing the library (DLL). +  1999-10-30  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>  	* 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 <towen@lucidcalm.dropbear.id.au> + * 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 <pthread.h> +#include "pthread.h" +#include "sched.h" +#include "semaphore.h"  #include <stdio.h>  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 */ | 
