Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: tests/clock/clock_test.c

Issue 23464007: Update glibc revision (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tests/clock/clock_irt_test.c ('k') | tests/clock/nacl.scons » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2013 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 #include <errno.h>
8 #include <inttypes.h>
9 #include <pthread.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/time.h>
14 #include <time.h>
15 #include <unistd.h>
16
17 #include "native_client/src/include/nacl_macros.h"
18
19 /*
20 * This test resembles the trusted version which can be found in
21 * src/shared/platform/nacl_clock_test.c, but uses the stable ABI
22 * to test the integration correctness. When making changes, please
23 * keep both tests in sync if possible.
24 */
25
26
27 /*
28 * On an unloaded i7, 1ms with a 1.25 fuzziness factor and a 100,000
29 * ns constant syscall overhead works fine. On bots, we have to be
30 * much more generous. (This is especially true for qemu-based
31 * testing.)
32 */
33 #define NANOS_PER_MICRO (1000)
34 #define MICROS_PER_MILLI (1000)
35 #define NANOS_PER_MILLI (NANOS_PER_MICRO * MICROS_PER_MILLI)
36 #define MICROS_PER_UNIT (1000 * 1000)
37 #define NANOS_PER_UNIT (NANOS_PER_MICRO * MICROS_PER_UNIT)
38
39 #define DEFAULT_NANOSLEEP_EXTRA_OVERHEAD (10 * NANOS_PER_MILLI)
40 #define DEFAULT_NANOSLEEP_EXTRA_FACTOR (100.0)
41 #define DEFAULT_NANOSLEEP_TIME (10 * NANOS_PER_MILLI)
42
43 /*
44 * Global testing parameters -- fuzziness coefficients in determining
45 * what is considered accurate.
46 */
47 int g_cputime = 1;
48 double g_fuzzy_factor = DEFAULT_NANOSLEEP_EXTRA_FACTOR;
49 uint64_t g_syscall_overhead = DEFAULT_NANOSLEEP_EXTRA_OVERHEAD;
50 uint64_t g_slop_ms = 0;
51
52 /*
53 * ClockMonotonicAccuracyTest samples the CLOCK_MONOTONIC
54 * clock before and after invoking NaClNanosleep and computes the time
55 * delta. The test is considered to pass if the time delta is close
56 * to the requested value. "Close" is a per-host-OS attribute, thus
57 * the above testing parameters.
58 */
59 int ClockMonotonicAccuracyTest(uint64_t sleep_nanos) {
60 int num_failures = 0;
61
62 int err;
63 struct timespec t_start;
64 struct timespec t_sleep;
65 struct timespec t_end;
66
67 uint64_t elapsed_nanos;
68 uint64_t elapsed_lower_bound;
69 uint64_t elapsed_upper_bound;
70
71 t_sleep.tv_sec = sleep_nanos / NANOS_PER_UNIT;
72 t_sleep.tv_nsec = sleep_nanos % NANOS_PER_UNIT;
73
74 printf("\nCLOCK_MONOTONIC accuracy test:\n");
75
76 if (0 != (err = clock_gettime(CLOCK_MONOTONIC, &t_start))) {
77 fprintf(stderr,
78 "nacl_clock_test: clock_gettime (start) failed, error %d\n",
79 err);
80 ++num_failures;
81 goto done;
82 }
83 for (;;) {
84 err = nanosleep(&t_sleep, &t_sleep);
85 if (0 == err) {
86 break;
87 }
88 if (-EINTR == err) {
Roland McGrath 2013/08/28 16:53:06 Return value is an errno code, not a negated errno
Petr Hosek 2013/08/28 19:31:11 Oh, I completely forgot about those return values,
89 /* interrupted syscall: sleep some more */
90 continue;
91 }
92 fprintf(stderr,
93 "nacl_clock_test: nanosleep failed, error %d\n", err);
94 num_failures++;
95 goto done;
96 }
97 if (0 != (err = clock_gettime(CLOCK_MONOTONIC, &t_end))) {
98 fprintf(stderr,
99 "nacl_clock_test: clock_gettime (end) failed, error %d\n",
100 err);
101 return 1;
102 }
103
104 elapsed_nanos = (t_end.tv_sec - t_start.tv_sec) * NANOS_PER_UNIT
105 + (t_end.tv_nsec - t_start.tv_nsec) + g_slop_ms * NANOS_PER_MILLI;
106
107 elapsed_lower_bound = sleep_nanos;
108 elapsed_upper_bound = (uint64_t) (sleep_nanos * g_fuzzy_factor
109 + g_syscall_overhead);
110
111 printf("requested sleep: %20"PRIu64" nS\n", sleep_nanos);
112 printf("actual elapsed sleep: %20"PRIu64" nS\n", elapsed_nanos);
113 printf("sleep lower bound: %20"PRIu64" nS\n", elapsed_lower_bound);
114 printf("sleep upper bound: %20"PRIu64" nS\n", elapsed_upper_bound);
115
116 if (elapsed_nanos < elapsed_lower_bound
117 || elapsed_upper_bound < elapsed_nanos) {
118 printf("discrepancy too large\n");
119 num_failures++;
120 }
121 done:
122 printf((0 == num_failures) ? "PASSED\n" : "FAILED\n");
123 return num_failures;
124 }
125
126 /*
127 * ClockRealtimeAccuracyTest compares the time returned by
128 * CLOCK_REALTIME against that returned by gettimeofday.
129 */
130 int ClockRealtimeAccuracyTest(void) {
131 int num_failures = 0;
132
133 int err;
134 struct timespec t_now_ts;
135 struct timeval t_now_tv;
136
137 uint64_t t_now_ts_nanos;
138 uint64_t t_now_tv_nanos;
139 int64_t t_now_diff_nanos;
140
141 printf("\nCLOCK_REALTIME accuracy test:\n");
142
143 if (0 != (err = clock_gettime(CLOCK_REALTIME, &t_now_ts))) {
144 fprintf(stderr,
145 "clock_test: clock_gettime (now) failed, error %d\n",
146 err);
147 num_failures++;
148 goto done;
149 }
150 if (0 != (err = gettimeofday(&t_now_tv, NULL))) {
Roland McGrath 2013/08/28 16:53:06 The return value is -1 and the error is in errno.
Petr Hosek 2013/08/28 19:31:11 ditto
151 fprintf(stderr,
152 "clock_test: gettimeofday (now) failed, error %d\n",
153 err);
154 num_failures++;
155 goto done;
156 }
157
158 t_now_ts_nanos = t_now_ts.tv_sec * NANOS_PER_UNIT + t_now_ts.tv_nsec;
159 t_now_tv_nanos = t_now_tv.tv_sec * NANOS_PER_UNIT
160 + t_now_tv.tv_usec * NANOS_PER_MICRO;
161
162 printf("clock_gettime: %20"PRIu64" nS\n", t_now_ts_nanos);
163 printf("gettimeofday: %20"PRIu64" nS\n", t_now_tv_nanos);
164
165 t_now_diff_nanos = t_now_ts_nanos - t_now_tv_nanos;
166 if (t_now_diff_nanos < 0) {
167 t_now_diff_nanos = -t_now_diff_nanos;
168 }
169 printf("time difference: %20"PRId64" nS\n", t_now_diff_nanos);
170
171 if (t_now_ts_nanos < g_syscall_overhead) {
172 printf("discrepancy too large\n");
173 num_failures++;
174 }
175 done:
176 printf((0 == num_failures) ? "PASSED\n" : "FAILED\n");
177 return num_failures;
178 }
179
180 struct ThreadInfo {
181 size_t cycles;
182 struct timespec thread_time;
183 struct timespec process_time;
184 int num_failures;
185 };
186
187 void *ThreadFunction(void *ptr) {
188 int err;
189
190 size_t i;
191 struct ThreadInfo *info = (struct ThreadInfo *) ptr;
192
193 for (i = 1; i < info->cycles; i++) {
194 __sync_synchronize();
195 }
196
197 if (0 != (err = clock_gettime(CLOCK_THREAD_CPUTIME_ID,
198 &info->thread_time))) {
199 fprintf(stderr,
200 "clock_test: clock_gettime (now) failed, error %d\n",
201 err);
202 info->num_failures++;
203 return NULL;
204 }
205
206 if (0 != (err = clock_gettime(CLOCK_PROCESS_CPUTIME_ID,
207 &info->process_time))) {
208 fprintf(stderr,
209 "clock_test: clock_gettime (now) failed, error %d\n",
210 err);
211 info->num_failures++;
212 return NULL;
213 }
214
215 return NULL;
216 }
217
218 int ClockCpuTimeAccuracyTest(void) {
219 int num_failures = 0;
220
221 int err;
222 struct timespec t_process_start;
223 struct timespec t_process_end;
224 struct timespec t_thread_start;
225 struct timespec t_thread_end;
226
227 uint64_t thread_elapsed = 0;
228 uint64_t process_elapsed = 0;
229 uint64_t child_thread_elapsed = 0;
230 uint64_t elapsed_lower_bound;
231 uint64_t elapsed_upper_bound;
232
233 size_t i;
234 struct ThreadInfo info[10];
235 pthread_t thread[10];
236
237 printf("\nCLOCK_PROCESS/THREAD_CPUTIME_ID accuracy test:\n");
238
239 if (0 != (err = clock_gettime(CLOCK_THREAD_CPUTIME_ID,
240 &t_thread_start))) {
241 fprintf(stderr,
242 "clock_test: clock_gettime (now) failed, error %d\n",
243 err);
244 num_failures++;
245 goto done;
246 }
247
248 if (0 != (err = clock_gettime(CLOCK_PROCESS_CPUTIME_ID,
249 &t_process_start))) {
250 fprintf(stderr,
251 "clock_test: clock_gettime (now) failed, error %d\n",
252 err);
253 num_failures++;
254 goto done;
255 }
256
257 for (i = 0; i < NACL_ARRAY_SIZE(thread); i++) {
258 memset(&info[i], 0, sizeof info[i]);
259 info[i].cycles = i * 10000000;
260 if (0 != (err = pthread_create(&thread[i], NULL,
261 ThreadFunction, &info[i]))) {
262 fprintf(stderr,
263 "clock_test: pthread_create failed, error %d\n",
264 err);
265 num_failures++;
266 goto done;
267 }
268 }
269
270 for (i = 0; i < NACL_ARRAY_SIZE(thread); i++) {
271 pthread_join(thread[i], NULL);
272 }
273
274 if (0 != (err = clock_gettime(CLOCK_PROCESS_CPUTIME_ID,
275 &t_process_end))) {
276 fprintf(stderr,
277 "clock_test: clock_gettime (now) failed, error %d\n",
278 err);
279 num_failures++;
280 goto done;
281 }
282
283 if (0 != (err = clock_gettime(CLOCK_THREAD_CPUTIME_ID,
284 &t_thread_end))) {
285 fprintf(stderr,
286 "clock_test: clock_gettime (now) failed, error %d\n",
287 err);
288 num_failures++;
289 goto done;
290 }
291
292 thread_elapsed =
293 (t_thread_end.tv_sec - t_thread_start.tv_sec) * NANOS_PER_UNIT
294 + (t_thread_end.tv_nsec - t_thread_start.tv_nsec);
295
296 process_elapsed =
297 (t_process_end.tv_sec - t_process_start.tv_sec) * NANOS_PER_UNIT
298 + (t_process_end.tv_nsec - t_process_start.tv_nsec);
299
300 for (i = 0; i < NACL_ARRAY_SIZE(thread); i++) {
301 uint64_t thread_elapsed_nanos;
302 uint64_t process_elapsed_nanos;
303
304 if (info[i].num_failures > 0) {
305 num_failures += info[i].num_failures;
306 goto done;
307 }
308
309 thread_elapsed_nanos = info[i].thread_time.tv_sec * NANOS_PER_UNIT
310 + info[i].thread_time.tv_nsec;
311 process_elapsed_nanos = info[i].process_time.tv_sec * NANOS_PER_UNIT
312 + info[i].process_time.tv_nsec;
313 printf("%zd: thread=%20"PRIu64" nS, process=%20"PRIu64" nS\n",
314 i, thread_elapsed_nanos, process_elapsed_nanos);
315 child_thread_elapsed += thread_elapsed_nanos;
316 }
317
318 elapsed_lower_bound = thread_elapsed + child_thread_elapsed;
319 elapsed_upper_bound = (uint64_t) (thread_elapsed
320 + child_thread_elapsed * g_fuzzy_factor + g_syscall_overhead);
321
322 printf("thread time: %20"PRIu64" nS\n", thread_elapsed);
323 printf("process time: %20"PRIu64" nS\n", process_elapsed);
324 printf("child thread time: %20"PRIu64" nS\n", child_thread_elapsed);
325 printf("elapsed lower bound: %20"PRIu64" nS\n", elapsed_lower_bound);
326 printf("elapsed upper bound: %20"PRIu64" nS\n", elapsed_upper_bound);
327
328 if (process_elapsed < elapsed_lower_bound
329 || elapsed_upper_bound < process_elapsed) {
330 printf("discrepancy too large\n");
331 num_failures++;
332 }
333 done:
334 printf((0 == num_failures) ? "PASSED\n" : "FAILED\n");
335 return num_failures;
336 }
337
338 int main(int ac, char **av) {
339 uint64_t sleep_nanos = DEFAULT_NANOSLEEP_TIME;
340 int opt;
341 uint32_t num_failures = 0;
342
343 while (-1 != (opt = getopt(ac, av, "cf:o:s:S:"))) {
344 switch (opt) {
345 case 'c':
346 g_cputime = 0;
347 break;
348 case 'f':
349 g_fuzzy_factor = strtod(optarg, (char **) NULL);
350 break;
351 case 'o':
352 g_syscall_overhead = strtoul(optarg, (char **) NULL, 0);
353 break;
354 case 's':
355 g_slop_ms = strtoul(optarg, (char **) NULL, 0);
356 break;
357 case 'S':
358 sleep_nanos = strtoul(optarg, (char **) NULL, 0);
359 break;
360 default:
361 fprintf(stderr, "clock_test: unrecognized option `%c'.\n",
362 opt);
363 fprintf(stderr,
364 "Usage: clock_test [-f fuzz_factor] [-s sleep_nanos]\n"
365 " [-o syscall_overhead_nanos]\n");
366 return -1;
367 }
368 }
369
370 num_failures += ClockMonotonicAccuracyTest(sleep_nanos);
371 num_failures += ClockRealtimeAccuracyTest();
372 if (g_cputime) {
373 num_failures += ClockCpuTimeAccuracyTest();
374 }
375
376 return num_failures;
377 }
OLDNEW
« no previous file with comments | « tests/clock/clock_irt_test.c ('k') | tests/clock/nacl.scons » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698