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 int fp_test(int argc, char** argv); 99 100 #if 0 101 #pragma mark - 102 #pragma mark main 103 #endif 104 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 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 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 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 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 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 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 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 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 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 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 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 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 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 748 void arm_function_3(int*p) { 749 int a = 0; 750 thumb_function_2(&a); 751 } 752 753 void arm_function_2(int*p) { 754 int a = 0; 755 thumb_function_1(&a); 756 } 757 758 void arm_function_1(int*p) { 759 int a = 0; 760 arm_function_2(&a); 761 } 762 763 int crawl_test(int argc, char** argv) 764 { 765 int a = 0; 766 arm_function_1(&a); 767 return 0; 768 } 769 770