Hello all,

As we all know ecore uses gettimeofday() to retrieve the time and
schedule timeouts. Our own code in ecore and even elementary just use
relative times, and we often have to resort to hacks to detect when
timezone changes or user sets time.

In order to solve this problem there is an API called clock_gettime()
that may receive a parameter CLOCK_MONOTONIC. The origin is not
guaranteed (often it is implemented as 0 = machine boot), but it does
guarantee time does not go back.

Raster says that ecore_time_get() and ecore_loop_time_get() are not
supposed to return the unix epoch, although the implementation and
thus the documentation said so... that lead people to use it as such
(a quick grep in svn shows people often save this value to know
timestamps... which is quite wrong).

So we can fix it in 3 ways:

   1. apply the attached patch that turns
ecore_time_get()/ecore_loop_time_get() into monotonic, change
occurrences of ecore_time_get()/ecore_loop_time_get() to be
ecore_unix_time_get() (actually in some places they must be changed to
something else, like gmtime or localtime)

   2. create a new patch that introduces ecore_monotonic_time_get()
and uses that from inside ecore_main.c

   3. change the attached patch to at start do a gettimeofday() and
register the time difference, then always consider that difference. it
would be monotonic but with Epoch as reference... this may be
extremely buggy if the system has a bad battery and clock is just set
by ntp after your efl program is running.

1 is more correct, but maybe too close to 1.0 release to get it, so
although I did the patch I may introduce the way I said in 2...

comments? suggestions?

PS: later on I'll provide a patch to ask for a system timer resolution
and probably change poller to behave better wrt wakeups.

-- 
Gustavo Sverzut Barbieri
http://profusion.mobi embedded systems
--------------------------------------
MSN: barbi...@gmail.com
Skype: gsbarbieri
Mobile: +55 (19) 9225-2202
Index: src/lib/ecore/Ecore.h
===================================================================
--- src/lib/ecore/Ecore.h	(revision 52524)
+++ src/lib/ecore/Ecore.h	(working copy)
@@ -445,6 +445,7 @@
 
 
    EAPI double ecore_time_get(void);
+   EAPI double ecore_unix_time_get(void);
    EAPI double ecore_loop_time_get(void);
 
    EAPI Ecore_Timer *ecore_timer_add(double in, Ecore_Task_Cb func, const void *data);
Index: src/lib/ecore/ecore_time.c
===================================================================
--- src/lib/ecore/ecore_time.c	(revision 52524)
+++ src/lib/ecore/ecore_time.c	(working copy)
@@ -15,21 +15,79 @@
 #include "Ecore.h"
 #include "ecore_private.h"
 
+#include <time.h>
 
-
-/* FIXME: clock_gettime() is an option... */
-
 /**
  * Retrieves the current system time as a floating point value in seconds.
  *
+ * This uses a monotonic clock and thus never goes back in time while
+ * machine is live (even if user changes time or timezone changes,
+ * however it may be reset whenever the machine is restarted).
+ *
  * Also see ecore_loop_time_get().
  *
- * @return  The number of seconds since 12.00AM 1st January 1970.
+ * @return The number of seconds. Start time is not defined (it may be
+ *         when the machine was booted, unix time, etc), all it is
+ *         defined is that it never goes backwards.
  * @ingroup Ecore_Time_Group
  */
 EAPI double
 ecore_time_get(void)
 {
+#if HAVE_CLOCK_GETTIME
+   struct timespec t;
+   static clockid_t clk_id = -1;
+
+   if (clk_id == -1) {
+      clk_id = CLOCK_MONOTONIC;
+      if (clock_gettime(clk_id, &t) == 0)
+        {
+           DBG("using CLOCK_MONOTONIC");
+           goto end;
+        }
+      clk_id = CLOCK_REALTIME; /* may go backwards */
+      if (clock_gettime(clk_id, &t) == 0)
+        {
+           WRN("using CLOCK_REALTIME");
+           goto end;
+        }
+
+      CRIT("cannot get a valid clock_gettime() clock id! "
+           "Fallback to unix time.");
+      goto fallback;
+   } else if (clk_id == -2)
+     goto fallback;
+
+   if (clock_gettime(clk_id, &t) < 0)
+     {
+        CRIT("cannot use clock_gettime(%d) anymore! "
+             "Fallback to unix time.", clk_id);
+        goto fallback;
+     }
+
+ end:
+   return (double)t.tv_sec + (((double)t.tv_nsec) / 1000000000.0);
+ fallback:
+   clk_id = -2;
+   return ecore_unix_time_get();
+
+#else
+# warning "Your platform isn't supported yet"
+   return ecore_unix_time_get();
+#endif
+}
+
+/**
+ * Retrieves the current UNIX time as a floating point value in seconds.
+ *
+ * Also see ecore_time_get().
+ *
+ * @return  The number of seconds since 12.00AM 1st January 1970.
+ * @ingroup Ecore_Time_Group
+ */
+EAPI double
+ecore_unix_time_get(void)
+{
 #ifdef HAVE_EVIL
   return evil_time_get();
 #else
Index: src/lib/ecore/Makefile.am
===================================================================
--- src/lib/ecore/Makefile.am	(revision 52524)
+++ src/lib/ecore/Makefile.am	(working copy)
@@ -45,7 +45,7 @@
 
 endif
 
-libecore_la_LIBADD = @dlopen_libs@ @EINA_LIBS@ @EVIL_LIBS@ @GLIB_LIBS@ @WIN32_LIBS@ @LTLIBINTL@ @EFL_PTHREAD_LIBS@ -lm
+libecore_la_LIBADD = @dlopen_libs@ @EINA_LIBS@ @EVIL_LIBS@ @GLIB_LIBS@ @WIN32_LIBS@ @LTLIBINTL@ @EFL_PTHREAD_LIBS@ @rt_libs@ -lm
 libecore_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@
 
 EXTRA_DIST = ecore_private.h
Index: configure.ac
===================================================================
--- configure.ac	(revision 52524)
+++ configure.ac	(working copy)
@@ -401,18 +401,30 @@
    mingw32ce* | cegcc*)
       WIN32_LIBS="-lws2"
       dlopen_libs="-ldl"
+      rt_libs="-lrt"
       ;;
    mingw*)
       WIN32_LIBS="-lws2_32"
       dlopen_libs="-ldl"
+      rt_libs="-lrt"
       ;;
    *)
       AC_CHECK_LIB(dl, dlopen, dlopen_libs=-ldl)
+      AC_CHECK_LIB(rt, clock_gettime, rt_libs=-lrt)
       ;;
 esac
 AC_SUBST(WIN32_LIBS)
 AC_SUBST(dlopen_libs)
+AC_SUBST(rt_libs)
 
+if test -n "$rt_libs"; then
+   _bkp_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $rt_libs"
+   AC_CHECK_FUNCS(clock_gettime)
+   LDFLAGS="$_bkp_LDFLAGS"
+   unset "$_bkp_LDFLAGS"
+fi
+
 # Eina library
 
 PKG_CHECK_MODULES(EINA, [eina >= 1.0.0])
------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing.
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to