Skip to content

Commit 6505f9e

Browse files
acervmetan-ucw
authored andcommitted
Add clock_settime04 test
Test that changing the value of the CLOCK_REALTIME clock via clock_settime(2) shall have no effect on a thread that is blocked on a relative/absolute clock_nanosleep(). Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com> Co-developed-by: Cyril Hrubis <chrubis@suse.cz> Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
1 parent 01604e8 commit 6505f9e

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

runtest/syscalls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ leapsec01 leapsec01
112112
clock_settime01 clock_settime01
113113
clock_settime02 clock_settime02
114114
clock_settime03 clock_settime03
115+
clock_settime04 clock_settime04
115116

116117
clone01 clone01
117118
clone02 clone02
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
clock_settime01
22
clock_settime02
33
clock_settime03
4+
clock_settime04
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* Copyright (c) 2025 Andrea Cervesato <andrea.cervesato@suse.com>
4+
*/
5+
6+
/*\
7+
* Verify that changing the value of the CLOCK_REALTIME clock via
8+
* clock_settime() shall have no effect on a thread that is blocked on
9+
* absolute/relative clock_nanosleep().
10+
*/
11+
12+
#include "tst_test.h"
13+
#include "tst_timer.h"
14+
#include "tst_safe_clocks.h"
15+
#include "time64_variants.h"
16+
17+
#define SEC_TO_US(x) (x * 1000 * 1000)
18+
19+
#define CHILD_SLEEP_US SEC_TO_US(5)
20+
#define PARENT_SLEEP_S 2
21+
#define DELTA_US SEC_TO_US(1)
22+
23+
static struct tst_ts *sleep_child;
24+
25+
static struct time64_variants variants[] = {
26+
{
27+
.clock_nanosleep = libc_clock_nanosleep,
28+
.ts_type = TST_LIBC_TIMESPEC,
29+
.desc = "vDSO or syscall with libc spec"
30+
},
31+
32+
#if (__NR_clock_nanosleep != __LTP__NR_INVALID_SYSCALL)
33+
{
34+
.clock_nanosleep = sys_clock_nanosleep,
35+
.ts_type = TST_KERN_OLD_TIMESPEC,
36+
.desc = "syscall with old kernel spec"
37+
},
38+
#endif
39+
40+
#if (__NR_clock_nanosleep_time64 != __LTP__NR_INVALID_SYSCALL)
41+
{
42+
.clock_nanosleep = sys_clock_nanosleep64,
43+
.ts_type = TST_KERN_TIMESPEC,
44+
.desc = "syscall time64 with kernel spec"
45+
},
46+
#endif
47+
};
48+
49+
static void child_nanosleep(struct time64_variants *tv, const int flags)
50+
{
51+
long long delta;
52+
struct timespec begin, end;
53+
54+
SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &begin);
55+
56+
if (flags & TIMER_ABSTIME) {
57+
tst_res(TINFO, "Using absolute time sleep");
58+
59+
tst_ts_set_sec(sleep_child, begin.tv_sec);
60+
tst_ts_set_nsec(sleep_child, begin.tv_nsec);
61+
62+
*sleep_child = tst_ts_add_us(*sleep_child, CHILD_SLEEP_US);
63+
} else {
64+
tst_res(TINFO, "Using relative time sleep");
65+
66+
*sleep_child = tst_ts_from_us(sleep_child->type, CHILD_SLEEP_US);
67+
}
68+
69+
TEST(tv->clock_nanosleep(CLOCK_REALTIME, flags, tst_ts_get(sleep_child), NULL));
70+
if (TST_RET)
71+
tst_brk(TBROK | TERRNO, "clock_nanosleep() error");
72+
73+
SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &end);
74+
75+
if (tst_timespec_lt(end, begin)) {
76+
tst_res(TFAIL, "clock_settime() didn't sleep enough. "
77+
"begin: %lld ms >= end: %lld ms",
78+
tst_timespec_to_ms(begin),
79+
tst_timespec_to_ms(end));
80+
return;
81+
}
82+
83+
delta = tst_timespec_abs_diff_us(begin, end);
84+
if (!(flags & TIMER_ABSTIME))
85+
delta -= CHILD_SLEEP_US;
86+
87+
if (delta > DELTA_US) {
88+
tst_res(TFAIL, "parent clock_settime() affected child sleep. "
89+
"begin: %lld ms, end: %lld ms",
90+
tst_timespec_to_ms(begin),
91+
tst_timespec_to_ms(end));
92+
return;
93+
}
94+
95+
tst_res(TPASS, "parent clock_settime() didn't affect child sleep "
96+
"(delta time: %lld us)", delta);
97+
}
98+
99+
static void run(unsigned int tc_index)
100+
{
101+
struct time64_variants *tv = &variants[tst_variant];
102+
struct timespec begin;
103+
struct timespec sleep_parent = {
104+
.tv_sec = PARENT_SLEEP_S,
105+
};
106+
107+
if (!SAFE_FORK()) {
108+
child_nanosleep(tv, tc_index ? TIMER_ABSTIME : 0);
109+
exit(0);
110+
}
111+
112+
SAFE_CLOCK_GETTIME(CLOCK_REALTIME, &begin);
113+
SAFE_CLOCK_NANOSLEEP(CLOCK_REALTIME, 0, &sleep_parent, NULL);
114+
SAFE_CLOCK_SETTIME(CLOCK_REALTIME, &begin);
115+
}
116+
117+
static void setup(void)
118+
{
119+
sleep_child->type = variants[tst_variant].ts_type;
120+
121+
tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
122+
}
123+
124+
static struct tst_test test = {
125+
.test = run,
126+
.setup = setup,
127+
.tcnt = 2,
128+
.needs_root = 1,
129+
.forks_child = 1,
130+
.restore_wallclock = 1,
131+
.test_variants = ARRAY_SIZE(variants),
132+
.bufs = (struct tst_buffers []) {
133+
{&sleep_child, .size = sizeof(struct tst_ts)},
134+
{},
135+
}
136+
};

0 commit comments

Comments
 (0)