diff options
| -rw-r--r-- | ChangeLog | 8 | ||||
| -rw-r--r-- | nonportable.c | 69 | 
2 files changed, 60 insertions, 17 deletions
| @@ -1,5 +1,13 @@  2002-02-02  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>
 +	Contributed by - Alexander Terekhov<TEREKHOV@de.ibm.com>
 +	
 +	* nonportable.c (pthread_delay_np): Make a true
 +	cancelation point. Deferred cancels will interrupt the
 +	wait.
 +	
 +2002-02-02  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>
 +
  	* cancel.c: Rearranged some code and introduced checks
  	to disable cancelation at the start of a thread's cancelation
  	run to prevent double cancelation. The main problem
 diff --git a/nonportable.c b/nonportable.c index 8bfeb2a..0d97300 100644 --- a/nonportable.c +++ b/nonportable.c @@ -64,7 +64,7 @@ pthread_getw32threadhandle_np(pthread_t thread)  /* - * Provide pthread_delay_np posix function for NT + * pthread_delay_np   *   * DESCRIPTION   * @@ -107,31 +107,66 @@ pthread_getw32threadhandle_np(pthread_t thread)  int  pthread_delay_np (struct timespec * interval)  { -  DWORD  wait_time, secs_in_millisecs, millisecs; +  DWORD wait_time; +  DWORD secs_in_millisecs; +  DWORD millisecs; +  DWORD status; -  /* -   * We are a cancelation point. -   */ -  pthread_testcancel(); +  if (interval == NULL) +    { +      return EINVAL; +    } -  if (interval->tv_sec < 0 || interval->tv_nsec < 0) +  if (interval->tv_sec == 0L && interval->tv_nsec == 0L)      { -      return (EINVAL); +      pthread_testcancel(); +      Sleep(0); +      pthread_testcancel();      } -  secs_in_millisecs = interval->tv_sec * 1000L;           /* convert secs to millisecs */ +  /* convert secs to millisecs */ +  secs_in_millisecs = interval->tv_sec * 1000L; -  /* -   * Pedantically, we're ensuring that we don't return before the time is up, -   * even by a fraction of a millisecond. -   */ -  millisecs = (interval->tv_nsec + 999999L) / 1000000L;    /* convert nanosecs to millisecs */ +  /* convert nanosecs to millisecs (rounding up) */ +  millisecs = (interval->tv_nsec + 999999L) / 1000000L; -  wait_time         = secs_in_millisecs + millisecs; +  if (0 > (wait_time = secs_in_millisecs + millisecs)) +    { +      return EINVAL; +    } -  Sleep(wait_time); +  if (self->cancelState == PTHREAD_CANCEL_ENABLE) +    { +      /* +       * Async cancelation won't catch us until wait_time is up. +       * Deferred cancelation will cancel us immediately. +       */ +      if (WAIT_OBJECT_0 ==  +          (status = WaitForSingleObject(self->cancelEvent, wait_time)) ) +        { +          /* +           * Canceling! +           */ +          (void) pthread_mutex_lock(&self->cancelLock); +          if (self->state < PThreadStateCanceling) +            { +              self->state = PThreadStateCanceling; +              self->cancelState = PTHREAD_CANCEL_DISABLE; +              (void) pthread_mutex_unlock(&self->cancelLock); + +              ptw32_throw(PTW32_EPS_CANCEL); +            } +        } -  pthread_testcancel(); +      if (status != WAIT_TIMEOUT) +        { +          return EINVAL; +        } +    } +  else +    { +      Sleep( wait_time ); +    }    return (0);  } | 
