diff options
| -rw-r--r-- | ANNOUNCE | 2 | ||||
| -rw-r--r-- | ChangeLog | 6 | ||||
| -rw-r--r-- | MAINTAINERS | 1 | ||||
| -rw-r--r-- | private.c | 24 | ||||
| -rw-r--r-- | pthread.h | 10 | ||||
| -rw-r--r-- | tests/ChangeLog | 8 | ||||
| -rw-r--r-- | tests/cancel1.c | 273 | ||||
| -rw-r--r-- | tests/ccl.bat | 2 | ||||
| -rw-r--r-- | tests/runall.bat | 21 | ||||
| -rw-r--r-- | tests/runtest.bat | 43 | 
10 files changed, 361 insertions, 29 deletions
| @@ -130,7 +130,7 @@ The following functions are implemented:        Static Initializers (macros)        ---------------------------        PTHREAD_ONCE_INIT -      PTHREAD_MUTEXINITIALIZER +      PTHREAD_MUTEX_INITIALIZER        PTHREAD_COND_INITIALIZER           --------------------------- @@ -1,3 +1,9 @@ +Fri Mar 19 09:12:59 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au> + +	* private.c (_pthread_threadStart): status returns PTHREAD_CANCELED. + +	* pthread.h (PTHREAD_CANCELED): defined. +  Tue Mar 16  1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>  	* 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 @@ -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 */ @@ -477,6 +477,16 @@ extern "C"  /*   * ====================   * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED       ((void *) -1) + + +/* + * ==================== + * ====================   * Once Key   * ====================   * ==================== 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  <rpj@ixobrychus.canberra.edu.au> + +	* *.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  <rpj@ixobrychus.canberra.edu.au>  	* 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 <stdio.h> +#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<NUM_THREADS; i++) { +    pthread_cancel(threads[i]); +  } + +  /* wait until all threads have finished */ +  for (i=0; i<NUM_THREADS; i++) { +    pthread_join(threads[i], &statusp); +    if (statusp == PTHREAD_CANCELED) { +      printf("main(): joined to thread %d, statusp=PTHREAD_CANCELED\n",i); +    } else { +      printf("main(): joined to thread %d\n",i); +    } +  } + +  printf("main()\t\tall %d threads have finished. \n", NUM_THREADS); + +  return 0; +} + + + + diff --git a/tests/ccl.bat b/tests/ccl.bat index 1f45e33..9dc72d9 100644 --- a/tests/ccl.bat +++ b/tests/ccl.bat @@ -1,3 +1,3 @@  cl /W3 /MT /nologo /Yd /Zi -I. -D_WIN32_WINNT=0x400 -DSTDCALL=_stdcall -c ..\%1.c  cl /Feaout.exe /Zi %1.obj .\pthread.lib -del %1.obj +del %1.obj > 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 + | 
