Skip to content

Commit 31735b8

Browse files
committed
clock millis, time: now use monotonic raw time if possible
Instead of using all time, these commands now use a monotonically increasing system timer so that they are not affected by time (e.g. ntp) adjustments. (But not on Windows since it doesn't work reliably) Fixes #240 Signed-off-by: Steve Bennett <[email protected]> not on widnows
1 parent 94fc343 commit 31735b8

File tree

5 files changed

+60
-58
lines changed

5 files changed

+60
-58
lines changed

auto.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ cc-check-functions geteuid mkstemp isatty
247247
cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist isascii
248248
cc-check-functions syslog opendir readlink sleep usleep pipe getaddrinfo utimes
249249
cc-check-functions shutdown socketpair link symlink fsync dup umask
250-
cc-check-functions localtime gmtime strptime clock_gettime
250+
cc-check-functions localtime gmtime strptime
251251
if {![cc-check-functions realpath]} {
252252
cc-check-functions _fullpath
253253
}
@@ -530,6 +530,9 @@ if {[have-feature windows]} {
530530
set buildjimext 0
531531
}
532532
}
533+
} else {
534+
# We don't trust any version of clock_gettime on windows
535+
cc-check-functions clock_gettime
533536
}
534537
if {[have-feature termios.h]} {
535538
lappend extra_objs jim-tty.o

jim-clock.c

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -151,37 +151,32 @@ static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
151151

152152
static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
153153
{
154-
Jim_SetResultInt(interp, time(NULL));
154+
Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_REALTIME) / 1000000);
155+
return JIM_OK;
156+
}
155157

158+
static int clock_cmd_clicks(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
159+
{
160+
Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW));
156161
return JIM_OK;
157162
}
158163

159164
static int clock_cmd_micros(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
160165
{
161-
struct timeval tv;
162-
163-
gettimeofday(&tv, NULL);
164-
165-
Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec);
166-
166+
Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_REALTIME));
167167
return JIM_OK;
168168
}
169169

170170
static int clock_cmd_millis(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
171171
{
172-
struct timeval tv;
173-
174-
gettimeofday(&tv, NULL);
175-
176-
Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000 + tv.tv_usec / 1000);
177-
172+
Jim_SetResultInt(interp, Jim_GetTimeUsec(CLOCK_REALTIME) / 1000);
178173
return JIM_OK;
179174
}
180175

181176
static const jim_subcmd_type clock_command_table[] = {
182177
{ "clicks",
183178
NULL,
184-
clock_cmd_micros,
179+
clock_cmd_clicks,
185180
0,
186181
0,
187182
/* Description: Returns the current time in 'clicks' */

jim-eventloop.c

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -237,32 +237,6 @@ void Jim_DeleteFileHandler(Jim_Interp *interp, int fd, int mask)
237237
}
238238
}
239239

240-
/**
241-
* Returns the time of day in microseconds.
242-
* (the time base is not relevant here)
243-
*/
244-
static jim_wide JimGetTimeUsec(Jim_EventLoop *eventLoop)
245-
{
246-
long long now;
247-
struct timeval tv;
248-
249-
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC_RAW)
250-
struct timespec ts;
251-
252-
if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) == 0) {
253-
now = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000;
254-
}
255-
else
256-
#endif
257-
{
258-
gettimeofday(&tv, NULL);
259-
260-
now = tv.tv_sec * 1000000LL + tv.tv_usec;
261-
}
262-
263-
return now;
264-
}
265-
266240
jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide us,
267241
Jim_TimeProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc)
268242
{
@@ -273,7 +247,7 @@ jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide us,
273247
te = Jim_Alloc(sizeof(*te));
274248
te->id = id;
275249
te->initialus = us;
276-
te->when = JimGetTimeUsec(eventLoop) + us;
250+
te->when = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) + us;
277251
te->timeProc = proc;
278252
te->finalizerProc = finalizerProc;
279253
te->clientData = clientData;
@@ -374,7 +348,7 @@ jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id)
374348
if (te) {
375349
jim_wide remain;
376350

377-
remain = te->when - JimGetTimeUsec(eventLoop);
351+
remain = te->when - Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
378352
remain = (remain < 0) ? 0 : remain;
379353

380354
Jim_FreeTimeHandler(interp, te);
@@ -432,7 +406,7 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
432406

433407
/* Calculate the time missing for the nearest
434408
* timer to fire. */
435-
sleep_us = shortest->when - JimGetTimeUsec(eventLoop);
409+
sleep_us = shortest->when - Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
436410
if (sleep_us < 0) {
437411
sleep_us = 0;
438412
}
@@ -534,7 +508,7 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
534508
te = te->next;
535509
continue;
536510
}
537-
if (JimGetTimeUsec(eventLoop) >= te->when) {
511+
if (Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) >= te->when) {
538512
id = te->id;
539513
/* Remove from the list before executing */
540514
Jim_RemoveTimeHandler(eventLoop, id);

jim.c

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -694,15 +694,35 @@ char *Jim_StrDupLen(const char *s, int l)
694694
* Time related functions
695695
* ---------------------------------------------------------------------------*/
696696

697-
/* Returns current time in microseconds */
698-
static jim_wide JimClock(void)
697+
/* Returns current time in microseconds
698+
* CLOCK_MONOTONIC (monotonic clock that is affected by time adjustments)
699+
* CLOCK_MONOTONIC_RAW (monotonic clock that is not affected by time adjustments)
700+
* CLOCK_REALTIME (wall time)
701+
*/
702+
jim_wide Jim_GetTimeUsec(unsigned type)
699703
{
704+
long long now;
700705
struct timeval tv;
701706

702-
gettimeofday(&tv, NULL);
703-
return (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec;
707+
#if defined(HAVE_CLOCK_GETTIME)
708+
struct timespec ts;
709+
710+
if (clock_gettime(type, &ts) == 0) {
711+
now = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000;
712+
}
713+
else
714+
#endif
715+
{
716+
gettimeofday(&tv, NULL);
717+
718+
now = tv.tv_sec * 1000000LL + tv.tv_usec;
719+
}
720+
721+
return now;
704722
}
705723

724+
725+
706726
/* -----------------------------------------------------------------------------
707727
* Hash Tables
708728
* ---------------------------------------------------------------------------*/
@@ -5614,7 +5634,7 @@ int Jim_Collect(Jim_Interp *interp)
56145634
}
56155635
Jim_FreeHashTable(&marks);
56165636
interp->lastCollectId = interp->referenceNextId;
5617-
interp->lastCollectTime = JimClock();
5637+
interp->lastCollectTime = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
56185638
return collected;
56195639
}
56205640

@@ -5627,7 +5647,7 @@ void Jim_CollectIfNeeded(Jim_Interp *interp)
56275647
jim_wide elapsedTime;
56285648

56295649
elapsedId = interp->referenceNextId - interp->lastCollectId;
5630-
elapsedTime = JimClock() - interp->lastCollectTime;
5650+
elapsedTime = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) - interp->lastCollectTime;
56315651

56325652

56335653
if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) {
@@ -5658,7 +5678,7 @@ Jim_Interp *Jim_CreateInterp(void)
56585678

56595679
i->maxCallFrameDepth = JIM_MAX_CALLFRAME_DEPTH;
56605680
i->maxEvalDepth = JIM_MAX_EVAL_DEPTH;
5661-
i->lastCollectTime = JimClock();
5681+
i->lastCollectTime = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
56625682

56635683
/* Note that we can create objects only after the
56645684
* interpreter liveList and freeList pointers are
@@ -14588,7 +14608,7 @@ static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
1458814608
if (count < 0)
1458914609
return JIM_OK;
1459014610
i = count;
14591-
start = JimClock();
14611+
start = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
1459214612
while (i-- > 0) {
1459314613
int retval;
1459414614

@@ -14597,7 +14617,7 @@ static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
1459714617
return retval;
1459814618
}
1459914619
}
14600-
elapsed = JimClock() - start;
14620+
elapsed = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) - start;
1460114621
if (elapsed < count * 10) {
1460214622
Jim_SetResult(interp, Jim_NewDoubleObj(interp, elapsed * 1.0 / count));
1460314623
}
@@ -14633,23 +14653,23 @@ static int Jim_TimeRateCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
1463314653
}
1463414654

1463514655
/* Run until we exceed the time limit */
14636-
start = JimClock();
14656+
start = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
1463714657
count = 0;
1463814658
do {
1463914659
int retval = Jim_EvalObj(interp, argv[1]);
14640-
delta = JimClock() - start;
14660+
delta = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) - start;
1464114661
if (retval != JIM_OK) {
1464214662
return retval;
1464314663
}
1464414664
count++;
1464514665
} while (delta < us);
1464614666

1464714667
/* Now try to account for the loop and eval overhead */
14648-
start = JimClock();
14668+
start = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW);
1464914669
n = 0;
1465014670
do {
1465114671
int retval = Jim_EvalObj(interp, interp->nullScriptObj);
14652-
overhead = JimClock() - start;
14672+
overhead = Jim_GetTimeUsec(CLOCK_MONOTONIC_RAW) - start;
1465314673
if (retval != JIM_OK) {
1465414674
return retval;
1465514675
}

jim.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,16 @@ JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
665665
JIM_EXPORT char **Jim_GetEnviron(void);
666666
JIM_EXPORT void Jim_SetEnviron(char **env);
667667
JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file);
668+
#ifndef CLOCK_REALTIME
669+
# define CLOCK_REALTIME 0
670+
#endif
671+
#ifndef CLOCK_MONOTONIC
672+
# define CLOCK_MONOTONIC 1
673+
#endif
674+
#ifndef CLOCK_MONOTONIC_RAW
675+
# define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
676+
#endif
677+
JIM_EXPORT jim_wide Jim_GetTimeUsec(unsigned type);
668678

669679
/* evaluation */
670680
JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);

0 commit comments

Comments
 (0)