From f30d6ddddca263719a851e213691a33e5da69f3a Mon Sep 17 00:00:00 2001 From: cgf Date: Sun, 7 Sep 2003 05:18:01 +0000 Subject: [PATCH] * signal.cc (nanosleep): Improve test for valid values. Round delay up to resolution. Fix test for negative remainder. Use timeGetTime through gtod. (sleep): Round up return value. Christopher Faylor * hires.h (HIRES_DELAY_MAX): Define. (hires_ms::minperiod): Declare static. (hires_ms::resolution): New. (hires_ms::dmsecs): New. (hires_ms::prime): Return UINT. (gtod): Declare. * times.cc (hires_ms::prime): Always calculate minperiod and set it to 1 in case of failure. Return minperiod. (hires_ms::resolution): Define. (hires_ms::~hires_ms): Delete. (hires_ms::usecs): Check minperiod to prime. (gtod) Define as global. --- winsup/cygwin/ChangeLog | 23 +++++++++++++++++++++ winsup/cygwin/fhandler_raw.cc | 2 +- winsup/cygwin/hires.h | 18 ++++++++++++++--- winsup/cygwin/signal.cc | 19 +++++++++-------- winsup/cygwin/times.cc | 47 +++++++++++++++++++++++++------------------ 5 files changed, 77 insertions(+), 32 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b8eb9245b9..e74675be1e 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,26 @@ +2003-09-07 Pierre Humblet + + * signal.cc (nanosleep): Improve test for valid values. Round delay up + to resolution. Fix test for negative remainder. Use timeGetTime + through gtod. + (sleep): Round up return value. + +2003-09-07 Pierre Humblet + Christopher Faylor + + * hires.h (HIRES_DELAY_MAX): Define. + (hires_ms::minperiod): Declare static. + (hires_ms::resolution): New. + (hires_ms::dmsecs): New. + (hires_ms::prime): Return UINT. + (gtod): Declare. + * times.cc (hires_ms::prime): Always calculate minperiod and set it to + 1 in case of failure. Return minperiod. + (hires_ms::resolution): Define. + (hires_ms::~hires_ms): Delete. + (hires_ms::usecs): Check minperiod to prime. + (gtod) Define as global. + 2003-09-06 Christopher Faylor Remove left coercion throughout. diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc index 5fdf462ab4..5ccaa42929 100644 --- a/winsup/cygwin/fhandler_raw.cc +++ b/winsup/cygwin/fhandler_raw.cc @@ -329,7 +329,7 @@ fhandler_dev_raw::raw_read (void *ptr, size_t& ulen) } } - (ssize_t) ulen = bytes_read; + ulen = (size_t) bytes_read; return; err: diff --git a/winsup/cygwin/hires.h b/winsup/cygwin/hires.h index b4599cb1ba..df4c44c4a1 100644 --- a/winsup/cygwin/hires.h +++ b/winsup/cygwin/hires.h @@ -13,11 +13,18 @@ details. */ #include +/* Largest delay in ms for sleep and alarm calls. + Allow actual delay to exceed requested delay by 10 s. + Express as multiple of 1000 (i.e. seconds) + max resolution + The tv_sec argument in timeval structures cannot exceed + HIRES_DELAY_MAX / 1000 - 1, so that adding fractional part + and rounding won't exceed HIRES_DELAY_MAX */ +#define HIRES_DELAY_MAX (((UINT_MAX - 10000) / 1000) * 1000) + 10 + class hires_base { protected: int inited; - virtual void prime () {} public: virtual LONGLONG usecs (bool justdelta) {return 0LL;} virtual ~hires_base () {} @@ -37,9 +44,14 @@ class hires_ms : hires_base { DWORD initime_ms; LARGE_INTEGER initime_us; - UINT minperiod; - void prime (); + static UINT minperiod; + UINT prime (); public: LONGLONG usecs (bool justdelta); + UINT dmsecs () { return timeGetTime (); } + UINT resolution () { return minperiod ?: prime (); } + }; + +extern hires_ms gtod; #endif /*__HIRES_H__*/ diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index 2b890dd624..133f192b45 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -17,6 +17,7 @@ details. */ #include #include "sigproc.h" #include "pinfo.h" +#include "hires.h" int sigcatchers; /* FIXME: Not thread safe. */ @@ -73,20 +74,22 @@ nanosleep (const struct timespec *rqtp, struct timespec *rmtp) sigframe thisframe (mainthread); pthread_testcancel (); - if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec > 999999999) + if ((unsigned int) rqtp->tv_sec > (HIRES_DELAY_MAX / 1000 - 1) + || (unsigned int) rqtp->tv_nsec > 999999999) { set_errno (EINVAL); return -1; } - - DWORD req = rqtp->tv_sec * 1000 + (rqtp->tv_nsec + 500000) / 1000000; - DWORD start_time = GetTickCount (); - DWORD end_time = start_time + req; + DWORD resolution = gtod.resolution (); + DWORD req = ((rqtp->tv_sec * 1000 + (rqtp->tv_nsec + 999999) / 1000000 + + resolution - 1) / resolution ) * resolution; + DWORD end_time = gtod.dmsecs () + req; syscall_printf ("nanosleep (%ld)", req); int rc = pthread::cancelable_wait (signal_arrived, req); - DWORD now = GetTickCount (); - DWORD rem = (rc == WAIT_TIMEOUT || now >= end_time) ? 0 : end_time - now; + DWORD rem; + if ((rem = end_time - gtod.dmsecs ()) > HIRES_DELAY_MAX) + rem = 0; if (rc == WAIT_OBJECT_0) { (void) thisframe.call_signal_handler (); @@ -111,7 +114,7 @@ sleep (unsigned int seconds) req.tv_sec = seconds; req.tv_nsec = 0; nanosleep (&req, &rem); - return rem.tv_sec + (rem.tv_nsec + 500000000) / 1000000000; + return rem.tv_sec + (rem.tv_nsec > 0); } extern "C" unsigned int diff --git a/winsup/cygwin/times.cc b/winsup/cygwin/times.cc index 0d4bc71127..9eea3352d0 100644 --- a/winsup/cygwin/times.cc +++ b/winsup/cygwin/times.cc @@ -142,11 +142,13 @@ totimeval (struct timeval *dst, FILETIME *src, int sub, int flag) dst->tv_sec = x / (long long) (1e6); } +hires_ms gtod; +UINT NO_COPY hires_ms::minperiod; + /* FIXME: Make thread safe */ extern "C" int gettimeofday (struct timeval *tv, struct timezone *tz) { - static hires_ms gtod; static bool tzflag; LONGLONG now = gtod.usecs (false); if (now == (LONGLONG) -1) @@ -620,37 +622,42 @@ hires_us::usecs (bool justdelta) return justdelta ? now.QuadPart : primed_ft.QuadPart + now.QuadPart; } -void +UINT hires_ms::prime () { TIMECAPS tc; FILETIME f; - int priority = GetThreadPriority (GetCurrentThread ()); - SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL); - if (timeGetDevCaps (&tc, sizeof (tc)) != TIMERR_NOERROR) - minperiod = 0; - else - { - minperiod = min (max (tc.wPeriodMin, 1), tc.wPeriodMax); - timeBeginPeriod (minperiod); - } + if (!minperiod) + if (timeGetDevCaps (&tc, sizeof (tc)) != TIMERR_NOERROR) + minperiod = 1; + else + { + minperiod = min (max (tc.wPeriodMin, 1), tc.wPeriodMax); + timeBeginPeriod (minperiod); + } - initime_ms = timeGetTime (); - GetSystemTimeAsFileTime (&f); - SetThreadPriority (GetCurrentThread (), priority); + if (!inited) + { + int priority = GetThreadPriority (GetCurrentThread ()); + SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL); + initime_ms = timeGetTime (); + GetSystemTimeAsFileTime (&f); + SetThreadPriority (GetCurrentThread (), priority); - inited = 1; - initime_us.HighPart = f.dwHighDateTime; - initime_us.LowPart = f.dwLowDateTime; - initime_us.QuadPart -= FACTOR; - initime_us.QuadPart /= 10; + inited = 1; + initime_us.HighPart = f.dwHighDateTime; + initime_us.LowPart = f.dwLowDateTime; + initime_us.QuadPart -= FACTOR; + initime_us.QuadPart /= 10; + } + return minperiod; } LONGLONG hires_ms::usecs (bool justdelta) { - if (!inited) + if (!minperiod) /* NO_COPY variable */ prime (); DWORD now = timeGetTime (); // FIXME: Not sure how this will handle the 49.71 day wrap around -- 2.11.0