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 
ZTEST(posix_clock_selection,test_clock_nanosleep_execution)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 
ZTEST(posix_clock_selection,test_pthread_condattr_getclock)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 
ZTEST(posix_clock_selection,test_pthread_condattr_setclock)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);
117