summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2019-01-16 18:40:53 +0100
committerCorinna Vinschen <corinna@vinschen.de>2019-01-16 18:40:53 +0100
commit173e067a31bde9812c0f0ad19de082fb5e176427 (patch)
tree749b83ce25bca2e288c35c2df9d294f4257a694f
parent0e8c7b8689d18b75371ee3411a3ac68ed37fa3ef (diff)
downloadcygnal-173e067a31bde9812c0f0ad19de082fb5e176427.tar.gz
cygnal-173e067a31bde9812c0f0ad19de082fb5e176427.tar.bz2
cygnal-173e067a31bde9812c0f0ad19de082fb5e176427.zip
Cygwin: timerfd: implement TFD_IOC_SET_TICKS ioctl
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
-rw-r--r--winsup/cygwin/fhandler_timerfd.cc18
-rw-r--r--winsup/cygwin/timer.cc16
-rw-r--r--winsup/cygwin/timer.h2
3 files changed, 34 insertions, 2 deletions
diff --git a/winsup/cygwin/fhandler_timerfd.cc b/winsup/cygwin/fhandler_timerfd.cc
index cbcbefdcb..360731ca1 100644
--- a/winsup/cygwin/fhandler_timerfd.cc
+++ b/winsup/cygwin/fhandler_timerfd.cc
@@ -176,15 +176,29 @@ int
fhandler_timerfd::ioctl (unsigned int cmd, void *p)
{
int ret = -1;
+ uint64_t ov_cnt;
switch (cmd)
{
case TFD_IOC_SET_TICKS:
- /* TODO */
+ __try
+ {
+ timer_tracker *tt = (timer_tracker *) timerid;
+
+ ov_cnt = *(uint64_t *) p;
+ if (!ov_cnt)
+ {
+ set_errno (EINVAL);
+ break;
+ }
+ tt->set_event (ov_cnt);
+ }
+ __except (EFAULT) {}
+ __endtry
ret = 0;
break;
default:
- set_errno (EINVAL);
+ ret = fhandler_base::ioctl (cmd, p);
break;
}
syscall_printf ("%d = ioctl_timerfd(%x, %p)", ret, cmd, p);
diff --git a/winsup/cygwin/timer.cc b/winsup/cygwin/timer.cc
index be3fcf7c5..c97274538 100644
--- a/winsup/cygwin/timer.cc
+++ b/winsup/cygwin/timer.cc
@@ -132,6 +132,22 @@ timer_tracker::arm_event ()
return ret;
}
+void
+timer_tracker::set_event (uint64_t ov_cnt)
+{
+ LONG ret;
+
+ while ((ret = InterlockedCompareExchange (&event_running, EVENT_LOCK,
+ EVENT_DISARMED)) == EVENT_LOCK)
+ yield ();
+ InterlockedExchange64 (&overrun_count, ov_cnt);
+ if (ret == EVENT_DISARMED)
+ {
+ SetEvent (get_timerfd_handle ());
+ InterlockedExchange (&event_running, EVENT_ARMED);
+ }
+}
+
LONG64
timer_tracker::_disarm_event ()
{
diff --git a/winsup/cygwin/timer.h b/winsup/cygwin/timer.h
index 3b426a308..b9a072e6d 100644
--- a/winsup/cygwin/timer.h
+++ b/winsup/cygwin/timer.h
@@ -55,7 +55,9 @@ class timer_tracker
void gettime (itimerspec *);
int settime (int, const itimerspec *, itimerspec *);
+
LONG arm_event ();
+ void set_event (uint64_t ov_cnt);
unsigned int disarm_event ();
DWORD thread_func ();