diff --git a/exec/cnex/CMakeLists.txt b/exec/cnex/CMakeLists.txt index e869f63e1..ad25beec0 100644 --- a/exec/cnex/CMakeLists.txt +++ b/exec/cnex/CMakeLists.txt @@ -22,6 +22,13 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") lib/runtime_posix.c ) elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") + # Not all flavors of Linx will have the function clock_gettime(), and some have it in a different include. + # See exec/cnex/lib/time_linux.c for more information. + include(CheckSymbolExists) + check_symbol_exists(clock_gettime "time.h;sys/time.h" HAVE_CLOCK_GETTIME) + if(HAVE_CLOCK_GETTIME) + add_definitions(-DHAVE_CLOCK_GETTIME) + endif() set(platform_cnex rtl_posix.c lib/file_posix.c diff --git a/exec/cnex/lib/time_linux.c b/exec/cnex/lib/time_linux.c index fc3cbb583..94db80bbe 100644 --- a/exec/cnex/lib/time_linux.c +++ b/exec/cnex/lib/time_linux.c @@ -1,6 +1,10 @@ #define _POSIX_C_SOURCE 200809L #include +#ifdef HAVE_CLOCK_GETTIME #include +#else +#include +#endif #include "cell.h" #include "exec.h" @@ -9,17 +13,30 @@ static Number NANOSECONDS_PER_SECOND; +static Number MICROSECONDS_PER_SECOND; void time_initModule() { NANOSECONDS_PER_SECOND = number_from_uint64(1000000000LL); + MICROSECONDS_PER_SECOND = number_from_uint64(1000000LL); } void time_tick(TExecutor *exec) { +#ifdef HAVE_CLOCK_GETTIME struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); push(exec->stack, cell_fromNumber(number_add(number_from_uint64(ts.tv_sec), number_divide(number_from_uint64(ts.tv_nsec), NANOSECONDS_PER_SECOND)))); +#else + // Not all Linux distros will have clock_gettime(), so we'll resort to gettimeofday() in those cases. Note the difference between + // between timespec and timeval structures as well; where timeval has a tv_usec (Microseconds), vs. tv_nsec (Nanoseconds) member. + // This means we have to divide by 1,000,000, not 1,000,000,000, when using timeval and gettimeofday(). + struct timeval tv; + + gettimeofday(&tv, NULL); + + push(exec->stack, cell_fromNumber(number_add(number_from_uint64(tv.tv_sec), number_divide(number_from_uint64(tv.tv_usec), MICROSECONDS_PER_SECOND)))); +#endif }