[LTP] [PATCH V7 07/19] syscalls/futex: Add support for time64 tests

Cyril Hrubis chrubis@suse.cz
Fri Jul 3 14:45:48 CEST 2020


Hi!
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> Reviewed-by: Petr Vorel <pvorel@suse.cz>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  .../syscalls/futex/futex_cmp_requeue01.c      |  34 +++-
>  .../syscalls/futex/futex_cmp_requeue02.c      |  24 ++-
>  testcases/kernel/syscalls/futex/futex_utils.h |  52 +++++--
>  .../kernel/syscalls/futex/futex_wait01.c      |  79 +++++-----
>  .../kernel/syscalls/futex/futex_wait02.c      | 102 ++++++------
>  .../kernel/syscalls/futex/futex_wait03.c      |  87 ++++++-----
>  .../kernel/syscalls/futex/futex_wait04.c      |  81 +++++-----
>  .../kernel/syscalls/futex/futex_wait05.c      |   2 +-
>  .../syscalls/futex/futex_wait_bitset01.c      |  48 ++++--
>  .../kernel/syscalls/futex/futex_wake01.c      |  67 ++++----
>  .../kernel/syscalls/futex/futex_wake02.c      |  95 ++++++------
>  .../kernel/syscalls/futex/futex_wake03.c      | 109 +++++++------
>  .../kernel/syscalls/futex/futex_wake04.c      | 145 +++++++++---------
>  testcases/kernel/syscalls/futex/futextest.h   | 122 ++++++++++-----
>  14 files changed, 580 insertions(+), 467 deletions(-)
> 
> diff --git a/testcases/kernel/syscalls/futex/futex_cmp_requeue01.c b/testcases/kernel/syscalls/futex/futex_cmp_requeue01.c
> index c50fade9f969..537641766357 100644
> --- a/testcases/kernel/syscalls/futex/futex_cmp_requeue01.c
> +++ b/testcases/kernel/syscalls/futex/futex_cmp_requeue01.c
> @@ -42,14 +42,29 @@ static struct tcase {
>  	{1000, 300, 500},
>  };
>  
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	enum tst_ts_type tstype;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .tstype = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .tstype = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
>  static void do_child(void)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
> +	struct tst_ts usec = tst_ts_from_ms(tv->tstype, max_sleep_ms);
>  	int slept_for_ms = 0;
> -	struct timespec usec = tst_timespec_from_ms(max_sleep_ms);
>  	int pid = getpid();
>  	int ret = 0;
>  
> -	if (futex_wait(&sd->futexes[0], sd->futexes[0], &usec, 0) == -1) {
> +	if (futex_wait(tv->fntype, &sd->futexes[0], sd->futexes[0], &usec, 0) == -1) {
>  		if (errno == EAGAIN) {
>  			/* spurious wakeup or signal */
>  			tst_atomic_inc(&sd->spurious);
> @@ -72,6 +87,7 @@ static void do_child(void)
>  
>  static void verify_futex_cmp_requeue(unsigned int n)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
>  	int num_requeues = 0, num_waits = 0, num_total = 0;
>  	int i, status, spurious, woken_up;
>  	struct tcase *tc = &tcases[n];
> @@ -104,8 +120,8 @@ static void verify_futex_cmp_requeue(unsigned int n)
>  	 * specifies an upper limit on the number of waiters that are requeued.
>  	 * Returns the total number of waiters that were woken up or requeued.
>  	 */
> -	TEST(futex_cmp_requeue(&sd->futexes[0], sd->futexes[0], &sd->futexes[1],
> -		tc->set_wakes, tc->set_requeues, 0));
> +	TEST(futex_cmp_requeue(tv->fntype, &sd->futexes[0], sd->futexes[0],
> +			&sd->futexes[1], tc->set_wakes, tc->set_requeues, 0));
>  
>  	/* Fail if more than requested wakes + requeues were returned */
>  	if (TST_RET > exp_ret) {
> @@ -115,8 +131,8 @@ static void verify_futex_cmp_requeue(unsigned int n)
>  		tst_res(TINFO, "futex_cmp_requeue() returned %ld", TST_RET);
>  	}
>  
> -	num_requeues = futex_wake(&sd->futexes[1], tc->num_waiters, 0);
> -	num_waits = futex_wake(&sd->futexes[0], tc->num_waiters, 0);
> +	num_requeues = futex_wake(tv->fntype, &sd->futexes[1], tc->num_waiters, 0);
> +	num_waits = futex_wake(tv->fntype, &sd->futexes[0], tc->num_waiters, 0);
>  
>  	tst_atomic_store(1, &sd->test_done);
>  	for (i = 0; i < tc->num_waiters; i++) {
> @@ -178,6 +194,11 @@ static void verify_futex_cmp_requeue(unsigned int n)
>  
>  static void setup(void)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
> +
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
> +
>  	max_sleep_ms = tst_multiply_timeout(5000);
>  
>  	sd = SAFE_MMAP(NULL, sizeof(*sd), PROT_READ | PROT_WRITE,
> @@ -198,5 +219,6 @@ static struct tst_test test = {
>  	.cleanup = cleanup,
>  	.tcnt = ARRAY_SIZE(tcases),
>  	.test = verify_futex_cmp_requeue,
> +	.test_variants = ARRAY_SIZE(variants),
>  	.forks_child = 1,
>  };
> diff --git a/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c b/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
> index 228d8cff6ea0..dd8fafb3ee38 100644
> --- a/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
> +++ b/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
> @@ -32,12 +32,26 @@ static struct tcase {
>  	{1, 1, FUTEX_INITIALIZER + 1, EAGAIN},
>  };
>  
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
>  static void verify_futex_cmp_requeue(unsigned int n)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
>  	struct tcase *tc = &tcases[n];
>  
> -	TEST(futex_cmp_requeue(&futexes[0], tc->exp_val, &futexes[1],
> -	     tc->set_wakes, tc->set_requeues, 0));
> +	TEST(futex_cmp_requeue(tv->fntype, &futexes[0], tc->exp_val,
> +			&futexes[1], tc->set_wakes, tc->set_requeues, 0));
>  	if (TST_RET != -1) {
>  		tst_res(TFAIL, "futex_cmp_requeue() succeeded unexpectedly");
>  		return;
> @@ -55,6 +69,11 @@ static void verify_futex_cmp_requeue(unsigned int n)
>  
>  static void setup(void)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
> +
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
> +
>  	futexes = SAFE_MMAP(NULL, sizeof(futex_t) * 2, PROT_READ | PROT_WRITE,
>  			    MAP_ANONYMOUS | MAP_SHARED, -1, 0);
>  
> @@ -73,6 +92,7 @@ static struct tst_test test = {
>  	.cleanup = cleanup,
>  	.test = verify_futex_cmp_requeue,
>  	.tcnt = ARRAY_SIZE(tcases),
> +	.test_variants = ARRAY_SIZE(variants),
>  	.tags = (const struct tst_tag[]) {
>  		{"CVE", "2018-6927"},
>  		{"linux-git", "fbe0e839d1e2"},
> diff --git a/testcases/kernel/syscalls/futex/futex_utils.h b/testcases/kernel/syscalls/futex/futex_utils.h
> index 63b97c00b631..f77b9d6b3b8a 100644
> --- a/testcases/kernel/syscalls/futex/futex_utils.h
> +++ b/testcases/kernel/syscalls/futex/futex_utils.h
> @@ -20,10 +20,13 @@
>  #ifndef FUTEX_UTILS_H__
>  #define FUTEX_UTILS_H__
>  
> +#include <stdio.h>
> +#include <stdlib.h>
> +
>  /*
>   * Wait for nr_threads to be sleeping
>   */
> -static int wait_for_threads(unsigned int nr_threads)
> +static inline int wait_for_threads(unsigned int nr_threads)
>  {
>  	char thread_state, name[1024];
>  	DIR *dir;
> @@ -32,34 +35,63 @@ static int wait_for_threads(unsigned int nr_threads)
>  
>  	snprintf(name, sizeof(name), "/proc/%i/task/", getpid());
>  
> -	dir = SAFE_OPENDIR(NULL, name);
> +	dir = SAFE_OPENDIR(name);
>  
> -	while ((dent = SAFE_READDIR(NULL, dir))) {
> +	while ((dent = SAFE_READDIR(dir))) {
>  		/* skip ".", ".." and the main thread */
>  		if (atoi(dent->d_name) == getpid() || atoi(dent->d_name) == 0)
>  			continue;
>  
>  		snprintf(name, sizeof(name), "/proc/%i/task/%s/stat",
> -		         getpid(), dent->d_name);
> +			 getpid(), dent->d_name);
>  
> -		SAFE_FILE_SCANF(NULL, name, "%*i %*s %c", &thread_state);
> +		SAFE_FILE_SCANF(name, "%*i %*s %c", &thread_state);
>  
>  		if (thread_state != 'S') {
> -			tst_resm(TINFO, "Thread %s not sleeping yet", dent->d_name);
> -			SAFE_CLOSEDIR(NULL, dir);
> +			tst_res(TINFO, "Thread %s not sleeping yet", dent->d_name);
> +			SAFE_CLOSEDIR(dir);
>  			return 1;
>  		}
>  		cnt++;
>  	}
>  
> -	SAFE_CLOSEDIR(NULL, dir);
> +	SAFE_CLOSEDIR(dir);
>  
>  	if (cnt != nr_threads) {
> -		tst_resm(TINFO, "%u threads sleeping, expected %u",
> -	                  cnt, nr_threads);
> +		tst_res(TINFO, "%u threads sleeping, expected %u", cnt,
> +			nr_threads);
>  	}
>  
>  	return 0;
>  }
>  
> +static inline int process_state_wait2(pid_t pid, const char state)
> +{
> +	char proc_path[128], cur_state;
> +
> +	snprintf(proc_path, sizeof(proc_path), "/proc/%i/stat", pid);
> +
> +	for (;;) {
> +		FILE *f = fopen(proc_path, "r");
> +		if (!f) {
> +			tst_res(TFAIL, "Failed to open '%s': %s\n", proc_path,
> +				strerror(errno));
> +			return 1;
> +		}
> +
> +		if (fscanf(f, "%*i %*s %c", &cur_state) != 1) {
> +			fclose(f);
> +			tst_res(TFAIL, "Failed to read '%s': %s\n", proc_path,
> +				strerror(errno));
> +			return 1;
> +		}
> +		fclose(f);
> +
> +		if (state == cur_state)
> +			return 0;
> +
> +		usleep(10000);
> +	}
> +}

There is no reason not to use the TST_PROCESS_STATE_WAIT() in the new
API tests. The old API was broken in child processes hence the special
function for children.

>  #endif /* FUTEX_UTILS_H__ */
> diff --git a/testcases/kernel/syscalls/futex/futex_wait01.c b/testcases/kernel/syscalls/futex/futex_wait01.c
> index 51a540d9e315..e884e696ef55 100644
> --- a/testcases/kernel/syscalls/futex/futex_wait01.c
> +++ b/testcases/kernel/syscalls/futex/futex_wait01.c
> @@ -1,3 +1,4 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
>   *
> @@ -5,34 +6,15 @@
>   * written by Darren Hart <dvhltc@us.ibm.com>
>   *            Gowrishankar <gowrishankar.m@in.ibm.com>
>   *
> - * Licensed under the GNU GPLv2 or later.
> - * This program is free software;  you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY;  without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> - * the GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program;  if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + * 1. Block on a futex and wait for timeout.
> + * 2. Test if FUTEX_WAIT op returns -EWOULDBLOCK if the futex value differs
> + *    from the expected one.
>   */
> - /*
> -  * 1. Block on a futex and wait for timeout.
> -  * 2. Test if FUTEX_WAIT op returns -EWOULDBLOCK if the futex value differs
> -  *    from the expected one.
> -  */
>  
>  #include <errno.h>
>  
> -#include "test.h"
>  #include "futextest.h"
>  
> -const char *TCID="futex_wait01";
> -
>  struct testcase {
>  	futex_t *f_addr;
>  	futex_t f_val;
> @@ -41,7 +23,6 @@ struct testcase {
>  };
>  
>  static futex_t futex = FUTEX_INITIALIZER;
> -static struct timespec to = {.tv_sec = 0, .tv_nsec = 10000};
>  
>  static struct testcase testcases[] = {
>  	{&futex, FUTEX_INITIALIZER, 0, ETIMEDOUT},
> @@ -50,38 +31,58 @@ static struct testcase testcases[] = {
>  	{&futex, FUTEX_INITIALIZER+1, FUTEX_PRIVATE_FLAG, EWOULDBLOCK},
>  };
>  
> -const int TST_TOTAL=ARRAY_SIZE(testcases);
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	enum tst_ts_type tstype;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .tstype = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .tstype = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
>  
> -static void verify_futex_wait(struct testcase *tc)
> +static void run(unsigned int n)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
> +	struct testcase *tc = &testcases[n];
> +	static struct tst_ts to;

Why the static here?

>  	int res;
>  
> -	res = futex_wait(tc->f_addr, tc->f_val, &to, tc->opflags);
> +	to.type = tv->tstype;
> +	tst_ts_set_sec(&to, 0);
> +	tst_ts_set_nsec(&to, 10000);

Maybe it would be easier to write it as:

struct tst_ts to = tst_ts_from_ns(tv->ts_type, 10000);

> +	res = futex_wait(tv->fntype, tc->f_addr, tc->f_val, &to, tc->opflags);
>  
>  	if (res != -1) {
> -		tst_resm(TFAIL, "futex_wait() returned %i, expected -1", res);
> +		tst_res(TFAIL, "futex_wait() succeeded unexpectedly");
>  		return;
>  	}
>  
>  	if (errno != tc->exp_errno) {
> -		tst_resm(TFAIL | TERRNO, "expected errno=%s",
> +		tst_res(TFAIL | TTERRNO, "futex_wait() failed with incorrect error, expected errno=%s",
>  		         tst_strerrno(tc->exp_errno));
>  		return;
>  	}
>  
> -	tst_resm(TPASS | TERRNO, "futex_wait()");
> +	tst_res(TPASS | TERRNO, "futex_wait() passed");
>  }
>  
> -int main(int argc, char *argv[])
> +static void setup(void)
>  {
> -	int lc, i;
> +	struct test_variants *tv = &variants[tst_variant];
>  
> -	tst_parse_opts(argc, argv, NULL, NULL);
> -
> -	for (lc = 0; TEST_LOOPING(lc); lc++) {
> -		for (i = 0; i < TST_TOTAL; i++)
> -			verify_futex_wait(testcases + i);
> -	}
> -
> -	tst_exit();
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
>  }
> +
> +static struct tst_test test = {
> +	.setup = setup,
> +	.test = run,
> +	.tcnt = ARRAY_SIZE(testcases),
> +	.test_variants = ARRAY_SIZE(variants),
> +};
> diff --git a/testcases/kernel/syscalls/futex/futex_wait02.c b/testcases/kernel/syscalls/futex/futex_wait02.c
> index 1ca1df457b4a..34b78357f6e6 100644
> --- a/testcases/kernel/syscalls/futex/futex_wait02.c
> +++ b/testcases/kernel/syscalls/futex/futex_wait02.c
> @@ -1,105 +1,93 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
>   *
> - * Licensed under the GNU GPLv2 or later.
> - * This program is free software;  you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> + * Block on a futex and wait for wakeup.
>   *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY;  without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> - * the GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program;  if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + * This tests uses shared memory page to store the mutex variable.
>   */
> - /*
> -  * Block on a futex and wait for wakeup.
> -  *
> -  * This tests uses shared memory page to store the mutex variable.
> -  */
>  
>  #include <sys/mman.h>
>  #include <sys/wait.h>
>  #include <errno.h>
>  
> -#include "test.h"
> -#include "safe_macros.h"
>  #include "futextest.h"
> -
> -const char *TCID="futex_wait02";
> -const int TST_TOTAL=1;
> +#include "futex_utils.h"
>  
>  static futex_t *futex;
>  
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
>  static void do_child(void)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
>  	int ret;
>  
> -	tst_process_state_wait2(getppid(), 'S');
> +	process_state_wait2(getppid(), 'S');
>  
> -	ret = futex_wake(futex, 1, 0);
> +	ret = futex_wake(tv->fntype, futex, 1, 0);
>  
>  	if (ret != 1)
> -		tst_brkm(TFAIL, NULL, "futex_wake() returned %i", ret);
> +		tst_res(TFAIL | TTERRNO, "futex_wake() failed");
>  
> -	exit(TPASS);
> +	exit(0);
>  }
>  
> -static void verify_futex_wait(void)
> +static void run(void)
>  {
> -	int res;
> -	int pid;
> +	struct test_variants *tv = &variants[tst_variant];
> +	int res, pid;
>  
> -	pid = tst_fork();
> +	pid = SAFE_FORK();
>  
>  	switch (pid) {
>  	case 0:
>  		do_child();
> -	break;
> -	case -1:
> -		tst_brkm(TBROK | TERRNO, NULL, "fork() failed");
> -	break;
>  	default:
> -	break;
> +		break;
>  	}

Well we no longer have to check for the failure so maybe simple

if (!pid)
	do_child();

would suffice here.

> -	res = futex_wait(futex, *futex, NULL, 0);
> -
> +	res = futex_wait(tv->fntype, futex, *futex, NULL, 0);
>  	if (res) {
> -		tst_resm(TFAIL, "futex_wait() returned %i, errno %s",
> -		         res, tst_strerrno(errno));
> +		tst_res(TFAIL | TTERRNO, "futex_wait() failed");
> +		return;
>  	}
>  
> -	SAFE_WAIT(NULL, &res);
> +	SAFE_WAIT(&res);
>  
>  	if (WIFEXITED(res) && WEXITSTATUS(res) == TPASS)
> -		tst_resm(TPASS, "futex_wait() woken up");
> +		tst_res(TPASS, "futex_wait() woken up");
>  	else
> -		tst_resm(TFAIL, "child failed");
> +		tst_res(TFAIL, "child failed");

And we no longer have to propagate the test status like that, we can
print PASS/FAIL in the child.

>  }
>  
>  static void setup(void)
>  {
> -	futex = SAFE_MMAP(NULL, NULL, sizeof(*futex), PROT_READ | PROT_WRITE,
> +	struct test_variants *tv = &variants[tst_variant];
> +
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
> +
> +	futex = SAFE_MMAP(NULL, sizeof(*futex), PROT_READ | PROT_WRITE,
>  			  MAP_ANONYMOUS | MAP_SHARED, -1, 0);
>  
>  	*futex = FUTEX_INITIALIZER;
>  }
>  
> -int main(int argc, char *argv[])
> -{
> -	int lc;
> -
> -	tst_parse_opts(argc, argv, NULL, NULL);
> -
> -	setup();
> -
> -	for (lc = 0; TEST_LOOPING(lc); lc++)
> -		verify_futex_wait();
> -
> -	tst_exit();
> -}
> +static struct tst_test test = {
> +	.setup = setup,
> +	.test_all = run,
> +	.test_variants = ARRAY_SIZE(variants),
> +	.forks_child = 1,
> +};
> diff --git a/testcases/kernel/syscalls/futex/futex_wait03.c b/testcases/kernel/syscalls/futex/futex_wait03.c
> index 9683e76503c0..e436b238a165 100644
> --- a/testcases/kernel/syscalls/futex/futex_wait03.c
> +++ b/testcases/kernel/syscalls/futex/futex_wait03.c
> @@ -1,87 +1,86 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
>   *
> - * Licensed under the GNU GPLv2 or later.
> - * This program is free software;  you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> + * Block on a futex and wait for wakeup.
>   *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY;  without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> - * the GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program;  if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + * This tests uses private mutexes with threads.
>   */
> - /*
> -  * Block on a futex and wait for wakeup.
> -  *
> -  * This tests uses private mutexes with threads.
> -  */
>  
>  #include <errno.h>
>  #include <pthread.h>
>  
> -#include "test.h"
>  #include "futextest.h"
> -
> -const char *TCID="futex_wait03";
> -const int TST_TOTAL=1;
> +#include "futex_utils.h"
>  
>  static futex_t futex = FUTEX_INITIALIZER;
>  
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
>  static void *threaded(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
>  	long ret;
>  
> -	tst_process_state_wait2(getpid(), 'S');
> +	process_state_wait2(getpid(), 'S');
>  
> -	ret = futex_wake(&futex, 1, FUTEX_PRIVATE_FLAG);
> +	ret = futex_wake(tv->fntype, &futex, 1, FUTEX_PRIVATE_FLAG);
>  
>  	return (void*)ret;
>  }
>  
> -static void verify_futex_wait(void)
> +static void run(void)
>  {
> -	long ret;
> -	int res;
> +	struct test_variants *tv = &variants[tst_variant];
> +	long ret, res;
>  	pthread_t t;
>  
>  	res = pthread_create(&t, NULL, threaded, NULL);
>  	if (res) {
> -		tst_brkm(TBROK, NULL, "pthread_create(): %s",
> -	                 tst_strerrno(res));
> +		tst_res(TFAIL | TTERRNO, "pthread_create() failed");
> +		return;
>  	}

Thread functions does not set errno, they return the error instead.

Also we do have tst_safe_pthread.h for new library testcases.

> -	res = futex_wait(&futex, futex, NULL, FUTEX_PRIVATE_FLAG);
> +	res = futex_wait(tv->fntype, &futex, futex, NULL, FUTEX_PRIVATE_FLAG);
>  	if (res) {
> -		tst_resm(TFAIL, "futex_wait() returned %i, errno %s",
> -	                 res, tst_strerrno(errno));
> +		tst_res(TFAIL | TTERRNO, "futex_wait() failed");

Beware that the TTERRNO is not TERRNO. The TERRNO uses errno to print
the error while TTERRNO uses TST_ERR, so it does not make sense to use
TTERRNO if you aren't using TEST() macro.

>  		pthread_join(t, NULL);
>  		return;
>  	}
>  
>  	res = pthread_join(t, (void*)&ret);
> -	if (res)
> -		tst_brkm(TBROK, NULL, "pthread_join(): %s", tst_strerrno(res));
> +	if (res) {
> +		tst_res(TFAIL | TTERRNO, "pthread_join() failed");
> +		return;
> +	}

Here as well, pthreads functions.

>  	if (ret != 1)
> -		tst_resm(TFAIL, "futex_wake() returned %li", ret);
> +		tst_res(TFAIL, "futex_wake() returned %li", ret);
>  	else
> -		tst_resm(TPASS, "futex_wait() woken up");
> +		tst_res(TPASS, "futex_wait() woken up");

The new test library is thread safe as well, so we can print these
statements from the threaded function instead.

>  }
>  
> -int main(int argc, char *argv[])
> +static void setup(void)
>  {
> -	int lc;
> +	struct test_variants *tv = &variants[tst_variant];
>  
> -	tst_parse_opts(argc, argv, NULL, NULL);
> -
> -	for (lc = 0; TEST_LOOPING(lc); lc++)
> -		verify_futex_wait();
> -
> -	tst_exit();
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
>  }
> +
> +static struct tst_test test = {
> +	.setup = setup,
> +	.test_all = run,
> +	.test_variants = ARRAY_SIZE(variants),
> +};
> diff --git a/testcases/kernel/syscalls/futex/futex_wait04.c b/testcases/kernel/syscalls/futex/futex_wait04.c
> index b8360ff80914..8de3c90b08d3 100644
> --- a/testcases/kernel/syscalls/futex/futex_wait04.c
> +++ b/testcases/kernel/syscalls/futex/futex_wait04.c
> @@ -1,65 +1,66 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
>   *
>   * Based on futextest (futext_wait_uninitialized_heap.c)
>   * written by KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
>   *
> - * Licensed under the GNU GPLv2 or later.
> - * This program is free software;  you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY;  without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> - * the GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program;  if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + * Wait on uninitialized heap. It shold be zero and FUTEX_WAIT should return
> + * immediately. This test tests zero page handling in futex code.
>   */
> - /*
> -  * Wait on uninitialized heap. It shold be zero and FUTEX_WAIT should return
> -  * immediately. This test tests zero page handling in futex code.
> -  */
>  
>  #include <errno.h>
>  
> -#include "test.h"
> -#include "safe_macros.h"
>  #include "futextest.h"
>  
> -const char *TCID="futex_wait04";
> -const int TST_TOTAL=1;
> -static struct timespec to = {.tv_sec = 0, .tv_nsec = 10000};
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	enum tst_ts_type tstype;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .tstype = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .tstype = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
>  
> -static void verify_futex_wait(void)
> +static void run(void)
>  {
> -	int res;
> -	void *buf;
> +	struct test_variants *tv = &variants[tst_variant];
> +	static struct tst_ts to;
>  	size_t pagesize = getpagesize();
> -	buf = SAFE_MMAP(NULL, NULL, pagesize, PROT_READ|PROT_WRITE,
> -                        MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
> +	void *buf;
> +	int res;
> +
> +	buf = SAFE_MMAP(NULL, pagesize, PROT_READ|PROT_WRITE,
> +			MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
>  
> -	res = futex_wait(buf, 1, &to, 0);
> +	to.type = tv->tstype;
> +	tst_ts_set_sec(&to, 0);
> +	tst_ts_set_nsec(&to, 10000);

Here as well.

> +	res = futex_wait(tv->fntype, buf, 1, &to, 0);
>  	if (res == -1 && errno == EWOULDBLOCK)
> -		tst_resm(TPASS | TERRNO, "futex_wait() returned %i", res);
> +		tst_res(TPASS | TERRNO, "futex_wait() returned %i", res);
>  	else
> -		tst_resm(TFAIL | TERRNO, "futex_wait() returned %i", res);
> +		tst_res(TFAIL | TERRNO, "futex_wait() returned %i", res);
>  
> -	SAFE_MUNMAP(NULL, buf, pagesize);
> +	SAFE_MUNMAP(buf, pagesize);
>  }
>  
> -int main(int argc, char *argv[])
> +static void setup(void)
>  {
> -	int lc;
> -
> -	tst_parse_opts(argc, argv, NULL, NULL);
> +	struct test_variants *tv = &variants[tst_variant];
>  
> -	for (lc = 0; TEST_LOOPING(lc); lc++)
> -		verify_futex_wait();
> -
> -	tst_exit();
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
>  }
> +
> +static struct tst_test test = {
> +	.setup = setup,
> +	.test_all = run,
> +	.test_variants = ARRAY_SIZE(variants),
> +};
> diff --git a/testcases/kernel/syscalls/futex/futex_wait05.c b/testcases/kernel/syscalls/futex/futex_wait05.c
> index 2573ae177d5b..8fad5d858716 100644
> --- a/testcases/kernel/syscalls/futex/futex_wait05.c
> +++ b/testcases/kernel/syscalls/futex/futex_wait05.c
> @@ -19,7 +19,7 @@ int sample_fn(int clk_id, long long usec)
>  	futex_t futex = FUTEX_INITIALIZER;
>  
>  	tst_timer_start(clk_id);
> -	TEST(futex_wait(&futex, futex, &to, 0));
> +	TEST(syscall(SYS_futex, &futex, FUTEX_WAIT, futex, &to, NULL, 0));
>  	tst_timer_stop();
>  	tst_timer_sample();

Why aren't we adding the two functions here as well?

Is the timer library incompatible with test variants?

> diff --git a/testcases/kernel/syscalls/futex/futex_wait_bitset01.c b/testcases/kernel/syscalls/futex/futex_wait_bitset01.c
> index b8546c3e640c..a871af992572 100644
> --- a/testcases/kernel/syscalls/futex/futex_wait_bitset01.c
> +++ b/testcases/kernel/syscalls/futex/futex_wait_bitset01.c
> @@ -23,22 +23,40 @@ static struct test_case_t {
>  	{ CLOCK_REALTIME }
>  };
>  
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	enum tst_ts_type tstype;
> +	int (*gettime)(clockid_t clk_id, void *ts);
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .tstype = TST_KERN_OLD_TIMESPEC, .gettime = sys_clock_gettime, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .tstype = TST_KERN_TIMESPEC, .gettime = sys_clock_gettime64, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
>  static void verify_futex_wait_bitset(long long wait_us, clock_t clk_id)
>  {
> -	struct timespec start, to, end;
> +	struct test_variants *tv = &variants[tst_variant];
> +	struct tst_ts start, to, end;
>  	futex_t futex = FUTEX_INITIALIZER;
>  	u_int32_t bitset = 0xffffffff;
>  	int flags = clk_id == CLOCK_REALTIME ? FUTEX_CLOCK_REALTIME : 0;
>  
> +	start.type = end.type = to.type = tv->tstype;
> +
>  	tst_res(TINFO, "testing futex_wait_bitset() timeout with %s",
>  		clk_id == CLOCK_REALTIME ? "CLOCK_REALTIME" : "CLOCK_MONOTONIC");
>  
> -	clock_gettime(clk_id, &start);
> -	to = tst_timespec_add_us(start, wait_us);
> +	tv->gettime(clk_id, tst_ts_get(&start));
> +	to = tst_ts_add_us(start, wait_us);
>  
> -	TEST(futex_wait_bitset(&futex, futex, &to, bitset, flags));
> +	TEST(futex_wait_bitset(tv->fntype, &futex, futex, &to, bitset, flags));
>  
> -	clock_gettime(clk_id, &end);
> +	tv->gettime(clk_id, tst_ts_get(&end));
>  
>  	if (TST_RET != -1) {
>  		tst_res(TFAIL, "futex_wait_bitset() returned %li, expected -1",
> @@ -58,22 +76,22 @@ static void verify_futex_wait_bitset(long long wait_us, clock_t clk_id)
>  		return;
>  	}
>  
> -	if (tst_timespec_lt(end, to)) {
> +	if (tst_ts_lt(end, to)) {
>  		tst_res(TFAIL,
>  			"futex_wait_bitset() woken up prematurely %llius, expected %llius",
> -			tst_timespec_diff_us(end, start), wait_us);
> +			tst_ts_diff_us(end, start), wait_us);
>  		return;
>  	}
>  
> -	if (tst_timespec_diff_us(end, to) > THRESHOLD_US) {
> +	if (tst_ts_diff_us(end, to) > THRESHOLD_US) {
>  		tst_res(TFAIL,
>  			"futex_wait_bitset() waited too long %llius, expected %llius",
> -			tst_timespec_diff_us(end, start), wait_us);
> +			tst_ts_diff_us(end, start), wait_us);
>  		return;
>  	}
>  
>  	tst_res(TPASS, "futex_wait_bitset() waited %llius, expected %llius",
> -		tst_timespec_diff_us(end, start), wait_us);
> +		tst_ts_diff_us(end, start), wait_us);
>  }
>  
>  static void run(unsigned int n)
> @@ -82,7 +100,17 @@ static void run(unsigned int n)
>  	verify_futex_wait_bitset(DEFAULT_TIMEOUT_US, tcases[n].clk_id);
>  }
>  
> +static void setup(void)
> +{
> +	struct test_variants *tv = &variants[tst_variant];
> +
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
> +}
> +
>  static struct tst_test test = {
> +	.setup = setup,
>  	.test = run,
>  	.tcnt = ARRAY_SIZE(tcases),
> +	.test_variants = ARRAY_SIZE(variants),
>  };
> diff --git a/testcases/kernel/syscalls/futex/futex_wake01.c b/testcases/kernel/syscalls/futex/futex_wake01.c
> index 42ea6f6e6a75..2dbe8cc2f3aa 100644
> --- a/testcases/kernel/syscalls/futex/futex_wake01.c
> +++ b/testcases/kernel/syscalls/futex/futex_wake01.c
> @@ -1,33 +1,15 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
>   *
> - * Licensed under the GNU GPLv2 or later.
> - * This program is free software;  you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY;  without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> - * the GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program;  if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + * futex_wake() returns 0 (0 woken up processes) when no processes wait on the mutex.
>   */
> - /*
> -  * futex_wake() returns 0 (0 woken up processes) when no processes wait on the mutex.
> -  */
>  
>  #include <errno.h>
>  #include <limits.h>
>  
> -#include "test.h"
>  #include "futextest.h"
>  
> -const char *TCID="futex_wake01";
> -
>  struct testcase {
>  	futex_t *f_addr;
>  	int nr_wake;
> @@ -46,32 +28,45 @@ static struct testcase testcases[] = {
>  	{&futex, INT_MAX, FUTEX_PRIVATE_FLAG},
>  };
>  
> -const int TST_TOTAL=ARRAY_SIZE(testcases);
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec"},
> +#endif
>  
> -static void verify_futex_wake(struct testcase *tc)
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
> +static void run(unsigned int n)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
> +	struct testcase *tc = &testcases[n];
>  	int res;
>  
> -	res = futex_wake(tc->f_addr, tc->nr_wake, tc->opflags);
> -
> +	res = futex_wake(tv->fntype, tc->f_addr, tc->nr_wake, tc->opflags);
>  	if (res != 0) {
> -		tst_resm(TFAIL, "futex_wake() returned %i, expected 0", res);
> +		tst_res(TFAIL | TTERRNO, "futex_wake() failed");

Here as well TERRNO not TTERRNO and I guess I missed a few.

>  		return;
>  	}
>  
> -	tst_resm(TPASS, "futex_wake() returned 0");
> +	tst_res(TPASS, "futex_wake() passed");
>  }
>  
> -int main(int argc, char *argv[])
> +static void setup(void)
>  {
> -	int lc, i;
> +	struct test_variants *tv = &variants[tst_variant];
>  
> -	tst_parse_opts(argc, argv, NULL, NULL);
> -
> -	for (lc = 0; TEST_LOOPING(lc); lc++) {
> -		for (i = 0; i < TST_TOTAL; i++)
> -			verify_futex_wake(testcases + i);
> -	}
> -
> -	tst_exit();
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
>  }
> +
> +static struct tst_test test = {
> +	.setup = setup,
> +	.test = run,
> +	.tcnt = ARRAY_SIZE(testcases),
> +	.test_variants = ARRAY_SIZE(variants),
> +};
> diff --git a/testcases/kernel/syscalls/futex/futex_wake02.c b/testcases/kernel/syscalls/futex/futex_wake02.c
> index 8a4c2d58e4b9..3491839872ac 100644
> --- a/testcases/kernel/syscalls/futex/futex_wake02.c
> +++ b/testcases/kernel/syscalls/futex/futex_wake02.c
> @@ -1,40 +1,34 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
>   *
> - * Licensed under the GNU GPLv2 or later.
> - * This program is free software;  you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY;  without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> - * the GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program;  if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + * Block several threads on a private mutex, then wake them up.
>   */
> - /*
> -  * Block several threads on a private mutex, then wake them up.
> -  */
>  
>  #include <errno.h>
>  #include <pthread.h>
> +#include <sys/types.h>
>  
> -#include "test.h"
> -#include "safe_macros.h"
>  #include "futextest.h"
>  #include "futex_utils.h"
>  
> -const char *TCID="futex_wake02";
> -const int TST_TOTAL=11;
> -
>  static futex_t futex = FUTEX_INITIALIZER;
>  
>  static volatile int threads_flags[55];
>  
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
>  static int threads_awake(void)
>  {
>  	int ret = 0;
> @@ -58,9 +52,10 @@ static void clear_threads_awake(void)
>  
>  static void *threaded(void *arg)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
>  	long i = (long)arg;
>  
> -	futex_wait(&futex, futex, NULL, FUTEX_PRIVATE_FLAG);
> +	futex_wait(tv->fntype, &futex, futex, NULL, FUTEX_PRIVATE_FLAG);
>  
>  	threads_flags[i] = 1;
>  
> @@ -69,14 +64,15 @@ static void *threaded(void *arg)
>  
>  static void do_child(void)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
>  	int res, i, j, awake;
>  	pthread_t t[55];
>  
>  	for (i = 0; i < (int)ARRAY_SIZE(t); i++) {
>  		res = pthread_create(&t[i], NULL, threaded, (void*)((long)i));
>  		if (res) {
> -			tst_brkm(TBROK, NULL, "pthread_create(): %s",
> -			         tst_strerrno(res));
> +			tst_res(TFAIL | TTERRNO, "pthread_create() failed");
> +			return;

Here as well, the res contains the error and we do have SAFE_PTHREAD_...

>  		}
>  	}
>  
> @@ -85,9 +81,9 @@ static void do_child(void)
>  
>  	for (i = 1; i <= 10; i++) {
>  		clear_threads_awake();
> -		res = futex_wake(&futex, i, FUTEX_PRIVATE_FLAG);
> +		res = futex_wake(tv->fntype, &futex, i, FUTEX_PRIVATE_FLAG);
>  		if (i != res) {
> -			tst_resm(TFAIL,
> +			tst_res(TFAIL | TTERRNO,
>  			         "futex_wake() woken up %i threads, expected %i",
>  			         res, i);
>  		}
> @@ -101,26 +97,26 @@ static void do_child(void)
>  		}
>  
>  		if (awake == i) {
> -			tst_resm(TPASS, "futex_wake() woken up %i threads", i);
> +			tst_res(TPASS, "futex_wake() woken up %i threads", i);
>  		} else {
> -			tst_resm(TFAIL, "Woken up %i threads, expected %i",
> -			         awake, i);
> +			tst_res(TFAIL | TTERRNO, "Woken up %i threads, expected %i",
> +				awake, i);
>  		}
>  	}
>  
> -	res = futex_wake(&futex, 1, FUTEX_PRIVATE_FLAG);
> +	res = futex_wake(tv->fntype, &futex, 1, FUTEX_PRIVATE_FLAG);
>  
>  	if (res) {
> -		tst_resm(TFAIL, "futex_wake() woken up %i, none were waiting",
> -		         res);
> +		tst_res(TFAIL | TTERRNO, "futex_wake() woken up %i, none were waiting",
> +			res);
>  	} else {
> -		tst_resm(TPASS, "futex_wake() woken up 0 threads");
> +		tst_res(TPASS, "futex_wake() woken up 0 threads");
>  	}
>  
>  	for (i = 0; i < (int)ARRAY_SIZE(t); i++)
>  		pthread_join(t[i], NULL);
>  
> -	tst_exit();
> +	exit(0);
>  }
>  
>  /*
> @@ -135,30 +131,31 @@ static void do_child(void)
>   * under /proc/$PID/tasks/, but the subsequent open() fails with ENOENT because
>   * the thread was removed meanwhile.
>   */
> -static void verify_futex_wake(void)
> +static void run(void)
>  {
> -	int pid;
> +	int status, pid;
>  
> -	pid = tst_fork();
> +	pid = SAFE_FORK();
>  
>  	switch (pid) {
>  	case 0:
>  		do_child();
> -	case -1:
> -		tst_brkm(TBROK | TERRNO, NULL, "fork() failed");
>  	default:
> -		tst_record_childstatus(NULL, pid);
> +		SAFE_WAITPID(pid, &status, 0);
>  	}

Here as well no need for the switch () simple iff would suffice.

>  }
>  
> -int main(int argc, char *argv[])
> +static void setup(void)
>  {
> -	int lc;
> -
> -	tst_parse_opts(argc, argv, NULL, NULL);
> +	struct test_variants *tv = &variants[tst_variant];
>  
> -	for (lc = 0; TEST_LOOPING(lc); lc++)
> -		verify_futex_wake();
> -
> -	tst_exit();
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
>  }
> +
> +static struct tst_test test = {
> +	.setup = setup,
> +	.test_all = run,
> +	.test_variants = ARRAY_SIZE(variants),
> +	.forks_child = 1,
> +};
> diff --git a/testcases/kernel/syscalls/futex/futex_wake03.c b/testcases/kernel/syscalls/futex/futex_wake03.c
> index d6e5e5422db9..29e586c40132 100644
> --- a/testcases/kernel/syscalls/futex/futex_wake03.c
> +++ b/testcases/kernel/syscalls/futex/futex_wake03.c
> @@ -1,54 +1,51 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
>   *
> - * Licensed under the GNU GPLv2 or later.
> - * This program is free software;  you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY;  without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> - * the GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program;  if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + * Block several processes on a mutex, then wake them up.
>   */
> - /*
> -  * Block several processes on a mutex, then wake them up.
> -  */
>  
>  #include <errno.h>
>  #include <sys/types.h>
>  #include <sys/wait.h>
>  
> -#include "test.h"
> -#include "safe_macros.h"
>  #include "futextest.h"
> -
> -const char *TCID="futex_wake03";
> -const int TST_TOTAL=11;
> +#include "futex_utils.h"
>  
>  static futex_t *futex;
>  
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
>  static void do_child(void)
>  {
> -	futex_wait(futex, *futex, NULL, 0);
> +	struct test_variants *tv = &variants[tst_variant];
> +
> +	futex_wait(tv->fntype, futex, *futex, NULL, 0);
>  	exit(0);
>  }
>  
>  static void do_wake(int nr_children)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
>  	int res, i, cnt;
>  
> -	res = futex_wake(futex, nr_children, 0);
> +	res = futex_wake(tv->fntype, futex, nr_children, 0);
>  
>  	if (res != nr_children) {
> -		tst_resm(TFAIL,
> -		         "futex_wake() woken up %i children, expected %i",
> -		         res, nr_children);
> +		tst_res(TFAIL | TTERRNO,
> +		        "futex_wake() woken up %i children, expected %i",
> +			res, nr_children);

Does anything set the TST_ERR here?

I doubt that we will even get something in errno here.

>  		return;
>  	}
>  
> @@ -63,65 +60,63 @@ static void do_wake(int nr_children)
>  	}
>  
>  	if (cnt != nr_children) {
> -		tst_resm(TFAIL, "reaped only %i childs, expected %i",
> -		         cnt, nr_children);
> +		tst_res(TFAIL | TTERRNO, "reaped only %i childs, expected %i",
> +		        cnt, nr_children);

Here as well.

>  	} else {
> -		tst_resm(TPASS, "futex_wake() woken up %i childs", cnt);
> +		tst_res(TPASS, "futex_wake() woken up %i childs", cnt);
>  	}
>  }
>  
> -static void verify_futex_wake(void)
> +static void run(void)
>  {
> -	int i, res;
> +	struct test_variants *tv = &variants[tst_variant];
>  	pid_t pids[55];
> +	unsigned int i;
> +	int res;
>  
> -	for (i = 0; i < (int)ARRAY_SIZE(pids); i++) {
> -		pids[i] = tst_fork();
> +	for (i = 0; i < ARRAY_SIZE(pids); i++) {
> +		pids[i] = SAFE_FORK();
>  
>  		switch (pids[i]) {
> -		case -1:
> -			tst_brkm(TBROK | TERRNO, NULL, "fork()");
>  		case 0:
>  			do_child();
>  		default:
> -		break;
> +			break;
>  		}

Here as well no need for the switch anymore.

>  	}
>  
> -	for (i = 0; i < (int)ARRAY_SIZE(pids); i++)
> -		tst_process_state_wait2(pids[i], 'S');
> +	for (i = 0; i < ARRAY_SIZE(pids); i++)
> +		process_state_wait2(pids[i], 'S');
>  
>  	for (i = 1; i <= 10; i++)
>  		do_wake(i);
>  
> -	res = futex_wake(futex, 1, 0);
> +	res = futex_wake(tv->fntype, futex, 1, 0);
>  
>  	if (res) {
> -		tst_resm(TFAIL, "futex_wake() woken up %u, none were waiting",
> -		         res);
> +		tst_res(TFAIL | TTERRNO, "futex_wake() woken up %u, none were waiting",
> +			res);

Here as well no real reason to add the TTERRNO.

>  	} else {
> -		tst_resm(TPASS, "futex_wake() woken up 0 children");
> +		tst_res(TPASS, "futex_wake() woken up 0 children");
>  	}
>  }
>  
>  static void setup(void)
>  {
> -	futex = SAFE_MMAP(NULL, NULL, sizeof(*futex), PROT_READ | PROT_WRITE,
> +	struct test_variants *tv = &variants[tst_variant];
> +
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
> +
> +	futex = SAFE_MMAP(NULL, sizeof(*futex), PROT_READ | PROT_WRITE,
>  			  MAP_ANONYMOUS | MAP_SHARED, -1, 0);
>  
>  	*futex = FUTEX_INITIALIZER;
>  }
>  
> -int main(int argc, char *argv[])
> -{
> -	int lc;
> -
> -	tst_parse_opts(argc, argv, NULL, NULL);
> -
> -	setup();
> -
> -	for (lc = 0; TEST_LOOPING(lc); lc++)
> -		verify_futex_wake();
> -
> -	tst_exit();
> -}
> +static struct tst_test test = {
> +	.setup = setup,
> +	.test_all = run,
> +	.test_variants = ARRAY_SIZE(variants),
> +	.forks_child = 1,
> +};
> diff --git a/testcases/kernel/syscalls/futex/futex_wake04.c b/testcases/kernel/syscalls/futex/futex_wake04.c
> index f92bda53f6c7..582ebc4b917a 100644
> --- a/testcases/kernel/syscalls/futex/futex_wake04.c
> +++ b/testcases/kernel/syscalls/futex/futex_wake04.c
> @@ -1,23 +1,9 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Copyright (C) 2015  Yi Zhang <wetpzy@gmail.com>
>   *                     Li Wang <liwang@redhat.com>
>   *
> - * Licensed under the GNU GPLv2 or later.
> - * This program is free software;  you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY;  without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> - * the GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program;  if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> - */
> - /* DESCRIPTION:
> + * DESCRIPTION:
>   *
>   *   It is a regression test for commit:
>   *   http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/
> @@ -42,53 +28,59 @@
>  #include <sys/time.h>
>  #include <string.h>
>  
> -#include "test.h"
> -#include "safe_macros.h"
>  #include "futextest.h"
>  #include "futex_utils.h"
>  #include "lapi/mmap.h"
> +#include "tst_safe_stdio.h"
>  
>  #define PATH_MEMINFO "/proc/meminfo"
>  #define PATH_NR_HUGEPAGES "/proc/sys/vm/nr_hugepages"
>  #define PATH_HUGEPAGES	"/sys/kernel/mm/hugepages/"
>  
> -const char *TCID = "futex_wake04";
> -const int TST_TOTAL = 1;
> -
>  static futex_t *futex1, *futex2;
>  
> -static struct timespec to = {.tv_sec = 30, .tv_nsec = 0};
> +static struct tst_ts to;
>  
>  static long orig_hugepages;
>  
> +static struct test_variants {
> +	enum futex_fn_type fntype;
> +	enum tst_ts_type tstype;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX, .tstype = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .fntype = FUTEX_FN_FUTEX64, .tstype = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
>  static void setup(void)
>  {
> -	tst_require_root();
> +	struct test_variants *tv = &variants[tst_variant];
>  
> -	if ((tst_kvercmp(2, 6, 32)) < 0) {
> -		tst_brkm(TCONF, NULL, "This test can only run on kernels "
> -			"that are 2.6.32 or higher");
> -	}
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	futex_supported_by_kernel(tv->fntype);
>  
> -	if (access(PATH_HUGEPAGES, F_OK))
> -		tst_brkm(TCONF, NULL, "Huge page is not supported.");
> +	to.type = tv->tstype;
> +	tst_ts_set_sec(&to, 30);
> +	tst_ts_set_nsec(&to, 0);

Here as well.

> -	tst_tmpdir();
> +	if (access(PATH_HUGEPAGES, F_OK))
> +		tst_brk(TCONF, "Huge page is not supported.");
>  
> -	SAFE_FILE_SCANF(NULL, PATH_NR_HUGEPAGES, "%ld", &orig_hugepages);
> +	SAFE_FILE_SCANF(PATH_NR_HUGEPAGES, "%ld", &orig_hugepages);
>  
>  	if (orig_hugepages <= 0)
> -		SAFE_FILE_PRINTF(NULL, PATH_NR_HUGEPAGES, "%d", 1);
> -
> -	TEST_PAUSE;
> +		SAFE_FILE_PRINTF(PATH_NR_HUGEPAGES, "%d", 1);
>  }
>  
>  static void cleanup(void)
>  {
>  	if (orig_hugepages <= 0)
> -		SAFE_FILE_PRINTF(NULL, PATH_NR_HUGEPAGES, "%ld", orig_hugepages);
> -
> -	tst_rmdir();
> +		SAFE_FILE_PRINTF(PATH_NR_HUGEPAGES, "%ld", orig_hugepages);
>  }
>  
>  static int read_hugepagesize(void)
> @@ -97,60 +89,63 @@ static int read_hugepagesize(void)
>  	char line[BUFSIZ], buf[BUFSIZ];
>  	int val;
>  
> -	fp = SAFE_FOPEN(cleanup, PATH_MEMINFO, "r");
> +	fp = SAFE_FOPEN(PATH_MEMINFO, "r");
>  	while (fgets(line, BUFSIZ, fp) != NULL) {
>  		if (sscanf(line, "%64s %d", buf, &val) == 2)
>  			if (strcmp(buf, "Hugepagesize:") == 0) {
> -				SAFE_FCLOSE(cleanup, fp);
> +				SAFE_FCLOSE(fp);
>  				return 1024 * val;
>  			}
>  	}
>  
> -	SAFE_FCLOSE(cleanup, fp);
> -	tst_brkm(TBROK, NULL, "can't find \"%s\" in %s",
> -			"Hugepagesize:", PATH_MEMINFO);
> +	SAFE_FCLOSE(fp);
> +	tst_res(TFAIL, "can't find \"%s\" in %s", "Hugepagesize:",
> +		PATH_MEMINFO);
> +	return 0;

We just got:

commit a29f542c8b3029cc074ae5a766dfc7dca92c9225
Author: Martin Doucha <mdoucha@suse.cz>
Date:   Thu Jul 2 12:01:50 2020 +0200

    lib: Add tst_get_hugepage_size() to LTP library


>  }
>  
>  static void *wait_thread1(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> -	futex_wait(futex1, *futex1, &to, 0);
> +	struct test_variants *tv = &variants[tst_variant];
> +
> +	futex_wait(tv->fntype, futex1, *futex1, &to, 0);
>  
>  	return NULL;
>  }
>  
>  static void *wait_thread2(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
>  	int res;
>  
> -	res = futex_wait(futex2, *futex2, &to, 0);
> +	res = futex_wait(tv->fntype, futex2, *futex2, &to, 0);
>  	if (!res)
> -		tst_resm(TPASS, "Hi hydra, thread2 awake!");
> +		tst_res(TPASS, "Hi hydra, thread2 awake!");
>  	else
> -		tst_resm(TFAIL, "Bug: wait_thread2 did not wake after 30 secs.");
> +		tst_res(TFAIL | TTERRNO, "Bug: wait_thread2 did not wake after 30 secs.");
>  
>  	return NULL;
>  }
>  
>  static void wakeup_thread2(void)
>  {
> +	struct test_variants *tv = &variants[tst_variant];
>  	void *addr;
>  	int hpsz, pgsz, res;
>  	pthread_t th1, th2;
>  
>  	hpsz = read_hugepagesize();
> -	tst_resm(TINFO, "Hugepagesize %i", hpsz);
> +	tst_res(TINFO, "Hugepagesize %i", hpsz);
>  
>  	/*allocate some shared memory*/
>  	addr = mmap(NULL, hpsz, PROT_WRITE | PROT_READ,
>  	            MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
>  
>  	if (addr == MAP_FAILED) {
> -		if (errno == ENOMEM) {
> -			tst_brkm(TCONF, NULL,
> -				 "Cannot allocate hugepage, memory too fragmented?");
> -		}
> +		if (errno == ENOMEM)
> +			tst_brk(TCONF, "Cannot allocate hugepage, memory too fragmented?");
>  
> -		tst_brkm(TBROK | TERRNO, NULL, "Cannot allocate hugepage");
> +		tst_brk(TBROK | TERRNO, "Cannot allocate hugepage");
>  	}
>  
>  	pgsz = getpagesize();
> @@ -165,45 +160,47 @@ static void wakeup_thread2(void)
>  	/*thread1 block on futex1 first,then thread2 block on futex2*/
>  	res = pthread_create(&th1, NULL, wait_thread1, NULL);
>  	if (res) {
> -		tst_brkm(TBROK, NULL, "pthread_create(): %s",
> -				tst_strerrno(res));
> +		tst_res(TFAIL | TTERRNO, "pthread_create() failed");

Here as well SAFE_PTHREAD().

> +		return;
>  	}
>  
>  	res = pthread_create(&th2, NULL, wait_thread2, NULL);
>  	if (res) {
> -		tst_brkm(TBROK, NULL, "pthread_create(): %s",
> -				tst_strerrno(res));
> +		tst_res(TFAIL | TTERRNO, "pthread_create() failed");
> +		return;
>  	}
>  
>  	while (wait_for_threads(2))
>  		usleep(1000);
>  
> -	futex_wake(futex2, 1, 0);
> +	futex_wake(tv->fntype, futex2, 1, 0);
>  
>  	res = pthread_join(th2, NULL);
> -	if (res)
> -		tst_brkm(TBROK, NULL, "pthread_join(): %s", tst_strerrno(res));
> +	if (res) {
> +		tst_res(TFAIL | TTERRNO, "pthread_join() failed");
> +		return;
> +	}
>  
> -	futex_wake(futex1, 1, 0);
> +	futex_wake(tv->fntype, futex1, 1, 0);
>  
>  	res = pthread_join(th1, NULL);
>  	if (res)
> -		tst_brkm(TBROK, NULL, "pthread_join(): %s", tst_strerrno(res));
> +		tst_res(TFAIL | TTERRNO, "pthread_join() failed");
>  
> -	SAFE_MUNMAP(NULL, addr, hpsz);
> +	SAFE_MUNMAP(addr, hpsz);
>  }
>  
> -int main(int argc, char *argv[])
> +static void run(void)
>  {
> -	int lc;
> -
> -	tst_parse_opts(argc, argv, NULL, NULL);
> -
> -	setup();
> -
> -	for (lc = 0; TEST_LOOPING(lc); lc++)
> -		wakeup_thread2();
> -
> -	cleanup();
> -	tst_exit();
> +	wakeup_thread2();
>  }
> +
> +static struct tst_test test = {
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.test_all = run,
> +	.test_variants = ARRAY_SIZE(variants),
> +	.needs_root = 1,
> +	.min_kver = "2.6.32",
> +	.needs_tmpdir = 1,
> +};
> diff --git a/testcases/kernel/syscalls/futex/futextest.h b/testcases/kernel/syscalls/futex/futextest.h
> index 5754d36dae51..b72d83bc711b 100644
> --- a/testcases/kernel/syscalls/futex/futextest.h
> +++ b/testcases/kernel/syscalls/futex/futextest.h
> @@ -39,6 +39,7 @@
>  #include <sys/types.h>
>  #include <linux/futex.h>
>  #include "lapi/futex.h"
> +#include "tst_timer.h"
>  
>  #define FUTEX_INITIALIZER 0
>  
> @@ -82,18 +83,35 @@
>  # define FUTEX_CLOCK_REALTIME 256
>  #endif
>  
> +enum futex_fn_type {
> +	FUTEX_FN_FUTEX,
> +	FUTEX_FN_FUTEX64,
> +};
> +
> +static inline void futex_supported_by_kernel(enum futex_fn_type fntype)
> +{
> +	if (fntype != FUTEX_FN_FUTEX64)
> +		return;
> +
> +	/* Check if the syscall is implemented on the platform */
> +	TEST(sys_futex_time64(NULL, 0, 0, NULL, NULL, 0));
> +	if (TST_RET == -1 && TST_ERR == ENOSYS)
> +		tst_brk(TCONF, "Test not supported on kernel/platform");
> +}
> +
>  /**
> - * futex() - SYS_futex syscall wrapper
> + * futex_syscall() - futex syscall wrapper
> + * @fntype:	Futex function type
>   * @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 tst_ts (except where noted
>   *		otherwise). Overloaded by some ops
>   * @uaddr2:	address of second futex for some ops\
>   * @val3:	varies by op
>   * @opflags:	flags to be bitwise OR'd with op, such as FUTEX_PRIVATE_FLAG
>   *
> - * futex() is used by all the following futex op wrappers. It can also be
> + * futex_syscall() is used by all the following futex op wrappers. It can also be
>   * used for misuse and abuse testing. Generally, the specific op wrappers
>   * should be used instead. It is a macro instead of an static inline function as
>   * some of the types over overloaded (timeout is used for nr_requeue for
> @@ -102,17 +120,30 @@
>   * 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)
> +static inline int futex_syscall(enum futex_fn_type fntype, futex_t *uaddr,
> +				int futex_op, futex_t val, void *timeout,
> +				futex_t *uaddr2, int val3, int opflags)
> +{
> +	int (*func)(int *uaddr, int futex_op, int val, void *to, int *uaddr2, int val3);
> +
> +	if (fntype == FUTEX_FN_FUTEX)
> +		func = sys_futex;
> +	else
> +		func = sys_futex_time64;
> +
> +	return func((int *)uaddr, futex_op | opflags, val, timeout, (int *)uaddr2, val3);
> +}
>  
>  /**
>   * 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(enum futex_fn_type fntype, futex_t *uaddr, futex_t val,
> +	   struct tst_ts *timeout, int opflags)
>  {
> -	return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
> +	return futex_syscall(fntype, uaddr, FUTEX_WAIT, val,
> +			     tst_ts_get(timeout), NULL, 0, opflags);
>  }
>  
>  /**
> @@ -120,9 +151,10 @@ futex_wait(futex_t *uaddr, futex_t val, struct timespec *timeout, int opflags)
>   * @nr_wake:	wake up to this many tasks
>   */
>  static inline int
> -futex_wake(futex_t *uaddr, int nr_wake, int opflags)
> +futex_wake(enum futex_fn_type fntype, futex_t *uaddr, int nr_wake, int opflags)
>  {
> -	return futex(uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0, opflags);
> +	return futex_syscall(fntype, uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0,
> +			     opflags);
>  }
>  
>  /**
> @@ -130,11 +162,11 @@ 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,
> -		  u_int32_t bitset, int opflags)
> +futex_wait_bitset(enum futex_fn_type fntype, futex_t *uaddr, futex_t val,
> +		  struct tst_ts *timeout, u_int32_t bitset, int opflags)
>  {
> -	return futex(uaddr, FUTEX_WAIT_BITSET, val, timeout, NULL, bitset,
> -		     opflags);
> +	return futex_syscall(fntype, uaddr, FUTEX_WAIT_BITSET, val,
> +			     tst_ts_get(timeout), NULL, bitset, opflags);
>  }
>  
>  /**
> @@ -142,10 +174,11 @@ futex_wait_bitset(futex_t *uaddr, futex_t val, struct timespec *timeout,
>   * @bitset:	bitset to compare with that used in futex_wait_bitset
>   */
>  static inline int
> -futex_wake_bitset(futex_t *uaddr, int nr_wake, u_int32_t bitset, int opflags)
> +futex_wake_bitset(enum futex_fn_type fntype, futex_t *uaddr, int nr_wake,
> +		  u_int32_t bitset, int opflags)
>  {
> -	return futex(uaddr, FUTEX_WAKE_BITSET, nr_wake, NULL, NULL, bitset,
> -		     opflags);
> +	return futex_syscall(fntype, uaddr, FUTEX_WAKE_BITSET, nr_wake, NULL,
> +			     NULL, bitset, opflags);
>  }
>  
>  /**
> @@ -153,30 +186,32 @@ 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,
> -	      int opflags)
> +futex_lock_pi(enum futex_fn_type fntype, futex_t *uaddr, struct tst_ts *timeout,
> +	      int detect, int opflags)
>  {
> -	return futex(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags);
> +	return futex_syscall(fntype, uaddr, FUTEX_LOCK_PI, detect,
> +			     tst_ts_get(timeout), NULL, 0, opflags);
>  }
>  
>  /**
>   * futex_unlock_pi() - release uaddr as a PI mutex, waking the top waiter
>   */
>  static inline int
> -futex_unlock_pi(futex_t *uaddr, int opflags)
> +futex_unlock_pi(enum futex_fn_type fntype, futex_t *uaddr, int opflags)
>  {
> -	return futex(uaddr, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0, opflags);
> -}
> +	return futex_syscall(fntype, uaddr, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0,
> +			     opflags); }
>  
>  /**
>   * futex_wake_op() - FIXME: COME UP WITH A GOOD ONE LINE DESCRIPTION
>   */
>  static inline int
> -futex_wake_op(futex_t *uaddr, futex_t *uaddr2, int nr_wake, int nr_wake2,
> -	      int wake_op, int opflags)
> +futex_wake_op(enum futex_fn_type fntype, futex_t *uaddr, futex_t *uaddr2,
> +	      int nr_wake, int nr_wake2, int wake_op, int opflags)
>  {
> -	return futex(uaddr, FUTEX_WAKE_OP, nr_wake, nr_wake2, uaddr2, wake_op,
> -		     opflags);
> +	return futex_syscall(fntype, uaddr, FUTEX_WAKE_OP, nr_wake,
> +			     (void *)((unsigned long)nr_wake2), uaddr2, wake_op,
> +			     opflags);
>  }
>  
>  /**
> @@ -188,11 +223,12 @@ futex_wake_op(futex_t *uaddr, futex_t *uaddr2, int nr_wake, int nr_wake2,
>   * favor of futex_cmp_requeue().
>   */
>  static inline int
> -futex_requeue(futex_t *uaddr, futex_t *uaddr2, int nr_wake, int nr_requeue,
> -	      int opflags)
> +futex_requeue(enum futex_fn_type fntype, futex_t *uaddr, futex_t *uaddr2,
> +	      int nr_wake, int nr_requeue, int opflags)
>  {
> -	return futex(uaddr, FUTEX_REQUEUE, nr_wake, nr_requeue, uaddr2, 0,
> -		     opflags);
> +	return futex_syscall(fntype, uaddr, FUTEX_REQUEUE, nr_wake,
> +			     (void *)((unsigned long)nr_requeue), uaddr2, 0,
> +			     opflags);
>  }
>  
>  /**
> @@ -201,11 +237,12 @@ futex_requeue(futex_t *uaddr, futex_t *uaddr2, int nr_wake, int nr_requeue,
>   * @nr_requeue:	requeue up to this many tasks
>   */
>  static inline int
> -futex_cmp_requeue(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake,
> -		  int nr_requeue, int opflags)
> +futex_cmp_requeue(enum futex_fn_type fntype, futex_t *uaddr, futex_t val,
> +		  futex_t *uaddr2, int nr_wake, int nr_requeue, int opflags)
>  {
> -	return futex(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
> -		     val, opflags);
> +	return futex_syscall(fntype, uaddr, FUTEX_CMP_REQUEUE, nr_wake,
> +			     (void *)((unsigned long)nr_requeue), uaddr2, val,
> +			     opflags);
>  }
>  
>  /**
> @@ -217,11 +254,11 @@ futex_cmp_requeue(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake,
>   * paired with futex_cmp_requeue_pi().
>   */
>  static inline int
> -futex_wait_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2,
> -		      struct timespec *timeout, int opflags)
> +futex_wait_requeue_pi(enum futex_fn_type fntype, futex_t *uaddr, futex_t val,
> +		      futex_t *uaddr2, struct tst_ts *timeout, int opflags)
>  {
> -	return futex(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0,
> -		     opflags);
> +	return futex_syscall(fntype, uaddr, FUTEX_WAIT_REQUEUE_PI, val,
> +			     tst_ts_get(timeout), uaddr2, 0, opflags);
>  }
>  
>  /**
> @@ -232,11 +269,12 @@ futex_wait_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2,
>   * @nr_requeue:	requeue up to this many tasks
>   */
>  static inline int
> -futex_cmp_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake,
> -		     int nr_requeue, int opflags)
> +futex_cmp_requeue_pi(enum futex_fn_type fntype, futex_t *uaddr, futex_t val,
> +		     futex_t *uaddr2, int nr_wake, int nr_requeue, int opflags)
>  {
> -	return futex(uaddr, FUTEX_CMP_REQUEUE_PI, nr_wake, nr_requeue, uaddr2, val,
> -		     opflags);
> +	return futex_syscall(fntype, uaddr, FUTEX_CMP_REQUEUE_PI, nr_wake,
> +			     (void *)((unsigned long)nr_requeue), uaddr2, val,
> +			     opflags);
>  }
>  
>  /**
> -- 
> 2.25.0.rc1.19.g042ed3e048af
> 

-- 
Cyril Hrubis
chrubis@suse.cz


More information about the ltp mailing list