@@ -27,7 +27,7 @@ void usage(char *prog)
void *waiterfn(void *arg)
{
- struct timespec to;
+ struct timespec64 to;
to.tv_sec = 0;
to.tv_nsec = timeout_ns;
@@ -48,7 +48,7 @@ static int locked;
struct thread_arg {
long id;
- struct timespec *timeout;
+ struct timespec64 *timeout;
int lock;
int ret;
};
@@ -281,7 +281,7 @@ int unit_test(int broadcast, long lock, int third_party_owner, long timeout_ns)
struct thread_arg blocker_arg = THREAD_ARG_INITIALIZER;
struct thread_arg waker_arg = THREAD_ARG_INITIALIZER;
pthread_t waiter[THREAD_MAX], waker, blocker;
- struct timespec ts, *tsp = NULL;
+ struct timespec64 ts, *tsp = NULL;
struct thread_arg args[THREAD_MAX];
int *waiter_ret;
int i, ret = RET_PASS;
@@ -290,7 +290,7 @@ int unit_test(int broadcast, long lock, int third_party_owner, long timeout_ns)
time_t secs;
info("timeout_ns = %ld\n", timeout_ns);
- ret = clock_gettime(CLOCK_MONOTONIC, &ts);
+ ret = gettime64(CLOCK_MONOTONIC, &ts);
secs = (ts.tv_nsec + timeout_ns) / 1000000000;
ts.tv_nsec = ((int64_t)ts.tv_nsec + timeout_ns) % 1000000000;
ts.tv_sec += secs;
@@ -30,7 +30,7 @@ void usage(char *prog)
static void *waiterfn(void *arg)
{
- struct timespec to;
+ struct timespec64 to;
unsigned int flags = 0;
if (arg)
@@ -38,7 +38,7 @@ futex_t val = 1;
char pad2[PAGE_SZ] = {1};
#define WAKE_WAIT_US 3000000
-struct timespec wait_timeout = { .tv_sec = 5, .tv_nsec = 0};
+struct timespec64 wait_timeout = { .tv_sec = 5, .tv_nsec = 0};
void usage(char *prog)
{
@@ -71,11 +71,11 @@ static void test_timeout(int res, int *ret, char *test_name, int err)
/*
* Calculate absolute timeout and correct overflow
*/
-static int futex_get_abs_timeout(clockid_t clockid, struct timespec *to,
+static int futex_get_abs_timeout(clockid_t clockid, struct timespec64 *to,
long timeout_ns)
{
- if (clock_gettime(clockid, to)) {
- error("clock_gettime failed\n", errno);
+ if (gettime64(clockid, to)) {
+ error("gettime64 failed\n", errno);
return errno;
}
@@ -93,7 +93,7 @@ int main(int argc, char *argv[])
{
futex_t f1 = FUTEX_INITIALIZER;
int res, ret = RET_PASS;
- struct timespec to;
+ struct timespec64 to;
pthread_t thread;
int c;
@@ -38,7 +38,7 @@ void usage(char *prog)
int main(int argc, char *argv[])
{
- struct timespec to = {.tv_sec = 0, .tv_nsec = timeout_ns};
+ struct timespec64 to = {.tv_sec = 0, .tv_nsec = timeout_ns};
futex_t f1 = FUTEX_INITIALIZER;
int res, ret = RET_PASS;
int c;
@@ -47,12 +47,17 @@ typedef volatile u_int32_t futex_t;
FUTEX_PRIVATE_FLAG)
#endif
+struct timespec64 {
+ long long tv_sec; /* seconds */
+ long long tv_nsec; /* nanoseconds */
+};
+
/**
* futex() - SYS_futex syscall wrapper
* @uaddr: address of first futex
* @op: futex op code
* @val: typically expected value of uaddr, but varies by op
- * @timeout: typically an absolute struct timespec (except where noted
+ * @timeout: typically an absolute struct timespec64 (except where noted
* otherwise). Overloaded by some ops
* @uaddr2: address of second futex for some ops\
* @val3: varies by op
@@ -67,15 +72,35 @@ typedef volatile u_int32_t futex_t;
* These argument descriptions are the defaults for all
* like-named arguments in the following wrappers except where noted below.
*/
-#define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \
- syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3)
+/**
+ * We only support 64-bit time_t for the timeout.
+ * On 64-bit architectures we can use __NR_futex
+ * On 32-bit architectures we use __NR_futex_time64. This only works on kernel
+ * versions 5.1+.
+ */
+#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
+# define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \
+ syscall(__NR_futex, uaddr, op | opflags, val, timeout, uaddr2, val3)
+#else
+# define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \
+ syscall(__NR_futex_time64, uaddr, op | opflags, val, timeout, uaddr2, val3)
+#endif
+
+static inline int gettime64(clock_t clockid, struct timespec64 *tv)
+{
+#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
+ return syscall(__NR_clock_gettime, clockid, tv);
+#else
+ return syscall(__NR_clock_gettime64, clockid, tv);
+#endif
+}
/**
* futex_wait() - block on uaddr with optional timeout
* @timeout: relative timeout
*/
static inline int
-futex_wait(futex_t *uaddr, futex_t val, struct timespec *timeout, int opflags)
+futex_wait(futex_t *uaddr, futex_t val, struct timespec64 *timeout, int opflags)
{
return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
}
@@ -95,7 +120,7 @@ futex_wake(futex_t *uaddr, int nr_wake, int opflags)
* @bitset: bitset to be used with futex_wake_bitset
*/
static inline int
-futex_wait_bitset(futex_t *uaddr, futex_t val, struct timespec *timeout,
+futex_wait_bitset(futex_t *uaddr, futex_t val, struct timespec64 *timeout,
u_int32_t bitset, int opflags)
{
return futex(uaddr, FUTEX_WAIT_BITSET, val, timeout, NULL, bitset,
@@ -118,7 +143,7 @@ futex_wake_bitset(futex_t *uaddr, int nr_wake, u_int32_t bitset, int opflags)
* @detect: whether (1) or not (0) to perform deadlock detection
*/
static inline int
-futex_lock_pi(futex_t *uaddr, struct timespec *timeout, int detect,
+futex_lock_pi(futex_t *uaddr, struct timespec64 *timeout, int detect,
int opflags)
{
return futex(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags);
@@ -183,7 +208,7 @@ futex_cmp_requeue(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake,
*/
static inline int
futex_wait_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2,
- struct timespec *timeout, int opflags)
+ struct timespec64 *timeout, int opflags)
{
return futex(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0,
opflags);