From 907de7f11ebcac02b705b421c3a4480cac9deaaf Mon Sep 17 00:00:00 2001 From: rpj Date: Thu, 18 Mar 1999 16:18:39 +0000 Subject: ==> ChangeLog <== Fri Mar 19 09:12:59 1999 Ross Johnson * private.c (_pthread_threadStart): status returns PTHREAD_CANCELED. * pthread.h (PTHREAD_CANCELED): defined. ==> tests/ChangeLog <== Fri Mar 19 1999 Ross Johnson * *.bat: redirect unwanted output to nul: * runall.bat: new. * cancel1.c: new. Not part of suite yet. --- ANNOUNCE | 2 +- ChangeLog | 6 ++ MAINTAINERS | 1 + private.c | 24 +++-- pthread.h | 10 ++ tests/ChangeLog | 8 ++ tests/cancel1.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/ccl.bat | 2 +- tests/runall.bat | 21 +++++ tests/runtest.bat | 43 +++++---- 10 files changed, 361 insertions(+), 29 deletions(-) create mode 100644 tests/cancel1.c create mode 100644 tests/runall.bat diff --git a/ANNOUNCE b/ANNOUNCE index 275a8ce..00987c4 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -130,7 +130,7 @@ The following functions are implemented: Static Initializers (macros) --------------------------- PTHREAD_ONCE_INIT - PTHREAD_MUTEXINITIALIZER + PTHREAD_MUTEX_INITIALIZER PTHREAD_COND_INITIALIZER --------------------------- diff --git a/ChangeLog b/ChangeLog index 8df6928..9bf3ccc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Fri Mar 19 09:12:59 1999 Ross Johnson + + * private.c (_pthread_threadStart): status returns PTHREAD_CANCELED. + + * pthread.h (PTHREAD_CANCELED): defined. + Tue Mar 16 1999 Ross Johnson * all: Add GNU LGPL and Copyright and Warranty. diff --git a/MAINTAINERS b/MAINTAINERS index 99e35cd..43d3142 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10,4 +10,5 @@ Contributors (in order of appearance) Robert Colquhoun rjc@trump.net.au John E. Bossom John.Bossom@cognos.com Anders Norlander anorland@hem2.passagen.se +Tor Lillqvist tml@iki.fi Kevin Ruland Kevin.Ruland@anheuser-busch.com diff --git a/private.c b/private.c index a4cdcda..9ffd1b3 100644 --- a/private.c +++ b/private.c @@ -147,7 +147,7 @@ _pthread_threadStart (ThreadParms * threadParms) void *(*start) (void *); void *arg; - int status; + void * status; tid = threadParms->tid; start = threadParms->start; @@ -165,7 +165,7 @@ _pthread_threadStart (ThreadParms * threadParms) * Run the caller's routine; */ (*start) (arg); - status = 0; + status = (void *) 0; } __except (EXCEPTION_EXECUTE_HANDLER) { @@ -173,7 +173,7 @@ _pthread_threadStart (ThreadParms * threadParms) * A system unexpected exception had occurred running the user's * routine. We get control back within this block. */ - status = -1; + status = PTHREAD_CANCELED; } #else /* _MSC_VER */ @@ -186,14 +186,14 @@ _pthread_threadStart (ThreadParms * threadParms) * Run the caller's routine; */ (*start) (arg); - status = 0; + status = (void *) 0; } catch (Pthread_exception) { /* * Thread was cancelled. */ - status = -1; + status = PTHREAD_CANCELED; } catch (...) { @@ -201,24 +201,28 @@ _pthread_threadStart (ThreadParms * threadParms) * A system unexpected exception had occurred running the user's * routine. We get control back within this block. */ - status = -1; + status = PTHREAD_CANCELED; } #else /* __cplusplus */ /* - * Run the caller's routine; + * Run the caller's routine; no cancelation or other exceptions will + * be honoured. */ (*start) (arg); - status = 0; + status = (void *) 0; #endif /* __cplusplus */ #endif /* _WIN32 */ - pthread_exit ((void *) status); + pthread_exit (status); - return ((void *) status); + /* + * Never reached. + */ + return (status); } /* threadStart */ diff --git a/pthread.h b/pthread.h index 9deff4d..bc11d1b 100644 --- a/pthread.h +++ b/pthread.h @@ -474,6 +474,16 @@ extern "C" #define PTHREAD_MUTEX_AUTO_CS_NP 0 #define PTHREAD_MUTEX_FORCE_CS_NP 1 +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + /* * ==================== * ==================== diff --git a/tests/ChangeLog b/tests/ChangeLog index 16af11f..7354fba 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,11 @@ +Fri Mar 19 1999 Ross Johnson + + * *.bat: redirect unwanted output to nul: + + * runall.bat: new. + + * cancel1.c: new. Not part of suite yet. + Mon Mar 15 00:17:55 1999 Ross Johnson * mutex1.c: only test mutex init and destroy; add assertions. diff --git a/tests/cancel1.c b/tests/cancel1.c new file mode 100644 index 0000000..189fc64 --- /dev/null +++ b/tests/cancel1.c @@ -0,0 +1,273 @@ +/******************************************************** + * An example source module to accompany... + * + * "Using POSIX Threads: Programming with Pthreads" + * by Brad nichols, Dick Buttlar, Jackie Farrell + * O'Reilly & Associates, Inc. + * + ******************************************************** + * cancel.c -- + * + * Demonstrates pthread cancellation. + * + */ + +#include +#include "pthread.h" + +#define NUM_THREADS 3 +#define MESSAGE_MAX_LEN 80 + +int count=NUM_THREADS; /* number of threads active */ +pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER; /* mutual exclusion + for count */ +pthread_cond_t init_done=PTHREAD_COND_INITIALIZER; /* signaled by + each thread after + completing initial- + ization */ +int id_arg[3] = {0,1,2}; + +/* + * Cleanup routine: last_breath() + */ +void last_breath(char *messagep) +{ + printf("\n\n%s last_breath() cleanup routine: free'ing 0x%x\n\n", + messagep, messagep); + + free(messagep); +} + +/* + * print_count() + */ +void print_count(char *messagep, int id, int i) +{ + int last_type,tmp_type; + + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_type); + switch(id) { + case 0: + printf("%s %4d\n", messagep, i); + break; + case 1: + printf("%s \t%4d\n", messagep, i); + break; + case 2: + printf("%s \t\t%4d\n", messagep, i); + break; + } + pthread_setcanceltype(last_type, &tmp_type); +} + +/* + * bullet_proof() + */ +void *bullet_proof(void *id_p) +{ + int i=0, last_state; + int *my_id = id_p; + char *messagep; + + + messagep = (char *)malloc(MESSAGE_MAX_LEN); + sprintf(messagep, "Bullet Proof, thread #%d: ", *my_id); + + printf("%s\tI'm Alive, setting general cancellation OFF\n", + messagep); + + /* push last_breath() routine onto stack */ + pthread_cleanup_push( (void *)last_breath, (void *)messagep ); + + /* We turn off general cancelability here ... */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &last_state); + + pthread_mutex_lock(&lock); + { + printf("\n%s signaling main that my init is done\n", messagep); + count -= 1; + /* signal to program that entering loop */ + pthread_cond_signal(&init_done); + pthread_mutex_unlock(&lock); + } + + /* loop forever until picked off with a cancel */ + for(;;i++) { + if (i%1000 == 0) + print_count(messagep, *my_id, i); + if (i%100000 == 0) { + printf("\n%s This is the thread that never ends... #%d\n", + messagep, i); + } + } + + /* Never get this far */ + + /* This pop is required by the standard, every push must have a pop + in the same lexical block. */ + pthread_cleanup_pop(0); + + return(NULL); +} + +/* + * ask_for_it() + */ +void *ask_for_it(void *id_p) +{ + int i=0, last_state, last_type; + int *my_id = id_p; + char *messagep; + + + messagep = (char *)malloc(MESSAGE_MAX_LEN); + sprintf(messagep, "Ask For It, thread #%d: ", *my_id); + + /* push last_breath() routine onto stack */ + pthread_cleanup_push( (void *)last_breath, (void *)messagep); + + /* We can turn on general cancelability here. Disable async cancellation */ + printf("%s\tI'm Alive, setting deferred cancellation ON\n", + messagep); + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_type); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state); + + pthread_mutex_lock(&lock); + { + printf("\n%s signaling main that my init is done\n", messagep); + count -= 1; + /* signal to program that entering loop */ + pthread_cond_signal(&init_done); + pthread_mutex_unlock(&lock); + } + + /* loop forever until picked off with a cancel */ + for(;;i++) { + if (i%1000 == 0) + print_count(messagep, *my_id, i); + if (i%10000 == 0) { + printf("\n%s\tLook, I'll tell you when you can cancel me.\n",messagep,i); + } + pthread_testcancel(); + } + + /* never get this far */ + + /* This pop is required by the standard, every push must have a pop + in the same lexical block. */ + pthread_cleanup_pop(0); + + return(NULL); +} + +/* + * sitting_duck() + */ +void *sitting_duck(void *id_p) +{ + int i=0, last_state, last_type, last_tmp; + int *my_id = id_p; + char *messagep; + + + messagep = (char *)malloc(MESSAGE_MAX_LEN); + sprintf(messagep, "Sitting Duck, thread #%d: ", *my_id); + + /* push last_breath() routine onto stack */ + pthread_cleanup_push( (void *)last_breath, (void *)messagep); + + pthread_mutex_lock(&lock); + { + printf("\n%s signaling main that my init is done\n", messagep); + count -= 1; + /* signal to program that entering loop */ + pthread_cond_signal(&init_done); + pthread_mutex_unlock(&lock); + } + + /* Now, we're safe to turn on async cancellability */ + printf("%s\tI'm Alive, setting async cancellation ON\n", + messagep); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &last_type); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state); + + /* loop forever until picked off with a cancel */ + for(;;i++) { + if (i%1000 == 0) + print_count(messagep, *my_id, i++); + if (i%10000 == 0) { + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_tmp); + printf("\n%s\tHum, nobody here but us chickens. %d\n", messagep,i); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &last_tmp); + } + } + + /* never get this far */ + + /* This pop is required by the standard, every push must have a pop + in the same lexical block. */ + pthread_cleanup_pop(0); + + return(NULL); +} + +extern int +main(void) +{ + int i; + void * statusp; + pthread_t threads[NUM_THREADS]; + + + /* spawn the threads */ + pthread_create(&(threads[0]), + NULL, + ask_for_it, + (void *) &(id_arg[0])); + + pthread_create(&(threads[1]), + NULL, + sitting_duck, + (void *) &(id_arg[1])); + + pthread_create(&(threads[2]), + NULL, + bullet_proof, + (void *) &(id_arg[2])); + + printf("main(): %d threads created\n", NUM_THREADS); + + pthread_mutex_lock(&lock); + + /* wait until all threads have entered loops */ + while (count != 0) { + pthread_cond_wait(&init_done, &lock); + } + + pthread_mutex_unlock(&lock); + + printf("main(): all threads have signaled that ready\n"); + + /* cancel each thread */ + for (i=0; i nul: diff --git a/tests/runall.bat b/tests/runall.bat new file mode 100644 index 0000000..21bbbbe --- /dev/null +++ b/tests/runall.bat @@ -0,0 +1,21 @@ +erase *.result + +call runtest cl mutex1 +call runtest cl mutex2 +call runtest cl exit1 +call runtest cl condvar1 +call runtest cl self1 +call runtest cl condvar2 +call runtest cl create1 +call runtest cl mutex3 +call runtest cl equal1 +call runtest cl exit2 +call runtest cl exit3 +call runtest cl join1 +call runtest cl count1 +call runtest cl once1 +call runtest cl tsd1 +call runtest cl self2 +call runtest cl eyal1 +call runtest cl condvar3 +call runtest cl condvar4 diff --git a/tests/runtest.bat b/tests/runtest.bat index c9106a2..03a9413 100644 --- a/tests/runtest.bat +++ b/tests/runtest.bat @@ -1,30 +1,39 @@ @echo off + +REM Usage: runtest cl|gcc testname testarg ... + +echo y | erase /s tmp > nul: +rmdir tmp +mkdir tmp cd tmp REM Make sure we start with only those files we expect to need -if exist pthread.dll erase pthread.dll -if exist pthread.h erase pthread.h -if exist pthread.lib erase pthread.lib -if exist libpthread32.a erase libpthread32.a -copy ..\..\pthread.dll . -copy ..\..\pthread.h . -copy ..\..\pthread.lib . -copy ..\..\libpthread32.a . +if exist pthread.dll erase pthread.dll > nul: +if exist pthread.h erase pthread.h > nul: +if exist test.h erase test.h > nul: +if exist pthread.lib erase pthread.lib > nul: +if exist libpthread32.a erase libpthread32.a > nul: +copy ..\..\pthread.dll . > nul: +copy ..\..\pthread.h . > nul: +copy ..\test.h . > nul: +copy ..\..\pthread.lib . > nul: +copy ..\..\libpthread32.a . > nul: REM Compile the test case REM produces aout.exe using the compiler given as %1 -call ..\c%1.bat %2 +call ..\c%1.bat %2 > nul: -echo TEST: %2 [%1] > results.txt +echo TEST: %2 [%1] > ..\%2.result REM Run the test case -aout.exe %3 %4 %5 %6 %7 %8 %9 >> results.txt +aout.exe %3 %4 %5 %6 %7 %8 %9 >> ..\%2.result REM Clean up -erase aout.exe -if exist pthread.dll erase pthread.dll -if exist pthread.h erase pthread.h -if exist pthread.lib erase pthread.lib -if exist libpthread32.a erase libpthread32.a +erase aout.exe > nul: +if exist pthread.dll erase pthread.dll > nul: +if exist pthread.h erase pthread.h > nul: +if exist pthread.lib erase pthread.lib > nul: +if exist libpthread32.a erase libpthread32.a > nul: cd .. -more < tmp\results.txt +more < %2.result + -- cgit v1.2.3