* [PATCH 0/2] selftests: futex: Improve timeout testing @ 2021-04-27 13:53 André Almeida 2021-04-27 13:53 ` [PATCH 1/2] selftests: futex: Correctly include headers dirs André Almeida 2021-04-27 13:53 ` [PATCH 2/2] selftests: futex: Expand timeout test André Almeida 0 siblings, 2 replies; 5+ messages in thread From: André Almeida @ 2021-04-27 13:53 UTC (permalink / raw) To: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart, linux-kernel Cc: kernel, linux-kselftest, shuah, André Almeida This small series expands futex timeout selftests by checking if all operations that allows timeouts works as expected. When some version of Thomas' series "futex: Bugfixes and FUTEX_LOCK_PI2"[0] get merged, I'll add the new rules to the timeout test. This test should be used to check for regressions when modifying the timeout path or changing the interface. Additionally, fix a bug in the Makefile that can be found when compiling selftests with new operations, like the one defined at [0] or from the futex2 patchset. [0] https://lore.kernel.org/lkml/20210422194417.866740847@linutronix.de/ André Almeida (2): selftests: futex: Correctly include headers dirs selftests: futex: Expand timeout test .../selftests/futex/functional/Makefile | 3 +- .../futex/functional/futex_wait_timeout.c | 126 +++++++++++++++--- 2 files changed, 112 insertions(+), 17 deletions(-) -- 2.31.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] selftests: futex: Correctly include headers dirs 2021-04-27 13:53 [PATCH 0/2] selftests: futex: Improve timeout testing André Almeida @ 2021-04-27 13:53 ` André Almeida 2021-05-12 18:50 ` [tip: locking/core] " tip-bot2 for André Almeida 2021-04-27 13:53 ` [PATCH 2/2] selftests: futex: Expand timeout test André Almeida 1 sibling, 1 reply; 5+ messages in thread From: André Almeida @ 2021-04-27 13:53 UTC (permalink / raw) To: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart, linux-kernel Cc: kernel, linux-kselftest, shuah, André Almeida When building selftests, the build system will install uapi linux headers at usr/include in kernel source's root directory. When building with a different output folder, the headers will be installed at kselftests/usr/include. Add both paths so we can build the tests using up-to-date headers. Currently, this is uncommon to happen since it's rare to find a build system with an outdated futex header, but it happens when testing new futex operations. Signed-off-by: André Almeida <andrealmeid@collabora.com> --- tools/testing/selftests/futex/functional/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile index 23207829ec75..1d2b3b2a5b86 100644 --- a/tools/testing/selftests/futex/functional/Makefile +++ b/tools/testing/selftests/futex/functional/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -INCLUDES := -I../include -I../../ +INCLUDES := -I../include -I../../ -I../../../../../usr/include/ \ + -I$(KBUILD_OUTPUT)/kselftest/usr/include CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE -pthread $(INCLUDES) LDLIBS := -lpthread -lrt -- 2.31.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [tip: locking/core] selftests: futex: Correctly include headers dirs 2021-04-27 13:53 ` [PATCH 1/2] selftests: futex: Correctly include headers dirs André Almeida @ 2021-05-12 18:50 ` tip-bot2 for André Almeida 0 siblings, 0 replies; 5+ messages in thread From: tip-bot2 for André Almeida @ 2021-05-12 18:50 UTC (permalink / raw) To: linux-tip-commits; +Cc: andrealmeid, Ingo Molnar, x86, linux-kernel The following commit has been merged into the locking/core branch of tip: Commit-ID: c7d84e7ff5a651d186a6ec41361c4f07acc2fb9c Gitweb: https://git.kernel.org/tip/c7d84e7ff5a651d186a6ec41361c4f07acc2fb9c Author: André Almeida <andrealmeid@collabora.com> AuthorDate: Tue, 27 Apr 2021 10:53:27 -03:00 Committer: Ingo Molnar <mingo@kernel.org> CommitterDate: Wed, 12 May 2021 20:44:58 +02:00 selftests: futex: Correctly include headers dirs When building selftests, the build system will install uapi linux headers at usr/include in kernel source's root directory. When building with a different output folder, the headers will be installed at kselftests/usr/include. Add both paths so we can build the tests using up-to-date headers. Currently, this is uncommon to happen since it's rare to find a build system with an outdated futex header, but it happens when testing new futex operations. Signed-off-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20210427135328.11013-2-andrealmeid@collabora.com --- tools/testing/selftests/futex/functional/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile index 2320782..1d2b3b2 100644 --- a/tools/testing/selftests/futex/functional/Makefile +++ b/tools/testing/selftests/futex/functional/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -INCLUDES := -I../include -I../../ +INCLUDES := -I../include -I../../ -I../../../../../usr/include/ \ + -I$(KBUILD_OUTPUT)/kselftest/usr/include CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE -pthread $(INCLUDES) LDLIBS := -lpthread -lrt ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] selftests: futex: Expand timeout test 2021-04-27 13:53 [PATCH 0/2] selftests: futex: Improve timeout testing André Almeida 2021-04-27 13:53 ` [PATCH 1/2] selftests: futex: Correctly include headers dirs André Almeida @ 2021-04-27 13:53 ` André Almeida 2021-05-12 18:50 ` [tip: locking/core] " tip-bot2 for André Almeida 1 sibling, 1 reply; 5+ messages in thread From: André Almeida @ 2021-04-27 13:53 UTC (permalink / raw) To: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart, linux-kernel Cc: kernel, linux-kselftest, shuah, André Almeida Improve futex timeout testing by checking all the operations that supports timeout and their available modes. Signed-off-by: André Almeida <andrealmeid@collabora.com> --- .../futex/functional/futex_wait_timeout.c | 126 +++++++++++++++--- 1 file changed, 110 insertions(+), 16 deletions(-) diff --git a/tools/testing/selftests/futex/functional/futex_wait_timeout.c b/tools/testing/selftests/futex/functional/futex_wait_timeout.c index ee55e6d389a3..1f8f6daaf1e7 100644 --- a/tools/testing/selftests/futex/functional/futex_wait_timeout.c +++ b/tools/testing/selftests/futex/functional/futex_wait_timeout.c @@ -11,21 +11,18 @@ * * HISTORY * 2009-Nov-6: Initial version by Darren Hart <dvhart@linux.intel.com> + * 2021-Apr-26: More test cases by André Almeida <andrealmeid@collabora.com> * *****************************************************************************/ -#include <errno.h> -#include <getopt.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> +#include <pthread.h> #include "futextest.h" #include "logging.h" #define TEST_NAME "futex-wait-timeout" static long timeout_ns = 100000; /* 100us default timeout */ +static futex_t futex_pi; void usage(char *prog) { @@ -37,11 +34,67 @@ void usage(char *prog) VQUIET, VCRITICAL, VINFO); } +/* + * Get a PI lock and hold it forever, so the main thread lock_pi will block + * and we can test the timeout + */ +void *get_pi_lock(void *arg) +{ + int ret; + volatile futex_t lock = 0; + + ret = futex_lock_pi(&futex_pi, NULL, 0, 0); + if (ret != 0) + error("futex_lock_pi failed\n", ret); + + /* Blocks forever */ + ret = futex_wait(&lock, 0, NULL, 0); + error("futex_wait failed\n", ret); + + return NULL; +} + +/* + * Check if the function returned the expected error + */ +static void test_timeout(int res, int *ret, char *test_name, int err) +{ + if (!res || errno != err) { + ksft_test_result_fail("%s returned %d\n", test_name, + res < 0 ? errno : res); + *ret = RET_FAIL; + } else { + ksft_test_result_pass("%s succeeds\n", test_name); + } +} + +/* + * Calculate absolute timeout and correct overflow + */ +static int futex_get_abs_timeout(clockid_t clockid, struct timespec *to, + long timeout_ns) +{ + if (clock_gettime(clockid, to)) { + error("clock_gettime failed\n", errno); + return errno; + } + + to->tv_nsec += timeout_ns; + + if (to->tv_nsec >= 1000000000) { + to->tv_sec++; + to->tv_nsec -= 1000000000; + } + + return 0; +} + int main(int argc, char *argv[]) { futex_t f1 = FUTEX_INITIALIZER; - struct timespec to; int res, ret = RET_PASS; + struct timespec to; + pthread_t thread; int c; while ((c = getopt(argc, argv, "cht:v:")) != -1) { @@ -65,22 +118,63 @@ int main(int argc, char *argv[]) } ksft_print_header(); - ksft_set_plan(1); + ksft_set_plan(7); 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); - /* initialize timeout */ + pthread_create(&thread, NULL, get_pi_lock, NULL); + + /* initialize relative timeout */ to.tv_sec = 0; to.tv_nsec = timeout_ns; - info("Calling futex_wait on f1: %u @ %p\n", f1, &f1); - res = futex_wait(&f1, f1, &to, FUTEX_PRIVATE_FLAG); - if (!res || errno != ETIMEDOUT) { - fail("futex_wait returned %d\n", ret < 0 ? errno : ret); - ret = RET_FAIL; - } + res = futex_wait(&f1, f1, &to, 0); + test_timeout(res, &ret, "futex_wait relative", ETIMEDOUT); + + /* FUTEX_WAIT_BITSET with CLOCK_REALTIME */ + if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns)) + return RET_FAIL; + res = futex_wait_bitset(&f1, f1, &to, 1, FUTEX_CLOCK_REALTIME); + test_timeout(res, &ret, "futex_wait_bitset realtime", ETIMEDOUT); + + /* FUTEX_WAIT_BITSET with CLOCK_MONOTONIC */ + if (futex_get_abs_timeout(CLOCK_MONOTONIC, &to, timeout_ns)) + return RET_FAIL; + res = futex_wait_bitset(&f1, f1, &to, 1, 0); + test_timeout(res, &ret, "futex_wait_bitset monotonic", ETIMEDOUT); + + /* FUTEX_WAIT_REQUEUE_PI with CLOCK_REALTIME */ + if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns)) + return RET_FAIL; + res = futex_wait_requeue_pi(&f1, f1, &futex_pi, &to, FUTEX_CLOCK_REALTIME); + test_timeout(res, &ret, "futex_wait_requeue_pi realtime", ETIMEDOUT); + + /* FUTEX_WAIT_REQUEUE_PI with CLOCK_MONOTONIC */ + if (futex_get_abs_timeout(CLOCK_MONOTONIC, &to, timeout_ns)) + return RET_FAIL; + res = futex_wait_requeue_pi(&f1, f1, &futex_pi, &to, 0); + test_timeout(res, &ret, "futex_wait_requeue_pi monotonic", ETIMEDOUT); + + /* + * FUTEX_LOCK_PI with CLOCK_REALTIME + * Due to historical reasons, FUTEX_LOCK_PI supports only realtime + * clock, but requires the caller to not set CLOCK_REALTIME flag. + * + * If you call FUTEX_LOCK_PI with a monotonic clock, it'll be + * interpreted as a realtime clock, and (unless you mess your machine's + * time or your time machine) the monotonic clock value is always + * smaller than realtime and the syscall will timeout immediately. + */ + if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns)) + return RET_FAIL; + res = futex_lock_pi(&futex_pi, &to, 0, 0); + test_timeout(res, &ret, "futex_lock_pi realtime", ETIMEDOUT); + + /* Test operations that don't support FUTEX_CLOCK_REALTIME */ + res = futex_lock_pi(&futex_pi, NULL, 0, FUTEX_CLOCK_REALTIME); + test_timeout(res, &ret, "futex_lock_pi invalid timeout flag", ENOSYS); - print_result(TEST_NAME, ret); + ksft_print_cnts(); return ret; } -- 2.31.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [tip: locking/core] selftests: futex: Expand timeout test 2021-04-27 13:53 ` [PATCH 2/2] selftests: futex: Expand timeout test André Almeida @ 2021-05-12 18:50 ` tip-bot2 for André Almeida 0 siblings, 0 replies; 5+ messages in thread From: tip-bot2 for André Almeida @ 2021-05-12 18:50 UTC (permalink / raw) To: linux-tip-commits; +Cc: andrealmeid, Ingo Molnar, x86, linux-kernel The following commit has been merged into the locking/core branch of tip: Commit-ID: f4addd54b1617067f735ad194a3580a2db7b8bf5 Gitweb: https://git.kernel.org/tip/f4addd54b1617067f735ad194a3580a2db7b8bf5 Author: André Almeida <andrealmeid@collabora.com> AuthorDate: Tue, 27 Apr 2021 10:53:28 -03:00 Committer: Ingo Molnar <mingo@kernel.org> CommitterDate: Wed, 12 May 2021 20:44:59 +02:00 selftests: futex: Expand timeout test Improve futex timeout testing by checking all the operations that supports timeout and their available modes. Signed-off-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20210427135328.11013-3-andrealmeid@collabora.com --- tools/testing/selftests/futex/functional/futex_wait_timeout.c | 126 ++++++- 1 file changed, 110 insertions(+), 16 deletions(-) diff --git a/tools/testing/selftests/futex/functional/futex_wait_timeout.c b/tools/testing/selftests/futex/functional/futex_wait_timeout.c index ee55e6d..1f8f6da 100644 --- a/tools/testing/selftests/futex/functional/futex_wait_timeout.c +++ b/tools/testing/selftests/futex/functional/futex_wait_timeout.c @@ -11,21 +11,18 @@ * * HISTORY * 2009-Nov-6: Initial version by Darren Hart <dvhart@linux.intel.com> + * 2021-Apr-26: More test cases by André Almeida <andrealmeid@collabora.com> * *****************************************************************************/ -#include <errno.h> -#include <getopt.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> +#include <pthread.h> #include "futextest.h" #include "logging.h" #define TEST_NAME "futex-wait-timeout" static long timeout_ns = 100000; /* 100us default timeout */ +static futex_t futex_pi; void usage(char *prog) { @@ -37,11 +34,67 @@ void usage(char *prog) VQUIET, VCRITICAL, VINFO); } +/* + * Get a PI lock and hold it forever, so the main thread lock_pi will block + * and we can test the timeout + */ +void *get_pi_lock(void *arg) +{ + int ret; + volatile futex_t lock = 0; + + ret = futex_lock_pi(&futex_pi, NULL, 0, 0); + if (ret != 0) + error("futex_lock_pi failed\n", ret); + + /* Blocks forever */ + ret = futex_wait(&lock, 0, NULL, 0); + error("futex_wait failed\n", ret); + + return NULL; +} + +/* + * Check if the function returned the expected error + */ +static void test_timeout(int res, int *ret, char *test_name, int err) +{ + if (!res || errno != err) { + ksft_test_result_fail("%s returned %d\n", test_name, + res < 0 ? errno : res); + *ret = RET_FAIL; + } else { + ksft_test_result_pass("%s succeeds\n", test_name); + } +} + +/* + * Calculate absolute timeout and correct overflow + */ +static int futex_get_abs_timeout(clockid_t clockid, struct timespec *to, + long timeout_ns) +{ + if (clock_gettime(clockid, to)) { + error("clock_gettime failed\n", errno); + return errno; + } + + to->tv_nsec += timeout_ns; + + if (to->tv_nsec >= 1000000000) { + to->tv_sec++; + to->tv_nsec -= 1000000000; + } + + return 0; +} + int main(int argc, char *argv[]) { futex_t f1 = FUTEX_INITIALIZER; - struct timespec to; int res, ret = RET_PASS; + struct timespec to; + pthread_t thread; int c; while ((c = getopt(argc, argv, "cht:v:")) != -1) { @@ -65,22 +118,63 @@ int main(int argc, char *argv[]) } ksft_print_header(); - ksft_set_plan(1); + ksft_set_plan(7); 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); - /* initialize timeout */ + pthread_create(&thread, NULL, get_pi_lock, NULL); + + /* initialize relative timeout */ to.tv_sec = 0; to.tv_nsec = timeout_ns; - info("Calling futex_wait on f1: %u @ %p\n", f1, &f1); - res = futex_wait(&f1, f1, &to, FUTEX_PRIVATE_FLAG); - if (!res || errno != ETIMEDOUT) { - fail("futex_wait returned %d\n", ret < 0 ? errno : ret); - ret = RET_FAIL; - } + res = futex_wait(&f1, f1, &to, 0); + test_timeout(res, &ret, "futex_wait relative", ETIMEDOUT); + + /* FUTEX_WAIT_BITSET with CLOCK_REALTIME */ + if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns)) + return RET_FAIL; + res = futex_wait_bitset(&f1, f1, &to, 1, FUTEX_CLOCK_REALTIME); + test_timeout(res, &ret, "futex_wait_bitset realtime", ETIMEDOUT); + + /* FUTEX_WAIT_BITSET with CLOCK_MONOTONIC */ + if (futex_get_abs_timeout(CLOCK_MONOTONIC, &to, timeout_ns)) + return RET_FAIL; + res = futex_wait_bitset(&f1, f1, &to, 1, 0); + test_timeout(res, &ret, "futex_wait_bitset monotonic", ETIMEDOUT); + + /* FUTEX_WAIT_REQUEUE_PI with CLOCK_REALTIME */ + if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns)) + return RET_FAIL; + res = futex_wait_requeue_pi(&f1, f1, &futex_pi, &to, FUTEX_CLOCK_REALTIME); + test_timeout(res, &ret, "futex_wait_requeue_pi realtime", ETIMEDOUT); + + /* FUTEX_WAIT_REQUEUE_PI with CLOCK_MONOTONIC */ + if (futex_get_abs_timeout(CLOCK_MONOTONIC, &to, timeout_ns)) + return RET_FAIL; + res = futex_wait_requeue_pi(&f1, f1, &futex_pi, &to, 0); + test_timeout(res, &ret, "futex_wait_requeue_pi monotonic", ETIMEDOUT); + + /* + * FUTEX_LOCK_PI with CLOCK_REALTIME + * Due to historical reasons, FUTEX_LOCK_PI supports only realtime + * clock, but requires the caller to not set CLOCK_REALTIME flag. + * + * If you call FUTEX_LOCK_PI with a monotonic clock, it'll be + * interpreted as a realtime clock, and (unless you mess your machine's + * time or your time machine) the monotonic clock value is always + * smaller than realtime and the syscall will timeout immediately. + */ + if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns)) + return RET_FAIL; + res = futex_lock_pi(&futex_pi, &to, 0, 0); + test_timeout(res, &ret, "futex_lock_pi realtime", ETIMEDOUT); + + /* Test operations that don't support FUTEX_CLOCK_REALTIME */ + res = futex_lock_pi(&futex_pi, NULL, 0, FUTEX_CLOCK_REALTIME); + test_timeout(res, &ret, "futex_lock_pi invalid timeout flag", ENOSYS); - print_result(TEST_NAME, ret); + ksft_print_cnts(); return ret; } ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2021-05-12 20:13 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-04-27 13:53 [PATCH 0/2] selftests: futex: Improve timeout testing André Almeida 2021-04-27 13:53 ` [PATCH 1/2] selftests: futex: Correctly include headers dirs André Almeida 2021-05-12 18:50 ` [tip: locking/core] " tip-bot2 for André Almeida 2021-04-27 13:53 ` [PATCH 2/2] selftests: futex: Expand timeout test André Almeida 2021-05-12 18:50 ` [tip: locking/core] " tip-bot2 for André Almeida
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.