3 #include <mach/mach_time.h>
7 #include <darwintest.h>
9 static void burn_cpu(void){
10 static char *dummy_text
= "Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the";
12 for (int i
= 0; i
< 100; i
++){
13 char key
[64]; char txt
[64];
14 strncpy(txt
, dummy_text
, 64);
15 for (int j
= 0; i
< 64; i
++){
24 T_DECL(clock_gettime_realtime
, "clock_gettime(CLOCK_REALTIME, tp)")
27 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_REALTIME
, &ts
), NULL
);
30 T_ASSERT_POSIX_ZERO(gettimeofday(&tv
, NULL
), NULL
);
32 T_EXPECT_LE((unsigned long)tv
.tv_sec
- (unsigned long)ts
.tv_sec
, (unsigned long)1,
33 "gettimeofday() should return same as clock_gettime(CLOCK_REALTIME)");
36 T_DECL(clock_gettime_monotonic
, "clock_gettime(CLOCK_MONOTONIC, tp)")
38 struct timespec ts1
, ts2
;
39 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC
, &ts1
), NULL
);
43 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC
, &ts2
), NULL
);
45 uint64_t nsec1
= (uint64_t)ts1
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts1
.tv_nsec
;
46 uint64_t nsec2
= (uint64_t)ts2
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts2
.tv_nsec
;
47 uint64_t nsec_diff
= (uint64_t)llabs((int64_t)nsec2
- (int64_t)nsec1
);
49 T_EXPECT_GE(nsec_diff
, 100 * NSEC_PER_MSEC
, "clock_gettime(CLOCK_MONOTONIC) should advance at least 100ms");
50 T_EXPECT_LE(nsec_diff
, 10 * NSEC_PER_SEC
, "clock_gettime(CLOCK_MONOTONIC) should advance no more than 10s");
52 T_DECL(clock_gettime_monotonic_raw
, "clock_gettime(CLOCK_MONOTONIC_RAW, tp)")
54 struct timespec ts1
, ts2
;
55 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC_RAW
, &ts1
), NULL
);
59 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC_RAW
, &ts2
), NULL
);
61 uint64_t nsec1
= (uint64_t)ts1
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts1
.tv_nsec
;
62 uint64_t nsec2
= (uint64_t)ts2
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts2
.tv_nsec
;
63 uint64_t nsec_diff
= (uint64_t)llabs((int64_t)nsec2
- (int64_t)nsec1
);
65 T_EXPECT_GE(nsec_diff
, 100 * NSEC_PER_MSEC
, "clock_gettime(CLOCK_MONOTONIC_RAW) should advance at least 100ms");
66 T_EXPECT_LE(nsec_diff
, 10 * NSEC_PER_SEC
, "clock_gettime(CLOCK_MONOTONIC_RAW) should advance no more than 10s");
69 T_DECL(clock_gettime_uptime_raw
, "clock_gettime(CLOCK_UPTIME_RAW, tp)")
71 struct timespec ts1
, ts2
;
72 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_UPTIME_RAW
, &ts1
), NULL
);
76 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_UPTIME_RAW
, &ts2
), NULL
);
78 uint64_t nsec1
= (uint64_t)ts1
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts1
.tv_nsec
;
79 uint64_t nsec2
= (uint64_t)ts2
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts2
.tv_nsec
;
80 uint64_t nsec_diff
= (uint64_t)llabs((int64_t)nsec2
- (int64_t)nsec1
);
82 T_EXPECT_GE(nsec_diff
, 100 * NSEC_PER_MSEC
, "clock_gettime(CLOCK_UPTIME_RAW) should advance at least 100ms");
83 T_EXPECT_LE(nsec_diff
, 10 * NSEC_PER_SEC
, "clock_gettime(CLOCK_UPTIME_RAW) should advance no more than 10s");
86 T_DECL(clock_gettime_cputime
, "clock_gettime(CLOCK_*_CPUTIME_ID, tp)")
88 struct timespec thread_ts1
, thread_ts2
;
89 struct timespec process_ts1
, process_ts2
;
90 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_PROCESS_CPUTIME_ID
, &process_ts1
), NULL
);
91 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_THREAD_CPUTIME_ID
, &thread_ts1
), NULL
);
95 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_PROCESS_CPUTIME_ID
, &process_ts2
), NULL
);
96 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_THREAD_CPUTIME_ID
, &thread_ts1
), NULL
);
98 uint64_t nsec1
, nsec2
, nsec_diff
;
100 // CLOCK_PROCESS_CPUTIME_ID
101 nsec1
= (uint64_t)process_ts1
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)process_ts1
.tv_nsec
;
102 nsec2
= (uint64_t)process_ts2
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)process_ts2
.tv_nsec
;
103 nsec_diff
= (uint64_t)llabs((int64_t)nsec2
- (int64_t)nsec1
);
104 T_EXPECT_GE(nsec_diff
, NSEC_PER_USEC
, "clock_gettime(CLOCK_PROCESS_CPUTIME_ID) should advance at least 1us");
105 T_EXPECT_LE(nsec_diff
, 10 * NSEC_PER_SEC
, "clock_gettime(CLOCK_PROCESS_CPUTIME_ID) should advance no more than 10s");
107 // CLOCK_THREAD_CPUTIME_ID
108 nsec1
= (uint64_t)thread_ts1
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)thread_ts1
.tv_nsec
;
109 nsec2
= (uint64_t)thread_ts2
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)thread_ts2
.tv_nsec
;
110 nsec_diff
= (uint64_t)llabs((int64_t)nsec2
- (int64_t)nsec1
);
111 T_EXPECT_GE(nsec_diff
, NSEC_PER_USEC
, "clock_gettime(CLOCK_THREAD_CPUTIME_ID) should advance at least 1us");
112 T_EXPECT_LE(nsec_diff
, 10 * NSEC_PER_SEC
, "clock_gettime(CLOCK_THREAD_CPUTIME_ID) should advance no more than 10s");
115 T_DECL(clock_gettime_monotonic_comparison
, "compare CLOCK_MONOTONIC to CLOCK_MONOTONIC_RAW")
117 struct timespec ts1
, ts2
;
118 bool should_retry
= true;
121 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC
, &ts1
), NULL
);
122 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC_RAW
, &ts2
), NULL
);
124 uint64_t nsec1
= (uint64_t)ts1
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts1
.tv_nsec
;
125 uint64_t nsec2
= (uint64_t)ts2
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts2
.tv_nsec
;
126 uint64_t nsec_diff
= (uint64_t)llabs((int64_t)nsec2
- (int64_t)nsec1
);
128 if (should_retry
&& nsec_diff
> nsec2
/20){
129 should_retry
= false;
133 T_EXPECT_LE(nsec_diff
, nsec2
/20, "CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW should be within 5%%");
136 T_DECL(clock_gettime_nsec_np
, "clock_gettime_nsec_np()")
139 uint64_t nsec
, ts_nsec
, diff
;
141 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_REALTIME
, &ts
), NULL
);
142 T_WITH_ERRNO
; T_ASSERT_NE((nsec
= clock_gettime_nsec_np(CLOCK_REALTIME
)), (uint64_t)0, NULL
);
143 ts_nsec
= (uint64_t)ts
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts
.tv_nsec
;
144 diff
= (uint64_t)llabs((int64_t)nsec
- (int64_t)ts_nsec
);
145 T_EXPECT_LE(diff
, 100 * NSEC_PER_MSEC
, "CLOCK_REALTIME: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
147 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC
, &ts
), NULL
);
148 T_WITH_ERRNO
; T_ASSERT_NE((nsec
= clock_gettime_nsec_np(CLOCK_MONOTONIC
)), (uint64_t)0, NULL
);
149 ts_nsec
= (uint64_t)ts
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts
.tv_nsec
;
150 diff
= (uint64_t)llabs((int64_t)nsec
- (int64_t)ts_nsec
);
151 T_EXPECT_LE(diff
, 100 * NSEC_PER_MSEC
, "CLOCK_MONOTONIC: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
153 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC_RAW
, &ts
), NULL
);
154 T_WITH_ERRNO
; T_ASSERT_NE((nsec
= clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW
)), (uint64_t)0, NULL
);
155 ts_nsec
= (uint64_t)ts
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts
.tv_nsec
;
156 diff
= (uint64_t)llabs((int64_t)nsec
- (int64_t)ts_nsec
);
157 T_EXPECT_LE(diff
, 100 * NSEC_PER_MSEC
, "CLOCK_MONOTONIC_RAW: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
159 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_UPTIME_RAW
, &ts
), NULL
);
160 T_WITH_ERRNO
; T_ASSERT_NE((nsec
= clock_gettime_nsec_np(CLOCK_UPTIME_RAW
)), (uint64_t)0, NULL
);
161 ts_nsec
= (uint64_t)ts
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts
.tv_nsec
;
162 diff
= (uint64_t)llabs((int64_t)nsec
- (int64_t)ts_nsec
);
163 T_EXPECT_LE(diff
, 100 * NSEC_PER_MSEC
, "CLOCK_UPTIME_RAW: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
165 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_PROCESS_CPUTIME_ID
, &ts
), NULL
);
166 T_WITH_ERRNO
; T_ASSERT_NE((nsec
= clock_gettime_nsec_np(CLOCK_PROCESS_CPUTIME_ID
)), (uint64_t)0, NULL
);
167 ts_nsec
= (uint64_t)ts
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts
.tv_nsec
;
168 diff
= (uint64_t)llabs((int64_t)nsec
- (int64_t)ts_nsec
);
169 T_EXPECT_LE(diff
, 100 * NSEC_PER_MSEC
, "CLOCK_PROCESS_CPUTIME_ID: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
171 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_THREAD_CPUTIME_ID
, &ts
), NULL
);
172 T_WITH_ERRNO
; T_ASSERT_NE((nsec
= clock_gettime_nsec_np(CLOCK_THREAD_CPUTIME_ID
)), (uint64_t)0, NULL
);
173 ts_nsec
= (uint64_t)ts
.tv_sec
* NSEC_PER_SEC
+ (uint64_t)ts
.tv_nsec
;
174 diff
= (uint64_t)llabs((int64_t)nsec
- (int64_t)ts_nsec
);
175 T_EXPECT_LE(diff
, 100 * NSEC_PER_MSEC
, "CLOCK_THREAD_CPUTIME_ID: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
178 T_DECL(clock_getres
, "clock_getres()")
182 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_REALTIME
, &ts
), NULL
);
183 T_LOG("Resolution of CLOCK_REALTIME is %ld ns", ts
.tv_nsec
);
184 T_EXPECT_EQ(ts
.tv_sec
, (long)0, NULL
);
185 T_EXPECT_GT(ts
.tv_nsec
, (long)0, NULL
);
187 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_MONOTONIC
, &ts
), NULL
);
188 T_LOG("Resolution of CLOCK_MONOTONIC is %ld ns", ts
.tv_nsec
);
189 T_EXPECT_EQ(ts
.tv_sec
, (long)0, NULL
);
190 T_EXPECT_GT(ts
.tv_nsec
, (long)0, NULL
);
192 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_MONOTONIC_RAW
, &ts
), NULL
);
193 T_LOG("Resolution of CLOCK_MONOTONIC_RAW is %ld ns", ts
.tv_nsec
);
194 T_EXPECT_EQ(ts
.tv_sec
, (long)0, NULL
);
195 T_EXPECT_GT(ts
.tv_nsec
, (long)0, NULL
);
197 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_UPTIME_RAW
, &ts
), NULL
);
198 T_LOG("Resolution of CLOCK_UPTIME_RAW is %ld ns", ts
.tv_nsec
);
199 T_EXPECT_EQ(ts
.tv_sec
, (long)0, NULL
);
200 T_EXPECT_GT(ts
.tv_nsec
, (long)0, NULL
);
202 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_PROCESS_CPUTIME_ID
, &ts
), NULL
);
203 T_LOG("Resolution of CLOCK_MONOTONIC_RAW is %ld ns", ts
.tv_nsec
);
204 T_EXPECT_EQ(ts
.tv_sec
, (long)0, NULL
);
205 T_EXPECT_GT(ts
.tv_nsec
, (long)0, NULL
);
207 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_THREAD_CPUTIME_ID
, &ts
), NULL
);
208 T_LOG("Resolution of CLOCK_MONOTONIC_RAW is %ld ns", ts
.tv_nsec
);
209 T_EXPECT_EQ(ts
.tv_sec
, (long)0, NULL
);
210 T_EXPECT_GT(ts
.tv_nsec
, (long)0, NULL
);
213 T_DECL(clock_settime_realtime
, "clock_settime(CLOCK_REALTIME, tp)",
214 T_META("as_root", "true"))
217 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_REALTIME
, &ts
), NULL
);
219 time_t initial_time
= ts
.tv_sec
;
221 ts
.tv_nsec
+= 1 * NSEC_PER_SEC
;
222 T_ASSERT_POSIX_ZERO(clock_settime(CLOCK_REALTIME
, &ts
), NULL
);
224 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_REALTIME
, &ts
), NULL
);
225 T_EXPECT_GT(ts
.tv_sec
- initial_time
, (time_t)0, "time should move forward at least one second");
226 T_EXPECT_LE(ts
.tv_sec
- initial_time
, (time_t)2, "time should move forward less than two seconds");
228 T_DECL(clock_settime_other
, "clock_settime(CLOCK_*, tp)",
229 T_META("as_root", "true"))
232 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC_RAW
, &ts
), NULL
);
233 T_EXPECT_EQ(clock_settime(CLOCK_MONOTONIC_RAW
, &ts
), -1, NULL
);
234 T_EXPECT_EQ(errno
, EINVAL
, NULL
);
236 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_PROCESS_CPUTIME_ID
, &ts
), NULL
);
237 T_EXPECT_EQ(clock_settime(CLOCK_PROCESS_CPUTIME_ID
, &ts
), -1, NULL
);
238 T_EXPECT_EQ(errno
, EINVAL
, NULL
);
240 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_UPTIME_RAW
, &ts
), NULL
);
241 T_EXPECT_EQ(clock_settime(CLOCK_UPTIME_RAW
, &ts
), -1, NULL
);
242 T_EXPECT_EQ(errno
, EINVAL
, NULL
);
244 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_THREAD_CPUTIME_ID
, &ts
), NULL
);
245 T_EXPECT_EQ(clock_settime(CLOCK_THREAD_CPUTIME_ID
, &ts
), -1, NULL
);
246 T_EXPECT_EQ(errno
, EINVAL
, NULL
);