summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--nonportable.c69
2 files changed, 60 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index cad0504..1295213 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);
}