aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto.def2
-rw-r--r--jim-eventloop.c79
2 files changed, 48 insertions, 33 deletions
diff --git a/auto.def b/auto.def
index 61382ef..4b454be 100644
--- a/auto.def
+++ b/auto.def
@@ -114,7 +114,7 @@ cc-check-functions geteuid mkstemp realpath isatty
cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist isascii
cc-check-functions syslog opendir readlink sleep usleep pipe getaddrinfo utimes
cc-check-functions shutdown socketpair isinf isnan link symlink fsync dup umask
-cc-check-functions localtime gmtime strptime timegm
+cc-check-functions localtime gmtime strptime timegm clock_gettime
if {[cc-check-function-in-lib backtrace execinfo]} {
define-append LDLIBS [get-define lib_backtrace]
diff --git a/jim-eventloop.c b/jim-eventloop.c
index 1b1de47..cea5d9e 100644
--- a/jim-eventloop.c
+++ b/jim-eventloop.c
@@ -54,20 +54,19 @@
#if defined(__MINGW32__)
#include <windows.h>
#include <winsock.h>
-#define msleep Sleep
+#define usleep(US) Sleep((US) / 1000)
+#define HAVE_USLEEP
#else
#include <sys/types.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
+#endif
#ifndef HAVE_USLEEP
/* XXX: Implement this in terms of select() or nanosleep() */
-#define msleep(MS) sleep((MS) / 1000)
+#define usleep(US) sleep((US) / 1000000)
#warning "sub-second sleep not supported"
-#else
-#define msleep(MS) sleep((MS) / 1000); usleep(((MS) % 1000) * 1000);
-#endif
#endif
/* --- */
@@ -87,8 +86,8 @@ typedef struct Jim_FileEvent
typedef struct Jim_TimeEvent
{
jim_wide id; /* time event identifier. */
- long initialms; /* initial relative timer value */
- jim_wide when; /* milliseconds */
+ jim_wide initialus; /* initial relative timer value in microseconds */
+ jim_wide when; /* microseconds */
Jim_TimeProc *timeProc;
Jim_EventFinalizerProc *finalizerProc;
void *clientData;
@@ -189,28 +188,43 @@ void Jim_DeleteFileHandler(Jim_Interp *interp, int fd, int mask)
}
/**
- * Returns the time since interp creation in milliseconds.
+ * Returns the time since interp creation in microseconds.
*/
-static jim_wide JimGetTime(Jim_EventLoop *eventLoop)
+static jim_wide JimGetTimeUsec(Jim_EventLoop *eventLoop)
{
+ long long now;
struct timeval tv;
- gettimeofday(&tv, NULL);
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC_RAW)
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) == 0) {
+ now = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000;
+ }
+ else
+#endif
+ {
+ gettimeofday(&tv, NULL);
+
+ now = tv.tv_sec * 1000000LL + tv.tv_usec;
+ }
- return (jim_wide)(tv.tv_sec - eventLoop->timeBase) * 1000 + tv.tv_usec / 1000;
+ return now - eventLoop->timeBase;
}
-jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide milliseconds,
+jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide us,
Jim_TimeProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc)
{
Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
jim_wide id = ++eventLoop->timeEventNextId;
Jim_TimeEvent *te, *e, *prev;
+ printf("Create time handler, us=%lld, now=%lld\n", us, JimGetTimeUsec(eventLoop));
+
te = Jim_Alloc(sizeof(*te));
te->id = id;
- te->initialms = milliseconds;
- te->when = JimGetTime(eventLoop) + milliseconds;
+ te->initialus = us;
+ te->when = JimGetTimeUsec(eventLoop) + us;
te->timeProc = proc;
te->finalizerProc = finalizerProc;
te->clientData = clientData;
@@ -311,7 +325,7 @@ jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id)
if (te) {
jim_wide remain;
- remain = te->when - JimGetTime(eventLoop);
+ remain = te->when - JimGetTimeUsec(eventLoop);
remain = (remain < 0) ? 0 : remain;
Jim_FreeTimeHandler(interp, te);
@@ -338,7 +352,7 @@ jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id)
*/
int Jim_ProcessEvents(Jim_Interp *interp, int flags)
{
- jim_wide sleep_ms = -1;
+ jim_wide sleep_us = -1;
int processed = 0;
Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
Jim_FileEvent *fe = eventLoop->fileEventHead;
@@ -360,7 +374,7 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
if (flags & JIM_DONT_WAIT) {
/* Wait no time */
- sleep_ms = 0;
+ sleep_us = 0;
}
else if (flags & JIM_TIME_EVENTS) {
/* The nearest timer is always at the head of the list */
@@ -369,14 +383,14 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
/* Calculate the time missing for the nearest
* timer to fire. */
- sleep_ms = shortest->when - JimGetTime(eventLoop);
- if (sleep_ms < 0) {
- sleep_ms = 0;
+ sleep_us = shortest->when - JimGetTimeUsec(eventLoop);
+ if (sleep_us < 0) {
+ sleep_us = 0;
}
}
else {
/* Wait forever */
- sleep_ms = -1;
+ sleep_us = -1;
}
}
@@ -404,10 +418,10 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
fe = fe->next;
}
- if (sleep_ms >= 0) {
+ if (sleep_us >= 0) {
tvp = &tv;
- tvp->tv_sec = sleep_ms / 1000;
- tvp->tv_usec = 1000 * (sleep_ms % 1000);
+ tvp->tv_sec = sleep_us / 1000000;
+ tvp->tv_usec = sleep_us % 1000000;
}
retval = select(maxfd + 1, &rfds, &wfds, &efds, tvp);
@@ -456,8 +470,8 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
}
}
#else
- if (sleep_ms > 0) {
- msleep(sleep_ms);
+ if (sleep_us > 0) {
+ usleep(sleep_us);
}
#endif
@@ -471,7 +485,7 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
te = te->next;
continue;
}
- if (JimGetTime(eventLoop) >= te->when) {
+ if (JimGetTimeUsec(eventLoop) >= te->when) {
id = te->id;
/* Remove from the list before executing */
Jim_RemoveTimeHandler(eventLoop, id);
@@ -616,7 +630,8 @@ static void JimAfterTimeEventFinalizer(Jim_Interp *interp, void *clientData)
static int JimELAfterCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_EventLoop *eventLoop = Jim_CmdPrivData(interp);
- jim_wide ms = 0, id;
+ double ms;
+ jim_wide id;
Jim_Obj *objPtr, *idObjPtr;
static const char * const options[] = {
"cancel", "info", "idle", NULL
@@ -629,7 +644,7 @@ static int JimELAfterCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_WrongNumArgs(interp, 1, argv, "option ?arg ...?");
return JIM_ERR;
}
- if (Jim_GetWide(interp, argv[1], &ms) != JIM_OK) {
+ if (Jim_GetDouble(interp, argv[1], &ms) != JIM_OK) {
if (Jim_GetEnum(interp, argv[1], options, &option, "argument", JIM_ERRMSG) != JIM_OK) {
return JIM_ERR;
}
@@ -637,7 +652,7 @@ static int JimELAfterCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
else if (argc == 2) {
/* Simply a sleep */
- msleep(ms);
+ usleep(ms * 1000);
return JIM_OK;
}
@@ -651,7 +666,7 @@ static int JimELAfterCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
case AFTER_CREATE: {
Jim_Obj *scriptObj = Jim_ConcatObj(interp, argc - 2, argv + 2);
Jim_IncrRefCount(scriptObj);
- id = Jim_CreateTimeHandler(interp, ms, JimAfterTimeHandler, scriptObj,
+ id = Jim_CreateTimeHandler(interp, (jim_wide)(ms * 1000), JimAfterTimeHandler, scriptObj,
JimAfterTimeEventFinalizer);
objPtr = Jim_NewStringObj(interp, NULL, 0);
Jim_AppendString(interp, objPtr, "after#", -1);
@@ -709,7 +724,7 @@ static int JimELAfterCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (e && e->timeProc == JimAfterTimeHandler) {
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
Jim_ListAppendElement(interp, listObj, e->clientData);
- Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, e->initialms ? "timer" : "idle", -1));
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, e->initialus ? "timer" : "idle", -1));
Jim_SetResult(interp, listObj);
return JIM_OK;
}