summaryrefslogtreecommitdiff
path: root/libc/sysdeps/mach/nanosleep.c
diff options
context:
space:
mode:
authorjoseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d>2012-05-12 15:44:41 +0000
committerjoseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d>2012-05-12 15:44:41 +0000
commit62eb53f68d92687a028f3c515489b30e3df1d979 (patch)
tree7fcf1c95d89caecbbff5d932778f04670c151c52 /libc/sysdeps/mach/nanosleep.c
parentc29b18b38ccefba22c13b33dd801acba0ae92523 (diff)
downloadeglibc2-62eb53f68d92687a028f3c515489b30e3df1d979.tar.gz
Merge changes between r18392 and r18519 from /fsf/trunk.
git-svn-id: svn://svn.eglibc.org/trunk@18520 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc/sysdeps/mach/nanosleep.c')
-rw-r--r--libc/sysdeps/mach/nanosleep.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/libc/sysdeps/mach/nanosleep.c b/libc/sysdeps/mach/nanosleep.c
index 0192ff0bd..a1ba19c17 100644
--- a/libc/sysdeps/mach/nanosleep.c
+++ b/libc/sysdeps/mach/nanosleep.c
@@ -1,5 +1,5 @@
/* nanosleep -- sleep for a period specified with a struct timespec
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -27,6 +27,15 @@ __nanosleep (const struct timespec *requested_time,
{
mach_port_t recv;
struct timeval before, after;
+
+ if (requested_time->tv_sec < 0
+ || requested_time->tv_nsec < 0
+ || requested_time->tv_nsec >= 1000000000)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
const mach_msg_timeout_t ms
= requested_time->tv_sec * 1000
+ (requested_time->tv_nsec + 999999) / 1000000;
@@ -35,16 +44,22 @@ __nanosleep (const struct timespec *requested_time,
if (remaining && __gettimeofday (&before, NULL) < 0)
return -1;
- (void) __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
- 0, 0, recv, ms, MACH_PORT_NULL);
+ error_t err = __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
+ 0, 0, recv, ms, MACH_PORT_NULL);
__mach_port_destroy (mach_task_self (), recv);
- if (remaining && __gettimeofday (&after, NULL) < 0)
- return -1;
-
- if (remaining)
+ if (err == EMACH_RCV_INTERRUPTED)
{
- timersub (&after, &before, &after);
- TIMEVAL_TO_TIMESPEC (&after, remaining);
+ if (remaining && __gettimeofday (&after, NULL) >= 0)
+ {
+ struct timeval req_time, elapsed, rem;
+ TIMESPEC_TO_TIMEVAL (&req_time, requested_time);
+ timersub (&after, &before, &elapsed);
+ timersub (&req_time, &elapsed, &rem);
+ TIMEVAL_TO_TIMESPEC (&rem, remaining);
+ }
+
+ errno = EINTR;
+ return -1;
}
return 0;