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 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)); 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 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 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 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 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 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,%lu) 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,%lu) 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,%lu) 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 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 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,%lu) clobbered past end of destination!\n",d,(int)c,size); 352 nberr++; 353 } 354 if (d[-1]!=0x55) { 355 printf("*** memset(%p,%02x,%lu) 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,%lu) failed at offset %lu\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 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 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,%lu) failed %d should be %d\n",s,d,size,b,a); 396 return 1; 397 } 398 return 0; 399 } 400 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 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 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 = %9lu failed\n", size); 600 size >>= 1; 601 } else { 602 total += size; 603 printf("size = %9lu, addr = %p (total = %9lu (%lu 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 %lu MB\n", total / (1024*1024)); 614 return 0; 615 } 616 617 #if 0 618 #pragma mark - 619 #pragma mark madvise 620 #endif 621 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 %lu 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 %lu 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 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 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 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 746 void arm_function_3(int*p) { 747 int a = 0; 748 thumb_function_2(&a); 749 } 750 751 void arm_function_2(int*p) { 752 int a = 0; 753 thumb_function_1(&a); 754 } 755 756 void arm_function_1(int*p) { 757 int a = 0; 758 arm_function_2(&a); 759 } 760 761 int crawl_test(int argc, char** argv) 762 { 763 int a = 0; 764 arm_function_1(&a); 765 return 0; 766 } 767 768