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 20 static 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 62 int 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 ksft_print_header(); 70 71 nscheck(); 72 73 ksft_set_plan(2); 74 75 clock_gettime(CLOCK_MONOTONIC, &mtime_now); 76 77 if (unshare_timens()) 78 return 1; 79 80 len = snprintf(buf, sizeof(buf), "%d %d 0", 81 CLOCK_MONOTONIC, 70 * 24 * 3600); 82 fd = open("/proc/self/timens_offsets", O_WRONLY); 83 if (fd < 0) 84 return pr_perror("/proc/self/timens_offsets"); 85 86 if (write(fd, buf, len) != len) 87 return pr_perror("/proc/self/timens_offsets"); 88 89 close(fd); 90 91 pid = fork(); 92 if (pid < 0) 93 return pr_perror("Unable to fork"); 94 if (pid == 0) { 95 int ret = 0; 96 97 ret |= run_test(CLOCK_REALTIME); 98 ret |= run_test(CLOCK_MONOTONIC); 99 if (ret) 100 ksft_exit_fail(); 101 ksft_exit_pass(); 102 return 0; 103 } 104 105 if (waitpid(pid, &status, 0) != pid) 106 return pr_perror("Unable to wait the child process"); 107 108 if (WIFEXITED(status)) 109 return WEXITSTATUS(status); 110 111 return 1; 112 } 113