Skip to content

Commit 4ac1e9b

Browse files
sofarShadowNinja
authored andcommittedJan 29, 2016
Clocksource: use a better clock if available.
clock_gettime() is a far better clock than gettimeofday(). Even better than clock_gettime() is that you can select either CLOCK_MONOTONIC, or even CLOCK_MONOTONIC_RAW. These clocks offer high precision time. And the _RAW variant will never roll back due to NTP drift or daylight savings, or otherwise. I've adjusted this code to select the right clock method auto- matically based on what's available in the OS. This means that if you're running a very old linux version, MacOS or other, you will automatically get the best clocksource available. I've tested all Linux clocksources by selectively compiling and running a 10k+ timer test suite. In all cases I confirmed that the 3 POSIX Linux clocksources worked properly, and were selected properly. I've modified the OS X compile path to use the high-res clock source for all time functions, but I can't confirm it works or that it compiles. As for WIN32, I confirmed that the used clocksource is indeed a Monotonic clocksource, so good news: that code section appears to be exactly what it should be.
1 parent 860d70b commit 4ac1e9b

File tree

2 files changed

+35
-22
lines changed

2 files changed

+35
-22
lines changed
 

Diff for: ‎doc/lua_api.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1727,7 +1727,7 @@ Helper functions
17271727
* `minetest.is_yes(arg)`
17281728
* returns whether `arg` can be interpreted as yes
17291729
* `minetest.get_us_time()`
1730-
* returns time with microsecond precision
1730+
* returns time with microsecond precision. May not return wall time.
17311731
* `table.copy(table)`: returns a table
17321732
* returns a deep copy of `table`
17331733

Diff for: ‎src/porting.h

+34-21
Original file line numberDiff line numberDiff line change
@@ -211,43 +211,56 @@ void initIrrlicht(irr::IrrlichtDevice * );
211211
}
212212

213213
#else // Posix
214-
215-
inline u32 getTimeS()
214+
inline void _os_get_clock(struct timespec *ts)
216215
{
216+
#if defined(__MACH__) && defined(__APPLE__)
217+
// from http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
218+
// OS X does not have clock_gettime, use clock_get_time
219+
clock_serv_t cclock;
220+
mach_timespec_t mts;
221+
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
222+
clock_get_time(cclock, &mts);
223+
mach_port_deallocate(mach_task_self(), cclock);
224+
ts.tv_sec = mts.tv_sec;
225+
ts.tv_nsec = mts.tv_nsec;
226+
#elif defined(CLOCK_MONOTONIC_RAW)
227+
clock_gettime(CLOCK_MONOTONIC_RAW, ts);
228+
#elif defined(_POSIX_MONOTONIC_CLOCK)
229+
clock_gettime(CLOCK_MONOTONIC, ts);
230+
#else
217231
struct timeval tv;
218232
gettimeofday(&tv, NULL);
219-
return tv.tv_sec;
233+
TIMEVAL_TO_TIMESPEC(&tv, ts);
234+
#endif // defined(__MACH__) && defined(__APPLE__)
235+
}
236+
237+
// Note: these clock functions do not return wall time, but
238+
// generally a clock that starts at 0 when the process starts.
239+
inline u32 getTimeS()
240+
{
241+
struct timespec ts;
242+
_os_get_clock(&ts);
243+
return ts.tv_sec;
220244
}
221245

222246
inline u32 getTimeMs()
223247
{
224-
struct timeval tv;
225-
gettimeofday(&tv, NULL);
226-
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
248+
struct timespec ts;
249+
_os_get_clock(&ts);
250+
return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
227251
}
228252

229253
inline u32 getTimeUs()
230254
{
231-
struct timeval tv;
232-
gettimeofday(&tv, NULL);
233-
return tv.tv_sec * 1000000 + tv.tv_usec;
255+
struct timespec ts;
256+
_os_get_clock(&ts);
257+
return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
234258
}
235259

236260
inline u32 getTimeNs()
237261
{
238262
struct timespec ts;
239-
// from http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
240-
#if defined(__MACH__) && defined(__APPLE__) // OS X does not have clock_gettime, use clock_get_time
241-
clock_serv_t cclock;
242-
mach_timespec_t mts;
243-
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
244-
clock_get_time(cclock, &mts);
245-
mach_port_deallocate(mach_task_self(), cclock);
246-
ts.tv_sec = mts.tv_sec;
247-
ts.tv_nsec = mts.tv_nsec;
248-
#else
249-
clock_gettime(CLOCK_REALTIME, &ts);
250-
#endif
263+
_os_get_clock(&ts);
251264
return ts.tv_sec * 1000000000 + ts.tv_nsec;
252265
}
253266

0 commit comments

Comments
 (0)
Please sign in to comment.