Linux Audio

Check our new training course

Loading...
  1// SPDX-License-Identifier: GPL-2.0
  2#define _GNU_SOURCE
  3#include <sched.h>
  4
  5#include <linux/unistd.h>
  6#include <linux/futex.h>
  7#include <stdio.h>
  8#include <string.h>
  9#include <sys/syscall.h>
 10#include <sys/types.h>
 11#include <sys/wait.h>
 12#include <time.h>
 13#include <unistd.h>
 14
 15#include "log.h"
 16#include "timens.h"
 17
 18#define NSEC_PER_SEC 1000000000ULL
 19
 20static int run_test(int clockid)
 21{
 22	int futex_op = FUTEX_WAIT_BITSET;
 23	struct timespec timeout, end;
 24	int val = 0;
 25
 26	if (clockid == CLOCK_REALTIME)
 27		futex_op |= FUTEX_CLOCK_REALTIME;
 28
 29	clock_gettime(clockid, &timeout);
 30	timeout.tv_nsec += NSEC_PER_SEC / 10; // 100ms
 31	if (timeout.tv_nsec > NSEC_PER_SEC) {
 32		timeout.tv_sec++;
 33		timeout.tv_nsec -= NSEC_PER_SEC;
 34	}
 35
 36	if (syscall(__NR_futex, &val, futex_op, 0,
 37		    &timeout, 0, FUTEX_BITSET_MATCH_ANY) >= 0) {
 38		ksft_test_result_fail("futex didn't return ETIMEDOUT\n");
 39		return 1;
 40	}
 41
 42	if (errno != ETIMEDOUT) {
 43		ksft_test_result_fail("futex didn't return ETIMEDOUT: %s\n",
 44							strerror(errno));
 45		return 1;
 46	}
 47
 48	clock_gettime(clockid, &end);
 49
 50	if (end.tv_sec < timeout.tv_sec ||
 51	    (end.tv_sec == timeout.tv_sec && end.tv_nsec < timeout.tv_nsec)) {
 52		ksft_test_result_fail("futex slept less than 100ms\n");
 53		return 1;
 54	}
 55
 56
 57	ksft_test_result_pass("futex with the %d clockid\n", clockid);
 58
 59	return 0;
 60}
 61
 62int main(int argc, char *argv[])
 63{
 64	int status, len, fd;
 65	char buf[4096];
 66	pid_t pid;
 67	struct timespec mtime_now;
 68
 69	nscheck();
 70
 71	ksft_set_plan(2);
 72
 73	clock_gettime(CLOCK_MONOTONIC, &mtime_now);
 74
 75	if (unshare_timens())
 76		return 1;
 77
 78	len = snprintf(buf, sizeof(buf), "%d %d 0",
 79			CLOCK_MONOTONIC, 70 * 24 * 3600);
 80	fd = open("/proc/self/timens_offsets", O_WRONLY);
 81	if (fd < 0)
 82		return pr_perror("/proc/self/timens_offsets");
 83
 84	if (write(fd, buf, len) != len)
 85		return pr_perror("/proc/self/timens_offsets");
 86
 87	close(fd);
 88
 89	pid = fork();
 90	if (pid < 0)
 91		return pr_perror("Unable to fork");
 92	if (pid == 0) {
 93		int ret = 0;
 94
 95		ret |= run_test(CLOCK_REALTIME);
 96		ret |= run_test(CLOCK_MONOTONIC);
 97		if (ret)
 98			ksft_exit_fail();
 99		ksft_exit_pass();
100		return 0;
101	}
102
103	if (waitpid(pid, &status, 0) != pid)
104		return pr_perror("Unable to wait the child process");
105
106	if (WIFEXITED(status))
107		return WEXITSTATUS(status);
108
109	return 1;
110}