All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants
@ 2020-06-26  6:22 Viresh Kumar
  2020-06-26  6:22 ` [LTP] [PATCH V7 01/19] tst_timer: Add new definitions Viresh Kumar
                   ` (19 more replies)
  0 siblings, 20 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

Hi,

This updates the pending syscall tests that lacked the time64 updates.

V7:
- Move all tst_timer.h changes to a single patch.
- Provide more generic helpers for itimerspec and update the patches
  accordingly.
- Also include the y2038 patch in the series as that depends on the
  first patch here.

V6: Drop the binary files included by mistake.
V5: Use __kernel_old_itimerspec instead of __kernel_itimerspec.
V4:
- Pass timer_t type to timer_gettime/settime syscalls instead of
  kernel_timer_t.
- Some part of timer_settime() patch was merged in timerfd_gettime()
  earlier by mistake, fixed that.

V3:
- Fix issues related to passing incorrect timespec type to syscalls.
- Take care of futex and semtimedop tests where the architecture
  provides the syscall number, but doesn't implement it.
- Other improvements and cleanups.

Viresh Kumar (19):
  tst_timer: Add new definitions
  syscalls/timer_gettime: Add support for time64 tests
  syscalls/timer_settime: Add support for time64 tests
  syscalls/timerfd: Add support for time64 tests
  syscalls/sched_rr_get_interval: Add support for time64 tests
  syscalls/futex: Merge futex_wait_bitset tests
  syscalls/futex: Add support for time64 tests
  syscalls/io_pgetevents: Add support for time64 tests
  syscalls/sigwaitinfo: Migrate to new test framework
  syscalls/rt_sigtimedwait: Add support for time64 tests
  syscalls/mq_timed{send|receive}: Add support for time64 tests
  syscalls/recvmmsg: Add support for time64 tests
  syscalls/ppoll: Add support for time64 tests
  syscalls/select6: Add support for time64 tests
  syscalls/semop: Migrate to new test framework
  syscalls/semtimedop: Add support for semtimedop and its time64 version
  syscalls/utimensat: Migrate to new test framework
  syscalls/utimensat: Add support for time64 tests
  syscalls: clock_settime: Add test around y2038 vulnerability

 include/lapi/io_pgetevents.h                  |  15 +-
 include/tst_timer.h                           | 326 ++++++++++-
 runtest/syscalls                              |   4 +-
 .../kernel/syscalls/clock_settime/.gitignore  |   1 +
 .../syscalls/clock_settime/clock_settime03.c  | 119 ++++
 testcases/kernel/syscalls/futex/.gitignore    |   1 -
 testcases/kernel/syscalls/futex/Makefile      |   1 -
 .../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 +-
 .../kernel/syscalls/futex/futex_wait_bitset.h |  75 ---
 .../syscalls/futex/futex_wait_bitset01.c      | 101 +++-
 .../syscalls/futex/futex_wait_bitset02.c      |  18 -
 .../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 +++--
 .../syscalls/io_pgetevents/io_pgetevents01.c  |  33 +-
 .../syscalls/io_pgetevents/io_pgetevents02.c  |  51 +-
 testcases/kernel/syscalls/ipc/semop/Makefile  |   4 +-
 testcases/kernel/syscalls/ipc/semop/semop.h   |  55 ++
 testcases/kernel/syscalls/ipc/semop/semop01.c | 148 +++--
 testcases/kernel/syscalls/ipc/semop/semop02.c | 156 +++---
 testcases/kernel/syscalls/ipc/semop/semop03.c | 162 +++---
 testcases/kernel/syscalls/ipc/semop/semop04.c | 177 +++---
 testcases/kernel/syscalls/ipc/semop/semop05.c | 313 +++++------
 .../mq_timedreceive/mq_timedreceive01.c       |  92 +++-
 .../syscalls/mq_timedsend/mq_timedsend01.c    |  96 ++--
 testcases/kernel/syscalls/ppoll/ppoll01.c     |  71 ++-
 .../sched_rr_get_interval01.c                 | 116 ++--
 .../sched_rr_get_interval02.c                 | 122 ++---
 .../sched_rr_get_interval03.c                 | 146 +++--
 testcases/kernel/syscalls/select/select_var.h |  25 +-
 .../kernel/syscalls/sendmmsg/sendmmsg01.c     |  40 +-
 .../kernel/syscalls/sendmmsg/sendmmsg_var.h   |  55 +-
 .../syscalls/sigwaitinfo/sigwaitinfo01.c      | 311 ++++++-----
 .../syscalls/timer_gettime/timer_gettime01.c  | 135 +++--
 .../syscalls/timer_settime/timer_settime01.c  |  51 +-
 .../syscalls/timer_settime/timer_settime02.c  |  69 ++-
 testcases/kernel/syscalls/timerfd/timerfd01.c |  56 +-
 testcases/kernel/syscalls/timerfd/timerfd04.c |  54 +-
 .../syscalls/timerfd/timerfd_gettime01.c      | 133 ++---
 .../syscalls/timerfd/timerfd_settime01.c      | 136 +++--
 .../syscalls/timerfd/timerfd_settime02.c      |  28 +-
 testcases/kernel/syscalls/utils/mq_timed.h    |  42 +-
 testcases/kernel/syscalls/utimensat/Makefile  |   4 -
 .../kernel/syscalls/utimensat/utimensat01.c   | 472 ++++++++--------
 .../syscalls/utimensat/utimensat_tests.sh     | 517 ------------------
 54 files changed, 2819 insertions(+), 2711 deletions(-)
 create mode 100644 testcases/kernel/syscalls/clock_settime/clock_settime03.c
 delete mode 100644 testcases/kernel/syscalls/futex/futex_wait_bitset.h
 delete mode 100644 testcases/kernel/syscalls/futex/futex_wait_bitset02.c
 create mode 100644 testcases/kernel/syscalls/ipc/semop/semop.h
 delete mode 100755 testcases/kernel/syscalls/utimensat/utimensat_tests.sh

-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 01/19] tst_timer: Add new definitions
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-06-26  9:49   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 02/19] syscalls/timer_gettime: Add support for time64 tests Viresh Kumar
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This patch adds new helpers for itimerspec and wrapper functions for
multiple syscalls. These will be used by later patches.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 include/tst_timer.h | 326 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 305 insertions(+), 21 deletions(-)

diff --git a/include/tst_timer.h b/include/tst_timer.h
index 82e3e1e308f1..7fd4a7093960 100644
--- a/include/tst_timer.h
+++ b/include/tst_timer.h
@@ -12,9 +12,12 @@
 #ifndef TST_TIMER
 #define TST_TIMER
 
+#include <sched.h>
 #include <sys/time.h>
+#include <mqueue.h>
 #include <time.h>
 #include "tst_test.h"
+#include "lapi/common_timers.h"
 #include "lapi/posix_types.h"
 #include "lapi/syscalls.h"
 
@@ -112,6 +115,16 @@ struct __kernel_timespec {
 	__kernel_time64_t       tv_sec;                 /* seconds */
 	long long               tv_nsec;                /* nanoseconds */
 };
+
+struct __kernel_old_itimerspec {
+	struct __kernel_old_timespec it_interval;    /* timer period */
+	struct __kernel_old_timespec it_value;       /* timer expiration */
+};
+
+struct __kernel_itimerspec {
+	struct __kernel_timespec it_interval;    /* timer period */
+	struct __kernel_timespec it_value;       /* timer expiration */
+};
 #endif
 
 enum tst_ts_type {
@@ -129,6 +142,14 @@ struct tst_ts {
 	} ts;
 };
 
+struct tst_its {
+	enum tst_ts_type type;
+	union {
+		struct __kernel_old_itimerspec kern_old_its;
+		struct __kernel_itimerspec kern_its;
+	} ts;
+};
+
 static inline void *tst_ts_get(struct tst_ts *t)
 {
 	if (!t)
@@ -147,6 +168,22 @@ static inline void *tst_ts_get(struct tst_ts *t)
 	}
 }
 
+static inline void *tst_its_get(struct tst_its *t)
+{
+	if (!t)
+		return NULL;
+
+	switch (t->type) {
+	case TST_KERN_OLD_TIMESPEC:
+		return &t->ts.kern_old_its;
+	case TST_KERN_TIMESPEC:
+		return &t->ts.kern_its;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", t->type);
+		return NULL;
+	}
+}
+
 static inline int libc_clock_getres(clockid_t clk_id, void *ts)
 {
 	return clock_getres(clk_id, ts);
@@ -212,6 +249,117 @@ static inline int sys_clock_nanosleep64(clockid_t clk_id, int flags,
 			   request, remain);
 }
 
+static inline int sys_futex(int *uaddr, int futex_op, int val, void *to,
+			    int *uaddr2, int val3)
+{
+	return tst_syscall(__NR_futex, uaddr, futex_op, val, to, uaddr2, val3);
+}
+
+static inline int sys_futex_time64(int *uaddr, int futex_op, int val, void *to,
+				   int *uaddr2, int val3)
+{
+	return tst_syscall(__NR_futex_time64, uaddr, futex_op, val, to, uaddr2, val3);
+}
+
+static inline int libc_mq_timedsend(mqd_t mqdes, const char *msg_ptr,
+		size_t msg_len, unsigned int msg_prio, void *abs_timeout)
+{
+	return mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, abs_timeout);
+}
+
+static inline int sys_mq_timedsend(mqd_t mqdes, const char *msg_ptr,
+		size_t msg_len, unsigned int msg_prio, void *abs_timeout)
+{
+	return tst_syscall(__NR_mq_timedsend, mqdes, msg_ptr, msg_len, msg_prio,
+			   abs_timeout);
+}
+
+static inline int sys_mq_timedsend64(mqd_t mqdes, const char *msg_ptr,
+		size_t msg_len, unsigned int msg_prio, void *abs_timeout)
+{
+	return tst_syscall(__NR_mq_timedsend_time64, mqdes, msg_ptr, msg_len,
+			   msg_prio, abs_timeout);
+}
+
+static inline ssize_t libc_mq_timedreceive(mqd_t mqdes, char *msg_ptr,
+		size_t msg_len, unsigned int *msg_prio, void *abs_timeout)
+{
+	return mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, abs_timeout);
+}
+
+static inline ssize_t sys_mq_timedreceive(mqd_t mqdes, char *msg_ptr,
+		size_t msg_len, unsigned int *msg_prio, void *abs_timeout)
+{
+	return tst_syscall(__NR_mq_timedreceive, mqdes, msg_ptr, msg_len,
+			   msg_prio, abs_timeout);
+}
+
+static inline ssize_t sys_mq_timedreceive64(mqd_t mqdes, char *msg_ptr,
+		size_t msg_len, unsigned int *msg_prio, void *abs_timeout)
+{
+	return tst_syscall(__NR_mq_timedreceive_time64, mqdes, msg_ptr, msg_len,
+			   msg_prio, abs_timeout);
+}
+
+static inline int libc_sched_rr_get_interval(pid_t pid, void *ts)
+{
+	return sched_rr_get_interval(pid, ts);
+}
+
+static inline int sys_sched_rr_get_interval(pid_t pid, void *ts)
+{
+	return tst_syscall(__NR_sched_rr_get_interval, pid, ts);
+}
+
+static inline int sys_sched_rr_get_interval64(pid_t pid, void *ts)
+{
+	return tst_syscall(__NR_sched_rr_get_interval_time64, pid, ts);
+}
+
+static inline int sys_timer_gettime(timer_t timerid, void *its)
+{
+	return tst_syscall(__NR_timer_gettime, timerid, its);
+}
+
+static inline int sys_timer_gettime64(timer_t timerid, void *its)
+{
+	return tst_syscall(__NR_timer_gettime64, timerid, its);
+}
+
+static inline int sys_timer_settime(timer_t timerid, int flags, void *its,
+				    void *old_its)
+{
+	return tst_syscall(__NR_timer_settime, timerid, flags, its, old_its);
+}
+
+static inline int sys_timer_settime64(timer_t timerid, int flags, void *its,
+				      void *old_its)
+{
+	return tst_syscall(__NR_timer_settime64, timerid, flags, its, old_its);
+}
+
+static inline int sys_timerfd_gettime(int fd, void *its)
+{
+	return tst_syscall(__NR_timerfd_gettime, fd, its);
+}
+
+static inline int sys_timerfd_gettime64(int fd, void *its)
+{
+	return tst_syscall(__NR_timerfd_gettime64, fd, its);
+}
+
+static inline int sys_timerfd_settime(int fd, int flags, void *its,
+				      void *old_its)
+{
+	return tst_syscall(__NR_timerfd_settime, fd, flags, its, old_its);
+}
+
+static inline int sys_timerfd_settime64(int fd, int flags, void *its,
+				      void *old_its)
+{
+	return tst_syscall(__NR_timerfd_settime64, fd, flags, its, old_its);
+}
+
 /*
  * Returns tst_ts seconds.
  */
@@ -248,27 +396,6 @@ static inline long long tst_ts_get_nsec(struct tst_ts ts)
 	}
 }
 
-/*
- * Checks that timespec is valid, i.e. that the timestamp is not zero and that
- * the nanoseconds are normalized i.e. in <0, 1s) interval.
- *
- *  0: On success, i.e. timespec updated correctly.
- * -1: Error, timespec not updated.
- * -2: Error, tv_nsec is corrupted.
- */
-static inline int tst_ts_valid(struct tst_ts *t)
-{
-	long long nsec = tst_ts_get_nsec(*t);
-
-	if (nsec < 0 || nsec >= 1000000000)
-		return -2;
-
-	if (tst_ts_get_sec(*t) == 0 && tst_ts_get_nsec(*t) == 0)
-		return -1;
-
-	return 0;
-}
-
 /*
  * Sets tst_ts seconds.
  */
@@ -309,6 +436,163 @@ static inline void tst_ts_set_nsec(struct tst_ts *ts, long long nsec)
 	}
 }
 
+/*
+ * Returns tst_its it_interval seconds.
+ */
+static inline long long tst_its_get_interval_sec(struct tst_its its)
+{
+	switch (its.type) {
+	case TST_KERN_OLD_TIMESPEC:
+		return its.ts.kern_old_its.it_interval.tv_sec;
+	case TST_KERN_TIMESPEC:
+		return its.ts.kern_its.it_interval.tv_sec;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", its.type);
+		return -1;
+	}
+}
+
+/*
+ * Returns tst_its it_interval nanoseconds.
+ */
+static inline long long tst_its_get_interval_nsec(struct tst_its its)
+{
+	switch (its.type) {
+	case TST_KERN_OLD_TIMESPEC:
+		return its.ts.kern_old_its.it_interval.tv_nsec;
+	case TST_KERN_TIMESPEC:
+		return its.ts.kern_its.it_interval.tv_nsec;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", its.type);
+		return -1;
+	}
+}
+
+/*
+ * Sets tst_its it_interval seconds.
+ */
+static inline void tst_its_set_interval_sec(struct tst_its *its, long long sec)
+{
+	switch (its->type) {
+	break;
+	case TST_KERN_OLD_TIMESPEC:
+		its->ts.kern_old_its.it_interval.tv_sec = sec;
+	break;
+	case TST_KERN_TIMESPEC:
+		its->ts.kern_its.it_interval.tv_sec = sec;
+	break;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", its->type);
+	}
+}
+
+/*
+ * Sets tst_its it_interval nanoseconds.
+ */
+static inline void tst_its_set_interval_nsec(struct tst_its *its, long long nsec)
+{
+	switch (its->type) {
+	break;
+	case TST_KERN_OLD_TIMESPEC:
+		its->ts.kern_old_its.it_interval.tv_nsec = nsec;
+	break;
+	case TST_KERN_TIMESPEC:
+		its->ts.kern_its.it_interval.tv_nsec = nsec;
+	break;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", its->type);
+	}
+}
+
+/*
+ * Returns tst_its it_value seconds.
+ */
+static inline long long tst_its_get_value_sec(struct tst_its its)
+{
+	switch (its.type) {
+	case TST_KERN_OLD_TIMESPEC:
+		return its.ts.kern_old_its.it_value.tv_sec;
+	case TST_KERN_TIMESPEC:
+		return its.ts.kern_its.it_value.tv_sec;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", its.type);
+		return -1;
+	}
+}
+
+/*
+ * Returns tst_its it_value nanoseconds.
+ */
+static inline long long tst_its_get_value_nsec(struct tst_its its)
+{
+	switch (its.type) {
+	case TST_KERN_OLD_TIMESPEC:
+		return its.ts.kern_old_its.it_value.tv_nsec;
+	case TST_KERN_TIMESPEC:
+		return its.ts.kern_its.it_value.tv_nsec;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", its.type);
+		return -1;
+	}
+}
+
+/*
+ * Sets tst_its it_value seconds.
+ */
+static inline void tst_its_set_value_sec(struct tst_its *its, long long sec)
+{
+	switch (its->type) {
+	break;
+	case TST_KERN_OLD_TIMESPEC:
+		its->ts.kern_old_its.it_value.tv_sec = sec;
+	break;
+	case TST_KERN_TIMESPEC:
+		its->ts.kern_its.it_value.tv_sec = sec;
+	break;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", its->type);
+	}
+}
+
+/*
+ * Sets tst_its it_value nanoseconds.
+ */
+static inline void tst_its_set_value_nsec(struct tst_its *its, long long nsec)
+{
+	switch (its->type) {
+	break;
+	case TST_KERN_OLD_TIMESPEC:
+		its->ts.kern_old_its.it_value.tv_nsec = nsec;
+	break;
+	case TST_KERN_TIMESPEC:
+		its->ts.kern_its.it_value.tv_nsec = nsec;
+	break;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", its->type);
+	}
+}
+
+/*
+ * Checks that timespec is valid, i.e. that the timestamp is not zero and that
+ * the nanoseconds are normalized i.e. in <0, 1s) interval.
+ *
+ *  0: On success, i.e. timespec updated correctly.
+ * -1: Error, timespec not updated.
+ * -2: Error, tv_nsec is corrupted.
+ */
+static inline int tst_ts_valid(struct tst_ts *t)
+{
+	long long nsec = tst_ts_get_nsec(*t);
+
+	if (nsec < 0 || nsec >= 1000000000)
+		return -2;
+
+	if (tst_ts_get_sec(*t) == 0 && tst_ts_get_nsec(*t) == 0)
+		return -1;
+
+	return 0;
+}
+
 /*
  * Converts timespec to tst_ts.
  */
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 02/19] syscalls/timer_gettime: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
  2020-06-26  6:22 ` [LTP] [PATCH V7 01/19] tst_timer: Add new definitions Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-06-26  9:49   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 03/19] syscalls/timer_settime: " Viresh Kumar
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing timer_gettime()
syscall tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../syscalls/timer_gettime/timer_gettime01.c  | 135 ++++++++----------
 1 file changed, 63 insertions(+), 72 deletions(-)

diff --git a/testcases/kernel/syscalls/timer_gettime/timer_gettime01.c b/testcases/kernel/syscalls/timer_gettime/timer_gettime01.c
index 1c75f1cf0e45..f7083917317c 100644
--- a/testcases/kernel/syscalls/timer_gettime/timer_gettime01.c
+++ b/testcases/kernel/syscalls/timer_gettime/timer_gettime01.c
@@ -1,24 +1,10 @@
-/******************************************************************************
- * Copyright (c) Crackerjack Project., 2007                                   *
- * Porting from Crackerjack to LTP is done by:                                *
- *              Manas Kumar Nayak <maknayak@in.ibm.com>                       *
- * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>                          *
- *                                                                            *
- * 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           *
- *                                                                            *
- ******************************************************************************/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Crackerjack Project., 2007
+ * Porting from Crackerjack to LTP is done by:
+ *	Manas Kumar Nayak <maknayak@in.ibm.com>
+ * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
+ */
 
 #include <time.h>
 #include <signal.h>
@@ -26,71 +12,76 @@
 #include <stdio.h>
 #include <errno.h>
 
-#include "test.h"
-#include "lapi/syscalls.h"
+#include "tst_timer.h"
 
-char *TCID = "timer_gettime01";
-int TST_TOTAL = 3;
+static struct test_variants {
+	int (*func)(timer_t timer, void *its);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timer_gettime != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_timer_gettime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
 
-static void cleanup(void)
-{
-	tst_rmdir();
-}
+#if (__NR_timer_gettime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_timer_gettime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
 
-static void setup(void)
-{
-	TEST_PAUSE;
-	tst_tmpdir();
-}
+static timer_t timer;
 
-int main(int ac, char **av)
+static void setup(void)
 {
-	int lc;
-
 	struct sigevent ev;
-	struct itimerspec spec;
-	int timer;
 
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
 
 	ev.sigev_value = (union sigval) 0;
 	ev.sigev_signo = SIGALRM;
 	ev.sigev_notify = SIGEV_SIGNAL;
-	TEST(ltp_syscall(__NR_timer_create, CLOCK_REALTIME, &ev, &timer));
-
-	if (TEST_RETURN != 0)
-		tst_brkm(TBROK | TERRNO, cleanup, "Failed to create timer");
 
-	for (lc = 0; TEST_LOOPING(lc); ++lc) {
-		tst_count = 0;
+	TEST(tst_syscall(__NR_timer_create, CLOCK_REALTIME, &ev, &timer));
 
-		TEST(ltp_syscall(__NR_timer_gettime, timer, &spec));
-		if (TEST_RETURN == 0) {
-			tst_resm(TPASS, "timer_gettime(CLOCK_REALTIME) Passed");
-		} else {
-			tst_resm(TFAIL | TERRNO,
-			         "timer_gettime(CLOCK_REALTIME) Failed");
-		}
-
-		TEST(ltp_syscall(__NR_timer_gettime, -1, &spec));
-		if (TEST_RETURN == -1 && TEST_ERRNO == EINVAL) {
-			tst_resm(TPASS,	"timer_gettime(-1) Failed: EINVAL");
-		} else {
-			tst_resm(TFAIL | TERRNO,
-			         "timer_gettime(-1) = %li", TEST_RETURN);
-		}
+	if (TST_RET) {
+		tst_res(TFAIL | TTERRNO, "timer_create() failed");
+		return;
+	}
+}
 
-		TEST(ltp_syscall(__NR_timer_gettime, timer, NULL));
-		if (TEST_RETURN == -1 && TEST_ERRNO == EFAULT) {
-			tst_resm(TPASS,	"timer_gettime(NULL) Failed: EFAULT");
-		} else {
-			tst_resm(TFAIL | TERRNO,
-			         "timer_gettime(-1) = %li", TEST_RETURN);
-		}
+static void verify(void)
+{
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_its spec = {.type = tv->type, };
+
+	TEST(tv->func(timer, tst_its_get(&spec)));
+	if (TST_RET == 0) {
+		if (tst_its_get_interval_sec(spec) ||
+		    tst_its_get_interval_nsec(spec) ||
+		    tst_its_get_value_sec(spec) ||
+		    tst_its_get_value_nsec(spec))
+			tst_res(TFAIL, "timespec should have been zeroed");
+		else
+			tst_res(TPASS, "timer_gettime() Passed");
+	} else {
+		tst_res(TFAIL | TTERRNO, "timer_gettime() Failed");
 	}
 
-	cleanup();
-	tst_exit();
+	TEST(tv->func((timer_t)-1, tst_its_get(&spec)));
+	if (TST_RET == -1 && TST_ERR == EINVAL)
+		tst_res(TPASS, "timer_gettime(-1) Failed: EINVAL");
+	else
+		tst_res(TFAIL | TTERRNO, "timer_gettime(-1) = %li", TST_RET);
+
+	TEST(tv->func(timer, NULL));
+	if (TST_RET == -1 && TST_ERR == EFAULT)
+		tst_res(TPASS, "timer_gettime(NULL) Failed: EFAULT");
+	else
+		tst_res(TFAIL | TTERRNO, "timer_gettime(-1) = %li", TST_RET);
 }
+
+static struct tst_test test = {
+	.test_all = verify,
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
+	.needs_tmpdir = 1,
+};
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 03/19] syscalls/timer_settime: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
  2020-06-26  6:22 ` [LTP] [PATCH V7 01/19] tst_timer: Add new definitions Viresh Kumar
  2020-06-26  6:22 ` [LTP] [PATCH V7 02/19] syscalls/timer_gettime: Add support for time64 tests Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-06-29  9:39   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 04/19] syscalls/timerfd: " Viresh Kumar
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing timer_settime()
syscall tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../syscalls/timer_settime/timer_settime01.c  | 51 ++++++++++----
 .../syscalls/timer_settime/timer_settime02.c  | 69 ++++++++++++++-----
 2 files changed, 88 insertions(+), 32 deletions(-)

diff --git a/testcases/kernel/syscalls/timer_settime/timer_settime01.c b/testcases/kernel/syscalls/timer_settime/timer_settime01.c
index da365d221086..08fb56e4943a 100644
--- a/testcases/kernel/syscalls/timer_settime/timer_settime01.c
+++ b/testcases/kernel/syscalls/timer_settime/timer_settime01.c
@@ -25,15 +25,14 @@
 #include <errno.h>
 #include <time.h>
 #include <signal.h>
-#include "tst_test.h"
-#include "lapi/common_timers.h"
+#include "tst_timer.h"
 
-static struct timespec timenow;
-static struct itimerspec new_set, old_set;
-static kernel_timer_t timer;
+static struct tst_ts timenow;
+static struct tst_its new_set, old_set;
+static timer_t timer;
 
 static struct testcase {
-	struct itimerspec	*old_ptr;
+	struct tst_its		*old_ptr;
 	int			it_value_tv_sec;
 	int			it_interval_tv_sec;
 	int			flag;
@@ -45,10 +44,28 @@ static struct testcase {
 	{&old_set, 5, 0, TIMER_ABSTIME, "using absolute time"},
 };
 
+static struct test_variants {
+	int (*gettime)(clockid_t clk_id, void *ts);
+	int (*func)(timer_t timerid, int flags, void *its,
+		    void *old_its);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timer_settime != __LTP__NR_INVALID_SYSCALL)
+	{ .gettime = sys_clock_gettime, .func = sys_timer_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_timer_settime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .gettime = sys_clock_gettime64, .func = sys_timer_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
 static void run(unsigned int n)
 {
-	unsigned int i;
+	struct test_variants *tv = &variants[tst_variant];
 	struct testcase *tc = &tcases[n];
+	long long val;
+	unsigned int i;
 
 	tst_res(TINFO, "Testing for %s:", tc->description);
 
@@ -78,21 +95,27 @@ static void run(unsigned int n)
 		memset(&new_set, 0, sizeof(new_set));
 		memset(&old_set, 0, sizeof(old_set));
 
-		new_set.it_value.tv_sec = tc->it_value_tv_sec;
-		new_set.it_interval.tv_sec = tc->it_interval_tv_sec;
+		new_set.type = old_set.type = tv->type;
+
+		val = tc->it_value_tv_sec;
 
 		if (tc->flag & TIMER_ABSTIME) {
-			if (clock_gettime(clock, &timenow) < 0) {
+			timenow.type = tv->type;
+			if (tv->gettime(clock, tst_ts_get(&timenow)) < 0) {
 				tst_res(TFAIL,
 					"clock_gettime(%s) failed - skipping the test",
 					get_clock_str(clock));
 				continue;
 			}
-			new_set.it_value.tv_sec += timenow.tv_sec;
+			val += tst_ts_get_sec(timenow);
 		}
 
-		TEST(tst_syscall(__NR_timer_settime, timer,
-			tc->flag, &new_set, tc->old_ptr));
+		tst_its_set_interval_sec(&new_set, tc->it_interval_tv_sec);
+		tst_its_set_interval_nsec(&new_set, 0);
+		tst_its_set_value_sec(&new_set, val);
+		tst_its_set_value_nsec(&new_set, 0);
+
+		TEST(tv->func(timer, tc->flag, tst_its_get(&new_set), tst_its_get(tc->old_ptr)));
 
 		if (TST_RET != 0) {
 			tst_res(TFAIL | TTERRNO, "%s failed",
@@ -116,6 +139,7 @@ static void sighandler(int sig)
 
 static void setup(void)
 {
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
 	SAFE_SIGNAL(SIGALRM, sighandler);
 }
 
@@ -123,6 +147,7 @@ static struct tst_test test = {
 	.test = run,
 	.needs_root = 1,
 	.tcnt = ARRAY_SIZE(tcases),
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.tags = (const struct tst_tag[]) {
 		{"linux-git", "f18ddc13af98"},
diff --git a/testcases/kernel/syscalls/timer_settime/timer_settime02.c b/testcases/kernel/syscalls/timer_settime/timer_settime02.c
index bcabb76956f8..e82adddc3189 100644
--- a/testcases/kernel/syscalls/timer_settime/timer_settime02.c
+++ b/testcases/kernel/syscalls/timer_settime/timer_settime02.c
@@ -25,12 +25,13 @@
 
 #include <errno.h>
 #include <time.h>
-#include "tst_test.h"
-#include "lapi/common_timers.h"
+#include "tst_timer.h"
 
-static struct itimerspec new_set, old_set;
-static kernel_timer_t timer;
-static kernel_timer_t timer_inval = -1;
+static struct tst_its new_set, old_set;
+static struct tst_its *pnew_set = &new_set, *pold_set = &old_set, *null_set = NULL;
+static void *faulty_set;
+static timer_t timer;
+static timer_t timer_inval = -1;
 
 /* separate description-array to (hopefully) improve readability */
 static const char * const descriptions[] = {
@@ -43,24 +44,47 @@ static const char * const descriptions[] = {
 };
 
 static struct testcase {
-	kernel_timer_t		*timer_id;
-	struct itimerspec	*new_ptr;
-	struct itimerspec	*old_ptr;
+	timer_t			*timer_id;
+	struct tst_its		**new_ptr;
+	struct tst_its		**old_ptr;
 	int			it_value_tv_nsec;
 	int			error;
 } tcases[] = {
-	{&timer, NULL, &old_set, 0, EINVAL},
-	{&timer, &new_set, &old_set, -1, EINVAL},
-	{&timer, &new_set, &old_set, NSEC_PER_SEC + 1, EINVAL},
-	{&timer_inval, &new_set, &old_set, 0, EINVAL},
-	{&timer, (struct itimerspec *) -1, &old_set, 0, EFAULT},
-	{&timer, &new_set, (struct itimerspec *) -1, 0, EFAULT},
+	{&timer, &null_set, &pold_set, 0, EINVAL},
+	{&timer, &pnew_set, &pold_set, -1, EINVAL},
+	{&timer, &pnew_set, &pold_set, NSEC_PER_SEC + 1, EINVAL},
+	{&timer_inval, &pnew_set, &pold_set, 0, EINVAL},
+	{&timer, (struct tst_its **)&faulty_set, &pold_set, 0, EFAULT},
+	{&timer, &pnew_set, (struct tst_its **)&faulty_set, 0, EFAULT},
 };
 
+static struct test_variants {
+	int (*func)(timer_t timerid, int flags, void *its,
+		    void *old_its);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timer_settime != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_timer_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_timer_settime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_timer_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static void setup(void)
+{
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
+	faulty_set = tst_get_bad_addr(NULL);
+}
+
 static void run(unsigned int n)
 {
-	unsigned int i;
+	struct test_variants *tv = &variants[tst_variant];
 	struct testcase *tc = &tcases[n];
+	void *new, *old;
+	unsigned int i;
 
 	tst_res(TINFO, "Testing for %s:", descriptions[n]);
 
@@ -91,11 +115,16 @@ static void run(unsigned int n)
 		memset(&new_set, 0, sizeof(new_set));
 		memset(&old_set, 0, sizeof(old_set));
 
-		new_set.it_value.tv_sec  = 5;
-		new_set.it_value.tv_nsec = tc->it_value_tv_nsec;
+		new_set.type = old_set.type = tv->type;
+		tst_its_set_interval_sec(&new_set, 0);
+		tst_its_set_interval_nsec(&new_set, 0);
+		tst_its_set_value_sec(&new_set, 5);
+		tst_its_set_value_nsec(&new_set, tc->it_value_tv_nsec);
+
+		new = (tc->new_ptr == (struct tst_its **)&faulty_set) ? faulty_set : tst_its_get(*tc->new_ptr);
+		old = (tc->old_ptr == (struct tst_its **)&faulty_set) ? faulty_set : tst_its_get(*tc->old_ptr);
 
-		TEST(tst_syscall(__NR_timer_settime, *tc->timer_id,
-					0, tc->new_ptr,	tc->old_ptr));
+		TEST(tv->func(*tc->timer_id, 0, new, old));
 
 		if (tc->error != TST_ERR) {
 			tst_res(TFAIL | TTERRNO,
@@ -119,6 +148,8 @@ static struct tst_test test = {
 	.test = run,
 	.needs_root = 1,
 	.tcnt = ARRAY_SIZE(tcases),
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
 	.tags = (const struct tst_tag[]) {
 		{"linux-git", "f18ddc13af98"},
 		{}
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 04/19] syscalls/timerfd: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (2 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 03/19] syscalls/timer_settime: " Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-02 12:24   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 05/19] syscalls/sched_rr_get_interval: " Viresh Kumar
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing timerfd_gettime() and
timerfd_settime() syscall tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 testcases/kernel/syscalls/timerfd/timerfd01.c |  56 ++++++--
 testcases/kernel/syscalls/timerfd/timerfd04.c |  54 +++++--
 .../syscalls/timerfd/timerfd_gettime01.c      | 133 ++++++++---------
 .../syscalls/timerfd/timerfd_settime01.c      | 136 ++++++++----------
 .../syscalls/timerfd/timerfd_settime02.c      |  28 +++-
 5 files changed, 237 insertions(+), 170 deletions(-)

diff --git a/testcases/kernel/syscalls/timerfd/timerfd01.c b/testcases/kernel/syscalls/timerfd/timerfd01.c
index 45d4c5d5ea0d..90144b843e30 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd01.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd01.c
@@ -17,7 +17,6 @@
 
 #define _GNU_SOURCE
 #include <poll.h>
-#include "tst_test.h"
 #include "tst_timer.h"
 #include "tst_safe_timerfd.h"
 
@@ -29,25 +28,49 @@ static struct tcase {
 	{CLOCK_REALTIME, "CLOCK REALTIME"},
 };
 
+static struct test_variants {
+	int (*cgettime)(clockid_t clk_id, void *ts);
+	int (*tfd_gettime)(int fd, void *its);
+	int (*tfd_settime)(int fd, int flags, void *new_value, void *old_value);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timerfd_gettime != __LTP__NR_INVALID_SYSCALL)
+	{ .cgettime = sys_clock_gettime, .tfd_gettime = sys_timerfd_gettime, .tfd_settime = sys_timerfd_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_timerfd_gettime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .cgettime = sys_clock_gettime64, .tfd_gettime = sys_timerfd_gettime64, .tfd_settime = sys_timerfd_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
 static unsigned long long getustime(int clockid)
 {
-	struct timespec tp;
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_ts tp = {.type = tv->type, };
 
-	if (clock_gettime((clockid_t) clockid, &tp)) {
+	if (tv->cgettime((clockid_t) clockid, tst_ts_get(&tp))) {
 		tst_res(TFAIL | TERRNO, "clock_gettime() failed");
 		return 0;
 	}
 
-	return 1000000ULL * tp.tv_sec + tp.tv_nsec / 1000;
+	return 1000000ULL * tst_ts_get_sec(tp) + tst_ts_get_nsec(tp) / 1000;
 }
 
-static void settime(int tfd, struct itimerspec *tmr, int tflags,
+static void settime(int tfd, struct tst_its *tmr, int tflags,
                     unsigned long long tvalue, int tinterval)
 {
-	tmr->it_value = tst_timespec_from_us(tvalue);
-	tmr->it_interval = tst_timespec_from_us(tinterval);
+	struct test_variants *tv = &variants[tst_variant];
+	struct timespec value = tst_timespec_from_us(tvalue);
+	struct timespec interval = tst_timespec_from_us(tinterval);
 
-	SAFE_TIMERFD_SETTIME(tfd, tflags, tmr, NULL);
+	tst_its_set_interval_sec(tmr, interval.tv_sec);
+	tst_its_set_interval_nsec(tmr, interval.tv_nsec);
+	tst_its_set_value_sec(tmr, value.tv_sec);
+	tst_its_set_value_nsec(tmr, value.tv_nsec);
+
+	if (tv->tfd_settime(tfd, tflags, tst_its_get(tmr), NULL))
+		tst_res(TFAIL, "timerfd_settime() failed");
 }
 
 static void waittmr(int tfd, unsigned int exp_ticks)
@@ -78,10 +101,11 @@ static void waittmr(int tfd, unsigned int exp_ticks)
 
 static void run(unsigned int n)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	int tfd;
 	unsigned long long tnow;
 	uint64_t uticks;
-	struct itimerspec tmr;
+	struct tst_its tmr = {.type = tv->type, };
 	struct tcase *clks = &tcases[n];
 
 	tst_res(TINFO, "testing %s", clks->name);
@@ -102,11 +126,12 @@ static void run(unsigned int n)
 	settime(tfd, &tmr, TFD_TIMER_ABSTIME, tnow + 50 * 1000, 50 * 1000);
 
 	memset(&tmr, 0, sizeof(tmr));
-	if (timerfd_gettime(tfd, &tmr))
-		tst_res(TFAIL | TERRNO, "timerfd_gettime() failed");
+	tmr.type = tv->type;
 
+	if (tv->tfd_gettime(tfd, tst_its_get(&tmr)))
+		tst_res(TFAIL | TERRNO, "timerfd_gettime() failed");
 
-	if (tmr.it_value.tv_sec != 0 || tmr.it_value.tv_nsec > 50 * 1000000)
+	if (tst_its_get_value_sec(tmr) != 0 || tst_its_get_value_nsec(tmr) > 50 * 1000000)
 		tst_res(TFAIL, "Timer read back value not relative");
 	else
 		tst_res(TPASS, "Timer read back value is relative");
@@ -132,8 +157,15 @@ static void run(unsigned int n)
 	SAFE_CLOSE(tfd);
 }
 
+static void setup(void)
+{
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
+}
+
 static struct tst_test test = {
 	.test = run,
 	.tcnt = ARRAY_SIZE(tcases),
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
 	.min_kver = "2.6.25",
 };
diff --git a/testcases/kernel/syscalls/timerfd/timerfd04.c b/testcases/kernel/syscalls/timerfd/timerfd04.c
index 7197fc67ed47..49d50d00022a 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd04.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd04.c
@@ -19,7 +19,6 @@
 #include "tst_safe_timerfd.h"
 #include "tst_timer.h"
 #include "lapi/namespaces_constants.h"
-#include "tst_test.h"
 
 #define SLEEP_US 40000
 
@@ -35,26 +34,59 @@ static struct tcase {
 	{CLOCK_BOOTTIME, CLOCK_BOOTTIME, -10},
 };
 
+static struct test_variants {
+	int (*cgettime)(clockid_t clk_id, void *ts);
+	int (*tfd_settime)(int fd, int flags, void *new_value, void *old_value);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timerfd_settime != __LTP__NR_INVALID_SYSCALL)
+	{ .cgettime = sys_clock_gettime, .tfd_settime = sys_timerfd_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_timerfd_settime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .cgettime = sys_clock_gettime64, .tfd_settime = sys_timerfd_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static void setup(void)
+{
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
+}
+
 static void verify_timerfd(unsigned int n)
 {
-	struct timespec start, end;
-	struct itimerspec it = {};
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_ts start, end;
+	struct tst_its it;
 	struct tcase *tc = &tcases[n];
 
+	start.type = end.type = it.type = tv->type;
 	SAFE_UNSHARE(CLONE_NEWTIME);
 
 	SAFE_FILE_PRINTF("/proc/self/timens_offsets", "%d %d 0",
 	                 tc->clk_off, tc->off);
 
-	SAFE_CLOCK_GETTIME(tc->clk_id, &start);
+	if (tv->cgettime(tc->clk_id, tst_ts_get(&start))) {
+		tst_res(TFAIL | TTERRNO, "clock_gettime(2) failed for clock %s",
+			tst_clock_name(tc->clk_id));
+		return;
+	}
 
-	it.it_value = tst_timespec_add_us(start, 1000000 * tc->off + SLEEP_US);
+	end = tst_ts_add_us(start, 1000000 * tc->off + SLEEP_US);
+	tst_its_set_interval_sec(&it, 0);
+	tst_its_set_interval_nsec(&it, 0);
+	tst_its_set_value_sec(&it, tst_ts_get_sec(end));
+	tst_its_set_value_nsec(&it, tst_ts_get_nsec(end));
 
 	if (!SAFE_FORK()) {
 		uint64_t exp;
 		int fd = SAFE_TIMERFD_CREATE(tc->clk_id, 0);
 
-		SAFE_TIMERFD_SETTIME(fd, TFD_TIMER_ABSTIME, &it, NULL);
+		if (tv->tfd_settime(fd, TFD_TIMER_ABSTIME, tst_its_get(&it), NULL)) {
+			tst_res(TFAIL, "timerfd_settime() failed");
+			return;
+		}
 
 		SAFE_READ(1, fd, &exp, sizeof(exp));
 
@@ -67,9 +99,13 @@ static void verify_timerfd(unsigned int n)
 
 	SAFE_WAIT(NULL);
 
-	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &end);
+	if (tv->cgettime(CLOCK_MONOTONIC, tst_ts_get(&end))) {
+		tst_res(TFAIL | TTERRNO, "clock_gettime(2) failed for clock %s",
+			tst_clock_name(CLOCK_MONOTONIC));
+		return;
+	}
 
-	long long diff = tst_timespec_diff_us(end, start);
+	long long diff = tst_ts_diff_us(end, start);
 
 	if (diff > 5 * SLEEP_US) {
 		tst_res(TFAIL, "timerfd %s slept too long %lli",
@@ -90,6 +126,8 @@ static void verify_timerfd(unsigned int n)
 static struct tst_test test = {
 	.tcnt = ARRAY_SIZE(tcases),
 	.test = verify_timerfd,
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
 	.needs_root = 1,
 	.forks_child = 1,
 	.needs_kconfigs = (const char *[]) {
diff --git a/testcases/kernel/syscalls/timerfd/timerfd_gettime01.c b/testcases/kernel/syscalls/timerfd/timerfd_gettime01.c
index 5f3240bdc7d7..49f5aa59a96b 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd_gettime01.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd_gettime01.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) 2014 Fujitsu Ltd.
  * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
  * DESCRIPTION
  *  Verify that,
  *   1. fd is not a valid file descriptor, EBADF would return.
@@ -24,99 +12,96 @@
 
 #define _GNU_SOURCE
 
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "test.h"
-#include "safe_macros.h"
-#include "lapi/timerfd.h"
+#include "tst_timer.h"
+#include "tst_safe_timerfd.h"
 
 char *TCID = "timerfd_gettime01";
 
 static int bad_clockfd = -1;
 static int clockfd;
 static int fd;
+static void *bad_addr;
 
 static struct test_case_t {
 	int *fd;
-	struct itimerspec *curr_value;
+	struct tst_its *curr_value;
 	int exp_errno;
 } test_cases[] = {
 	{&bad_clockfd, NULL, EBADF},
-	{&clockfd, (struct itimerspec *)-1, EFAULT},
+	{&clockfd, NULL, EFAULT},
 	{&fd, NULL, EINVAL},
 };
 
-int TST_TOTAL = ARRAY_SIZE(test_cases);
-static void setup(void);
-static void timerfd_gettime_verify(const struct test_case_t *);
-static void cleanup(void);
+static struct test_variants {
+	int (*tfd_gettime)(int fd, void *its);
+	char *desc;
+} variants[] = {
+#if (__NR_timerfd_gettime != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_gettime = sys_timerfd_gettime, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_timerfd_gettime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_gettime = sys_timerfd_gettime64, .desc = "syscall time64 with kernel spec"},
+#endif
+};
 
-int main(int argc, char *argv[])
+static void setup(void)
 {
-	int lc;
-	int i;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
-
-	setup();
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
+	bad_addr = tst_get_bad_addr(NULL);
 
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-		for (i = 0; i < TST_TOTAL; i++)
-			timerfd_gettime_verify(&test_cases[i]);
+	clockfd = timerfd_create(CLOCK_REALTIME, 0);
+	if (clockfd == -1) {
+		tst_brk(TFAIL | TERRNO, "timerfd_create() fail");
+		return;
 	}
 
-	cleanup();
-	tst_exit();
+	fd = SAFE_OPEN("test_file", O_RDWR | O_CREAT, 0644);
 }
 
-static void setup(void)
+static void cleanup(void)
 {
-	if ((tst_kvercmp(2, 6, 25)) < 0)
-		tst_brkm(TCONF, NULL, "This test needs kernel 2.6.25 or newer");
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	tst_tmpdir();
-
-	clockfd = timerfd_create(CLOCK_REALTIME, 0);
-	if (clockfd == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "timerfd_create() fail");
+	if (clockfd > 0)
+		close(clockfd);
 
-	fd = SAFE_OPEN(cleanup, "test_file", O_RDWR | O_CREAT, 0644);
+	if (fd > 0)
+		close(fd);
 }
 
-static void timerfd_gettime_verify(const struct test_case_t *test)
+static void run(unsigned int n)
 {
-	TEST(timerfd_gettime(*test->fd, test->curr_value));
+	struct test_variants *tv = &variants[tst_variant];
+	struct test_case_t *test = &test_cases[n];
+	void *its;
 
-	if (TEST_RETURN != -1) {
-		tst_resm(TFAIL, "timerfd_gettime() succeeded unexpectedly");
+	if (test->exp_errno == EFAULT)
+		its = bad_addr;
+	else
+		its = tst_its_get(test->curr_value);
+
+	TEST(tv->tfd_gettime(*test->fd, its));
+
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "timerfd_gettime() succeeded unexpectedly");
 		return;
 	}
 
-	if (TEST_ERRNO == test->exp_errno) {
-		tst_resm(TPASS | TTERRNO,
-			 "timerfd_gettime() failed as expected");
+	if (TST_ERR == test->exp_errno) {
+		tst_res(TPASS | TTERRNO,
+			"timerfd_gettime() failed as expected");
 	} else {
-		tst_resm(TFAIL | TTERRNO,
-			 "timerfd_gettime() failed unexpectedly; expected: "
-			 "%d - %s", test->exp_errno, strerror(test->exp_errno));
+		tst_res(TFAIL | TTERRNO,
+			"timerfd_gettime() failed unexpectedly; expected: "
+			"%d - %s", test->exp_errno, strerror(test->exp_errno));
 	}
 }
 
-static void cleanup(void)
-{
-	if (clockfd > 0)
-		close(clockfd);
-
-	if (fd > 0)
-		close(fd);
-
-	tst_rmdir();
-}
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(test_cases),
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.min_kver = "2.6.25",
+};
diff --git a/testcases/kernel/syscalls/timerfd/timerfd_settime01.c b/testcases/kernel/syscalls/timerfd/timerfd_settime01.c
index 2e65d23ae825..2fd64c1c6a04 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd_settime01.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd_settime01.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) 2014 Fujitsu Ltd.
  * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
  * DESCRIPTION
  *  Verify that,
  *   1. fd is not a valid file descriptor, EBADF would return.
@@ -25,13 +13,7 @@
 
 #define _GNU_SOURCE
 
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "test.h"
-#include "safe_macros.h"
+#include "tst_timer.h"
 #include "lapi/timerfd.h"
 
 char *TCID = "timerfd_settime01";
@@ -39,80 +21,51 @@ char *TCID = "timerfd_settime01";
 static int bad_clockfd = -1;
 static int clockfd;
 static int fd;
+static void *bad_addr;
 
 static struct test_case_t {
 	int *fd;
 	int flags;
-	struct itimerspec *old_value;
+	struct tst_its *old_value;
 	int exp_errno;
 } test_cases[] = {
 	{&bad_clockfd, 0, NULL, EBADF},
-	{&clockfd, 0, (struct itimerspec *)-1, EFAULT},
+	{&clockfd, 0, NULL, EFAULT},
 	{&fd, 0, NULL, EINVAL},
 	{&clockfd, -1, NULL, EINVAL},
 };
 
-int TST_TOTAL = ARRAY_SIZE(test_cases);
-static void setup(void);
-static void timerfd_settime_verify(const struct test_case_t *);
-static void cleanup(void);
-static struct itimerspec new_value;
+static struct tst_its new_value;
 
-int main(int argc, char *argv[])
-{
-	int lc;
-	int i;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
+static struct test_variants {
+	int (*tfd_settime)(int fd, int flags, void *new_value, void *old_value);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timerfd_settime != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_settime = sys_timerfd_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
 
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-		for (i = 0; i < TST_TOTAL; i++)
-			timerfd_settime_verify(&test_cases[i]);
-	}
-
-	cleanup();
-	tst_exit();
-}
+#if (__NR_timerfd_settime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_settime = sys_timerfd_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
 
 static void setup(void)
 {
-	if ((tst_kvercmp(2, 6, 25)) < 0)
-		tst_brkm(TCONF, NULL, "This test needs kernel 2.6.25 or newer");
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
+	struct test_variants *tv = &variants[tst_variant];
 
-	TEST_PAUSE;
-
-	tst_tmpdir();
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	bad_addr = tst_get_bad_addr(NULL);
+	new_value.type = tv->type;
 
 	clockfd = timerfd_create(CLOCK_REALTIME, 0);
-	if (clockfd == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "timerfd_create() fail");
-
-	fd = SAFE_OPEN(cleanup, "test_file", O_RDWR | O_CREAT, 0644);
-}
-
-static void timerfd_settime_verify(const struct test_case_t *test)
-{
-	TEST(timerfd_settime(*test->fd, test->flags, &new_value,
-			     test->old_value));
-
-	if (TEST_RETURN != -1) {
-		tst_resm(TFAIL, "timerfd_settime() succeeded unexpectedly");
+	if (clockfd == -1) {
+		tst_brk(TFAIL | TERRNO, "timerfd_create() fail");
 		return;
 	}
 
-	if (TEST_ERRNO == test->exp_errno) {
-		tst_resm(TPASS | TTERRNO,
-			 "timerfd_settime() failed as expected");
-	} else {
-		tst_resm(TFAIL | TTERRNO,
-			 "timerfd_settime() failed unexpectedly; expected: "
-			 "%d - %s", test->exp_errno, strerror(test->exp_errno));
-	}
+	fd = SAFE_OPEN("test_file", O_RDWR | O_CREAT, 0644);
 }
 
 static void cleanup(void)
@@ -122,6 +75,43 @@ static void cleanup(void)
 
 	if (fd > 0)
 		close(fd);
+}
+
+static void run(unsigned int n)
+{
+	struct test_variants *tv = &variants[tst_variant];
+	struct test_case_t *test = &test_cases[n];
+	void *its;
+
+	if (test->exp_errno == EFAULT)
+		its = bad_addr;
+	else
+		its = tst_its_get(test->old_value);
 
-	tst_rmdir();
+	TEST(tv->tfd_settime(*test->fd, test->flags, tst_its_get(&new_value),
+			     its));
+
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "timerfd_settime() succeeded unexpectedly");
+		return;
+	}
+
+	if (TST_ERR == test->exp_errno) {
+		tst_res(TPASS | TTERRNO,
+			"timerfd_settime() failed as expected");
+	} else {
+		tst_res(TFAIL | TTERRNO,
+			"timerfd_settime() failed unexpectedly; expected: "
+			"%d - %s", test->exp_errno, strerror(test->exp_errno));
+	}
 }
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(test_cases),
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.min_kver = "2.6.25",
+};
diff --git a/testcases/kernel/syscalls/timerfd/timerfd_settime02.c b/testcases/kernel/syscalls/timerfd/timerfd_settime02.c
index 0565802f4288..c15b69dca9ca 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd_settime02.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd_settime02.c
@@ -15,8 +15,8 @@
  *  timerfd: Protect the might cancel mechanism proper
  */
 #include <unistd.h>
+#include "tst_timer.h"
 #include "tst_safe_timerfd.h"
-#include "tst_test.h"
 #include "tst_fuzzy_sync.h"
 #include "tst_taint.h"
 
@@ -27,11 +27,30 @@
 #endif
 
 static int fd = -1;
-static struct itimerspec its;
+static struct tst_its its;
 static struct tst_fzsync_pair fzsync_pair;
 
+static struct test_variants {
+	int (*tfd_settime)(int fd, int flags, void *new_value, void *old_value);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timerfd_settime != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_settime = sys_timerfd_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_timerfd_settime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_settime = sys_timerfd_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	its.type = tv->type;
+
 	tst_taint_init(TST_TAINT_W | TST_TAINT_D);
 	fd = SAFE_TIMERFD_CREATE(CLOCK_REALTIME, 0);
 
@@ -48,7 +67,9 @@ static void cleanup(void)
 
 static int punch_clock(int flags)
 {
-	return timerfd_settime(fd, flags, &its, NULL);
+	return variants[tst_variant].tfd_settime(fd, flags, tst_its_get(&its),
+						 NULL);
+
 }
 
 static void *thread_run(void *arg)
@@ -91,6 +112,7 @@ static void run(void)
 
 static struct tst_test test = {
 	.test_all = run,
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.cleanup = cleanup,
 	.min_kver = "2.6.25",
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 05/19] syscalls/sched_rr_get_interval: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (3 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 04/19] syscalls/timerfd: " Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-02 13:06   ` Cyril Hrubis
  2020-07-03  7:38   ` [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice Viresh Kumar
  2020-06-26  6:22 ` [LTP] [PATCH V7 06/19] syscalls/futex: Merge futex_wait_bitset tests Viresh Kumar
                   ` (14 subsequent siblings)
  19 siblings, 2 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing
sched_rr_get_interval() syscall tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../sched_rr_get_interval01.c                 | 116 ++++++--------
 .../sched_rr_get_interval02.c                 | 122 ++++++---------
 .../sched_rr_get_interval03.c                 | 146 ++++++++----------
 3 files changed, 157 insertions(+), 227 deletions(-)

diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
index 6ebf873de798..9bad698aa6ec 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
@@ -1,20 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/**********************************************************
  *
  *    TEST IDENTIFIER	: sched_rr_get_interval01
  *
@@ -62,81 +48,69 @@
  *				-P x : Pause for x seconds between iterations.
  *				-t   : Turn on syscall timing.
  *
- ****************************************************************/
+ */
 
-#include <errno.h>
 #include <sched.h>
-#include "test.h"
-
-static void setup();
-static void cleanup();
-
-char *TCID = "sched_rr_get_interval01";
-int TST_TOTAL = 1;
-
-struct timespec tp;
-
-int main(int ac, char **av)
-{
-
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
+#include "tst_timer.h"
 
-	setup();
+struct tst_ts tp;
 
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
+static struct test_variants {
+	int (*func)(pid_t pid, void *ts);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+	{ .func = libc_sched_rr_get_interval, .type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"},
 
-		tst_count = 0;
+#if (__NR_sched_rr_get_interval != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_sched_rr_get_interval, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
 
-		/*
-		 * Call sched_rr_get_interval(2) with pid=0 so that it will
-		 * write into the timespec structure pointed to by tp, the
-		 * round robin time quantum for the current process.
-		 */
-		TEST(sched_rr_get_interval(0, &tp));
+#if (__NR_sched_rr_get_interval_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_sched_rr_get_interval64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
 
-		if (TEST_RETURN == 0) {
-			tst_resm(TPASS, "sched_rr_get_interval() returned %ld",
-				 TEST_RETURN);
-		} else {
-			tst_resm(TFAIL | TTERRNO,
-				 "Test Failed, sched_rr_get_interval()"
-				 "returned %ld", TEST_RETURN);
-		}
-	}
-
-	/* cleanup and exit */
-	cleanup();
-	tst_exit();
-
-}
-
-/* setup() - performs all ONE TIME setup for this test */
-void setup(void)
+static void setup(void)
 {
-	tst_require_root();
+	struct test_variants *tv = &variants[tst_variant];
 	/*
 	 * Initialize scheduling parameter structure to use with
 	 * sched_setscheduler()
 	 */
 	struct sched_param p = { 1 };
 
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
 
-	TEST_PAUSE;
+	tp.type = tv->type;
 
 	/* Change scheduling policy to SCHED_RR */
-	if ((sched_setscheduler(0, SCHED_RR, &p)) == -1) {
-		tst_brkm(TBROK|TERRNO, cleanup, "sched_setscheduler() failed");
-	}
+	if ((sched_setscheduler(0, SCHED_RR, &p)) == -1)
+		tst_res(TFAIL | TTERRNO, "sched_setscheduler() failed");
 }
 
-/*
- *cleanup() -  performs all ONE TIME cleanup for this test at
- *		completion or premature exit.
- */
-void cleanup(void)
+static void run(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
+
+	/*
+	 * Call sched_rr_get_interval(2) with pid=0 so that it will
+	 * write into the timespec structure pointed to by tp, the
+	 * round robin time quantum for the current process.
+	 */
+	TEST(tv->func(0, tst_ts_get(&tp)));
 
+	if (!TST_RET) {
+		tst_res(TPASS, "sched_rr_get_interval() passed");
+	} else {
+		tst_res(TFAIL | TTERRNO, "Test Failed, sched_rr_get_interval() returned %ld",
+			TST_RET);
+	}
 }
+
+static struct tst_test test = {
+	.test_all = run,
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
+	.needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c
index 367d9e3ff486..8da42e97404b 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c
@@ -1,20 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/**********************************************************
  *
  *    TEST IDENTIFIER	: sched_rr_get_interval02
  *
@@ -63,84 +49,72 @@
  *				-P x : Pause for x seconds between iterations.
  *				-t   : Turn on syscall timing.
  *
- ****************************************************************/
+ */
 
-#include <errno.h>
 #include <sched.h>
-#include "test.h"
-
-static void setup();
-static void cleanup();
+#include "tst_timer.h"
 
-char *TCID = "sched_rr_get_interval02";
-int TST_TOTAL = 1;
+struct tst_ts tp;
 
-struct timespec tp;
+static struct test_variants {
+	int (*func)(pid_t pid, void *ts);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+	{ .func = libc_sched_rr_get_interval, .type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"},
 
-int main(int ac, char **av)
-{
-
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
+#if (__NR_sched_rr_get_interval != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_sched_rr_get_interval, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
 
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
+#if (__NR_sched_rr_get_interval_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_sched_rr_get_interval64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
 
-		tst_count = 0;
-
-		tp.tv_sec = 99;
-		tp.tv_nsec = 99;
-		/*
-		 * Call sched_rr_get_interval(2) with pid=0 sothat it will
-		 * write into the timespec structure pointed to by tp the
-		 * round robin time quantum for the current process.
-		 */
-		TEST(sched_rr_get_interval(0, &tp));
-
-		if ((TEST_RETURN == 0) && (tp.tv_sec == 0) && (tp.tv_nsec == 0)) {
-			tst_resm(TPASS, "Test passed");
-		} else {
-			tst_resm(TFAIL, "Test Failed, sched_rr_get_interval()"
-				 "returned %ld, errno = %d : %s, tp.tv_sec = %d,"
-				 " tp.tv_nsec = %ld", TEST_RETURN, TEST_ERRNO,
-				 strerror(TEST_ERRNO), (int)tp.tv_sec,
-				 tp.tv_nsec);
-		}
-	}
-
-	/* cleanup and exit */
-	cleanup();
-	tst_exit();
-
-}
-
-/* setup() - performs all ONE TIME setup for this test */
-void setup(void)
+static void setup(void)
 {
-	tst_require_root();
+	struct test_variants *tv = &variants[tst_variant];
 	/*
 	 * Initialize scheduling parameter structure to use with
 	 * sched_setscheduler()
 	 */
 	struct sched_param p = { 1 };
 
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
 
-	TEST_PAUSE;
+	tp.type = tv->type;
 
 	/* Change scheduling policy to SCHED_FIFO */
-	if ((sched_setscheduler(0, SCHED_FIFO, &p)) == -1) {
-		tst_brkm(TBROK|TERRNO, cleanup, "sched_setscheduler() failed");
-	}
+	if ((sched_setscheduler(0, SCHED_FIFO, &p)) == -1)
+		tst_res(TFAIL | TTERRNO, "sched_setscheduler() failed");
 }
 
-/*
- *cleanup() -  performs all ONE TIME cleanup for this test at
- *		completion or premature exit.
- */
-void cleanup(void)
+static void run(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
 
+	tst_ts_set_sec(&tp, 99);
+	tst_ts_set_nsec(&tp, 99);
+
+	/*
+	 * Call sched_rr_get_interval(2) with pid=0 so that it will
+	 * write into the timespec structure pointed to by tp the
+	 * round robin time quantum for the current process.
+	 */
+	TEST(tv->func(0, tst_ts_get(&tp)));
+
+	if (!TST_RET && tst_ts_valid(&tp) == -1) {
+		tst_res(TPASS, "sched_rr_get_interval() passed");
+	} else {
+		tst_res(TFAIL | TTERRNO, "Test Failed, sched_rr_get_interval() returned %ld, tp.tv_sec = %lld, tp.tv_nsec = %lld",
+			TST_RET, tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
+	}
 }
+
+static struct tst_test test = {
+	.test_all = run,
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
+	.needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c
index 40b636b4dc65..0ccf47d2a561 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c
@@ -1,20 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/**********************************************************
  *
  *    TEST IDENTIFIER	: sched_rr_get_interval03
  *
@@ -68,104 +54,100 @@
  *				-P x : Pause for x seconds between iterations.
  *				-t   : Turn on syscall timing.
  *
- ****************************************************************/
+ */
 
-#include <errno.h>
 #include <sched.h>
-#include "test.h"
-
-static void setup();
-static void cleanup();
-
-char *TCID = "sched_rr_get_interval03";
-struct timespec tp;
+#include "tst_timer.h"
 
 static pid_t unused_pid;
 static pid_t inval_pid = -1;
 static pid_t zero_pid;
 
+struct tst_ts tp;
+static void *bad_addr;
+
 struct test_cases_t {
 	pid_t *pid;
-	struct timespec *tp;
+	struct tst_ts *tp;
 	int exp_errno;
 } test_cases[] = {
-	{
-	&inval_pid, &tp, EINVAL}, {
-	&unused_pid, &tp, ESRCH},
+	{ &inval_pid, &tp, EINVAL},
+	{ &unused_pid, &tp, ESRCH},
 #ifndef UCLINUX
-	    /* Skip since uClinux does not implement memory protection */
-	{
-	&zero_pid, (struct timespec *)-1, EFAULT}
+	/* Skip since uClinux does not implement memory protection */
+	{ &zero_pid, NULL, EFAULT}
 #endif
 };
 
-int TST_TOTAL = sizeof(test_cases) / sizeof(test_cases[0]);
+static struct test_variants {
+	int (*func)(pid_t pid, void *ts);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+	{ .func = libc_sched_rr_get_interval, .type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"},
 
-int main(int ac, char **av)
-{
-
-	int lc, i;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-
-		tst_count = 0;
-
-		for (i = 0; i < TST_TOTAL; ++i) {
-			/*
-			 * Call sched_rr_get_interval(2)
-			 */
-			TEST(sched_rr_get_interval(*(test_cases[i].pid),
-						   test_cases[i].tp));
-
-			if ((TEST_RETURN == -1) &&
-			    (TEST_ERRNO == test_cases[i].exp_errno)) {
-				tst_resm(TPASS, "Test Passed");
-			} else {
-				tst_resm(TFAIL | TTERRNO, "Test Failed,"
-					 " sched_rr_get_interval() returned %ld",
-					 TEST_RETURN);
-			}
-		}
-	}
-
-	/* cleanup and exit */
-	cleanup();
-
-	tst_exit();
+#if (__NR_sched_rr_get_interval != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_sched_rr_get_interval, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
 
-}
+#if (__NR_sched_rr_get_interval_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_sched_rr_get_interval64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
 
-/* setup() - performs all ONE TIME setup for this test */
-void setup(void)
+static void setup(void)
 {
-	tst_require_root();
+	struct test_variants *tv = &variants[tst_variant];
 	/*
 	 * Initialize scheduling parameter structure to use with
 	 * sched_setscheduler()
 	 */
 	struct sched_param p = { 1 };
 
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
 
-	TEST_PAUSE;
+	bad_addr = tst_get_bad_addr(NULL);
+	tp.type = tv->type;
 
 	/* Change scheduling policy to SCHED_RR */
-	if ((sched_setscheduler(0, SCHED_RR, &p)) == -1) {
-		tst_brkm(TBROK|TERRNO, cleanup, "sched_setscheduler() failed");
-	}
+	if ((sched_setscheduler(0, SCHED_RR, &p)) == -1)
+		tst_res(TFAIL | TTERRNO, "sched_setscheduler() failed");
 
-	unused_pid = tst_get_unused_pid(cleanup);
+	unused_pid = tst_get_unused_pid();
 }
 
-/*
- *cleanup() -  performs all ONE TIME cleanup for this test at
- *		completion or premature exit.
- */
-void cleanup(void)
+static void run(unsigned int i)
 {
+	struct test_variants *tv = &variants[tst_variant];
+	struct test_cases_t *tc = &test_cases[i];
+	struct timerspec *ts;
 
+	if (tc->exp_errno == EFAULT)
+		ts = bad_addr;
+	else
+		ts = tst_ts_get(tc->tp);
+
+	/*
+	 * Call sched_rr_get_interval(2)
+	 */
+	TEST(tv->func(*tc->pid, ts));
+
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "sched_rr_get_interval() passed unexcpectedly");
+		return;
+	}
+
+	if (tc->exp_errno == TST_ERR)
+		tst_res(TPASS | TTERRNO, "sched_rr_get_interval() failed as excpected");
+	else
+		tst_res(TFAIL | TTERRNO, "sched_rr_get_interval() failed unexcpectedly: %s",
+			tst_strerrno(tc->exp_errno));
 }
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(test_cases),
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
+	.needs_root = 1,
+};
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 06/19] syscalls/futex: Merge futex_wait_bitset tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (4 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 05/19] syscalls/sched_rr_get_interval: " Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-03  9:15   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 07/19] syscalls/futex: Add support for time64 tests Viresh Kumar
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

We can handle them easily in a single test, lets do it.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Petr Vorel <pvorel@suse.cz>
---
 runtest/syscalls                              |  1 -
 testcases/kernel/syscalls/futex/.gitignore    |  1 -
 testcases/kernel/syscalls/futex/Makefile      |  1 -
 .../kernel/syscalls/futex/futex_wait_bitset.h | 75 -------------------
 .../syscalls/futex/futex_wait_bitset01.c      | 73 +++++++++++++++++-
 .../syscalls/futex/futex_wait_bitset02.c      | 18 -----
 6 files changed, 71 insertions(+), 98 deletions(-)
 delete mode 100644 testcases/kernel/syscalls/futex/futex_wait_bitset.h
 delete mode 100644 testcases/kernel/syscalls/futex/futex_wait_bitset02.c

diff --git a/runtest/syscalls b/runtest/syscalls
index b4d523319924..5b3a0862faea 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1671,7 +1671,6 @@ futex_wake02 futex_wake02
 futex_wake03 futex_wake03
 futex_wake04 futex_wake04
 futex_wait_bitset01 futex_wait_bitset01
-futex_wait_bitset02 futex_wait_bitset02
 
 memfd_create01 memfd_create01
 memfd_create02 memfd_create02
diff --git a/testcases/kernel/syscalls/futex/.gitignore b/testcases/kernel/syscalls/futex/.gitignore
index 68bc2028e1b2..54cd02b0223f 100644
--- a/testcases/kernel/syscalls/futex/.gitignore
+++ b/testcases/kernel/syscalls/futex/.gitignore
@@ -6,7 +6,6 @@
 /futex_wait04
 /futex_wait05
 /futex_wait_bitset01
-/futex_wait_bitset02
 /futex_wake01
 /futex_wake02
 /futex_wake03
diff --git a/testcases/kernel/syscalls/futex/Makefile b/testcases/kernel/syscalls/futex/Makefile
index 8dd239301e63..c88af7c9643b 100644
--- a/testcases/kernel/syscalls/futex/Makefile
+++ b/testcases/kernel/syscalls/futex/Makefile
@@ -12,7 +12,6 @@ futex_wake02: CFLAGS+=-pthread
 futex_wake04: CFLAGS+=-pthread
 futex_wait05: LDLIBS+=-lrt
 futex_wait_bitset01: LDLIBS+=-lrt
-futex_wait_bitset02: LDLIBS+=-lrt
 
 include $(top_srcdir)/include/mk/testcases.mk
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/futex/futex_wait_bitset.h b/testcases/kernel/syscalls/futex/futex_wait_bitset.h
deleted file mode 100644
index 84712816bfe8..000000000000
--- a/testcases/kernel/syscalls/futex/futex_wait_bitset.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
- */
-
-#define THRESHOLD_US 100000
-#define DEFAULT_TIMEOUT_US 100010
-
-static void verify_futex_wait_bitset(long long wait_us, clock_t clk_id)
-{
-	struct timespec start, to, end;
-	futex_t futex = FUTEX_INITIALIZER;
-	u_int32_t bitset = 0xffffffff;
-	int flags = clk_id == CLOCK_REALTIME ? FUTEX_CLOCK_REALTIME : 0;
-
-	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);
-
-	TEST(futex_wait_bitset(&futex, futex, &to, bitset, flags));
-
-	clock_gettime(clk_id, &end);
-
-	if (TST_RET != -1) {
-		tst_res(TFAIL, "futex_wait_bitset() returned %li, expected -1",
-			TST_RET);
-		return;
-	}
-
-	if (TST_ERR == ENOSYS) {
-		tst_res(TCONF,
-			"In this kernel, futex() does not support FUTEX_WAIT_BITSET operation");
-		return;
-	}
-
-	if (TST_ERR != ETIMEDOUT) {
-		tst_res(TFAIL | TTERRNO, "expected %s",
-			tst_strerrno(ETIMEDOUT));
-		return;
-	}
-
-	if (tst_timespec_lt(end, to)) {
-		tst_res(TFAIL,
-			"futex_wait_bitset() woken up prematurely %llius, expected %llius",
-			tst_timespec_diff_us(end, start), wait_us);
-		return;
-	}
-
-	if (tst_timespec_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);
-		return;
-	}
-
-	tst_res(TPASS, "futex_wait_bitset() waited %llius, expected %llius",
-		tst_timespec_diff_us(end, start), wait_us);
-}
-
-static void setup(void)
-{
-	tst_timer_check(USE_CLOCK);
-}
-
-static void run(void)
-{
-	verify_futex_wait_bitset(DEFAULT_TIMEOUT_US, USE_CLOCK);
-}
-
-static struct tst_test test = {
-	.setup = setup,
-	.test_all = run,
-};
diff --git a/testcases/kernel/syscalls/futex/futex_wait_bitset01.c b/testcases/kernel/syscalls/futex/futex_wait_bitset01.c
index 1ae3253cfe13..b8546c3e640c 100644
--- a/testcases/kernel/syscalls/futex/futex_wait_bitset01.c
+++ b/testcases/kernel/syscalls/futex/futex_wait_bitset01.c
@@ -13,7 +13,76 @@
 #include "tst_timer.h"
 #include "futextest.h"
 
-#define USE_CLOCK CLOCK_MONOTONIC
+#define THRESHOLD_US 100000
+#define DEFAULT_TIMEOUT_US 100010
 
-#include "futex_wait_bitset.h"
+static struct test_case_t {
+	clockid_t clk_id;
+} tcases[] = {
+	{ CLOCK_MONOTONIC },
+	{ CLOCK_REALTIME }
+};
 
+static void verify_futex_wait_bitset(long long wait_us, clock_t clk_id)
+{
+	struct timespec start, to, end;
+	futex_t futex = FUTEX_INITIALIZER;
+	u_int32_t bitset = 0xffffffff;
+	int flags = clk_id == CLOCK_REALTIME ? FUTEX_CLOCK_REALTIME : 0;
+
+	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);
+
+	TEST(futex_wait_bitset(&futex, futex, &to, bitset, flags));
+
+	clock_gettime(clk_id, &end);
+
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "futex_wait_bitset() returned %li, expected -1",
+			TST_RET);
+		return;
+	}
+
+	if (TST_ERR == ENOSYS) {
+		tst_res(TCONF,
+			"In this kernel, futex() does not support FUTEX_WAIT_BITSET operation");
+		return;
+	}
+
+	if (TST_ERR != ETIMEDOUT) {
+		tst_res(TFAIL | TTERRNO, "expected %s",
+			tst_strerrno(ETIMEDOUT));
+		return;
+	}
+
+	if (tst_timespec_lt(end, to)) {
+		tst_res(TFAIL,
+			"futex_wait_bitset() woken up prematurely %llius, expected %llius",
+			tst_timespec_diff_us(end, start), wait_us);
+		return;
+	}
+
+	if (tst_timespec_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);
+		return;
+	}
+
+	tst_res(TPASS, "futex_wait_bitset() waited %llius, expected %llius",
+		tst_timespec_diff_us(end, start), wait_us);
+}
+
+static void run(unsigned int n)
+{
+	tst_timer_check(tcases[n].clk_id);
+	verify_futex_wait_bitset(DEFAULT_TIMEOUT_US, tcases[n].clk_id);
+}
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+};
diff --git a/testcases/kernel/syscalls/futex/futex_wait_bitset02.c b/testcases/kernel/syscalls/futex/futex_wait_bitset02.c
deleted file mode 100644
index 4d532fc07775..000000000000
--- a/testcases/kernel/syscalls/futex/futex_wait_bitset02.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
- *
- * 1. Block on a bitset futex and wait for timeout, the difference between
- *    normal futex and bitset futex is that that the later have absolute timeout.
- * 2. Check that the futex waited for expected time.
- */
-
-#include <errno.h>
-
-#include "tst_test.h"
-#include "tst_timer.h"
-#include "futextest.h"
-
-#define USE_CLOCK CLOCK_REALTIME
-
-#include "futex_wait_bitset.h"
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 07/19] syscalls/futex: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (5 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 06/19] syscalls/futex: Merge futex_wait_bitset tests Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-03 12:45   ` Cyril Hrubis
  2020-07-06 11:40   ` [LTP] [PATCH V7.1 " Viresh Kumar
  2020-06-26  6:22 ` [LTP] [PATCH V7 08/19] syscalls/io_pgetevents: " Viresh Kumar
                   ` (12 subsequent siblings)
  19 siblings, 2 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing futex() syscall
tests.

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);
+	}
+}
+
 #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;
 	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);
+
+	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;
 	}
 
-	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");
 }
 
 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;
 	}
 
-	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");
 		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;
+	}
 
 	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");
 }
 
-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);
 
+	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();
 
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");
 		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;
 		}
 	}
 
@@ -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);
 	}
 }
 
-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);
 		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);
 	} 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;
 		}
 	}
 
-	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);
 	} 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);
 
-	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;
 }
 
 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");
+		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


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 08/19] syscalls/io_pgetevents: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (6 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 07/19] syscalls/futex: Add support for time64 tests Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-03 14:59   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 09/19] syscalls/sigwaitinfo: Migrate to new test framework Viresh Kumar
                   ` (11 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing io_pgetevents()
syscall tests.

While at it, also pass mode to SAFE_OPEN() to avoid any errors when the
tests are run for multiple variants together.

Also get rid of an extra copy of local fd variable, which is incorrect.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 include/lapi/io_pgetevents.h                  | 15 ++++--
 .../syscalls/io_pgetevents/io_pgetevents01.c  | 33 +++++++++++-
 .../syscalls/io_pgetevents/io_pgetevents02.c  | 51 +++++++++++++++----
 3 files changed, 83 insertions(+), 16 deletions(-)

diff --git a/include/lapi/io_pgetevents.h b/include/lapi/io_pgetevents.h
index 3c9d5b2d7618..5bb9a60c352a 100644
--- a/include/lapi/io_pgetevents.h
+++ b/include/lapi/io_pgetevents.h
@@ -16,15 +16,20 @@
 #ifdef HAVE_LIBAIO
 #include <libaio.h>
 
-#ifndef HAVE_IO_PGETEVENTS
-int io_pgetevents(io_context_t ctx, long min_nr, long max_nr,
-		 struct io_event *events, struct timespec *timeout,
-		 sigset_t *sigmask)
+static inline int sys_io_pgetevents(io_context_t ctx, long min_nr, long max_nr,
+		struct io_event *events, void *timeout, sigset_t *sigmask)
 {
 	return tst_syscall(__NR_io_pgetevents, ctx, min_nr, max_nr, events,
 			   timeout, sigmask);
 }
-#endif /* HAVE_IO_PGETEVENTS */
+
+static inline int sys_io_pgetevents_time64(io_context_t ctx, long min_nr, long max_nr,
+		struct io_event *events, void *timeout, sigset_t *sigmask)
+{
+	return tst_syscall(__NR_io_pgetevents_time64, ctx, min_nr, max_nr,
+			   events, timeout, sigmask);
+}
+
 #endif /* HAVE_LIBAIO */
 
 #endif /* IO_PGETEVENTS_H */
diff --git a/testcases/kernel/syscalls/io_pgetevents/io_pgetevents01.c b/testcases/kernel/syscalls/io_pgetevents/io_pgetevents01.c
index e6077e47984d..fea380e52f4d 100644
--- a/testcases/kernel/syscalls/io_pgetevents/io_pgetevents01.c
+++ b/testcases/kernel/syscalls/io_pgetevents/io_pgetevents01.c
@@ -6,11 +6,32 @@
  * Basic io_pgetevents() test to receive 1 event successfully.
  */
 #include "tst_test.h"
+#include "tst_timer.h"
 #include "lapi/io_pgetevents.h"
 
 #ifdef HAVE_LIBAIO
 static int fd;
 
+static struct test_variants {
+	int (*io_pgetevents)(io_context_t ctx, long min_nr, long max_nr,
+		struct io_event *events, void *timeout, sigset_t *sigmask);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_io_pgetevents != __LTP__NR_INVALID_SYSCALL)
+	{ .io_pgetevents = sys_io_pgetevents, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_io_pgetevents_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .io_pgetevents = sys_io_pgetevents_time64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static void setup(void)
+{
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
+}
+
 static void cleanup(void)
 {
 	if (fd > 0)
@@ -19,12 +40,18 @@ static void cleanup(void)
 
 static void run(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	struct io_event events[1];
 	struct iocb cb, *cbs[1];
 	io_context_t ctx = 0;
+	struct tst_ts to;
 	sigset_t sigmask;
 	char data[4096];
-	int ret, fd;
+	int ret;
+
+	to.type = tv->type;
+	tst_ts_set_sec(&to, 0);
+	tst_ts_set_nsec(&to, 10000);
 
 	cbs[0] = &cb;
 	sigemptyset(&sigmask);
@@ -41,7 +68,7 @@ static void run(void)
 		tst_brk(TBROK | TERRNO, "io_submit() failed");
 
 	/* get the reply */
-	ret = io_pgetevents(ctx, 1, 1, events, NULL, &sigmask);
+	ret = tv->io_pgetevents(ctx, 1, 1, events, tst_ts_get(&to), &sigmask);
 
 	if (ret == 1)
 		tst_res(TPASS, "io_pgetevents() works as expected");
@@ -55,8 +82,10 @@ static void run(void)
 static struct tst_test test = {
 	.min_kver = "4.18",
 	.test_all = run,
+	.test_variants = ARRAY_SIZE(variants),
 	.needs_tmpdir = 1,
 	.cleanup = cleanup,
+	.setup = setup,
 };
 
 #else
diff --git a/testcases/kernel/syscalls/io_pgetevents/io_pgetevents02.c b/testcases/kernel/syscalls/io_pgetevents/io_pgetevents02.c
index 62a8afba3bf1..a15b3d0dda92 100644
--- a/testcases/kernel/syscalls/io_pgetevents/io_pgetevents02.c
+++ b/testcases/kernel/syscalls/io_pgetevents/io_pgetevents02.c
@@ -6,6 +6,7 @@
  * Basic io_pgetevents() test to check various failures.
  */
 #include "tst_test.h"
+#include "tst_timer.h"
 #include "lapi/io_pgetevents.h"
 
 #ifdef HAVE_LIBAIO
@@ -14,30 +15,55 @@ static struct io_event events[1];
 static io_context_t ctx, invalid_ctx = 0;
 static int fd, ctx_initialized;
 
+static struct tst_ts to;
+static void *bad_addr;
+
 static struct tcase {
 	char *name;
 	io_context_t *ctx;
 	long min_nr;
 	long max_nr;
 	struct io_event *events;
-	struct timespec *timeout;
+	struct tst_ts *timeout;
 	sigset_t *sigmask;
 	int exp_errno;
 } tcases[] = {
-	{"invalid ctx", &invalid_ctx, 1, 1, events, NULL, &sigmask, EINVAL},
-	{"invalid min_nr", &ctx, -1, 1, events, NULL, &sigmask, EINVAL},
-	{"invalid max_nr", &ctx, 1, -1, events, NULL, &sigmask, EINVAL},
-	{"invalid events", &ctx, 1, 1, NULL, NULL, &sigmask, EFAULT},
-	{"invalid timeout", &ctx, 1, 1, events, (void *)(0xDEAD), &sigmask, EFAULT},
-	{"invalid sigmask", &ctx, 1, 1, events, NULL, (void *)(0xDEAD), EFAULT},
+	{"invalid ctx", &invalid_ctx, 1, 1, events, &to, &sigmask, EINVAL},
+	{"invalid min_nr", &ctx, -1, 1, events, &to, &sigmask, EINVAL},
+	{"invalid max_nr", &ctx, 1, -1, events, &to, &sigmask, EINVAL},
+	{"invalid events", &ctx, 1, 1, NULL, &to, &sigmask, EFAULT},
+	{"invalid timeout", &ctx, 1, 1, events, NULL, &sigmask, EFAULT},
+	{"invalid sigmask", &ctx, 1, 1, events, &to, NULL, EFAULT},
+};
+
+static struct test_variants {
+	int (*io_pgetevents)(io_context_t ctx, long min_nr, long max_nr,
+		struct io_event *events, void *timeout, sigset_t *sigmask);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_io_pgetevents != __LTP__NR_INVALID_SYSCALL)
+	{ .io_pgetevents = sys_io_pgetevents, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_io_pgetevents_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .io_pgetevents = sys_io_pgetevents_time64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
 };
 
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	struct iocb cb, *cbs[1];
 	char data[4096];
 	int ret;
 
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	bad_addr = tst_get_bad_addr(NULL);
+	to.type = tv->type;
+	tst_ts_set_sec(&to, 0);
+	tst_ts_set_nsec(&to, 10000);
+
 	cbs[0] = &cb;
 
 	sigemptyset(&sigmask);
@@ -69,10 +95,16 @@ static void cleanup(void)
 
 static void run(unsigned int n)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	struct tcase *tc = &tcases[n];
+	struct timespec *to;
+	sigset_t *sigmask;
+
+	sigmask = tc->sigmask ? tc->sigmask : bad_addr;
+	to = tc->timeout ? tc->timeout : bad_addr;
 
-	TEST(io_pgetevents(*tc->ctx, tc->min_nr, tc->max_nr, tc->events,
-			   tc->timeout, tc->sigmask));
+	TEST(tv->io_pgetevents(*tc->ctx, tc->min_nr, tc->max_nr, tc->events, to,
+			       sigmask));
 
 	if (TST_RET == 1) {
 		tst_res(TFAIL, "%s: io_pgetevents() passed unexpectedly",
@@ -95,6 +127,7 @@ static struct tst_test test = {
 	.needs_tmpdir = 1,
 	.tcnt = ARRAY_SIZE(tcases),
 	.test = run,
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.cleanup = cleanup,
 };
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 09/19] syscalls/sigwaitinfo: Migrate to new test framework
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (7 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 08/19] syscalls/io_pgetevents: " Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-03 13:58   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 10/19] syscalls/rt_sigtimedwait: Add support for time64 tests Viresh Kumar
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This migrates the sigwaitinfo tests to use the new test framework.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../syscalls/sigwaitinfo/sigwaitinfo01.c      | 209 +++++++-----------
 1 file changed, 84 insertions(+), 125 deletions(-)

diff --git a/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c b/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c
index 6a30c27f6f2f..1b976a271d28 100644
--- a/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c
+++ b/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c
@@ -1,93 +1,58 @@
-/*
- * Copyright (c) Jiri Palecek<jpalecek@web.de>, 2009
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#include "test.h"
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) Jiri Palecek<jpalecek@web.de>, 2009 */
+
+#include "tst_test.h"
 #include <errno.h>
+#include <stdlib.h>
 #include <signal.h>
-#include "../utils/include_j_h.h"
-#include "../utils/common_j_h.c"
 #include <limits.h>
 #include "lapi/syscalls.h"
+#include "tst_sig_proc.h"
 
 #define SUCCEED_OR_DIE(syscall, message, ...)				 \
 	(errno = 0,							 \
 		({int ret=syscall(__VA_ARGS__);				 \
 			if (ret==-1)					 \
-				tst_brkm(TBROK|TERRNO, cleanup, message);\
+				tst_brk(TBROK|TERRNO, message);\
 			ret;}))
 
-/* Report success iff TEST_RETURN and TEST_ERRNO are equal to
+/* Report success iff TST_RET and TST_ERR are equal to
 	 exp_return and exp_errno, resp., and cond is true. If cond is not
 	 true, report condition_errmsg
 */
-static void report_success_cond(const char *func, const char *file, int line,
+static void report_success_cond(const char *func, int line,
 				long exp_return, int exp_errno, int condition,
 				char *condition_errmsg)
 {
-	if (exp_return == TEST_RETURN
-	    && (exp_return != -1 || exp_errno == TEST_ERRNO))
+	if (exp_return == TST_RET
+	    && (exp_return != -1 || exp_errno == TST_ERR))
 		if (condition)
-			tst_resm(TPASS, "Test passed");
+			tst_res(TPASS, "%s (%d): Test passed", func, line);
 		else
-			tst_resm(TFAIL, "%s (%s: %d): %s", func, file, line,
+			tst_res(TFAIL, "%s (%d): %s", func, line,
 				 condition_errmsg);
-	else if (TEST_RETURN != -1)
-		tst_resm(TFAIL,
-			 "%s (%s: %d): Unexpected return value; expected %ld, got %ld",
-			 func, file, line, exp_return, TEST_RETURN);
+	else if (TST_RET != -1)
+		tst_res(TFAIL,
+			 "%s (%d): Unexpected return value; expected %ld, got %ld",
+			 func, line, exp_return, TST_RET);
 	else
-		tst_resm(TFAIL | TTERRNO, "%s (%s: %d): Unexpected failure",
-			 func, file, line);
+		tst_res(TFAIL | TTERRNO, "%s (%d): Unexpected failure",
+			 func, line);
 }
 
 #define REPORT_SUCCESS_COND(exp_return, exp_errno, condition, condition_errmsg)	\
-	report_success_cond(__FUNCTION__, __FILE__, __LINE__, exp_return, exp_errno, condition, condition_errmsg);
+	report_success_cond(__FUNCTION__, __LINE__, exp_return, exp_errno, condition, condition_errmsg);
 
-/* Report success iff TEST_RETURN and TEST_ERRNO are equal to
+/* Report success iff TST_RET and TST_ERR are equal to
 	 exp_return and exp_errno, resp.
 */
 #define REPORT_SUCCESS(exp_return, exp_errno)					\
 	REPORT_SUCCESS_COND(exp_return, exp_errno, 1, "");
 
-static void cleanup(void);
-
 static void empty_handler(int sig)
 {
 }
 
-static void setup(void)
-{
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-	signal(SIGUSR1, empty_handler);
-	signal(SIGALRM, empty_handler);
-	signal(SIGUSR2, SIG_IGN);
-
-	TEST_PAUSE;
-}
-
-static void cleanup(void)
-{
-}
-
 typedef int (*swi_func) (const sigset_t * set, siginfo_t * info,
 			 struct timespec * timeout);
 typedef void (*test_func) (swi_func, int);
@@ -110,7 +75,6 @@ static int my_sigwait(const sigset_t * set, siginfo_t * info,
 static int my_sigwaitinfo(const sigset_t * set, siginfo_t * info,
 			  struct timespec *timeout)
 {
-
 	return sigwaitinfo(set, info);
 }
 #endif
@@ -119,7 +83,6 @@ static int my_sigwaitinfo(const sigset_t * set, siginfo_t * info,
 static int my_sigtimedwait(const sigset_t * set, siginfo_t * info,
 			   struct timespec *timeout)
 {
-
 	return sigtimedwait(set, info, timeout);
 }
 #endif
@@ -129,7 +92,7 @@ static int my_rt_sigtimedwait(const sigset_t * set, siginfo_t * info,
 			      struct timespec *timeout)
 {
 	/* _NSIG is always the right number of bits of signal map for all arches */
-	return ltp_syscall(__NR_rt_sigtimedwait, set, info, timeout, _NSIG/8);
+	return tst_syscall(__NR_rt_sigtimedwait, set, info, timeout, _NSIG/8);
 }
 #endif
 
@@ -141,12 +104,13 @@ void test_empty_set(swi_func sigwaitinfo, int signo)
 
 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
 	/* Run a child that will wake us up */
-	child = create_sig_proc(100000, signo, UINT_MAX);
+	child = create_sig_proc(signo, INT_MAX, 100000);
 
 	TEST(sigwaitinfo(&sigs, &si, NULL));
 	REPORT_SUCCESS(-1, EINTR);
 
-	kill(child, SIGTERM);
+	SAFE_KILL(child, SIGTERM);
+	SAFE_WAIT(NULL);
 }
 
 void test_timeout(swi_func sigwaitinfo, int signo)
@@ -159,12 +123,13 @@ void test_timeout(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
 
 	/* Run a child that will wake us up */
-	child = create_sig_proc(100000, signo, UINT_MAX);
+	child = create_sig_proc(signo, INT_MAX, 100000);
 
 	TEST(sigwaitinfo(&sigs, &si, &ts));
 	REPORT_SUCCESS(-1, EAGAIN);
 
-	kill(child, SIGTERM);
+	SAFE_KILL(child, SIGTERM);
+	SAFE_WAIT(NULL);
 }
 
 /* Note: sigwait-ing for a signal that is not blocked is unspecified
@@ -180,14 +145,15 @@ void test_unmasked_matching(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
 
 	/* Run a child that will wake us up */
-	child = create_sig_proc(100000, signo, UINT_MAX);
+	child = create_sig_proc(signo, INT_MAX, 100000);
 
 	TEST(sigwaitinfo(&sigs, &si, NULL));
 	REPORT_SUCCESS_COND(signo, 0, si.si_pid == child
 			    && si.si_code == SI_USER
 			    && si.si_signo == signo, "Struct siginfo mismatch");
 
-	kill(child, SIGTERM);
+	SAFE_KILL(child, SIGTERM);
+	SAFE_WAIT(NULL);
 }
 
 void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo)
@@ -198,12 +164,13 @@ void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
 	/* Run a child that will wake us up */
-	child = create_sig_proc(100000, signo, UINT_MAX);
+	child = create_sig_proc(signo, INT_MAX, 100000);
 
 	TEST(sigwaitinfo(&sigs, NULL, NULL));
 	REPORT_SUCCESS(signo, 0);
 
-	kill(child, SIGTERM);
+	SAFE_KILL(child, SIGTERM);
+	SAFE_WAIT(NULL);
 }
 
 void test_masked_matching(swi_func sigwaitinfo, int signo)
@@ -224,7 +191,7 @@ void test_masked_matching(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
 
 	/* Run a child that will wake us up */
-	child = create_sig_proc(0, signo, 1);
+	child = create_sig_proc(signo, 1, 0);
 
 	TEST(sigwaitinfo(&sigs, &si, NULL));
 	REPORT_SUCCESS_COND(signo, 0, si.si_pid == child
@@ -234,13 +201,14 @@ void test_masked_matching(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
 		       SIG_SETMASK, &oldmask, &oldmask);
 
-	tst_count--;
-
 	if (sigismember(&oldmask, signo))
-		tst_resm(TPASS, "sigwaitinfo restored the original mask");
+		tst_res(TPASS, "sigwaitinfo restored the original mask");
 	else
-		tst_resm(TFAIL,
+		tst_res(TFAIL,
 			 "sigwaitinfo failed to restore the original mask");
+
+	SAFE_KILL(child, SIGTERM);
+	SAFE_WAIT(NULL);
 }
 
 void test_masked_matching_rt(swi_func sigwaitinfo, int signo)
@@ -265,12 +233,12 @@ void test_masked_matching_rt(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigdelset, "sigdelset failed", &sigs, SIGCHLD);
 
 	/* Run a child that will wake us up */
-	child[0] = create_sig_proc(0, signo, 1);
-	child[1] = create_sig_proc(0, signo + 1, 1);
+	child[0] = create_sig_proc(signo, 1, 0);
+	child[1] = create_sig_proc(signo + 1, 1, 0);
 
 	/* Ensure that the signals have been sent */
-	waitpid(child[0], &status, 0);
-	waitpid(child[1], &status, 0);
+	SAFE_WAITPID(child[0], &status, 0);
+	SAFE_WAITPID(child[1], &status, 0);
 
 	TEST(sigwaitinfo(&sigs, &si, NULL));
 	REPORT_SUCCESS_COND(signo, 0, si.si_pid == child[0]
@@ -278,7 +246,6 @@ void test_masked_matching_rt(swi_func sigwaitinfo, int signo)
 			    && si.si_signo == signo, "Struct siginfo mismatch");
 
 	/* eat the other signal */
-	tst_count--;
 	TEST(sigwaitinfo(&sigs, &si, NULL));
 	REPORT_SUCCESS_COND(signo + 1, 0, si.si_pid == child[1]
 			    && si.si_code == SI_USER
@@ -288,12 +255,10 @@ void test_masked_matching_rt(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
 		       SIG_SETMASK, &oldmask, &oldmask);
 
-	tst_count--;
-
 	if (sigismember(&oldmask, signo))
-		tst_resm(TPASS, "sigwaitinfo restored the original mask");
+		tst_res(TPASS, "sigwaitinfo restored the original mask");
 	else
-		tst_resm(TFAIL,
+		tst_res(TFAIL,
 			 "sigwaitinfo failed to restore the original mask");
 }
 
@@ -314,7 +279,7 @@ void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
 
 	/* Run a child that will wake us up */
-	child = create_sig_proc(0, signo, 1);
+	child = create_sig_proc(signo, 1, 0);
 
 	TEST(sigwaitinfo(&sigs, NULL, NULL));
 	REPORT_SUCCESS(signo, 0);
@@ -322,14 +287,14 @@ void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
 		       SIG_SETMASK, &oldmask, &oldmask);
 
-	tst_count--;
-
 	if (sigismember(&oldmask, signo))
-		tst_resm(TPASS, "sigwaitinfo restored the original mask");
+		tst_res(TPASS, "sigwaitinfo restored the original mask");
 	else
-		tst_resm(TFAIL,
+		tst_res(TFAIL,
 			 "sigwaitinfo failed to restore the original mask");
 
+	SAFE_KILL(child, SIGTERM);
+	SAFE_WAIT(NULL);
 }
 
 void test_bad_address(swi_func sigwaitinfo, int signo)
@@ -349,7 +314,7 @@ void test_bad_address(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
 
 	/* Run a child that will wake us up */
-	child = create_sig_proc(0, signo, 1);
+	child = create_sig_proc(signo, 1, 0);
 
 	TEST(sigwaitinfo(&sigs, (void *)1, NULL));
 	REPORT_SUCCESS(-1, EFAULT);
@@ -357,7 +322,8 @@ void test_bad_address(swi_func sigwaitinfo, int signo)
 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &oldmask,
 		       &oldmask);
 
-	kill(child, SIGTERM);
+	SAFE_KILL(child, SIGTERM);
+	SAFE_WAIT(NULL);
 }
 
 void test_bad_address2(swi_func sigwaitinfo, int signo)
@@ -367,7 +333,7 @@ void test_bad_address2(swi_func sigwaitinfo, int signo)
 
 	switch (pid = fork()) {
 	case -1:
-		tst_brkm(TBROK | TERRNO, NULL, "fork() failed");
+		tst_brk(TBROK | TERRNO, "fork() failed");
 	case 0:
 		signal(SIGSEGV, SIG_DFL);
 
@@ -377,31 +343,31 @@ void test_bad_address2(swi_func sigwaitinfo, int signo)
 		 */
 		TEST(sigwaitinfo((void *)1, NULL, NULL));
 
-		if (TEST_RETURN == -1 && TEST_ERRNO == EFAULT)
+		if (TST_RET == -1 && TST_ERR == EFAULT)
 			_exit(0);
 
-		tst_resm(TINFO | TTERRNO, "swi_func returned: %ld",
-			TEST_RETURN);
+		tst_res(TINFO | TTERRNO, "swi_func returned: %ld",
+			TST_RET);
 		_exit(1);
 		break;
 	default:
 		break;
 	}
 
-	SUCCEED_OR_DIE(waitpid, "waitpid failed", pid, &status, 0);
+	SAFE_WAITPID(pid, &status, 0);
 
 	if ((WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)
 		|| (WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
-		tst_resm(TPASS, "Test passed");
+		tst_res(TPASS, "Test passed");
 		return;
 	}
 
 	if (WIFEXITED(status)) {
-		tst_resm(TFAIL, "Unrecognised child exit code: %d",
+		tst_res(TFAIL, "Unrecognised child exit code: %d",
 			WEXITSTATUS(status));
 	}
 	if (WIFSIGNALED(status)) {
-		tst_resm(TFAIL, "Unrecognised child termsig: %d",
+		tst_res(TFAIL, "Unrecognised child termsig: %d",
 			WTERMSIG(status));
 	}
 }
@@ -474,38 +440,31 @@ struct test_desc {
 #endif
 };
 
-#if defined TEST_SIGWAITINFO
-const char *TCID = "sigwaitinfo01";
-#elif defined TEST_RT_SIGTIMEDWAIT
-const char *TCID = "rt_sigtimedwait01";
-#elif defined TEST_SIGTIMEDWAIT
-const char *TCID = "sigtimedwait01";
-#elif defined TEST_SIGWAIT
-const char *TCID = "sigwait01";
-#endif
-
-int TST_TOTAL = ARRAY_SIZE(tests);
-
-int main(int argc, char **argv)
+static void run(unsigned int i)
 {
-	unsigned i;
-	int lc;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
+	struct test_desc *tc = &tests[i];
 
-	setup();
+	tc->tf(tc->swi, tc->signo);
+}
 
-	for (lc = 0; TEST_LOOPING(lc); ++lc) {
-		tst_count = 0;
+static void setup(void)
+{
+	signal(SIGUSR1, empty_handler);
+	signal(SIGALRM, empty_handler);
+	signal(SIGUSR2, SIG_IGN);
 
-		for (i = 0; i < ARRAY_SIZE(tests); i++) {
-			alarm(10);	/* arrange a 10 second timeout */
-			tst_resm(TINFO, "%p, %d", tests[i].swi, tests[i].signo);
-			tests[i].tf(tests[i].swi, tests[i].signo);
-		}
-		alarm(0);
-	}
+	alarm(10);	/* arrange a 10 second timeout */
+}
 
-	cleanup();
-	tst_exit();
+static void cleanup(void)
+{
+	alarm(0);
 }
+
+static struct tst_test test = {
+	.test= run,
+	.tcnt = ARRAY_SIZE(tests),
+	.setup = setup,
+	.cleanup = cleanup,
+	.forks_child = 1,
+};
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 10/19] syscalls/rt_sigtimedwait: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (8 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 09/19] syscalls/sigwaitinfo: Migrate to new test framework Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-22 10:03   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 11/19] syscalls/mq_timed{send|receive}: " Viresh Kumar
                   ` (9 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing rt_sigtimedwait()
syscall tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../syscalls/sigwaitinfo/sigwaitinfo01.c      | 112 +++++++++++++-----
 1 file changed, 80 insertions(+), 32 deletions(-)

diff --git a/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c b/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c
index 1b976a271d28..05e62999ca6c 100644
--- a/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c
+++ b/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c
@@ -2,6 +2,7 @@
 /* Copyright (c) Jiri Palecek<jpalecek@web.de>, 2009 */
 
 #include "tst_test.h"
+#include "tst_timer.h"
 #include <errno.h>
 #include <stdlib.h>
 #include <signal.h>
@@ -54,12 +55,12 @@ static void empty_handler(int sig)
 }
 
 typedef int (*swi_func) (const sigset_t * set, siginfo_t * info,
-			 struct timespec * timeout);
-typedef void (*test_func) (swi_func, int);
+			 void * timeout);
+typedef void (*test_func) (swi_func, int, enum tst_ts_type type);
 
 #ifdef TEST_SIGWAIT
 static int my_sigwait(const sigset_t * set, siginfo_t * info,
-		      struct timespec *timeout)
+		      void *timeout)
 {
 	int ret;
 	int err = sigwait(set, &ret);
@@ -73,7 +74,7 @@ static int my_sigwait(const sigset_t * set, siginfo_t * info,
 
 #ifdef TEST_SIGWAITINFO
 static int my_sigwaitinfo(const sigset_t * set, siginfo_t * info,
-			  struct timespec *timeout)
+			  void *timeout)
 {
 	return sigwaitinfo(set, info);
 }
@@ -81,7 +82,7 @@ static int my_sigwaitinfo(const sigset_t * set, siginfo_t * info,
 
 #ifdef TEST_SIGTIMEDWAIT
 static int my_sigtimedwait(const sigset_t * set, siginfo_t * info,
-			   struct timespec *timeout)
+			   void *timeout)
 {
 	return sigtimedwait(set, info, timeout);
 }
@@ -89,14 +90,23 @@ static int my_sigtimedwait(const sigset_t * set, siginfo_t * info,
 
 #ifdef TEST_RT_SIGTIMEDWAIT
 static int my_rt_sigtimedwait(const sigset_t * set, siginfo_t * info,
-			      struct timespec *timeout)
+			      void *timeout)
 {
 	/* _NSIG is always the right number of bits of signal map for all arches */
 	return tst_syscall(__NR_rt_sigtimedwait, set, info, timeout, _NSIG/8);
 }
+
+#if (__NR_rt_sigtimedwait_time64 != __LTP__NR_INVALID_SYSCALL)
+static int my_rt_sigtimedwait_time64(const sigset_t * set, siginfo_t * info,
+				     void *timeout)
+{
+	/* _NSIG is always the right number of bits of signal map for all arches */
+	return tst_syscall(__NR_rt_sigtimedwait_time64, set, info, timeout, _NSIG/8);
+}
+#endif
 #endif
 
-void test_empty_set(swi_func sigwaitinfo, int signo)
+void test_empty_set(swi_func sigwaitinfo, int signo, enum tst_ts_type type)
 {
 	sigset_t sigs;
 	siginfo_t si;
@@ -113,19 +123,23 @@ void test_empty_set(swi_func sigwaitinfo, int signo)
 	SAFE_WAIT(NULL);
 }
 
-void test_timeout(swi_func sigwaitinfo, int signo)
+void test_timeout(swi_func sigwaitinfo, int signo, enum tst_ts_type type)
 {
 	sigset_t sigs;
 	siginfo_t si;
 	pid_t child;
-	struct timespec ts = {.tv_sec = 1 };
+	struct tst_ts ts;
+
+	ts.type = type;
+	tst_ts_set_sec(&ts, 1);
+	tst_ts_set_nsec(&ts, 0);
 
 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
 
 	/* Run a child that will wake us up */
 	child = create_sig_proc(signo, INT_MAX, 100000);
 
-	TEST(sigwaitinfo(&sigs, &si, &ts));
+	TEST(sigwaitinfo(&sigs, &si, tst_ts_get(&ts)));
 	REPORT_SUCCESS(-1, EAGAIN);
 
 	SAFE_KILL(child, SIGTERM);
@@ -135,7 +149,8 @@ void test_timeout(swi_func sigwaitinfo, int signo)
 /* Note: sigwait-ing for a signal that is not blocked is unspecified
  * by POSIX; but works for non-ignored signals under Linux
  */
-void test_unmasked_matching(swi_func sigwaitinfo, int signo)
+void test_unmasked_matching(swi_func sigwaitinfo, int signo,
+			    enum tst_ts_type type)
 {
 	sigset_t sigs;
 	siginfo_t si;
@@ -156,7 +171,8 @@ void test_unmasked_matching(swi_func sigwaitinfo, int signo)
 	SAFE_WAIT(NULL);
 }
 
-void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo)
+void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo,
+				   enum tst_ts_type type)
 {
 	sigset_t sigs;
 	pid_t child;
@@ -173,7 +189,8 @@ void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo)
 	SAFE_WAIT(NULL);
 }
 
-void test_masked_matching(swi_func sigwaitinfo, int signo)
+void test_masked_matching(swi_func sigwaitinfo, int signo,
+			  enum tst_ts_type type)
 {
 	sigset_t sigs, oldmask;
 	siginfo_t si;
@@ -211,7 +228,8 @@ void test_masked_matching(swi_func sigwaitinfo, int signo)
 	SAFE_WAIT(NULL);
 }
 
-void test_masked_matching_rt(swi_func sigwaitinfo, int signo)
+void test_masked_matching_rt(swi_func sigwaitinfo, int signo,
+			     enum tst_ts_type type)
 {
 	sigset_t sigs, oldmask;
 	siginfo_t si;
@@ -262,7 +280,8 @@ void test_masked_matching_rt(swi_func sigwaitinfo, int signo)
 			 "sigwaitinfo failed to restore the original mask");
 }
 
-void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo)
+void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo,
+				 enum tst_ts_type type)
 {
 	sigset_t sigs, oldmask;
 	pid_t child;
@@ -297,7 +316,7 @@ void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo)
 	SAFE_WAIT(NULL);
 }
 
-void test_bad_address(swi_func sigwaitinfo, int signo)
+void test_bad_address(swi_func sigwaitinfo, int signo, enum tst_ts_type type)
 {
 	sigset_t sigs, oldmask;
 	pid_t child;
@@ -326,7 +345,7 @@ void test_bad_address(swi_func sigwaitinfo, int signo)
 	SAFE_WAIT(NULL);
 }
 
-void test_bad_address2(swi_func sigwaitinfo, int signo)
+void test_bad_address2(swi_func sigwaitinfo, int signo, enum tst_ts_type type)
 {
 	pid_t pid;
 	int status;
@@ -372,7 +391,7 @@ void test_bad_address2(swi_func sigwaitinfo, int signo)
 	}
 }
 
-void test_bad_address3(swi_func sigwaitinfo, int signo)
+void test_bad_address3(swi_func sigwaitinfo, int signo, enum tst_ts_type type)
 {
 	sigset_t sigs;
 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
@@ -388,28 +407,28 @@ struct test_desc {
 } tests[] = {
 #ifdef TEST_RT_SIGTIMEDWAIT
 	{
-	test_empty_set, my_rt_sigtimedwait, SIGUSR1}, {
-	test_unmasked_matching, my_rt_sigtimedwait, SIGUSR1}, {
-	test_masked_matching, my_rt_sigtimedwait, SIGUSR1}, {
-	test_unmasked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, {
-	test_masked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, {
-	test_bad_address, my_rt_sigtimedwait, SIGUSR1}, {
-	test_bad_address2, my_rt_sigtimedwait, SIGUSR1}, {
-	test_bad_address3, my_rt_sigtimedwait, SIGUSR1}, {
-	test_timeout, my_rt_sigtimedwait, 0},
+	test_empty_set, NULL, SIGUSR1}, {
+	test_unmasked_matching, NULL, SIGUSR1}, {
+	test_masked_matching, NULL, SIGUSR1}, {
+	test_unmasked_matching_noinfo, NULL, SIGUSR1}, {
+	test_masked_matching_noinfo, NULL, SIGUSR1}, {
+	test_bad_address, NULL, SIGUSR1}, {
+	test_bad_address2, NULL, SIGUSR1}, {
+	test_bad_address3, NULL, SIGUSR1}, {
+	test_timeout, NULL, 0},
 	    /* Special cases */
 	    /* 1: sigwaitinfo does respond to ignored signal */
 	{
-	test_masked_matching, my_rt_sigtimedwait, SIGUSR2},
+	test_masked_matching, NULL, SIGUSR2},
 	    /* 2: An ignored signal doesn't cause sigwaitinfo to return EINTR */
 	{
-	test_timeout, my_rt_sigtimedwait, SIGUSR2},
+	test_timeout, NULL, SIGUSR2},
 	    /* 3: The handler is not called when the signal is waited for by sigwaitinfo */
 	{
-	test_masked_matching, my_rt_sigtimedwait, SIGTERM},
+	test_masked_matching, NULL, SIGTERM},
 	    /* 4: Simultaneous realtime signals are delivered in the order of increasing signal number */
 	{
-	test_masked_matching_rt, my_rt_sigtimedwait, -1},
+	test_masked_matching_rt, NULL, -1},
 #endif
 #if defined TEST_SIGWAIT
 	{
@@ -440,15 +459,43 @@ struct test_desc {
 #endif
 };
 
+static struct test_variants {
+	swi_func swi;
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#ifdef TEST_RT_SIGTIMEDWAIT
+
+#if (__NR_rt_sigtimedwait != __LTP__NR_INVALID_SYSCALL)
+	{ .swi = my_rt_sigtimedwait, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_rt_sigtimedwait_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .swi = my_rt_sigtimedwait_time64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+
+#else /* !TEST_RT_SIGTIMEDWAIT */
+
+	{ .swi = NULL, .type = TST_LIBC_TIMESPEC, .desc = "syscall with libc spec"},
+
+#endif /* TEST_RT_SIGTIMEDWAIT */
+};
+
 static void run(unsigned int i)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	struct test_desc *tc = &tests[i];
+	swi_func swi;
 
-	tc->tf(tc->swi, tc->signo);
+	swi = tv->swi ? tv->swi : tc->swi;
+
+	tc->tf(swi, tc->signo, tv->type);
 }
 
 static void setup(void)
 {
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
+
 	signal(SIGUSR1, empty_handler);
 	signal(SIGALRM, empty_handler);
 	signal(SIGUSR2, SIG_IGN);
@@ -464,6 +511,7 @@ static void cleanup(void)
 static struct tst_test test = {
 	.test= run,
 	.tcnt = ARRAY_SIZE(tests),
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.cleanup = cleanup,
 	.forks_child = 1,
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 11/19] syscalls/mq_timed{send|receive}: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (9 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 10/19] syscalls/rt_sigtimedwait: Add support for time64 tests Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-24 14:51   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 12/19] syscalls/recvmmsg: " Viresh Kumar
                   ` (8 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing
mq_timed{send|receive}() syscall tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../mq_timedreceive/mq_timedreceive01.c       | 92 ++++++++++++------
 .../syscalls/mq_timedsend/mq_timedsend01.c    | 96 +++++++++++++------
 testcases/kernel/syscalls/utils/mq_timed.h    | 42 +++-----
 3 files changed, 141 insertions(+), 89 deletions(-)

diff --git a/testcases/kernel/syscalls/mq_timedreceive/mq_timedreceive01.c b/testcases/kernel/syscalls/mq_timedreceive/mq_timedreceive01.c
index 1be515ced671..876b54c81332 100644
--- a/testcases/kernel/syscalls/mq_timedreceive/mq_timedreceive01.c
+++ b/testcases/kernel/syscalls/mq_timedreceive/mq_timedreceive01.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) Crackerjack Project., 2007-2008, Hitachi, Ltd
  * Copyright (c) 2017 Petr Vorel <pvorel@suse.cz>
@@ -6,19 +7,6 @@
  * Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
  * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
  * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
- *
- * 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 would 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, see <http://www.gnu.org/licenses/>.
  */
 
 #include <errno.h>
@@ -28,7 +16,7 @@ static int fd, fd_root, fd_nonblock, fd_maxint = INT_MAX - 1, fd_invalid = -1;
 
 #include "mq_timed.h"
 
-static struct timespec ts;
+static struct tst_ts ts;
 
 static struct test_case tcase[] = {
 	{
@@ -95,21 +83,27 @@ static struct test_case tcase[] = {
 	{
 		.fd = &fd,
 		.len = 16,
-		.rq = &(struct timespec) {.tv_sec = -1, .tv_nsec = 0},
+		.tv_sec = -1,
+		.tv_nsec = 0,
+		.rq = &ts,
 		.ret = -1,
 		.err = EINVAL,
 	},
 	{
 		.fd = &fd,
 		.len = 16,
-		.rq = &(struct timespec) {.tv_sec = 0, .tv_nsec = -1},
+		.tv_sec = 0,
+		.tv_nsec = -1,
+		.rq = &ts,
 		.ret = -1,
 		.err = EINVAL,
 	},
 	{
 		.fd = &fd,
 		.len = 16,
-		.rq = &(struct timespec) {.tv_sec = 0, .tv_nsec = 1000000000},
+		.tv_sec = 0,
+		.tv_nsec = 1000000000,
+		.rq = &ts,
 		.ret = -1,
 		.err = EINVAL,
 	},
@@ -131,8 +125,40 @@ static struct test_case tcase[] = {
 	},
 };
 
+static struct test_variants {
+	int (*send)(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
+		    unsigned int msg_prio, void *abs_timeout);
+	ssize_t (*receive)(mqd_t mqdes, char *msg_ptr, size_t msg_len,
+			   unsigned int *msg_prio, void *abs_timeout);
+
+	int (*gettime)(clockid_t clk_id, void *ts);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+	{ .gettime = libc_clock_gettime, .send = libc_mq_timedsend, .receive = libc_mq_timedreceive, .type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"},
+
+#if (__NR_mq_timedsend != __LTP__NR_INVALID_SYSCALL)
+	{ .gettime = sys_clock_gettime, .send = sys_mq_timedsend, .receive = sys_mq_timedreceive, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_mq_timedsend_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .gettime = sys_clock_gettime64, .send = sys_mq_timedsend64, .receive = sys_mq_timedreceive64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static void setup(void)
+{
+	struct test_variants *tv = &variants[tst_variant];
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	ts.type = tv->type;
+
+	setup_common();
+}
+
 static void do_test(unsigned int i)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	const struct test_case *tc = &tcase[i];
 	unsigned int j;
 	unsigned int prio;
@@ -140,19 +166,26 @@ static void do_test(unsigned int i)
 	char rmsg[len];
 	pid_t pid = -1;
 
+	tst_ts_set_sec(&ts, tc->tv_sec);
+	tst_ts_set_nsec(&ts, tc->tv_nsec);
+
 	if (tc->signal)
-		pid = set_sig(tc->rq);
+		pid = set_sig(tc->rq, tv->gettime);
 
 	if (tc->timeout)
-		set_timeout(tc->rq);
+		set_timeout(tc->rq, tv->gettime);
 
-	if (tc->send)
-		send_msg(*tc->fd, tc->len, tc->prio);
+	if (tc->send) {
+		if (tv->send(*tc->fd, smsg, tc->len, tc->prio, NULL) < 0) {
+			tst_res(TFAIL | TTERRNO, "mq_timedsend() failed");
+			return;
+		}
+	}
 
 	if (tc->invalid_msg)
 		len -= 1;
 
-	TEST(mq_timedreceive(*tc->fd, rmsg, len, &prio, tc->rq));
+	TEST(tv->receive(*tc->fd, rmsg, len, &prio, tst_ts_get(tc->rq)));
 
 	if (pid > 0)
 		kill_pid(pid);
@@ -163,22 +196,22 @@ static void do_test(unsigned int i)
 	if (TST_RET < 0) {
 		if (tc->err != TST_ERR)
 			tst_res(TFAIL | TTERRNO,
-				"mq_timedreceive failed unexpectedly, expected %s",
+				"mq_timedreceive() failed unexpectedly, expected %s",
 				tst_strerrno(tc->err));
 		else
-			tst_res(TPASS | TTERRNO, "mq_timedreceive failed expectedly");
+			tst_res(TPASS | TTERRNO, "mq_timedreceive() failed expectedly");
 
 		return;
 	}
 
 	if (tc->len != TST_RET) {
-		tst_res(TFAIL, "mq_timedreceive wrong length %ld, expected %zu",
+		tst_res(TFAIL, "mq_timedreceive() wrong length %ld, expected %u",
 			TST_RET, tc->len);
 		return;
 	}
 
 	if (tc->prio != prio) {
-		tst_res(TFAIL, "mq_timedreceive wrong prio %d, expected %d",
+		tst_res(TFAIL, "mq_timedreceive() wrong prio %d, expected %d",
 			prio, tc->prio);
 		return;
 	}
@@ -186,20 +219,21 @@ static void do_test(unsigned int i)
 	for (j = 0; j < tc->len; j++) {
 		if (rmsg[j] != smsg[j]) {
 			tst_res(TFAIL,
-				"mq_timedreceive wrong data %d in %u, expected %d",
+				"mq_timedreceive() wrong data %d in %u, expected %d",
 				rmsg[j], i, smsg[j]);
 			return;
 		}
 	}
 
-	tst_res(TPASS, "mq_timedreceive returned %ld, priority %u, length: %zu",
+	tst_res(TPASS, "mq_timedreceive() returned %ld, priority %u, length: %zu",
 			TST_RET, prio, len);
 }
 
 static struct tst_test test = {
 	.tcnt = ARRAY_SIZE(tcase),
 	.test = do_test,
-	.setup = setup_common,
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
 	.cleanup = cleanup_common,
 	.forks_child = 1,
 };
diff --git a/testcases/kernel/syscalls/mq_timedsend/mq_timedsend01.c b/testcases/kernel/syscalls/mq_timedsend/mq_timedsend01.c
index 8f209d396040..4ff1da65c570 100644
--- a/testcases/kernel/syscalls/mq_timedsend/mq_timedsend01.c
+++ b/testcases/kernel/syscalls/mq_timedsend/mq_timedsend01.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) Crackerjack Project., 2007-2008, Hitachi, Ltd
  * Copyright (c) 2017 Petr Vorel <pvorel@suse.cz>
@@ -6,29 +7,17 @@
  * Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
  * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
  * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
- *
- * 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 would 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, see <http://www.gnu.org/licenses/>.
  */
 
 #include <errno.h>
 #include <limits.h>
 
 static int fd, fd_root, fd_nonblock, fd_maxint = INT_MAX - 1, fd_invalid = -1;
-static struct timespec ts;
 
 #include "mq_timed.h"
 
+static struct tst_ts ts;
+
 static struct test_case tcase[] = {
 	{
 		.fd = &fd,
@@ -95,7 +84,9 @@ static struct test_case tcase[] = {
 	{
 		.fd = &fd,
 		.len = 16,
-		.rq = &(struct timespec) {.tv_sec = -1, .tv_nsec = 0},
+		.tv_sec = -1,
+		.tv_nsec = 0,
+		.rq = &ts,
 		.send = 1,
 		.ret = -1,
 		.err = EINVAL,
@@ -103,7 +94,9 @@ static struct test_case tcase[] = {
 	{
 		.fd = &fd,
 		.len = 16,
-		.rq = &(struct timespec) {.tv_sec = 0, .tv_nsec = -1},
+		.tv_sec = 0,
+		.tv_nsec = -1,
+		.rq = &ts,
 		.send = 1,
 		.ret = -1,
 		.err = EINVAL,
@@ -111,7 +104,9 @@ static struct test_case tcase[] = {
 	{
 		.fd = &fd,
 		.len = 16,
-		.rq = &(struct timespec) {.tv_sec = 0, .tv_nsec = 1000000000},
+		.tv_sec = 0,
+		.tv_nsec = 1000000000,
+		.rq = &ts,
 		.send = 1,
 		.ret = -1,
 		.err = EINVAL,
@@ -136,8 +131,40 @@ static struct test_case tcase[] = {
 	},
 };
 
+static struct test_variants {
+	int (*send)(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
+		    unsigned int msg_prio, void *abs_timeout);
+	ssize_t (*receive)(mqd_t mqdes, char *msg_ptr, size_t msg_len,
+			   unsigned int *msg_prio, void *abs_timeout);
+
+	int (*gettime)(clockid_t clk_id, void *ts);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+	{ .gettime = libc_clock_gettime, .send = libc_mq_timedsend, .receive = libc_mq_timedreceive, .type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"},
+
+#if (__NR_mq_timedsend != __LTP__NR_INVALID_SYSCALL)
+	{ .gettime = sys_clock_gettime, .send = sys_mq_timedsend, .receive = sys_mq_timedreceive, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_mq_timedsend_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .gettime = sys_clock_gettime64, .send = sys_mq_timedsend64, .receive = sys_mq_timedreceive64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static void setup(void)
+{
+	struct test_variants *tv = &variants[tst_variant];
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	ts.type = tv->type;
+
+	setup_common();
+}
+
 static void do_test(unsigned int i)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	const struct test_case *tc = &tcase[i];
 	unsigned int j;
 	unsigned int prio;
@@ -145,18 +172,24 @@ static void do_test(unsigned int i)
 	char rmsg[len];
 	pid_t pid = -1;
 
+	tst_ts_set_sec(&ts, tc->tv_sec);
+	tst_ts_set_nsec(&ts, tc->tv_nsec);
+
 	if (tc->signal)
-		pid = set_sig(tc->rq);
+		pid = set_sig(tc->rq, tv->gettime);
 
 	if (tc->timeout)
-		set_timeout(tc->rq);
+		set_timeout(tc->rq, tv->gettime);
 
 	if (tc->send) {
 		for (j = 0; j < MSG_LENGTH; j++)
-			send_msg(*tc->fd, tc->len, tc->prio);
+			if (tv->send(*tc->fd, smsg, tc->len, tc->prio, NULL) < 0) {
+				tst_res(TFAIL | TTERRNO, "mq_timedsend() failed");
+				return;
+			}
 	}
 
-	TEST(mq_timedsend(*tc->fd, smsg, tc->len, tc->prio, tc->rq));
+	TEST(tv->send(*tc->fd, smsg, tc->len, tc->prio, tst_ts_get(tc->rq)));
 
 	if (pid > 0)
 		kill_pid(pid);
@@ -164,10 +197,10 @@ static void do_test(unsigned int i)
 	if (TST_RET < 0) {
 		if (tc->err != TST_ERR)
 			tst_res(TFAIL | TTERRNO,
-				"mq_timedsend failed unexpectedly, expected %s",
+				"mq_timedsend() failed unexpectedly, expected %s",
 				tst_strerrno(tc->err));
 		else
-			tst_res(TPASS | TTERRNO, "mq_timedreceive failed expectedly");
+			tst_res(TPASS | TTERRNO, "mq_timedreceive() failed expectedly");
 
 		if (*tc->fd == fd)
 			cleanup_queue(fd);
@@ -175,7 +208,7 @@ static void do_test(unsigned int i)
 		return;
 	}
 
-	TEST(mq_timedreceive(*tc->fd, rmsg, len, &prio, tc->rq));
+	TEST(tv->receive(*tc->fd, rmsg, len, &prio, tst_ts_get(tc->rq)));
 
 	if (*tc->fd == fd)
 		cleanup_queue(fd);
@@ -183,26 +216,26 @@ static void do_test(unsigned int i)
 	if (TST_RET < 0) {
 		if (tc->err != TST_ERR) {
 			tst_res(TFAIL | TTERRNO,
-				"mq_timedreceive failed unexpectedly, expected %s",
+				"mq_timedreceive() failed unexpectedly, expected %s",
 				tst_strerrno(tc->err));
 			return;
 		}
 
 		if (tc->ret >= 0) {
-			tst_res(TFAIL | TTERRNO, "mq_timedreceive returned %ld, expected %d",
+			tst_res(TFAIL | TTERRNO, "mq_timedreceive() returned %ld, expected %d",
 					TST_RET, tc->ret);
 			return;
 		}
 	}
 
 	if (tc->len != TST_RET) {
-		tst_res(TFAIL, "mq_timedreceive wrong length %ld, expected %d",
+		tst_res(TFAIL, "mq_timedreceive() wrong length %ld, expected %u",
 			TST_RET, tc->len);
 		return;
 	}
 
 	if (tc->prio != prio) {
-		tst_res(TFAIL, "mq_timedreceive wrong prio %d, expected %d",
+		tst_res(TFAIL, "mq_timedreceive() wrong prio %d, expected %d",
 			prio, tc->prio);
 		return;
 	}
@@ -210,20 +243,21 @@ static void do_test(unsigned int i)
 	for (j = 0; j < tc->len; j++) {
 		if (rmsg[j] != smsg[j]) {
 			tst_res(TFAIL,
-				"mq_timedreceive wrong data %d in %u, expected %d",
+				"mq_timedreceive() wrong data %d in %u, expected %d",
 				rmsg[j], i, smsg[j]);
 			return;
 		}
 	}
 
-	tst_res(TPASS, "mq_timedreceive returned %ld, priority %u, length: %zu",
+	tst_res(TPASS, "mq_timedreceive() returned %ld, priority %u, length: %zu",
 			TST_RET, prio, len);
 }
 
 static struct tst_test test = {
 	.tcnt = ARRAY_SIZE(tcase),
 	.test = do_test,
-	.setup = setup_common,
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
 	.cleanup = cleanup_common,
 	.forks_child = 1,
 };
diff --git a/testcases/kernel/syscalls/utils/mq_timed.h b/testcases/kernel/syscalls/utils/mq_timed.h
index a163ddcee3af..1d5515f9d629 100644
--- a/testcases/kernel/syscalls/utils/mq_timed.h
+++ b/testcases/kernel/syscalls/utils/mq_timed.h
@@ -1,30 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) 2017 Petr Vorel <pvorel@suse.cz>
- *
- * 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 would 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, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef MQ_TIMED_H
 #define MQ_TIMED_H
 
 #include "mq.h"
+#include "tst_timer.h"
 
 struct test_case {
 	int *fd;
 	unsigned int len;
 	unsigned int prio;
-	struct timespec *rq;
+	struct tst_ts *rq;
+	long tv_sec;
+	long tv_nsec;
 	int invalid_msg;
 	int send;
 	int signal;
@@ -33,27 +24,20 @@ struct test_case {
 	int err;
 };
 
-static pid_t set_sig(struct timespec *ts)
+static pid_t set_sig(struct tst_ts *ts,
+		     int (*gettime)(clockid_t clk_id, void *ts))
 {
-	clock_gettime(CLOCK_REALTIME, ts);
-	ts->tv_sec += 3;
+	gettime(CLOCK_REALTIME, tst_ts_get(ts));
+	*ts = tst_ts_add_us(*ts, 3000000);
 
 	return create_sig_proc(SIGINT, 40, 200000);
 }
 
-static void set_timeout(struct timespec *ts)
+static void set_timeout(struct tst_ts *ts,
+			int (*gettime)(clockid_t clk_id, void *ts))
 {
-	clock_gettime(CLOCK_REALTIME, ts);
-	ts->tv_nsec += 50000000;
-	ts->tv_sec += ts->tv_nsec / 1000000000;
-	ts->tv_nsec %= 1000000000;
-}
-
-static void send_msg(int fd, int len, int prio)
-{
-	if (mq_timedsend(fd, smsg, len, prio,
-		&((struct timespec){0})) < 0)
-		tst_brk(TBROK | TERRNO, "mq_timedsend failed");
+	gettime(CLOCK_REALTIME, tst_ts_get(ts));
+	*ts = tst_ts_add_us(*ts, 50000);
 }
 
 static void kill_pid(pid_t pid)
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 12/19] syscalls/recvmmsg: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (10 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 11/19] syscalls/mq_timed{send|receive}: " Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-24 15:13   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 13/19] syscalls/ppoll: " Viresh Kumar
                   ` (7 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing recvmmsg() syscall
tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../kernel/syscalls/sendmmsg/sendmmsg01.c     | 40 ++++++++++----
 .../kernel/syscalls/sendmmsg/sendmmsg_var.h   | 55 ++++++++-----------
 2 files changed, 53 insertions(+), 42 deletions(-)

diff --git a/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c b/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c
index 37084102ee09..016bbc6813c4 100644
--- a/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c
+++ b/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c
@@ -14,7 +14,6 @@
 #include "tst_test.h"
 #include "lapi/socket.h"
 #include "tst_safe_macros.h"
-
 #include "sendmmsg_var.h"
 
 #define BUFSIZE 16
@@ -25,27 +24,48 @@ static int receive_sockfd;
 static struct mmsghdr *snd_msg, *rcv_msg;
 static struct iovec *snd1, *snd2, *rcv1, *rcv2;
 
+static struct test_variants {
+	int (*receive)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
+		       unsigned int flags, void *timeout);
+	int (*send)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
+		    unsigned int flags);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+	{ .receive = libc_recvmmsg, .send = libc_sendmmsg, .type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"},
+
+#if (__NR_recvmmsg != __LTP__NR_INVALID_SYSCALL)
+	{ .receive = sys_recvmmsg, .send = sys_sendmmsg, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_recvmmsg_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .receive = sys_recvmmsg64, .send = sys_sendmmsg, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
 static void run(void)
 {
-	struct timespec timeout;
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_ts timeout;
 	int retval;
 
-	retval = do_sendmmsg(send_sockfd, snd_msg, VLEN, 0);
+	retval = tv->send(send_sockfd, snd_msg, VLEN, 0);
 	if (retval < 0 || snd_msg[0].msg_len != 6 || snd_msg[1].msg_len != 6) {
-		tst_res(TFAIL|TTERRNO, "sendmmsg failed");
+		tst_res(TFAIL|TTERRNO, "sendmmsg() failed");
 		return;
 	}
 
 	memset(rcv1->iov_base, 0, rcv1->iov_len);
 	memset(rcv2->iov_base, 0, rcv2->iov_len);
 
-	timeout.tv_sec = 1;
-	timeout.tv_nsec = 0;
+	timeout.type = tv->type;
+	tst_ts_set_sec(&timeout, 1);
+	tst_ts_set_nsec(&timeout, 0);
 
-	retval = do_recvmmsg(receive_sockfd, rcv_msg, VLEN, 0, &timeout);
+	retval = tv->receive(receive_sockfd, rcv_msg, VLEN, 0, tst_ts_get(&timeout));
 
 	if (retval == -1) {
-		tst_res(TFAIL | TTERRNO, "recvmmsg failed");
+		tst_res(TFAIL | TTERRNO, "recvmmsg() failed");
 		return;
 	}
 	if (retval != 2) {
@@ -96,7 +116,7 @@ static void setup(void)
 	rcv_msg[1].msg_hdr.msg_iov = rcv2;
 	rcv_msg[1].msg_hdr.msg_iovlen = 1;
 
-	test_info();
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
 }
 
 static void cleanup(void)
@@ -111,7 +131,7 @@ static struct tst_test test = {
 	.test_all = run,
 	.setup = setup,
 	.cleanup = cleanup,
-	.test_variants = TEST_VARIANTS,
+	.test_variants = ARRAY_SIZE(variants),
 	.bufs = (struct tst_buffers []) {
 		{&snd1, .iov_sizes = (int[]){3, 3, -1}},
 		{&snd2, .iov_sizes = (int[]){6, -1}},
diff --git a/testcases/kernel/syscalls/sendmmsg/sendmmsg_var.h b/testcases/kernel/syscalls/sendmmsg/sendmmsg_var.h
index f00cf056a747..a142b17f9718 100644
--- a/testcases/kernel/syscalls/sendmmsg/sendmmsg_var.h
+++ b/testcases/kernel/syscalls/sendmmsg/sendmmsg_var.h
@@ -6,55 +6,46 @@
 #ifndef SENDMMSG_VAR__
 #define SENDMMSG_VAR__
 
+#include "tst_timer.h"
 #include "lapi/syscalls.h"
 
-static int do_sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
-		       int flags)
+static inline int libc_sendmmsg(int sockfd, struct mmsghdr *msgvec,
+				unsigned int vlen, unsigned int flags)
 {
-	switch (tst_variant) {
-	case 0:
-		return tst_syscall(__NR_sendmmsg, sockfd, msgvec, vlen, flags);
-	case 1:
 #ifdef HAVE_SENDMMSG
-		return sendmmsg(sockfd, msgvec, vlen, flags);
+	return sendmmsg(sockfd, msgvec, vlen, flags);
 #else
-		tst_brk(TCONF, "libc sendmmsg not present");
+	tst_brk(TCONF, "libc sendmmsg not present");
 #endif
-	}
+}
 
-	return -1;
+static inline int sys_sendmmsg(int sockfd, struct mmsghdr *msgvec,
+			       unsigned int vlen, unsigned int flags)
+{
+	return tst_syscall(__NR_sendmmsg, sockfd, msgvec, vlen, flags);
 }
 
-static int do_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
-		       int flags, struct timespec *timeout)
+static inline int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec,
+			unsigned int vlen, unsigned int flags, void *timeout)
 {
-	switch (tst_variant) {
-	case 0:
-		return tst_syscall(__NR_recvmmsg, sockfd, msgvec, vlen, flags,
-				   timeout);
-	case 1:
 #ifdef HAVE_RECVMMSG
-		return recvmmsg(sockfd, msgvec, vlen, flags, timeout);
+	return recvmmsg(sockfd, msgvec, vlen, flags, timeout);
 #else
-		tst_brk(TCONF, "libc recvmmsg not present");
+	tst_brk(TCONF, "libc recvmmsg not present");
 #endif
-	}
-
-	return -1;
 }
 
-static void test_info(void)
+static inline int sys_recvmmsg(int sockfd, struct mmsghdr *msgvec,
+			unsigned int vlen, unsigned int flags, void *timeout)
 {
-	switch (tst_variant) {
-	case 0:
-		tst_res(TINFO, "Testing direct sendmmsg and recvmmsg syscalls");
-		break;
-	case 1:
-		tst_res(TINFO, "Testing libc sendmmsg and recvmmsg syscalls");
-		break;
-	}
+	return tst_syscall(__NR_recvmmsg, sockfd, msgvec, vlen, flags, timeout);
 }
 
-#define TEST_VARIANTS 2
+static inline int sys_recvmmsg64(int sockfd, struct mmsghdr *msgvec,
+			unsigned int vlen, unsigned int flags, void *timeout)
+{
+	return tst_syscall(__NR_recvmmsg_time64, sockfd, msgvec, vlen, flags,
+			   timeout);
+}
 
 #endif /* SENDMMSG_VAR__ */
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 13/19] syscalls/ppoll: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (11 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 12/19] syscalls/recvmmsg: " Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-27  9:17   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 14/19] syscalls/select6: " Viresh Kumar
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing ppoll() syscall
tests.

Note that the O_EXCL flag is removed from SAFE_OPEN() calls as it made
the tests failed when run for the second variant as the file existed.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 testcases/kernel/syscalls/ppoll/ppoll01.c | 71 ++++++++++++++++++-----
 1 file changed, 55 insertions(+), 16 deletions(-)

diff --git a/testcases/kernel/syscalls/ppoll/ppoll01.c b/testcases/kernel/syscalls/ppoll/ppoll01.c
index 2fadd0653948..a217254022d4 100644
--- a/testcases/kernel/syscalls/ppoll/ppoll01.c
+++ b/testcases/kernel/syscalls/ppoll/ppoll01.c
@@ -21,6 +21,7 @@
 #include "ltp_signal.h"
 #include "tst_sig_proc.h"
 #include "tst_test.h"
+#include "tst_timer.h"
 
 /* Older versions of glibc don't publish this constant's value. */
 #ifndef POLLRDHUP
@@ -38,7 +39,7 @@ struct test_case {
 	unsigned int nfds;	   /* nfds ppoll parameter */
 	sigset_t *sigmask;	   /* sigmask ppoll parameter */
 	sigset_t *sigmask_cur;	   /* sigmask set for current process */
-	struct timespec *ts;	   /* ts ppoll parameter */
+	struct tst_ts *ts;	   /* ts ppoll parameter */
 	struct pollfd *fds;	   /* fds ppoll parameter */
 	int sigint_count;	   /* if > 0, spawn process to send SIGINT */
 				   /* 'count' times to current process */
@@ -60,14 +61,7 @@ static int fd1 = -1;
 static sigset_t sigmask_empty, sigmask_sigint;
 static struct pollfd fds_good[1], fds_already_closed[1];
 
-static struct timespec ts_short = {
-	.tv_sec = 0,
-	.tv_nsec = 200000000,
-};
-static struct timespec ts_long = {
-	.tv_sec = 2,
-	.tv_nsec = 0,
-};
+static struct tst_ts ts_short, ts_long;
 
 /* Test cases
  *
@@ -160,14 +154,53 @@ static struct test_case tcase[] = {
 	},
 };
 
+static inline int libc_ppoll(struct pollfd *fds, nfds_t nfds, void *tmo_p,
+			     const sigset_t *sigmask, size_t sigsetsize)
+{
+	return ppoll(fds, nfds, tmo_p, sigmask);
+}
+
+static inline int sys_ppoll(struct pollfd *fds, nfds_t nfds, void *tmo_p,
+			    const sigset_t *sigmask, size_t sigsetsize)
+{
+	return tst_syscall(__NR_ppoll, fds, nfds, tmo_p, sigmask, sigsetsize);
+}
+
+static inline int sys_ppoll_time64(struct pollfd *fds, nfds_t nfds, void *tmo_p,
+				   const sigset_t *sigmask, size_t sigsetsize)
+{
+	return tst_syscall(__NR_ppoll_time64, fds, nfds, tmo_p, sigmask,
+			   sigsetsize);
+}
+
+static struct test_variants {
+	int (*ppoll)(struct pollfd *fds, nfds_t nfds, void *tmo_p,
+		     const sigset_t *sigmask, size_t sigsetsize);
+
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+	{ .ppoll = libc_ppoll, .type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"},
+
+#if (__NR_ppoll != __LTP__NR_INVALID_SYSCALL)
+	{ .ppoll = sys_ppoll, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_ppoll_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .ppoll = sys_ppoll_time64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
 static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
 {
 }
 
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	int fd2;
 
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
 	SAFE_SIGNAL(SIGINT, sighandler);
 
 	if (sigemptyset(&sigmask_empty) == -1)
@@ -177,18 +210,22 @@ static void setup(void)
 	if (sigaddset(&sigmask_sigint, SIGINT) == -1)
 		tst_brk(TBROK | TERRNO, "sigaddset");
 
-	fd1 = SAFE_OPEN("testfile1", O_CREAT | O_EXCL | O_RDWR,
-		S_IRUSR | S_IWUSR);
+	fd1 = SAFE_OPEN("testfile1", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
 	fds_good[0].fd = fd1;
 	fds_good[0].events = POLLIN | POLLPRI | POLLOUT | POLLRDHUP;
 	fds_good[0].revents = 0;
 
-	fd2 = SAFE_OPEN("testfile2", O_CREAT | O_EXCL | O_RDWR,
-		S_IRUSR | S_IWUSR);
+	fd2 = SAFE_OPEN("testfile2", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
 	fds_already_closed[0].fd = fd2;
 	fds_already_closed[0].events = POLLIN | POLLPRI | POLLOUT | POLLRDHUP;
 	fds_already_closed[0].revents = 0;
 	SAFE_CLOSE(fd2);
+
+	ts_short.type = ts_long.type = tv->type;
+	tst_ts_set_sec(&ts_short, 0);
+	tst_ts_set_nsec(&ts_short, 200000000);
+	tst_ts_set_sec(&ts_long, 2);
+	tst_ts_set_nsec(&ts_long, 0);
 }
 
 static void cleanup(void)
@@ -199,10 +236,11 @@ static void cleanup(void)
 
 static void do_test(unsigned int i)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	pid_t pid = 0;
 	int sys_ret, sys_errno = 0, dummy;
 	struct test_case *tc = &tcase[i];
-	struct timespec ts, *tsp = NULL;
+	struct tst_ts ts, *tsp = NULL;
 
 	if (tc->ts) {
 		memcpy(&ts, tc->ts, sizeof(ts));
@@ -223,8 +261,8 @@ static void do_test(unsigned int i)
 
 	/* test */
 	errno = 0;
-	sys_ret = tst_syscall(__NR_ppoll, tc->fds, tc->nfds, tsp,
-		tc->sigmask, SIGSETSIZE);
+	sys_ret = tv->ppoll(tc->fds, tc->nfds, tst_ts_get(tsp), tc->sigmask,
+			    SIGSETSIZE);
 	sys_errno = errno;
 
 	/* cleanup */
@@ -261,6 +299,7 @@ static void do_test(unsigned int i)
 static struct tst_test test = {
 	.tcnt = ARRAY_SIZE(tcase),
 	.test = do_test,
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.cleanup = cleanup,
 	.forks_child = 1,
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 14/19] syscalls/select6: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (12 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 13/19] syscalls/ppoll: " Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-27  9:40   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 15/19] syscalls/semop: Migrate to new test framework Viresh Kumar
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing select6() syscall
tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 testcases/kernel/syscalls/select/select_var.h | 25 ++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/testcases/kernel/syscalls/select/select_var.h b/testcases/kernel/syscalls/select/select_var.h
index b19a1d1bf085..2c7604807cf6 100644
--- a/testcases/kernel/syscalls/select/select_var.h
+++ b/testcases/kernel/syscalls/select/select_var.h
@@ -6,6 +6,7 @@
 #define SELECT_VAR__
 
 #include "lapi/syscalls.h"
+#include "tst_timer.h"
 
 struct compat_sel_arg_struct {
 	long _n;
@@ -38,7 +39,7 @@ static int do_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *except
 	}
 	case 2: {
 		int ret;
-		struct timespec ts = {
+		struct __kernel_old_timespec ts = {
 			.tv_sec = timeout->tv_sec,
 			.tv_nsec = timeout->tv_usec * 1000,
 		};
@@ -47,7 +48,22 @@ static int do_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *except
 		timeout->tv_usec = ts.tv_nsec / 1000;
 		return ret;
 	}
-	case 3:
+	case 3: {
+		int ret = 0;
+#if (__NR_clock_settime64 != __LTP__NR_INVALID_SYSCALL)
+		struct __kernel_timespec ts = {
+			.tv_sec = timeout->tv_sec,
+			.tv_nsec = timeout->tv_usec * 1000,
+		};
+		ret = tst_syscall(__NR_pselect6_time64, nfds, readfds, writefds, exceptfds, &ts, NULL);
+		timeout->tv_sec = ts.tv_sec;
+		timeout->tv_usec = ts.tv_nsec / 1000;
+#else
+		tst_brk(TCONF, "__NR_pselect6 time64 variant not supported");
+#endif
+		return ret;
+	}
+	case 4:
 #ifdef __NR__newselect
 		return tst_syscall(__NR__newselect, nfds, readfds, writefds, exceptfds, timeout);
 #else
@@ -72,11 +88,14 @@ static void select_info(void)
 		tst_res(TINFO, "Testing SYS_pselect6 syscall");
 	break;
 	case 3:
+		tst_res(TINFO, "Testing SYS_pselect6 time64 syscall");
+	break;
+	case 4:
 		tst_res(TINFO, "Testing SYS__newselect syscall");
 	break;
 	}
 }
 
-#define TEST_VARIANTS 4
+#define TEST_VARIANTS 5
 
 #endif /* SELECT_VAR__ */
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 15/19] syscalls/semop: Migrate to new test framework
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (13 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 14/19] syscalls/select6: " Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-27 13:46   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 16/19] syscalls/semtimedop: Add support for semtimedop and its time64 version Viresh Kumar
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This migrates the semop tests to the new test framework.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 testcases/kernel/syscalls/ipc/semop/Makefile  |   4 +-
 testcases/kernel/syscalls/ipc/semop/semop01.c | 140 ++++----
 testcases/kernel/syscalls/ipc/semop/semop02.c | 145 +++------
 testcases/kernel/syscalls/ipc/semop/semop03.c | 150 +++------
 testcases/kernel/syscalls/ipc/semop/semop04.c | 165 ++++------
 testcases/kernel/syscalls/ipc/semop/semop05.c | 303 ++++++++----------
 6 files changed, 348 insertions(+), 559 deletions(-)

diff --git a/testcases/kernel/syscalls/ipc/semop/Makefile b/testcases/kernel/syscalls/ipc/semop/Makefile
index f62cd1f481d9..a11cbcf2e699 100644
--- a/testcases/kernel/syscalls/ipc/semop/Makefile
+++ b/testcases/kernel/syscalls/ipc/semop/Makefile
@@ -3,10 +3,10 @@
 
 top_srcdir              ?= ../../../../..
 
-LTPLIBS = ltpipc
+LTPLIBS = ltpnewipc
 
 include $(top_srcdir)/include/mk/testcases.mk
 
-LDLIBS  += -lltpipc
+LDLIBS  += -lltpnewipc
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/ipc/semop/semop01.c b/testcases/kernel/syscalls/ipc/semop/semop01.c
index ea05c53eb919..bcb45fa69320 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop01.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop01.c
@@ -1,21 +1,5 @@
-/*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   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
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) International Business Machines  Corp., 2001 */
 
 /*
  * NAME
@@ -52,92 +36,73 @@
  *	none
  */
 
-#include "ipcsem.h"
+#include <stdlib.h>
+#include <sys/sem.h>
+#include "tst_test.h"
+#include "libnewipc.h"
+#include "lapi/semun.h"
 
 #define NSEMS	4		/* the number of primitive semaphores to test */
 
-char *TCID = "semop01";
-int TST_TOTAL = 1;
-
-int sem_id_1 = -1;		/* a semaphore set with read & alter permissions */
+static int sem_id = -1;		/* a semaphore set with read & alter permissions */
+static key_t semkey;
 
-union semun get_arr;
-struct sembuf sops[PSEMS];
+static union semun get_arr;
+static struct sembuf sops[PSEMS];
 
-int main(int ac, char **av)
+static void run(void)
 {
-	int lc;
-	int i;
+	union semun arr = { .val = 0 };
 	int fail = 0;
+	int i;
 
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-
-		TEST(semop(sem_id_1, sops, NSEMS));
-
-		if (TEST_RETURN == -1) {
-			tst_resm(TFAIL, "%s call failed - errno = %d : %s",
-				 TCID, TEST_ERRNO, strerror(TEST_ERRNO));
-		} else {
-			/* get the values and make sure they */
-			/* are the same as what was set      */
-			if (semctl(sem_id_1, 0, GETALL, get_arr) == -1) {
-				tst_brkm(TBROK, cleanup,
-					 "semctl() failed in functional test");
-			}
-
-			for (i = 0; i < NSEMS; i++) {
-				if (get_arr.array[i] != i * i) {
-					fail = 1;
-				}
-			}
-			if (fail)
-				tst_resm(TFAIL,
-					 "semaphore values are wrong");
-			else
-				tst_resm(TPASS,
-					 "semaphore values are correct");
-		}
+	TEST(semop(sem_id, sops, NSEMS));
 
+	if (TST_RET == -1) {
+		tst_res(TFAIL | TTERRNO, "semop() failed");
+	} else {
 		/*
-		 * clean up things in case we are looping
+		 * Get the values and make sure they are the same as what was
+		 * set
 		 */
-		union semun set_arr;
-		set_arr.val = 0;
+		if (semctl(sem_id, 0, GETALL, get_arr) == -1) {
+			tst_brk(TBROK | TERRNO, "semctl() failed in functional test");
+		}
+
 		for (i = 0; i < NSEMS; i++) {
-			if (semctl(sem_id_1, i, SETVAL, set_arr) == -1) {
-				tst_brkm(TBROK, cleanup, "semctl failed");
+			if (get_arr.array[i] != i * i) {
+				fail = 1;
 			}
 		}
+		if (fail)
+			tst_res(TFAIL | TERRNO, "semaphore values are wrong");
+		else
+			tst_res(TPASS, "semaphore values are correct");
 	}
 
-	cleanup();
-	tst_exit();
+	/*
+	 * clean up things in case we are looping
+	 */
+	for (i = 0; i < NSEMS; i++) {
+		if (semctl(sem_id, i, SETVAL, arr) == -1) {
+			tst_brk(TBROK | TERRNO, "semctl failed");
+		}
+	}
 }
 
-void setup(void)
+static void setup(void)
 {
 	int i;
 
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	tst_tmpdir();
-
 	get_arr.array = malloc(sizeof(unsigned short int) * PSEMS);
 	if (get_arr.array == NULL)
-		tst_brkm(TBROK, cleanup, "malloc failed");
+		tst_brk(TBROK, "malloc failed");
 
-	semkey = getipckey();
+	semkey = GETIPCKEY();
 
-	sem_id_1 = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA);
-	if (sem_id_1 == -1)
-		tst_brkm(TBROK, cleanup, "couldn't create semaphore in setup");
+	sem_id = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA);
+	if (sem_id == -1)
+		tst_brk(TBROK | TERRNO, "couldn't create semaphore in setup");
 
 	for (i = 0; i < NSEMS; i++) {
 		sops[i].sem_num = i;
@@ -146,11 +111,20 @@ void setup(void)
 	}
 }
 
-void cleanup(void)
+static void cleanup(void)
 {
-	rm_sema(sem_id_1);
+	union semun arr;
 
+	if (sem_id != -1) {
+		if (semctl(sem_id, 0, IPC_RMID, arr) == -1)
+			tst_res(TINFO, "WARNING: semaphore deletion failed.");
+	}
 	free(get_arr.array);
-
-	tst_rmdir();
 }
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/ipc/semop/semop02.c b/testcases/kernel/syscalls/ipc/semop/semop02.c
index f067229b1cf5..f24d284776a4 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop02.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop02.c
@@ -1,21 +1,5 @@
-/*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   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
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) International Business Machines  Corp., 2001 */
 
 /*
  * DESCRIPTION
@@ -31,30 +15,27 @@
 
 #define _GNU_SOURCE
 #include <pwd.h>
-#include "test.h"
-#include "safe_macros.h"
-#include "ipcsem.h"
-
-char *TCID = "semop02";
-
-static void semop_verify(int i);
-int sem_id_1 = -1;	/* a semaphore set with read & alter permissions */
-int sem_id_2 = -1;	/* a semaphore set without read & alter permissions */
-int bad_id = -1;
-
-struct sembuf s_buf[PSEMS];
-
-int badbuf = -1;
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include "tst_test.h"
+#include "libnewipc.h"
+#include "lapi/semun.h"
+
+static int sem_id_1 = -1;	/* a semaphore set with read & alter permissions */
+static int sem_id_2 = -1;	/* a semaphore set without read & alter permissions */
+static int bad_id = -1;
+static key_t semkey;
+static struct sembuf s_buf[PSEMS];
 
 #define NSOPS	5		/* a resonable number of operations */
 #define	BIGOPS	1024		/* a value that is too large for the number */
 				/* of semop operations that are permitted   */
-struct test_case_t {
+static struct test_case_t {
 	int *semid;
 	struct sembuf *t_sbuf;
 	unsigned t_ops;
 	int error;
-} TC[] = {
+} tc[] = {
 	{&sem_id_1, (struct sembuf *)&s_buf, BIGOPS, E2BIG},
 	{&sem_id_2, (struct sembuf *)&s_buf, NSOPS, EACCES},
 	{&sem_id_1, (struct sembuf *)-1, NSOPS, EFAULT},
@@ -63,29 +44,7 @@ struct test_case_t {
 	{&sem_id_1, (struct sembuf *)&s_buf, 1, ERANGE}
 };
 
-int TST_TOTAL = ARRAY_SIZE(TC);
-
-int main(int ac, char **av)
-{
-	int lc;
-	int i;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-
-		for (i = 0; i < TST_TOTAL; i++)
-			semop_verify(i);
-	}
-
-	cleanup();
-	tst_exit();
-}
-
-void setup(void)
+static void setup(void)
 {
 	char nobody_uid[] = "nobody";
 	struct passwd *ltpuser;
@@ -93,71 +52,73 @@ void setup(void)
 	struct seminfo ipc_buf;
 	union semun arr;
 
-	tst_require_root();
-
-	ltpuser = SAFE_GETPWNAM(NULL, nobody_uid);
-	SAFE_SETUID(NULL, ltpuser->pw_uid);
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	tst_tmpdir();
+	ltpuser = SAFE_GETPWNAM(nobody_uid);
+	SAFE_SETUID(ltpuser->pw_uid);
 
 	/* get an IPC resource key */
-	semkey = getipckey();
+	semkey = GETIPCKEY();
 
 	/* create a semaphore set with read and alter permissions */
 	sem_id_1 = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA);
-	if (sem_id_1 == -1) {
-		tst_brkm(TBROK | TERRNO, cleanup,
-			 "couldn't create semaphore in setup");
-	}
+	if (sem_id_1 == -1)
+		tst_brk(TBROK | TERRNO, "couldn't create semaphore in setup");
 
 	/* Get an new IPC resource key. */
-	semkey2 = getipckey();
+	semkey2 = GETIPCKEY();
 
 	/* create a semaphore set without read and alter permissions */
 	sem_id_2 = semget(semkey2, PSEMS, IPC_CREAT | IPC_EXCL);
-	if (sem_id_2 == -1) {
-		tst_brkm(TBROK | TERRNO, cleanup,
-			 "couldn't create semaphore in setup");
-	}
+	if (sem_id_2 == -1)
+		tst_brk(TBROK | TERRNO, "couldn't create semaphore in setup");
 
 	arr.__buf = &ipc_buf;
 	if (semctl(sem_id_1, 0, IPC_INFO, arr) == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "semctl() IPC_INFO failed");
+		tst_brk(TBROK | TERRNO, "semctl() IPC_INFO failed");
 
 	/* for ERANGE errno test */
 	arr.val = 1;
 	s_buf[0].sem_op = ipc_buf.semvmx;
 	if (semctl(sem_id_1, 0, SETVAL, arr) == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "semctl() SETVAL failed");
+		tst_brk(TBROK | TERRNO, "semctl() SETVAL failed");
 }
 
-static void semop_verify(int i)
+static void run(unsigned int i)
 {
-	TEST(semop(*(TC[i].semid), TC[i].t_sbuf, TC[i].t_ops));
+	TEST(semop(*(tc[i].semid), tc[i].t_sbuf, tc[i].t_ops));
 
-	if (TEST_RETURN != -1) {
-		tst_resm(TFAIL, "call succeeded unexpectedly");
+	if (TST_RET != -1) {
+		tst_res(TFAIL | TTERRNO, "call succeeded unexpectedly");
 		return;
 	}
 
-	if (TEST_ERRNO == TC[i].error) {
-		tst_resm(TPASS | TTERRNO, "semop failed as expected");
+	if (TST_ERR == tc[i].error) {
+		tst_res(TPASS | TTERRNO, "semop failed as expected");
 	} else {
-		tst_resm(TFAIL | TTERRNO,
+		tst_res(TFAIL | TTERRNO,
 			 "semop failed unexpectedly; expected: "
-			 "%d - %s", TC[i].error, strerror(TC[i].error));
+			 "%d - %s", tc[i].error, strerror(tc[i].error));
 	}
 }
 
-void cleanup(void)
+static void cleanup(void)
 {
-	/* if they exist, remove the semaphore resources */
-	rm_sema(sem_id_1);
-	rm_sema(sem_id_2);
+	union semun arr;
 
-	tst_rmdir();
+	if (sem_id_1 != -1) {
+		if (semctl(sem_id_1, 0, IPC_RMID, arr) == -1)
+			tst_res(TINFO, "WARNING: semaphore deletion failed.");
+	}
+	if (sem_id_2 != -1) {
+		if (semctl(sem_id_2, 0, IPC_RMID, arr) == -1)
+			tst_res(TINFO, "WARNING: semaphore deletion failed.");
+	}
 }
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tc),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/ipc/semop/semop03.c b/testcases/kernel/syscalls/ipc/semop/semop03.c
index 9c1c58202ad3..4f5f78eb6d8d 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop03.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop03.c
@@ -1,21 +1,5 @@
-/*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   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
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) International Business Machines  Corp., 2001 */
 
 /*
  * NAME
@@ -50,109 +34,75 @@
  *	none
  */
 
-#include "ipcsem.h"
-
-char *TCID = "semop03";
-int TST_TOTAL = 2;
+#include <sys/sem.h>
+#include "tst_test.h"
+#include "libnewipc.h"
+#include "lapi/semun.h"
 
-int sem_id_1 = -1;
+static key_t semkey;
+static int sem_id = -1;
+static struct sembuf s_buf;
 
-struct sembuf s_buf;
+static int tc[] = { -1, PSEMS + 1 }; /* negative and too many "primitive" semas */
 
-int TC[] = { -1, PSEMS + 1 };	/* negative and too many "primitive" semas */
-
-int main(int ac, char **av)
+static void run(unsigned int i)
 {
-	int lc;
-	int i;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();		/* global setup */
-
 	/* initialize two fields in the sembuf structure here */
 	s_buf.sem_op = 1;	/* add this value to struct sem.semval */
 	s_buf.sem_flg = SEM_UNDO;	/* undo when process exits */
 
-	/* The following loop checks looping state if -i option given */
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		/* reset tst_count in case we are looping */
-		tst_count = 0;
-
-		for (i = 0; i < TST_TOTAL; i++) {
-
-			/* initialize the last field in the sembuf */
-			/* structure to the test dependent value   */
-			s_buf.sem_num = TC[i];
-
-			/*
-			 * use the TEST macro to make the call
-			 */
+	/*
+	 * initialize the last field in the sembuf structure to the test
+	 * dependent value.
+	 */
+	s_buf.sem_num = tc[i];
 
-			TEST(semop(sem_id_1, &s_buf, 1));
+	/*
+	 * use the TEST macro to make the call
+	 */
 
-			if (TEST_RETURN != -1) {
-				tst_resm(TFAIL, "call succeeded unexpectedly");
-				continue;
-			}
+	TEST(semop(sem_id, &s_buf, 1));
 
-			switch (TEST_ERRNO) {
-			case EFBIG:
-				tst_resm(TPASS, "expected failure - errno = "
-					 "%d : %s", TEST_ERRNO,
-					 strerror(TEST_ERRNO));
-				break;
-			default:
-				tst_resm(TFAIL, "unexpected error - "
-					 "%d : %s", TEST_ERRNO,
-					 strerror(TEST_ERRNO));
-				break;
-			}
-		}
+	if (TST_RET != -1) {
+		tst_res(TFAIL | TTERRNO, "call succeeded unexpectedly");
+		return;
 	}
 
-	cleanup();
-
-	tst_exit();
+	switch (TST_ERR) {
+	case EFBIG:
+		tst_res(TPASS | TTERRNO, "expected failure");
+		break;
+	default:
+		tst_res(TFAIL | TTERRNO, "unexpected failure");
+		break;
+	}
 }
 
-/*
- * setup() - performs all the ONE TIME setup for this test.
- */
-void setup(void)
+static void setup(void)
 {
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	/*
-	 * Create a temporary directory and cd into it.
-	 * This helps to ensure that a unique msgkey is created.
-	 * See libs/libltpipc/libipc.c for more information.
-	 */
-	tst_tmpdir();
-
 	/* get an IPC resource key */
-	semkey = getipckey();
+	semkey = GETIPCKEY();
 
 	/* create a semaphore with read and alter permissions */
-	if ((sem_id_1 =
-	     semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)) == -1) {
-		tst_brkm(TBROK, cleanup, "couldn't create semaphore in setup");
-	}
+	if ((sem_id = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)) ==
+	    -1)
+		tst_brk(TBROK | TERRNO, "couldn't create semaphore in setup");
 }
 
-/*
- * cleanup() - performs all the ONE TIME cleanup for this test@completion
- * 	       or premature exit.
- */
-void cleanup(void)
+static void cleanup(void)
 {
-	/* if it exists, remove the semaphore resource */
-	rm_sema(sem_id_1);
-
-	tst_rmdir();
+	union semun arr;
 
+	if (sem_id != -1) {
+		if (semctl(sem_id, 0, IPC_RMID, arr) == -1)
+			tst_res(TINFO, "WARNING: semaphore deletion failed.");
+	}
 }
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tc),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/ipc/semop/semop04.c b/testcases/kernel/syscalls/ipc/semop/semop04.c
index c1fa2eba7584..0faf00a3585f 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop04.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop04.c
@@ -1,21 +1,5 @@
-/*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   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
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) International Business Machines  Corp., 2001 */
 
 /*
  * NAME
@@ -50,22 +34,24 @@
  *	none
  */
 
-#include "ipcsem.h"
-
-char *TCID = "semop04";
-int TST_TOTAL = 2;
+#include <sys/sem.h>
+#include "tst_test.h"
+#include "libnewipc.h"
+#include "lapi/semun.h"
 
-int sem_id_1 = -1;
+static int sem_id = -1;
+static int val; /* value for SETVAL */
 
-struct sembuf s_buf;
+static key_t semkey;
+static struct sembuf s_buf;
 
-struct test_case_t {
+static struct test_case_t {
 	union semun get_arr;
 	short op;
 	short flg;
 	short num;
 	int error;
-} TC[] = {
+} tc[] = {
 	/* EAGAIN sem_op = 0 */
 	{ {
 	1}, 0, IPC_NOWAIT, 2, EAGAIN},
@@ -74,104 +60,61 @@ struct test_case_t {
 	0}, -1, IPC_NOWAIT, 2, EAGAIN}
 };
 
-int main(int ac, char **av)
+static void run(unsigned int i)
 {
-	int lc;
-	int val;		/* value for SETVAL */
-
-	int i;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();		/* global setup */
-
-	/* The following loop checks looping state if -i option given */
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		/* reset tst_count in case we are looping */
-		tst_count = 0;
-
-		val = 1;
-		for (i = 0; i < TST_TOTAL; i++) {
-
-			/* initialize the s_buf buffer */
-			s_buf.sem_op = TC[i].op;
-			s_buf.sem_flg = TC[i].flg;
-			s_buf.sem_num = TC[i].num;
-
-			/* initialize all the primitive semaphores */
-			TC[i].get_arr.val = val--;
-			if (semctl(sem_id_1, TC[i].num, SETVAL, TC[i].get_arr)
-			    == -1) {
-				tst_brkm(TBROK, cleanup, "semctl() failed");
-			}
-
-			/*
-			 * make the call with the TEST macro
-			 */
-
-			TEST(semop(sem_id_1, &s_buf, 1));
-
-			if (TEST_RETURN != -1) {
-				tst_resm(TFAIL, "call succeeded unexpectedly");
-				continue;
-			}
-
-			if (TEST_ERRNO == TC[i].error) {
-				tst_resm(TPASS,
-					 "expected failure - errno = %d"
-					 " : %s", TEST_ERRNO,
-					 strerror(TEST_ERRNO));
-			} else {
-				tst_resm(TFAIL, "unexpected error - "
-					 "%d : %s", TEST_ERRNO,
-					 strerror(TEST_ERRNO));
-			}
-		}
+	/* initialize the s_buf buffer */
+	s_buf.sem_op = tc[i].op;
+	s_buf.sem_flg = tc[i].flg;
+	s_buf.sem_num = tc[i].num;
+
+	/* initialize all the primitive semaphores */
+	tc[i].get_arr.val = val--;
+	if (semctl(sem_id, tc[i].num, SETVAL, tc[i].get_arr) == -1)
+		tst_brk(TBROK | TERRNO, "semctl() failed");
+
+	TEST(semop(sem_id, &s_buf, 1));
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "call succeeded unexpectedly");
+		return;
 	}
 
-	cleanup();
-
-	tst_exit();
+	if (TST_ERR == tc[i].error)
+		tst_res(TPASS | TTERRNO, "expected failure");
+	else
+		tst_res(TFAIL | TTERRNO, "unexpected failure");
 }
 
-/*
- * setup() - performs all the ONE TIME setup for this test.
- */
-void setup(void)
+static void setup(void)
 {
+	val = 1;
 
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
+	/* get an IPC resource key */
+	semkey = GETIPCKEY();
 
 	/*
-	 * Create a temporary directory and cd into it.
-	 * This helps to ensure that a unique msgkey is created.
-	 * See libs/libltpipc/libipc.c for more information.
+	 * create a semaphore set with read and alter permissions and PSEMS
+	 * "primitive" semaphores.
 	 */
-	tst_tmpdir();
-
-	/* get an IPC resource key */
-	semkey = getipckey();
-
-	/* create a semaphore set with read and alter permissions */
-	/* and PSEMS "primitive" semaphores                       */
-	if ((sem_id_1 =
-	     semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)) == -1) {
-		tst_brkm(TBROK, cleanup, "couldn't create semaphore in setup");
+	if ((sem_id = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)) ==
+	     -1) {
+		tst_brk(TBROK | TERRNO, "couldn't create semaphore in setup");
 	}
 }
 
-/*
- * cleanup() - performs all the ONE TIME cleanup for this test@completion
- * 	       or premature exit.
- */
-void cleanup(void)
+static void cleanup(void)
 {
-	/* if it exists, remove the semaphore resource */
-	rm_sema(sem_id_1);
-
-	tst_rmdir();
+	union semun arr;
 
+	if (sem_id != -1) {
+		if (semctl(sem_id, 0, IPC_RMID, arr) == -1)
+			tst_res(TINFO, "WARNING: semaphore deletion failed.");
+	}
 }
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tc),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/ipc/semop/semop05.c b/testcases/kernel/syscalls/ipc/semop/semop05.c
index e97ad42fe01d..9e8e040b0b19 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop05.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop05.c
@@ -1,21 +1,5 @@
-/*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   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
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) International Business Machines  Corp., 2001 */
 
 /*
  * NAME
@@ -60,18 +44,18 @@
  *	none
  */
 
-#include "ipcsem.h"
-
+#include <stdio.h>
+#include <stdlib.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#include "safe_macros.h"
-
-char *TCID = "semop05";
-int TST_TOTAL = 4;
-
-int sem_id_1 = -1;
+#include <sys/sem.h>
+#include "tst_test.h"
+#include "libnewipc.h"
+#include "lapi/semun.h"
 
-struct sembuf s_buf;
+static key_t semkey;
+static int sem_id = -1;
+static struct sembuf s_buf;
 
 struct test_case_t {
 	union semun semunptr;
@@ -79,7 +63,7 @@ struct test_case_t {
 	short flg;
 	short num;
 	int error;
-} TC[] = {
+} tc[] = {
 	/* EIRDM sem_op = 0 */
 	{ {
 	1}, 0, 0, 2, EIDRM},
@@ -96,189 +80,166 @@ struct test_case_t {
 
 #ifdef UCLINUX
 #define PIPE_NAME	"semop05"
-void do_child_uclinux();
+static void do_child_uclinux();
 static int i_uclinux;
 #endif
 
-int main(int ac, char **av)
+static inline int process_state_wait2(pid_t pid, const char state)
 {
-	int lc;
-	int i;
-	pid_t pid;
-	void do_child();
+	char proc_path[128], cur_state;
 
-	tst_parse_opts(ac, av, NULL, NULL);
+	snprintf(proc_path, sizeof(proc_path), "/proc/%i/stat", pid);
 
-#ifdef UCLINUX
-	maybe_run_child(&do_child_uclinux, "dd", &i_uclinux, &sem_id_1);
-#endif
-
-	setup();		/* global setup */
-
-	/* The following loop checks looping state if -i option given */
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		/* reset tst_count in case we are looping */
-		tst_count = 0;
-
-		for (i = 0; i < TST_TOTAL; i++) {
-
-			/* initialize the s_buf buffer */
-			s_buf.sem_op = TC[i].op;
-			s_buf.sem_flg = TC[i].flg;
-			s_buf.sem_num = TC[i].num;
-
-			/* initialize all of the primitive semaphores */
-			if (semctl(sem_id_1, TC[i].num, SETVAL, TC[i].semunptr)
-			    == -1) {
-				tst_brkm(TBROK, cleanup, "semctl() failed");
-			}
-
-			if ((pid = FORK_OR_VFORK()) == -1) {
-				tst_brkm(TBROK, cleanup, "could not fork");
-			}
-
-			if (pid == 0) {	/* child */
+	for (;;) {
+		FILE *f = fopen(proc_path, "r");
+		if (!f) {
+			tst_res(TFAIL, "Failed to open '%s': %s\n", proc_path,
+				strerror(errno));
+			return 1;
+		}
 
-#ifdef UCLINUX
-				if (self_exec(av[0], "dd", i, sem_id_1) < 0) {
-					tst_brkm(TBROK, cleanup,
-						 "could not self_exec");
-				}
-#else
-				do_child(i);
-#endif
-			} else {
-				TST_PROCESS_STATE_WAIT(cleanup, pid, 'S');
-
-				/*
-				 * If we are testing for EIDRM then remove
-				 * the semaphore, else send a signal that
-				 * must be caught as we are testing for
-				 * EINTR.
-				 */
-				if (TC[i].error == EIDRM) {
-					/* remove the semaphore resource */
-					rm_sema(sem_id_1);
-				} else {
-					SAFE_KILL(cleanup, pid, SIGHUP);
-				}
-
-				/* let the child carry on */
-				waitpid(pid, NULL, 0);
-			}
-
-			/*
-			 * recreate the semaphore resource if needed
-			 */
-			if (TC[i].error == EINTR) {
-				continue;
-			}
-
-			if ((sem_id_1 = semget(semkey, PSEMS, IPC_CREAT |
-					       IPC_EXCL | SEM_RA)) == -1) {
-				tst_brkm(TBROK, cleanup, "couldn't recreate "
-					 "semaphore");
-			}
+		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);
 
-	cleanup();
+		if (state == cur_state)
+			return 0;
 
-	tst_exit();
+		usleep(10000);
+	}
 }
 
-/*
- * do_child()
- */
-void do_child(int i)
+static void do_child(int i)
 {
-	/*
-	 * make the call with the TEST macro
-	 */
-
-	TEST(semop(sem_id_1, &s_buf, 1));
-
-	if (TEST_RETURN != -1) {
-		tst_resm(TFAIL, "call succeeded when error expected");
+	TEST(semop(sem_id, &s_buf, 1));
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "call succeeded when error expected");
 		exit(-1);
 	}
 
-	if (TEST_ERRNO == TC[i].error) {
-		tst_resm(TPASS, "expected failure - errno = %d"
-			 " : %s", TEST_ERRNO, strerror(TEST_ERRNO));
-	} else {
-		tst_resm(TFAIL, "unexpected error - "
-			 "%d : %s", TEST_ERRNO, strerror(TEST_ERRNO));
-	}
+	if (TST_ERR == tc[i].error)
+		tst_res(TPASS | TTERRNO, "expected failure");
+	else
+		tst_res(TFAIL | TTERRNO, "unexpected failure");
 
 	exit(0);
 }
 
-void sighandler(int sig)
+static void sighandler(int sig)
 {
-	if (sig == SIGHUP)
-		return;
-	else
-		tst_brkm(TBROK, NULL, "unexpected signal %d received", sig);
+	if (sig != SIGHUP)
+		tst_brk(TBROK, "unexpected signal %d received", sig);
 }
 
-#ifdef UCLINUX
-/*
- * do_child_uclinux() - capture signals, re-initialize s_buf then call do_child
- *                      with the appropriate argument
- */
-void do_child_uclinux(void)
+static void setup(void)
 {
-	int i = i_uclinux;
+	SAFE_SIGNAL(SIGHUP, sighandler);
 
-	tst_sig(FORK, sighandler, cleanup);
+	/* get an IPC resource key */
+	semkey = GETIPCKEY();
 
-	/* initialize the s_buf buffer */
-	s_buf.sem_op = TC[i].op;
-	s_buf.sem_flg = TC[i].flg;
-	s_buf.sem_num = TC[i].num;
+	/*
+	 * create a semaphore set with read and alter permissions and PSEMS
+	 * "primitive" semaphores.
+	 */
+	if ((sem_id = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)) ==
+	    -1)
+		tst_brk(TBROK | TERRNO, "couldn't create semaphore in setup");
+}
 
-	do_child(i);
+static void cleanup(void)
+{
+	union semun arr;
+
+	if (sem_id != -1) {
+		if (semctl(sem_id, 0, IPC_RMID, arr) == -1)
+			tst_res(TINFO, "WARNING: semaphore deletion failed.");
+	}
 }
-#endif
 
-/*
- * setup() - performs all the ONE TIME setup for this test.
- */
-void setup(void)
+static void run(unsigned int i)
 {
+	pid_t pid;
 
-	tst_sig(FORK, sighandler, cleanup);
+#ifdef UCLINUX
+	maybe_run_child(&do_child_uclinux, "dd", &i_uclinux, &sem_id);
+#endif
+	/* initialize the s_buf buffer */
+	s_buf.sem_op = tc[i].op;
+	s_buf.sem_flg = tc[i].flg;
+	s_buf.sem_num = tc[i].num;
 
-	TEST_PAUSE;
+	/* initialize all of the primitive semaphores */
+	if (semctl(sem_id, tc[i].num, SETVAL, tc[i].semunptr) == -1)
+		tst_brk(TBROK | TERRNO, "semctl() failed");
 
-	/*
-	 * Create a temporary directory and cd into it.
-	 * This helps to ensure that a unique msgkey is created.
-	 * See libs/libltpipc/libipc.c for more information.
-	 */
-	tst_tmpdir();
+	pid = SAFE_FORK();
 
-	/* get an IPC resource key */
-	semkey = getipckey();
+	if (pid == 0) {	/* child */
+#ifdef UCLINUX
+		if (self_exec(av[0], "dd", i, sem_id) < 0)
+			tst_brk(TBROK, "could not self_exec");
+#else
+		do_child(i);
+#endif
+	} else {
+		process_state_wait2(pid, 'S');
+
+		/*
+		 * If we are testing for EIDRM then remove
+		 * the semaphore, else send a signal that
+		 * must be caught as we are testing for
+		 * EINTR.
+		 */
+		if (tc[i].error == EIDRM) {
+			/* remove the semaphore resource */
+			cleanup();
+		} else {
+			SAFE_KILL(pid, SIGHUP);
+		}
 
-	/* create a semaphore set with read and alter permissions */
-	/* and PSEMS "primitive" semaphores                       */
-	if ((sem_id_1 =
-	     semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)) == -1) {
-		tst_brkm(TBROK, cleanup, "couldn't create semaphore in setup");
+		/* let the child carry on */
+		waitpid(pid, NULL, 0);
 	}
+
+	/*
+	 * recreate the semaphore resource if needed
+	 */
+	if (tc[i].error == EINTR)
+		return;
+
+	if ((sem_id = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)) ==
+	    -1)
+		tst_brk(TBROK | TERRNO, "couldn't recreate semaphore");
 }
 
+#ifdef UCLINUX
 /*
- * cleanup() - performs all the ONE TIME cleanup for this test@completion
- *	       or premature exit.
+ * do_child_uclinux() - capture signals, re-initialize s_buf then call do_child
+ *                      with the appropriate argument
  */
-void cleanup(void)
+static void do_child_uclinux(void)
 {
-	/* if it exists, remove the semaphore resource */
-	rm_sema(sem_id_1);
+	int i = i_uclinux;
+
+	/* initialize the s_buf buffer */
+	s_buf.sem_op = tc[i].op;
+	s_buf.sem_flg = tc[i].flg;
+	s_buf.sem_num = tc[i].num;
 
-	tst_rmdir();
+	do_child(i);
 }
+#endif
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tc),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.forks_child = 1,
+};
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 16/19] syscalls/semtimedop: Add support for semtimedop and its time64 version
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (14 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 15/19] syscalls/semop: Migrate to new test framework Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-06-26  6:22 ` [LTP] [PATCH V7 17/19] syscalls/utimensat: Migrate to new test framework Viresh Kumar
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for semtimedop() and its time64 variant to the
existing semop() syscall tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 testcases/kernel/syscalls/ipc/semop/semop.h   | 55 +++++++++++++++++++
 testcases/kernel/syscalls/ipc/semop/semop01.c | 14 ++++-
 testcases/kernel/syscalls/ipc/semop/semop02.c | 15 ++++-
 testcases/kernel/syscalls/ipc/semop/semop03.c | 16 +++++-
 testcases/kernel/syscalls/ipc/semop/semop04.c | 16 +++++-
 testcases/kernel/syscalls/ipc/semop/semop05.c | 16 +++++-
 6 files changed, 127 insertions(+), 5 deletions(-)
 create mode 100644 testcases/kernel/syscalls/ipc/semop/semop.h

diff --git a/testcases/kernel/syscalls/ipc/semop/semop.h b/testcases/kernel/syscalls/ipc/semop/semop.h
new file mode 100644
index 000000000000..584d12c68e0d
--- /dev/null
+++ b/testcases/kernel/syscalls/ipc/semop/semop.h
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifndef SEMOP_VAR__
+#define SEMOP_VAR__
+
+#include <sys/sem.h>
+#include "tst_timer.h"
+
+static inline int sys_semtimedop(int semid, struct sembuf *sops, size_t nsops,
+		void *timeout)
+{
+	return tst_syscall(__NR_semtimedop, semid, sops, nsops, timeout);
+}
+
+static inline int sys_semtimedop_time64(int semid, struct sembuf *sops,
+					size_t nsops, void *timeout)
+{
+	return tst_syscall(__NR_semtimedop_time64, semid, sops, nsops, timeout);
+}
+
+struct test_variants {
+	int (*semop)(int semid, struct sembuf *sops, size_t nsops);
+	int (*semtimedop)(int semid, struct sembuf *sops, size_t nsops, void *timeout);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+	{ .semop = semop, .type = TST_LIBC_TIMESPEC, .desc = "semop: vDSO or syscall"},
+
+#if (__NR_semtimedop != __LTP__NR_INVALID_SYSCALL)
+	{ .semtimedop = sys_semtimedop, .type = TST_KERN_OLD_TIMESPEC, .desc = "semtimedop: syscall with old kernel spec"},
+#endif
+
+#if (__NR_semtimedop_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .semtimedop = sys_semtimedop_time64, .type = TST_KERN_TIMESPEC, .desc = "semtimedop: syscall time64 with kernel spec"},
+#endif
+};
+
+static inline int call_semop(struct test_variants *tv, int semid,
+		struct sembuf *sops, size_t nsops, struct tst_ts *timeout)
+{
+	if (tv->semop)
+		return tv->semop(semid, sops, nsops);
+
+	return tv->semtimedop(semid, sops, nsops, tst_ts_get(timeout));
+}
+
+static inline void semop_supported_by_kernel(struct test_variants *tv)
+{
+       /* Check if the syscall is implemented on the platform */
+       TEST(call_semop(tv, 0, NULL, 0, NULL));
+       if (TST_RET == -1 && TST_ERR == ENOSYS)
+               tst_brk(TCONF, "Test not supported on kernel/platform");
+}
+
+#endif /* SEMOP_VAR__ */
diff --git a/testcases/kernel/syscalls/ipc/semop/semop01.c b/testcases/kernel/syscalls/ipc/semop/semop01.c
index bcb45fa69320..7947183c837b 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop01.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop01.c
@@ -41,6 +41,7 @@
 #include "tst_test.h"
 #include "libnewipc.h"
 #include "lapi/semun.h"
+#include "semop.h"
 
 #define NSEMS	4		/* the number of primitive semaphores to test */
 
@@ -52,11 +53,17 @@ static struct sembuf sops[PSEMS];
 
 static void run(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	union semun arr = { .val = 0 };
+	struct tst_ts timeout;
 	int fail = 0;
 	int i;
 
-	TEST(semop(sem_id, sops, NSEMS));
+	timeout.type = tv->type;
+	tst_ts_set_sec(&timeout, 1);
+	tst_ts_set_nsec(&timeout, 10000);
+
+	TEST(call_semop(tv, sem_id, sops, NSEMS, &timeout));
 
 	if (TST_RET == -1) {
 		tst_res(TFAIL | TTERRNO, "semop() failed");
@@ -92,8 +99,12 @@ static void run(void)
 
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	int i;
 
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	semop_supported_by_kernel(tv);
+
 	get_arr.array = malloc(sizeof(unsigned short int) * PSEMS);
 	if (get_arr.array == NULL)
 		tst_brk(TBROK, "malloc failed");
@@ -124,6 +135,7 @@ static void cleanup(void)
 
 static struct tst_test test = {
 	.test_all = run,
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.cleanup = cleanup,
 	.needs_tmpdir = 1,
diff --git a/testcases/kernel/syscalls/ipc/semop/semop02.c b/testcases/kernel/syscalls/ipc/semop/semop02.c
index f24d284776a4..4ffb9dd72c1c 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop02.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop02.c
@@ -20,6 +20,7 @@
 #include "tst_test.h"
 #include "libnewipc.h"
 #include "lapi/semun.h"
+#include "semop.h"
 
 static int sem_id_1 = -1;	/* a semaphore set with read & alter permissions */
 static int sem_id_2 = -1;	/* a semaphore set without read & alter permissions */
@@ -46,12 +47,16 @@ static struct test_case_t {
 
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	char nobody_uid[] = "nobody";
 	struct passwd *ltpuser;
 	key_t semkey2;
 	struct seminfo ipc_buf;
 	union semun arr;
 
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	semop_supported_by_kernel(tv);
+
 	ltpuser = SAFE_GETPWNAM(nobody_uid);
 	SAFE_SETUID(ltpuser->pw_uid);
 
@@ -84,7 +89,14 @@ static void setup(void)
 
 static void run(unsigned int i)
 {
-	TEST(semop(*(tc[i].semid), tc[i].t_sbuf, tc[i].t_ops));
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_ts timeout;
+
+	timeout.type = tv->type;
+	tst_ts_set_sec(&timeout, 1);
+	tst_ts_set_nsec(&timeout, 10000);
+
+	TEST(call_semop(tv, *(tc[i].semid), tc[i].t_sbuf, tc[i].t_ops, &timeout));
 
 	if (TST_RET != -1) {
 		tst_res(TFAIL | TTERRNO, "call succeeded unexpectedly");
@@ -117,6 +129,7 @@ static void cleanup(void)
 static struct tst_test test = {
 	.test = run,
 	.tcnt = ARRAY_SIZE(tc),
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.cleanup = cleanup,
 	.needs_tmpdir = 1,
diff --git a/testcases/kernel/syscalls/ipc/semop/semop03.c b/testcases/kernel/syscalls/ipc/semop/semop03.c
index 4f5f78eb6d8d..40a6b095c57d 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop03.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop03.c
@@ -38,6 +38,7 @@
 #include "tst_test.h"
 #include "libnewipc.h"
 #include "lapi/semun.h"
+#include "semop.h"
 
 static key_t semkey;
 static int sem_id = -1;
@@ -47,6 +48,13 @@ static int tc[] = { -1, PSEMS + 1 }; /* negative and too many "primitive" semas
 
 static void run(unsigned int i)
 {
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_ts timeout;
+
+	timeout.type = tv->type;
+	tst_ts_set_sec(&timeout, 1);
+	tst_ts_set_nsec(&timeout, 10000);
+
 	/* initialize two fields in the sembuf structure here */
 	s_buf.sem_op = 1;	/* add this value to struct sem.semval */
 	s_buf.sem_flg = SEM_UNDO;	/* undo when process exits */
@@ -61,7 +69,7 @@ static void run(unsigned int i)
 	 * use the TEST macro to make the call
 	 */
 
-	TEST(semop(sem_id, &s_buf, 1));
+	TEST(call_semop(tv, sem_id, &s_buf, 1, &timeout));
 
 	if (TST_RET != -1) {
 		tst_res(TFAIL | TTERRNO, "call succeeded unexpectedly");
@@ -80,6 +88,11 @@ static void run(unsigned int i)
 
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	semop_supported_by_kernel(tv);
+
 	/* get an IPC resource key */
 	semkey = GETIPCKEY();
 
@@ -102,6 +115,7 @@ static void cleanup(void)
 static struct tst_test test = {
 	.test = run,
 	.tcnt = ARRAY_SIZE(tc),
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.cleanup = cleanup,
 	.needs_tmpdir = 1,
diff --git a/testcases/kernel/syscalls/ipc/semop/semop04.c b/testcases/kernel/syscalls/ipc/semop/semop04.c
index 0faf00a3585f..5e4bfeb625e2 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop04.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop04.c
@@ -38,6 +38,7 @@
 #include "tst_test.h"
 #include "libnewipc.h"
 #include "lapi/semun.h"
+#include "semop.h"
 
 static int sem_id = -1;
 static int val; /* value for SETVAL */
@@ -62,6 +63,13 @@ static struct test_case_t {
 
 static void run(unsigned int i)
 {
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_ts timeout;
+
+	timeout.type = tv->type;
+	tst_ts_set_sec(&timeout, 1);
+	tst_ts_set_nsec(&timeout, 10000);
+
 	/* initialize the s_buf buffer */
 	s_buf.sem_op = tc[i].op;
 	s_buf.sem_flg = tc[i].flg;
@@ -72,7 +80,7 @@ static void run(unsigned int i)
 	if (semctl(sem_id, tc[i].num, SETVAL, tc[i].get_arr) == -1)
 		tst_brk(TBROK | TERRNO, "semctl() failed");
 
-	TEST(semop(sem_id, &s_buf, 1));
+	TEST(call_semop(tv, sem_id, &s_buf, 1, &timeout));
 	if (TST_RET != -1) {
 		tst_res(TFAIL, "call succeeded unexpectedly");
 		return;
@@ -86,6 +94,11 @@ static void run(unsigned int i)
 
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	semop_supported_by_kernel(tv);
+
 	val = 1;
 
 	/* get an IPC resource key */
@@ -114,6 +127,7 @@ static void cleanup(void)
 static struct tst_test test = {
 	.test = run,
 	.tcnt = ARRAY_SIZE(tc),
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.cleanup = cleanup,
 	.needs_tmpdir = 1,
diff --git a/testcases/kernel/syscalls/ipc/semop/semop05.c b/testcases/kernel/syscalls/ipc/semop/semop05.c
index 9e8e040b0b19..770646bc564c 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop05.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop05.c
@@ -52,6 +52,7 @@
 #include "tst_test.h"
 #include "libnewipc.h"
 #include "lapi/semun.h"
+#include "semop.h"
 
 static key_t semkey;
 static int sem_id = -1;
@@ -115,7 +116,14 @@ static inline int process_state_wait2(pid_t pid, const char state)
 
 static void do_child(int i)
 {
-	TEST(semop(sem_id, &s_buf, 1));
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_ts timeout;
+
+	timeout.type = tv->type;
+	tst_ts_set_sec(&timeout, 1);
+	tst_ts_set_nsec(&timeout, 10000);
+
+	TEST(call_semop(tv, sem_id, &s_buf, 1, &timeout));
 	if (TST_RET != -1) {
 		tst_res(TFAIL, "call succeeded when error expected");
 		exit(-1);
@@ -137,6 +145,11 @@ static void sighandler(int sig)
 
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	semop_supported_by_kernel(tv);
+
 	SAFE_SIGNAL(SIGHUP, sighandler);
 
 	/* get an IPC resource key */
@@ -238,6 +251,7 @@ static void do_child_uclinux(void)
 static struct tst_test test = {
 	.test = run,
 	.tcnt = ARRAY_SIZE(tc),
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.cleanup = cleanup,
 	.needs_tmpdir = 1,
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 17/19] syscalls/utimensat: Migrate to new test framework
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (15 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 16/19] syscalls/semtimedop: Add support for semtimedop and its time64 version Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-27 15:35   ` Cyril Hrubis
  2020-06-26  6:22 ` [LTP] [PATCH V7 18/19] syscalls/utimensat: Add support for time64 tests Viresh Kumar
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This gets rid of the test script and updates the utimensat01.c file to
handle most of the tests covered earlier (apart from testing the same
for files owned by root, as the test is run as root right now).

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../kernel/syscalls/utimensat/utimensat01.c   | 424 ++++++--------
 .../syscalls/utimensat/utimensat_tests.sh     | 517 ------------------
 2 files changed, 179 insertions(+), 762 deletions(-)
 delete mode 100755 testcases/kernel/syscalls/utimensat/utimensat_tests.sh

diff --git a/testcases/kernel/syscalls/utimensat/utimensat01.c b/testcases/kernel/syscalls/utimensat/utimensat01.c
index 264ca1e15120..97a43713454f 100644
--- a/testcases/kernel/syscalls/utimensat/utimensat01.c
+++ b/testcases/kernel/syscalls/utimensat/utimensat01.c
@@ -1,282 +1,216 @@
-/*************************************************************************************/
-/*                                                                                   */
-/* Copyright (C) 2008, Michael Kerrisk <mtk.manpages@gmail.com>,                     */
-/* Copyright (C) 2008, Linux Foundation                                              */
-/*                                                                                   */
-/* 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           */
-/*************************************************************************************/
-/*                                                                                   */
-/* File: utimnsat01.c                                                                */
-/* Description: A command-line interface for testing the utimensat() system call.    */
-/* Author: Michael Kerrisk <mtk.manpages@gmail.com>                                  */
-/* History:                                                                          */
-/*	17 Mar  2008  Initial creation,                                              */
-/*	31 May  2008  Reworked for easier test automation,                           */
-/*	2  June 2008  Renamed from t_utimensat.c to test_utimensat.c,                */
-/*	05 June 2008  Submitted to LTP by Subrata Modak <subrata@linux.vnet.ibm.com> */
-/*************************************************************************************/
-
-#define _GNU_SOURCE
-#define _ATFILE_SOURCE
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2008 Michael Kerrisk <mtk.manpages@gmail.com>
+ * Copyright (c) 2008 Subrata Modak <subrata@linux.vnet.ibm.com>
+ * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * Basic utimnsat() test.
+ */
+
 #include <stdio.h>
 #include <time.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <sys/syscall.h>
 #include <fcntl.h>
 #include <string.h>
 #include <sys/stat.h>
-#include "test.h"
+#include "lapi/fs.h"
+#include "tst_test.h"
 #include "lapi/syscalls.h"
 
-char *TCID = "utimensat01";
-int TST_TOTAL = 0;
-
-#define cleanup tst_exit
+#define UTIME_NOW	((1l << 30) - 1l)
+#define UTIME_OMIT	((1l << 30) - 2l)
+
+#define TEST_FILE	"test_file"
+#define TEST_DIR	"test_dir"
+
+static void *bad_addr;
+
+struct mytime {
+	long access_tv_sec;
+	long access_tv_nsec;
+	long mod_tv_sec;
+	long mod_tv_nsec;
+};
+
+static struct mytime tnn = {0, UTIME_NOW, 0, UTIME_NOW}, *time_nn = &tnn;
+static struct mytime too = {0, UTIME_OMIT, 0, UTIME_OMIT}, *time_oo = &too;
+static struct mytime tno = {0, UTIME_NOW, 0, UTIME_OMIT}, *time_no = &tno;
+static struct mytime ton = {0, UTIME_OMIT, 0, UTIME_NOW}, *time_on = &ton;
+static struct mytime t11 = {1, 1, 1, 1}, *time_11 = &t11;
+
+struct test_case {
+	int dirfd;
+	char *pathname;
+	struct mytime **mytime;
+	int flags;
+	int oflags;
+	int attr;
+	int mode;
+	int exp_err;
+} tcase[] = {
+	/* Testing read-only file */
+	{AT_FDCWD, TEST_FILE, NULL, 0, O_RDONLY, 0, 0400, 0},
+	{AT_FDCWD, TEST_FILE, &time_nn, 0, O_RDONLY, 0, 0400, 0},
+	{AT_FDCWD, TEST_FILE, &time_oo, 0, O_RDONLY, 0, 0400, 0},
+	{AT_FDCWD, TEST_FILE, &time_no, 0, O_RDONLY, 0, 0400, 0},
+	{AT_FDCWD, TEST_FILE, &time_on, 0, O_RDONLY, 0, 0400, 0},
+	{AT_FDCWD, TEST_FILE, &time_11, 0, O_RDONLY, 0, 0400, 0},
+
+	/* Testing writable file */
+	{AT_FDCWD, TEST_FILE, NULL, 0, O_RDONLY, 0, 0666, 0},
+	{AT_FDCWD, TEST_FILE, &time_nn, 0, O_RDONLY, 0, 0666, 0},
+	{AT_FDCWD, TEST_FILE, &time_oo, 0, O_RDONLY, 0, 0666, 0},
+	{AT_FDCWD, TEST_FILE, &time_no, 0, O_RDONLY, 0, 0666, 0},
+	{AT_FDCWD, TEST_FILE, &time_on, 0, O_RDONLY, 0, 0666, 0},
+	{AT_FDCWD, TEST_FILE, &time_11, 0, O_RDONLY, 0, 0666, 0},
+
+	/* Testing append-only file */
+	{AT_FDCWD, TEST_FILE, NULL, 0, O_RDONLY, FS_APPEND_FL, 0600, 0},
+	{AT_FDCWD, TEST_FILE, &time_nn, 0, O_RDONLY, FS_APPEND_FL, 0600, 0},
+	{AT_FDCWD, TEST_FILE, &time_oo, 0, O_RDONLY, FS_APPEND_FL, 0600, 0},
+	{AT_FDCWD, TEST_FILE, &time_no, 0, O_RDONLY, FS_APPEND_FL, 0600, EPERM},
+	{AT_FDCWD, TEST_FILE, &time_on, 0, O_RDONLY, FS_APPEND_FL, 0600, EPERM},
+	{AT_FDCWD, TEST_FILE, &time_11, 0, O_RDONLY, FS_APPEND_FL, 0600, EPERM},
+
+	/* Testing immutable file */
+	{AT_FDCWD, TEST_FILE, NULL, 0, O_RDONLY, FS_IMMUTABLE_FL, 0600, -1},
+	{AT_FDCWD, TEST_FILE, &time_nn, 0, O_RDONLY, FS_IMMUTABLE_FL, 0600, -1},
+	{AT_FDCWD, TEST_FILE, &time_oo, 0, O_RDONLY, FS_IMMUTABLE_FL, 0600, 0},
+	{AT_FDCWD, TEST_FILE, &time_no, 0, O_RDONLY, FS_IMMUTABLE_FL, 0600, EPERM},
+	{AT_FDCWD, TEST_FILE, &time_on, 0, O_RDONLY, FS_IMMUTABLE_FL, 0600, EPERM},
+	{AT_FDCWD, TEST_FILE, &time_11, 0, O_RDONLY, FS_IMMUTABLE_FL, 0600, EPERM},
+
+	/* Testing immutable-append-only file */
+	{AT_FDCWD, TEST_FILE, NULL, 0, O_RDONLY, FS_APPEND_FL|FS_IMMUTABLE_FL, 0600, -1},
+	{AT_FDCWD, TEST_FILE, &time_nn, 0, O_RDONLY, FS_APPEND_FL|FS_IMMUTABLE_FL, 0600, -1},
+	{AT_FDCWD, TEST_FILE, &time_oo, 0, O_RDONLY, FS_APPEND_FL|FS_IMMUTABLE_FL, 0600, 0},
+	{AT_FDCWD, TEST_FILE, &time_no, 0, O_RDONLY, FS_APPEND_FL|FS_IMMUTABLE_FL, 0600, EPERM},
+	{AT_FDCWD, TEST_FILE, &time_on, 0, O_RDONLY, FS_APPEND_FL|FS_IMMUTABLE_FL, 0600, EPERM},
+	{AT_FDCWD, TEST_FILE, &time_11, 0, O_RDONLY, FS_APPEND_FL|FS_IMMUTABLE_FL, 0600, EPERM},
+
+	/* Other failure tests */
+	{AT_FDCWD, TEST_FILE, NULL, 0, O_RDONLY, 0, 0400, EFAULT},
+	{AT_FDCWD, NULL, &time_nn, 0, O_RDONLY, 0, 0400, EFAULT},
+	{-1, NULL, &time_nn, AT_SYMLINK_NOFOLLOW, O_RDONLY, 0, 0400, EINVAL},
+	{-1, TEST_FILE, &time_nn, 0, O_RDONLY, 0, 0400, ENOENT},
+};
+
+static inline int sys_utimensat(int dirfd, const char *pathname,
+				const struct timespec times[2], int flags)
+{
+	return tst_syscall(__NR_utimensat, dirfd, pathname, times, flags);
+}
 
-/* We use EXIT_FAILURE for an expected failure from utimensat()
-   (e.g., EACCES and EPERM), and one of the following for unexpected
-   failures (i.e., something broke in our test setup). */
+static void setup(void)
+{
+	bad_addr = tst_get_bad_addr(NULL);
+}
 
-#ifndef AT_FDCWD
-#define AT_FDCWD -100
-#endif
-#ifndef AT_SYMLINK_NOFOLLOW
-#define AT_SYMLINK_NOFOLLOW 0x100
-#endif
+static void update_error(struct test_case *tc)
+{
+	if (tc->exp_err != -1)
+		return;
+
+	/*
+	 * Starting with 4.8.0 operations on immutable files return EPERM
+	 * instead of EACCES.
+	 * This patch has also been merged to stable 4.4 with
+	 * b3b4283 ("vfs: move permission checking into notify_change() for utimes(NULL)")
+	 */
+	if (tst_kvercmp(4, 4, 27) < 0)
+		tc->exp_err = EACCES;
+	else
+		tc->exp_err = EPERM;
+}
 
-#define EXIT_bad_usage 3
-#define EXIT_failed_syscall 3
+static void change_attr(struct test_case *tc, int fd, int set)
+{
+	int attr;
 
-#define errExit(msg)    do { perror(msg); exit(EXIT_failed_syscall); \
-                        } while (0)
+	if (!tc->attr)
+		return;
 
-#define UTIME_NOW      ((1l << 30) - 1l)
-#define UTIME_OMIT     ((1l << 30) - 2l)
+	SAFE_IOCTL(fd, FS_IOC_GETFLAGS, &attr);
 
-static inline int
-utimensat_sc(int dirfd, const char *pathname,
-	     const struct timespec times[2], int flags)
-{
-	return ltp_syscall(__NR_utimensat, dirfd, pathname, times, flags);
-}
+	if (set)
+		attr |= tc->attr;
+	else
+		attr &= ~tc->attr;
 
-static void usageError(char *progName)
-{
-	fprintf(stderr, "Usage: %s pathname [atime-sec "
-		"atime-nsec mtime-sec mtime-nsec]\n\n", progName);
-	fprintf(stderr, "Permitted options are:\n");
-	fprintf(stderr, "    [-d path] "
-		"open a directory file descriptor"
-		" (instead of using AT_FDCWD)\n");
-	fprintf(stderr, "    -q        Quiet\n");
-	fprintf(stderr, "    -w        Open directory file "
-		"descriptor with O_RDWR|O_APPEND\n"
-		"              (instead of O_RDONLY)\n");
-	fprintf(stderr, "    -n        Use AT_SYMLINK_NOFOLLOW\n");
-	fprintf(stderr, "\n");
-
-	fprintf(stderr, "pathname can be \"NULL\" to use NULL "
-		"argument in call\n");
-	fprintf(stderr, "\n");
-
-	fprintf(stderr, "Either nsec field can be\n");
-	fprintf(stderr, "    'n' for UTIME_NOW\n");
-	fprintf(stderr, "    'o' for UTIME_OMIT\n");
-	fprintf(stderr, "\n");
-
-	fprintf(stderr, "If the time fields are omitted, "
-		"then a NULL 'times' argument is used\n");
-	fprintf(stderr, "\n");
-
-	exit(EXIT_bad_usage);
+	SAFE_IOCTL(fd, FS_IOC_SETFLAGS, &attr);
 }
 
-int main(int argc, char *argv[])
+static void run(unsigned int i)
 {
-	int flags, dirfd, opt, oflag;
+	struct test_case *tc = &tcase[i];
 	struct timespec ts[2];
-	struct timespec *tsp;
-	char *pathname, *dirfdPath;
+	void *tsp = NULL;
+	char *pathname = NULL;
+	int dfd = AT_FDCWD, fd = 0;
 	struct stat sb;
-	int verbose;
-
-	/* Command-line argument parsing */
-
-	flags = 0;
-	verbose = 1;
-	dirfd = AT_FDCWD;
-	dirfdPath = NULL;
-	oflag = O_RDONLY;
-
-	while ((opt = getopt(argc, argv, "d:nqw")) != -1) {
-		switch (opt) {
-		case 'd':
-			dirfdPath = optarg;
-			break;
-
-		case 'n':
-			flags |= AT_SYMLINK_NOFOLLOW;
-			if (verbose)
-				printf("Not following symbolic links\n");
-			break;
-
-		case 'q':
-			verbose = 0;
-			break;
-
-		case 'w':
-			oflag = O_RDWR | O_APPEND;
-			break;
-
-		default:
-			usageError(argv[0]);
-		}
-	}
-
-	if ((optind + 5 != argc) && (optind + 1 != argc))
-		usageError(argv[0]);
-
-	if (dirfdPath != NULL) {
-		dirfd = open(dirfdPath, oflag);
-		if (dirfd == -1)
-			errExit("open");
-
-		if (verbose) {
-			printf("Opened dirfd %d", oflag);
-			if ((oflag & O_ACCMODE) == O_RDWR)
-				printf(" O_RDWR");
-			if (oflag & O_APPEND)
-				printf(" O_APPEND");
-			printf(": %s\n", dirfdPath);
-		}
-	}
 
-	pathname = (strcmp(argv[optind], "NULL") == 0) ? NULL : argv[optind];
+	SAFE_MKDIR(TEST_DIR, 0700);
+	update_error(tc);
 
-	/* Either, we get no values for 'times' fields, in which case
-	   we give a NULL pointer to utimensat(), or we get four values,
-	   for secs+nsecs for each of atime and mtime.  The special
-	   values 'n' and 'o' can be used for tv_nsec settings of
-	   UTIME_NOW and UTIME_OMIT, respectively. */
+	if (tc->dirfd != AT_FDCWD)
+		dfd = SAFE_OPEN(TEST_DIR, tc->oflags);
 
-	if (argc == optind + 1) {
-		tsp = NULL;
-
-	} else {
-		ts[0].tv_sec = atoi(argv[optind + 1]);
-		if (argv[optind + 2][0] == 'n') {
-			ts[0].tv_nsec = UTIME_NOW;
-		} else if (argv[optind + 2][0] == 'o') {
-			ts[0].tv_nsec = UTIME_OMIT;
-		} else {
-			ts[0].tv_nsec = atoi(argv[optind + 2]);
-		}
-
-		ts[1].tv_sec = atoi(argv[optind + 3]);
-		if (argv[optind + 4][0] == 'n') {
-			ts[1].tv_nsec = UTIME_NOW;
-		} else if (argv[optind + 4][0] == 'o') {
-			ts[1].tv_nsec = UTIME_OMIT;
-		} else {
-			ts[1].tv_nsec = atoi(argv[optind + 4]);
-		}
+	if (tc->mytime) {
+		struct mytime *mytime = *tc->mytime;
 
+		ts[0].tv_sec = mytime->access_tv_sec;
+		ts[0].tv_nsec = mytime->access_tv_nsec;
+		ts[1].tv_sec = mytime->mod_tv_sec;
+		ts[1].tv_nsec = mytime->mod_tv_nsec;
 		tsp = ts;
+	} else if (tc->exp_err == EFAULT) {
+		tsp = bad_addr;
 	}
 
-	/* For testing purposes, it may have been useful to run this program
-	   as set-user-ID-root so that a directory file descriptor could be
-	   opened as root.  (This allows us to obtain a file descriptor even
-	   if normal user doesn't have permissions on the file.)  Now we
-	   reset to the real UID before making the utimensat() call, so that
-	   the permission checking for the utimensat() call is performed
-	   under that UID. */
-
-	if (geteuid() == 0) {
-		uid_t u;
-
-		u = getuid();
-
-		if (verbose)
-			printf("Resetting UIDs to %ld\n", (long)u);
-
-		if (setresuid(u, u, u) == -1)
-			errExit("setresuid");
+	if (tc->pathname) {
+		fd = SAFE_OPEN(tc->pathname, O_WRONLY | O_CREAT);
+		pathname = tc->pathname;
+		SAFE_CHMOD(tc->pathname, tc->mode);
+		change_attr(tc, fd, 1);
+	} else if (tc->exp_err == EFAULT) {
+		pathname = bad_addr;
 	}
 
-	/* Display information allowing user to verify arguments for call */
+	TEST(sys_utimensat(dfd, pathname, tsp, tc->flags));
+	if (tc->pathname)
+		change_attr(tc, fd, 0);
 
-	if (verbose) {
-		printf("dirfd is %d\n", dirfd);
-		printf("pathname is %s\n", pathname);
-		printf("tsp is %p", tsp);
-		if (tsp != NULL) {
-			printf("; struct  = { %ld, %ld } { %ld, %ld }",
-			       (long)tsp[0].tv_sec, (long)tsp[0].tv_nsec,
-			       (long)tsp[1].tv_sec, (long)tsp[1].tv_nsec);
-		}
-		printf("\n");
-		printf("flags is %d\n", flags);
-	}
-
-	/* Make the call and see what happened */
-
-	if (utimensat_sc(dirfd, pathname, tsp, flags) == -1) {
-		if (errno == EPERM) {
-			if (verbose)
-				printf("utimensat() failed with EPERM\n");
-			else
-				printf("EPERM\n");
-			exit(EXIT_FAILURE);
-
-		} else if (errno == EACCES) {
-			if (verbose)
-				printf("utimensat() failed with EACCES\n");
-			else
-				printf("EACCES\n");
-			exit(EXIT_FAILURE);
-
-		} else if (errno == EINVAL) {
-			if (verbose)
-				printf("utimensat() failed with EINVAL\n");
-			else
-				printf("EINVAL\n");
-			exit(EXIT_FAILURE);
-
-		} else {	/* Unexpected failure case from utimensat() */
-			errExit("utimensat");
+	if (TST_RET) {
+		if (!tc->exp_err) {
+			tst_res(TFAIL | TTERRNO, "%2d: utimensat() failed", i);
+		} else if (tc->exp_err == TST_ERR) {
+			tst_res(TPASS | TTERRNO, "%2d: utimensat() failed expectedly", i);
+		} else {
+			tst_res(TFAIL | TTERRNO, "%2d: utimensat() failed with incorrect error, expected %s",
+				i, tst_strerrno(tc->exp_err));
 		}
-	}
-
-	if (verbose)
-		printf("utimensat() succeeded\n");
-
-	if (stat((pathname != NULL) ? pathname : dirfdPath, &sb) == -1)
-		errExit("stat");
-
-	if (verbose) {
-		printf("Last file access:         %s", ctime(&sb.st_atime));
-		printf("Last file modification:   %s", ctime(&sb.st_mtime));
-		printf("Last status change:       %s", ctime(&sb.st_ctime));
-
+	} else if (tc->exp_err) {
+		tst_res(TFAIL, "%2d: utimensat() passed unexpectedly", i);
 	} else {
-		printf("SUCCESS %ld %ld\n", (long)sb.st_atime,
-		       (long)sb.st_mtime);
+		TEST(stat(tc->pathname ? tc->pathname : TEST_DIR, &sb));
+		tst_res(TPASS, "%2d: utimensat() passed: access time: %lu %lu", i,
+			sb.st_atime, sb.st_mtime);
 	}
 
-	exit(EXIT_SUCCESS);
+	if (dfd != AT_FDCWD)
+		SAFE_CLOSE(dfd);
+
+	if (tc->pathname)
+		SAFE_CLOSE(fd);
+	SAFE_RMDIR(TEST_DIR);
 }
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcase),
+	.setup = setup,
+	.needs_root = 1,
+	.needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/utimensat/utimensat_tests.sh b/testcases/kernel/syscalls/utimensat/utimensat_tests.sh
deleted file mode 100755
index 46a0cc64bf90..000000000000
--- a/testcases/kernel/syscalls/utimensat/utimensat_tests.sh
+++ /dev/null
@@ -1,517 +0,0 @@
-#!/bin/sh
-#
-# Automated tests for utimensat()
-#
-# Copyright (C) 2008, Linux Foundation
-# Written by Michael Kerrisk <mtk.manpages@gmail.com>
-# Licensed under GPLv2 or later
-#
-# Not (yet) included in this automated test set:
-# * AT_SYMLINK_NOFOLLOW in flags: If pathname specifies a symbolic link,
-#   then update the timestamps of the link, rather than the file to which
-#   it refers.
-# * Setting of nanosecond components of timestamps (support for
-#   nanosecond timestamps is file-system-dependent)
-# * "Updated file timestamps are set to the greatest value supported
-#   by the file system that is not greater than the specified time."
-#   (i.e., if we set timestamp to {0, 999999999}, then the setting
-#   is rounded down, rather than up, to unit of timestamp resolution.
-# * Privileged processes should be able to bypass permission checks.
-#   (except when file is marked with the "Immutable" EFA).
-
-#=====================================================================
-
-export TCID=utimensat01
-export TST_TOTAL=99
-export TST_COUNT=0
-. test.sh
-
-if tst_kvcmp -lt "2.6.22"; then
-	tst_brkm TCONF "System kernel version is less than 2.6.22,cannot execute test"
-fi
-
-# Starting with 4.8.0 operations on immutable files return EPERM instead of
-# EACCES.
-# This patch has also been merged to stable 4.4 with
-# b3b4283 ("vfs: move permission checking into notify_change() for utimes(NULL)")
-if tst_kvcmp -ge "4.4.27" -a -lt "4.5.0"; then
-	imaccess=EPERM
-elif tst_kvcmp -lt "4.4.27"; then
-	imaccess=EACCES
-else
-	imaccess=EPERM
-fi
-
-
-RESULT_FILE=$TMPDIR/utimensat.result
-
-TEST_DIR=$TMPDIR/utimensat_tests
-FILE=$TEST_DIR/utimensat.test_file
-
-TEST_PROG=utimensat01
-
-if [ ! -f $LTPROOT/testcases/bin/$TEST_PROG ]; then
-	tst_brkm TBROK "$LTPROOT/testcases/bin/$TEST_PROG is missing (please check install)"
-fi
-
-# Summary counters of all test results
-
-test_num=0
-failed_cnt=0
-passed_cnt=0
-failed_list=""
-
-#=====================================================================
-
-setup_file()
-{
-# $1 is test file pathname
-# $2 is owner for test file (chown(1))
-# $3 is permissions for test file (chmod(1))
-# $4 is "ext2" extended file attributes for test file (chattr(1))
-
-    FILE=$1
-
-    # Make sure any old version of file is deleted
-
-    if test -e $FILE; then
-        sudo $s_arg chattr -ai $FILE || return $?
-        sudo $s_arg rm -f $FILE || return $?
-    fi
-
-    # Create file and make atime and mtime zero.
-
-    sudo $s_arg -u $test_user touch $FILE || return $?
-    if ! $TEST_PROG -q $FILE 0 0 0 0 > $RESULT_FILE; then
-        echo "Failed to set up test file $FILE" 1>&2
-        exit 1
-    fi
-
-    read res atime mtime < $RESULT_FILE
-    if test "X$res" != "XSUCCESS" ||
-                test $atime -ne 0 || test $mtime != 0; then
-        echo "Failed to set correct times on test file $FILE" 1>&2
-        exit 1
-    fi
-
-    # Set owner, permissions, and EFAs for file.
-
-    if test -n "$2"; then
-        sudo $s_arg chown $2 $FILE || return $?
-    fi
-
-    sudo $s_arg chmod $3 $FILE || return $?
-
-    if test -n "$4"; then
-        sudo $s_arg chattr $4 $FILE || return $?
-    fi
-
-    # Display file setup, for visual verification
-
-    ls -l $FILE | awk '{ printf "Owner=%s; perms=%s; ", $3, $1}'
-    if ! sudo $s_arg lsattr -l $FILE | sed 's/, /,/g' | awk '{print "EFAs=" $2}'
-    then
-        return $?
-    fi
-
-}
-
-test_failed()
-{
-    tst_resm TFAIL "FAILED test $test_num"
-
-    failed_cnt=$(expr $failed_cnt + 1)
-    failed_list="$failed_list $test_num"
-}
-
-check_result()
-{
-    STATUS=$1                   # Exit status from test program
-    EXPECTED_RESULT=$2          # SUCCESS / EACCES / EPERM / EINVAL
-    EXPECT_ATIME_CHANGED=$3     # Should be 'y' or 'n' (only for SUCCESS)
-    EXPECT_MTIME_CHANGED=$4     # Should be 'y' or 'n' (only for SUCCESS)
-
-    test_num=$(expr $test_num + 1)
-
-    # If our test setup failed, stop immediately
-
-    if test $STATUS -gt 1; then
-        echo "FAILED (bad test setup)"
-        exit 1
-    fi
-
-    read res atime mtime < $RESULT_FILE
-
-    echo "EXPECTED: $EXPECTED_RESULT $EXPECT_ATIME_CHANGED "\
-         "$EXPECT_MTIME_CHANGED"
-    echo "RESULT:   $res $atime $mtime"
-
-    if test "$res" != "$EXPECTED_RESULT"; then
-        test_failed
-        return
-    fi
-
-    passed=1
-
-    # If the test program exited successfully, then check that atime and
-    # and mtime were updated / not updated, as expected.
-
-    if test $EXPECTED_RESULT = "SUCCESS"; then
-        if test $EXPECT_ATIME_CHANGED = "y"; then
-            if test $atime -eq 0; then
-                echo "atime should have changed, but did not"
-                passed=0
-            fi
-        else
-            if test $atime -ne 0; then
-                echo "atime should not have changed, but did"
-                passed=0
-            fi
-        fi
-
-        if test $EXPECT_MTIME_CHANGED = "y"; then
-            if test $mtime -eq 0; then
-                echo "mtime should have changed, but did not"
-                passed=0
-            fi
-        else
-            if test $mtime -ne 0; then
-                echo "mtime should not have changed, but did"
-                passed=0
-            fi
-        fi
-
-        if test $passed -eq 0; then
-            test_failed
-            return
-        fi
-    fi
-
-    passed_cnt=$(expr $passed_cnt + 1)
-    tst_resm TPASS "PASSED test $test_num"
-}
-
-run_test()
-{
-    # By default, we do three types of test:
-    # a) pathname (pathname != NULL)
-    # b) readable file descriptor (pathname == NULL, dirfd opened O_RDONLY)
-    # c) writable file descriptor (pathname == NULL, dirfd opened O_RDWR).
-    #    For this case we also include O_APPEND in open flags, since that
-    #    is needed if testing with a file that has the Append-only
-    #    attribute enabled.
-
-    # -R says don't do tests with readable file descriptor
-    # -W says don't do tests with writable file descriptor
-
-    OPTIND=1
-
-    do_read_fd_test=1
-    do_write_fd_test=1
-    while getopts "RW" opt; do
-        case "$opt" in
-        R) do_read_fd_test=0
-           ;;
-        W) do_write_fd_test=0
-           ;;
-        *) echo "run_test: bad usage"
-           exit 1
-           ;;
-        esac
-    done
-    shift `expr $OPTIND - 1`
-
-    echo "Pathname test"
-    setup_file $FILE "$1" "$2" "$3"
-    cp $LTPROOT/testcases/bin/$TEST_PROG ./
-    CMD="./$TEST_PROG -q $FILE $4"
-    echo "$CMD"
-    sudo $s_arg -u $test_user $CMD > $RESULT_FILE
-    check_result $? $5 $6 $7
-    echo
-
-    if test $do_read_fd_test -ne 0; then
-        echo "Readable file descriptor (futimens(3)) test"
-        setup_file $FILE "$1" "$2" "$3"
-        CMD="./$TEST_PROG -q -d $FILE NULL $4"
-        echo "$CMD"
-        sudo $s_arg -u $test_user $CMD > $RESULT_FILE
-        check_result $? $5 $6 $7
-        echo
-    fi
-
-    # Can't do the writable file descriptor test for immutable files
-    # (even root can't open an immutable file for writing)
-
-    if test $do_write_fd_test -ne 0; then
-        echo "Writable file descriptor (futimens(3)) test"
-        setup_file $FILE "$1" "$2" "$3"
-        CMD="./$TEST_PROG -q -w -d $FILE NULL $4"
-        echo "$CMD"
-        sudo $s_arg -u $test_user $CMD > $RESULT_FILE
-        check_result $? $5 $6 $7
-        echo
-    fi
-
-    sudo $s_arg chattr -ai $FILE
-    sudo $s_arg rm -f $FILE
-}
-
-#=====================================================================
-
-# Since some automated testing systems have no tty while testing,
-# comment this line in /etc/sudoers to avoid the error message:
-# `sudo: sorry, you must have a tty to run sudo'
-# Use trap to restore this line after program terminates.
-sudoers=/etc/sudoers
-if [ ! -r $sudoers ]; then
-	tst_brkm TBROK "can't read $sudoers"
-fi
-pattern="[[:space:]]*Defaults[[:space:]]*requiretty.*"
-if grep -q "^${pattern}" $sudoers; then
-	tst_resm TINFO "Comment requiretty in $sudoers for automated testing systems"
-	if ! sed -r -i.$$ -e "s/^($pattern)/#\1/" $sudoers; then
-		tst_brkm TBROK "failed to mangle $sudoers properly"
-	fi
-	trap 'trap "" EXIT; restore_sudoers' EXIT
-fi
-
-restore_sudoers()
-{
-	tst_resm TINFO "Restore requiretty in $sudoers"
-	mv /etc/sudoers.$$ /etc/sudoers
-}
-
-test_user=nobody
-echo "test sudo for -n option, non-interactive"
-if sudo -h | grep -q -- -n; then
-	s_arg="-n"
-	echo "sudo supports -n"
-else
-	s_arg=
-	echo "sudo does not support -n"
-fi
-
-if ! sudo $s_arg true; then
-	tst_brkm TBROK "sudo cannot be run by user non-interactively"
-fi
-if test ! -f $sudoers
-then
-	echo "root    ALL=(ALL)    ALL" > $sudoers || exit
-	chmod 440 $sudoers
-	trap 'trap "" EXIT; nuke_sudoers' EXIT
-fi
-
-nuke_sudoers()
-{
-	sudo rm -f $sudoers
-}
-
-sudo $s_arg -u $test_user mkdir -p $TEST_DIR
-
-# Make sure chattr command is supported
-touch $TEST_DIR/tmp_file
-chattr +a $TEST_DIR/tmp_file
-if [ $? -ne 0 ] ; then
-	rm -rf $TEST_DIR
-	tst_brkm TCONF "chattr not supported"
-fi
-chattr -a $TEST_DIR/tmp_file
-
-cd $TEST_DIR
-chown root $LTPROOT/testcases/bin/$TEST_PROG
-chmod ugo+x,u+s $LTPROOT/testcases/bin/$TEST_PROG
-
-#=====================================================================
-
-
-echo "============================================================"
-
-echo
-echo "Testing read-only file, owned by self"
-echo
-
-echo "***** Testing times==NULL case *****"
-run_test -W "" 400 "" "" SUCCESS y y
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_NOW } case *****"
-run_test -W "" 400 "" "0 n 0 n" SUCCESS y y
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_OMIT } case *****"
-run_test -W "" 400 "" "0 o 0 o" SUCCESS n n
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_OMIT } case *****"
-run_test -W "" 400 "" "0 n 0 o" SUCCESS y n
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_NOW } case *****"
-run_test -W "" 400 "" "0 o 0 n" SUCCESS n y
-
-echo "***** Testing times=={ x, y } case *****"
-run_test -W "" 400 "" "1 1 1 1" SUCCESS y y
-
-echo "============================================================"
-
-echo
-echo "Testing read-only file, not owned by self"
-echo
-
-echo "***** Testing times==NULL case *****"
-run_test -RW root 400 "" "" EACCES
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_NOW } case *****"
-run_test -RW root 400 "" "0 n 0 n" EACCES
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_OMIT } case *****"
-run_test -RW root 400 "" "0 o 0 o" SUCCESS n n
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_OMIT } case *****"
-run_test -RW root 400 "" "0 n 0 o" EPERM
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_NOW } case *****"
-run_test -RW root 400 "" "0 o 0 n" EPERM
-
-echo "***** Testing times=={ x, y } case *****"
-run_test -RW root 400 "" "1 1 1 1" EPERM
-
-echo "============================================================"
-
-echo
-echo "Testing writable file, not owned by self"
-echo
-
-echo "***** Testing times==NULL case *****"
-run_test root 666 "" "" SUCCESS y y
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_NOW } case *****"
-run_test root 666 "" "0 n 0 n" SUCCESS y y
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_OMIT } case *****"
-run_test root 666 "" "0 o 0 o" SUCCESS n n
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_OMIT } case *****"
-run_test root 666 "" "0 n 0 o" EPERM
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_NOW } case *****"
-run_test root 666 "" "0 o 0 n" EPERM
-
-echo "***** Testing times=={ x, y } case *****"
-run_test root 666 "" "1 1 1 1" EPERM
-
-echo "============================================================"
-
-echo
-echo "Testing append-only file, owned by self"
-echo
-
-echo "***** Testing times==NULL case *****"
-run_test "" 600 "+a" "" SUCCESS y y
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_NOW } case *****"
-run_test "" 600 "+a" "0 n 0 n" SUCCESS y y
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_OMIT } case *****"
-run_test "" 600 "+a" "0 o 0 o" SUCCESS n n
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_OMIT } case *****"
-run_test "" 600 "+a" "0 n 0 o" EPERM
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_NOW } case *****"
-run_test "" 600 "+a" "0 o 0 n" EPERM
-
-echo "***** Testing times=={ x, y } case *****"
-run_test "" 600 "+a" "1 1 1 1" EPERM
-
-echo "============================================================"
-
-echo
-echo "Testing immutable file, owned by self"
-echo
-
-echo "***** Testing times==NULL case *****"
-run_test -W "" 600 "+i" "" $imaccess
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_NOW } case *****"
-run_test -W "" 600 "+i" "0 n 0 n" $imaccess
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_OMIT } case *****"
-run_test -W "" 600 "+i" "0 o 0 o" SUCCESS n n
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_OMIT } case *****"
-run_test -W "" 600 "+i" "0 n 0 o" EPERM
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_NOW } case *****"
-run_test -W "" 600 "+i" "0 o 0 n" EPERM
-
-echo "***** Testing times=={ x, y } case *****"
-run_test -W "" 600 "+i" "1 1 1 1" EPERM
-
-echo "============================================================"
-
-# Immutable+append-only should have same results as immutable
-
-echo
-echo "Testing immutable append-only file, owned by self"
-echo
-
-echo "***** Testing times==NULL case *****"
-run_test -W "" 600 "+ai" "" $imaccess
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_NOW } case *****"
-run_test -W "" 600 "+ai" "0 n 0 n" $imaccess
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_OMIT } case *****"
-run_test -W "" 600 "+ai" "0 o 0 o" SUCCESS n n
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_OMIT } case *****"
-run_test -W "" 600 "+ai" "0 n 0 o" EPERM
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_NOW } case *****"
-run_test -W "" 600 "+ai" "0 o 0 n" EPERM
-
-echo "***** Testing times=={ x, y } case *****"
-run_test -W "" 600 "+ai" "1 1 1 1" EPERM
-
-echo "============================================================"
-
-echo
-
-# EINVAL should result, if pathname is NULL, dirfd is not
-# AT_FDCWD, and flags contains AT_SYMLINK_NOFOLLOW.
-
-echo "***** Testing pathname==NULL, dirfd!=AT_FDCWD, flags has" \
-     "AT_SYMLINK_NOFOLLOW *****"
-setup_file $FILE "" 600 ""
-CMD="$TEST_PROG -q -n -d $FILE NULL $4"
-echo "$CMD"
-$CMD > $RESULT_FILE
-check_result $? EINVAL
-echo
-
-echo "============================================================"
-
-echo
-
-# If UTIME_NOW / UTIME_OMIT in tv_nsec field, the tv_sec should
-# be ignored.
-
-echo "tv_sec should be ignored if tv_nsec is UTIME_OMIT or UTIME_NOW"
-
-echo "***** Testing times=={ UTIME_NOW, UTIME_NOW } case *****"
-run_test -RW "" 600 "" "1 n 1 n" SUCCESS y y
-
-echo "***** Testing times=={ UTIME_OMIT, UTIME_OMIT } case *****"
-run_test -RW "" 600 "" "1 o 1 o" SUCCESS n n
-
-echo "============================================================"
-
-echo
-
-rm -rf "$TEST_DIR"
-uname -a
-date
-echo "Total tests: $test_num; passed: $passed_cnt; failed: $failed_cnt"
-if test $failed_cnt -gt 0; then
-    echo "Failed tests: $failed_list"
-fi
-
-tst_exit
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 18/19] syscalls/utimensat: Add support for time64 tests
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (16 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 17/19] syscalls/utimensat: Migrate to new test framework Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-06-26  6:22 ` [LTP] [PATCH V7 19/19] syscalls: clock_settime: Add test around y2038 vulnerability Viresh Kumar
  2020-07-20 10:19 ` [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
  19 siblings, 0 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing utimensat() syscall
tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 runtest/syscalls                              |  2 +-
 testcases/kernel/syscalls/utimensat/Makefile  |  4 -
 .../kernel/syscalls/utimensat/utimensat01.c   | 74 ++++++++++++++++---
 3 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/runtest/syscalls b/runtest/syscalls
index 5b3a0862faea..2d2e24615be6 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1607,7 +1607,7 @@ utime06 utime06
 utimes01 utimes01
 
 # Introduced from Kernel 2.6.22 onwards
-utimensat01 utimensat_tests.sh
+utimensat01 utimensat01
 
 vfork01 vfork01
 vfork02 vfork02
diff --git a/testcases/kernel/syscalls/utimensat/Makefile b/testcases/kernel/syscalls/utimensat/Makefile
index 69cab8dbc057..044619fb8724 100644
--- a/testcases/kernel/syscalls/utimensat/Makefile
+++ b/testcases/kernel/syscalls/utimensat/Makefile
@@ -5,8 +5,4 @@ top_srcdir		?= ../../../..
 
 include $(top_srcdir)/include/mk/testcases.mk
 
-vpath %.c $(srcdir):$(top_srcdir)/lib
-
-INSTALL_TARGETS		:= utimensat_tests.sh
-
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/utimensat/utimensat01.c b/testcases/kernel/syscalls/utimensat/utimensat01.c
index 97a43713454f..0139d6ddfedf 100644
--- a/testcases/kernel/syscalls/utimensat/utimensat01.c
+++ b/testcases/kernel/syscalls/utimensat/utimensat01.c
@@ -16,8 +16,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include "lapi/fs.h"
-#include "tst_test.h"
-#include "lapi/syscalls.h"
+#include "tst_timer.h"
 
 #define UTIME_NOW	((1l << 30) - 1l)
 #define UTIME_OMIT	((1l << 30) - 2l)
@@ -98,13 +97,68 @@ struct test_case {
 };
 
 static inline int sys_utimensat(int dirfd, const char *pathname,
-				const struct timespec times[2], int flags)
+				void *times, int flags)
 {
 	return tst_syscall(__NR_utimensat, dirfd, pathname, times, flags);
 }
 
+static inline int sys_utimensat_time64(int dirfd, const char *pathname,
+				       void *times, int flags)
+{
+	return tst_syscall(__NR_utimensat_time64, dirfd, pathname, times, flags);
+}
+
+static struct test_variants {
+	int (*utimensat)(int dirfd, const char *pathname, void *times,
+			 int flags);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_utimensat != __LTP__NR_INVALID_SYSCALL)
+	{ .utimensat = sys_utimensat, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_utimensat_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .utimensat = sys_utimensat_time64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+union tst_multi {
+	struct timespec libc_ts[2];
+	struct __kernel_old_timespec kern_old_ts[2];
+	struct __kernel_timespec kern_ts[2];
+} ts;
+
+static void tst_multi_set_time(enum tst_ts_type type, long access_tv_sec,
+			long access_tv_nsec, long mod_tv_sec, long mod_tv_nsec)
+{
+	switch (type) {
+	case TST_LIBC_TIMESPEC:
+		ts.libc_ts[0].tv_sec = access_tv_sec;
+		ts.libc_ts[0].tv_nsec = access_tv_nsec;
+		ts.libc_ts[1].tv_sec = mod_tv_sec;
+		ts.libc_ts[1].tv_nsec = mod_tv_nsec;
+		break;
+	case TST_KERN_OLD_TIMESPEC:
+		ts.kern_old_ts[0].tv_sec = access_tv_sec;
+		ts.kern_old_ts[0].tv_nsec = access_tv_nsec;
+		ts.kern_old_ts[1].tv_sec = mod_tv_sec;
+		ts.kern_old_ts[1].tv_nsec = mod_tv_nsec;
+		break;
+	case TST_KERN_TIMESPEC:
+		ts.kern_ts[0].tv_sec = access_tv_sec;
+		ts.kern_ts[0].tv_nsec = access_tv_nsec;
+		ts.kern_ts[1].tv_sec = mod_tv_sec;
+		ts.kern_ts[1].tv_nsec = mod_tv_nsec;
+		break;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", type);
+	}
+}
+
 static void setup(void)
 {
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
 	bad_addr = tst_get_bad_addr(NULL);
 }
 
@@ -144,8 +198,8 @@ static void change_attr(struct test_case *tc, int fd, int set)
 
 static void run(unsigned int i)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	struct test_case *tc = &tcase[i];
-	struct timespec ts[2];
 	void *tsp = NULL;
 	char *pathname = NULL;
 	int dfd = AT_FDCWD, fd = 0;
@@ -160,11 +214,10 @@ static void run(unsigned int i)
 	if (tc->mytime) {
 		struct mytime *mytime = *tc->mytime;
 
-		ts[0].tv_sec = mytime->access_tv_sec;
-		ts[0].tv_nsec = mytime->access_tv_nsec;
-		ts[1].tv_sec = mytime->mod_tv_sec;
-		ts[1].tv_nsec = mytime->mod_tv_nsec;
-		tsp = ts;
+		tst_multi_set_time(tv->type, mytime->access_tv_sec,
+				   mytime->access_tv_nsec, mytime->mod_tv_sec,
+				   mytime->mod_tv_nsec);
+		tsp = &ts.libc_ts;
 	} else if (tc->exp_err == EFAULT) {
 		tsp = bad_addr;
 	}
@@ -178,7 +231,7 @@ static void run(unsigned int i)
 		pathname = bad_addr;
 	}
 
-	TEST(sys_utimensat(dfd, pathname, tsp, tc->flags));
+	TEST(tv->utimensat(dfd, pathname, tsp, tc->flags));
 	if (tc->pathname)
 		change_attr(tc, fd, 0);
 
@@ -210,6 +263,7 @@ static void run(unsigned int i)
 static struct tst_test test = {
 	.test = run,
 	.tcnt = ARRAY_SIZE(tcase),
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.needs_root = 1,
 	.needs_tmpdir = 1,
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 19/19] syscalls: clock_settime: Add test around y2038 vulnerability
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (17 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 18/19] syscalls/utimensat: Add support for time64 tests Viresh Kumar
@ 2020-06-26  6:22 ` Viresh Kumar
  2020-07-28 12:11   ` Cyril Hrubis
  2020-07-20 10:19 ` [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-06-26  6:22 UTC (permalink / raw)
  To: ltp

This adds a test around the y2038 vulnerability, it sets the system time
to just before y2038 time (i.e. max value that can be stored in s32),
and adds a timer to expire just after crossing it.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 runtest/syscalls                              |   1 +
 .../kernel/syscalls/clock_settime/.gitignore  |   1 +
 .../syscalls/clock_settime/clock_settime03.c  | 119 ++++++++++++++++++
 3 files changed, 121 insertions(+)
 create mode 100644 testcases/kernel/syscalls/clock_settime/clock_settime03.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 2d2e24615be6..718ac1148392 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -101,6 +101,7 @@ leapsec01 leapsec01
 
 clock_settime01 clock_settime01
 clock_settime02 clock_settime02
+clock_settime03 clock_settime03
 
 clone01 clone01
 clone02 clone02
diff --git a/testcases/kernel/syscalls/clock_settime/.gitignore b/testcases/kernel/syscalls/clock_settime/.gitignore
index 28121755006b..b66169b3eb7b 100644
--- a/testcases/kernel/syscalls/clock_settime/.gitignore
+++ b/testcases/kernel/syscalls/clock_settime/.gitignore
@@ -1,2 +1,3 @@
 clock_settime01
 clock_settime02
+clock_settime03
diff --git a/testcases/kernel/syscalls/clock_settime/clock_settime03.c b/testcases/kernel/syscalls/clock_settime/clock_settime03.c
new file mode 100644
index 000000000000..7245863137b5
--- /dev/null
+++ b/testcases/kernel/syscalls/clock_settime/clock_settime03.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 Linaro Limited. All rights reserved.
+ * Author: Viresh Kumar<viresh.kumar@linaro.org>
+ *
+ * Check Year 2038 related vulnerabilities.
+ */
+
+#include <signal.h>
+#include "config.h"
+#include "tst_timer.h"
+#include "tst_safe_clocks.h"
+
+#define TIMER_DELTA	3
+#define ALLOWED_DELTA	(50 * 1000) /* 50 ms */
+
+static struct tst_ts start, end;
+static struct tst_its its;
+
+static struct test_variants {
+	int (*clock_gettime)(clockid_t clk_id, void *ts);
+	int (*clock_settime)(clockid_t clk_id, void *ts);
+	int (*timer_settime)(timer_t timerid, int flags, void *its,
+			     void *old_its);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_clock_settime != __LTP__NR_INVALID_SYSCALL)
+	{ .clock_gettime = sys_clock_gettime, .clock_settime = sys_clock_settime, .timer_settime = sys_timer_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_clock_settime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .clock_gettime = sys_clock_gettime64, .clock_settime = sys_clock_settime64, .timer_settime = sys_timer_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static void setup(void)
+{
+	struct test_variants *tv = &variants[tst_variant];
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	start.type = end.type = its.type = tv->type;
+
+	/* Check if the kernel is y2038 safe */
+	if (tv->type != TST_KERN_OLD_TIMESPEC &&
+	    sizeof(start.ts.kern_old_ts) == 8)
+		tst_brk(TFAIL, "Not Y2038 safe to run test");
+}
+
+static void run(void)
+{
+	struct test_variants *tv = &variants[tst_variant];
+	unsigned long long time = 0x7FFFFFFE; /* Time just before y2038 */
+	struct sigevent ev = {
+		.sigev_notify = SIGEV_SIGNAL,
+		.sigev_signo = SIGABRT,
+	};
+	long long diff;
+	timer_t timer;
+	sigset_t set;
+	int sig, ret;
+
+	if (sigemptyset(&set) == -1)
+		tst_brk(TBROK, "sigemptyset() failed");
+
+	if (sigaddset(&set, SIGABRT) == -1)
+		tst_brk(TBROK, "sigaddset() failed");
+
+	if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
+		tst_brk(TBROK, "sigprocmask() failed");
+
+	TEST(tst_syscall(__NR_timer_create, CLOCK_REALTIME_ALARM, &ev, &timer));
+	if (TST_RET != 0)
+		tst_brk(TBROK | TERRNO, "timer_create() failed");
+
+	tst_ts_set_sec(&start, time);
+	tst_ts_set_nsec(&start, 0);
+
+	ret = tv->clock_settime(CLOCK_REALTIME, tst_ts_get(&start));
+	if (ret == -1)
+		tst_brk(TBROK | TERRNO, "clock_settime() failed");
+
+	tst_its_set_interval_sec(&its, 0);
+	tst_its_set_interval_nsec(&its, 0);
+	tst_its_set_value_sec(&its, time + TIMER_DELTA);
+	tst_its_set_value_nsec(&its, 0);
+
+	TEST(tv->timer_settime(timer, TIMER_ABSTIME, tst_its_get(&its), NULL));
+	if (TST_RET == -1)
+		tst_brk(TBROK | TTERRNO, "timer_settime() failed");
+
+	if (sigwait(&set, &sig) == -1)
+		tst_brk(TBROK, "sigwait() failed");
+
+	ret = tv->clock_gettime(CLOCK_REALTIME, tst_ts_get(&end));
+	if (ret == -1)
+		tst_brk(TBROK | TERRNO, "clock_gettime() failed");
+
+	if (sig == SIGABRT) {
+		diff = tst_ts_diff_ms(end, start);
+
+		if (diff < TIMER_DELTA * 1000 - ALLOWED_DELTA ||
+		    diff > TIMER_DELTA * 1000 + ALLOWED_DELTA)
+			tst_res(TINFO, "Slept for unexpected duration, expected:%d, actual:%lld",
+				TIMER_DELTA * 1000, diff);
+		tst_res(TPASS, "clock_settime(): Y2038 test passed");
+		return;
+	}
+
+	tst_res(TFAIL, "clock_settime(): Y2038 test failed");
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
+	.needs_root = 1,
+	.restore_wallclock = 1,
+};
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 01/19] tst_timer: Add new definitions
  2020-06-26  6:22 ` [LTP] [PATCH V7 01/19] tst_timer: Add new definitions Viresh Kumar
@ 2020-06-26  9:49   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-06-26  9:49 UTC (permalink / raw)
  To: ltp

Hi!
Pushed, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 02/19] syscalls/timer_gettime: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 02/19] syscalls/timer_gettime: Add support for time64 tests Viresh Kumar
@ 2020-06-26  9:49   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-06-26  9:49 UTC (permalink / raw)
  To: ltp

Hi!
Pushed, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 03/19] syscalls/timer_settime: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 03/19] syscalls/timer_settime: " Viresh Kumar
@ 2020-06-29  9:39   ` Cyril Hrubis
  2020-06-29 11:43     ` Viresh Kumar
  0 siblings, 1 reply; 64+ messages in thread
From: Cyril Hrubis @ 2020-06-29  9:39 UTC (permalink / raw)
  To: ltp

Hi!
Pushed with a minor change, thanks.

Added cast to (timer_t) to the -1 to avoid warnings.

Also if you are not burned out writing timer testcases and still willing
to spend a bit of time none of the timer tests actually check that the
timer fires. I guess that it would be easy to add the check that reads
back the itmierspec, checks that the value is sane and also waits for
singnal or two to the timer_settime01.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 03/19] syscalls/timer_settime: Add support for time64 tests
  2020-06-29  9:39   ` Cyril Hrubis
@ 2020-06-29 11:43     ` Viresh Kumar
  0 siblings, 0 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-06-29 11:43 UTC (permalink / raw)
  To: ltp

On 29-06-20, 11:39, Cyril Hrubis wrote:
> Hi!
> Pushed with a minor change, thanks.
> 
> Added cast to (timer_t) to the -1 to avoid warnings.
> 
> Also if you are not burned out writing timer testcases and still willing
> to spend a bit of time none of the timer tests actually check that the
> timer fires. I guess that it would be easy to add the check that reads
> back the itmierspec, checks that the value is sane and also waits for
> singnal or two to the timer_settime01.

Done and sent.

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 04/19] syscalls/timerfd: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 04/19] syscalls/timerfd: " Viresh Kumar
@ 2020-07-02 12:24   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-02 12:24 UTC (permalink / raw)
  To: ltp

Hi!
Pushed with minor changes, thanks.

I've added a few more tst_its helpers and made use of them in the test
to make the code a bit more readable.

Also I've removed one useless TCID from newlib tests and added a few
missing TERRNOs.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 05/19] syscalls/sched_rr_get_interval: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 05/19] syscalls/sched_rr_get_interval: " Viresh Kumar
@ 2020-07-02 13:06   ` Cyril Hrubis
  2020-07-03  3:15     ` Viresh Kumar
  2020-07-03  7:38   ` [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice Viresh Kumar
  1 sibling, 1 reply; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-02 13:06 UTC (permalink / raw)
  To: ltp

Hi!
I've did some further cleanup and pushed, thanks.

Btw, we may as well add a check that the value is consistent with
/proc/sys/kernel/sched_rr_timeslice_ms.

I've mostly removed useless comments, etc. but also added a sanity check for
the time quantum timespec. See:

diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
index 9bad698aa..31d7b5d56 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
@@ -1,53 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
- *
- *    TEST IDENTIFIER	: sched_rr_get_interval01
- *
- *    EXECUTED BY	: root / superuser
- *
- *    TEST TITLE	: Basic test for sched_rr_get_interval(2)
- *
- *    TEST CASE TOTAL	: 1
- *
  *    AUTHOR		: Saji Kumar.V.R <saji.kumar@wipro.com>
  *
- *    SIGNALS
- *	Uses SIGUSR1 to pause before test if option set.
- *	(See the parse_opts(3) man page).
- *
- *    DESCRIPTION
- *	This is a Phase I test for the sched_rr_get_interval(2) system call.
- *	It is intended to provide a limited exposure of the system call.
- *
- *	Setup:
- *	  Setup signal handling.
- *	  Pause for SIGUSR1 if option specified.
- *	  Change scheduling policy to SCHED_RR
- *
- *	Test:
- *	 Loop if the proper options are given.
- *	  Execute system call
- *	  Check return code, if it is 0,
- *		Test passed.
- *	  Otherwise
- *		Test failed
- *
- *	Cleanup:
- *	  Print errno log and/or timing stats if options given
- *
- * USAGE:  <for command-line>
- * sched_rr_get_interval01 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-h] [-f] [-p]
- *			where,  -c n : Run n copies concurrently.
- *				-e   : Turn on errno logging.
- *				-h   : Show help screen
- *				-f   : Turn off functional testing
- *				-i n : Execute test n times.
- *				-I x : Execute test for x seconds.
- *				-p   : Pause for SIGUSR1 before starting
- *				-P x : Pause for x seconds between iterations.
- *				-t   : Turn on syscall timing.
- *
+ * Gets round-robin time quantum by calling sched_rr_get_interval() and
+ * checks that the value is sane.
  */
 
 #include <sched.h>
@@ -74,17 +31,12 @@ static struct test_variants {
 static void setup(void)
 {
 	struct test_variants *tv = &variants[tst_variant];
-	/*
-	 * Initialize scheduling parameter structure to use with
-	 * sched_setscheduler()
-	 */
 	struct sched_param p = { 1 };
 
 	tst_res(TINFO, "Testing variant: %s", tv->desc);
 
 	tp.type = tv->type;
 
-	/* Change scheduling policy to SCHED_RR */
 	if ((sched_setscheduler(0, SCHED_RR, &p)) == -1)
 		tst_res(TFAIL | TTERRNO, "sched_setscheduler() failed");
 }
@@ -93,11 +45,6 @@ static void run(void)
 {
 	struct test_variants *tv = &variants[tst_variant];
 
-	/*
-	 * Call sched_rr_get_interval(2) with pid=0 so that it will
-	 * write into the timespec structure pointed to by tp, the
-	 * round robin time quantum for the current process.
-	 */
 	TEST(tv->func(0, tst_ts_get(&tp)));
 
 	if (!TST_RET) {
@@ -106,6 +53,15 @@ static void run(void)
 		tst_res(TFAIL | TTERRNO, "Test Failed, sched_rr_get_interval() returned %ld",
 			TST_RET);
 	}
+
+	if (!tst_ts_valid(&tp)) {
+		tst_res(TPASS, "Time quantum %llis %llins",
+		        tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
+	} else {
+		tst_res(TFAIL, "Invalid time quantum %llis %llins",
+		        tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
+	}
+
 }
 
 static struct tst_test test = {
diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c
index 8da42e974..5b38e5bff 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c
@@ -1,60 +1,17 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
- *
- *    TEST IDENTIFIER	: sched_rr_get_interval02
- *
- *    EXECUTED BY	: root / superuser
- *
- *    TEST TITLE	: Functionality test
- *
- *    TEST CASE TOTAL	: 1
- *
  *    AUTHOR		: Saji Kumar.V.R <saji.kumar@wipro.com>
  *
- *    SIGNALS
- *	Uses SIGUSR1 to pause before test if option set.
- *	(See the parse_opts(3) man page).
- *
- *    DESCRIPTION
- *	Verify that for a process with scheduling policy SCHED_FIFO,
- *	sched_rr_get_interval() writes zero into timespec structure
- *	for tv_sec & tv_nsec.
- *
- *	Setup:
- *	  Setup signal handling.
- *	  Pause for SIGUSR1 if option specified.
- *	  Change scheduling policy to SCHED_FIFO
- *
- *	Test:
- *	 Loop if the proper options are given.
- *	  Execute system call
- *	  Check (return code == 0) & (got 0 for tv_sec & tv_nsec )
- *		Test passed.
- *	  Otherwise
- *		Test failed
- *
- *	Cleanup:
- *	  Print errno log and/or timing stats if options given
- *
- * USAGE:  <for command-line>
- * sched_rr_get_interval02 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-h] [-f] [-p]
- *			where,  -c n : Run n copies concurrently.
- *				-e   : Turn on errno logging.
- *				-h   : Show help screen
- *				-f   : Turn off functional testing
- *				-i n : Execute test n times.
- *				-I x : Execute test for x seconds.
- *				-p   : Pause for SIGUSR1 before starting
- *				-P x : Pause for x seconds between iterations.
- *				-t   : Turn on syscall timing.
- *
+ * Verify that for a process with scheduling policy SCHED_FIFO,
+ * sched_rr_get_interval() writes zero into timespec structure
+ * for tv_sec & tv_nsec.
  */
 
 #include <sched.h>
 #include "tst_timer.h"
 
-struct tst_ts tp;
+static struct tst_ts tp;
 
 static struct test_variants {
 	int (*func)(pid_t pid, void *ts);
@@ -75,17 +32,12 @@ static struct test_variants {
 static void setup(void)
 {
 	struct test_variants *tv = &variants[tst_variant];
-	/*
-	 * Initialize scheduling parameter structure to use with
-	 * sched_setscheduler()
-	 */
 	struct sched_param p = { 1 };
 
 	tst_res(TINFO, "Testing variant: %s", tv->desc);
 
 	tp.type = tv->type;
 
-	/* Change scheduling policy to SCHED_FIFO */
 	if ((sched_setscheduler(0, SCHED_FIFO, &p)) == -1)
 		tst_res(TFAIL | TTERRNO, "sched_setscheduler() failed");
 }
@@ -97,17 +49,13 @@ static void run(void)
 	tst_ts_set_sec(&tp, 99);
 	tst_ts_set_nsec(&tp, 99);
 
-	/*
-	 * Call sched_rr_get_interval(2) with pid=0 so that it will
-	 * write into the timespec structure pointed to by tp the
-	 * round robin time quantum for the current process.
-	 */
 	TEST(tv->func(0, tst_ts_get(&tp)));
 
 	if (!TST_RET && tst_ts_valid(&tp) == -1) {
 		tst_res(TPASS, "sched_rr_get_interval() passed");
 	} else {
-		tst_res(TFAIL | TTERRNO, "Test Failed, sched_rr_get_interval() returned %ld, tp.tv_sec = %lld, tp.tv_nsec = %lld",
+		tst_res(TFAIL | TTERRNO,
+			"sched_rr_get_interval() returned %ld, tp.tv_sec = %lld, tp.tv_nsec = %lld",
 			TST_RET, tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
 	}
 }
diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c
index 0ccf47d2a..d7bbe2686 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c
@@ -1,59 +1,15 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
- *
- *    TEST IDENTIFIER	: sched_rr_get_interval03
- *
- *    EXECUTED BY	: root / superuser
- *
- *    TEST TITLE	: Tests for error conditions
- *
- *    TEST CASE TOTAL	: 3
- *
  *    AUTHOR		: Saji Kumar.V.R <saji.kumar@wipro.com>
  *
- *    SIGNALS
- *	Uses SIGUSR1 to pause before test if option set.
- *	(See the parse_opts(3) man page).
- *
- *    DESCRIPTION
- *	Verify that
- *	1) sched_rr_get_interval() fails with errno set to EINVAL for an
- *	   invalid pid
- *	2) sched_rr_get_interval() fails with errno set to ESRCH if the
- *	   process with specified pid does not exists
- *	2) sched_rr_get_interval() fails with errno set to EFAULT if the
- *	   address specified as &tp is invalid
- *
- *	Setup:
- *	  Setup signal handling.
- *	  Set expected errors for logging.
- *	  Pause for SIGUSR1 if option specified.
- *	  Change scheduling policy to SCHED_RR
- *
- *	Test:
- *	 Loop if the proper options are given.
- *	  Execute system call
- *	  if call fails with expected errno,
- *		Test passed.
- *	  Otherwise
- *		Test failed
- *
- *	Cleanup:
- *	  Print errno log and/or timing stats if options given
- *
- * USAGE:  <for command-line>
- * sched_rr_get_interval03 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-h] [-f] [-p]
- *			where,  -c n : Run n copies concurrently.
- *				-e   : Turn on errno logging.
- *				-h   : Show help screen
- *				-f   : Turn off functional testing
- *				-i n : Execute test n times.
- *				-I x : Execute test for x seconds.
- *				-p   : Pause for SIGUSR1 before starting
- *				-P x : Pause for x seconds between iterations.
- *				-t   : Turn on syscall timing.
- *
+ * Verify that
+ *  1) sched_rr_get_interval() fails with errno set to EINVAL for an
+ *     invalid pid
+ *  2) sched_rr_get_interval() fails with errno set to ESRCH if the
+ *     process with specified pid does not exists
+ *  3) sched_rr_get_interval() fails with errno set to EFAULT if the
+ *     address specified as &tp is invalid
  */
 
 #include <sched.h>
@@ -63,7 +19,7 @@ static pid_t unused_pid;
 static pid_t inval_pid = -1;
 static pid_t zero_pid;
 
-struct tst_ts tp;
+static struct tst_ts tp;
 static void *bad_addr;
 
 struct test_cases_t {
@@ -73,10 +29,7 @@ struct test_cases_t {
 } test_cases[] = {
 	{ &inval_pid, &tp, EINVAL},
 	{ &unused_pid, &tp, ESRCH},
-#ifndef UCLINUX
-	/* Skip since uClinux does not implement memory protection */
 	{ &zero_pid, NULL, EFAULT}
-#endif
 };
 
 static struct test_variants {
@@ -98,10 +51,6 @@ static struct test_variants {
 static void setup(void)
 {
 	struct test_variants *tv = &variants[tst_variant];
-	/*
-	 * Initialize scheduling parameter structure to use with
-	 * sched_setscheduler()
-	 */
 	struct sched_param p = { 1 };
 
 	tst_res(TINFO, "Testing variant: %s", tv->desc);
@@ -109,7 +58,6 @@ static void setup(void)
 	bad_addr = tst_get_bad_addr(NULL);
 	tp.type = tv->type;
 
-	/* Change scheduling policy to SCHED_RR */
 	if ((sched_setscheduler(0, SCHED_RR, &p)) == -1)
 		tst_res(TFAIL | TTERRNO, "sched_setscheduler() failed");
 
@@ -127,9 +75,6 @@ static void run(unsigned int i)
 	else
 		ts = tst_ts_get(tc->tp);
 
-	/*
-	 * Call sched_rr_get_interval(2)
-	 */
 	TEST(tv->func(*tc->pid, ts));
 
 	if (TST_RET != -1) {

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 05/19] syscalls/sched_rr_get_interval: Add support for time64 tests
  2020-07-02 13:06   ` Cyril Hrubis
@ 2020-07-03  3:15     ` Viresh Kumar
  2020-07-03  5:52       ` Yang Xu
  0 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-07-03  3:15 UTC (permalink / raw)
  To: ltp

On 02-07-20, 15:06, Cyril Hrubis wrote:
> Btw, we may as well add a check that the value is consistent with
> /proc/sys/kernel/sched_rr_timeslice_ms.

diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
index 31d7b5d56a52..0641b6651502 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
@@ -44,6 +44,7 @@ static void setup(void)
 static void run(void)
 {
        struct test_variants *tv = &variants[tst_variant];
+       unsigned long long timeslice_ms;
 
        TEST(tv->func(0, tst_ts_get(&tp)));
 
@@ -54,6 +55,8 @@ static void run(void)
                        TST_RET);
        }
 
+       SAFE_FILE_SCANF("/proc/sys/kernel/sched_rr_timeslice_ms", "%llu", &timeslice_ms);
+
        if (!tst_ts_valid(&tp)) {
                tst_res(TPASS, "Time quantum %llis %llins",
                        tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
@@ -62,6 +65,7 @@ static void run(void)
                        tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
        }
 
+       tst_res(TINFO, "%llu: %llu", timeslice_ms, tst_ts_to_ms(tp));
 }
 
 static struct tst_test test = {



and it is coming as:

sched_rr_get_interval01.c:68: INFO: 25: 100

They aren't consistent here. Perhaps because first one is system wide
while other one is per process ?

-- 
viresh

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 05/19] syscalls/sched_rr_get_interval: Add support for time64 tests
  2020-07-03  3:15     ` Viresh Kumar
@ 2020-07-03  5:52       ` Yang Xu
  2020-07-03  7:26         ` Viresh Kumar
  0 siblings, 1 reply; 64+ messages in thread
From: Yang Xu @ 2020-07-03  5:52 UTC (permalink / raw)
  To: ltp

Hi Viresh

> On 02-07-20, 15:06, Cyril Hrubis wrote:
>> Btw, we may as well add a check that the value is consistent with
>> /proc/sys/kernel/sched_rr_timeslice_ms.

I guess cyril may want to add a check using TST_ASSERT_INT api like this

TST_ASSERT_INT("/proc/sys/kernel/sched_rr_timeslice_ms", tst_ts_to_ms(tp));

> diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> index 31d7b5d56a52..0641b6651502 100644
> --- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> +++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> @@ -44,6 +44,7 @@ static void setup(void)
>   static void run(void)
>   {
>          struct test_variants *tv = &variants[tst_variant];
> +       unsigned long long timeslice_ms;
>   
>          TEST(tv->func(0, tst_ts_get(&tp)));
>   
> @@ -54,6 +55,8 @@ static void run(void)
>                          TST_RET);
>          }
>   
> +       SAFE_FILE_SCANF("/proc/sys/kernel/sched_rr_timeslice_ms", "%llu", &timeslice_ms);
> +
>          if (!tst_ts_valid(&tp)) {
>                  tst_res(TPASS, "Time quantum %llis %llins",
>                          tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
> @@ -62,6 +65,7 @@ static void run(void)
>                          tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
>          }
>   
> +       tst_res(TINFO, "%llu: %llu", timeslice_ms, tst_ts_to_ms(tp));
>   }
>   
>   static struct tst_test test = {
>
>
>
> and it is coming as:
>
> sched_rr_get_interval01.c:68: INFO: 25: 100
>
> They aren't consistent here. Perhaps because first one is system wide
> while other one is per process ?

It is strange.
On my machine, the two values are all 100. AFAIK, it has a bug (set in milliseconds but the result is shown in jiffies.) on old kernel whenCONFIG_HZ is not 1000. what kernel version do you test?
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=975e155ed8732cb81f55c021c441ae662dd040b5

>


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linux.it/pipermail/ltp/attachments/20200703/d6b8e72a/attachment.htm>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 05/19] syscalls/sched_rr_get_interval: Add support for time64 tests
  2020-07-03  5:52       ` Yang Xu
@ 2020-07-03  7:26         ` Viresh Kumar
  0 siblings, 0 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-07-03  7:26 UTC (permalink / raw)
  To: ltp

On 03-07-20, 13:52, Yang Xu wrote:
> Hi Viresh
> 
> > On 02-07-20, 15:06, Cyril Hrubis wrote:
> > > Btw, we may as well add a check that the value is consistent with
> > > /proc/sys/kernel/sched_rr_timeslice_ms.
> 
> I guess cyril may want to add a check using TST_ASSERT_INT api like this
> 
> TST_ASSERT_INT("/proc/sys/kernel/sched_rr_timeslice_ms", tst_ts_to_ms(tp));
> 
> It is strange.
> On my machine, the two values are all 100. AFAIK, it has a bug (set in milliseconds but the result is shown in jiffies.) on old kernel whenCONFIG_HZ is not 1000. what kernel version do you test?

I am running an old kernel (4.4) and with 250 CONFIG_HZ.

> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=975e155ed8732cb81f55c021c441ae662dd040b5

I sent it to get included in stable kernels now.

https://lore.kernel.org/lkml/ffdfb849a11b9cd66e0aded2161869e36aec7fc0.1593757471.git.viresh.kumar@linaro.org/

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice
  2020-06-26  6:22 ` [LTP] [PATCH V7 05/19] syscalls/sched_rr_get_interval: " Viresh Kumar
  2020-07-02 13:06   ` Cyril Hrubis
@ 2020-07-03  7:38   ` Viresh Kumar
  2020-07-03  7:43     ` Yang Xu
                       ` (2 more replies)
  1 sibling, 3 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-07-03  7:38 UTC (permalink / raw)
  To: ltp

Validate the timespec returned by sched_rr_get_interval() against the
value read from /proc/sys/kernel/sched_rr_timeslice_ms.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../syscalls/sched_rr_get_interval/sched_rr_get_interval01.c     | 1 +
 1 file changed, 1 insertion(+)

diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
index 31d7b5d56a52..f358c91ac505 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
@@ -62,6 +62,7 @@ static void run(void)
 		        tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
 	}
 
+	TST_ASSERT_INT("/proc/sys/kernel/sched_rr_timeslice_ms", tst_ts_to_ms(tp));
 }
 
 static struct tst_test test = {
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice
  2020-07-03  7:38   ` [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice Viresh Kumar
@ 2020-07-03  7:43     ` Yang Xu
  2020-07-03  7:51       ` Viresh Kumar
  2020-07-03 14:08     ` Cyril Hrubis
  2020-07-06  3:31     ` [LTP] [PATCH V2] " Viresh Kumar
  2 siblings, 1 reply; 64+ messages in thread
From: Yang Xu @ 2020-07-03  7:43 UTC (permalink / raw)
  To: ltp

Hi Viresh

Can we add a linux tag for this case(also a regression test for the before kernel patch).

> Validate the timespec returned by sched_rr_get_interval() against the
> value read from /proc/sys/kernel/sched_rr_timeslice_ms.
>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>   .../syscalls/sched_rr_get_interval/sched_rr_get_interval01.c     | 1 +
>   1 file changed, 1 insertion(+)
>
> diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> index 31d7b5d56a52..f358c91ac505 100644
> --- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> +++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> @@ -62,6 +62,7 @@ static void run(void)
>   		        tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
>   	}
>   
> +	TST_ASSERT_INT("/proc/sys/kernel/sched_rr_timeslice_ms", tst_ts_to_ms(tp));
>   }
>   
>   static struct tst_test test = {


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linux.it/pipermail/ltp/attachments/20200703/501abbfb/attachment.htm>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice
  2020-07-03  7:43     ` Yang Xu
@ 2020-07-03  7:51       ` Viresh Kumar
  2020-07-03  8:00         ` Yang Xu
  0 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-07-03  7:51 UTC (permalink / raw)
  To: ltp

On 03-07-20, 15:43, Yang Xu wrote:
> Hi Viresh
> 
> Can we add a linux tag for this case(also a regression test for the before kernel patch).

Right, so this patch must be tested for kernels >= v3.9. I missed
that. This is what you were referring to, right ?

What's the regression test you are suggesting here ?

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice
  2020-07-03  7:51       ` Viresh Kumar
@ 2020-07-03  8:00         ` Yang Xu
  2020-07-03  8:18           ` Viresh Kumar
  0 siblings, 1 reply; 64+ messages in thread
From: Yang Xu @ 2020-07-03  8:00 UTC (permalink / raw)
  To: ltp

Hi Viresh

> On 03-07-20, 15:43, Yang Xu wrote:
>> Hi Viresh
>>
>> Can we add a linux tag for this case(also a regression test for the before kernel patch).
> Right, so this patch must be tested for kernels >= v3.9. I missed
> that. This is what you were referring to, right ?

We only need to check /proc/sys/kernel/sched_rr_timeslice_ms whether existed in setup phase and
then check proc value in run like prctl08.c[1].

[1]https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/syscalls/prctl/prctl08.c

>
> What's the regression test you are suggesting here ?

The following kernel patch.

  https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=975e155ed8732cb81f55c021c441ae662dd040b5

>


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linux.it/pipermail/ltp/attachments/20200703/42e2b934/attachment-0001.htm>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice
  2020-07-03  8:00         ` Yang Xu
@ 2020-07-03  8:18           ` Viresh Kumar
  2020-07-03  9:01             ` Yang Xu
  0 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-07-03  8:18 UTC (permalink / raw)
  To: ltp

On 03-07-20, 16:00, Yang Xu wrote:
> We only need to check /proc/sys/kernel/sched_rr_timeslice_ms whether existed in setup phase and
> then check proc value in run like prctl08.c[1].
> 
> [1]https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/syscalls/prctl/prctl08.c

This is certainly better, thanks.

> > What's the regression test you are suggesting here ?
> 
> The following kernel patch.
> 
>  https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=975e155ed8732cb81f55c021c441ae662dd040b5

Yeah I got that you were talking about this, but I am not sure of what
regression test you are asking for and if we should be adding a test
towards it at all as this is a kernel bug and we should keep showing
the error for such kernels, isn't it ?

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice
  2020-07-03  8:18           ` Viresh Kumar
@ 2020-07-03  9:01             ` Yang Xu
  0 siblings, 0 replies; 64+ messages in thread
From: Yang Xu @ 2020-07-03  9:01 UTC (permalink / raw)
  To: ltp

Hi Viresh


> Yeah I got that you were talking about this, but I am not sure of what
> regression test you are asking for and if we should be adding a test
> towards it at all as this is a kernel bug and we should keep showing
> the error for such kernels, isn't it ?

Yes, we only add a linux tag and comment as below:
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
@@ -5,6 +5,10 @@
   *
   * Gets round-robin time quantum by calling sched_rr_get_interval() and
   * checks that the value is sane.
+ *
+ * It is also a regression test for kernel
+ * commit 975e155ed873 ("sched/rt: Show the 'sched_rr_timeslice' SCHED_RR
+ * timeslice tuning knob in milliseconds").
   */

  #include <sched.h>
@@ -53,7 +57,6 @@ static void run(void)
                 tst_res(TFAIL | TTERRNO, "Test Failed, sched_rr_get_interval() returned %ld",
                         TST_RET);
         }
-
         if (!tst_ts_valid(&tp)) {
                 tst_res(TPASS, "Time quantum %llis %llins",
                         tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
@@ -61,7 +64,7 @@ static void run(void)
                 tst_res(TFAIL, "Invalid time quantum %llis %llins",
                         tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
         }
-
+       TST_ASSERT_INT("/proc/sys/kernel/sched_rr_timeslice_ms", tst_ts_to_ms(tp));
  }

  static struct tst_test test = {
@@ -69,4 +72,8 @@ static struct tst_test test = {
         .test_variants = ARRAY_SIZE(variants),
         .setup = setup,
         .needs_root = 1,
+       .tags = (const struct tst_tag[]) {
+               {"linux-git", "975e155ed873"},
+               {}
+       }
  };

so run this case without this kernel patch and config_hz=250 fail as below:
sched_rr_get_interval01.c:40: INFO: Testing variant: syscall with old kernel spec
sched_rr_get_interval01.c:55: PASS: sched_rr_get_interval() passed
sched_rr_get_interval01.c:62: PASS: Time quantum 0s 100000000ns
sched_rr_get_interval01.c:67: FAIL: /proc/sys/kernel/sched_rr_timeslice_ms != 100 got 25

HINT: You _MAY_ be missing kernel fixes, see:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=975e155ed873



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linux.it/pipermail/ltp/attachments/20200703/9290fa68/attachment-0001.htm>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 06/19] syscalls/futex: Merge futex_wait_bitset tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 06/19] syscalls/futex: Merge futex_wait_bitset tests Viresh Kumar
@ 2020-07-03  9:15   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-03  9:15 UTC (permalink / raw)
  To: ltp

Hi!
> We can handle them easily in a single test, lets do it.

I guess that the original reason to keep them separate was due to
tst_timer_check() function that exits the test if particular timer is
not present.

However these days we expect that CLOCK_MONOTONIC is present in many
testcases so we can as well remove the function from the test, which I
did before applying, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 07/19] syscalls/futex: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 07/19] syscalls/futex: Add support for time64 tests Viresh Kumar
@ 2020-07-03 12:45   ` Cyril Hrubis
  2020-07-06 10:40     ` Viresh Kumar
  2020-07-06 11:40   ` [LTP] [PATCH V7.1 " Viresh Kumar
  1 sibling, 1 reply; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-03 12:45 UTC (permalink / raw)
  To: ltp

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 09/19] syscalls/sigwaitinfo: Migrate to new test framework
  2020-06-26  6:22 ` [LTP] [PATCH V7 09/19] syscalls/sigwaitinfo: Migrate to new test framework Viresh Kumar
@ 2020-07-03 13:58   ` Cyril Hrubis
  2020-07-06  2:39     ` Viresh Kumar
  0 siblings, 1 reply; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-03 13:58 UTC (permalink / raw)
  To: ltp

Hi!
Honestly I'm not sure what we should do about this test. Obviously this
is a step into right direction but it still keeps the SUCCEED_OR_DIE()
macro that produces many warnings.

I'm also not happy about the fact that we compile different test based
on ifdefs and that there are empty directories where binaries are
magically appear during the build. I would be much happier if we had a
real test sources there and share the large enough common bits in a
different way.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice
  2020-07-03  7:38   ` [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice Viresh Kumar
  2020-07-03  7:43     ` Yang Xu
@ 2020-07-03 14:08     ` Cyril Hrubis
  2020-07-06  3:31     ` [LTP] [PATCH V2] " Viresh Kumar
  2 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-03 14:08 UTC (permalink / raw)
  To: ltp

Hi!
> Validate the timespec returned by sched_rr_get_interval() against the
> value read from /proc/sys/kernel/sched_rr_timeslice_ms.

Looking at centos 6, the older distribution we support, the kernel there
is based on 4.15 so we do not have to bother with check if the file is
present. But we should really add a tag for the kernel commit that fixed
the issue.

> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  .../syscalls/sched_rr_get_interval/sched_rr_get_interval01.c     | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> index 31d7b5d56a52..f358c91ac505 100644
> --- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> +++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> @@ -62,6 +62,7 @@ static void run(void)
>  		        tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
>  	}
>  
> +	TST_ASSERT_INT("/proc/sys/kernel/sched_rr_timeslice_ms", tst_ts_to_ms(tp));
>  }
>  
>  static struct tst_test test = {
> -- 
> 2.25.0.rc1.19.g042ed3e048af
> 

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 08/19] syscalls/io_pgetevents: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 08/19] syscalls/io_pgetevents: " Viresh Kumar
@ 2020-07-03 14:59   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-03 14:59 UTC (permalink / raw)
  To: ltp

Hi!
> +	to.type = tv->type;
> +	tst_ts_set_sec(&to, 0);
> +	tst_ts_set_nsec(&to, 10000);

I've simplified these to "to = tst_ts_from_ns(tv->type, 10000)" and
pushed, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 09/19] syscalls/sigwaitinfo: Migrate to new test framework
  2020-07-03 13:58   ` Cyril Hrubis
@ 2020-07-06  2:39     ` Viresh Kumar
  2020-07-07 15:16       ` Cyril Hrubis
  0 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-07-06  2:39 UTC (permalink / raw)
  To: ltp

On 03-07-20, 15:58, Cyril Hrubis wrote:
> Hi!
> Honestly I'm not sure what we should do about this test. Obviously this
> is a step into right direction but it still keeps the SUCCEED_OR_DIE()
> macro that produces many warnings.
> 
> I'm also not happy about the fact that we compile different test based
> on ifdefs and that there are empty directories where binaries are
> magically appear during the build. I would be much happier if we had a
> real test sources there and share the large enough common bits in a
> different way.

What about merging this patch as is (so I don't to keep sending it)
and then I fix all the issues you want to get fixed in this test
separately ?

I agree with the issues you raised. It took me a while to understand
how it tests different syscalls and how things magically work in
multiple directories :)

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V2] syscalls/sched_rr_get_interval: Validate the timeslice
  2020-07-03  7:38   ` [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice Viresh Kumar
  2020-07-03  7:43     ` Yang Xu
  2020-07-03 14:08     ` Cyril Hrubis
@ 2020-07-06  3:31     ` Viresh Kumar
  2020-07-06  4:41       ` Yang Xu
  2020-07-07  9:30       ` Cyril Hrubis
  2 siblings, 2 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-07-06  3:31 UTC (permalink / raw)
  To: ltp

Validate the timespec returned by sched_rr_get_interval() against the
value read from /proc/sys/kernel/sched_rr_timeslice_ms.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
V2:
- Add .tags entry
- check if file is present or not.

 .../sched_rr_get_interval01.c                     | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
index 31d7b5d56a52..0466be36bec0 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
@@ -5,11 +5,18 @@
  *
  * Gets round-robin time quantum by calling sched_rr_get_interval() and
  * checks that the value is sane.
+ *
+ * It is also a regression test for kernel
+ * commit 975e155ed873 ("sched/rt: Show the 'sched_rr_timeslice' SCHED_RR
+ * timeslice tuning knob in milliseconds").
  */
 
 #include <sched.h>
 #include "tst_timer.h"
 
+#define PROC_SCHED_RR_TIMESLICE_MS	"/proc/sys/kernel/sched_rr_timeslice_ms"
+static int proc_flag;
+
 struct tst_ts tp;
 
 static struct test_variants {
@@ -39,6 +46,8 @@ static void setup(void)
 
 	if ((sched_setscheduler(0, SCHED_RR, &p)) == -1)
 		tst_res(TFAIL | TTERRNO, "sched_setscheduler() failed");
+
+	proc_flag = !access(PROC_SCHED_RR_TIMESLICE_MS, F_OK);
 }
 
 static void run(void)
@@ -62,6 +71,8 @@ static void run(void)
 		        tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
 	}
 
+	if (proc_flag)
+		TST_ASSERT_INT("/proc/sys/kernel/sched_rr_timeslice_ms", tst_ts_to_ms(tp));
 }
 
 static struct tst_test test = {
@@ -69,4 +80,8 @@ static struct tst_test test = {
 	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.needs_root = 1,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "975e155ed873"},
+		{}
+	}
 };
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V2] syscalls/sched_rr_get_interval: Validate the timeslice
  2020-07-06  3:31     ` [LTP] [PATCH V2] " Viresh Kumar
@ 2020-07-06  4:41       ` Yang Xu
  2020-07-07  9:30       ` Cyril Hrubis
  1 sibling, 0 replies; 64+ messages in thread
From: Yang Xu @ 2020-07-06  4:41 UTC (permalink / raw)
  To: ltp

Hi Viresh

Acked-by.

> Validate the timespec returned by sched_rr_get_interval() against the
> value read from /proc/sys/kernel/sched_rr_timeslice_ms.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
> V2:
> - Add .tags entry
> - check if file is present or not.
> 
>   .../sched_rr_get_interval01.c                     | 15 +++++++++++++++
>   1 file changed, 15 insertions(+)
> 
> diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> index 31d7b5d56a52..0466be36bec0 100644
> --- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> +++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
> @@ -5,11 +5,18 @@
>    *
>    * Gets round-robin time quantum by calling sched_rr_get_interval() and
>    * checks that the value is sane.
> + *
> + * It is also a regression test for kernel
> + * commit 975e155ed873 ("sched/rt: Show the 'sched_rr_timeslice' SCHED_RR
> + * timeslice tuning knob in milliseconds").
>    */
>   
>   #include <sched.h>
>   #include "tst_timer.h"
>   
> +#define PROC_SCHED_RR_TIMESLICE_MS	"/proc/sys/kernel/sched_rr_timeslice_ms"
> +static int proc_flag;
> +
>   struct tst_ts tp;
>   
>   static struct test_variants {
> @@ -39,6 +46,8 @@ static void setup(void)
>   
>   	if ((sched_setscheduler(0, SCHED_RR, &p)) == -1)
>   		tst_res(TFAIL | TTERRNO, "sched_setscheduler() failed");
> +
> +	proc_flag = !access(PROC_SCHED_RR_TIMESLICE_MS, F_OK);
>   }
>   
>   static void run(void)
> @@ -62,6 +71,8 @@ static void run(void)
>   		        tst_ts_get_sec(tp), tst_ts_get_nsec(tp));
>   	}
>   
> +	if (proc_flag)
> +		TST_ASSERT_INT("/proc/sys/kernel/sched_rr_timeslice_ms", tst_ts_to_ms(tp));
>   }
>   
>   static struct tst_test test = {
> @@ -69,4 +80,8 @@ static struct tst_test test = {
>   	.test_variants = ARRAY_SIZE(variants),
>   	.setup = setup,
>   	.needs_root = 1,
> +	.tags = (const struct tst_tag[]) {
> +		{"linux-git", "975e155ed873"},
> +		{}
> +	}
>   };
> 



^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 07/19] syscalls/futex: Add support for time64 tests
  2020-07-03 12:45   ` Cyril Hrubis
@ 2020-07-06 10:40     ` Viresh Kumar
  2020-07-06 11:36       ` Viresh Kumar
  0 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-07-06 10:40 UTC (permalink / raw)
  To: ltp

On 03-07-20, 14:45, Cyril Hrubis wrote:
> > 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?

I am not sure which two functions are you talking about here ..

> Is the timer library incompatible with test variants?

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 07/19] syscalls/futex: Add support for time64 tests
  2020-07-06 10:40     ` Viresh Kumar
@ 2020-07-06 11:36       ` Viresh Kumar
  0 siblings, 0 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-07-06 11:36 UTC (permalink / raw)
  To: ltp

On 06-07-20, 16:10, Viresh Kumar wrote:
> On 03-07-20, 14:45, Cyril Hrubis wrote:
> > > 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?
> 
> I am not sure which two functions are you talking about here ..
> 
> > Is the timer library incompatible with test variants?

I kept staring at this code and your comment and may have understood
finally :)

I haven't added futex variants here as this uses the _sample_
callback, which works with the simple timer code in LTP and as I
remember from some earlier discussion, that would be a lot of changes
and may not be worth it.

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7.1 07/19] syscalls/futex: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 07/19] syscalls/futex: Add support for time64 tests Viresh Kumar
  2020-07-03 12:45   ` Cyril Hrubis
@ 2020-07-06 11:40   ` Viresh Kumar
  2020-07-23 19:44     ` Cyril Hrubis
  1 sibling, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-07-06 11:40 UTC (permalink / raw)
  To: ltp

This adds support for time64 tests to the existing futex() syscall
tests.

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>
---
V7.1:
- s/TTERRNO/TERRNO/ at many places
- Use TST_PROCESS_STATE_WAIT()
- Use PTHREAD and hugepage library helpers
- Many other cleanups that Cyril suggested

 .../syscalls/futex/futex_cmp_requeue01.c      |  34 +++-
 .../syscalls/futex/futex_cmp_requeue02.c      |  28 ++-
 testcases/kernel/syscalls/futex/futex_utils.h |  24 +--
 .../kernel/syscalls/futex/futex_wait01.c      |  75 ++++----
 .../kernel/syscalls/futex/futex_wait02.c      | 109 +++++------
 .../kernel/syscalls/futex/futex_wait03.c      |  94 +++++-----
 .../kernel/syscalls/futex/futex_wait04.c      |  79 ++++----
 .../kernel/syscalls/futex/futex_wait05.c      |   2 +-
 .../syscalls/futex/futex_wait_bitset01.c      |  50 ++++--
 .../kernel/syscalls/futex/futex_wake01.c      |  67 ++++---
 .../kernel/syscalls/futex/futex_wake02.c      | 110 ++++++------
 .../kernel/syscalls/futex/futex_wake03.c      | 114 ++++++------
 .../kernel/syscalls/futex/futex_wake04.c      | 169 +++++++-----------
 testcases/kernel/syscalls/futex/futextest.h   | 122 ++++++++-----
 14 files changed, 539 insertions(+), 538 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..e5257ec18369 100644
--- a/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
+++ b/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
@@ -32,29 +32,48 @@ 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;
 	}
 
 	if (TST_ERR != tc->exp_errno) {
-		tst_res(TFAIL | TTERRNO,
+		tst_res(TFAIL | TERRNO,
 			"futex_cmp_requeue() failed unexpectedly, expected %s",
 			tst_strerrno(tc->exp_errno));
 		return;
 	}
 
-	tst_res(TPASS | TTERRNO, "futex_cmp_requeue() failed as expected");
+	tst_res(TPASS | TERRNO, "futex_cmp_requeue() failed as expected");
 }
 
 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..bdcbc90d5b2d 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,33 @@ 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;
 }
-
 #endif /* FUTEX_UTILS_H__ */
diff --git a/testcases/kernel/syscalls/futex/futex_wait01.c b/testcases/kernel/syscalls/futex/futex_wait01.c
index 51a540d9e315..9b5846f932c5 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,54 @@ 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];
+	struct tst_ts to = tst_ts_from_ns(tv->tstype, 10000);
 	int res;
 
-	res = futex_wait(tc->f_addr, tc->f_val, &to, tc->opflags);
+	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 | TERRNO, "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;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
+	struct test_variants *tv = &variants[tst_variant];
 
-	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..092e540f5fb7 100644
--- a/testcases/kernel/syscalls/futex/futex_wait02.c
+++ b/testcases/kernel/syscalls/futex/futex_wait02.c
@@ -1,105 +1,84 @@
+// 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');
+	TST_PROCESS_STATE_WAIT(getppid(), 'S', 1000);
 
-	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 | TERRNO, "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();
-
-	switch (pid) {
-	case 0:
+	pid = SAFE_FORK();
+	if (!pid)
 		do_child();
-	break;
-	case -1:
-		tst_brkm(TBROK | TERRNO, NULL, "fork() failed");
-	break;
-	default:
-	break;
-	}
-
-	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 | TERRNO, "futex_wait() failed");
+		return;
 	}
 
-	SAFE_WAIT(NULL, &res);
-
-	if (WIFEXITED(res) && WEXITSTATUS(res) == TPASS)
-		tst_resm(TPASS, "futex_wait() woken up");
-	else
-		tst_resm(TFAIL, "child failed");
+	SAFE_WAIT(NULL);
+	tst_res(TPASS, "futex_wait() woken up");
 }
 
 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..94d522dcb75a 100644
--- a/testcases/kernel/syscalls/futex/futex_wait03.c
+++ b/testcases/kernel/syscalls/futex/futex_wait03.c
@@ -1,87 +1,77 @@
+// 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"
+#include "tst_safe_pthread.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');
+	TST_PROCESS_STATE_WAIT(getppid(), 'S', 1000);
 
-	ret = futex_wake(&futex, 1, FUTEX_PRIVATE_FLAG);
+	ret = futex_wake(tv->fntype, &futex, 1, FUTEX_PRIVATE_FLAG);
+	if (ret != 1)
+		tst_res(TFAIL, "futex_wake() returned %li", ret);
 
 	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 res;
 	pthread_t t;
 
-	res = pthread_create(&t, NULL, threaded, NULL);
-	if (res) {
-		tst_brkm(TBROK, NULL, "pthread_create(): %s",
-	                 tst_strerrno(res));
-	}
+	SAFE_PTHREAD_CREATE(&t, NULL, threaded, NULL);
 
-	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));
-		pthread_join(t, NULL);
+		tst_res(TFAIL | TERRNO, "futex_wait() failed");
+		SAFE_PTHREAD_JOIN(t, NULL);
 		return;
 	}
 
-	res = pthread_join(t, (void*)&ret);
-	if (res)
-		tst_brkm(TBROK, NULL, "pthread_join(): %s", tst_strerrno(res));
-
-	if (ret != 1)
-		tst_resm(TFAIL, "futex_wake() returned %li", ret);
-	else
-		tst_resm(TPASS, "futex_wait() woken up");
+	SAFE_PTHREAD_JOIN(t, NULL);
+	tst_res(TPASS, "futex_wait() woken up");
 }
 
-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..f2885c8b27d5 100644
--- a/testcases/kernel/syscalls/futex/futex_wait04.c
+++ b/testcases/kernel/syscalls/futex/futex_wait04.c
@@ -1,65 +1,62 @@
+// 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 void verify_futex_wait(void)
+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 run(void)
 {
-	int res;
-	void *buf;
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_ts to = tst_ts_from_ns(tv->tstype, 10000);
 	size_t pagesize = getpagesize();
-	buf = SAFE_MMAP(NULL, NULL, pagesize, PROT_READ|PROT_WRITE,
-                        MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+	void *buf;
+	int res;
 
-	res = futex_wait(buf, 1, &to, 0);
+	buf = SAFE_MMAP(NULL, pagesize, PROT_READ|PROT_WRITE,
+			MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
 
+	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();
 
diff --git a/testcases/kernel/syscalls/futex/futex_wait_bitset01.c b/testcases/kernel/syscalls/futex/futex_wait_bitset01.c
index fc5656060951..cfde61083de2 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",
@@ -53,27 +71,27 @@ static void verify_futex_wait_bitset(long long wait_us, clock_t clk_id)
 	}
 
 	if (TST_ERR != ETIMEDOUT) {
-		tst_res(TFAIL | TTERRNO, "expected %s",
+		tst_res(TFAIL | TERRNO, "expected %s",
 			tst_strerrno(ETIMEDOUT));
 		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)
@@ -81,7 +99,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..f2f682fe7e2e 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 | TERRNO, "futex_wake() failed");
 		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..d8a35e7a6d2c 100644
--- a/testcases/kernel/syscalls/futex/futex_wake02.c
+++ b/testcases/kernel/syscalls/futex/futex_wake02.c
@@ -1,40 +1,35 @@
+// 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;
+#include "tst_safe_pthread.h"
 
 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 +53,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,25 +65,21 @@ 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));
-		}
-	}
+	for (i = 0; i < (int)ARRAY_SIZE(t); i++)
+		SAFE_PTHREAD_CREATE(&t[i], NULL, threaded, (void*)((long)i));
 
 	while (wait_for_threads(ARRAY_SIZE(t)))
 		usleep(100);
 
 	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 | TERRNO,
 			         "futex_wake() woken up %i threads, expected %i",
 			         res, i);
 		}
@@ -101,26 +93,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, "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 | TERRNO, "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);
+		SAFE_PTHREAD_JOIN(t[i], NULL);
 
-	tst_exit();
+	exit(0);
 }
 
 /*
@@ -135,30 +127,28 @@ 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;
-
-	pid = tst_fork();
+	int status, pid;
 
-	switch (pid) {
-	case 0:
+	pid = SAFE_FORK();
+	if (!pid)
 		do_child();
-	case -1:
-		tst_brkm(TBROK | TERRNO, NULL, "fork() failed");
-	default:
-		tst_record_childstatus(NULL, pid);
-	}
+
+	SAFE_WAITPID(pid, &status, 0);
 }
 
-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_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..32936df87aa8 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 | TERRNO,
+		        "futex_wake() woken up %i children, expected %i",
+			res, nr_children);
 		return;
 	}
 
@@ -63,65 +60,58 @@ 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, "reaped only %i childs, expected %i",
+		        cnt, nr_children);
 	} 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();
-
-		switch (pids[i]) {
-		case -1:
-			tst_brkm(TBROK | TERRNO, NULL, "fork()");
-		case 0:
+	for (i = 0; i < ARRAY_SIZE(pids); i++) {
+		pids[i] = SAFE_FORK();
+		if (!pids[i])
 			do_child();
-		default:
-		break;
-		}
 	}
 
-	for (i = 0; i < (int)ARRAY_SIZE(pids); i++)
-		tst_process_state_wait2(pids[i], 'S');
+	for (i = 0; i < ARRAY_SIZE(pids); i++)
+		TST_PROCESS_STATE_WAIT(pids[i], 'S', 1000);
 
 	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 | TERRNO, "futex_wake() woken up %u, none were waiting",
+			res);
 	} 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..0b8e30e7521a 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,115 +28,98 @@
 #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"
-
-#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;
+#include "tst_safe_stdio.h"
+#include "tst_safe_pthread.h"
 
 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 = tst_ts_from_ns(tv->tstype, 30 * NSEC_PER_SEC);
 
-	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_HPAGES, "%ld", &orig_hugepages);
 
 	if (orig_hugepages <= 0)
-		SAFE_FILE_PRINTF(NULL, PATH_NR_HUGEPAGES, "%d", 1);
-
-	TEST_PAUSE;
+		SAFE_FILE_PRINTF(PATH_NR_HPAGES, "%d", 1);
 }
 
 static void cleanup(void)
 {
 	if (orig_hugepages <= 0)
-		SAFE_FILE_PRINTF(NULL, PATH_NR_HUGEPAGES, "%ld", orig_hugepages);
-
-	tst_rmdir();
-}
-
-static int read_hugepagesize(void)
-{
-	FILE *fp;
-	char line[BUFSIZ], buf[BUFSIZ];
-	int val;
-
-	fp = SAFE_FOPEN(cleanup, 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);
-				return 1024 * val;
-			}
-	}
-
-	SAFE_FCLOSE(cleanup, fp);
-	tst_brkm(TBROK, NULL, "can't find \"%s\" in %s",
-			"Hugepagesize:", PATH_MEMINFO);
+		SAFE_FILE_PRINTF(PATH_NR_HPAGES, "%ld", orig_hugepages);
 }
 
 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 | TERRNO, "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;
+	int hpsz, pgsz;
 	pthread_t th1, th2;
 
-	hpsz = read_hugepagesize();
-	tst_resm(TINFO, "Hugepagesize %i", hpsz);
+	hpsz = tst_get_hugepage_size();
+	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();
@@ -163,47 +132,31 @@ static void wakeup_thread2(void)
 	*futex2 = 0;
 
 	/*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));
-	}
-
-	res = pthread_create(&th2, NULL, wait_thread2, NULL);
-	if (res) {
-		tst_brkm(TBROK, NULL, "pthread_create(): %s",
-				tst_strerrno(res));
-	}
+	SAFE_PTHREAD_CREATE(&th1, NULL, wait_thread1, NULL);
+	SAFE_PTHREAD_CREATE(&th2, NULL, wait_thread2, NULL);
 
 	while (wait_for_threads(2))
 		usleep(1000);
 
-	futex_wake(futex2, 1, 0);
-
-	res = pthread_join(th2, NULL);
-	if (res)
-		tst_brkm(TBROK, NULL, "pthread_join(): %s", tst_strerrno(res));
+	futex_wake(tv->fntype, futex2, 1, 0);
+	SAFE_PTHREAD_JOIN(th2, NULL);
+	futex_wake(tv->fntype, futex1, 1, 0);
+	SAFE_PTHREAD_JOIN(th1, NULL);
 
-	futex_wake(futex1, 1, 0);
-
-	res = pthread_join(th1, NULL);
-	if (res)
-		tst_brkm(TBROK, NULL, "pthread_join(): %s", tst_strerrno(res));
-
-	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


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V2] syscalls/sched_rr_get_interval: Validate the timeslice
  2020-07-06  3:31     ` [LTP] [PATCH V2] " Viresh Kumar
  2020-07-06  4:41       ` Yang Xu
@ 2020-07-07  9:30       ` Cyril Hrubis
  1 sibling, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-07  9:30 UTC (permalink / raw)
  To: ltp

Hi!
Applied, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 09/19] syscalls/sigwaitinfo: Migrate to new test framework
  2020-07-06  2:39     ` Viresh Kumar
@ 2020-07-07 15:16       ` Cyril Hrubis
  2020-07-09 10:46         ` Viresh Kumar
  0 siblings, 1 reply; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-07 15:16 UTC (permalink / raw)
  To: ltp

Hi!
> > Honestly I'm not sure what we should do about this test. Obviously this
> > is a step into right direction but it still keeps the SUCCEED_OR_DIE()
> > macro that produces many warnings.
> > 
> > I'm also not happy about the fact that we compile different test based
> > on ifdefs and that there are empty directories where binaries are
> > magically appear during the build. I would be much happier if we had a
> > real test sources there and share the large enough common bits in a
> > different way.
> 
> What about merging this patch as is (so I don't to keep sending it)
> and then I fix all the issues you want to get fixed in this test
> separately ?

Fair enough, merged.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 09/19] syscalls/sigwaitinfo: Migrate to new test framework
  2020-07-07 15:16       ` Cyril Hrubis
@ 2020-07-09 10:46         ` Viresh Kumar
  0 siblings, 0 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-07-09 10:46 UTC (permalink / raw)
  To: ltp

On 07-07-20, 17:16, Cyril Hrubis wrote:
> Hi!
> > > Honestly I'm not sure what we should do about this test. Obviously this
> > > is a step into right direction but it still keeps the SUCCEED_OR_DIE()
> > > macro that produces many warnings.
> > > 
> > > I'm also not happy about the fact that we compile different test based
> > > on ifdefs and that there are empty directories where binaries are
> > > magically appear during the build. I would be much happier if we had a
> > > real test sources there and share the large enough common bits in a
> > > different way.
> > 
> > What about merging this patch as is (so I don't to keep sending it)
> > and then I fix all the issues you want to get fixed in this test
> > separately ?
> 
> Fair enough, merged.

I believe you will apply the next patch (10/19) as well, which touches
this file and so I am starting to work on top of that now.

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants
  2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
                   ` (18 preceding siblings ...)
  2020-06-26  6:22 ` [LTP] [PATCH V7 19/19] syscalls: clock_settime: Add test around y2038 vulnerability Viresh Kumar
@ 2020-07-20 10:19 ` Viresh Kumar
  2020-07-22 10:04   ` Cyril Hrubis
  19 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-07-20 10:19 UTC (permalink / raw)
  To: ltp

On 26-06-20, 11:52, Viresh Kumar wrote:
> Hi,
> 
> This updates the pending syscall tests that lacked the time64 updates.
> 
> V7:
> - Move all tst_timer.h changes to a single patch.
> - Provide more generic helpers for itimerspec and update the patches
>   accordingly.
> - Also include the y2038 patch in the series as that depends on the
>   first patch here.

Ping for a lot of patches from this series as well.

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 10/19] syscalls/rt_sigtimedwait: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 10/19] syscalls/rt_sigtimedwait: Add support for time64 tests Viresh Kumar
@ 2020-07-22 10:03   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-22 10:03 UTC (permalink / raw)
  To: ltp

Hi!
Applied, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants
  2020-07-20 10:19 ` [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
@ 2020-07-22 10:04   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-22 10:04 UTC (permalink / raw)
  To: ltp

Hi!
> Ping for a lot of patches from this series as well.

Sorry, I've been a bit overloaded lately, I will get to them hopefully
soon.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7.1 07/19] syscalls/futex: Add support for time64 tests
  2020-07-06 11:40   ` [LTP] [PATCH V7.1 " Viresh Kumar
@ 2020-07-23 19:44     ` Cyril Hrubis
  2020-07-24  2:33       ` Viresh Kumar
  0 siblings, 1 reply; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-23 19:44 UTC (permalink / raw)
  To: ltp

Hi!
Pushed with minor changes, thanks.

Here is the diff, if something there is puzzling I will explain it
tomorrow, I'm too tired to do it now...

diff --git a/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c b/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
index e5257ec18..dd8fafb3e 100644
--- a/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
+++ b/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
@@ -58,13 +58,13 @@ static void verify_futex_cmp_requeue(unsigned int n)
 	}
 
 	if (TST_ERR != tc->exp_errno) {
-		tst_res(TFAIL | TERRNO,
+		tst_res(TFAIL | TTERRNO,
 			"futex_cmp_requeue() failed unexpectedly, expected %s",
 			tst_strerrno(tc->exp_errno));
 		return;
 	}
 
-	tst_res(TPASS | TERRNO, "futex_cmp_requeue() failed as expected");
+	tst_res(TPASS | TTERRNO, "futex_cmp_requeue() failed as expected");
 }
 
 static void setup(void)
diff --git a/testcases/kernel/syscalls/futex/futex_utils.h b/testcases/kernel/syscalls/futex/futex_utils.h
index bdcbc90d5..156895efb 100644
--- a/testcases/kernel/syscalls/futex/futex_utils.h
+++ b/testcases/kernel/syscalls/futex/futex_utils.h
@@ -64,4 +64,5 @@ static inline int wait_for_threads(unsigned int nr_threads)
 
 	return 0;
 }
+
 #endif /* FUTEX_UTILS_H__ */
diff --git a/testcases/kernel/syscalls/futex/futex_wait01.c b/testcases/kernel/syscalls/futex/futex_wait01.c
index 9b5846f93..09a95aa2c 100644
--- a/testcases/kernel/syscalls/futex/futex_wait01.c
+++ b/testcases/kernel/syscalls/futex/futex_wait01.c
@@ -11,8 +11,6 @@
  *    from the expected one.
  */
 
-#include <errno.h>
-
 #include "futextest.h"
 
 struct testcase {
diff --git a/testcases/kernel/syscalls/futex/futex_wait02.c b/testcases/kernel/syscalls/futex/futex_wait02.c
index 092e540f5..32bcfd1e7 100644
--- a/testcases/kernel/syscalls/futex/futex_wait02.c
+++ b/testcases/kernel/syscalls/futex/futex_wait02.c
@@ -9,7 +9,6 @@
 
 #include <sys/mman.h>
 #include <sys/wait.h>
-#include <errno.h>
 
 #include "futextest.h"
 #include "futex_utils.h"
diff --git a/testcases/kernel/syscalls/futex/futex_wait03.c b/testcases/kernel/syscalls/futex/futex_wait03.c
index 94d522dcb..e6e94055b 100644
--- a/testcases/kernel/syscalls/futex/futex_wait03.c
+++ b/testcases/kernel/syscalls/futex/futex_wait03.c
@@ -7,9 +7,6 @@
  * This tests uses private mutexes with threads.
  */
 
-#include <errno.h>
-#include <pthread.h>
-
 #include "futextest.h"
 #include "futex_utils.h"
 #include "tst_safe_pthread.h"
@@ -34,7 +31,7 @@ static void *threaded(void *arg LTP_ATTRIBUTE_UNUSED)
 	struct test_variants *tv = &variants[tst_variant];
 	long ret;
 
-	TST_PROCESS_STATE_WAIT(getppid(), 'S', 1000);
+	TST_PROCESS_STATE_WAIT(getppid(), 'S', 0);
 
 	ret = futex_wake(tv->fntype, &futex, 1, FUTEX_PRIVATE_FLAG);
 	if (ret != 1)
diff --git a/testcases/kernel/syscalls/futex/futex_wait_bitset01.c b/testcases/kernel/syscalls/futex/futex_wait_bitset01.c
index cfde61083..358a5cd45 100644
--- a/testcases/kernel/syscalls/futex/futex_wait_bitset01.c
+++ b/testcases/kernel/syscalls/futex/futex_wait_bitset01.c
@@ -7,8 +7,6 @@
  * 2. Check that the futex waited for expected time.
  */
 
-#include <errno.h>
-
 #include "tst_test.h"
 #include "tst_timer.h"
 #include "futextest.h"
@@ -71,7 +69,7 @@ static void verify_futex_wait_bitset(long long wait_us, clock_t clk_id)
 	}
 
 	if (TST_ERR != ETIMEDOUT) {
-		tst_res(TFAIL | TERRNO, "expected %s",
+		tst_res(TFAIL | TTERRNO, "expected %s",
 			tst_strerrno(ETIMEDOUT));
 		return;
 	}
diff --git a/testcases/kernel/syscalls/futex/futex_wake01.c b/testcases/kernel/syscalls/futex/futex_wake01.c
index f2f682fe7..a2f225a9c 100644
--- a/testcases/kernel/syscalls/futex/futex_wake01.c
+++ b/testcases/kernel/syscalls/futex/futex_wake01.c
@@ -5,7 +5,6 @@
  * futex_wake() returns 0 (0 woken up processes) when no processes wait on the mutex.
  */
 
-#include <errno.h>
 #include <limits.h>
 
 #include "futextest.h"
diff --git a/testcases/kernel/syscalls/futex/futex_wake02.c b/testcases/kernel/syscalls/futex/futex_wake02.c
index d8a35e7a6..de80738bd 100644
--- a/testcases/kernel/syscalls/futex/futex_wake02.c
+++ b/testcases/kernel/syscalls/futex/futex_wake02.c
@@ -5,8 +5,6 @@
  * Block several threads on a private mutex, then wake them up.
  */
 
-#include <errno.h>
-#include <pthread.h>
 #include <sys/types.h>
 
 #include "futextest.h"
@@ -66,7 +64,7 @@ static void *threaded(void *arg)
 static void do_child(void)
 {
 	struct test_variants *tv = &variants[tst_variant];
-	int res, i, j, awake;
+	int i, j, awake;
 	pthread_t t[55];
 
 	for (i = 0; i < (int)ARRAY_SIZE(t); i++)
@@ -77,11 +75,11 @@ static void do_child(void)
 
 	for (i = 1; i <= 10; i++) {
 		clear_threads_awake();
-		res = futex_wake(tv->fntype, &futex, i, FUTEX_PRIVATE_FLAG);
-		if (i != res) {
-			tst_res(TFAIL | TERRNO,
-			         "futex_wake() woken up %i threads, expected %i",
-			         res, i);
+		TEST(futex_wake(tv->fntype, &futex, i, FUTEX_PRIVATE_FLAG));
+		if (i != TST_RET) {
+			tst_res(TFAIL | TTERRNO,
+			         "futex_wake() woken up %li threads, expected %i",
+			         TST_RET, i);
 		}
 
 		for (j = 0; j < 100000; j++) {
@@ -100,11 +98,10 @@ static void do_child(void)
 		}
 	}
 
-	res = futex_wake(tv->fntype, &futex, 1, FUTEX_PRIVATE_FLAG);
-
-	if (res) {
-		tst_res(TFAIL | TERRNO, "futex_wake() woken up %i, none were waiting",
-			res);
+	TEST(futex_wake(tv->fntype, &futex, 1, FUTEX_PRIVATE_FLAG));
+	if (TST_RET) {
+		tst_res(TFAIL | TTERRNO, "futex_wake() woken up %li, none were waiting",
+			TST_RET);
 	} else {
 		tst_res(TPASS, "futex_wake() woken up 0 threads");
 	}
@@ -129,13 +126,8 @@ static void do_child(void)
  */
 static void run(void)
 {
-	int status, pid;
-
-	pid = SAFE_FORK();
-	if (!pid)
+	if (!SAFE_FORK())
 		do_child();
-
-	SAFE_WAITPID(pid, &status, 0);
 }
 
 static void setup(void)
diff --git a/testcases/kernel/syscalls/futex/futex_wake03.c b/testcases/kernel/syscalls/futex/futex_wake03.c
index 32936df87..02b291e1a 100644
--- a/testcases/kernel/syscalls/futex/futex_wake03.c
+++ b/testcases/kernel/syscalls/futex/futex_wake03.c
@@ -5,7 +5,6 @@
  * Block several processes on a mutex, then wake them up.
  */
 
-#include <errno.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -40,12 +39,11 @@ static void do_wake(int nr_children)
 	struct test_variants *tv = &variants[tst_variant];
 	int res, i, cnt;
 
-	res = futex_wake(tv->fntype, futex, nr_children, 0);
-
-	if (res != nr_children) {
-		tst_res(TFAIL | TERRNO,
-		        "futex_wake() woken up %i children, expected %i",
-			res, nr_children);
+	TEST(futex_wake(tv->fntype, futex, nr_children, 0));
+	if (TST_RET != nr_children) {
+		tst_res(TFAIL | TTERRNO,
+		        "futex_wake() woken up %li children, expected %i",
+			TST_RET, nr_children);
 		return;
 	}
 
@@ -72,7 +70,6 @@ static void run(void)
 	struct test_variants *tv = &variants[tst_variant];
 	pid_t pids[55];
 	unsigned int i;
-	int res;
 
 	for (i = 0; i < ARRAY_SIZE(pids); i++) {
 		pids[i] = SAFE_FORK();
@@ -81,16 +78,16 @@ static void run(void)
 	}
 
 	for (i = 0; i < ARRAY_SIZE(pids); i++)
-		TST_PROCESS_STATE_WAIT(pids[i], 'S', 1000);
+		TST_PROCESS_STATE_WAIT(pids[i], 'S', 0);
 
 	for (i = 1; i <= 10; i++)
 		do_wake(i);
 
-	res = futex_wake(tv->fntype, futex, 1, 0);
-
-	if (res) {
-		tst_res(TFAIL | TERRNO, "futex_wake() woken up %u, none were waiting",
-			res);
+	TEST(futex_wake(tv->fntype, futex, 1, 0));
+	if (TST_RET) {
+		tst_res(TFAIL | TTERRNO,
+			"futex_wake() woken up %li, none were waiting",
+		        TST_RET);
 	} else {
 		tst_res(TPASS, "futex_wake() woken up 0 children");
 	}
diff --git a/testcases/kernel/syscalls/futex/futex_wake04.c b/testcases/kernel/syscalls/futex/futex_wake04.c
index 0b8e30e75..8fae7ced9 100644
--- a/testcases/kernel/syscalls/futex/futex_wake04.c
+++ b/testcases/kernel/syscalls/futex/futex_wake04.c
@@ -23,8 +23,6 @@
 #include <stdio.h>
 #include <sys/mman.h>
 #include <fcntl.h>
-#include <pthread.h>
-#include <errno.h>
 #include <sys/time.h>
 #include <string.h>
 
@@ -92,6 +90,7 @@ static void *wait_thread2(void *arg LTP_ATTRIBUTE_UNUSED)
 	struct test_variants *tv = &variants[tst_variant];
 	int res;
 
+	errno = 0;
 	res = futex_wait(tv->fntype, futex2, *futex2, &to, 0);
 	if (!res)
 		tst_res(TPASS, "Hi hydra, thread2 awake!");
@@ -146,15 +145,10 @@ static void wakeup_thread2(void)
 	SAFE_MUNMAP(addr, hpsz);
 }
 
-static void run(void)
-{
-	wakeup_thread2();
-}
-
 static struct tst_test test = {
 	.setup = setup,
 	.cleanup = cleanup,
-	.test_all = run,
+	.test_all = wakeup_thread2,
 	.test_variants = ARRAY_SIZE(variants),
 	.needs_root = 1,
 	.min_kver = "2.6.32",
diff --git a/testcases/kernel/syscalls/futex/futextest.h b/testcases/kernel/syscalls/futex/futextest.h
index b72d83bc7..c50876fa6 100644
--- a/testcases/kernel/syscalls/futex/futextest.h
+++ b/testcases/kernel/syscalls/futex/futextest.h
@@ -1,35 +1,14 @@
-/******************************************************************************
- *
- *   Copyright ? International Business Machines  Corp., 2009
- *   Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
- *
- *   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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * NAME
- *      futextest.h
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright ? International Business Machines  Corp., 2009
+ * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
  *
  * DESCRIPTION
  *      Glibc independent futex library for testing kernel functionality.
  *
  * AUTHOR
  *      Darren Hart <dvhltc@us.ibm.com>
- *
- * HISTORY
- *      2009-Nov-6: Initial version by Darren Hart <dvhltc@us.ibm.com>
- *
- *****************************************************************************/
+ */
 
 #ifndef _FUTEXTEST_H
 #define _FUTEXTEST_H

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7.1 07/19] syscalls/futex: Add support for time64 tests
  2020-07-23 19:44     ` Cyril Hrubis
@ 2020-07-24  2:33       ` Viresh Kumar
  0 siblings, 0 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-07-24  2:33 UTC (permalink / raw)
  To: ltp

On 23-07-20, 21:44, Cyril Hrubis wrote:
> Hi!
> Pushed with minor changes, thanks.
> 
> Here is the diff, if something there is puzzling I will explain it
> tomorrow, I'm too tired to do it now...

No, it looks fine, thanks.

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 11/19] syscalls/mq_timed{send|receive}: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 11/19] syscalls/mq_timed{send|receive}: " Viresh Kumar
@ 2020-07-24 14:51   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-24 14:51 UTC (permalink / raw)
  To: ltp

Hi!
I've put the variant definition to the common header, since we have one
already it's pointless to keep two copies and pushed, thanks.

I've also pushed a patch on the top of that one that modifies the
timeous so that the test runs reasonably fast.

Also I'm starting to think that it may be easier to add all the syscall
variants into a single structure into an header that would be then
included by various tests, something as:

struct variant {
	int (*gettime)(clockid_t clk_id, void *ts);
	int (*settime)(clockid_t clk_id, void *ts);
	int (*getres)(clockid_t, void *ts);
	int (*tfd_gettime)(int fd, void *ts);
	int (*tfd_settime)(int fd, int flags, void *new_ts, void *old_ts);

	...

	enum tst_ts_type type;
	char desc;
} variants[] = {
...
};

Then we can include this to each test that needs it and be done with
it...

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 12/19] syscalls/recvmmsg: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 12/19] syscalls/recvmmsg: " Viresh Kumar
@ 2020-07-24 15:13   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-24 15:13 UTC (permalink / raw)
  To: ltp

Hi!
I've corrected the commit message with s/recvmmsg/sendmmsg/ and also
fixed two wrong TTERRNO in the code and pushed, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 13/19] syscalls/ppoll: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 13/19] syscalls/ppoll: " Viresh Kumar
@ 2020-07-27  9:17   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-27  9:17 UTC (permalink / raw)
  To: ltp

Hi!
Pushed with two minor changes, thanks.

* Added LTP_ATTRIBUTE_UNUSED to the libc wrapper to silence a warning

* Shortened the short ts in order to speed up the test a little

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 14/19] syscalls/select6: Add support for time64 tests
  2020-06-26  6:22 ` [LTP] [PATCH V7 14/19] syscalls/select6: " Viresh Kumar
@ 2020-07-27  9:40   ` Cyril Hrubis
  2020-07-28  7:23     ` Viresh Kumar
  0 siblings, 1 reply; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-27  9:40 UTC (permalink / raw)
  To: ltp

Hi!
> This adds support for time64 tests to the existing select6() syscall
> tests.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  testcases/kernel/syscalls/select/select_var.h | 25 ++++++++++++++++---
>  1 file changed, 22 insertions(+), 3 deletions(-)
> 
> diff --git a/testcases/kernel/syscalls/select/select_var.h b/testcases/kernel/syscalls/select/select_var.h
> index b19a1d1bf085..2c7604807cf6 100644
> --- a/testcases/kernel/syscalls/select/select_var.h
> +++ b/testcases/kernel/syscalls/select/select_var.h
> @@ -6,6 +6,7 @@
>  #define SELECT_VAR__
>  
>  #include "lapi/syscalls.h"
> +#include "tst_timer.h"
>  
>  struct compat_sel_arg_struct {
>  	long _n;
> @@ -38,7 +39,7 @@ static int do_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *except
>  	}
>  	case 2: {
>  		int ret;
> -		struct timespec ts = {
> +		struct __kernel_old_timespec ts = {
>  			.tv_sec = timeout->tv_sec,
>  			.tv_nsec = timeout->tv_usec * 1000,
>  		};

I'm a bit lost here, should we actually pass the __kernel_old_timespec
to all the tst_syscall() fuctions here?

I guess that the only function that would take the argument as struct
timeval is the select() glibc function, or do I miss something?

Also this change should be ideally done in a separate patch from the
second half that adds the __NR_pselect6_time64.

> @@ -47,7 +48,22 @@ static int do_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *except
>  		timeout->tv_usec = ts.tv_nsec / 1000;
>  		return ret;
>  	}
> -	case 3:
> +	case 3: {
> +		int ret = 0;
> +#if (__NR_clock_settime64 != __LTP__NR_INVALID_SYSCALL)
            ^
	    __NR_pselect6_time64 ?

> +		struct __kernel_timespec ts = {
> +			.tv_sec = timeout->tv_sec,
> +			.tv_nsec = timeout->tv_usec * 1000,
> +		};
> +		ret = tst_syscall(__NR_pselect6_time64, nfds, readfds, writefds, exceptfds, &ts, NULL);
> +		timeout->tv_sec = ts.tv_sec;
> +		timeout->tv_usec = ts.tv_nsec / 1000;
> +#else
> +		tst_brk(TCONF, "__NR_pselect6 time64 variant not supported");
> +#endif
> +		return ret;
> +	}
> +	case 4:
>  #ifdef __NR__newselect
>  		return tst_syscall(__NR__newselect, nfds, readfds, writefds, exceptfds, timeout);
>  #else
> @@ -72,11 +88,14 @@ static void select_info(void)
>  		tst_res(TINFO, "Testing SYS_pselect6 syscall");
>  	break;
>  	case 3:
> +		tst_res(TINFO, "Testing SYS_pselect6 time64 syscall");
> +	break;
> +	case 4:
>  		tst_res(TINFO, "Testing SYS__newselect syscall");
>  	break;
>  	}
>  }
>  
> -#define TEST_VARIANTS 4
> +#define TEST_VARIANTS 5

Also lastly but not least we should clean up the rest of the select
tests and add support for the different variants there as well.

Looking at them these are just copy&paste of the same test with a
different fds, we can easily merge them into a single test.

And the coverate in these tests is a bit lacking, we do not have a
single tests that would send a data over a pipe to a fd select is
watching and check that select was woken up by that. There is no such
test in the pselect/ directory either.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 15/19] syscalls/semop: Migrate to new test framework
  2020-06-26  6:22 ` [LTP] [PATCH V7 15/19] syscalls/semop: Migrate to new test framework Viresh Kumar
@ 2020-07-27 13:46   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-27 13:46 UTC (permalink / raw)
  To: ltp

Hi!
>  testcases/kernel/syscalls/ipc/semop/Makefile  |   4 +-
>  testcases/kernel/syscalls/ipc/semop/semop01.c | 140 ++++----
>  testcases/kernel/syscalls/ipc/semop/semop02.c | 145 +++------
>  testcases/kernel/syscalls/ipc/semop/semop03.c | 150 +++------
>  testcases/kernel/syscalls/ipc/semop/semop04.c | 165 ++++------
>  testcases/kernel/syscalls/ipc/semop/semop05.c | 303 ++++++++----------

Looking at the code, is there a real reson to keep the EFBIG tests in a
separate test? Why can't we just add these to the array in semop02? I
guess that we can merge semop04 to the semop02 as well.

Also if nothing else the support for uClinux has to be removed from
semop04. We have stopped supporting it a few years ago and any test
converted to the new library must remove it.

And lastly but not least, the tests should be a cleaned up a bit more,
there is still plenty of useless comments kept in the source. E.g. we do
have:

        /* Get an new IPC resource key. */
        semkey2 = GETIPCKEY();

How is that comment helping? It's stating the obvious. So can we please
get rid of these?

As well as the useless parts in the top level comment? For that part I
would do:

diff --git a/testcases/kernel/syscalls/ipc/semop/semop01.c b/testcases/kernel/syscalls/ipc/semop/semop01.c
index bcb45fa69..cbcbcea91 100644
--- a/testcases/kernel/syscalls/ipc/semop/semop01.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop01.c
@@ -1,41 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
-/* Copyright (c) International Business Machines  Corp., 2001 */
-
-/*
- * NAME
- *     semop01.c
- *
- * DESCRIPTION
- *     semop01 - test that semop() basic functionality is correct
- *
- * ALGORITHM
- *     create a semaphore set and initialize some values
- *     loop if that option was specified
- *     call semop() to set values for the primitive semaphores
- *     check the return code
- *       if failure, issue a FAIL message.
- *     otherwise,
- *       if doing functionality testing
- *             get the semaphore values and compare with expected values
- *             if correct,
- *                     issue a PASS message
- *             otherwise
- *                     issue a FAIL message
- *       else issue a PASS message
- *     call cleanup
- *
- * HISTORY
+/* Copyright (c) International Business Machines  Corp., 2001
  *     03/2001  - Written by Wayne Boyer
  *     17/01/02 - Modified. Manoj Iyer, IBM Austin. TX. manjo@austin.ibm.com
- *                4th argument to semctl() system call was modified according
- *                to man pages.
- *                In my opinion The test should not even have compiled but
- *                it was working due to some mysterious reason.
- *
- * RESTRICTIONS
- *     none
  */
-
+/*
+ * Test that semop() basic functionality is correct
+ */



-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 17/19] syscalls/utimensat: Migrate to new test framework
  2020-06-26  6:22 ` [LTP] [PATCH V7 17/19] syscalls/utimensat: Migrate to new test framework Viresh Kumar
@ 2020-07-27 15:35   ` Cyril Hrubis
  0 siblings, 0 replies; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-27 15:35 UTC (permalink / raw)
  To: ltp

Hi!
> This gets rid of the test script and updates the utimensat01.c file to
> handle most of the tests covered earlier (apart from testing the same
> for files owned by root, as the test is run as root right now).

We also lost a check if atime and mtime was modified or not.

The original script did set both to 0 and then depending on what have
been passed as the times and if the call succeeded checked if the value
stayed zero or was modified. Can we add this back as well?

Also the modification for the makefile and runtest file is part of the
patch that adds the time64 variant while it should have been part of
this patch.

Other than this there are a few minor things, for instance I do not see
the reason for double indirection in the struct mytime. And I would have
done some of the initialization in the test setup, e.g. why do we call
update_error(), re-create TEST_DIR, etc. on each run.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 14/19] syscalls/select6: Add support for time64 tests
  2020-07-27  9:40   ` Cyril Hrubis
@ 2020-07-28  7:23     ` Viresh Kumar
  2020-07-28  8:02       ` Arnd Bergmann
  0 siblings, 1 reply; 64+ messages in thread
From: Viresh Kumar @ 2020-07-28  7:23 UTC (permalink / raw)
  To: ltp

On 27-07-20, 11:40, Cyril Hrubis wrote:
> > @@ -38,7 +39,7 @@ static int do_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *except
> >  	}
> >  	case 2: {
> >  		int ret;
> > -		struct timespec ts = {
> > +		struct __kernel_old_timespec ts = {
> >  			.tv_sec = timeout->tv_sec,
> >  			.tv_nsec = timeout->tv_usec * 1000,
> >  		};
> 
> I'm a bit lost here, should we actually pass the __kernel_old_timespec
> to all the tst_syscall() fuctions here?

select, pselect6, pselect6_time64, and newselect, all have different
requirements, some take timespec and others take timeval.

Though after looking again at kernel sources I feel pselect6 may need
__kernel_timespec instead of __kernel_old_timespec, which is different than what
we did with other syscalls.

Arnd, can you confirm this please ?

> I guess that the only function that would take the argument as struct
> timeval is the select() glibc function, or do I miss something?

select in kernel also takes old timeval.

> > @@ -47,7 +48,22 @@ static int do_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *except
> >  		timeout->tv_usec = ts.tv_nsec / 1000;
> >  		return ret;
> >  	}
> > -	case 3:
> > +	case 3: {
> > +		int ret = 0;
> > +#if (__NR_clock_settime64 != __LTP__NR_INVALID_SYSCALL)
>             ^
> 	    __NR_pselect6_time64 ?
> 
> > +		struct __kernel_timespec ts = {
> > +			.tv_sec = timeout->tv_sec,
> > +			.tv_nsec = timeout->tv_usec * 1000,
> > +		};
> > +		ret = tst_syscall(__NR_pselect6_time64, nfds, readfds, writefds, exceptfds, &ts, NULL);
> > +		timeout->tv_sec = ts.tv_sec;
> > +		timeout->tv_usec = ts.tv_nsec / 1000;
> > +#else
> > +		tst_brk(TCONF, "__NR_pselect6 time64 variant not supported");
> > +#endif
> > +		return ret;
> > +	}
> > +	case 4:
> >  #ifdef __NR__newselect
> >  		return tst_syscall(__NR__newselect, nfds, readfds, writefds, exceptfds, timeout);
> >  #else
> > @@ -72,11 +88,14 @@ static void select_info(void)
> >  		tst_res(TINFO, "Testing SYS_pselect6 syscall");
> >  	break;
> >  	case 3:
> > +		tst_res(TINFO, "Testing SYS_pselect6 time64 syscall");
> > +	break;
> > +	case 4:
> >  		tst_res(TINFO, "Testing SYS__newselect syscall");
> >  	break;
> >  	}
> >  }
> >  
> > -#define TEST_VARIANTS 4
> > +#define TEST_VARIANTS 5
> 
> Also lastly but not least we should clean up the rest of the select
> tests and add support for the different variants there as well.

Maybe not. IIUC only pselect6 got changed to adapt to different timespec
structures and the other ones aren't.

Arnd: Can you confirm this as well ?

> Looking at them these are just copy&paste of the same test with a
> different fds, we can easily merge them into a single test.
> 
> And the coverate in these tests is a bit lacking, we do not have a
> single tests that would send a data over a pipe to a fd select is
> watching and check that select was woken up by that. There is no such
> test in the pselect/ directory either.

Hmm, I will look at that separately then.

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 14/19] syscalls/select6: Add support for time64 tests
  2020-07-28  7:23     ` Viresh Kumar
@ 2020-07-28  8:02       ` Arnd Bergmann
  0 siblings, 0 replies; 64+ messages in thread
From: Arnd Bergmann @ 2020-07-28  8:02 UTC (permalink / raw)
  To: ltp

On Tue, Jul 28, 2020 at 9:24 AM Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 27-07-20, 11:40, Cyril Hrubis wrote:
> > > @@ -38,7 +39,7 @@ static int do_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *except
> > >     }
> > >     case 2: {
> > >             int ret;
> > > -           struct timespec ts = {
> > > +           struct __kernel_old_timespec ts = {
> > >                     .tv_sec = timeout->tv_sec,
> > >                     .tv_nsec = timeout->tv_usec * 1000,
> > >             };
> >
> > I'm a bit lost here, should we actually pass the __kernel_old_timespec
> > to all the tst_syscall() fuctions here?
>
> select, pselect6, pselect6_time64, and newselect, all have different
> requirements, some take timespec and others take timeval.
>
> Though after looking again at kernel sources I feel pselect6 may need
> __kernel_timespec instead of __kernel_old_timespec, which is different than what
> we did with other syscalls.
>
> Arnd, can you confirm this please ?

On the kernel side, there is '__NR_pselect6', which refers to the syscall
that takes a 'struct __kernel_old_timespec'., while 32-bit architectures
have another syscall with the number __NR_pselect6_time64 that
takes a 'struct __kernel_timespec'.

The kernel implementation internally uses sys_pselect6_time32()
for the entry point that takes a 32-bit time_t (__NR_pselect6 on
32-bit architectures), and sys_pselect6() for the entry point
that passes a 64-bit time_t (__NR_pselect6 on 64-bit architectures
or __NR_pselect6_time64 on 32-bit architectures).

> > I guess that the only function that would take the argument as struct
> > timeval is the select() glibc function, or do I miss something?
>
> select in kernel also takes old timeval.

Correct, though most modern architectures do not implement this
and only provide pselect6 (and pselect6_time64).

> > > @@ -72,11 +88,14 @@ static void select_info(void)
> > >             tst_res(TINFO, "Testing SYS_pselect6 syscall");
> > >     break;
> > >     case 3:
> > > +           tst_res(TINFO, "Testing SYS_pselect6 time64 syscall");
> > > +   break;
> > > +   case 4:
> > >             tst_res(TINFO, "Testing SYS__newselect syscall");
> > >     break;
> > >     }
> > >  }
> > >
> > > -#define TEST_VARIANTS 4
> > > +#define TEST_VARIANTS 5
> >
> > Also lastly but not least we should clean up the rest of the select
> > tests and add support for the different variants there as well.
>
> Maybe not. IIUC only pselect6 got changed to adapt to different timespec
> structures and the other ones aren't.
>
> Arnd: Can you confirm this as well ?

Yes, this is correct. __NR__newselect (sys_select) and __NR_select
(sys_old_select or sys_select) are both considered obsolete and only
provided on older architectures for backwards compatibility with old libc
versions.

       Arnd

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 19/19] syscalls: clock_settime: Add test around y2038 vulnerability
  2020-06-26  6:22 ` [LTP] [PATCH V7 19/19] syscalls: clock_settime: Add test around y2038 vulnerability Viresh Kumar
@ 2020-07-28 12:11   ` Cyril Hrubis
  2020-08-04 12:37     ` Viresh Kumar
  0 siblings, 1 reply; 64+ messages in thread
From: Cyril Hrubis @ 2020-07-28 12:11 UTC (permalink / raw)
  To: ltp

Hi!
> This adds a test around the y2038 vulnerability, it sets the system time
> to just before y2038 time (i.e. max value that can be stored in s32),
> and adds a timer to expire just after crossing it.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  runtest/syscalls                              |   1 +
>  .../kernel/syscalls/clock_settime/.gitignore  |   1 +
>  .../syscalls/clock_settime/clock_settime03.c  | 119 ++++++++++++++++++
>  3 files changed, 121 insertions(+)
>  create mode 100644 testcases/kernel/syscalls/clock_settime/clock_settime03.c
> 
> diff --git a/runtest/syscalls b/runtest/syscalls
> index 2d2e24615be6..718ac1148392 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -101,6 +101,7 @@ leapsec01 leapsec01
>  
>  clock_settime01 clock_settime01
>  clock_settime02 clock_settime02
> +clock_settime03 clock_settime03
>  
>  clone01 clone01
>  clone02 clone02
> diff --git a/testcases/kernel/syscalls/clock_settime/.gitignore b/testcases/kernel/syscalls/clock_settime/.gitignore
> index 28121755006b..b66169b3eb7b 100644
> --- a/testcases/kernel/syscalls/clock_settime/.gitignore
> +++ b/testcases/kernel/syscalls/clock_settime/.gitignore
> @@ -1,2 +1,3 @@
>  clock_settime01
>  clock_settime02
> +clock_settime03
> diff --git a/testcases/kernel/syscalls/clock_settime/clock_settime03.c b/testcases/kernel/syscalls/clock_settime/clock_settime03.c
> new file mode 100644
> index 000000000000..7245863137b5
> --- /dev/null
> +++ b/testcases/kernel/syscalls/clock_settime/clock_settime03.c
> @@ -0,0 +1,119 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2020 Linaro Limited. All rights reserved.
> + * Author: Viresh Kumar<viresh.kumar@linaro.org>
> + *
> + * Check Year 2038 related vulnerabilities.
> + */
> +
> +#include <signal.h>
> +#include "config.h"
> +#include "tst_timer.h"
> +#include "tst_safe_clocks.h"
> +
> +#define TIMER_DELTA	3
> +#define ALLOWED_DELTA	(50 * 1000) /* 50 ms */
> +
> +static struct tst_ts start, end;
> +static struct tst_its its;
> +
> +static struct test_variants {
> +	int (*clock_gettime)(clockid_t clk_id, void *ts);
> +	int (*clock_settime)(clockid_t clk_id, void *ts);
> +	int (*timer_settime)(timer_t timerid, int flags, void *its,
> +			     void *old_its);
> +	enum tst_ts_type type;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_clock_settime != __LTP__NR_INVALID_SYSCALL)
> +	{ .clock_gettime = sys_clock_gettime, .clock_settime = sys_clock_settime, .timer_settime = sys_timer_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_clock_settime64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .clock_gettime = sys_clock_gettime64, .clock_settime = sys_clock_settime64, .timer_settime = sys_timer_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
> +static void setup(void)
> +{
> +	struct test_variants *tv = &variants[tst_variant];
> +
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	start.type = end.type = its.type = tv->type;
> +
> +	/* Check if the kernel is y2038 safe */
> +	if (tv->type != TST_KERN_OLD_TIMESPEC &&
> +	    sizeof(start.ts.kern_old_ts) == 8)

Huh, what exactly are we trying to assert here? First of all we make
sure we are not using KERN_OLD_TIMESPEC and then check it's size?

Shouldn't it be tv->type == TST_KERNL_OLD_TIMESPEC && sizeof(start.ts.kern_old_ts) != 8?
That way we would abort if the old timespec is not 64bit which would
make a bit more sense to me.

> +		tst_brk(TFAIL, "Not Y2038 safe to run test");

The test library does not work with tst_brk(TFAIL, ) see:

https://github.com/linux-test-project/ltp/issues/462


Also shouldn't we rather return TCONF here? It's not like the old kernel
timespec will ever change on 32bit architectures, so this would
practically fail the test on any 32bit arch, or did I miss something?

> +}
> +
> +static void run(void)
> +{
> +	struct test_variants *tv = &variants[tst_variant];
> +	unsigned long long time = 0x7FFFFFFE; /* Time just before y2038 */
> +	struct sigevent ev = {
> +		.sigev_notify = SIGEV_SIGNAL,
> +		.sigev_signo = SIGABRT,
> +	};
> +	long long diff;
> +	timer_t timer;
> +	sigset_t set;
> +	int sig, ret;
> +
> +	if (sigemptyset(&set) == -1)
> +		tst_brk(TBROK, "sigemptyset() failed");
> +
> +	if (sigaddset(&set, SIGABRT) == -1)
> +		tst_brk(TBROK, "sigaddset() failed");
> +
> +	if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
> +		tst_brk(TBROK, "sigprocmask() failed");
> +
> +	TEST(tst_syscall(__NR_timer_create, CLOCK_REALTIME_ALARM, &ev, &timer));
> +	if (TST_RET != 0)
> +		tst_brk(TBROK | TERRNO, "timer_create() failed");
> +
> +	tst_ts_set_sec(&start, time);
> +	tst_ts_set_nsec(&start, 0);
> +
> +	ret = tv->clock_settime(CLOCK_REALTIME, tst_ts_get(&start));
> +	if (ret == -1)
> +		tst_brk(TBROK | TERRNO, "clock_settime() failed");
> +
> +	tst_its_set_interval_sec(&its, 0);
> +	tst_its_set_interval_nsec(&its, 0);
> +	tst_its_set_value_sec(&its, time + TIMER_DELTA);
> +	tst_its_set_value_nsec(&its, 0);
> +
> +	TEST(tv->timer_settime(timer, TIMER_ABSTIME, tst_its_get(&its), NULL));
> +	if (TST_RET == -1)
> +		tst_brk(TBROK | TTERRNO, "timer_settime() failed");
> +
> +	if (sigwait(&set, &sig) == -1)
> +		tst_brk(TBROK, "sigwait() failed");
> +
> +	ret = tv->clock_gettime(CLOCK_REALTIME, tst_ts_get(&end));
> +	if (ret == -1)
> +		tst_brk(TBROK | TERRNO, "clock_gettime() failed");
> +
> +	if (sig == SIGABRT) {
> +		diff = tst_ts_diff_ms(end, start);
> +
> +		if (diff < TIMER_DELTA * 1000 - ALLOWED_DELTA ||

AFAIK timers must not expire sooner than requested so we can as well do just:

if (diff < TIMER_DELTA * 1000)
	tst_res(TFAL, "Timer expired too soon, after %llims", diff);

> +		    diff > TIMER_DELTA * 1000 + ALLOWED_DELTA)
> +			tst_res(TINFO, "Slept for unexpected duration, expected:%d, actual:%lld",
> +				TIMER_DELTA * 1000, diff);
> +		tst_res(TPASS, "clock_settime(): Y2038 test passed");
> +		return;
> +	}
> +
> +	tst_res(TFAIL, "clock_settime(): Y2038 test failed");

I guess that it would be a bit cleaner with:

	if (sig != SIGABRT) {
		tst_res(TFAIL, "...");
		return;
	}

	diff = ...
	...

> +}
> +
> +static struct tst_test test = {
> +	.test_all = run,
> +	.test_variants = ARRAY_SIZE(variants),
> +	.setup = setup,
> +	.needs_root = 1,
> +	.restore_wallclock = 1,
> +};
> -- 
> 2.25.0.rc1.19.g042ed3e048af
> 

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [LTP] [PATCH V7 19/19] syscalls: clock_settime: Add test around y2038 vulnerability
  2020-07-28 12:11   ` Cyril Hrubis
@ 2020-08-04 12:37     ` Viresh Kumar
  0 siblings, 0 replies; 64+ messages in thread
From: Viresh Kumar @ 2020-08-04 12:37 UTC (permalink / raw)
  To: ltp

On 28-07-20, 14:11, Cyril Hrubis wrote:
> Hi!
> > +++ b/testcases/kernel/syscalls/clock_settime/clock_settime03.c
> > +static void setup(void)
> > +{
> > +	struct test_variants *tv = &variants[tst_variant];
> > +
> > +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> > +	start.type = end.type = its.type = tv->type;
> > +
> > +	/* Check if the kernel is y2038 safe */
> > +	if (tv->type != TST_KERN_OLD_TIMESPEC &&

Wow!

> > +	    sizeof(start.ts.kern_old_ts) == 8)
> 
> Huh, what exactly are we trying to assert here? First of all we make
> sure we are not using KERN_OLD_TIMESPEC and then check it's size?
> 
> Shouldn't it be tv->type == TST_KERNL_OLD_TIMESPEC && sizeof(start.ts.kern_old_ts) != 8?
> That way we would abort if the old timespec is not 64bit which would
> make a bit more sense to me.

Yeah, thanks for noticing this. I kept it like that throughout the
discussion with Arnd and finally made the mistake while sending the
patch :(

-- 
viresh

^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2020-08-04 12:37 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-26  6:22 [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
2020-06-26  6:22 ` [LTP] [PATCH V7 01/19] tst_timer: Add new definitions Viresh Kumar
2020-06-26  9:49   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 02/19] syscalls/timer_gettime: Add support for time64 tests Viresh Kumar
2020-06-26  9:49   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 03/19] syscalls/timer_settime: " Viresh Kumar
2020-06-29  9:39   ` Cyril Hrubis
2020-06-29 11:43     ` Viresh Kumar
2020-06-26  6:22 ` [LTP] [PATCH V7 04/19] syscalls/timerfd: " Viresh Kumar
2020-07-02 12:24   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 05/19] syscalls/sched_rr_get_interval: " Viresh Kumar
2020-07-02 13:06   ` Cyril Hrubis
2020-07-03  3:15     ` Viresh Kumar
2020-07-03  5:52       ` Yang Xu
2020-07-03  7:26         ` Viresh Kumar
2020-07-03  7:38   ` [LTP] [PATCH] syscalls/sched_rr_get_interval: Validate the timeslice Viresh Kumar
2020-07-03  7:43     ` Yang Xu
2020-07-03  7:51       ` Viresh Kumar
2020-07-03  8:00         ` Yang Xu
2020-07-03  8:18           ` Viresh Kumar
2020-07-03  9:01             ` Yang Xu
2020-07-03 14:08     ` Cyril Hrubis
2020-07-06  3:31     ` [LTP] [PATCH V2] " Viresh Kumar
2020-07-06  4:41       ` Yang Xu
2020-07-07  9:30       ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 06/19] syscalls/futex: Merge futex_wait_bitset tests Viresh Kumar
2020-07-03  9:15   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 07/19] syscalls/futex: Add support for time64 tests Viresh Kumar
2020-07-03 12:45   ` Cyril Hrubis
2020-07-06 10:40     ` Viresh Kumar
2020-07-06 11:36       ` Viresh Kumar
2020-07-06 11:40   ` [LTP] [PATCH V7.1 " Viresh Kumar
2020-07-23 19:44     ` Cyril Hrubis
2020-07-24  2:33       ` Viresh Kumar
2020-06-26  6:22 ` [LTP] [PATCH V7 08/19] syscalls/io_pgetevents: " Viresh Kumar
2020-07-03 14:59   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 09/19] syscalls/sigwaitinfo: Migrate to new test framework Viresh Kumar
2020-07-03 13:58   ` Cyril Hrubis
2020-07-06  2:39     ` Viresh Kumar
2020-07-07 15:16       ` Cyril Hrubis
2020-07-09 10:46         ` Viresh Kumar
2020-06-26  6:22 ` [LTP] [PATCH V7 10/19] syscalls/rt_sigtimedwait: Add support for time64 tests Viresh Kumar
2020-07-22 10:03   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 11/19] syscalls/mq_timed{send|receive}: " Viresh Kumar
2020-07-24 14:51   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 12/19] syscalls/recvmmsg: " Viresh Kumar
2020-07-24 15:13   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 13/19] syscalls/ppoll: " Viresh Kumar
2020-07-27  9:17   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 14/19] syscalls/select6: " Viresh Kumar
2020-07-27  9:40   ` Cyril Hrubis
2020-07-28  7:23     ` Viresh Kumar
2020-07-28  8:02       ` Arnd Bergmann
2020-06-26  6:22 ` [LTP] [PATCH V7 15/19] syscalls/semop: Migrate to new test framework Viresh Kumar
2020-07-27 13:46   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 16/19] syscalls/semtimedop: Add support for semtimedop and its time64 version Viresh Kumar
2020-06-26  6:22 ` [LTP] [PATCH V7 17/19] syscalls/utimensat: Migrate to new test framework Viresh Kumar
2020-07-27 15:35   ` Cyril Hrubis
2020-06-26  6:22 ` [LTP] [PATCH V7 18/19] syscalls/utimensat: Add support for time64 tests Viresh Kumar
2020-06-26  6:22 ` [LTP] [PATCH V7 19/19] syscalls: clock_settime: Add test around y2038 vulnerability Viresh Kumar
2020-07-28 12:11   ` Cyril Hrubis
2020-08-04 12:37     ` Viresh Kumar
2020-07-20 10:19 ` [LTP] [PATCH V7 00/19] Syscalls: Add support for time64 variants Viresh Kumar
2020-07-22 10:04   ` Cyril Hrubis

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.