diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 981338080..804128965 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,19 @@ +2011-08-03 Yaakov Selkowitz + + * cygwin.din (clock_nanosleep): Export. + * posix.sgml (std-notimpl): Move clock_nanosleep from here... + (std-susv4): ... to here. + (std-notes): Note limitations of clock_nanosleep. + * signal.cc (clock_nanosleep): Renamed from nanosleep, adding clock_id + and flags arguments and changing return values throughout. + Improve checks for illegal rqtp values. Add support for + CLOCK_MONOTONIC and TIMER_ABSTIME. + (nanosleep): Rewrite in terms of clock_nanosleep. + (sleep): Ditto. + (usleep): Ditto. + * thread.cc: Mark clock_nanosleep in list of cancellation points. + * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. + 2011-08-03 Christopher Faylor * dll_init.cc: Use fabort in favor of api_fatal and fork_info->abort diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index eeb040886..cc544a32a 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -223,6 +223,7 @@ _clock = clock SIGFE clock_getcpuclockid SIGFE clock_getres SIGFE clock_gettime SIGFE +clock_nanosleep SIGFE clock_setres SIGFE clock_settime SIGFE clog NOSIGFE diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 9ed8db911..3798eb8df 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -418,12 +418,13 @@ details. */ error_print_progname. 248: Export __fpurge. 249: Export pthread_condattr_getclock, pthread_condattr_setclock. + 250: Export clock_nanosleep. */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 249 +#define CYGWIN_VERSION_API_MINOR 250 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/posix.sgml b/winsup/cygwin/posix.sgml index 1b122ebd3..5c92f53f4 100644 --- a/winsup/cygwin/posix.sgml +++ b/winsup/cygwin/posix.sgml @@ -92,6 +92,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008). clock_getcpuclockid clock_getres clock_gettime + clock_nanosleep (see chapter "Implementation Notes") clock_settime (see chapter "Implementation Notes") clog clogf @@ -1299,7 +1300,6 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008). ceill cexpl cimagl - clock_nanosleep clogl conjl copysignl @@ -1446,8 +1446,10 @@ by keeping track of the current root and accomodating this in the file related function calls. A real chroot functionality is not supported by Windows however. -clock_setres, clock_settime, -and timer_create only support CLOCK_REALTIME. +clock_nanosleep currently supports only +CLOCK_REALTIME and CLOCK_MONOTONIC. clock_setres, +clock_settime, and timer_create +currently support only CLOCK_REALTIME. BSD file locks created via flock are not propagated to the parent process and sibling processes. The locks are diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index f279dbf1f..4aa60d449 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -81,52 +81,104 @@ signal (int sig, _sig_func_ptr func) } extern "C" int -nanosleep (const struct timespec *rqtp, struct timespec *rmtp) +clock_nanosleep (clockid_t clk_id, int flags, const struct timespec *rqtp, + struct timespec *rmtp) { + const bool abstime = (flags & TIMER_ABSTIME) ? true : false; int res = 0; sig_dispatch_pending (); pthread_testcancel (); - if ((unsigned int) rqtp->tv_nsec > 999999999) + if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec > 999999999L) + return EINVAL; + + /* Explicitly disallowed by POSIX. Needs to be checked first to avoid + being caught by the following test. */ + if (clk_id == CLOCK_THREAD_CPUTIME_ID) + return EINVAL; + + /* support for CPU-time clocks is optional */ + if (CLOCKID_IS_PROCESS (clk_id) || CLOCKID_IS_THREAD (clk_id)) + return ENOTSUP; + + switch (clk_id) { - set_errno (EINVAL); - return -1; + case CLOCK_REALTIME: + case CLOCK_MONOTONIC: + break; + default: + /* unknown or illegal clock ID */ + return EINVAL; } + LARGE_INTEGER timeout; timeout.QuadPart = (LONGLONG) rqtp->tv_sec * NSPERSEC + ((LONGLONG) rqtp->tv_nsec + 99LL) / 100LL; - timeout.QuadPart *= -1LL; - syscall_printf ("nanosleep (%ld.%09ld)", rqtp->tv_sec, rqtp->tv_nsec); + if (abstime) + { + struct timespec tp; + + clock_gettime (clk_id, &tp); + /* Check for immediate timeout */ + if (tp.tv_sec > rqtp->tv_sec + || (tp.tv_sec == rqtp->tv_sec && tp.tv_nsec > rqtp->tv_nsec)) + return 0; + + if (clk_id == CLOCK_REALTIME) + timeout.QuadPart += FACTOR; + else + { + /* other clocks need to be handled with a relative timeout */ + timeout.QuadPart -= tp.tv_sec * NSPERSEC + tp.tv_nsec / 100LL; + timeout.QuadPart *= -1LL; + } + } + else /* !abstime */ + timeout.QuadPart *= -1LL; + + syscall_printf ("clock_nanosleep (%ld.%09ld)", rqtp->tv_sec, rqtp->tv_nsec); int rc = cancelable_wait (signal_arrived, &timeout); if (rc == WAIT_OBJECT_0) { _my_tls.call_signal_handler (); - set_errno (EINTR); - res = -1; + res = EINTR; } - if (rmtp) + /* according to POSIX, rmtp is used only if !abstime */ + if (rmtp && !abstime) { rmtp->tv_sec = (time_t) (timeout.QuadPart / NSPERSEC); rmtp->tv_nsec = (long) ((timeout.QuadPart % NSPERSEC) * 100LL); } - syscall_printf ("%d = nanosleep (%ld.%09ld, %ld.%09.ld)", res, rqtp->tv_sec, - rqtp->tv_nsec, rmtp ? rmtp->tv_sec : 0, - rmtp ? rmtp->tv_nsec : 0); + syscall_printf ("%d = clock_nanosleep (%lu, %d, %ld.%09ld, %ld.%09.ld)", + res, clk_id, flags, rqtp->tv_sec, rqtp->tv_nsec, + rmtp ? rmtp->tv_sec : 0, rmtp ? rmtp->tv_nsec : 0); return res; } +extern "C" int +nanosleep (const struct timespec *rqtp, struct timespec *rmtp) +{ + int res = clock_nanosleep (CLOCK_REALTIME, 0, rqtp, rmtp); + if (res != 0) + { + set_errno (res); + return -1; + } + return 0; +} + extern "C" unsigned int sleep (unsigned int seconds) { struct timespec req, rem; req.tv_sec = seconds; req.tv_nsec = 0; - if (nanosleep (&req, &rem)) + if (clock_nanosleep (CLOCK_REALTIME, 0, &req, &rem)) return rem.tv_sec + (rem.tv_nsec > 0); return 0; } @@ -137,8 +189,13 @@ usleep (useconds_t useconds) struct timespec req; req.tv_sec = useconds / 1000000; req.tv_nsec = (useconds % 1000000) * 1000; - int res = nanosleep (&req, NULL); - return res; + int res = clock_nanosleep (CLOCK_REALTIME, 0, &req, NULL); + if (res != 0) + { + set_errno (res); + return -1; + } + return 0; } extern "C" int diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 40526e6f8..389c8fda3 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -577,7 +577,7 @@ pthread::cancel () * accept () o aio_suspend () - o clock_nanosleep () + * clock_nanosleep () * close () * connect () * creat ()