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