Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POSIX: Fix portability issues with clock_gettime #1360

Merged
merged 8 commits into from
Apr 24, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
156 changes: 149 additions & 7 deletions ffi/posix_h.lua
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,6 @@ char *realpath(const char *restrict, char *restrict) __attribute__((nothrow, lea
char *basename(char *) __attribute__((nothrow, leaf));
char *dirname(char *) __attribute__((nothrow, leaf));
typedef int clockid_t;
static const int CLOCK_REALTIME = 0;
static const int CLOCK_REALTIME_COARSE = 5;
static const int CLOCK_MONOTONIC = 1;
static const int CLOCK_MONOTONIC_COARSE = 6;
static const int CLOCK_MONOTONIC_RAW = 4;
static const int CLOCK_BOOTTIME = 7;
static const int CLOCK_TAI = 11;
int clock_getres(clockid_t, struct timespec *) __attribute__((nothrow, leaf));
int clock_gettime(clockid_t, struct timespec *) __attribute__((nothrow, leaf));
int clock_settime(clockid_t, const struct timespec *) __attribute__((nothrow, leaf));
Expand Down Expand Up @@ -202,3 +195,152 @@ if ffi.os == "Linux" then
-- in order to let the dynamic loader figure it out on its own (e.g., multilib).
pcall(ffi.load, "rt.so.1", true)
end

-- The clockid_t constants are not portable :/.
if ffi.os == "Linux" then
ffi.cdef[[
static const int CLOCK_REALTIME = 0;
static const int CLOCK_REALTIME_COARSE = 5;
static const int CLOCK_MONOTONIC = 1;
static const int CLOCK_MONOTONIC_COARSE = 6;
static const int CLOCK_MONOTONIC_RAW = 4;
static const int CLOCK_BOOTTIME = 7;
static const int CLOCK_TAI = 11;
]]
elseif ffi.os == "OSX" then
-- c.f., https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.12.sdk/usr/include/time.h
--[[
typedef enum {
_CLOCK_REALTIME = 0,
_CLOCK_MONOTONIC = 6,
_CLOCK_MONOTONIC_RAW = 4,
_CLOCK_MONOTONIC_RAW_APPROX = 5,
_CLOCK_UPTIME_RAW = 8,
_CLOCK_UPTIME_RAW_APPROX = 9,
_CLOCK_PROCESS_CPUTIME_ID = 12,
_CLOCK_THREAD_CPUTIME_ID = 16
} clockid_t;
--]]
-- Portability notes:
-- Unlike on Linux, MONO ticks during sleep (which is technically the POSIX-compliant behavior).
-- CLOCK_UPTIME_* doesn't.
-- (e.g., macOS UPTIME == Linux MONO, and macOS MONO == Linux BOOTTIME)

-- NOTE: Requires macOS 10.12
ffi.cdef[[
static const int CLOCK_REALTIME = 0;
static const int CLOCK_REALTIME_COARSE = -1;
static const int CLOCK_MONOTONIC = 6;
static const int CLOCK_MONOTONIC_COARSE = 5;
static const int CLOCK_MONOTONIC_RAW = 4;
static const int CLOCK_BOOTTIME = -1;
static const int CLOCK_TAI = -1;
]]
elseif ffi.os == "BSD" then
-- OpenBSD
-- c.f., https://github.com/openbsd/src/blob/master/sys/sys/_time.h
--[[
#define CLOCK_REALTIME 0
#define CLOCK_PROCESS_CPUTIME_ID 2
#define CLOCK_MONOTONIC 3
#define CLOCK_THREAD_CPUTIME_ID 4
#define CLOCK_UPTIME 5
#define CLOCK_BOOTTIME 6
--]]
-- Portability notes:
-- OpenBSD UPTIME == Linux MONOTONIC, OpenBSD BOOTTIME == Linux BOOTTIME
-- (Meaning MONOTONIC starts ticking at an *undefined* positive value).

-- NetBSD
-- c.f., https://anonhg.netbsd.org/src/file/tip/sys/sys/time.h
--[[
#define CLOCK_REALTIME 0
#define CLOCK_VIRTUAL 1
#define CLOCK_PROF 2
#define CLOCK_MONOTONIC 3
#define CLOCK_THREAD_CPUTIME_ID 0x20000000
#define CLOCK_PROCESS_CPUTIME_ID 0x40000000
--]]

-- FreeBSD
-- c.f., https://github.com/freebsd/freebsd-src/blob/main/include/time.h
--[[
#define CLOCK_REALTIME 0
#define CLOCK_VIRTUAL 1
#define CLOCK_PROF 2
#define CLOCK_MONOTONIC 4
#define CLOCK_UPTIME 5 /* FreeBSD-specific. */
#define CLOCK_UPTIME_PRECISE 7 /* FreeBSD-specific. */
#define CLOCK_UPTIME_FAST 8 /* FreeBSD-specific. */
#define CLOCK_REALTIME_PRECISE 9 /* FreeBSD-specific. */
#define CLOCK_REALTIME_FAST 10 /* FreeBSD-specific. */
#define CLOCK_MONOTONIC_PRECISE 11 /* FreeBSD-specific. */
#define CLOCK_MONOTONIC_FAST 12 /* FreeBSD-specific. */
#define CLOCK_SECOND 13 /* FreeBSD-specific. */
#define CLOCK_THREAD_CPUTIME_ID 14
#define CLOCK_PROCESS_CPUTIME_ID 15
--]]
-- Portability notes:
-- FreeBSD UPTIME == Linux MONOTONIC
-- (I assume that, like on OpenBSD, this means MONOTONIC starts ticking at an *undefined* positive value).

-- So, here comes probey-time!
local C = ffi.C
local probe_ts = ffi.new("struct timespec")
if C.clock_getres(15, probe_ts) == 0 then
-- FreeBSD
ffi.cdef[[
static const int CLOCK_REALTIME = 0;
static const int CLOCK_REALTIME_COARSE = 10;
static const int CLOCK_MONOTONIC = 4;
static const int CLOCK_MONOTONIC_COARSE = 12;
static const int CLOCK_MONOTONIC_RAW = 11;
static const int CLOCK_BOOTTIME = -1;
static const int CLOCK_TAI = -1;
]]
elseif C.clock_getres(0x40000000, probe_ts) == 0 then
-- NetBSD
ffi.cdef[[
static const int CLOCK_REALTIME = 0;
static const int CLOCK_REALTIME_COARSE = -1;
static const int CLOCK_MONOTONIC = 3;
static const int CLOCK_MONOTONIC_COARSE = -1;
static const int CLOCK_MONOTONIC_RAW = -1;
static const int CLOCK_BOOTTIME = -1;
static const int CLOCK_TAI = -1;
]]
else
-- OpenBSD
ffi.cdef[[
static const int CLOCK_REALTIME = 0;
static const int CLOCK_REALTIME_COARSE = -1;
static const int CLOCK_MONOTONIC = 3;
static const int CLOCK_MONOTONIC_COARSE = -1;
static const int CLOCK_MONOTONIC_RAW = -1;
static const int CLOCK_BOOTTIME = 6;
static const int CLOCK_TAI = -1;
]]
end
probe_ts = nil --luacheck: ignore
else
-- Assume minimal Linux compat on other OSes.

-- This holds true for Windows via mingw,
-- c.f., https://github.com/mirror/mingw-w64/blob/master/mingw-w64-libraries/winpthreads/include/pthread_time.h
--[[
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
#define CLOCK_PROCESS_CPUTIME_ID 2
#define CLOCK_THREAD_CPUTIME_ID 3
--]]

ffi.cdef[[
static const int CLOCK_REALTIME = 0;
static const int CLOCK_REALTIME_COARSE = -1;
static const int CLOCK_MONOTONIC = 1;
static const int CLOCK_MONOTONIC_COARSE = -1;
static const int CLOCK_MONOTONIC_RAW = -1;
static const int CLOCK_BOOTTIME = -1;
static const int CLOCK_TAI = -1;
]]
end