]> Git Repo - linux.git/blob - tools/testing/selftests/timens/clock_nanosleep.c
x86/kaslr: Expose and use the end of the physical memory address space
[linux.git] / tools / testing / selftests / timens / clock_nanosleep.c
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3 #include <sched.h>
4
5 #include <sys/timerfd.h>
6 #include <sys/syscall.h>
7 #include <time.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <pthread.h>
13 #include <signal.h>
14 #include <string.h>
15
16 #include "log.h"
17 #include "timens.h"
18
19 void test_sig(int sig)
20 {
21         if (sig == SIGUSR2)
22                 pthread_exit(NULL);
23 }
24
25 struct thread_args {
26         struct timespec *now, *rem;
27         pthread_mutex_t *lock;
28         int clockid;
29         int abs;
30 };
31
32 void *call_nanosleep(void *_args)
33 {
34         struct thread_args *args = _args;
35
36         clock_nanosleep(args->clockid, args->abs ? TIMER_ABSTIME : 0, args->now, args->rem);
37         pthread_mutex_unlock(args->lock);
38         return NULL;
39 }
40
41 int run_test(int clockid, int abs)
42 {
43         struct timespec now = {}, rem;
44         struct thread_args args = { .now = &now, .rem = &rem, .clockid = clockid};
45         struct timespec start;
46         pthread_mutex_t lock;
47         pthread_t thread;
48         int j, ok, ret;
49
50         signal(SIGUSR1, test_sig);
51         signal(SIGUSR2, test_sig);
52
53         pthread_mutex_init(&lock, NULL);
54         pthread_mutex_lock(&lock);
55
56         if (clock_gettime(clockid, &start) == -1) {
57                 if (errno == EINVAL && check_skip(clockid))
58                         return 0;
59                 return pr_perror("clock_gettime");
60         }
61
62
63         if (abs) {
64                 now.tv_sec = start.tv_sec;
65                 now.tv_nsec = start.tv_nsec;
66         }
67
68         now.tv_sec += 3600;
69         args.abs = abs;
70         args.lock = &lock;
71         ret = pthread_create(&thread, NULL, call_nanosleep, &args);
72         if (ret != 0) {
73                 pr_err("Unable to create a thread: %s", strerror(ret));
74                 return 1;
75         }
76
77         /* Wait when the thread will call clock_nanosleep(). */
78         ok = 0;
79         for (j = 0; j < 8; j++) {
80                 /* The maximum timeout is about 5 seconds. */
81                 usleep(10000 << j);
82
83                 /* Try to interrupt clock_nanosleep(). */
84                 pthread_kill(thread, SIGUSR1);
85
86                 usleep(10000 << j);
87                 /* Check whether clock_nanosleep() has been interrupted or not. */
88                 if (pthread_mutex_trylock(&lock) == 0) {
89                         /**/
90                         ok = 1;
91                         break;
92                 }
93         }
94         if (!ok)
95                 pthread_kill(thread, SIGUSR2);
96         pthread_join(thread, NULL);
97         pthread_mutex_destroy(&lock);
98
99         if (!ok) {
100                 ksft_test_result_pass("clockid: %d abs:%d timeout\n", clockid, abs);
101                 return 1;
102         }
103
104         if (rem.tv_sec < 3300 || rem.tv_sec > 3900) {
105                 pr_fail("clockid: %d abs: %d remain: %ld\n",
106                         clockid, abs, rem.tv_sec);
107                 return 1;
108         }
109         ksft_test_result_pass("clockid: %d abs:%d\n", clockid, abs);
110
111         return 0;
112 }
113
114 int main(int argc, char *argv[])
115 {
116         int ret, nsfd;
117
118         nscheck();
119
120         ksft_set_plan(4);
121
122         check_supported_timers();
123
124         if (unshare_timens())
125                 return 1;
126
127         if (_settime(CLOCK_MONOTONIC, 7 * 24 * 3600))
128                 return 1;
129         if (_settime(CLOCK_BOOTTIME, 9 * 24 * 3600))
130                 return 1;
131
132         nsfd = open("/proc/self/ns/time_for_children", O_RDONLY);
133         if (nsfd < 0)
134                 return pr_perror("Unable to open timens_for_children");
135
136         if (setns(nsfd, CLONE_NEWTIME))
137                 return pr_perror("Unable to set timens");
138
139         ret = 0;
140         ret |= run_test(CLOCK_MONOTONIC, 0);
141         ret |= run_test(CLOCK_MONOTONIC, 1);
142         ret |= run_test(CLOCK_BOOTTIME_ALARM, 0);
143         ret |= run_test(CLOCK_BOOTTIME_ALARM, 1);
144
145         if (ret)
146                 ksft_exit_fail();
147         ksft_exit_pass();
148         return ret;
149 }
This page took 0.040468 seconds and 4 git commands to generate.