summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/ChangeLog19
-rw-r--r--tests/Makefile11
-rw-r--r--tests/cancel2.c216
-rw-r--r--tests/cancel3.c180
-rw-r--r--tests/cancel4.c183
-rw-r--r--tests/ccl.bat6
-rw-r--r--tests/condvar2.c4
-rw-r--r--tests/condvar3.c4
-rw-r--r--tests/condvar4.c4
-rw-r--r--tests/condvar5.c4
-rw-r--r--tests/condvar6.c4
-rw-r--r--tests/condvar7.c4
-rw-r--r--tests/condvar8.c4
-rw-r--r--tests/condvar9.c4
-rw-r--r--tests/context1.c110
-rw-r--r--tests/count1.c4
-rw-r--r--tests/join2.c4
-rw-r--r--tests/loadfree.c38
-rw-r--r--tests/runall.bat5
-rw-r--r--tests/test.h35
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 */