From 006bf1acd58ea44c44d7de5a70f3fc6f5e040ac7 Mon Sep 17 00:00:00 2001 From: rpj Date: Thu, 7 Feb 2002 09:44:06 +0000 Subject: * nonportable.c (pthread_delay_np): Make a true cancelation point. Deferred cancels will interrupt the wait. --- ChangeLog | 8 +++++++ nonportable.c | 69 ++++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index cad0504..1295213 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2002-02-02 Ross Johnson + + Contributed by - Alexander Terekhov + + * nonportable.c (pthread_delay_np): Make a true + cancelation point. Deferred cancels will interrupt the + wait. + 2002-02-02 Ross Johnson * cancel.c: Rearranged some code and introduced checks 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); } -- cgit v1.2.3