]>
Commit | Line | Data |
---|---|---|
1 | #include <stdio.h> | |
2 | #include <errno.h> | |
3 | #include <string.h> | |
4 | #include <unistd.h> | |
5 | #include <sys/mman.h> | |
6 | #include <mach/clock_types.h> | |
7 | #include <sys/timex.h> | |
8 | #include <mach/mach.h> | |
9 | #include <darwintest.h> | |
10 | #include <darwintest_utils.h> | |
11 | ||
12 | ||
13 | #define DAY 86400 /*1 day in sec*/ | |
14 | #define ERROR 2 /*2 us of error tolerance*/ | |
15 | ||
16 | T_DECL(settimeofday_29192647, | |
17 | "Verify that the syscall settimeofday is effective", | |
18 | T_META_ASROOT(true), T_META_CHECK_LEAKS(NO), T_META_LTEPHASE(LTE_POSTINIT)) | |
19 | { | |
20 | struct timeval time; | |
21 | long new_time; | |
22 | ||
23 | if (geteuid() != 0) { | |
24 | T_SKIP("settimeofday_29192647 test requires root privileges to run."); | |
25 | } | |
26 | ||
27 | T_QUIET; | |
28 | T_ASSERT_POSIX_ZERO(gettimeofday(&time, NULL), NULL); | |
29 | ||
30 | /* increment the time of one day */ | |
31 | new_time = time.tv_sec + DAY; | |
32 | ||
33 | time.tv_sec = new_time; | |
34 | time.tv_usec = 0; | |
35 | ||
36 | T_LOG("Attemping to set the time one day after."); | |
37 | ||
38 | T_WITH_ERRNO; | |
39 | T_ASSERT_POSIX_ZERO(settimeofday(&time, NULL), NULL); | |
40 | ||
41 | T_QUIET; | |
42 | T_ASSERT_POSIX_ZERO(gettimeofday(&time, NULL), NULL); | |
43 | ||
44 | /* expext to be past new_time */ | |
45 | T_EXPECT_GE_LONG(time.tv_sec, new_time, "Time successfully changed"); | |
46 | ||
47 | /* set the time back to previous value */ | |
48 | if (time.tv_sec >= new_time) { | |
49 | time.tv_sec = time.tv_sec - DAY; | |
50 | time.tv_usec = 0; | |
51 | ||
52 | T_WITH_ERRNO; | |
53 | T_ASSERT_POSIX_ZERO(settimeofday(&time, NULL), NULL); | |
54 | } | |
55 | } | |
56 | ||
57 | static void | |
58 | get_abs_to_us_scale_factor(uint64_t* numer, uint64_t* denom) | |
59 | { | |
60 | struct timespec time; | |
61 | uint64_t old_abstime, new_abstime; | |
62 | uint64_t old_time_usec, new_time_usec; | |
63 | uint64_t time_conv1, diff; | |
64 | mach_timebase_info_data_t timebaseInfo = { 0, 0 }; | |
65 | ||
66 | T_QUIET; T_ASSERT_EQ(mach_get_times(&old_abstime, NULL, &time), KERN_SUCCESS, NULL); | |
67 | ||
68 | old_time_usec = (uint64_t)time.tv_sec * USEC_PER_SEC + (uint64_t)time.tv_nsec / 1000; | |
69 | ||
70 | sleep(1); | |
71 | ||
72 | T_QUIET; T_ASSERT_EQ(mach_get_times(&new_abstime, NULL, &time), KERN_SUCCESS, NULL); | |
73 | ||
74 | new_time_usec = (uint64_t)time.tv_sec * USEC_PER_SEC + (uint64_t)time.tv_nsec / 1000; | |
75 | ||
76 | /* this is conversion factors from abs to nanos */ | |
77 | T_ASSERT_EQ(mach_timebase_info(&timebaseInfo), KERN_SUCCESS, NULL); | |
78 | ||
79 | new_time_usec -= old_time_usec; | |
80 | new_abstime -= old_abstime; | |
81 | ||
82 | time_conv1 = new_abstime; | |
83 | time_conv1 *= timebaseInfo.numer; | |
84 | time_conv1 /= timebaseInfo.denom * 1000; | |
85 | ||
86 | if (time_conv1 > new_time_usec) { | |
87 | diff = time_conv1 - new_time_usec; | |
88 | } else { | |
89 | diff = new_time_usec - time_conv1; | |
90 | } | |
91 | ||
92 | T_EXPECT_LE_ULLONG(diff, (unsigned long long)ERROR, "Check scale factor time base (%u/%u) delta read usec %llu delta converted %llu delta abs %llu", timebaseInfo.numer, timebaseInfo.denom, time_conv1, new_time_usec, new_abstime); | |
93 | ||
94 | *numer = (uint64_t)timebaseInfo.numer; | |
95 | *denom = (uint64_t)timebaseInfo.denom * 1000; | |
96 | } | |
97 | ||
98 | ||
99 | #define ADJSTMENT 3333 /*3333 us*/ | |
100 | #define ADJTIME_OFFSET_PER_SEC 500 | |
101 | ||
102 | T_DECL(adjtime_29192647, | |
103 | "Verify that the syscall adjtime is effective", | |
104 | T_META_CHECK_LEAKS(NO), T_META_LTEPHASE(LTE_POSTINIT), T_META_ASROOT(true)) | |
105 | { | |
106 | struct timespec time; | |
107 | struct timeval adj; | |
108 | uint64_t old_abstime, new_abstime, abs_delta; | |
109 | uint64_t old_time_usec, new_time_usec, us_delta, num, den; | |
110 | unsigned int sleep_time; | |
111 | long diff; | |
112 | const char * lterdos_env = NULL; | |
113 | ||
114 | #if defined(__i386__) || defined(__x86_64__) | |
115 | T_SKIP("adjtime_29192647 test requires LTE to run."); | |
116 | #endif | |
117 | ||
118 | if (geteuid() != 0) { | |
119 | T_SKIP("adjtime_29192647 test requires root privileges to run."); | |
120 | } | |
121 | ||
122 | lterdos_env = getenv("LTERDOS"); | |
123 | ||
124 | if (lterdos_env != NULL) { | |
125 | if (!(strcmp(lterdos_env, "YES") == 0)) { | |
126 | T_SKIP("adjtime_29192647 test requires LTE to run."); | |
127 | } | |
128 | } else { | |
129 | T_SKIP("adjtime_29192647 test requires LTE to run."); | |
130 | } | |
131 | ||
132 | /* | |
133 | * Calibrate scale factor for converting from abs time to usec | |
134 | */ | |
135 | get_abs_to_us_scale_factor(&num, &den); | |
136 | ||
137 | T_QUIET; T_ASSERT_EQ(mach_get_times(&old_abstime, NULL, &time), KERN_SUCCESS, NULL); | |
138 | ||
139 | old_time_usec = (uint64_t)time.tv_sec * USEC_PER_SEC + (uint64_t)time.tv_nsec / 1000; | |
140 | ||
141 | adj.tv_sec = 0; | |
142 | adj.tv_usec = ADJSTMENT; | |
143 | ||
144 | T_LOG("Attemping to adjust the time of %d", ADJSTMENT); | |
145 | ||
146 | /* | |
147 | * If more than one second of adjustment | |
148 | * the system slews at a rate of 5ms/s otherwise 500us/s | |
149 | * until the last second is slewed the final < 500 usecs. | |
150 | */ | |
151 | T_WITH_ERRNO; | |
152 | T_ASSERT_POSIX_ZERO(adjtime(&adj, NULL), NULL); | |
153 | ||
154 | /* | |
155 | * Wait that the full adjustment is applied. | |
156 | * Note, add 2 more secs for take into account division error | |
157 | * and that the last block of adj is fully elapsed. | |
158 | */ | |
159 | sleep_time = (ADJSTMENT) / (ADJTIME_OFFSET_PER_SEC)+2; | |
160 | ||
161 | T_LOG("Waiting for %u sec\n", sleep_time); | |
162 | sleep(sleep_time); | |
163 | ||
164 | T_QUIET; T_ASSERT_EQ(mach_get_times(&new_abstime, NULL, &time), KERN_SUCCESS, NULL); | |
165 | ||
166 | new_time_usec = (uint64_t)time.tv_sec * USEC_PER_SEC + (uint64_t)time.tv_nsec / 1000; | |
167 | ||
168 | us_delta = new_time_usec - old_time_usec; | |
169 | us_delta -= ADJSTMENT; | |
170 | ||
171 | /* abs time is not affected by adjtime */ | |
172 | abs_delta = new_abstime - old_abstime; | |
173 | ||
174 | abs_delta *= num; | |
175 | abs_delta /= den; | |
176 | ||
177 | diff = (long) us_delta - (long) abs_delta; | |
178 | ||
179 | /* expext that us_delta == abs_delta */ | |
180 | T_EXPECT_LE_LONG(diff, (long) ERROR, "Check abs time vs calendar time"); | |
181 | ||
182 | T_EXPECT_GE_LONG(diff, (long) -ERROR, "Check abs time vs calendar time"); | |
183 | } | |
184 | ||
185 | #define FREQ_PPM 222 /*222 PPM(us/s)*/ | |
186 | #define SHIFT_PLL 4 | |
187 | #define OFFSET_US 123 /*123us*/ | |
188 | ||
189 | T_DECL(ntp_adjtime_29192647, | |
190 | "Verify that the syscall ntp_adjtime is effective", | |
191 | T_META_CHECK_LEAKS(NO), T_META_LTEPHASE(LTE_POSTINIT), T_META_ASROOT(true)) | |
192 | { | |
193 | struct timespec time; | |
194 | struct timex ntptime; | |
195 | uint64_t abstime1, abstime2, abs_delta, num, den, time_delta; | |
196 | uint64_t time1_usec, time2_usec, time_conv, us_delta, app; | |
197 | int64_t offset; | |
198 | long diff, freq; | |
199 | unsigned int sleep_time; | |
200 | const char * lterdos_env = NULL; | |
201 | ||
202 | #if defined(__i386__) || defined(__x86_64__) | |
203 | T_SKIP("ntp_adjtime_29192647 test requires LTE to run."); | |
204 | #endif | |
205 | ||
206 | if (geteuid() != 0) { | |
207 | T_SKIP("ntp_adjtime_29192647 test requires root privileges to run."); | |
208 | } | |
209 | ||
210 | lterdos_env = getenv("LTERDOS"); | |
211 | ||
212 | if (lterdos_env != NULL) { | |
213 | if (!(strcmp(lterdos_env, "YES") == 0)) { | |
214 | T_SKIP("adjtime_29192647 test requires LTE to run."); | |
215 | } | |
216 | } else { | |
217 | T_SKIP("adjtime_29192647 test requires LTE to run."); | |
218 | } | |
219 | ||
220 | /* | |
221 | * Calibrate scale factor for converting from abs time to usec | |
222 | */ | |
223 | get_abs_to_us_scale_factor(&num, &den); | |
224 | ||
225 | /* | |
226 | * scale frequency using ntp_adjtime; | |
227 | */ | |
228 | memset(&ntptime, 0, sizeof(ntptime)); | |
229 | ||
230 | ntptime.modes = MOD_STATUS; | |
231 | ntptime.status = TIME_OK; | |
232 | /* ntp input freq is in ppm (us/s) * 2^16, max freq is 500 ppm */ | |
233 | freq = (FREQ_PPM) * 65536; | |
234 | ntptime.modes |= MOD_FREQUENCY; | |
235 | ntptime.freq = freq; | |
236 | ||
237 | T_LOG("Attemping to change calendar frequency of %d ppm", FREQ_PPM); | |
238 | ||
239 | T_WITH_ERRNO; | |
240 | T_ASSERT_EQ(ntp_adjtime(&ntptime), TIME_OK, NULL); | |
241 | ||
242 | T_WITH_ERRNO; | |
243 | T_ASSERT_EQ(ntptime.freq, freq, NULL); | |
244 | ||
245 | sleep(2); | |
246 | ||
247 | T_QUIET; T_ASSERT_EQ(mach_get_times(&abstime1, NULL, &time), KERN_SUCCESS, NULL); | |
248 | ||
249 | time1_usec = (uint64_t)time.tv_sec * USEC_PER_SEC + (uint64_t)time.tv_nsec / 1000; | |
250 | ||
251 | sleep(1); | |
252 | ||
253 | T_QUIET; T_ASSERT_EQ(mach_get_times(&abstime2, NULL, &time), KERN_SUCCESS, NULL); | |
254 | ||
255 | time2_usec = (uint64_t)time.tv_sec * USEC_PER_SEC + (uint64_t)time.tv_nsec / 1000; | |
256 | ||
257 | abs_delta = abstime2 - abstime1; | |
258 | us_delta = time2_usec - time1_usec; | |
259 | ||
260 | time_conv = abs_delta; | |
261 | time_conv *= num; | |
262 | time_conv /= den; | |
263 | ||
264 | app = time_conv / USEC_PER_SEC; //sec elapsed | |
265 | ||
266 | time_delta = time_conv; | |
267 | time_delta += app * (FREQ_PPM); | |
268 | ||
269 | app = time_conv % USEC_PER_SEC; | |
270 | ||
271 | time_delta += (app * (FREQ_PPM)) / USEC_PER_SEC; | |
272 | ||
273 | diff = (long) us_delta - (long) time_delta; | |
274 | ||
275 | /* expext that us_delta == time_delta */ | |
276 | T_EXPECT_LE_LONG(diff, (long) ERROR, "Check abs time vs calendar time"); | |
277 | ||
278 | T_EXPECT_GE_LONG(diff, (long) -ERROR, "Check abs time vs calendar time"); | |
279 | ||
280 | memset(&ntptime, 0, sizeof(ntptime)); | |
281 | ||
282 | /* reset freq to zero */ | |
283 | freq = 0; | |
284 | ntptime.modes = MOD_STATUS; | |
285 | ntptime.status = TIME_OK; | |
286 | ntptime.modes |= MOD_FREQUENCY; | |
287 | ntptime.freq = freq; | |
288 | ||
289 | T_WITH_ERRNO; | |
290 | T_ASSERT_EQ(ntp_adjtime(&ntptime), TIME_OK, NULL); | |
291 | ||
292 | T_WITH_ERRNO; | |
293 | T_ASSERT_EQ(ntptime.freq, freq, NULL); | |
294 | ||
295 | sleep(1); | |
296 | ||
297 | /* | |
298 | * adjust the phase using ntp_adjtime; | |
299 | */ | |
300 | memset(&ntptime, 0, sizeof(ntptime)); | |
301 | ntptime.modes |= MOD_STATUS; | |
302 | ntptime.status = TIME_OK; | |
303 | ntptime.status |= STA_PLL | STA_FREQHOLD; | |
304 | ||
305 | /* ntp input phase can be both ns or us (MOD_MICRO), max offset is 500 ms */ | |
306 | ntptime.offset = OFFSET_US; | |
307 | ntptime.modes |= MOD_OFFSET | MOD_MICRO; | |
308 | ||
309 | /* | |
310 | * The system will slew each sec of: | |
311 | * slew = ntp.offset >> (SHIFT_PLL + time_constant); | |
312 | * ntp.offset -= slew; | |
313 | */ | |
314 | offset = (OFFSET_US) * 1000; | |
315 | sleep_time = 2; | |
316 | ||
317 | while ((offset >> SHIFT_PLL) > 0) { | |
318 | offset -= offset >> SHIFT_PLL; | |
319 | sleep_time++; | |
320 | } | |
321 | ||
322 | T_QUIET; T_ASSERT_EQ(mach_get_times(&abstime1, NULL, &time), KERN_SUCCESS, NULL); | |
323 | ||
324 | time1_usec = (uint64_t)time.tv_sec * USEC_PER_SEC + (uint64_t)time.tv_nsec / 1000; | |
325 | ||
326 | T_LOG("Attemping to change calendar phase of %d us", OFFSET_US); | |
327 | ||
328 | T_WITH_ERRNO; | |
329 | T_ASSERT_EQ(ntp_adjtime(&ntptime), TIME_OK, NULL); | |
330 | ||
331 | T_WITH_ERRNO; | |
332 | T_ASSERT_EQ(ntptime.offset, (long) OFFSET_US, NULL); | |
333 | ||
334 | T_LOG("Waiting for %u sec\n", sleep_time); | |
335 | sleep(sleep_time); | |
336 | ||
337 | T_QUIET; T_ASSERT_EQ(mach_get_times(&abstime2, NULL, &time), KERN_SUCCESS, NULL); | |
338 | ||
339 | time2_usec = (uint64_t)time.tv_sec * USEC_PER_SEC + (uint64_t)time.tv_nsec / 1000; | |
340 | ||
341 | abs_delta = abstime2 - abstime1; | |
342 | us_delta = time2_usec - time1_usec; | |
343 | ||
344 | abs_delta *= num; | |
345 | abs_delta /= den; | |
346 | ||
347 | us_delta -= OFFSET_US; | |
348 | ||
349 | diff = (long) us_delta - (long) abs_delta; | |
350 | ||
351 | /* expext that us_delta == abs_delta */ | |
352 | T_EXPECT_LE_LONG(diff, (long) ERROR, "Check abs time vs calendar time"); | |
353 | ||
354 | T_EXPECT_GE_LONG(diff, (long) -ERROR, "Check abs time vs calendar time"); | |
355 | ||
356 | memset(&ntptime, 0, sizeof(ntptime)); | |
357 | ntptime.modes = MOD_STATUS; | |
358 | ntptime.status = TIME_OK; | |
359 | ntptime.modes |= MOD_FREQUENCY; | |
360 | ntptime.freq = 0; | |
361 | ||
362 | ntptime.status |= STA_PLL; | |
363 | ntptime.offset = 0; | |
364 | ntptime.modes |= MOD_OFFSET; | |
365 | ||
366 | T_WITH_ERRNO; | |
367 | T_ASSERT_EQ(ntp_adjtime(&ntptime), TIME_OK, NULL); | |
368 | } |