<commit_before>/*
 * Copyright (c) 2016 <NAME> <<EMAIL>>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "tests.h"

#include <asm/unistd.h>

#ifdef __NR_futex

# include <errno.h>
# include <stdarg.h>
# include <stdbool.h>
# include <stdio.h>
# include <stdint.h>
# include <unistd.h>

# include <sys/time.h>

# ifndef FUTEX_PRIVATE_FLAG
#  define FUTEX_PRIVATE_FLAG 128
# endif
# ifndef FUTEX_CLOCK_REALTIME
#  define FUTEX_CLOCK_REALTIME 256
# endif
# ifndef FUTEX_CMD_MASK
#  define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
# endif

# include "xlat.h"
# include "xlat/futexops.h"
# include "xlat/futexwakeops.h"
# include "xlat/futexwakecmps.h"

static struct timespec *tmout;

void futex_error(int *uaddr, int op, unsigned long val, unsigned long timeout,
	int *uaddr2, unsigned long val3, int rc)
{
	perror_msg_and_fail("futex(%p, %#x, %#x, %#lx, %p, %#x) = %d",
		uaddr, op, (unsigned)val, timeout, uaddr, (unsigned)val3, rc);
}

# define CHECK_FUTEX_GENERIC(uaddr, op, val, timeout, uaddr2, val3, check, \
	enosys) \
	do { \
		rc = syscall(__NR_futex, (uaddr), (op), (val), (timeout), \
			(uaddr2), (val3)); \
		/* It is here due to EPERM on WAKE_OP on AArch64 */ \
		if ((rc == -1) && (errno == EPERM)) \
			break; \
		if (enosys && (rc == -1) && (errno == ENOSYS)) \
			break; \
		if (!(check)) \
			futex_error((uaddr), (op), (val), \
				(unsigned long)(timeout), (int *)(uaddr2), \
				(val3), rc); \
	} while (0)

# define CHECK_FUTEX_ENOSYS(uaddr, op, val, timeout, uaddr2, val3, check) \
	CHECK_FUTEX_GENERIC(uaddr, op, val, timeout, uaddr2, val3, check, 1)

# define CHECK_FUTEX(uaddr, op, val, timeout, uaddr2, val3, check) \
	CHECK_FUTEX_GENERIC(uaddr, op, val, timeout, uaddr2, val3, check, 0)

enum argmask {
	ARG3 = 1 << 0,
	ARG4 = 1 << 1,
	ARG5 = 1 << 2,
	ARG6 = 1 << 3,
};

void invalid_op(int *val, int op, uint32_t argmask, ...)
{
	static const unsigned long args[] = {
		(unsigned long)0xface1e55deadbee1ULL,
		(unsigned long)0xface1e56deadbee2ULL,
		(unsigned long)0xface1e57deadbee3ULL,
		(unsigned long)0xface1e58deadbee4ULL,
	};
	/* Since timeout value is copied before full op check, we should provide
	 * some valid timeout address or NULL */
	int cmd = op & FUTEX_CMD_MASK;
	bool valid_timeout = (cmd == FUTEX_WAIT) || (cmd == FUTEX_LOCK_PI) ||
		(cmd == FUTEX_WAIT_BITSET) || (cmd == FUTEX_WAIT_REQUEUE_PI);
	bool timeout_is_val2 = (cmd == FUTEX_REQUEUE) ||
		(cmd == FUTEX_CMP_REQUEUE) || (cmd == FUTEX_WAKE_OP) ||
		(cmd == FUTEX_CMP_REQUEUE_PI);
	const char *fmt;
	int saved_errno;
	int rc;
	int i;
	va_list ap;


	CHECK_FUTEX(val, op, args[0], valid_timeout ? 0 : args[1], args[2],
		args[3], (rc == -1) && (errno == ENOSYS));
	saved_errno = errno;
	printf("futex(%p, %#x /* FUTEX_??? */", val, op);

	va_start(ap, argmask);

	for (i = 0; i < 4; i++) {
		if (argmask & (1 << i)) {
			fmt = va_arg(ap, const char *);

			printf(", ");

			if (((1 << i) == ARG3) || ((1 << i) == ARG6) ||
			    (((1 << i) == ARG4) && timeout_is_val2))
				printf(fmt, (unsigned)args[i]);
			else
				printf(fmt, args[i]);
		}
	}

	va_end(ap);

	errno = saved_errno;
	printf(") = -1 ENOSYS (%m)\n");
}

const char *sprintrc(long rc)
{
	enum { RES_BUF_SIZE = 256 };
	static char buf[RES_BUF_SIZE];

	if (rc == 0)
		return "0";

	snprintf(buf, sizeof(buf), "-1 %s (%m)", errno2name());

	return buf;
}

# define CHECK_INVALID_CLOCKRT(op, ...) \
	do { \
		invalid_op(uaddr, FUTEX_CLOCK_REALTIME | (op), __VA_ARGS__); \
		invalid_op(uaddr, FUTEX_CLOCK_REALTIME | FUTEX_PRIVATE_FLAG | \
			(op), __VA_ARGS__); \
	} while (0)

/* Value which differs from one stored in int *val */
# define VAL     ((unsigned long)0xbadda7a0facefeedLLU)
# define VAL_PR  ((unsigned)VAL)

# define VAL2    ((unsigned long)0xbadda7a0ca7b100dLLU)<commit_msg>tests/futex: increase sprintrc static buffer size<commit_after>/*
 * Copyright (c) 2016 <NAME> <<EMAIL>>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "tests.h"

#include <asm/unistd.h>

#ifdef __NR_futex

# include <errno.h>
# include <stdarg.h>
# include <stdbool.h>
# include <stdio.h>
# include <stdint.h>
# include <unistd.h>

# include <sys/time.h>

# ifndef FUTEX_PRIVATE_FLAG
#  define FUTEX_PRIVATE_FLAG 128
# endif
# ifndef FUTEX_CLOCK_REALTIME
#  define FUTEX_CLOCK_REALTIME 256
# endif
# ifndef FUTEX_CMD_MASK
#  define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
# endif

# include "xlat.h"
# include "xlat/futexops.h"
# include "xlat/futexwakeops.h"
# include "xlat/futexwakecmps.h"

static struct timespec *tmout;

void futex_error(int *uaddr, int op, unsigned long val, unsigned long timeout,
	int *uaddr2, unsigned long val3, int rc)
{
	perror_msg_and_fail("futex(%p, %#x, %#x, %#lx, %p, %#x) = %d",
		uaddr, op, (unsigned)val, timeout, uaddr, (unsigned)val3, rc);
}

# define CHECK_FUTEX_GENERIC(uaddr, op, val, timeout, uaddr2, val3, check, \
	enosys) \
	do { \
		rc = syscall(__NR_futex, (uaddr), (op), (val), (timeout), \
			(uaddr2), (val3)); \
		/* It is here due to EPERM on WAKE_OP on AArch64 */ \
		if ((rc == -1) && (errno == EPERM)) \
			break; \
		if (enosys && (rc == -1) && (errno == ENOSYS)) \
			break; \
		if (!(check)) \
			futex_error((uaddr), (op), (val), \
				(unsigned long)(timeout), (int *)(uaddr2), \
				(val3), rc); \
	} while (0)

# define CHECK_FUTEX_ENOSYS(uaddr, op, val, timeout, uaddr2, val3, check) \
	CHECK_FUTEX_GENERIC(uaddr, op, val, timeout, uaddr2, val3, check, 1)

# define CHECK_FUTEX(uaddr, op, val, timeout, uaddr2, val3, check) \
	CHECK_FUTEX_GENERIC(uaddr, op, val, timeout, uaddr2, val3, check, 0)

enum argmask {
	ARG3 = 1 << 0,
	ARG4 = 1 << 1,
	ARG5 = 1 << 2,
	ARG6 = 1 << 3,
};

void invalid_op(int *val, int op, uint32_t argmask, ...)
{
	static const unsigned long args[] = {
		(unsigned long)0xface1e55deadbee1ULL,
		(unsigned long)0xface1e56deadbee2ULL,
		(unsigned long)0xface1e57deadbee3ULL,
		(unsigned long)0xface1e58deadbee4ULL,
	};
	/* Since timeout value is copied before full op check, we should provide
	 * some valid timeout address or NULL */
	int cmd = op & FUTEX_CMD_MASK;
	bool valid_timeout = (cmd == FUTEX_WAIT) || (cmd == FUTEX_LOCK_PI) ||
		(cmd == FUTEX_WAIT_BITSET) || (cmd == FUTEX_WAIT_REQUEUE_PI);
	bool timeout_is_val2 = (cmd == FUTEX_REQUEUE) ||
		(cmd == FUTEX_CMP_REQUEUE) || (cmd == FUTEX_WAKE_OP) ||
		(cmd == FUTEX_CMP_REQUEUE_PI);
	const char *fmt;
	int saved_errno;
	int rc;
	int i;
	va_list ap;


	CHECK_FUTEX(val, op, args[0], valid_timeout ? 0 : args[1], args[2],
		args[3], (rc == -1) && (errno == ENOSYS));
	saved_errno = errno;
	printf("futex(%p, %#x /* FUTEX_??? */", val, op);

	va_start(ap, argmask);

	for (i = 0; i < 4; i++) {
		if (argmask & (1 << i)) {
			fmt = va_arg(ap, const char *);

			printf(", ");

			if (((1 << i) == ARG3) || ((1 << i) == ARG6) ||
			    (((1 << i) == ARG4) && timeout_is_val2))
				printf(fmt, (unsigned)args[i]);
			else
				printf(fmt, args[i]);
		}
	}

	va_end(ap);

	errno = saved_errno;
	printf(") = -1 ENOSYS (%m)\n");
}

const char *sprintrc(long rc)
{
	static char buf[4096];

	if (rc == 0)
		return "0";

	snprintf(buf, sizeof(buf), "-1 %s (%m)", errno2name());

	return buf;
}

# define CHECK_INVALID_CLOCKRT(op, ...) \
	do { \
		invalid_op(uaddr, FUTEX_CLOCK_REALTIME | (op), __VA_ARGS__); \
		invalid_op(uaddr, FUTEX_CLOCK_REALTIME | FUTEX_PRIVATE_FLAG | \
			(op), __VA_ARGS__); \
	} while (0)

/* Value which differs from one stored in int *val */
# define VAL     ((unsigned long)0xbadda7a0facefeedLLU)
# define VAL_PR  ((unsigned)VAL)

# define VAL2    ((unsigned long)0xbadda7a0ca7b100dLLU)
{'fraction_non_alphanumeric': 0.13638124757845796, 'fraction_numerical': 0.021018984889577683, 'mean_word_length': 4.017006802721088, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3459510', 'n_tokens_mistral': 4131, 'n_tokens_neox': 3795, 'n_words': 1169}