barbieri pushed a commit to branch master.

commit ca39ff976e576dd917becf989f28fdf149c9f1d0
Author: Gustavo Sverzut Barbieri <[email protected]>
Date:   Fri Aug 9 00:02:04 2013 -0300

    ecore: detect and emit event on system time changed.
    
    If we have timerfd then we can set a timer with special features
    (ABSTIME | CANCELON) to be notified if its offset to monotonic time
    change, effectively this will alert us if user called settimeofday()
    or similar method to change system time.
    
    This code was inspired by Enlightenment's clock module.
---
 src/lib/ecore/ecore_main.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c
index 0500052..3a6210d 100644
--- a/src/lib/ecore/ecore_main.c
+++ b/src/lib/ecore/ecore_main.c
@@ -127,6 +127,13 @@ epoll_ctl(int                 epfd EINA_UNUSED,
 # endif
 #endif /* HAVE_SYS_TIMERFD_H */
 
+#ifndef TFD_TIMER_ABSTIME
+# define TFD_TIMER_ABSTIME (1 << 0)
+#endif
+#ifndef TFD_TIMER_CANCELON_SET
+# define TFD_TIMER_CANCELON_SET (1 << 1)
+#endif
+
 #ifndef HAVE_TIMERFD_CREATE
 static inline int
 timerfd_create(int clockid EINA_UNUSED,
@@ -763,6 +770,67 @@ static GSourceFuncs ecore_gsource_funcs =
 
 #endif
 
+#ifdef HAVE_SYS_TIMERFD_H
+static int realtime_fd = -1;
+
+static void detect_time_changes_start(void);
+static Eina_Bool
+_realtime_update(void *data EINA_UNUSED, Ecore_Fd_Handler *fdh EINA_UNUSED)
+{
+   char buf[64];
+
+   if (read(realtime_fd, buf, sizeof(buf)) >= 0) return EINA_TRUE;
+
+   DBG("system clock changed");
+   ecore_event_add(ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED, NULL, NULL, NULL);
+
+   close(realtime_fd);
+   realtime_fd = -1;
+   detect_time_changes_start();
+   return EINA_FALSE;
+}
+#endif
+
+static void
+detect_time_changes_start(void)
+{
+#ifdef HAVE_SYS_TIMERFD_H
+   struct itimerspec its;
+
+   if (realtime_fd >= 0) return;
+
+   realtime_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);
+   if (realtime_fd < 0) return;
+
+   memset(&its, 0, sizeof(its));
+   if (timerfd_settime(realtime_fd,
+                       TFD_TIMER_ABSTIME | TFD_TIMER_CANCELON_SET,
+                       &its, NULL) < 0)
+     {
+        WRN("Couldn't arm timerfd to detect clock changes: %s",
+            strerror(errno));
+        close(realtime_fd);
+        realtime_fd = -1;
+        return;
+     }
+
+   ecore_main_fd_handler_add(realtime_fd, ECORE_FD_READ,
+                             _realtime_update, NULL, NULL, NULL);
+#endif
+}
+
+static void
+detect_time_changes_stop(void)
+{
+#ifdef HAVE_SYS_TIMERFD_H
+   if (realtime_fd > 0)
+     {
+        close(realtime_fd);
+        realtime_fd = -1;
+     }
+#endif
+}
+
 void
 _ecore_main_loop_init(void)
 {
@@ -818,6 +886,8 @@ _ecore_main_loop_init(void)
           CRIT("Failed to attach glib source to default context");
      }
 #endif
+
+   detect_time_changes_start();
 }
 
 void
@@ -831,6 +901,8 @@ _ecore_main_loop_shutdown(void)
      }
 #endif
 
+   detect_time_changes_stop();
+
    if (epoll_fd >= 0)
      {
         close(epoll_fd);

-- 

------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite!
It's a free troubleshooting tool designed for production.
Get down to code-level detail for bottlenecks, with <2% overhead. 
Download for free and get started troubleshooting in minutes. 
http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk

Reply via email to