1 // SPDX-License-Identifier: GPL-2.0
9 #include <sys/syscall.h>
10 #include <sys/types.h>
20 #define OFFSET (36000)
27 static void *tcheck(void *_args)
29 struct thread_args *args = _args;
30 struct timespec *now = args->now, tst;
33 for (i = 0; i < 2; i++) {
34 _gettime(CLOCK_MONOTONIC, &tst, i);
35 if (abs(tst.tv_sec - now->tv_sec) > 5) {
36 pr_fail("%s: in-thread: unexpected value: %ld (%ld)\n",
37 args->tst_name, tst.tv_sec, now->tv_sec);
44 static int check_in_thread(char *tst_name, struct timespec *now)
46 struct thread_args args = {
53 if (pthread_create(&th, NULL, tcheck, &args))
54 return pr_perror("thread");
55 if (pthread_join(th, &retval))
56 return pr_perror("pthread_join");
57 return !(retval == NULL);
60 static int check(char *tst_name, struct timespec *now)
65 for (i = 0; i < 2; i++) {
66 _gettime(CLOCK_MONOTONIC, &tst, i);
67 if (abs(tst.tv_sec - now->tv_sec) > 5)
68 return pr_fail("%s: unexpected value: %ld (%ld)\n",
69 tst_name, tst.tv_sec, now->tv_sec);
71 if (check_in_thread(tst_name, now))
73 ksft_test_result_pass("%s\n", tst_name);
77 int main(int argc, char *argv[])
86 ksft_cnt.ksft_pass = 1;
87 now.tv_sec = strtoul(argv[1], &endptr, 0);
89 return pr_perror("strtoul");
91 return check("child after exec", &now);
98 clock_gettime(CLOCK_MONOTONIC, &now);
100 if (unshare_timens())
103 if (_settime(CLOCK_MONOTONIC, OFFSET))
106 if (check("parent before vfork", &now))
111 return pr_perror("fork");
115 char *cargv[] = {"exec", now_str, NULL};
116 char *cenv[] = {NULL};
118 /* Check for proper vvar offsets after execve. */
119 snprintf(now_str, sizeof(now_str), "%ld", now.tv_sec + OFFSET);
120 execve("/proc/self/exe", cargv, cenv);
125 if (waitpid(pid, &status, 0) != pid)
126 return pr_perror("waitpid");
131 ksft_test_result_pass("wait for child\n");
133 /* Check that we are still in the source timens. */
134 if (check("parent after vfork", &now))