12int64_t st_now(clockid_t clock) {
14 return clock_gettime(clock, &now) ? -1 : (int64_t)now.tv_sec * 1000000000 + now.tv_nsec;
16struct timespec st_timespec(int64_t nanoseconds) {
17 return (
struct timespec){nanoseconds / 1000000000, nanoseconds % 1000000000};
19void st_pause(
int milliseconds) {
20 struct timespec pause = st_timespec((int64_t)milliseconds * 1000000);
21 while (nanosleep(&pause, &pause) && errno == EINTR) {
24int st_wait(
volatile int* flag,
int milliseconds) {
25 int64_t deadline = st_now(CLOCK_MONOTONIC) + (int64_t)milliseconds * 1000000;
26 while (!__atomic_load_n(flag, __ATOMIC_ACQUIRE)) {
27 if (st_now(CLOCK_MONOTONIC) >= deadline)
33int st_reap(pid_t child,
int milliseconds) {
34 int64_t deadline = st_now(CLOCK_MONOTONIC) + (int64_t)milliseconds * 1000000;
35 while (st_now(CLOCK_MONOTONIC) < deadline) {
37 pid_t result = waitpid(child, &status, WNOHANG);
39 return WIFEXITED(status) ? WEXITSTATUS(status) : 128 + WTERMSIG(status);
40 if (result < 0 && errno != EINTR)
45 while (waitpid(child, NULL, 0) < 0 && errno == EINTR) {
50static int run(
const char* name,
int (*test)(
void)) {
51 printf(
"SIGNAL-TIMER-CONTRACT: BEGIN %s\n", name);
53 const int clock_suite = !strcmp(name,
"clock") || !strcmp(name,
"raw-clock");
54 int64_t realtime = st_now(CLOCK_REALTIME), monotonic = st_now(CLOCK_MONOTONIC);
63 _exit(result ? 1 : 0);
65 int result = st_reap(child, 35000);
66 if (clock_suite && geteuid() == 0) {
68 struct timespec restored = st_timespec(realtime + st_now(CLOCK_MONOTONIC) - monotonic);
69 if (clock_settime(CLOCK_REALTIME, &restored))
72 printf(
"SIGNAL-TIMER-CONTRACT: %s %s status=%d\n", result ?
"FAIL" :
"PASS", name, result);
76int main(
int argc,
char** argv) {
77 if (argc > 1 && !strcmp(argv[1],
"timer-exec"))
78 return signal_timer_exec(argc, argv);
82 } suites[] = {{
"signals", signal_timer_test_signals},
83 {
"timers", signal_timer_test_timers},
84 {
"cpu-itimers", signal_timer_test_cpu_itimers},
85 {
"clock", signal_timer_test_clock},
86 {
"raw-clock", signal_timer_test_raw_clock}};
88 for (
unsigned n = 0; n <
sizeof(suites) /
sizeof(suites[0]); ++n) {
89 if (argc > 1 && strcmp(argv[1], suites[n].name))
92 if (run(suites[n].name, suites[n].test))
97 puts(
"SIGNAL-TIMER-CONTRACT: END PASS");