aboutsummaryrefslogtreecommitdiffstats
path: root/bin/mc2mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/mc2mem.c')
-rw-r--r--bin/mc2mem.c326
1 files changed, 326 insertions, 0 deletions
diff --git a/bin/mc2mem.c b/bin/mc2mem.c
new file mode 100644
index 0000000..1087381
--- /dev/null
+++ b/bin/mc2mem.c
@@ -0,0 +1,326 @@
1#include <sys/time.h>
2#include <sys/mman.h>
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <time.h>
8#include <string.h>
9#include <assert.h>
10#include <limits.h>
11#include <fcntl.h>
12#include <math.h>
13
14#include "litmus.h"
15#include "common.h"
16#include "cache_common.h"
17
18#define PAGE_SIZE (4096)
19#define CACHELINE_SIZE 32
20#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
21#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
22#define INTS_IN_1KB (1024 / sizeof(int))
23#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
24
25static int loops = 100;
26static cacheline_t* arena = NULL;
27static int verbose = 0;
28
29struct timeval t1,t2;
30
31
32#define UNCACHE_DEV "/dev/litmus/uncache"
33
34/* Random walk around the arena in cacheline-sized chunks.
35 Cacheline-sized chucks ensures the same utilization of each
36 hit line as sequential read. (Otherwise, our utilization
37 would only be 1/INTS_IN_CACHELINE.) */
38static int random_walk(cacheline_t *mem, int wss, int write_cycle)
39{
40 /* a random cycle among the cache lines was set up by init_arena(). */
41 int sum, i, next;
42
43 int numlines = wss * CACHELINES_IN_1KB;
44
45 sum = 0;
46
47 /* contents of arena is structured s.t. offsets are all
48 w.r.t. to start of arena, so compute the initial offset */
49 next = mem - arena;
50
51 if (write_cycle == 0) {
52 for (i = 0; i < numlines; i++) {
53 /* every element in the cacheline has the same value */
54 next = arena[next].line[0];
55 sum += next;
56 }
57 }
58
59 else {
60 int w, which_line;
61 for (i = 0, w = 0; i < numlines; i++) {
62 which_line = next;
63 next = arena[next].line[0];
64 if((w % write_cycle) != (write_cycle - 1)) {
65 sum += next;
66 }
67 else {
68 ((volatile cacheline_t*)arena)[which_line].line[0] = next;
69 }
70 }
71 }
72 return sum;
73}
74
75static cacheline_t* random_start(int wss)
76{
77 return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
78}
79
80static volatile int dont_optimize_me = 0;
81
82static void usage(char *error) {
83 fprintf(stderr, "Error: %s\n", error);
84 fprintf(stderr,
85 "Usage:\n"
86 " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
87 " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
88 " rt_spin -l\n"
89 "\n"
90 "COMMON-OPTS = [-w] [-s SCALE]\n"
91 " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
92 " [-k WSS] [-l LOOPS] [-b BUDGET]\n"
93 "\n"
94 "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
95 exit(EXIT_FAILURE);
96}
97
98static int loop_once(int wss)
99{
100 cacheline_t *mem;
101 int temp;
102
103 mem = random_start(wss);
104 temp = random_walk(mem, wss, 1);
105
106 //mem = sequential_start(wss);
107 //temp = sequential_walk(mem, wss, 0);
108 dont_optimize_me = temp;
109
110 return dont_optimize_me;
111}
112
113static int job(int wss, double exec_time, double program_end)
114{
115 if (wctime() > program_end)
116 return 0;
117 else {
118 register unsigned int iter = 0;
119 register cycles_t t;
120 t = get_cycles();
121 while(iter++ < loops) {
122 loop_once(wss);
123 }
124 t = get_cycles() - t;
125 if (verbose)
126 printf("%ld cycles\n", t);
127 sleep_next_period();
128 return 1;
129 }
130}
131
132#define OPTSTR "p:wl:m:i:b:k:vs:"
133int main(int argc, char** argv)
134{
135 int ret, i;
136 lt_t wcet, period, budget;
137 double wcet_ms, period_ms, budget_ms;
138 unsigned int priority = LITMUS_NO_PRIORITY;
139 int migrate = 0;
140 int cluster = 0;
141 int opt;
142 int wait = 0;
143 double duration = 0, start = 0;
144 struct rt_task param;
145 struct mc2_task mc2_param;
146 struct reservation_config config;
147 int res_type = PERIODIC_POLLING;
148 size_t arena_sz;
149 int wss = 1;
150 uint32_t mode_mask;
151
152 /* default for reservation */
153 config.id = 0;
154 config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
155 config.cpu = -1;
156
157 mc2_param.crit = CRIT_LEVEL_C;
158
159 budget_ms = 1000;
160
161 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
162 switch (opt) {
163 case 'w':
164 wait = 1;
165 break;
166 case 'p':
167 cluster = atoi(optarg);
168 migrate = 1;
169 config.cpu = cluster;
170 break;
171 case 'l':
172 loops = atoi(optarg);
173 break;
174 case 's':
175 wss = atoi(optarg);
176 break;
177 case 'k':
178 mode_mask = atoi(optarg);
179 break;
180 case 'm':
181 mc2_param.crit = atoi(optarg);
182 if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
183 res_type = PERIODIC_POLLING;
184 }
185 else
186 usage("Invalid criticality level.");
187 break;
188 case 'b':
189 budget_ms = atof(optarg);
190 break;
191 case 'i':
192 config.priority = atoi(optarg);
193 break;
194 case 'v':
195 verbose = 1;
196 break;
197 case ':':
198 usage("Argument missing.");
199 break;
200 case '?':
201 default:
202 usage("Bad argument.");
203 break;
204 }
205 }
206 srand(getpid());
207
208 /*
209 * We need three parameters
210 */
211 if (argc - optind < 3)
212 usage("Arguments missing.");
213
214 wcet_ms = atof(argv[optind + 0]);
215 period_ms = atof(argv[optind + 1]);
216
217 wcet = ms2ns(wcet_ms);
218 period = ms2ns(period_ms);
219 budget = ms2ns(budget_ms);
220 if (wcet <= 0)
221 usage("The worst-case execution time must be a "
222 "positive number.");
223 if (period <= 0)
224 usage("The period must be a positive number.");
225 if (wcet > period) {
226 usage("The worst-case execution time must not "
227 "exceed the period.");
228 }
229 if (wss == 0) {
230 usage("You need to specify a WSS (-k option).");
231 }
232
233 duration = atof(argv[optind + 2]);
234
235 if (migrate) {
236 ret = be_migrate_to_domain(cluster);
237 if (ret < 0)
238 bail_out("could not migrate to target partition or cluster.");
239 }
240
241 /* reservation config */
242 config.id = gettid();
243 config.polling_params.budget = budget;
244 config.polling_params.period = period;
245 config.polling_params.offset = 0;
246 config.polling_params.relative_deadline = 0;
247
248 if (config.polling_params.budget > config.polling_params.period) {
249 usage("The budget must not exceed the period.");
250 }
251
252 /* create a reservation */
253 for(i = 0; i < 32; i++){
254 if ( !( (1 << i) & mode_mask) )
255 continue;
256 config.mode = i;
257 ret = reservation_create(res_type, &config);
258 if (ret < 0) {
259 bail_out("failed to create reservation.");
260 }
261 }
262
263 init_rt_task_param(&param);
264 param.exec_cost = wcet;
265 param.period = period;
266 param.priority = priority;
267 param.cls = RT_CLASS_HARD;
268 param.release_policy = TASK_PERIODIC;
269 param.budget_policy = NO_ENFORCEMENT;
270 if (migrate) {
271 param.cpu = gettid();
272 //param.cpu = config.cpu;
273 }
274 ret = set_rt_task_param(gettid(), &param);
275 if (ret < 0)
276 bail_out("could not setup rt task params");
277
278 mc2_param.res_id = gettid();
279 mc2_param.mode_mask = mode_mask;
280 ret = set_mc2_task_param(gettid(), &mc2_param);
281 if (ret < 0)
282 bail_out("could not setup mc2 task params");
283
284 arena_sz = wss*1024;
285 arena = alloc_arena(arena_sz, 0, 0);
286 init_arena(arena, arena_sz);
287
288 mlockall(MCL_CURRENT | MCL_FUTURE);
289
290 ret = init_litmus();
291 if (ret != 0)
292 bail_out("init_litmus() failed\n");
293
294 start = wctime();
295 ret = task_mode(LITMUS_RT_TASK);
296 if (ret != 0)
297 bail_out("could not become RT task");
298
299 if (mc2_param.crit == CRIT_LEVEL_C)
300 set_page_color(-1);
301 else
302 set_page_color(config.cpu);
303
304 mlockall(MCL_CURRENT | MCL_FUTURE);
305
306 if (wait) {
307 ret = wait_for_ts_release();
308 if (ret != 0)
309 bail_out("wait_for_ts_release()");
310 start = wctime();
311 }
312
313 while (job(wss, wcet_ms * 0.001, start + duration)) {};
314
315//set_page_color(config.cpu);
316 //test_call(0);
317 ret = task_mode(BACKGROUND_TASK);
318 if (ret != 0)
319 bail_out("could not become regular task (huh?)");
320
321 reservation_destroy(gettid(), config.cpu);
322 dealloc_arena(arena, arena_sz);
323 printf("%s finished.\n", argv[0]);
324 //test_call(1);
325 return 0;
326}