Skip to content

Commit 3c7e43f

Browse files
cfriedtnashif
authored andcommitted
tests: posix: add posix_clock_selection testsuite
Add a testsuite for the POSIX_CLOCK_SELECTION Option Group which consists of clock_nanosleep(), pthread_condattr_getclock(), and pthread_condattr_setclock(). Signed-off-by: Chris Friedt <[email protected]>
1 parent ae4a1db commit 3c7e43f

File tree

7 files changed

+270
-162
lines changed

7 files changed

+270
-162
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(posix_clock_selection)
6+
7+
target_sources(app PRIVATE src/main.c ../timers/src/nanosleep_common.c)
8+
9+
target_compile_options(app PRIVATE -U_POSIX_C_SOURCE -D_POSIX_C_SOURCE=200809L)

tests/posix/clock_selection/prj.conf

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CONFIG_POSIX_API=y
2+
CONFIG_ZTEST=y
3+
4+
CONFIG_POSIX_AEP_CHOICE_BASE=y
5+
CONFIG_POSIX_CLOCK_SELECTION=y
6+
7+
CONFIG_DYNAMIC_THREAD=y
8+
CONFIG_DYNAMIC_THREAD_POOL_SIZE=3
9+
CONFIG_THREAD_STACK_INFO=y
+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright (c) 2018 Intel Corporation
3+
* Copyright (c) 2025 Tenstorrent AI ULC
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#include <pthread.h>
9+
#include <time.h>
10+
11+
#include <zephyr/logging/log.h>
12+
#include <zephyr/sys/util.h>
13+
#include <zephyr/ztest.h>
14+
15+
#define SELECT_NANOSLEEP 1
16+
#define SELECT_CLOCK_NANOSLEEP 0
17+
18+
void common_lower_bound_check(int selection, clockid_t clock_id, int flags, const uint32_t s,
19+
uint32_t ns);
20+
int select_nanosleep(int selection, clockid_t clock_id, int flags, const struct timespec *rqtp,
21+
struct timespec *rmtp);
22+
23+
ZTEST(posix_clock_selection, test_clock_nanosleep_execution)
24+
{
25+
struct timespec ts;
26+
27+
clock_gettime(CLOCK_MONOTONIC, &ts);
28+
29+
/* absolute sleeps with the monotonic clock and reference time ts */
30+
31+
/* until 1s + 1ns past the reference time */
32+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
33+
ts.tv_sec + 1, 1);
34+
35+
/* until 1s + 1us past the reference time */
36+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
37+
ts.tv_sec + 1, 1000);
38+
39+
/* until 1s + 500000000ns past the reference time */
40+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
41+
ts.tv_sec + 1, 500000000);
42+
43+
/* until 2s past the reference time */
44+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
45+
ts.tv_sec + 2, 0);
46+
47+
/* until 2s + 1ns past the reference time */
48+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
49+
ts.tv_sec + 2, 1);
50+
51+
/* until 2s + 1us + 1ns past reference time */
52+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
53+
ts.tv_sec + 2, 1001);
54+
55+
clock_gettime(CLOCK_REALTIME, &ts);
56+
57+
/* absolute sleeps with the real time clock and adjusted reference time ts */
58+
59+
/* until 1s + 1ns past the reference time */
60+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
61+
ts.tv_sec + 1, 1);
62+
63+
/* until 1s + 1us past the reference time */
64+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
65+
ts.tv_sec + 1, 1000);
66+
67+
/* until 1s + 500000000ns past the reference time */
68+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
69+
ts.tv_sec + 1, 500000000);
70+
71+
/* until 2s past the reference time */
72+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
73+
ts.tv_sec + 2, 0);
74+
75+
/* until 2s + 1ns past the reference time */
76+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
77+
ts.tv_sec + 2, 1);
78+
79+
/* until 2s + 1us + 1ns past the reference time */
80+
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
81+
ts.tv_sec + 2, 1001);
82+
}
83+
84+
ZTEST(posix_clock_selection, test_pthread_condattr_getclock)
85+
{
86+
clockid_t clock_id;
87+
pthread_condattr_t att = {0};
88+
89+
zassert_ok(pthread_condattr_init(&att));
90+
91+
zassert_ok(pthread_condattr_getclock(&att, &clock_id), "pthread_condattr_getclock failed");
92+
zassert_equal(clock_id, CLOCK_REALTIME, "clock attribute not set correctly");
93+
94+
zassert_ok(pthread_condattr_destroy(&att));
95+
}
96+
97+
ZTEST(posix_clock_selection, test_pthread_condattr_setclock)
98+
{
99+
clockid_t clock_id;
100+
pthread_condattr_t att = {0};
101+
102+
zassert_ok(pthread_condattr_init(&att));
103+
104+
zassert_ok(pthread_condattr_setclock(&att, CLOCK_MONOTONIC),
105+
"pthread_condattr_setclock failed");
106+
107+
zassert_ok(pthread_condattr_getclock(&att, &clock_id), "pthread_condattr_setclock failed");
108+
zassert_equal(clock_id, CLOCK_MONOTONIC, "clock attribute not set correctly");
109+
110+
zassert_equal(pthread_condattr_setclock(&att, 42), -EINVAL,
111+
"pthread_condattr_setclock did not return EINVAL");
112+
113+
zassert_ok(pthread_condattr_destroy(&att));
114+
}
115+
116+
ZTEST_SUITE(posix_clock_selection, NULL, NULL, NULL, NULL, NULL);
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
common:
2+
filter: not CONFIG_NATIVE_LIBC
3+
tags:
4+
- posix
5+
- clock_selection
6+
# 1 tier0 platform per supported architecture
7+
platform_key:
8+
- arch
9+
- simulation
10+
integration_platforms:
11+
- qemu_riscv64
12+
min_flash: 64
13+
min_ram: 32
14+
tests:
15+
portability.posix.clock_selection: {}
16+
portability.posix.clock_selection.minimal:
17+
extra_configs:
18+
- CONFIG_MINIMAL_LIBC=y
19+
portability.posix.clock_selection.newlib:
20+
filter: TOOLCHAIN_HAS_NEWLIB == 1
21+
extra_configs:
22+
- CONFIG_NEWLIB_LIBC=y
23+
- CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=8192
24+
portability.posix.clock_selection.picolibc:
25+
tags: picolibc
26+
filter: CONFIG_PICOLIBC_SUPPORTED
27+
extra_configs:
28+
- CONFIG_PICOLIBC=y

tests/posix/common/src/cond.c

-13
Original file line numberDiff line numberDiff line change
@@ -49,23 +49,10 @@ ZTEST(cond, test_cond_resource_leak)
4949

5050
ZTEST(cond, test_pthread_condattr)
5151
{
52-
clockid_t clock_id;
5352
pthread_condattr_t att = {0};
5453

5554
zassert_ok(pthread_condattr_init(&att));
5655

57-
zassert_ok(pthread_condattr_getclock(&att, &clock_id), "pthread_condattr_getclock failed");
58-
zassert_equal(clock_id, CLOCK_REALTIME, "clock attribute not set correctly");
59-
60-
zassert_ok(pthread_condattr_setclock(&att, CLOCK_REALTIME),
61-
"pthread_condattr_setclock failed");
62-
63-
zassert_ok(pthread_condattr_getclock(&att, &clock_id), "pthread_condattr_setclock failed");
64-
zassert_equal(clock_id, CLOCK_REALTIME, "clock attribute not set correctly");
65-
66-
zassert_equal(pthread_condattr_setclock(&att, 42), -EINVAL,
67-
"pthread_condattr_setclock did not return EINVAL");
68-
6956
zassert_ok(pthread_condattr_destroy(&att));
7057
}
7158

tests/posix/timers/src/nanosleep.c

+4-149
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,10 @@
1414
#define SELECT_NANOSLEEP 1
1515
#define SELECT_CLOCK_NANOSLEEP 0
1616

17-
static inline int select_nanosleep(int selection, clockid_t clock_id, int flags,
18-
const struct timespec *rqtp, struct timespec *rmtp)
19-
{
20-
if (selection == SELECT_NANOSLEEP) {
21-
return nanosleep(rqtp, rmtp);
22-
}
23-
return clock_nanosleep(clock_id, flags, rqtp, rmtp);
24-
}
25-
26-
static inline uint64_t cycle_get_64(void)
27-
{
28-
if (IS_ENABLED(CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER)) {
29-
return k_cycle_get_64();
30-
} else {
31-
return k_cycle_get_32();
32-
}
33-
}
17+
void common_lower_bound_check(int selection, clockid_t clock_id, int flags, const uint32_t s,
18+
uint32_t ns);
19+
int select_nanosleep(int selection, clockid_t clock_id, int flags, const struct timespec *rqtp,
20+
struct timespec *rmtp);
3421

3522
static void common_errors(int selection, clockid_t clock_id, int flags)
3623
{
@@ -129,77 +116,6 @@ ZTEST(posix_timers, test_clock_nanosleep_errors_errno)
129116
zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d", rem.tv_nsec, 0);
130117
}
131118

132-
/**
133-
* @brief Check that a call to nanosleep has yielded execution for some minimum time.
134-
*
135-
* Check that the actual time slept is >= the total time specified by @p s (in seconds) and
136-
* @p ns (in nanoseconds).
137-
*
138-
* @note The time specified by @p s and @p ns is assumed to be absolute (i.e. a time-point)
139-
* when @p selection is set to @ref SELECT_CLOCK_NANOSLEEP. The time is assumed to be relative
140-
* when @p selection is set to @ref SELECT_NANOSLEEP.
141-
*
142-
* @param selection Either @ref SELECT_CLOCK_NANOSLEEP or @ref SELECT_NANOSLEEP
143-
* @param clock_id The clock to test (e.g. @ref CLOCK_MONOTONIC or @ref CLOCK_REALTIME)
144-
* @param flags Flags to pass to @ref clock_nanosleep
145-
* @param s Partial lower bound for yielded time (in seconds)
146-
* @param ns Partial lower bound for yielded time (in nanoseconds)
147-
*/
148-
static void common_lower_bound_check(int selection, clockid_t clock_id, int flags, const uint32_t s,
149-
uint32_t ns)
150-
{
151-
int r;
152-
uint64_t actual_ns = 0;
153-
uint64_t exp_ns;
154-
uint64_t now;
155-
uint64_t then;
156-
struct timespec rem = {0, 0};
157-
struct timespec req = {s, ns};
158-
159-
errno = 0;
160-
then = cycle_get_64();
161-
r = select_nanosleep(selection, clock_id, flags, &req, &rem);
162-
now = cycle_get_64();
163-
164-
zassert_equal(r, 0, "actual: %d expected: %d", r, 0);
165-
zassert_equal(errno, 0, "actual: %d expected: %d", errno, 0);
166-
zassert_equal(req.tv_sec, s, "actual: %d expected: %d", req.tv_sec, s);
167-
zassert_equal(req.tv_nsec, ns, "actual: %d expected: %d", req.tv_nsec, ns);
168-
zassert_equal(rem.tv_sec, 0, "actual: %d expected: %d", rem.tv_sec, 0);
169-
zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d", rem.tv_nsec, 0);
170-
171-
switch (selection) {
172-
case SELECT_NANOSLEEP:
173-
/* exp_ns and actual_ns are relative (i.e. durations) */
174-
actual_ns = k_cyc_to_ns_ceil64(now + then);
175-
break;
176-
case SELECT_CLOCK_NANOSLEEP:
177-
/* exp_ns and actual_ns are absolute (i.e. time-points) */
178-
actual_ns = k_cyc_to_ns_ceil64(now);
179-
break;
180-
default:
181-
zassert_unreachable();
182-
break;
183-
}
184-
185-
exp_ns = (uint64_t)s * NSEC_PER_SEC + ns;
186-
/* round up to the nearest microsecond for k_busy_wait() */
187-
exp_ns = DIV_ROUND_UP(exp_ns, NSEC_PER_USEC) * NSEC_PER_USEC;
188-
189-
/* The comparison may be incorrect if counter wrap happened. In case of ARC HSDK platforms
190-
* we have high counter clock frequency (500MHz or 1GHz) so counter wrap quite likely to
191-
* happen if we wait long enough. As in some test cases we wait more than 1 second, there
192-
* are significant chances to get false-positive assertion.
193-
* TODO: switch test for k_cycle_get_64 usage where available.
194-
*/
195-
#if !defined(CONFIG_SOC_ARC_HSDK) && !defined(CONFIG_SOC_ARC_HSDK4XD)
196-
/* lower bounds check */
197-
zassert_true(actual_ns >= exp_ns, "actual: %llu expected: %llu", actual_ns, exp_ns);
198-
#endif
199-
200-
/* TODO: Upper bounds check when hr timers are available */
201-
}
202-
203119
ZTEST(posix_timers, test_nanosleep_execution)
204120
{
205121
/* sleep for 1ns */
@@ -220,64 +136,3 @@ ZTEST(posix_timers, test_nanosleep_execution)
220136
/* sleep for 1s + 1us + 1ns */
221137
common_lower_bound_check(SELECT_NANOSLEEP, 0, 0, 1, 1001);
222138
}
223-
224-
ZTEST(posix_timers, test_clock_nanosleep_execution)
225-
{
226-
struct timespec ts;
227-
228-
clock_gettime(CLOCK_MONOTONIC, &ts);
229-
230-
/* absolute sleeps with the monotonic clock and reference time ts */
231-
232-
/* until 1s + 1ns past the reference time */
233-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
234-
ts.tv_sec + 1, 1);
235-
236-
/* until 1s + 1us past the reference time */
237-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
238-
ts.tv_sec + 1, 1000);
239-
240-
/* until 1s + 500000000ns past the reference time */
241-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
242-
ts.tv_sec + 1, 500000000);
243-
244-
/* until 2s past the reference time */
245-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
246-
ts.tv_sec + 2, 0);
247-
248-
/* until 2s + 1ns past the reference time */
249-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
250-
ts.tv_sec + 2, 1);
251-
252-
/* until 2s + 1us + 1ns past reference time */
253-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
254-
ts.tv_sec + 2, 1001);
255-
256-
clock_gettime(CLOCK_REALTIME, &ts);
257-
258-
/* absolute sleeps with the real time clock and adjusted reference time ts */
259-
260-
/* until 1s + 1ns past the reference time */
261-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
262-
ts.tv_sec + 1, 1);
263-
264-
/* until 1s + 1us past the reference time */
265-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
266-
ts.tv_sec + 1, 1000);
267-
268-
/* until 1s + 500000000ns past the reference time */
269-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
270-
ts.tv_sec + 1, 500000000);
271-
272-
/* until 2s past the reference time */
273-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
274-
ts.tv_sec + 2, 0);
275-
276-
/* until 2s + 1ns past the reference time */
277-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
278-
ts.tv_sec + 2, 1);
279-
280-
/* until 2s + 1us + 1ns past the reference time */
281-
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
282-
ts.tv_sec + 2, 1001);
283-
}

0 commit comments

Comments
 (0)