Skip to content
Snippets Groups Projects
Commit 714afdc1 authored by Gabriel Krisman Bertazi's avatar Gabriel Krisman Bertazi Committed by André Almeida
Browse files

selftests: futex: Add FUTEX_WAIT_MULTIPLE timeout test


Add test for timeout when waiting for multiple futexes. Skip the test if
it's a x32 application and the kernel returned the approtiaded error,
since this ABI is not supported for this operation.

Signed-off-by: default avatarGabriel Krisman Bertazi <krisman@collabora.com>
Co-developed-by: default avatarAndré Almeida <andrealmeid@collabora.com>
Signed-off-by: default avatarAndré Almeida <andrealmeid@collabora.com>
---
Changes since v2: none
parent dc3e0456
No related branches found
No related tags found
No related merge requests found
......@@ -11,6 +11,7 @@
*
* HISTORY
* 2009-Nov-6: Initial version by Darren Hart <dvhart@linux.intel.com>
* 2019-Dec-13: Add WAIT_MULTIPLE test by Krisman <krisman@collabora.com>
*
*****************************************************************************/
......@@ -41,6 +42,8 @@ int main(int argc, char *argv[])
{
futex_t f1 = FUTEX_INITIALIZER;
struct timespec to;
time_t secs;
struct futex_wait_block fwb = {&f1, f1, 0};
int res, ret = RET_PASS;
int c;
......@@ -65,7 +68,7 @@ int main(int argc, char *argv[])
}
ksft_print_header();
ksft_set_plan(1);
ksft_set_plan(2);
ksft_print_msg("%s: Block on a futex and wait for timeout\n",
basename(argv[0]));
ksft_print_msg("\tArguments: timeout=%ldns\n", timeout_ns);
......@@ -79,8 +82,39 @@ int main(int argc, char *argv[])
if (!res || errno != ETIMEDOUT) {
fail("futex_wait returned %d\n", ret < 0 ? errno : ret);
ret = RET_FAIL;
} else
ksft_test_result_pass("futex_wait timeout succeeds\n");
info("Calling futex_wait_multiple on f1: %u @ %p\n", f1, &f1);
/* Setup absolute time */
ret = clock_gettime(CLOCK_REALTIME, &to);
secs = (to.tv_nsec + timeout_ns) / 1000000000;
to.tv_nsec = ((int64_t)to.tv_nsec + timeout_ns) % 1000000000;
to.tv_sec += secs;
info("to.tv_sec = %ld\n", to.tv_sec);
info("to.tv_nsec = %ld\n", to.tv_nsec);
res = futex_wait_multiple(&fwb, 1, &to,
FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME);
#ifdef __ILP32__
if (res == -1 && errno == ENOSYS) {
ksft_test_result_skip("futex_wait_multiple not supported at x32\n");
} else {
ksft_test_result_fail("futex_wait_multiple returned %d\n",
res < 0 ? errno : res);
ret = RET_FAIL;
}
#else
if (!res || errno != ETIMEDOUT) {
ksft_test_result_fail("futex_wait_multiple returned %d\n",
res < 0 ? errno : res);
ret = RET_FAIL;
} else
ksft_test_result_pass("futex_wait_multiple timeout succeeds\n");
#endif /* __ILP32__ */
print_result(TEST_NAME, ret);
ksft_print_cnts();
return ret;
}
......@@ -38,6 +38,14 @@ typedef volatile u_int32_t futex_t;
#ifndef FUTEX_CMP_REQUEUE_PI
#define FUTEX_CMP_REQUEUE_PI 12
#endif
#ifndef FUTEX_WAIT_MULTIPLE
#define FUTEX_WAIT_MULTIPLE 13
struct futex_wait_block {
futex_t *uaddr;
futex_t val;
__u32 bitset;
};
#endif
#ifndef FUTEX_WAIT_REQUEUE_PI_PRIVATE
#define FUTEX_WAIT_REQUEUE_PI_PRIVATE (FUTEX_WAIT_REQUEUE_PI | \
FUTEX_PRIVATE_FLAG)
......@@ -80,6 +88,20 @@ futex_wait(futex_t *uaddr, futex_t val, struct timespec *timeout, int opflags)
return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
}
/**
* futex_wait_multiple() - block on several futexes with optional timeout
* @fwb: wait block user space address
* @count: number of entities at fwb
* @timeout: absolute timeout
*/
static inline int
futex_wait_multiple(struct futex_wait_block *fwb, int count,
struct timespec *timeout, int opflags)
{
return futex(fwb, FUTEX_WAIT_MULTIPLE, count, timeout, NULL, 0,
opflags);
}
/**
* futex_wake() - wake one or more tasks blocked on uaddr
* @nr_wake: wake up to this many tasks
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment