1 /*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/time.h>
21 #include <time.h>
22 #include <unistd.h>
23 #include <sched.h>
24 #include <sys/resource.h>
25 #include <sys/syscall.h>
26 #include <sys/types.h>
27 #include <sys/mman.h>
28
29 #if 0
30 const int DCACHE_SIZE = 8*1024;
31 const int CPU_FREQ_EST = 195;
32 const int BRANCH_CYCLE = 3;
33 #else
34 const int DCACHE_SIZE = 32*1024;
35 const int CPU_FREQ_EST = 384;
36 const int BRANCH_CYCLE = 2;
37 #endif
38
39 //extern "C" void* xmemcpy(void*, void*, size_t);
40 #define MEMCPY memcpy
41
42 typedef long long nsecs_t;
43
system_time()44 static nsecs_t system_time()
45 {
46 struct timespec t;
47 t.tv_sec = t.tv_nsec = 0;
48 clock_gettime(CLOCK_MONOTONIC, &t);
49 return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec;
50 }
51
52 nsecs_t loop_overhead(size_t count) __attribute__((noinline));
loop_overhead(size_t count)53 nsecs_t loop_overhead(size_t count)
54 {
55 nsecs_t overhead = -system_time();
56 do {
57 asm volatile ("":::"memory");
58 } while (--count);
59 overhead += system_time();
60 return overhead;
61 }
62
preload(volatile char * addr,size_t s)63 static void preload(volatile char* addr, size_t s)
64 {
65 for (size_t i=0 ; i<s ; i+=32) {
66 char c = addr[i];
67 (void)c;
68 }
69 }
70
usage(char * p)71 static void usage(char* p) {
72 printf( "Usage: %s <test> <options>\n"
73 "<test> is one of the following:\n"
74 " cpufreq\n"
75 " memcpy [perf [fast] | test]\n"
76 " memset [perf | test]\n"
77 " memcmp [perf | test]\n"
78 " strlen [perf | test]\n"
79 " malloc [fill]\n"
80 " madvise\n"
81 " resampler\n"
82 " crash\n"
83 " stack (stack smasher)\n"
84 " crawl\n"
85 , p);
86 }
87
88 int cpufreq_test(int argc, char** argv);
89 int memcpy_test(int argc, char** argv);
90 int memset_test(int argc, char** argv);
91 int memcmp_test(int argc, char** argv);
92 int strlen_test(int argc, char** argv);
93 int malloc_test(int argc, char** argv);
94 int madvise_test(int argc, char** argv);
95 int crash_test(int argc, char** argv);
96 int stack_smasher_test(int argc, char** argv);
97 int crawl_test(int argc, char** argv);
98 int fp_test(int argc, char** argv);
99
100 #if 0
101 #pragma mark -
102 #pragma mark main
103 #endif
104
main(int argc,char ** argv)105 int main(int argc, char** argv)
106 {
107 if (argc == 1) {
108 usage(argv[0]);
109 return 0;
110 }
111 int err = -1;
112 if (!strcmp(argv[1], "cpufreq")) err = cpufreq_test(argc-1, argv+1);
113 else if (!strcmp(argv[1], "memcpy")) err = memcpy_test(argc-1, argv+1);
114 else if (!strcmp(argv[1], "memset")) err = memset_test(argc-1, argv+1);
115 else if (!strcmp(argv[1], "memcmp")) err = memcmp_test(argc-1, argv+1);
116 else if (!strcmp(argv[1], "strlen")) err = strlen_test(argc-1, argv+1);
117 else if (!strcmp(argv[1], "malloc")) err = malloc_test(argc-1, argv+1);
118 else if (!strcmp(argv[1], "madvise")) err = madvise_test(argc-1, argv+1);
119 else if (!strcmp(argv[1], "crash")) err = crash_test(argc-1, argv+1);
120 else if (!strcmp(argv[1], "stack")) err = stack_smasher_test(argc-1, argv+1);
121 else if (!strcmp(argv[1], "crawl")) err = crawl_test(argc-1, argv+1);
122 else if (!strcmp(argv[1], "fp")) err = fp_test(argc-1, argv+1);
123 if (err) {
124 usage(argv[0]);
125 }
126 return 0;
127 }
128
129 #if 0
130 #pragma mark -
131 #pragma mark memcpy
132 #endif
133
134 int validate_memcpy(char* s, char* d, size_t size);
135 int validate_memset(char* s, char c, size_t size);
136
memcpy_test(int argc,char ** argv)137 int memcpy_test(int argc, char** argv)
138 {
139 int option = 0;
140 if (argc >= 2) {
141 if (!strcmp(argv[1], "perf")) option = 0;
142 else if (!strcmp(argv[1], "test")) option = 1;
143 else return -1;
144 }
145
146 const int MAX_SIZE = 1024*1024; // 1MB
147 const int CACHED_SPEED_EST = CPU_FREQ_EST*1024*1024; // 150 MB/s
148 const int UNCACHED_SPEED_EST = (CPU_FREQ_EST/4)*1024*1024; // 60 MB/s
149 char* src = (char*)malloc(MAX_SIZE+4+8+32);
150 char* dst = (char*)malloc(MAX_SIZE+4+8+32);
151 memset(src, 0, MAX_SIZE+4+8+32);
152 memset(dst, 0, MAX_SIZE+4+8+32);
153
154 if (option == 0) {
155 bool fast = (argc>=3 && !strcmp(argv[2], "fast"));
156 printf("memcpy() performance test is running, please wait...\n");
157 fflush(stdout);
158 usleep(10000);
159 setpriority(PRIO_PROCESS, 0, -20);
160 static int FAST_SIZES[] = { 1024, DCACHE_SIZE/2, DCACHE_SIZE, DCACHE_SIZE*2, MAX_SIZE };
161
162 struct result_t { int size; float res; };
163 result_t* results = (result_t*)src;
164 int nbr = 0;
165 int size = 0;
166 for (int i=0 ; ; i++) {
167 if (!fast) {
168 if (size<128) size += 8;
169 else if (size<1024) size += 128;
170 else if (size<16384) size += 1024;
171 else size <<= 1;
172 } else {
173 if (size_t(i) >= sizeof(FAST_SIZES)/sizeof(FAST_SIZES[0]))
174 break;
175 size = FAST_SIZES[i];
176 }
177 if (size > MAX_SIZE) {
178 break;
179 }
180
181 const int REPEAT = (((size < DCACHE_SIZE) ?
182 (CACHED_SPEED_EST) : (UNCACHED_SPEED_EST)) / size) / 2;
183 // ~0.5 second per test
184
185 const nsecs_t overhead = loop_overhead(REPEAT);
186
187 // tweak to make it a bad case
188 char* ddd = (char*)((long(dst+31)&~31) + 4);
189 char* sss = (char*)((long(src+31)&~31) + 28);
190
191 for (int offset=0 ; offset<=2 ; offset +=2 ) {
192 memcpy(dst, src, size); // just make sure to load the caches I/D
193 nsecs_t t = -system_time();
194 register int count = REPEAT;
195 do {
196 MEMCPY(ddd, sss+offset, size);
197 } while (--count);
198 t += system_time() - overhead;
199 const float throughput = (size*1000000000.0f*REPEAT) / (1024*1024*t);
200 results[nbr].size = size;
201 results[nbr].res = throughput;
202 nbr++;
203 }
204 }
205
206 printf("%9s %9s %9s\n", "size", "MB/s", "MB/s (nc)");
207 for (int i=0 ; i<nbr ; i+=2) {
208 printf("%9d %9ld %9ld\n", results[i].size, (long)results[i].res, (long)results[i+1].res);
209 }
210 } else if (option == 1) {
211 printf("memcpy() validation test is running, please wait...\n");
212 fflush(stdout);
213 char* curr = (char*)src;
214 for (int i=0 ; i<MAX_SIZE ; i++) {
215 char c = rand();
216 *curr++ = c != 0x55 ? c : 0xAA;
217 }
218 char* s = src + 1024;
219 char* d = dst + 1024;
220 int nb = 0;
221 for (int size=0 ; size<4096 && !nb ; size++) {
222 nb += validate_memcpy(s, d, size);
223 for (int o=1 ; o<32 && !nb ; o++) {
224 nb += validate_memcpy(s+o, d, size);
225 nb += validate_memcpy(s, d+o, size);
226 nb += validate_memcpy(s+o, d+o, size);
227 }
228 }
229 if (nb) printf("%d error(s) found\n", nb);
230 else printf("success!\n");
231 }
232 fflush(stdout);
233 free(dst);
234 free(src);
235 return 0;
236 }
237
validate_memcpy(char * s,char * d,size_t size)238 int validate_memcpy(char* s, char* d, size_t size)
239 {
240 int nberr = 0;
241 memset(d-4, 0x55, size+8);
242 MEMCPY(s, d, size);
243 if (memcmp(s,d,size)) {
244 printf("*** memcpy(%p,%p,%zd) destination != source\n",s,d,size);
245 nberr++;
246 }
247 bool r = (d[size]==0x55)&&(d[size+1]==0x55)&&(d[size+2]==0x55)&&(d[size+3]==0x55);
248 if (!r) {
249 printf("*** memcpy(%p,%p,%zd) clobbered past end of destination!\n",s,d,size);
250 nberr++;
251 }
252 r = (d[-1]==0x55)&&(d[-2]==0x55)&&(d[-3]==0x55)&&(d[-4]==0x55);
253 if (!r) {
254 printf("*** memcpy(%p,%p,%zd) clobbered before start of destination!\n",s,d,size);
255 nberr++;
256 }
257 return nberr;
258 }
259
260
261 #if 0
262 #pragma mark -
263 #pragma mark memset
264 #endif
265
memset_test(int argc,char ** argv)266 int memset_test(int argc, char** argv)
267 {
268 int option = 0;
269 if (argc >= 2) {
270 if (!strcmp(argv[1], "perf")) option = 0;
271 else if (!strcmp(argv[1], "test")) option = 1;
272 else return -1;
273 }
274
275 const int MAX_SIZE = 1024*1024; // 1MB
276 const int CACHED_SPEED_EST = CPU_FREQ_EST*1024*1024; // 195 MB/s
277 const int UNCACHED_SPEED_EST = CPU_FREQ_EST*1024*1024; // 195 MB/s
278 char* dst = (char*)malloc(MAX_SIZE+4+8);
279
280 if (option == 0) {
281 printf("memset() performance test is running, please wait...\n");
282 fflush(stdout);
283 usleep(10000);
284 setpriority(PRIO_PROCESS, 0, -20);
285
286 static int FAST_SIZES[] = { 1024, DCACHE_SIZE/2, DCACHE_SIZE, DCACHE_SIZE*2, MAX_SIZE };
287 const size_t FAST_SIZES_COUNT = sizeof(FAST_SIZES)/sizeof(FAST_SIZES[0]);
288 struct result_t { int size; float res; };
289 result_t results[FAST_SIZES_COUNT*2];
290 int nbr = 0;
291 int size = 0;
292 for (int i=0 ; ; i++) {
293 if (size_t(i) >= sizeof(FAST_SIZES)/sizeof(FAST_SIZES[0]))
294 break;
295 size = FAST_SIZES[i];
296 if (size > MAX_SIZE) {
297 break;
298 }
299 const int REPEAT = (((size < DCACHE_SIZE) ?
300 (CACHED_SPEED_EST) : (UNCACHED_SPEED_EST)) / size);
301 // ~0.5 second per test
302
303 const nsecs_t overhead = loop_overhead(REPEAT);
304
305 for (int j=0 ; j<2 ; j++) {
306 if (j==0) preload(dst, DCACHE_SIZE*4); // flush D
307 else preload(dst, size); // load D
308 nsecs_t t = -system_time();
309 size_t count = REPEAT;
310 do {
311 memset(dst, 0, size);
312 } while (--count);
313 t += system_time() - overhead;
314
315 const float throughput = (size*1000000000.0f*REPEAT) / (1024*1024*t);
316 results[nbr].size = size;
317 results[nbr].res = throughput;
318 nbr++;
319 }
320 }
321
322 printf("%9s %9s %9s\n", "size", "MB/s", "MB/s (cached)");
323 for (int i=0 ; i<nbr ; i+=2) {
324 printf("%9d %9ld %9ld\n", results[i].size, (long)results[i].res, (long)results[i+1].res);
325 }
326 } else if (option == 1) {
327 printf("memset() validation test is running, please wait...\n");
328 fflush(stdout);
329 char* d = dst + 1024;
330 int nb = 0;
331 for (int o=1 ; o<32 ; o++) {
332 for (int size=0 ; size<4096 && !nb ; size++) {
333 nb += validate_memset(d, char(o), size);
334 nb += validate_memset(d+o, char(o), size);
335 }
336 }
337 if (nb) printf("%d error(s) found\n", nb);
338 else printf("success!\n");
339 }
340 fflush(stdout);
341 free(dst);
342 return 0;
343 }
344
validate_memset(char * d,char c,size_t size)345 int validate_memset(char* d, char c, size_t size)
346 {
347 int nberr = 0;
348 for (size_t i=0; i<size ; d[i++]=0xaa) ;
349 d[-1] = 0x55;
350 d[size+1] = 0x55;
351 memset(d, c, size);
352 if (d[size+1]!=0x55) {
353 printf("*** memset(%p,%02x,%zd) clobbered past end of destination!\n",d,(int)c,size);
354 nberr++;
355 }
356 if (d[-1]!=0x55) {
357 printf("*** memset(%p,%02x,%zd) clobbered before start of destination!\n",d,(int)c,size);
358 nberr++;
359 }
360 for (size_t i=0 ; i<size ; i++) {
361 if (d[i] != c) {
362 printf("*** memset(%p,%02x,%zd) failed at offset %zd\n",d,(int)c,size, i);
363 nberr++;
364 break;
365 }
366 }
367 return nberr;
368 }
369
370 #if 0
371 #pragma mark -
372 #pragma mark memcmp
373 #endif
374
ref_memcmp(const void * s1,const void * s2,size_t n)375 static int ref_memcmp(const void *s1, const void *s2, size_t n)
376 {
377 const unsigned char *c1 = (const unsigned char *)s1, *c2 = (const unsigned char *)s2;
378 int d = 0;
379
380 while ( n-- ) {
381 d = (int)*c1++ - (int)*c2++;
382 if ( d )
383 break;
384 }
385
386 return (d < 0 ? -1 : (d > 0 ? 1 : 0));
387 }
388
validate_memcmp(const char * s,const char * d,size_t size)389 int validate_memcmp(const char* s, const char* d, size_t size)
390 {
391
392 int a = ref_memcmp(s, d, size);
393 int b = memcmp(s, d, size);
394 b = (b < 0 ? -1 : (b > 0 ? 1 : 0));
395 //printf("%d, %d\n", a, b);
396 if (a != b) {
397 printf("*** memcmp(%p,%p,%zd) failed %d should be %d\n",s,d,size,b,a);
398 return 1;
399 }
400 return 0;
401 }
402
memcmp_test(int argc,char ** argv)403 int memcmp_test(int argc, char** argv)
404 {
405 int option = 0;
406 if (argc >= 2) {
407 if (!strcmp(argv[1], "perf")) option = 0;
408 else if (!strcmp(argv[1], "test")) option = 1;
409 else return -1;
410 }
411
412 const int MAX_SIZE = 1024*1024; // 1MB
413 const int CACHED_SPEED_EST = CPU_FREQ_EST*1024*1024; // 150 MB/s
414 const int UNCACHED_SPEED_EST = (CPU_FREQ_EST/4)*1024*1024; // 60 MB/s
415 char* src = (char*)malloc(MAX_SIZE+4+8+32);
416 char* dst = (char*)malloc(MAX_SIZE+4+8+32);
417
418 if (option == 0) {
419 printf("memcmp() performance test is running, please wait...\n");
420 fflush(stdout);
421 usleep(10000);
422 setpriority(PRIO_PROCESS, 0, -20);
423
424 static int FAST_SIZES[] = { 1024, DCACHE_SIZE/2, DCACHE_SIZE, DCACHE_SIZE*2, MAX_SIZE };
425
426 struct result_t { int size; float res; };
427 result_t* results = (result_t*)src;
428 int nbr = 0;
429 int size = 0;
430 for (int i=0 ; ; i++) {
431 if (size_t(i) >= sizeof(FAST_SIZES)/sizeof(FAST_SIZES[0]))
432 break;
433 size = FAST_SIZES[i];
434 if (size > MAX_SIZE) {
435 break;
436 }
437
438 const int REPEAT = (((size < DCACHE_SIZE) ?
439 (CACHED_SPEED_EST) : (UNCACHED_SPEED_EST)) / size) / 2;
440 // ~0.5 second per test
441
442 const nsecs_t overhead = loop_overhead(REPEAT);
443
444 // tweak to make it a bad case
445 char* ddd = (char*)((long(dst+31)&~31) + 4);
446 char* sss = (char*)((long(src+31)&~31) + 28);
447
448 for (int offset=0 ; offset<=2 ; offset +=2 ) {
449 memcpy(ddd, sss+offset, size); // just make sure to load the caches I/D
450 nsecs_t t = -system_time();
451 register int count = REPEAT;
452 char c;
453 c = memcmp(ddd, sss+offset, size);
454 //printf("size %d, memcmp -> %d\n", size, (int)c);
455 do {
456 c = memcmp(ddd, sss+offset, size);
457 asm volatile (""::"r"(c):"memory");
458 } while (--count);
459 t += system_time() - overhead;
460 const float throughput = (size*1000000000.0f*REPEAT) / (1024*1024*t);
461 results[nbr].size = size;
462 results[nbr].res = throughput;
463 nbr++;
464 }
465 }
466
467 printf("%9s %9s %9s\n", "size", "MB/s", "MB/s (nc)");
468 for (int i=0 ; i<nbr ; i+=2) {
469 printf("%9d %9ld %9ld\n", results[i].size, (long)results[i].res, (long)results[i+1].res);
470 }
471 } else {
472 printf("memcmp() validation test is running, please wait...\n");
473 fflush(stdout);
474
475 const char* const s = (const char*)src + 1024;
476 const char* const d = (const char*)dst + 1024;
477 int nb = 0;
478 for (int j=0 ; j<32 ; j++) {
479
480 char *curr0 = (char*)src;
481 char *curr1 = (char*)dst;
482 for (int i=0 ; i<MAX_SIZE ; i++) {
483 char c = rand();
484 *curr0++ = c;
485 *curr1++ = c;
486 }
487 if (j) {
488 src[1024 + j] ^= 0xFF;
489 }
490
491
492 for (int size=0 ; size<32 && !nb ; size++) {
493 for (int o=0 ; o<4 ; o++) {
494 nb += validate_memcmp(s+o, d+o, size);
495 }
496 // memmove((char*)d+1, d, size);
497 for (int o=0 ; o<4 ; o++) {
498 nb += validate_memcmp(s, d+o, size);
499 }
500 }
501 }
502 if (nb) printf("%d error(s) found\n", nb);
503 else printf("success!\n");
504 }
505 fflush(stdout);
506 free(dst);
507 free(src);
508 return 0;
509 }
510
511 #if 0
512 #pragma mark -
513 #pragma mark strlen
514 #endif
515
strlen_test(int argc,char ** argv)516 int strlen_test(int argc, char** argv)
517 {
518 int option = 0;
519 if (argc >= 2) {
520 if (!strcmp(argv[1], "perf")) option = 0;
521 else if (!strcmp(argv[1], "test")) option = 1;
522 else return -1;
523 }
524
525 const int MAX_SIZE = 1024*1024; // 1MB
526 const int CACHED_SPEED_EST = CPU_FREQ_EST*1024*1024; // 195 MB/s
527 const int UNCACHED_SPEED_EST = CPU_FREQ_EST*1024*1024; // 195 MB/s
528 char* str = (char*)calloc(MAX_SIZE+4+8, 1);
529
530 if (option == 0) {
531 printf("strlen() performance test is running, please wait...\n");
532 fflush(stdout);
533 usleep(10000);
534 setpriority(PRIO_PROCESS, 0, -20);
535
536 static int FAST_SIZES[] = { 1024, DCACHE_SIZE/2, DCACHE_SIZE, DCACHE_SIZE*2, MAX_SIZE };
537 const size_t FAST_SIZES_COUNT = sizeof(FAST_SIZES)/sizeof(FAST_SIZES[0]);
538 struct result_t { int size; float res; };
539 result_t results[FAST_SIZES_COUNT*2];
540 int nbr = 0;
541 int size = 0;
542 for (int i=0 ; ; i++) {
543 if (size_t(i) >= sizeof(FAST_SIZES)/sizeof(FAST_SIZES[0]))
544 break;
545 size = FAST_SIZES[i];
546 if (size > MAX_SIZE) {
547 break;
548 }
549 const int REPEAT = (((size < DCACHE_SIZE) ?
550 (CACHED_SPEED_EST) : (UNCACHED_SPEED_EST)) / size);
551 // ~0.5 second per test
552
553 const nsecs_t overhead = loop_overhead(REPEAT);
554
555 for (int j=0 ; j<2 ; j++) {
556 memset(str, 'A', size-1);
557 if (j==0) preload(str, DCACHE_SIZE*4); // flush D
558 else preload(str, size); // load D
559
560 nsecs_t t = -system_time();
561 size_t count = REPEAT;
562 int c=0;
563 do {
564 c = strlen(str);
565 asm volatile (""::"r"(c):"memory");
566 } while (--count);
567 t += system_time() - overhead;
568
569 const float throughput = (size*1000000000.0f*REPEAT) / (1024*1024*t);
570 results[nbr].size = size;
571 results[nbr].res = throughput;
572 nbr++;
573 }
574 }
575
576 printf("%9s %9s %9s\n", "size", "MB/s", "MB/s (cached)");
577 for (int i=0 ; i<nbr ; i+=2) {
578 printf("%9d %9ld %9ld\n", results[i].size, (long)results[i].res, (long)results[i+1].res);
579 }
580 }
581
582 fflush(stdout);
583 free(str);
584 return 0;
585 }
586
587
588 #if 0
589 #pragma mark -
590 #pragma mark malloc
591 #endif
592
malloc_test(int argc,char ** argv)593 int malloc_test(int argc, char** argv)
594 {
595 bool fill = (argc>=2 && !strcmp(argv[1], "fill"));
596 size_t total = 0;
597 size_t size = 0x40000000;
598 while (size) {
599 void* addr = malloc(size);
600 if (addr == 0) {
601 printf("size = %9zd failed\n", size);
602 size >>= 1;
603 } else {
604 total += size;
605 printf("size = %9zd, addr = %p (total = %9zd (%zd MB))\n",
606 size, addr, total, total / (1024*1024));
607 if (fill) {
608 printf("filling...\n");
609 fflush(stdout);
610 memset(addr, 0, size);
611 }
612 size = size + (size>>1);
613 }
614 }
615 printf("done. allocated %zd MB\n", total / (1024*1024));
616 return 0;
617 }
618
619 #if 0
620 #pragma mark -
621 #pragma mark madvise
622 #endif
623
madvise_test(int argc,char ** argv)624 int madvise_test(int argc, char** argv)
625 {
626 for (int i=0 ; i<2 ; i++) {
627 size_t size = i==0 ? 4096 : 48*1024*1024; // 48 MB
628 printf("Allocating %zd MB... ", size/(1024*1024)); fflush(stdout);
629 void* addr1 = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
630 printf("%p (%s)\n", addr1, addr1==(void*)-1 ? "failed" : "OK"); fflush(stdout);
631
632 printf("touching %p...\n", addr1); fflush(stdout);
633 memset(addr1, 0x55, size);
634
635 printf("advising DONTNEED...\n"); fflush(stdout);
636 madvise(addr1, size, MADV_DONTNEED);
637
638 printf("reading back %p...\n", addr1); fflush(stdout);
639 if (*(long*)addr1 == 0) {
640 printf("madvise freed some pages\n");
641 } else if (*(long*)addr1 == 0x55555555) {
642 printf("pages are still there\n");
643 } else {
644 printf("getting garbage back\n");
645 }
646
647 printf("Allocating %zd MB... ", size/(1024*1024)); fflush(stdout);
648 void* addr2 = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
649 printf("%p (%s)\n", addr2, addr2==(void*)-1 ? "failed" : "OK"); fflush(stdout);
650
651 printf("touching %p...\n", addr2); fflush(stdout);
652 memset(addr2, 0xAA, size);
653
654 printf("unmap %p ...\n", addr2); fflush(stdout);
655 munmap(addr2, size);
656
657 printf("touching %p...\n", addr1); fflush(stdout);
658 memset(addr1, 0x55, size);
659
660 printf("unmap %p ...\n", addr1); fflush(stdout);
661 munmap(addr1, size);
662 }
663
664 printf("Done\n"); fflush(stdout);
665 return 0;
666 }
667
668 #if 0
669 #pragma mark -
670 #pragma mark cpufreq
671 #endif
672
cpufreq_test(int argc,char ** argv)673 int cpufreq_test(int argc, char** argv)
674 {
675 struct timespec res;
676 clock_getres(CLOCK_REALTIME, &res);
677 printf("CLOCK_REALTIME resolution: %lu ns\n", res.tv_nsec);
678 clock_getres(CLOCK_MONOTONIC, &res);
679 printf("CLOCK_MONOTONIC resolution: %lu ns\n", res.tv_nsec);
680 clock_getres(CLOCK_PROCESS_CPUTIME_ID, &res);
681 printf("CLOCK_PROCESS_CPUTIME_ID resolution: %lu ns\n", res.tv_nsec);
682 clock_getres(CLOCK_THREAD_CPUTIME_ID, &res);
683 printf("CLOCK_THREAD_CPUTIME_ID resolution: %lu ns\n", res.tv_nsec);
684
685 if (clock_getres(CLOCK_REALTIME_HR, &res) != 0)
686 printf("CLOCK_REALTIME_HR resolution: %lu ns\n", res.tv_nsec);
687 else
688 printf("CLOCK_REALTIME_HR not supported\n");
689
690 if (clock_getres(CLOCK_MONOTONIC_HR, &res) != 0)
691 printf("CLOCK_MONOTONIC_HR resolution: %lu ns\n", res.tv_nsec);
692 else
693 printf("CLOCK_MONOTONIC_HR not supported\n");
694
695 printf("\nEstimating the CPU frequency, please wait...\n");
696 fflush(stdout);
697 usleep(10000);
698 setpriority(PRIO_PROCESS, 0, -20);
699
700 const int LOOP_CYCLES = 1+BRANCH_CYCLE; // 1 cycle + 3 cycles for the branch
701 const size_t REPEAT = CPU_FREQ_EST*1000000; // ~4 seconds (4cycles/loop)
702 register size_t count = REPEAT;
703 nsecs_t t = system_time();
704 do { // this loop generates 1+3 cycles
705 asm volatile ("":::"memory");
706 } while (--count);
707 t = system_time() - t;
708 const float freq = t ? (1000.0f*float(REPEAT)*LOOP_CYCLES) / t : 0;
709 printf("this CPU frequency: %ld MHz\n", long(freq+0.5f));
710 return 0;
711 }
712
713 #if 0
714 #pragma mark -
715 #pragma mark crash_test
716 #endif
717
crash_test(int argc,char ** argv)718 int crash_test(int argc, char** argv)
719 {
720 printf("about to crash...\n");
721 asm volatile(
722 "mov r0, #0 \n"
723 "mov r1, #1 \n"
724 "mov r2, #2 \n"
725 "mov r3, #3 \n"
726 "ldr r12, [r0] \n"
727 );
728
729 return 0;
730 }
731
stack_smasher_test(int argc,char ** argv)732 int stack_smasher_test(int argc, char** argv)
733 {
734 int dummy = 0;
735 printf("corrupting our stack...\n");
736 *(volatile long long*)&dummy = 0;
737 return 0;
738 }
739
740 // --------------------------------------------------------------------
741
742 extern "C" void thumb_function_1(int*p);
743 extern "C" void thumb_function_2(int*p);
744 extern "C" void arm_function_3(int*p);
745 extern "C" void arm_function_2(int*p);
746 extern "C" void arm_function_1(int*p);
747
arm_function_3(int * p)748 void arm_function_3(int*p) {
749 int a = 0;
750 thumb_function_2(&a);
751 }
752
arm_function_2(int * p)753 void arm_function_2(int*p) {
754 int a = 0;
755 thumb_function_1(&a);
756 }
757
arm_function_1(int * p)758 void arm_function_1(int*p) {
759 int a = 0;
760 arm_function_2(&a);
761 }
762
crawl_test(int argc,char ** argv)763 int crawl_test(int argc, char** argv)
764 {
765 int a = 0;
766 arm_function_1(&a);
767 return 0;
768 }
769
770