diff options
| -rw-r--r-- | ANNOUNCE | 4 | ||||
| -rw-r--r-- | ChangeLog | 26 | ||||
| -rw-r--r-- | cancel.c | 13 | ||||
| -rw-r--r-- | misc.c | 9 | ||||
| -rw-r--r-- | private.c | 14 | ||||
| -rw-r--r-- | pthread.h | 4 | ||||
| -rw-r--r-- | tests/ChangeLog | 10 | ||||
| -rw-r--r-- | tests/GNUmakefile | 5 | ||||
| -rw-r--r-- | tests/Makefile | 5 | ||||
| -rw-r--r-- | tests/cancel5.c | 177 | ||||
| -rw-r--r-- | tests/eyal1.c | 4 | 
11 files changed, 240 insertions, 31 deletions
| @@ -1,5 +1,5 @@ -                 PTHREADS-WIN32 SNAPSHOT 2000-08-13
 +                 PTHREADS-WIN32 SNAPSHOT 2000-09-08
                   ----------------------------------
         Web Site: http://sources.redhat.com/pthreads-win32/
        FTP Site: ftp://sources.redhat.com/pub/pthreads-win32
 @@ -30,6 +30,8 @@ New:  		pthread_getw32threadhandle_np
  Bugs fixed:
 +-       Calling pthread_cancel from non-POSIX threads fixed.
 +-       Possible deadlock threat using pthread_cond_broadcast() reduced.
  -	TSD key creation race condition;
  -	Other potential race conditions
  	associated with initialising various
 @@ -1,3 +1,29 @@ +2000-09-08  Ross Johnson  <rpj@special.ise.canberra.edu.au> + +	* 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 <ollie@mpt.ie> +	(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  <rpj@special.ise.canberra.edu.au> + +	* 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. +  2000-09-02  Ross Johnson  <rpj@special.ise.canberra.edu.au>  	* condvar.c (ptw32_cond_wait_cleanup): Ensure that all @@ -106,7 +106,7 @@ pthread_setcancelstate (int state, int *oldstate)        */  {    int result = 0; -  pthread_t self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey); +  pthread_t self = pthread_self();    if (self == NULL        || (state != PTHREAD_CANCEL_ENABLE @@ -190,7 +190,7 @@ pthread_setcanceltype (int type, int *oldtype)        */  {    int result = 0; -  pthread_t self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey); +  pthread_t self = pthread_self();    if (self == NULL        || (type != PTHREAD_CANCEL_DEFERRED @@ -261,7 +261,7 @@ pthread_testcancel (void)        * ------------------------------------------------------        */  { -  pthread_t self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey); +  pthread_t self = pthread_self();    if (self != NULL        && self->cancelState == PTHREAD_CANCEL_ENABLE @@ -295,7 +295,7 @@ pthread_cancel (pthread_t thread)        * RESULTS        *              0               successfully requested cancellation,        *              ESRCH           no thread found corresponding to 'thread', -      * +      *              ENOMEM          implicit self thread create failed.        * ------------------------------------------------------        */  { @@ -309,7 +309,10 @@ pthread_cancel (pthread_t thread)      }    result = 0; -  self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey); +  if ((self = pthread_self()) == NULL) +    { +      return ENOMEM; +    };    /*     * FIXME!! @@ -229,7 +229,11 @@ pthread_equal (pthread_t t1, pthread_t t2)  {    int result; -  result = ((t1 == t2) && (t1->thread == t2->thread)); +  /* +   * We also accept NULL == NULL - treating NULL as a thread +   * for this special case, because there is no error that we can return. +   */ +  result = ( ( t1 == t2 ) && ( t1 == NULL || ( t1->thread == t2->thread ) ) );    return (result); @@ -260,8 +264,7 @@ ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout)    handles[0] = waitHandle; -  if ((self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey))  -      != NULL) +  if ((self = pthread_self()) != NULL)      {        /*         * Get cancelEvent handle @@ -399,22 +399,10 @@ ptw32_tkAssocCreate (ThreadKeyAssoc ** assocP,        goto FAIL0;      } -#if 0 - -  if ((result = pthread_mutex_init (&(assoc->lock), NULL)) != 0) -    { -      goto FAIL1; -    } - -#else -    /*     * Initialise only when used for the first time.     */    assoc->lock = PTHREAD_MUTEX_INITIALIZER; - -#endif -    assoc->thread = thread;    assoc->key = key; @@ -451,8 +439,6 @@ ptw32_tkAssocCreate (ThreadKeyAssoc ** assocP,     */  FAIL2:    pthread_mutex_destroy (&(assoc->lock)); - -FAIL1:    free (assoc);  FAIL0: @@ -981,14 +981,14 @@ class ptw32_exception_exit   : public ptw32_exception {};  #endif -#ifndef PTW32_BUILD -  /* FIXME: This is only required if the library was built using SEH */  /*   * Get internal SEH tag   */  DWORD ptw32_get_exception_services_code(void); +#ifndef PTW32_BUILD +  #if defined(_MSC_VER) && !defined(__cplusplus)  /* 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  <rpj@special.ise.canberra.edu.au> + +	* 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  <rpj@special.ise.canberra.edu.au>  	* 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; | 
