1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #define EFL_LOOP_PROTECTED
6 
7 #include <stdlib.h>
8 #include <sys/time.h>
9 
10 #if defined(__APPLE__) && defined(__MACH__)
11 # include <mach/mach_time.h>
12 #endif
13 
14 #include <time.h>
15 
16 #ifdef _WIN32
17 # include <evil_private.h> /* gettimeofday */
18 #endif
19 
20 #include "Ecore.h"
21 #include "ecore_private.h"
22 
23 #if defined(_WIN32)
24 static LONGLONG _ecore_time_freq;
25 #elif defined (HAVE_CLOCK_GETTIME)
26 static clockid_t _ecore_time_clock_id;
27 static Eina_Bool _ecore_time_got_clock_id = EINA_FALSE;
28 #elif defined(__APPLE__) && defined(__MACH__)
29 static double _ecore_time_clock_conversion = 1e-9;
30 #endif
31 
32 EAPI double
ecore_time_get(void)33 ecore_time_get(void)
34 {
35 #ifdef _WIN32
36    LARGE_INTEGER count;
37 
38    QueryPerformanceCounter(&count);
39    return (double)count.QuadPart/ (double)_ecore_time_freq;
40 #elif defined (HAVE_CLOCK_GETTIME)
41    struct timespec t;
42 
43    if (EINA_UNLIKELY(!_ecore_time_got_clock_id))
44      return ecore_time_unix_get();
45 
46    if (EINA_UNLIKELY(clock_gettime(_ecore_time_clock_id, &t)))
47      {
48         CRI("Cannot get current time");
49         return 0.0;
50      }
51 
52    return (double)t.tv_sec + (((double)t.tv_nsec) / 1000000000.0);
53 #elif defined(__APPLE__) && defined(__MACH__)
54    return _ecore_time_clock_conversion * (double)mach_absolute_time();
55 #else
56    return ecore_time_unix_get();
57 #endif
58 }
59 
60 EAPI double
ecore_time_unix_get(void)61 ecore_time_unix_get(void)
62 {
63 #ifdef HAVE_GETTIMEOFDAY
64    struct timeval timev;
65 
66    gettimeofday(&timev, NULL);
67    return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
68 #else
69 # error "Your platform isn't supported yet"
70 #endif
71 }
72 
73 EAPI double
ecore_loop_time_get(void)74 ecore_loop_time_get(void)
75 {
76    return efl_loop_time_get(ML_OBJ);
77 }
78 
79 EAPI void
ecore_loop_time_set(double t)80 ecore_loop_time_set(double t)
81 {
82    efl_loop_time_set(ML_OBJ, t);
83 }
84 
85 /*-********************   Internal methods   ********************************/
86 
87 /* TODO: Documentation says "All  implementations  support  the  system-wide
88  * real-time clock, which is identified by CLOCK_REALTIME. Check if the fallback
89  * to unix time (without specifying the resolution) might be removed
90  */
91 void
_ecore_time_init(void)92 _ecore_time_init(void)
93 {
94 #if defined(_WIN32)
95    LARGE_INTEGER freq;
96 
97    QueryPerformanceFrequency(&freq);
98    _ecore_time_freq = freq.QuadPart;
99 #elif defined(HAVE_CLOCK_GETTIME)
100    struct timespec t;
101 
102    if (_ecore_time_got_clock_id) return;
103 
104    if (!clock_gettime(CLOCK_MONOTONIC, &t))
105      {
106         _ecore_time_clock_id = CLOCK_MONOTONIC;
107         _ecore_time_got_clock_id = EINA_TRUE;
108         DBG("using CLOCK_MONOTONIC");
109      }
110    else if (!clock_gettime(CLOCK_REALTIME, &t))
111      {
112         // may go backwards
113         _ecore_time_clock_id = CLOCK_REALTIME;
114         _ecore_time_got_clock_id = EINA_TRUE;
115         WRN("CLOCK_MONOTONIC not available. Fallback to CLOCK_REALTIME");
116      }
117    else
118      CRI("Cannot get a valid clock_gettime() clock id! Fallback to unix time");
119 #else
120 # if defined(__APPLE__) && defined(__MACH__)
121    mach_timebase_info_data_t info;
122    kern_return_t err = mach_timebase_info(&info);
123    if (err == 0)
124      _ecore_time_clock_conversion = 1e-9 * (double)info.numer / (double)info.denom;
125    else
126      WRN("Unable to get timebase info. Fallback to nanoseconds");
127 # else
128 #  warning "Your platform isn't supported yet"
129    CRI("Platform does not support clock_gettime. Fallback to unix time");
130 # endif
131 #endif
132    ecore_loop_time_set(ecore_time_get());
133 }
134 
135