diff options
Diffstat (limited to 'bin/mc2bench.c')
-rw-r--r-- | bin/mc2bench.c | 503 |
1 files changed, 0 insertions, 503 deletions
diff --git a/bin/mc2bench.c b/bin/mc2bench.c deleted file mode 100644 index dfb4f15..0000000 --- a/bin/mc2bench.c +++ /dev/null | |||
@@ -1,503 +0,0 @@ | |||
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 | |||
13 | #include "litmus.h" | ||
14 | #include "common.h" | ||
15 | #include "color_shm.h" | ||
16 | |||
17 | #define PAGE_SIZE (4096) | ||
18 | //#define CACHELINE_SIZE 32 | ||
19 | //#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int)) | ||
20 | //#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t)) | ||
21 | #define INTS_IN_1KB (1024 / sizeof(int)) | ||
22 | |||
23 | //typedef struct cacheline | ||
24 | //{ | ||
25 | // int line[INTS_IN_CACHELINE]; | ||
26 | //} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t; | ||
27 | |||
28 | static int loops = 100000; | ||
29 | static cacheline_t* arena = NULL; | ||
30 | static cacheline_t* local_buf = NULL; | ||
31 | |||
32 | struct timeval t1,t2; | ||
33 | |||
34 | lt_t exectime[100000]; | ||
35 | |||
36 | inline unsigned long get_cyclecount (void) | ||
37 | { | ||
38 | unsigned long value; | ||
39 | // Read CCNT Register | ||
40 | asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value)); | ||
41 | return value; | ||
42 | } | ||
43 | |||
44 | #define UNCACHE_DEV "/dev/litmus/uncache" | ||
45 | |||
46 | static cacheline_t* alloc_shm(int cs, size_t size, int use_huge_pages, int use_uncache_pages) | ||
47 | { | ||
48 | struct color_ioctl_cmd shm_info; | ||
49 | struct color_ioctl_offset shm_offset; | ||
50 | cacheline_t* arena = NULL; | ||
51 | |||
52 | |||
53 | shm_info.color = 0x0000ffff; | ||
54 | |||
55 | if (cs == 1 || cs == 2) | ||
56 | shm_info.bank = 0x00000020; // hi crit. bank | ||
57 | else if (cs == 3) | ||
58 | shm_info.bank = 0x00000040; // levelC | ||
59 | |||
60 | shm_offset.offset = 0; | ||
61 | shm_offset.lock = 1; | ||
62 | |||
63 | arena = color_mmap(size, shm_info, shm_offset); | ||
64 | if (arena == MAP_FAILED) { | ||
65 | printf("mmap failed.\n"); | ||
66 | return NULL; | ||
67 | } | ||
68 | |||
69 | mlockall(MCL_CURRENT | MCL_FUTURE); | ||
70 | /* finish allocation */ | ||
71 | |||
72 | assert(arena); | ||
73 | |||
74 | return arena; | ||
75 | } | ||
76 | |||
77 | static cacheline_t* alloc_local(size_t size, int use_huge_pages, int use_uncache_pages) | ||
78 | { | ||
79 | int flags = MAP_PRIVATE | MAP_POPULATE; | ||
80 | cacheline_t* arena = NULL; | ||
81 | int fd; | ||
82 | |||
83 | if(use_huge_pages) | ||
84 | flags |= MAP_HUGETLB; | ||
85 | |||
86 | if(use_uncache_pages) { | ||
87 | fd = open(UNCACHE_DEV, O_RDWR|O_SYNC); | ||
88 | if (fd == -1) | ||
89 | bail_out("Failed to open uncache device. Are you running the LITMUS^RT kernel?"); | ||
90 | } | ||
91 | else { | ||
92 | fd = -1; | ||
93 | flags |= MAP_ANONYMOUS; | ||
94 | } | ||
95 | |||
96 | arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0); | ||
97 | |||
98 | if(use_uncache_pages) | ||
99 | close(fd); | ||
100 | |||
101 | assert(arena); | ||
102 | |||
103 | return arena; | ||
104 | } | ||
105 | |||
106 | static void dealloc_arena(cacheline_t* arena, size_t size) | ||
107 | { | ||
108 | int ret = munmap((void*)arena, size); | ||
109 | if(ret != 0) | ||
110 | bail_out("munmap() error"); | ||
111 | } | ||
112 | |||
113 | static int randrange(int min, int max) | ||
114 | { | ||
115 | /* generate a random number on the range [min, max) w/o skew */ | ||
116 | int limit = max - min; | ||
117 | int devisor = RAND_MAX/limit; | ||
118 | int retval; | ||
119 | |||
120 | do { | ||
121 | retval = rand() / devisor; | ||
122 | } while(retval == limit); | ||
123 | retval += min; | ||
124 | |||
125 | return retval; | ||
126 | } | ||
127 | |||
128 | static void init_arena(cacheline_t* arena, size_t size) | ||
129 | { | ||
130 | int i; | ||
131 | size_t num_arena_elem = size / sizeof(cacheline_t); | ||
132 | |||
133 | /* Generate a cycle among the cache lines using Sattolo's algorithm. | ||
134 | Every int in the cache line points to the same cache line. | ||
135 | Note: Sequential walk doesn't care about these values. */ | ||
136 | for (i = 0; i < num_arena_elem; i++) { | ||
137 | int j; | ||
138 | for(j = 0; j < INTS_IN_CACHELINE; ++j) | ||
139 | arena[i].line[j] = i; | ||
140 | } | ||
141 | while(1 < i--) { | ||
142 | int j = randrange(0, i); | ||
143 | cacheline_t temp = arena[j]; | ||
144 | arena[j] = arena[i]; | ||
145 | arena[i] = temp; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | /* Random walk around the arena in cacheline-sized chunks. | ||
150 | Cacheline-sized chucks ensures the same utilization of each | ||
151 | hit line as sequential read. (Otherwise, our utilization | ||
152 | would only be 1/INTS_IN_CACHELINE.) */ | ||
153 | static int random_walk(cacheline_t *mem, int wss, int write_cycle) | ||
154 | { | ||
155 | /* a random cycle among the cache lines was set up by init_arena(). */ | ||
156 | int sum, i, next, j; | ||
157 | |||
158 | int numlines = wss * CACHELINES_IN_1KB; | ||
159 | |||
160 | sum = 0; | ||
161 | |||
162 | /* contents of arena is structured s.t. offsets are all | ||
163 | w.r.t. to start of arena, so compute the initial offset */ | ||
164 | next = mem - arena; | ||
165 | |||
166 | if (write_cycle == 0) { | ||
167 | for (i = 0; i < numlines; i++) { | ||
168 | for (j = 0; j < INTS_IN_CACHELINE; j++) { | ||
169 | /* every element in the cacheline has the same value */ | ||
170 | //next = arena[next].line[j]; | ||
171 | local_buf[next].line[j] = arena[next].line[j]; | ||
172 | //sum += next; | ||
173 | //local_buf[next].line[j] = next; | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | |||
178 | else { | ||
179 | int w, which_line; | ||
180 | for (i = 0, w = 0; i < numlines; i++) { | ||
181 | for (j = 0; j < INTS_IN_CACHELINE; j++) { | ||
182 | which_line = next; | ||
183 | next = local_buf[next].line[j]; | ||
184 | ((volatile cacheline_t*)arena)[which_line].line[j] = next; | ||
185 | //sum += next; | ||
186 | } | ||
187 | } | ||
188 | } | ||
189 | return sum; | ||
190 | } | ||
191 | |||
192 | static cacheline_t* random_start(int wss) | ||
193 | { | ||
194 | return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t))); | ||
195 | } | ||
196 | |||
197 | static int sequential_walk(cacheline_t *mem, int wss, int write_cycle) | ||
198 | { | ||
199 | int sum = 0, i, j; | ||
200 | //int* mem = (int*)_mem; /* treat as raw buffer of ints */ | ||
201 | int num_ints = wss * CACHELINES_IN_1KB; | ||
202 | |||
203 | if (write_cycle > 0) { | ||
204 | for (i = 0; i < num_ints; i++) { | ||
205 | //if (i % write_cycle == (write_cycle - 1)) { | ||
206 | //mem[i]++; | ||
207 | for (j = 0; j < INTS_IN_CACHELINE; j++) { | ||
208 | //sum += local_buf[i].line[j]; | ||
209 | mem[i].line[j] = local_buf[i].line[j];; | ||
210 | } | ||
211 | //} | ||
212 | //else { | ||
213 | // sum += mem[i]; | ||
214 | //} | ||
215 | } | ||
216 | } else { | ||
217 | /* sequential access, pure read */ | ||
218 | for (i = 0; i < num_ints; i++) { | ||
219 | for (j = 0; j < INTS_IN_CACHELINE; j++) { | ||
220 | //sum += mem[i]; | ||
221 | local_buf[i].line[j] = mem[i].line[j]; | ||
222 | //sum += mem[i]; | ||
223 | } | ||
224 | } | ||
225 | } | ||
226 | return sum; | ||
227 | } | ||
228 | |||
229 | static cacheline_t* sequential_start(int wss) | ||
230 | { | ||
231 | return arena; | ||
232 | /* static int pos = 0; | ||
233 | |||
234 | int num_cachelines = wss * CACHELINES_IN_1KB; | ||
235 | size_t num_arena_elem = wss * 1024 / sizeof(cacheline_t); | ||
236 | cacheline_t *mem; | ||
237 | */ | ||
238 | |||
239 | /* Don't allow re-use between allocations. | ||
240 | * At most half of the arena may be used | ||
241 | * at any one time. | ||
242 | */ | ||
243 | /* if (num_cachelines * 2 > num_arena_elem) | ||
244 | bail_out("static memory arena too small"); | ||
245 | |||
246 | if (pos + num_cachelines > num_arena_elem) { | ||
247 | mem = arena; | ||
248 | pos = num_cachelines; | ||
249 | } else { | ||
250 | mem = arena + pos; | ||
251 | pos += num_cachelines; | ||
252 | } | ||
253 | |||
254 | return mem;*/ | ||
255 | } | ||
256 | |||
257 | static volatile int dont_optimize_me = 0; | ||
258 | |||
259 | static void usage(char *error) { | ||
260 | fprintf(stderr, "Error: %s\n", error); | ||
261 | fprintf(stderr, | ||
262 | "Usage:\n" | ||
263 | " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n" | ||
264 | " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n" | ||
265 | " rt_spin -l\n" | ||
266 | "\n" | ||
267 | "COMMON-OPTS = [-w] [-s SCALE]\n" | ||
268 | " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n" | ||
269 | " [-k WSS] [-l LOOPS] [-b BUDGET]\n" | ||
270 | "\n" | ||
271 | "WCET and PERIOD are milliseconds, DURATION is seconds.\n"); | ||
272 | exit(EXIT_FAILURE); | ||
273 | } | ||
274 | |||
275 | static int loop_once(int cs, int wss, unsigned int iter) | ||
276 | { | ||
277 | //cacheline_t *mem; | ||
278 | //int temp; | ||
279 | |||
280 | //mem = random_start(wss); | ||
281 | //temp = random_walk(mem, wss, 1); | ||
282 | |||
283 | //mem = sequential_start(wss); | ||
284 | //temp = sequential_walk(arena, wss, 1); | ||
285 | run_bench(cs, wss, arena, local_buf, &exectime[iter]); | ||
286 | dont_optimize_me = (int)exectime[iter]; | ||
287 | |||
288 | return dont_optimize_me; | ||
289 | } | ||
290 | |||
291 | static int job(int cs, int wss, double exec_time, double program_end) | ||
292 | { | ||
293 | if (wctime() > program_end) | ||
294 | return 0; | ||
295 | else { | ||
296 | register unsigned long t; | ||
297 | register unsigned int iter = 0; | ||
298 | //t = get_cyclecount(); | ||
299 | //gettimeofday(&t1, NULL); | ||
300 | while(iter < loops) { | ||
301 | loop_once(cs, wss, iter++); | ||
302 | } | ||
303 | //gettimeofday(&t2, NULL); | ||
304 | //printf("%ld cycles\n", get_cyclecount() - t); | ||
305 | //printf("%ld\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec))); | ||
306 | sleep_next_period(); | ||
307 | return 1; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | #define OPTSTR "p:wl:m:i:b:k:c:" | ||
312 | int main(int argc, char** argv) | ||
313 | { | ||
314 | int ret, i; | ||
315 | lt_t wcet, period, budget; | ||
316 | double wcet_ms, period_ms, budget_ms; | ||
317 | unsigned int priority = LITMUS_NO_PRIORITY; | ||
318 | int migrate = 0; | ||
319 | int cluster = 0; | ||
320 | int opt; | ||
321 | int wait = 0; | ||
322 | double duration = 0, start = 0; | ||
323 | struct rt_task param; | ||
324 | struct mc2_task mc2_param; | ||
325 | struct reservation_config config; | ||
326 | int res_type = PERIODIC_POLLING; | ||
327 | size_t arena_sz; | ||
328 | int wss, cs; | ||
329 | |||
330 | /* default for reservation */ | ||
331 | config.id = 0; | ||
332 | config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */ | ||
333 | config.cpu = -1; | ||
334 | |||
335 | mc2_param.crit = CRIT_LEVEL_C; | ||
336 | |||
337 | budget_ms = 1000; | ||
338 | |||
339 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | ||
340 | switch (opt) { | ||
341 | case 'w': | ||
342 | wait = 1; | ||
343 | break; | ||
344 | case 'p': | ||
345 | cluster = atoi(optarg); | ||
346 | migrate = 1; | ||
347 | config.cpu = cluster; | ||
348 | break; | ||
349 | case 'l': | ||
350 | loops = atoi(optarg); | ||
351 | break; | ||
352 | case 'k': | ||
353 | wss = atoi(optarg); | ||
354 | break; | ||
355 | case 'm': | ||
356 | mc2_param.crit = atoi(optarg); | ||
357 | if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) { | ||
358 | res_type = PERIODIC_POLLING; | ||
359 | } | ||
360 | else | ||
361 | usage("Invalid criticality level."); | ||
362 | break; | ||
363 | case 'b': | ||
364 | budget_ms = atof(optarg); | ||
365 | break; | ||
366 | case 'i': | ||
367 | config.priority = atoi(optarg); | ||
368 | break; | ||
369 | case 'c': | ||
370 | cs = atoi(optarg); | ||
371 | break; | ||
372 | case ':': | ||
373 | usage("Argument missing."); | ||
374 | break; | ||
375 | case '?': | ||
376 | default: | ||
377 | usage("Bad argument."); | ||
378 | break; | ||
379 | } | ||
380 | } | ||
381 | srand(getpid()); | ||
382 | |||
383 | /* | ||
384 | * We need three parameters | ||
385 | */ | ||
386 | if (argc - optind < 3) | ||
387 | usage("Arguments missing."); | ||
388 | |||
389 | wcet_ms = atof(argv[optind + 0]); | ||
390 | period_ms = atof(argv[optind + 1]); | ||
391 | |||
392 | wcet = ms2ns(wcet_ms); | ||
393 | period = ms2ns(period_ms); | ||
394 | budget = ms2ns(budget_ms); | ||
395 | if (wcet <= 0) | ||
396 | usage("The worst-case execution time must be a " | ||
397 | "positive number."); | ||
398 | if (period <= 0) | ||
399 | usage("The period must be a positive number."); | ||
400 | if (wcet > period) { | ||
401 | usage("The worst-case execution time must not " | ||
402 | "exceed the period."); | ||
403 | } | ||
404 | |||
405 | duration = atof(argv[optind + 2]); | ||
406 | |||
407 | if (migrate) { | ||
408 | ret = be_migrate_to_domain(cluster); | ||
409 | if (ret < 0) | ||
410 | bail_out("could not migrate to target partition or cluster."); | ||
411 | } | ||
412 | |||
413 | /* reservation config */ | ||
414 | config.id = gettid(); | ||
415 | config.polling_params.budget = budget; | ||
416 | config.polling_params.period = period; | ||
417 | config.polling_params.offset = 0; | ||
418 | config.polling_params.relative_deadline = 0; | ||
419 | |||
420 | if (config.polling_params.budget > config.polling_params.period) { | ||
421 | usage("The budget must not exceed the period."); | ||
422 | } | ||
423 | |||
424 | /* create a reservation */ | ||
425 | ret = reservation_create(res_type, &config); | ||
426 | if (ret < 0) { | ||
427 | bail_out("failed to create reservation."); | ||
428 | } | ||
429 | |||
430 | init_rt_task_param(¶m); | ||
431 | param.exec_cost = wcet; | ||
432 | param.period = period; | ||
433 | param.priority = priority; | ||
434 | param.cls = RT_CLASS_HARD; | ||
435 | param.release_policy = TASK_PERIODIC; | ||
436 | param.budget_policy = NO_ENFORCEMENT; | ||
437 | if (migrate) { | ||
438 | param.cpu = gettid(); | ||
439 | } | ||
440 | ret = set_rt_task_param(gettid(), ¶m); | ||
441 | if (ret < 0) | ||
442 | bail_out("could not setup rt task params"); | ||
443 | |||
444 | mc2_param.res_id = gettid(); | ||
445 | ret = set_mc2_task_param(gettid(), &mc2_param); | ||
446 | if (ret < 0) | ||
447 | bail_out("could not setup mc2 task params"); | ||
448 | |||
449 | |||
450 | arena_sz = wss*1024; | ||
451 | |||
452 | arena = alloc_shm(cs, arena_sz, 0, 0); | ||
453 | if (!arena) | ||
454 | bail_out("alloc_shm failed.\n"); | ||
455 | init_arena(arena, arena_sz); | ||
456 | |||
457 | local_buf = alloc_local(arena_sz, 0, 0); | ||
458 | if (!local_buf) | ||
459 | bail_out("alloc_local failed.\n"); | ||
460 | init_arena(local_buf, arena_sz); | ||
461 | |||
462 | ret = init_litmus(); | ||
463 | if (ret != 0) | ||
464 | bail_out("init_litmus() failed\n"); | ||
465 | |||
466 | start = wctime(); | ||
467 | ret = task_mode(LITMUS_RT_TASK); | ||
468 | if (ret != 0) | ||
469 | bail_out("could not become RT task"); | ||
470 | |||
471 | if (mc2_param.crit == CRIT_LEVEL_C) | ||
472 | set_page_color(-1); | ||
473 | else | ||
474 | set_page_color(config.cpu); | ||
475 | |||
476 | mlockall(MCL_CURRENT | MCL_FUTURE); | ||
477 | // init_arena(local_buf, arena_sz); | ||
478 | // test_call(1); | ||
479 | // init_arena(arena, arena_sz); | ||
480 | // test_call(2); | ||
481 | |||
482 | if (wait) { | ||
483 | ret = wait_for_ts_release(); | ||
484 | if (ret != 0) | ||
485 | bail_out("wait_for_ts_release()"); | ||
486 | start = wctime(); | ||
487 | } | ||
488 | |||
489 | //while (job(wss, wcet_ms * 0.001, start + duration)) {}; | ||
490 | job(cs, wss, wcet_ms * 0.001, start + duration); | ||
491 | |||
492 | ret = task_mode(BACKGROUND_TASK); | ||
493 | if (ret != 0) | ||
494 | bail_out("could not become regular task (huh?)"); | ||
495 | |||
496 | reservation_destroy(gettid(), config.cpu); | ||
497 | dealloc_arena(arena, arena_sz); | ||
498 | dealloc_arena(local_buf, arena_sz); | ||
499 | printf("%s finished.\n", argv[0]); | ||
500 | for (i = 0; i<loops; i++) | ||
501 | printf("%llu\n", exectime[i]); | ||
502 | return 0; | ||
503 | } | ||