aboutsummaryrefslogtreecommitdiffstats
path: root/bin/mc2bench.c
diff options
context:
space:
mode:
authorNamhoon Kim <namhoonk@cs.unc.edu>2017-05-01 16:02:05 -0400
committerNamhoon Kim <namhoonk@cs.unc.edu>2017-05-01 16:02:05 -0400
commit11765fcf37057053065abd3715cf9cb46f2fa4db (patch)
tree8403d716bbcbd96493c481a82e7e02b5da9231e8 /bin/mc2bench.c
parentbfee87a910560e022b04c81a026b1f88522cd62f (diff)
RTSS17 submitwip-modechange
Diffstat (limited to 'bin/mc2bench.c')
-rw-r--r--bin/mc2bench.c503
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
28static int loops = 100000;
29static cacheline_t* arena = NULL;
30static cacheline_t* local_buf = NULL;
31
32struct timeval t1,t2;
33
34lt_t exectime[100000];
35
36inline 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
46static 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
77static 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
106static 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
113static 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
128static 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.) */
153static 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
192static cacheline_t* random_start(int wss)
193{
194 return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
195}
196
197static 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
229static 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
257static volatile int dont_optimize_me = 0;
258
259static 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
275static 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
291static 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:"
312int 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(&param);
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(), &param);
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}