@@ -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