From 199d96f3e3f6077235be8e0bf9482d2a46e108c2 Mon Sep 17 00:00:00 2001 From: rpj Date: Thu, 7 Sep 2000 15:41:11 +0000 Subject: 2000-09-08 Ross Johnson * cancel.c (pthread_cancel): Must get "self" through calling pthread_self() which will ensure a POSIX thread struct is built for non-POSIX threads; return an error if this fails - Ollie Leahy (pthread_setcancelstate): Likewise. (pthread_setcanceltype): Likewise. * misc.c (ptw32_cancelable_wait): Likewise. * private.c (ptw32_tkAssocCreate): Remove unused #if 0 wrapped code. * pthread.h (ptw32_get_exception_services_code): Needed to be forward declared unconditionally. 2000-09-06 Ross Johnson * cancel.c (pthread_cancel): If called from the main thread "self" would be NULL; get "self" via pthread_self() instead of directly from TLS so that an implicit pthread object is created. * misc.c (pthread_equal): Strengthen test for NULLs. --- tests/ChangeLog | 10 +++ tests/GNUmakefile | 5 +- tests/Makefile | 5 +- tests/cancel5.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/eyal1.c | 4 +- 5 files changed, 195 insertions(+), 6 deletions(-) create mode 100644 tests/cancel5.c (limited to 'tests') diff --git a/tests/ChangeLog b/tests/ChangeLog index 0bccb5b..a809dca 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,13 @@ +2000-09-08 Ross Johnson + + * cancel5.c: New; tests calling pthread_cancel() + from the main thread without first creating a + POSIX thread struct for the non-POSIX main thread + - this forces pthread_cancel() to create one via + pthread_self(). + * Makefile (cancel5): Add new test. + * GNUmakefile (cancel5): Likewise. + 2000-08-17 Ross Johnson * create2.c: New; Test that pthread_t contains diff --git a/tests/GNUmakefile b/tests/GNUmakefile index e8438e2..a775e10 100644 --- a/tests/GNUmakefile +++ b/tests/GNUmakefile @@ -35,7 +35,7 @@ TESTS = loadfree \ condvar3 condvar4 condvar5 condvar6 condvar7 condvar8 condvar9 \ errno1 \ rwlock1 rwlock2 rwlock3 rwlock4 rwlock5 rwlock6 \ - context1 cancel3 cancel4 \ + context1 cancel3 cancel4 cancel5 \ cleanup0 cleanup1 cleanup2 cleanup3 \ exception1 @@ -83,7 +83,8 @@ rwlock6.pass: rwlock5.pass context1.pass: cancel2.pass cancel3.pass: context1.pass cancel4.pass: cancel3.pass -cleanup0.pass: cancel4.pass +cancel5.pass: cancel3.pass +cleanup0.pass: cancel5.pass cleanup1.pass: cleanup0.pass cleanup2.pass: cleanup1.pass cleanup3.pass: cleanup2.pass diff --git a/tests/Makefile b/tests/Makefile index 08cfcce..41e202c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -47,7 +47,7 @@ PASSES= loadfree.pass \ errno1.pass \ rwlock1.pass rwlock2.pass rwlock3.pass rwlock4.pass rwlock5.pass rwlock6.pass \ context1.pass \ - cancel3.pass cancel4.pass \ + cancel3.pass cancel4.pass cancel5.pass \ cleanup0.pass cleanup1.pass cleanup2.pass cleanup3.pass \ exception1.pass @@ -140,7 +140,8 @@ rwlock6.pass: rwlock5.pass context1.pass: cancel2.pass cancel3.pass: context1.pass cancel4.pass: cancel3.pass -cleanup0.pass: cancel4.pass +cancel5.pass: cancel3.pass +cleanup0.pass: cancel5.pass cleanup1.pass: cleanup0.pass cleanup2.pass: cleanup1.pass cleanup3.pass: cleanup2.pass diff --git a/tests/cancel5.c b/tests/cancel5.c new file mode 100644 index 0000000..7d7262a --- /dev/null +++ b/tests/cancel5.c @@ -0,0 +1,177 @@ +/* + * File: cancel5.c + * + * Test Synopsis: Test calling pthread_cancel from the main thread + * without calling pthread_self() in main. + * + * 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]; + +void * +mythread(void * arg) +{ + int result = ((int)PTHREAD_CANCELED + 1); + 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 (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + 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/eyal1.c b/tests/eyal1.c index 412fbf0..843cb33 100644 --- a/tests/eyal1.c +++ b/tests/eyal1.c @@ -62,8 +62,8 @@ struct thread_control { typedef struct thread_control TC; static TC *tcs = NULL; -static int nthreads = 7; -static int nwork = 50; +static int nthreads = 14; +static int nwork = 100; static int quiet = 0; static int todo = -1; -- cgit v1.2.3