summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/signal.cc
diff options
context:
space:
mode:
authorYaakov Selkowitz <yselkowi@redhat.com>2011-08-03 19:17:02 +0000
committerYaakov Selkowitz <yselkowi@redhat.com>2011-08-03 19:17:02 +0000
commitbfc071dbce317bf01107bfec1c1e823d7d96dc31 (patch)
tree53570cc6ca963911e874e074c506739933a67ed9 /winsup/cygwin/signal.cc
parent2964913236ed6ec76b4dc5bab7412bc6868fdce0 (diff)
downloadcygnal-bfc071dbce317bf01107bfec1c1e823d7d96dc31.tar.gz
cygnal-bfc071dbce317bf01107bfec1c1e823d7d96dc31.tar.bz2
cygnal-bfc071dbce317bf01107bfec1c1e823d7d96dc31.zip
* 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.
Diffstat (limited to 'winsup/cygwin/signal.cc')
-rw-r--r--winsup/cygwin/signal.cc87
1 files changed, 72 insertions, 15 deletions
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