njn | f131b3a | 2005-12-14 05:33:35 +0000 | [diff] [blame] | 1 | // This artificial program runs a lot of code. The exact amount depends on |
| 2 | // the command line -- if any command line args are given, it does exactly |
| 3 | // the same amount of work, but using four times as much code. |
| 4 | // |
| 5 | // It's a stress test for Valgrind's translation speed; natively the two |
| 6 | // modes run in about the same time (the I-cache effects aren't big enough |
| 7 | // to make a difference), but under Valgrind the one running more code is |
| 8 | // significantly slower due to the extra translation time. |
| 9 | |
| 10 | #include <stdio.h> |
| 11 | #include <string.h> |
sewardj | 0d3a1a8 | 2005-12-15 16:11:25 +0000 | [diff] [blame] | 12 | #include <assert.h> |
petarj | 213b0d3 | 2013-09-15 22:16:38 +0000 | [diff] [blame^] | 13 | #if defined(__mips__) |
| 14 | #include <asm/cachectl.h> |
| 15 | #include <sys/syscall.h> |
| 16 | #endif |
njn | 83b62cb | 2009-04-15 03:12:43 +0000 | [diff] [blame] | 17 | #include "tests/sys_mman.h" |
njn | f131b3a | 2005-12-14 05:33:35 +0000 | [diff] [blame] | 18 | |
| 19 | #define FN_SIZE 996 // Must be big enough to hold the compiled f() |
| 20 | #define N_LOOPS 20000 // Should be divisible by four |
| 21 | #define RATIO 4 // Ratio of code sizes between the two modes |
| 22 | |
| 23 | int f(int x, int y) |
| 24 | { |
| 25 | int i; |
| 26 | for (i = 0; i < 5000; i++) { |
| 27 | switch (x % 8) { |
| 28 | case 1: y += 3; |
| 29 | case 2: y += x; |
| 30 | case 3: y *= 2; |
| 31 | default: y--; |
| 32 | } |
| 33 | } |
| 34 | return y; |
| 35 | } |
| 36 | |
njn | f131b3a | 2005-12-14 05:33:35 +0000 | [diff] [blame] | 37 | int main(int argc, char* argv[]) |
| 38 | { |
| 39 | int h, i, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0; |
| 40 | int n_fns, n_reps; |
| 41 | |
sewardj | 0d3a1a8 | 2005-12-15 16:11:25 +0000 | [diff] [blame] | 42 | char* a = mmap(0, FN_SIZE * N_LOOPS, |
| 43 | PROT_EXEC|PROT_WRITE, |
sewardj | 799a284 | 2006-10-17 02:27:41 +0000 | [diff] [blame] | 44 | MAP_PRIVATE|MAP_ANONYMOUS, -1,0); |
sewardj | 0d3a1a8 | 2005-12-15 16:11:25 +0000 | [diff] [blame] | 45 | assert(a != (char*)MAP_FAILED); |
| 46 | |
njn | f131b3a | 2005-12-14 05:33:35 +0000 | [diff] [blame] | 47 | if (argc <= 1) { |
| 48 | // Mode 1: not so much code |
| 49 | n_fns = N_LOOPS / RATIO; |
| 50 | n_reps = RATIO; |
| 51 | printf("mode 1: "); |
| 52 | } else { |
| 53 | // Mode 2: lots of code |
| 54 | n_fns = N_LOOPS; |
| 55 | n_reps = 1; |
| 56 | printf("mode 1: "); |
| 57 | } |
| 58 | printf("%d copies of f(), %d reps\n", n_fns, n_reps); |
| 59 | |
| 60 | // Make a whole lot of copies of f(). FN_SIZE is much bigger than f() |
| 61 | // will ever be (we hope). |
| 62 | for (i = 0; i < n_fns; i++) { |
| 63 | memcpy(&a[FN_SIZE*i], f, FN_SIZE); |
| 64 | } |
petarj | 213b0d3 | 2013-09-15 22:16:38 +0000 | [diff] [blame^] | 65 | |
| 66 | #if defined(__mips__) |
| 67 | syscall(__NR_cacheflush, a, FN_SIZE * n_fns, ICACHE); |
| 68 | #endif |
| 69 | |
njn | f131b3a | 2005-12-14 05:33:35 +0000 | [diff] [blame] | 70 | for (h = 0; h < n_reps; h += 1) { |
| 71 | for (i = 0; i < n_fns; i += 4) { |
| 72 | int(*f1)(int,int) = (void*)&a[FN_SIZE*(i+0)]; |
| 73 | int(*f2)(int,int) = (void*)&a[FN_SIZE*(i+1)]; |
| 74 | int(*f3)(int,int) = (void*)&a[FN_SIZE*(i+2)]; |
| 75 | int(*f4)(int,int) = (void*)&a[FN_SIZE*(i+3)]; |
| 76 | sum1 += f1(i+0, n_fns-i+0); |
| 77 | sum2 += f2(i+1, n_fns-i+1); |
| 78 | sum3 += f3(i+2, n_fns-i+2); |
| 79 | sum4 += f4(i+3, n_fns-i+3); |
| 80 | if (i % 1000 == 0) |
| 81 | printf("."); |
| 82 | } |
| 83 | } |
| 84 | printf("result = %d\n", sum1 + sum2 + sum3 + sum4); |
| 85 | return 0; |
| 86 | } |