[PATCH v4 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall

Florian Bezdeka florian.bezdeka at siemens.com
Fri May 7 18:17:10 CEST 2021


On 07.05.21 17:58, Jan Kiszka wrote:
> On 07.05.21 14:49, Florian Bezdeka wrote:
>> Introducing a new smokey plugin that can be extended for all kind of
>> y2038 tests. For now we are testing the new sc_cobalt_sem_timedwait64
>> syscall without using any libc wrappers provided by libcobalt.
>>
>> Signed-off-by: Florian Bezdeka <florian.bezdeka at siemens.com>
>> ---
>>  configure.ac                           |   1 +
>>  testsuite/smokey/Makefile.am           |   6 +-
>>  testsuite/smokey/y2038/Makefile.am     |  10 ++
>>  testsuite/smokey/y2038/syscall-tests.c | 177 +++++++++++++++++++++++++
>>  4 files changed, 192 insertions(+), 2 deletions(-)
>>  create mode 100644 testsuite/smokey/y2038/Makefile.am
>>  create mode 100644 testsuite/smokey/y2038/syscall-tests.c
>>
>> diff --git a/configure.ac b/configure.ac
>> index abe538dbd..bd5fd5ba9 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -990,6 +990,7 @@ AC_CONFIG_FILES([ \
>>  	testsuite/smokey/net_common/Makefile \
>>  	testsuite/smokey/cpu-affinity/Makefile \
>>  	testsuite/smokey/gdb/Makefile \
>> +	testsuite/smokey/y2038/Makefile \
>>  	testsuite/clocktest/Makefile \
>>  	testsuite/xeno-test/Makefile \
>>  	utils/Makefile \
>> diff --git a/testsuite/smokey/Makefile.am b/testsuite. Eventually, we /smokey/Makefile.am
>> index 02613c7dc..56c873026 100644
>> --- a/testsuite/smokey/Makefile.am
>> +++ b/testsuite/smokey/Makefile.am
>> @@ -38,7 +38,8 @@ COBALT_SUBDIRS = 	\
>>  	timerfd		\
>>  	tsc		\
>>  	vdso-access 	\
>> -	xddp
>> +	xddp		\
>> +	y2038
>>  
>>  MERCURY_SUBDIRS =	\
>>  	memory-heapmem	\
>> @@ -76,7 +77,8 @@ DIST_SUBDIRS = 		\
>>  	timerfd		\
>>  	tsc		\
>>  	vdso-access 	\
>> -	xddp
>> +	xddp		\
>> +	y2038
>>  
>>  if XENO_COBALT
>>  if CONFIG_XENO_LIBS_DLOPEN
>> diff --git a/testsuite/smokey/y2038/Makefile.am b/testsuite/smokey/y2038/Makefile.am
>> new file mode 100644
>> index 000000000..4bf629e87
>> --- /dev/null
>> +++ b/testsuite/smokey/y2038/Makefile.am
>> @@ -0,0 +1,10 @@
>> +
>> +noinst_LIBRARIES = liby2038>> +
>> +liby2038_a_SOURCES = syscall-tests.c
>> +
>> +liby2038_a_CPPFLAGS = 	\
>> +	@XENO_USER_CFLAGS@	\
>> +	-I$(top_srcdir)		\
>> +	-I$(top_srcdir)/include \
>> +	-I$(top_srcdir)/lib/cobalt/arch/@XENO_TARGET_ARCH@/include
> 
> Is that really needed? How do libs get access to those headers?

There should not be a need to directly call syscalls, so I guess that's
the reason why this interface is "private" to libcobalt and external
libraries are "unable" to use it.

Normally we would call the time64 related syscalls through the libc
wrapper provided by libcobalt. But as current glibc does not have y2038
built in yet, we are kind of lost. musl has y2038 already but I never
succeeded in building Xenomai against it.

v3 of this patch used syscall() instead of the internal / private API.
But as we now know that does not work on ARM. It's still not clear to me
if there is still another problem somewhere in the ARM syscall
prologue/epilogue. Not an ARM expert, so hard to say...

> 
>> diff --git a/testsuite/smokey/y2038/syscall-tests.c b/testsuite/smokey/y2038/syscall-tests.c
>> new file mode 100644
>> index 000000000..9d5b93ef9
>> --- /dev/null
>> +++ b/testsuite/smokey/y2038/syscall-tests.c
>> @@ -0,0 +1,177 @@
>> +/*
>> + * y2038 tests
>> + *
>> + * Copyright (c) Siemens AG 2021
>> + *
>> + * Authors:
>> + *  Florian Bezdeka <florian.bezdeka at siemens.com>
>> + *
>> + * Released under the terms of GPLv2.
>> + */
>> +#include <asm/xenomai/syscall.h>
>> +#include <cobalt/uapi/syscall.h>
>> +#include <smokey/smokey.h>
>> +#include <semaphore.h>
>> +#include <unistd.h>
>> +#include <stdint.h>
>> +#include <stdbool.h>
>> +#include <errno.h>
>> +
>> +smokey_test_plugin(y2038, SMOKEY_NOARGS, "Validate correct y2038 support");
>> +
>> +/*
>> + * libc independent data type representing a time64_t based struct timespec
>> + */
>> +struct xn_timespec64 {
>> +	int64_t tv_sec;
>> +	int64_t tv_nsec;
>> +};
>> +
>> +#define NSEC_PER_SEC 1000000000
>> +
>> +static void ts_normalise(struct xn_timespec64 *ts)
>> +{
>> +	while (ts->tv_nsec >= NSEC_PER_SEC) {
>> +		ts->tv_nsec += 1;
>> +		ts->tv_nsec -= NSEC_PER_SEC;
>> +	}
>> +
>> +	while (ts->tv_nsec <= -NSEC_PER_SEC) {
>> +		ts->tv_sec -= 1;
>> +		ts->tv_nsec += NSEC_PER_SEC;
>> +	}
>> +
>> +	if (ts->tv_nsec < 0) {
>> +		/*
>> +		 * Negative nanoseconds isn't valid according to POSIX.
>> +		 * Decrement tv_sec and roll tv_nsec over.
>> +		 */
>> +		ts->tv_sec -= 1;
>> +		ts->tv_nsec = (NSEC_PER_SEC + ts->tv_nsec);
>> +	}
>> +}
>> +
>> +static inline void ts_add_ns(struct xn_timespec64 *ts, int ns)
>> +{
>> +	ts->tv_nsec += ns;
>> +	ts_normalise(ts);
>> +}
>> +
>> +/**
>> + * Compare two struct timespec instances
>> + *
>> + * @param a
>> + * @param b
>> + * @return True if a < b, false otherwise
>> + */
>> +static inline bool ts_less(const struct xn_timespec64 *a,
>> +			   const struct xn_timespec64 *b)
>> +{
>> +	if (a->tv_sec < b->tv_sec)
>> +		return true;
>> +
>> +	if (a->tv_sec > b->tv_sec)
>> +		return false;
>> +
>> +	/* a->tv_sec == b->tv_sec */
>> +
>> +	if (a->tv_nsec < b->tv_nsec)
>> +		return true;
>> +
>> +	return false;
>> +}
>> +
>> +static int test_sc_cobalt_sem_timedwait64(void)
>> +{
>> +	int ret;
>> +	sem_t sem;
>> +	int sc_nr = sc_cobalt_sem_timedwait64;
> 
> Why a variable? Do shorting the statements?

Yes.

> 
> How about wrapping the calls into helper functions (one per new syscall)?

We have 17 y2038 related syscalls on the list already. That would
produce a lot of helpers just used for testing. But why not... If you
prefer we could do that. But remember that Song already sent out some
patches using this series as pattern or "base".

> 
>> +	struct xn_timespec64 ts64, ts_wu;
>> +	struct timespec ts_nat;
>> +
>> +	sem_init(&sem, 0, 0);
>> +
>> +	/* Make sure we don't crash because of NULL pointers */
>> +	ret = XENOMAI_SYSCALL2(sc_nr, NULL, NULL);
>> +	if (ret == -ENOSYS) {
>> +		smokey_note("sem_timedwait64: skipped. (no kernel support)");
>> +		return 0; // Not implemented, nothing to test, success
>> +	}
>> +	if (!smokey_assert(ret == -EINVAL))
>> +		return ret;
>> +
>> +	/* Timeout is never read by the kernel, so NULL should be OK */
>> +	sem_post(&sem);
>> +	ret = XENOMAI_SYSCALL2(sc_nr, &sem, NULL);
>> +	if (!smokey_assert(!ret))
>> +		return ret;
>> +
>> +	/*
>> +	 * The semaphore is already exhausted, so calling again will validate
>> +	 * the provided timeout now. Providing NULL has to deliver EFAULT
>> +	 */
>> +	ret = XENOMAI_SYSCALL2(sc_nr, &sem, NULL);
>> +	if (!smokey_assert(ret == -EFAULT))
>> +		return ret;
>> +
>> +	/*
>> +	 * The semaphore is already exhausted, so calling again will validate
>> +	 * the provided timeout now. Providing an invalid adress has to deliver
>> +	 * EFAULT
>> +	 */
>> +	ret = XENOMAI_SYSCALL2(sc_nr, &sem, (void *)0xdeadbeefUL);
>> +	if (!smokey_assert(ret == -EFAULT))
>> +		return ret;
>> +
>> +	/*
>> +	 * The semaphore is still exhausted, calling again will validate the
>> +	 * timeout, providing an invalid timeout has to deliver EINVAL
>> +	 */
>> +	ts64.tv_sec = -1;
>> +	ret = XENOMAI_SYSCALL2(sc_nr, &sem, &ts64);
>> +	if (!smokey_assert(ret == -EINVAL))
>> +		return ret;
>> +
>> +	/*
>> +	 * Providing a valid timeout, waiting for it to time out and check
>> +	 * that we didn't come back to early.
>> +	 */
>> +	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ts64.tv_sec = ts_nat.tv_sec;
>> +	ts64.tv_nsec = ts_nat.tv_nsec;
>> +	ts_add_ns(&ts64, 500000);
>> +
>> +	ret = XENOMAI_SYSCALL2(sc_nr, &sem, &ts64);
>> +	if (!smokey_assert(ret == -ETIMEDOUT))
>> +		return ret;
>> +
>> +	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ts_wu.tv_sec = ts_nat.tv_sec;
>> +	ts_wu.tv_nsec = ts_nat.tv_nsec;
>> +
>> +	if (ts_less(&ts_wu, &ts64))
>> +		smokey_warning("sem_timedwait64 returned to early!\n"
>> +			       "Expected wakeup at: %lld sec %lld nsec\n"
>> +			       "Back at           : %lld sec %lld nsec\n",
>> +			       ts64.tv_sec, ts64.tv_nsec, ts_wu.tv_sec,
>> +			       ts_wu.tv_nsec);
>> +
>> +	return 0;
>> +}
>> +
>> +static int run_y2038(struct smokey_test *t, int argc, char *const argv[])
>> +{
>> +	int ret;
>> +
>> +	ret = test_sc_cobalt_sem_timedwait64();
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>>
> 
> Jan
> 


-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux



More information about the Xenomai mailing list