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