blob: c10c38481db58183b82ece01e01117416068313d [file] [log] [blame]
philippecabdbb52015-04-20 21:33:16 +00001#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
22static int nr_mb = 0; // total nr of mb used by the program
23static int nr_mb_ws = 0; // nr_mb in program working set
24static int nr_loops = 0; // nr of loops reading or writing the ws
25static int nr_thr; // nr of threads (hardcoded to 1 currently)
26
27// Note: the total nr of mb is what is explicitely allocated.
28// On top of that, we have the stacks, local vars, lib vars, ...
29// The working set is just the first nr_mb_ws of nr_mb.
30
31static int verbose = 0;
32static unsigned char **mb;
33
34static void *memrw_fn(void *v)
35{
36 int loops, m, b;
philippe71a04ea2015-04-30 20:30:12 +000037 int dowrite;
philippecabdbb52015-04-20 21:33:16 +000038 int differs = 0;
39 unsigned char prev = 0;
40
41 for (loops = 0; loops < nr_loops; loops++) {
philippe71a04ea2015-04-30 20:30:12 +000042 // printf("loop %d dowrite %d\n", loops, dowrite);
philippecabdbb52015-04-20 21:33:16 +000043 // Note: in case of multiple threads, we will have
44 // to add lock/unlock somewhere in the below, maybe to lock
45 // the MB we are reading or writing.
46 for (m = 0; m < nr_mb_ws; m++) {
47 for (b = 0; b < 1024 * 1024; b++) {
philippe71a04ea2015-04-30 20:30:12 +000048 dowrite = b % 5 == 0;
philippecabdbb52015-04-20 21:33:16 +000049 // Do some write or read operations.
philippe71a04ea2015-04-30 20:30:12 +000050 if (dowrite) {
philippecabdbb52015-04-20 21:33:16 +000051 if (mb[m][b] < 255)
52 mb[m][b] += differs;
53 else
54 mb[m][b] = 0;
55 } else {
56 differs = mb[m][b] != prev;
57 prev = mb[m][b];
58 }
59 }
60 }
61 }
62 return NULL;
63}
64
65int main (int argc, char *argv[])
66{
67 int a;
68 int ret;
69 int i;
70 pthread_t thr;
71
72 // usage: memrw [-t nr_mb default 10] [-w nr_mb_ws default 10]
73 // [-l nr_loops_on_ws default 3]
74 // [-f fan_out default 0]
75 // [-v verbosity default 0]
76 nr_mb = 10;
77 nr_mb_ws = 10;
78 nr_loops = 3;
79 verbose = 0;
80 for (a = 1; a < argc; a+=2) {
81 if (strcmp(argv[a], "-t") == 0) {
82 nr_mb = atoi(argv[a+1]);
83 } else if (strcmp(argv[a], "-w") == 0) {
84 nr_mb_ws = atoi(argv[a+1]);
85 } else if (strcmp(argv[a], "-l") == 0) {
86 nr_loops = atoi(argv[a+1]);
87 } else if (strcmp(argv[a], "-v") == 0) {
88 verbose = atoi(argv[a+1]);
89 } else {
90 printf("unknown arg %s\n", argv[a]);
91 }
92 }
93 if (nr_mb_ws > nr_mb)
94 nr_mb_ws = nr_mb; // to make it easy to do loops combining values
95
96 nr_thr = 1;
97
98 printf ("total program memory -t %d MB"
99 " working set -w %d MB"
100 " working set R or W -l %d times"
101 "\n",
102 nr_mb,
103 nr_mb_ws,
104 nr_loops);
105
106 printf ("creating and initialising the total program memory\n");
107 mb = malloc(nr_mb * sizeof(char*));
108 if (mb == NULL)
109 perror("malloc mb");
110 for (i = 0; i < nr_mb; i++) {
111 mb[i] = calloc(1024*1024, 1);
112 if (mb[i] == NULL)
113 perror("malloc mb[i]");
114 }
115
116 printf("starting thread that will read or write the working set\n");
117 ret = pthread_create(&thr, NULL, memrw_fn, &nr_thr);
118 if (ret != 0)
119 perror("pthread_create");
120 printf("waiting for thread termination\n");
121
122 ret = pthread_join(thr, NULL);
123 if (ret != 0)
124 perror("pthread_join");
125 printf("thread terminated\n");
126
127 return 0;
128}