Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #define _GNU_SOURCE
0003 #include <sched.h>
0004 
0005 #include <linux/unistd.h>
0006 #include <linux/futex.h>
0007 #include <stdio.h>
0008 #include <string.h>
0009 #include <sys/syscall.h>
0010 #include <sys/types.h>
0011 #include <sys/wait.h>
0012 #include <time.h>
0013 #include <unistd.h>
0014 
0015 #include "log.h"
0016 #include "timens.h"
0017 
0018 #define NSEC_PER_SEC 1000000000ULL
0019 
0020 static int run_test(int clockid)
0021 {
0022     int futex_op = FUTEX_WAIT_BITSET;
0023     struct timespec timeout, end;
0024     int val = 0;
0025 
0026     if (clockid == CLOCK_REALTIME)
0027         futex_op |= FUTEX_CLOCK_REALTIME;
0028 
0029     clock_gettime(clockid, &timeout);
0030     timeout.tv_nsec += NSEC_PER_SEC / 10; // 100ms
0031     if (timeout.tv_nsec > NSEC_PER_SEC) {
0032         timeout.tv_sec++;
0033         timeout.tv_nsec -= NSEC_PER_SEC;
0034     }
0035 
0036     if (syscall(__NR_futex, &val, futex_op, 0,
0037             &timeout, 0, FUTEX_BITSET_MATCH_ANY) >= 0) {
0038         ksft_test_result_fail("futex didn't return ETIMEDOUT\n");
0039         return 1;
0040     }
0041 
0042     if (errno != ETIMEDOUT) {
0043         ksft_test_result_fail("futex didn't return ETIMEDOUT: %s\n",
0044                             strerror(errno));
0045         return 1;
0046     }
0047 
0048     clock_gettime(clockid, &end);
0049 
0050     if (end.tv_sec < timeout.tv_sec ||
0051         (end.tv_sec == timeout.tv_sec && end.tv_nsec < timeout.tv_nsec)) {
0052         ksft_test_result_fail("futex slept less than 100ms\n");
0053         return 1;
0054     }
0055 
0056 
0057     ksft_test_result_pass("futex with the %d clockid\n", clockid);
0058 
0059     return 0;
0060 }
0061 
0062 int main(int argc, char *argv[])
0063 {
0064     int status, len, fd;
0065     char buf[4096];
0066     pid_t pid;
0067     struct timespec mtime_now;
0068 
0069     nscheck();
0070 
0071     ksft_set_plan(2);
0072 
0073     clock_gettime(CLOCK_MONOTONIC, &mtime_now);
0074 
0075     if (unshare_timens())
0076         return 1;
0077 
0078     len = snprintf(buf, sizeof(buf), "%d %d 0",
0079             CLOCK_MONOTONIC, 70 * 24 * 3600);
0080     fd = open("/proc/self/timens_offsets", O_WRONLY);
0081     if (fd < 0)
0082         return pr_perror("/proc/self/timens_offsets");
0083 
0084     if (write(fd, buf, len) != len)
0085         return pr_perror("/proc/self/timens_offsets");
0086 
0087     close(fd);
0088 
0089     pid = fork();
0090     if (pid < 0)
0091         return pr_perror("Unable to fork");
0092     if (pid == 0) {
0093         int ret = 0;
0094 
0095         ret |= run_test(CLOCK_REALTIME);
0096         ret |= run_test(CLOCK_MONOTONIC);
0097         if (ret)
0098             ksft_exit_fail();
0099         ksft_exit_pass();
0100         return 0;
0101     }
0102 
0103     if (waitpid(pid, &status, 0) != pid)
0104         return pr_perror("Unable to wait the child process");
0105 
0106     if (WIFEXITED(status))
0107         return WEXITSTATUS(status);
0108 
0109     return 1;
0110 }