1 #define _GNU_SOURCE 2 #include <string.h> 3 #include <pthread.h> 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include <unistd.h> 7 #include <sys/types.h> 8 9 // memrw provides a simulation of an application 10 // reading and writing memory, for the sake of tuning helgrind. 11 // It is a very simple (simplistic) model: 12 // * only one thread 13 // * only one exe context reading or writing the memory 14 // * the working set of the application is unrealistically 15 // concentrated on a consecutive nr of MB. 16 // At this moment, it was just used to tune the EvM data structure 17 // of helgrind. 18 // It would be nice to enhance this program to cope with a richer 19 // model e.g. multiple threads, many different stack traces touching 20 // the memory, better working set distribution, ... 21 22 static int sz_b; // size of a block 23 static int nr_b; // total nr of blocks used by the program 24 static int nr_b_ws; // nr_b in program working set 25 static int nr_loops; // nr of loops reading or writing the ws 26 static int nr_thr; // nr of threads (hardcoded to 1 currently) 27 static int nr_repeat; // nr of times we will allocate, use, then free total+ws 28 29 // Note: the total nr of MB is what is explicitly allocated. 30 // On top of that, we have the stacks, local vars, lib vars, ... 31 // The working set is just the first nr_b_ws blocks of nr_b. 32 33 static int verbose = 0; 34 static unsigned char **t_b; // Pointers to all blocks 35 36 static void *memrw_fn(void *v) 37 { 38 int loops, m, b; 39 int dowrite; 40 int differs = 0; 41 unsigned char prev = 0; 42 43 for (loops = 0; loops < nr_loops; loops++) { 44 // printf("loop %d dowrite %d\n", loops, dowrite); 45 // Note: in case of multiple threads, we will have 46 // to add lock/unlock somewhere in the below, maybe to lock 47 // the MB we are reading or writing. 48 for (m = 0; m < nr_b_ws; m++) { 49 for (b = 0; b < sz_b; b++) { 50 dowrite = b % 5 == 0; 51 // Do some write or read operations. 52 if (dowrite) { 53 if (t_b[m][b] < 255) 54 t_b[m][b] += differs; 55 else 56 t_b[m][b] = 0; 57 } else { 58 differs = t_b[m][b] != prev; 59 prev = t_b[m][b]; 60 } 61 } 62 } 63 } 64 return NULL; 65 } 66 67 int main (int argc, char *argv[]) 68 { 69 int a; 70 int ret; 71 int i; 72 int r; 73 pthread_t thr; 74 75 // usage: memrw [-b blocksize default 1MB ] 76 // [-t nr_b default 10] [-w nr_b_ws default 10] 77 // [-l nr_loops_on_ws default 3] 78 // [-r nr_repeat default 1] 79 // [-f fan_out default 0] 80 // [-v verbosity default 0] 81 sz_b = 1024 * 1024; 82 nr_b = 10; 83 nr_b_ws = 10; 84 nr_loops = 3; 85 nr_repeat = 1; 86 verbose = 0; 87 for (a = 1; a < argc; a+=2) { 88 if (strcmp(argv[a], "-b") == 0) { 89 sz_b = atoi(argv[a+1]); 90 } else if (strcmp(argv[a], "-t") == 0) { 91 nr_b = atoi(argv[a+1]); 92 } else if (strcmp(argv[a], "-w") == 0) { 93 nr_b_ws = atoi(argv[a+1]); 94 } else if (strcmp(argv[a], "-l") == 0) { 95 nr_loops = atoi(argv[a+1]); 96 } else if (strcmp(argv[a], "-r") == 0) { 97 nr_repeat = atoi(argv[a+1]); 98 } else if (strcmp(argv[a], "-v") == 0) { 99 verbose = atoi(argv[a+1]); 100 } else { 101 printf("unknown arg %s\n", argv[a]); 102 } 103 } 104 if (nr_b_ws > nr_b) 105 nr_b_ws = nr_b; // to make it easy to do loops combining values 106 107 nr_thr = 1; 108 109 printf ("total program memory -t %llu MB" 110 " working set -w %llu MB\n", 111 ((unsigned long long)nr_b * sz_b) 112 / (unsigned long long) (1024*1024), 113 ((unsigned long long)nr_b_ws * sz_b) 114 / (unsigned long long)(1024*1024)); 115 printf (" working set R or W -l %d times" 116 " repeat the whole stuff -r %d times\n", 117 nr_loops, 118 nr_repeat); 119 120 for (r = 0; r < nr_repeat; r++) { 121 printf ("creating and initialising the total program memory\n"); 122 t_b = malloc(nr_b * sizeof(char*)); 123 if (t_b == NULL) 124 perror("malloc t_b"); 125 for (i = 0; i < nr_b; i++) { 126 t_b[i] = calloc(sz_b, 1); 127 if (t_b[i] == NULL) 128 perror("malloc t_b[i]"); 129 } 130 131 printf("starting thread that will read or write the working set\n"); 132 ret = pthread_create(&thr, NULL, memrw_fn, &nr_thr); 133 if (ret != 0) 134 perror("pthread_create"); 135 printf("waiting for thread termination\n"); 136 137 ret = pthread_join(thr, NULL); 138 if (ret != 0) 139 perror("pthread_join"); 140 printf("thread terminated\n"); 141 142 /* Now, free the memory used, for the next repeat */ 143 for (i = 0; i < nr_b; i++) 144 free (t_b[i]); 145 free (t_b); 146 printf("memory freed\n"); 147 } 148 149 return 0; 150 } 151