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. --- tests/cancel1.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 tests/cancel1.c (limited to 'tests/cancel1.c') 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