diff --git a/winsup/cygwin/fhandler_timerfd.cc b/winsup/cygwin/fhandler_timerfd.cc index 8d3085692..33829edac 100644 --- a/winsup/cygwin/fhandler_timerfd.cc +++ b/winsup/cygwin/fhandler_timerfd.cc @@ -322,8 +322,6 @@ extern "C" int timerfd_settime (int fd_in, int flags, const struct itimerspec *value, struct itimerspec *ovalue) { - /* TODO: There's no easy way to implement TFD_TIMER_CANCEL_ON_SET, - but we should at least accept the flag. */ if ((flags & ~(TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET)) != 0) { set_errno (EINVAL); diff --git a/winsup/cygwin/timerfd.cc b/winsup/cygwin/timerfd.cc index 145f3a665..ae26004a4 100644 --- a/winsup/cygwin/timerfd.cc +++ b/winsup/cygwin/timerfd.cc @@ -36,6 +36,7 @@ timerfd_tracker::thread_func () } /* Inner loop: Timer expired? If not, wait for it. */ + /* TODO: TFD_TIMER_CANCEL_ON_SET */ HANDLE expired[3] = { tfd_shared->timer (), tfd_shared->disarm_evt (), cancel_evt }; @@ -359,16 +360,21 @@ repeat: { ret = read_and_reset_overrun_count (); leave_critical_section (); - if (ret) - break; - /* A 0 overrun count indicates another read was quicker. - Continue as if we didn't catch the expiry. */ - if (!nonblocking) + switch (ret) { - Sleep (100L); - goto repeat; + case -1: /* TFD_TIMER_CANCEL_ON_SET */ + ret = -ECANCELED; + break; + case 0: /* Another read was quicker. */ + if (!nonblocking) + goto repeat; + ret = -EAGAIN; + break; + default: /* Return (positive) overrun count. */ + if (ret < 0) + ret = INT64_MAX; + break; } - ret = -EAGAIN; } break; case WAIT_OBJECT_0 + 1: /* signal */