diff options
-rw-r--r-- | Makefile | 15 | ||||
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | luasystem-0.1.1-0.rockspec | 12 | ||||
-rw-r--r-- | luasystem-scm-0.rockspec | 12 | ||||
-rw-r--r-- | spec/time_spec.lua | 11 | ||||
-rw-r--r-- | src/Makefile | 26 | ||||
-rw-r--r-- | src/time.c | 40 | ||||
-rw-r--r-- | src/time_osx.h | 66 |
8 files changed, 173 insertions, 10 deletions
@@ -7,6 +7,21 @@ # install-all install for lua51 lua52 lua53 # print print the build settings +ifeq ($(origin PLAT),undefined) +UNAME_S:=$(shell uname -s) +ifeq ($(UNAME_S),Linux) + PLAT=linux +endif +ifeq ($(UNAME_S),Darwin) + PLAT=macosx +endif +ifeq ($(UNAME_S),FreeBSD) + PLAT=freebsd +endif +ifeq ($(patsubst MINGW%,MINGW,$(UNAME_S)),MINGW) + PLAT=mingw +endif +endif PLAT?= linux PLATS= macosx linux win32 mingw freebsd @@ -9,6 +9,7 @@ Supports Lua >= 5.1 and luajit >= 2.0.0. Currently the following functions are supported: * gettime +* monotime * sleep License diff --git a/luasystem-0.1.1-0.rockspec b/luasystem-0.1.1-0.rockspec index 40c8b74..9c5f88d 100644 --- a/luasystem-0.1.1-0.rockspec +++ b/luasystem-0.1.1-0.rockspec @@ -18,16 +18,25 @@ dependencies = { local function make_platform(plat) local defines = { + linux = { }, + unix = { }, + macosx = { }, + win32 = { "WINVER=0x0600", "_WIN32_WINNT=0x0600" }, + mingw32 = { "WINVER=0x0600", "_WIN32_WINNT=0x0600" }, + } + local libraries = { + linux = { "rt" }, unix = { }, macosx = { }, win32 = { }, - mingw32 = { "WINVER=0x0501" }, + mingw32 = { }, } return { modules = { ['system.core'] = { sources = { 'src/core.c', 'src/compat.c', 'src/time.c', }, defines = defines[plat], + libraries = libraries[plat], }, }, } @@ -36,6 +45,7 @@ end build = { type = 'builtin', platforms = { + linux = make_platform('linux'), unix = make_platform('unix'), macosx = make_platform('macosx'), win32 = make_platform('win32'), diff --git a/luasystem-scm-0.rockspec b/luasystem-scm-0.rockspec index 83f4172..1093ac4 100644 --- a/luasystem-scm-0.rockspec +++ b/luasystem-scm-0.rockspec @@ -18,16 +18,25 @@ dependencies = { local function make_platform(plat) local defines = { + linux = { }, + unix = { }, + macosx = { }, + win32 = { "WINVER=0x0600", "_WIN32_WINNT=0x0600" }, + mingw32 = { "WINVER=0x0600", "_WIN32_WINNT=0x0600" }, + } + local libraries = { + linux = { "rt" }, unix = { }, macosx = { }, win32 = { }, - mingw32 = { "WINVER=0x0501" }, + mingw32 = { }, } return { modules = { ['system.core'] = { sources = { 'src/core.c', 'src/compat.c', 'src/time.c', }, defines = defines[plat], + libraries = libraries[plat], }, }, } @@ -36,6 +45,7 @@ end build = { type = 'builtin', platforms = { + linux = make_platform('linux'), unix = make_platform('unix'), macosx = make_platform('macosx'), win32 = make_platform('win32'), diff --git a/spec/time_spec.lua b/spec/time_spec.lua index c9d3d6d..e1b457a 100644 --- a/spec/time_spec.lua +++ b/spec/time_spec.lua @@ -12,9 +12,20 @@ describe('Test time functions', function() assert.is_near(expected, avg, 1 + delta) end) + it('monottime returns monotonically increasing time', function() + local starttime = system.monotime() + local endtime = system.monotime() + local delta = endtime - starttime + assert.is_true(starttime > 0) + assert.is_true(delta >= 0) + assert.is_true(system.monotime() - endtime >= 0) + end) + it('sleep will wait for specified amount of time', function() local starttime = system.gettime() + local starttick = system.monotime() system.sleep(0.5) assert.is_near(0.5, system.gettime() - starttime, 0.1) + assert.is_near(0.5, system.monotime() - starttick, 0.1) end) end) diff --git a/src/Makefile b/src/Makefile index 25f468d..10fc31a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,13 +4,28 @@ # environment. # -# PLAT: linux macosx win32 mingw +# PLAT: linux macosx win32 mingw freebsd # platform to build for +ifeq ($(origin PLAT),undefined) +UNAME_S:=$(shell uname -s) +ifeq ($(UNAME_S),Linux) + PLAT=linux +endif +ifeq ($(UNAME_S),Darwin) + PLAT=macosx +endif +ifeq ($(UNAME_S),FreeBSD) + PLAT=freebsd +endif +ifeq ($(patsubst MINGW%,MINGW,$(UNAME_S)),MINGW) + PLAT=mingw +endif +endif PLAT?=linux # LUA_VERSION: 5.1 5.2 5.3 # lua version to build against -LUA_VERSION?=5.1 +LUA_VERSION?=$(basename $(word 2,$(shell lua -v))) # MYCFLAGS: to be set by user if needed MYCFLAGS= @@ -130,7 +145,7 @@ CC_linux=gcc DEF_linux= CFLAGS_linux= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden -LDFLAGS_linux=-O -shared -fpic -o +LDFLAGS_linux=-lrt -O -shared -fpic -o LD_linux=gcc #------ @@ -151,7 +166,7 @@ LD_freebsd=gcc SO_mingw=dll O_mingw=o CC_mingw=gcc -DEF_mingw=-DWINVER=0x0501 +DEF_mingw=-DWINVER=0x0600 -D_WIN32_WINNT=0x0600 CFLAGS_mingw= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \ -fvisibility=hidden LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -o @@ -165,7 +180,8 @@ SO_win32=dll O_win32=obj CC_win32=cl DEF_win32= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \ - //D "_CRT_SECURE_NO_WARNINGS" //D "_WINDLL" + //D "_CRT_SECURE_NO_WARNINGS" //D "_WINDLL" \ + //D"WINVER=0x0600" //D"_WIN32_WINNT=0x0600" CFLAGS_win32=//I "$(LUAINC)" $(DEF) //O2 //Ot //MD //W3 //nologo LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ //MANIFEST //MANIFESTFILE:"intermediate.manifest" \ @@ -10,6 +10,10 @@ #include <sys/time.h> #endif +#ifdef __APPLE__ +#include "time_osx.h" +#endif + #include "compat.h" /*------------------------------------------------------------------------- @@ -23,7 +27,7 @@ static double time_gettime(void) { double t; GetSystemTimeAsFileTime(&ft); /* Windows file time (time since January 1, 1601 (UTC)) */ - t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7); + t = ft.dwLowDateTime*1.0e-7 + ft.dwHighDateTime*(4294967296.0*1.0e-7); /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */ return (t - 11644473600.0); } @@ -32,12 +36,32 @@ static double time_gettime(void) { struct timeval v; gettimeofday(&v, (struct timezone *) NULL); /* Unix Epoch time (time since January 1, 1970 (UTC)) */ - return v.tv_sec + v.tv_usec/1.0e6; + return v.tv_sec + v.tv_usec*1.0e-6; } #endif /*------------------------------------------------------------------------- - * Returns the time the system has been up, in secconds. + * Gets monotonic time in s + * Returns + * time in s. + *-------------------------------------------------------------------------*/ +#ifdef _WIN32 +WINBASEAPI ULONGLONG WINAPI GetTickCount64(VOID); + +static double time_monotime(void) { + ULONGLONG ms = GetTickCount64(); + return ms*1.0e-3; +} +#else +static double time_monotime(void) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec + ts.tv_nsec*1.0e-9; +} +#endif + +/*------------------------------------------------------------------------- + * Returns the current system time, 1970 (UTC), in secconds. *-------------------------------------------------------------------------*/ static int time_lua_gettime(lua_State *L) { @@ -46,6 +70,15 @@ static int time_lua_gettime(lua_State *L) } /*------------------------------------------------------------------------- + * Returns the monotonic time the system has been up, in secconds. + *-------------------------------------------------------------------------*/ +static int time_lua_monotime(lua_State *L) +{ + lua_pushnumber(L, time_monotime()); + return 1; +} + +/*------------------------------------------------------------------------- * Sleep for n seconds. *-------------------------------------------------------------------------*/ #ifdef _WIN32 @@ -79,6 +112,7 @@ static int time_lua_sleep(lua_State *L) static luaL_Reg func[] = { { "gettime", time_lua_gettime }, + { "monotime", time_lua_monotime }, { "sleep", time_lua_sleep }, { NULL, NULL } }; diff --git a/src/time_osx.h b/src/time_osx.h new file mode 100644 index 0000000..3308318 --- /dev/null +++ b/src/time_osx.h @@ -0,0 +1,66 @@ +#ifndef TIME_OSX_H +#define TIME_OSX_H + +/* + * clock_gettime() + * + * OS X doesn't implement the clock_gettime() POSIX interface, but does + * provide a monotonic clock through mach_absolute_time(). On i386 and + * x86_64 architectures this clock is in nanosecond units, but not so on + * other devices. mach_timebase_info() provides the conversion parameters. + * + */ + +#include <time.h> /* struct timespec */ +#include <errno.h> /* errno EINVAL */ +#include <sys/time.h> /* TIMEVAL_TO_TIMESPEC struct timeval gettimeofday(3) */ +#include <mach/mach_time.h> /* mach_timebase_info_data_t mach_timebase_info() mach_absolute_time() */ + + +#define CLOCK_REALTIME 0 +#define CLOCK_VIRTUAL 1 +#define CLOCK_PROF 2 +#define CLOCK_MONOTONIC 3 + +static mach_timebase_info_data_t clock_timebase = { + .numer = 1, .denom = 1, +}; /* clock_timebase */ + +void clock_gettime_init(void) __attribute__((constructor)); + +void clock_gettime_init(void) { + if (mach_timebase_info(&clock_timebase) != KERN_SUCCESS) + __builtin_abort(); +} /* clock_gettime_init() */ + +static int clock_gettime(int clockid, struct timespec *ts) { + switch (clockid) { + case CLOCK_REALTIME: { + struct timeval tv; + + if (0 != gettimeofday(&tv, 0)) + return -1; + + TIMEVAL_TO_TIMESPEC(&tv, ts); + + return 0; + } + case CLOCK_MONOTONIC: { + unsigned long long abt; + + abt = mach_absolute_time(); + abt = abt * clock_timebase.numer / clock_timebase.denom; + + ts->tv_sec = abt / 1000000000UL; + ts->tv_nsec = abt % 1000000000UL; + + return 0; + } + default: + errno = EINVAL; + + return -1; + } /* switch() */ +} /* clock_gettime() */ + +#endif /* TIME_OSX_H */ |