Attachment 'MC2-liblitmus-rtss16.patch'
Download 1 diff --git .gitignore .gitignore
2 index a52500b..ec913c5 100644
3 --- .gitignore
4 +++ .gitignore
5 @@ -3,10 +3,13 @@
6 *.a
7
8
9 +# editor backup files
10 +*~
11
12 # generated files
13 tests/test_catalog.inc
14 *.d
15 +*.d.*
16 docs/
17
18 # executables
19 @@ -23,6 +26,13 @@ showst
20 rtspin
21 cycles
22 measure_syscall
23 +uncache
24 +resctrl
25 +mc2pollute
26 +mc2spin
27 +mc2syn
28 +memthrash
29 +mttest
30
31 # build system files
32 .config
33 @@ -32,3 +42,5 @@ test_catalog.inc
34 # files copied in from the kernel tree
35 include/litmus
36 arch/*/include/asm
37 +arch/x86/include/generated
38 +arch/x86/include/uapi
39 diff --git Makefile Makefile
40 index 4742fd2..6e9723d 100644
41 --- Makefile
42 +++ Makefile
43 @@ -19,8 +19,8 @@ LITMUS_KERNEL ?= ../litmus-rt
44 # Internal configuration.
45
46 # compiler flags
47 -flags-debug = -O2 -Wall -Werror -g -Wdeclaration-after-statement
48 -flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
49 +flags-debug = -O0 -Wall -g -Wdeclaration-after-statement
50 +flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE -DCONFIG_PGMRT_SUPPORT
51
52 # architecture-specific flags
53 flags-i386 = -m32
54 @@ -73,7 +73,8 @@ AR := ${CROSS_COMPILE}${AR}
55
56 all = lib ${rt-apps}
57 rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
58 - base_mt_task uncache runtests
59 + base_mt_task uncache runtests resctrl mc2spin \
60 + mc2thrash mc2thrash1 mc2thrash2 mc2thrash3 mc2bench
61
62 .PHONY: all lib clean dump-config TAGS tags cscope help doc
63
64 @@ -168,7 +169,8 @@ litmus-headers = \
65 include/litmus/rt_param.h \
66 include/litmus/fpmath.h \
67 include/litmus/unistd_32.h \
68 - include/litmus/unistd_64.h
69 + include/litmus/unistd_64.h \
70 + include/litmus/mc2_common.h
71
72 unistd-headers = \
73 $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/$(file))
74 @@ -234,6 +236,34 @@ obj-release_ts = release_ts.o
75 obj-measure_syscall = null_call.o
76 lib-measure_syscall = -lm
77
78 +obj-resctrl = resctrl.o
79 +
80 +obj-mc2spin = mc2spin.o common.o
81 +lib-mc2spin = -lrt -static
82 +
83 +obj-mc2pollute = mc2pollute.o common.o
84 +lib-mc2pollute = -lrt -static
85 +
86 +obj-mc2syn = mc2syn.o common.o
87 +lib-mc2syn = -lrt -static
88 +
89 +obj-memthrash = memthrash.o
90 +lib-memthrash = -lrt
91 +
92 +obj-mc2thrash = mc2thrash.o common.o
93 +lib-mc2thrash = -lrt -static
94 +
95 +obj-mc2thrash1 = mc2thrash.o common.o
96 +lib-mc2thrash1 = -lrt -static
97 +
98 +obj-mc2thrash2 = mc2thrash.o common.o
99 +lib-mc2thrash2 = -lrt -static
100 +
101 +obj-mc2thrash3 = mc2thrash.o common.o
102 +lib-mc2thrash3 = -lrt -static
103 +
104 +obj-mc2bench = mc2bench.o common.o
105 +lib-mc2bench = -lrt -static
106 # ##############################################################################
107 # Build everything that depends on liblitmus.
108
109 diff --git bin/base_mt_task.c bin/base_mt_task.c
110 index aec79a4..1665203 100644
111 --- bin/base_mt_task.c
112 +++ bin/base_mt_task.c
113 @@ -29,11 +29,13 @@
114 /* Let's create 10 threads in the example,
115 * for a total utilization of 1.
116 */
117 -#define NUM_THREADS 10
118 +#define NUM_THREADS 3
119
120 /* The information passed to each thread. Could be anything. */
121 struct thread_context {
122 int id;
123 + int cpu;
124 + int job_no;
125 };
126
127 /* The real-time thread program. Doesn't have to be the same for
128 @@ -45,7 +47,7 @@ void* rt_thread(void *tcontext);
129 * Returns 1 -> task should exit.
130 * 0 -> task should continue.
131 */
132 -int job(void);
133 +int job(struct thread_context *tcx);
134
135
136 /* Catch errors.
137 @@ -97,6 +99,8 @@ int main(int argc, char** argv)
138 */
139 for (i = 0; i < NUM_THREADS; i++) {
140 ctx[i].id = i;
141 + ctx[i].cpu = 0;
142 + ctx[i].job_no = 0;
143 pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
144 }
145
146 @@ -125,6 +129,7 @@ void* rt_thread(void *tcontext)
147 int do_exit;
148 struct thread_context *ctx = (struct thread_context *) tcontext;
149 struct rt_task param;
150 + int ret;
151
152 /* Set up task parameters */
153 init_rt_task_param(¶m);
154 @@ -157,6 +162,12 @@ void* rt_thread(void *tcontext)
155 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
156 * set_rt_task_param().
157 */
158 + param.cpu = ctx->cpu;
159 + ret = be_migrate_to_cpu(ctx->cpu);
160 + if (ret < 0) {
161 + printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
162 + return NULL;
163 + }
164 CALL( set_rt_task_param(gettid(), ¶m) );
165
166 /*****
167 @@ -176,7 +187,7 @@ void* rt_thread(void *tcontext)
168 /* Wait until the next job is released. */
169 sleep_next_period();
170 /* Invoke job. */
171 - do_exit = job();
172 + do_exit = job(ctx);
173 } while (!do_exit);
174
175
176 @@ -192,10 +203,13 @@ void* rt_thread(void *tcontext)
177
178
179
180 -int job(void)
181 +int job(struct thread_context *tcx)
182 {
183 /* Do real-time calculation. */
184 -
185 + printf("Job executinig\n");
186 + tcx->job_no++;
187 + if (tcx->job_no == 5)
188 + return 1;
189 /* Don't exit. */
190 return 0;
191 }
192 diff --git bin/mc2bench.c bin/mc2bench.c
193 new file mode 100644
194 index 0000000..ea555b5
195 --- /dev/null
196 +++ bin/mc2bench.c
197 @@ -0,0 +1,363 @@
198 +#include <sys/time.h>
199 +#include <sys/mman.h>
200 +
201 +#include <stdio.h>
202 +#include <stdlib.h>
203 +#include <unistd.h>
204 +#include <time.h>
205 +#include <string.h>
206 +#include <assert.h>
207 +#include <limits.h>
208 +#include <fcntl.h>
209 +
210 +#include "litmus.h"
211 +#include "common.h"
212 +#include "color_shm.h"
213 +
214 +#define PAGE_SIZE (4096)
215 +#define INTS_IN_1KB (1024 / sizeof(int))
216 +
217 +static int loops = 100000;
218 +static cacheline_t* arena = NULL;
219 +static cacheline_t* local_buf = NULL;
220 +
221 +struct timeval t1,t2;
222 +
223 +lt_t exectime[100000];
224 +
225 +#define UNCACHE_DEV "/dev/litmus/uncache"
226 +
227 +static cacheline_t* alloc_shm(int cs, size_t size, int use_huge_pages, int use_uncache_pages)
228 +{
229 + struct color_ioctl_cmd shm_info;
230 + struct color_ioctl_offset shm_offset;
231 + cacheline_t* arena = NULL;
232 +
233 +
234 + shm_info.color = 0x0000ffff;
235 +
236 + /* Shared memory bank allocation
237 + * Change values according to /proc/sys/litmus/C[core#]_L[crit. lv]_bank
238 + */
239 + if (cs == 1 || cs == 2)
240 + shm_info.bank = 0x00000020; // hi crit. bank
241 + else if (cs == 3)
242 + shm_info.bank = 0x00000040; // levelC
243 +
244 + shm_offset.offset = 0;
245 + shm_offset.lock = 1;
246 +
247 + arena = color_mmap(size, shm_info, shm_offset);
248 + if (arena == MAP_FAILED) {
249 + printf("mmap failed.\n");
250 + return NULL;
251 + }
252 +
253 + mlockall(MCL_CURRENT | MCL_FUTURE);
254 + /* finish allocation */
255 +
256 + assert(arena);
257 +
258 + return arena;
259 +}
260 +
261 +static cacheline_t* alloc_local(size_t size, int use_huge_pages, int use_uncache_pages)
262 +{
263 + int flags = MAP_PRIVATE | MAP_POPULATE;
264 + cacheline_t* arena = NULL;
265 + int fd;
266 +
267 + if(use_huge_pages)
268 + flags |= MAP_HUGETLB;
269 +
270 + if(use_uncache_pages) {
271 + fd = open(UNCACHE_DEV, O_RDWR|O_SYNC);
272 + if (fd == -1)
273 + bail_out("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
274 + }
275 + else {
276 + fd = -1;
277 + flags |= MAP_ANONYMOUS;
278 + }
279 +
280 + arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
281 +
282 + if(use_uncache_pages)
283 + close(fd);
284 +
285 + assert(arena);
286 +
287 + return arena;
288 +}
289 +
290 +static void dealloc_arena(cacheline_t* arena, size_t size)
291 +{
292 + int ret = munmap((void*)arena, size);
293 + if(ret != 0)
294 + bail_out("munmap() error");
295 +}
296 +
297 +static int randrange(int min, int max)
298 +{
299 + /* generate a random number on the range [min, max) w/o skew */
300 + int limit = max - min;
301 + int devisor = RAND_MAX/limit;
302 + int retval;
303 +
304 + do {
305 + retval = rand() / devisor;
306 + } while(retval == limit);
307 + retval += min;
308 +
309 + return retval;
310 +}
311 +
312 +static void init_arena(cacheline_t* arena, size_t size)
313 +{
314 + int i;
315 + size_t num_arena_elem = size / sizeof(cacheline_t);
316 +
317 + /* Generate a cycle among the cache lines using Sattolo's algorithm.
318 + Every int in the cache line points to the same cache line.
319 + Note: Sequential walk doesn't care about these values. */
320 + for (i = 0; i < num_arena_elem; i++) {
321 + int j;
322 + for(j = 0; j < INTS_IN_CACHELINE; ++j)
323 + arena[i].line[j] = i;
324 + }
325 + while(1 < i--) {
326 + int j = randrange(0, i);
327 + cacheline_t temp = arena[j];
328 + arena[j] = arena[i];
329 + arena[i] = temp;
330 + }
331 +}
332 +
333 +static volatile int dont_optimize_me = 0;
334 +
335 +static void usage(char *error) {
336 + fprintf(stderr, "Error: %s\n", error);
337 + fprintf(stderr,
338 + "Usage:\n"
339 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
340 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
341 + " rt_spin -l\n"
342 + "\n"
343 + "COMMON-OPTS = [-w] [-s SCALE]\n"
344 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
345 + " [-k WSS] [-l LOOPS] [-b BUDGET]\n"
346 + "\n"
347 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
348 + exit(EXIT_FAILURE);
349 +}
350 +
351 +static int loop_once(int cs, int wss, unsigned int iter)
352 +{
353 + run_bench(cs, wss, arena, local_buf, &exectime[iter]);
354 + dont_optimize_me = (int)exectime[iter];
355 +
356 + return dont_optimize_me;
357 +}
358 +
359 +static int job(int cs, int wss, double exec_time, double program_end)
360 +{
361 + if (wctime() > program_end)
362 + return 0;
363 + else {
364 + register unsigned int iter = 0;
365 + while(iter < loops) {
366 + loop_once(cs, wss, iter++);
367 + }
368 + sleep_next_period();
369 + return 1;
370 + }
371 +}
372 +
373 +#define OPTSTR "p:wl:m:i:b:k:c:"
374 +int main(int argc, char** argv)
375 +{
376 + int ret, i;
377 + lt_t wcet, period, budget;
378 + double wcet_ms, period_ms, budget_ms;
379 + unsigned int priority = LITMUS_NO_PRIORITY;
380 + int migrate = 0;
381 + int cluster = 0;
382 + int opt;
383 + int wait = 0;
384 + double duration = 0, start = 0;
385 + struct rt_task param;
386 + struct mc2_task mc2_param;
387 + struct reservation_config config;
388 + int res_type = PERIODIC_POLLING;
389 + size_t arena_sz;
390 + int wss, cs;
391 +
392 + /* default for reservation */
393 + config.id = 0;
394 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
395 + config.cpu = -1;
396 +
397 + mc2_param.crit = CRIT_LEVEL_C;
398 +
399 + budget_ms = 1000;
400 +
401 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
402 + switch (opt) {
403 + case 'w':
404 + wait = 1;
405 + break;
406 + case 'p':
407 + cluster = atoi(optarg);
408 + migrate = 1;
409 + config.cpu = cluster;
410 + break;
411 + case 'l':
412 + loops = atoi(optarg);
413 + break;
414 + case 'k':
415 + wss = atoi(optarg);
416 + break;
417 + case 'm':
418 + mc2_param.crit = atoi(optarg);
419 + if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
420 + res_type = PERIODIC_POLLING;
421 + }
422 + else
423 + usage("Invalid criticality level.");
424 + break;
425 + case 'b':
426 + budget_ms = atof(optarg);
427 + break;
428 + case 'i':
429 + config.priority = atoi(optarg);
430 + break;
431 + case 'c':
432 + cs = atoi(optarg);
433 + break;
434 + case ':':
435 + usage("Argument missing.");
436 + break;
437 + case '?':
438 + default:
439 + usage("Bad argument.");
440 + break;
441 + }
442 + }
443 + srand(getpid());
444 +
445 + /*
446 + * We need three parameters
447 + */
448 + if (argc - optind < 3)
449 + usage("Arguments missing.");
450 +
451 + wcet_ms = atof(argv[optind + 0]);
452 + period_ms = atof(argv[optind + 1]);
453 +
454 + wcet = ms2ns(wcet_ms);
455 + period = ms2ns(period_ms);
456 + budget = ms2ns(budget_ms);
457 + if (wcet <= 0)
458 + usage("The worst-case execution time must be a "
459 + "positive number.");
460 + if (period <= 0)
461 + usage("The period must be a positive number.");
462 + if (wcet > period) {
463 + usage("The worst-case execution time must not "
464 + "exceed the period.");
465 + }
466 +
467 + duration = atof(argv[optind + 2]);
468 +
469 + if (migrate) {
470 + ret = be_migrate_to_domain(cluster);
471 + if (ret < 0)
472 + bail_out("could not migrate to target partition or cluster.");
473 + }
474 +
475 + /* reservation config */
476 + config.id = gettid();
477 + config.polling_params.budget = budget;
478 + config.polling_params.period = period;
479 + config.polling_params.offset = 0;
480 + config.polling_params.relative_deadline = 0;
481 +
482 + if (config.polling_params.budget > config.polling_params.period) {
483 + usage("The budget must not exceed the period.");
484 + }
485 +
486 + /* create a reservation */
487 + ret = reservation_create(res_type, &config);
488 + if (ret < 0) {
489 + bail_out("failed to create reservation.");
490 + }
491 +
492 + init_rt_task_param(¶m);
493 + param.exec_cost = wcet;
494 + param.period = period;
495 + param.priority = priority;
496 + param.cls = RT_CLASS_HARD;
497 + param.release_policy = TASK_PERIODIC;
498 + param.budget_policy = NO_ENFORCEMENT;
499 + if (migrate) {
500 + param.cpu = gettid();
501 + }
502 + ret = set_rt_task_param(gettid(), ¶m);
503 + if (ret < 0)
504 + bail_out("could not setup rt task params");
505 +
506 + mc2_param.res_id = gettid();
507 + ret = set_mc2_task_param(gettid(), &mc2_param);
508 + if (ret < 0)
509 + bail_out("could not setup mc2 task params");
510 +
511 +
512 + arena_sz = wss*1024;
513 +
514 + arena = alloc_shm(cs, arena_sz, 0, 0);
515 + if (!arena)
516 + bail_out("alloc_shm failed.\n");
517 + init_arena(arena, arena_sz);
518 +
519 + local_buf = alloc_local(arena_sz, 0, 0);
520 + if (!local_buf)
521 + bail_out("alloc_local failed.\n");
522 + init_arena(local_buf, arena_sz);
523 +
524 + ret = init_litmus();
525 + if (ret != 0)
526 + bail_out("init_litmus() failed\n");
527 +
528 + start = wctime();
529 + ret = task_mode(LITMUS_RT_TASK);
530 + if (ret != 0)
531 + bail_out("could not become RT task");
532 +
533 + if (mc2_param.crit == CRIT_LEVEL_C)
534 + set_page_color(-1);
535 + else
536 + set_page_color(config.cpu);
537 +
538 + mlockall(MCL_CURRENT | MCL_FUTURE);
539 +
540 + if (wait) {
541 + ret = wait_for_ts_release();
542 + if (ret != 0)
543 + bail_out("wait_for_ts_release()");
544 + start = wctime();
545 + }
546 +
547 + job(cs, wss, wcet_ms * 0.001, start + duration);
548 +
549 + ret = task_mode(BACKGROUND_TASK);
550 + if (ret != 0)
551 + bail_out("could not become regular task (huh?)");
552 +
553 + reservation_destroy(gettid(), config.cpu);
554 + dealloc_arena(arena, arena_sz);
555 + dealloc_arena(local_buf, arena_sz);
556 + printf("%s finished.\n", argv[0]);
557 + for (i = 0; i<loops; i++)
558 + printf("%llu\n", exectime[i]);
559 + return 0;
560 +}
561 diff --git bin/mc2spin.c bin/mc2spin.c
562 new file mode 100644
563 index 0000000..25b1c58
564 --- /dev/null
565 +++ bin/mc2spin.c
566 @@ -0,0 +1,574 @@
567 +#include <sys/time.h>
568 +#include <sys/mman.h>
569 +
570 +#include <stdio.h>
571 +#include <stdlib.h>
572 +#include <unistd.h>
573 +#include <time.h>
574 +#include <string.h>
575 +#include <assert.h>
576 +#include <limits.h>
577 +
578 +
579 +#include "litmus.h"
580 +#include "common.h"
581 +
582 +#define PAGE_SIZE 4096
583 +#define NUM_ITEMS 8192
584 +
585 +int *pages;
586 +unsigned long *access_order;
587 +
588 +static void usage(char *error) {
589 + fprintf(stderr, "Error: %s\n", error);
590 + fprintf(stderr,
591 + "Usage:\n"
592 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
593 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
594 + " rt_spin -l\n"
595 + "\n"
596 + "COMMON-OPTS = [-w] [-s SCALE]\n"
597 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
598 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
599 + " [-i [start,end]:[start,end]...]\n"
600 + "\n"
601 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
602 + "CRITICAL SECTION LENGTH is in milliseconds.\n");
603 + exit(EXIT_FAILURE);
604 +}
605 +
606 +/*
607 + * returns the character that made processing stop, newline or EOF
608 + */
609 +static int skip_to_next_line(FILE *fstream)
610 +{
611 + int ch;
612 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
613 + return ch;
614 +}
615 +
616 +static void skip_comments(FILE *fstream)
617 +{
618 + int ch;
619 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
620 + skip_to_next_line(fstream);
621 + ungetc(ch, fstream);
622 +}
623 +
624 +static void get_exec_times(const char *file, const int column,
625 + int *num_jobs, double **exec_times)
626 +{
627 + FILE *fstream;
628 + int cur_job, cur_col, ch;
629 + *num_jobs = 0;
630 +
631 + fstream = fopen(file, "r");
632 + if (!fstream)
633 + bail_out("could not open execution time file");
634 +
635 + /* figure out the number of jobs */
636 + do {
637 + skip_comments(fstream);
638 + ch = skip_to_next_line(fstream);
639 + if (ch != EOF)
640 + ++(*num_jobs);
641 + } while (ch != EOF);
642 +
643 + if (-1 == fseek(fstream, 0L, SEEK_SET))
644 + bail_out("rewinding file failed");
645 +
646 + /* allocate space for exec times */
647 + *exec_times = calloc(*num_jobs, sizeof(*exec_times));
648 + if (!*exec_times)
649 + bail_out("couldn't allocate memory");
650 +
651 + for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
652 +
653 + skip_comments(fstream);
654 +
655 + for (cur_col = 1; cur_col < column; ++cur_col) {
656 + /* discard input until we get to the column we want */
657 + int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
658 + }
659 +
660 + /* get the desired exec. time */
661 + if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
662 + fprintf(stderr, "invalid execution time near line %d\n",
663 + cur_job);
664 + exit(EXIT_FAILURE);
665 + }
666 +
667 + skip_to_next_line(fstream);
668 + }
669 +
670 + assert(cur_job == *num_jobs);
671 + fclose(fstream);
672 +}
673 +
674 +#define NUMS 4096
675 +static int num[NUMS];
676 +static char* progname;
677 +
678 +static int randrange(const int max)
679 +{
680 + return (rand() / (RAND_MAX / max + 1));
681 +}
682 +
683 +static void sattolo(unsigned long *items, const unsigned long len)
684 +{
685 + unsigned long i;
686 + /* first set up 0, 1, ..., n - 1 */
687 + for (i = 0; i < len; i++)
688 + items[i] = i;
689 + /* note: i is now n */
690 + while (1 < i--) {
691 + /* 0 <= j < i */
692 + int t, j = randrange(i);
693 + t = items[i];
694 + items[i] = items[j];
695 + items[j] = t;
696 + }
697 +}
698 +
699 +static int loop_once(void)
700 +{
701 + int i, j = 0;
702 + for (i = 0; i < NUMS; i++)
703 + j += num[i]++;
704 + return j;
705 +/*
706 + int i, tmp;
707 + for (i = 0; i < NUM_ITEMS; i++) {
708 + tmp = pages[access_order[i]];
709 + if (access_order[i] % 3 == 0)
710 + pages[access_order[i]] = i+tmp;
711 + }
712 + return 1;
713 +*/
714 +}
715 +
716 +static int loop_for(double exec_time, double emergency_exit)
717 +{
718 + double last_loop = 0, loop_start;
719 + int tmp = 0;
720 +
721 + double start = cputime();
722 + double now = cputime();
723 +
724 + while (now + last_loop < start + exec_time) {
725 + loop_start = now;
726 + tmp += loop_once();
727 + now = cputime();
728 + last_loop = now - loop_start;
729 + if (emergency_exit && wctime() > emergency_exit) {
730 + /* Oops --- this should only be possible if the execution time tracking
731 + * is broken in the LITMUS^RT kernel. */
732 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
733 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
734 + break;
735 + }
736 + }
737 +
738 + return tmp;
739 +}
740 +
741 +
742 +static void debug_delay_loop(int count)
743 +{
744 + double start, end, delay;
745 +
746 + while (count--) {
747 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
748 + start = wctime();
749 + loop_for(delay, 0);
750 + end = wctime();
751 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
752 + delay,
753 + end - start,
754 + end - start - delay,
755 + 100 * (end - start - delay) / delay);
756 + }
757 + }
758 +}
759 +
760 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
761 +{
762 + double chunk1, chunk2;
763 +
764 + if (wctime() > program_end)
765 + return 0;
766 + else {
767 + if (lock_od >= 0) {
768 + /* simulate critical section somewhere in the middle */
769 + chunk1 = drand48() * (exec_time - cs_length);
770 + chunk2 = exec_time - cs_length - chunk1;
771 +
772 + /* non-critical section */
773 + loop_for(chunk1, program_end + 1);
774 +
775 + /* critical section */
776 + litmus_lock(lock_od);
777 + loop_for(cs_length, program_end + 1);
778 + litmus_unlock(lock_od);
779 +
780 + /* non-critical section */
781 + loop_for(chunk2, program_end + 2);
782 + } else {
783 + loop_for(exec_time, program_end + 1);
784 + }
785 + sleep_next_period();
786 + return 1;
787 + }
788 +}
789 +
790 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
791 +{
792 + int i, matched;
793 + struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
794 + char** arg = (char**)malloc(sizeof(char*) * num);
795 + char *token, *saveptr;
796 + double start, end;
797 +
798 + for (i = 0; i < num; i++) {
799 + arg[i] = (char*)malloc(sizeof(char)*100);
800 + }
801 +
802 + i = 0;
803 + token = strtok_r(optarg, ":", &saveptr);
804 + while(token != NULL) {
805 + sprintf(arg[i++], "%s", token);
806 + token = strtok_r(NULL, ":", &saveptr);
807 + }
808 +
809 + *num_intervals = 0;
810 +
811 + for (i=0; i<num; i++) {
812 + matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
813 + if (matched != 2) {
814 + fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
815 + exit(5);
816 + }
817 + if (start < 0) {
818 + fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
819 + exit(5);
820 + }
821 + if (end <= start) {
822 + fprintf(stderr, "interval %s: end before start\n", arg[i]);
823 + exit(5);
824 + }
825 +
826 + slots[i].start = ms2ns(start);
827 + slots[i].end = ms2ns(end);
828 +
829 + if (i > 0 && slots[i - 1].end >= slots[i].start) {
830 + fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
831 + exit(5);
832 + }
833 +
834 + (*num_intervals)++;
835 + }
836 +
837 + for (i=0; i<num; i++) {
838 + free(arg[i]);
839 + }
840 + free(arg);
841 + return slots;
842 +}
843 +
844 +#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:"
845 +int main(int argc, char** argv)
846 +{
847 + int ret;
848 + lt_t wcet;
849 + lt_t period;
850 + lt_t hyperperiod;
851 + lt_t budget;
852 + double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
853 + unsigned int priority = LITMUS_NO_PRIORITY;
854 + int migrate = 0;
855 + int cluster = 0;
856 + int opt;
857 + int wait = 0;
858 + int test_loop = 0;
859 + int column = 1;
860 + const char *file = NULL;
861 + int want_enforcement = 0;
862 + double duration = 0, start = 0;
863 + double *exec_times = NULL;
864 + double scale = 1.0;
865 + task_class_t class = RT_CLASS_HARD;
866 + int cur_job = 0, num_jobs = 0;
867 + struct rt_task param;
868 + struct mc2_task mc2_param;
869 + struct reservation_config config;
870 + int res_type = PERIODIC_POLLING;
871 + int n_str, num_int = 0;
872 +
873 + int verbose = 0;
874 + unsigned int job_no;
875 +
876 + /* locking */
877 + int lock_od = -1;
878 + int resource_id = 0;
879 + const char *lock_namespace = "./rtspin-locks";
880 + int protocol = -1;
881 + double cs_length = 1; /* millisecond */
882 +
883 + progname = argv[0];
884 +
885 + /* default for reservation */
886 + config.id = 0;
887 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
888 + config.cpu = -1;
889 +
890 + mc2_param.crit = CRIT_LEVEL_C;
891 +
892 + hyperperiod_ms = 1000;
893 + budget_ms = 10;
894 +
895 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
896 + switch (opt) {
897 + case 'w':
898 + wait = 1;
899 + break;
900 + case 'p':
901 + cluster = atoi(optarg);
902 + migrate = 1;
903 + config.cpu = cluster;
904 + break;
905 + case 'q':
906 + priority = atoi(optarg);
907 + if (!litmus_is_valid_fixed_prio(priority))
908 + usage("Invalid priority.");
909 + break;
910 + case 'c':
911 + class = str2class(optarg);
912 + if (class == -1)
913 + usage("Unknown task class.");
914 + break;
915 + case 'e':
916 + want_enforcement = 1;
917 + break;
918 + case 'l':
919 + test_loop = 1;
920 + break;
921 + case 'o':
922 + column = atoi(optarg);
923 + break;
924 + case 'f':
925 + file = optarg;
926 + break;
927 + case 's':
928 + scale = atof(optarg);
929 + break;
930 + case 'X':
931 + protocol = lock_protocol_for_name(optarg);
932 + if (protocol < 0)
933 + usage("Unknown locking protocol specified.");
934 + break;
935 + case 'L':
936 + cs_length = atof(optarg);
937 + if (cs_length <= 0)
938 + usage("Invalid critical section length.");
939 + break;
940 + case 'Q':
941 + resource_id = atoi(optarg);
942 + if (resource_id <= 0 && strcmp(optarg, "0"))
943 + usage("Invalid resource ID.");
944 + break;
945 + case 'v':
946 + verbose = 1;
947 + break;
948 + case 'm':
949 + mc2_param.crit = atoi(optarg);
950 + if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
951 + usage("Invalid criticality level.");
952 + }
953 + res_type = PERIODIC_POLLING;
954 + break;
955 + case 'h':
956 + hyperperiod_ms = atof(optarg);
957 + break;
958 + case 'b':
959 + budget_ms = atof(optarg);
960 + break;
961 + case 'i':
962 + config.priority = atoi(optarg);
963 + break;
964 + case ':':
965 + usage("Argument missing.");
966 + break;
967 + case '?':
968 + default:
969 + usage("Bad argument.");
970 + break;
971 + }
972 + }
973 +
974 + if (test_loop) {
975 + debug_delay_loop(1);
976 + return 0;
977 + }
978 +
979 + if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
980 + usage("Bad criticailty level or priority");
981 +
982 + srand(getpid());
983 +
984 + if (file) {
985 + get_exec_times(file, column, &num_jobs, &exec_times);
986 +
987 + if (argc - optind < 2)
988 + usage("Arguments missing.");
989 +
990 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
991 + /* convert the execution time to seconds */
992 + duration += exec_times[cur_job] * 0.001;
993 + }
994 + } else {
995 + /*
996 + * if we're not reading from the CSV file, then we need
997 + * three parameters
998 + */
999 + if (argc - optind < 3)
1000 + usage("Arguments missing.");
1001 + }
1002 +
1003 + wcet_ms = atof(argv[optind + 0]);
1004 + period_ms = atof(argv[optind + 1]);
1005 +
1006 + wcet = ms2ns(wcet_ms);
1007 + period = ms2ns(period_ms);
1008 + budget = ms2ns(budget_ms);
1009 + hyperperiod = ms2ns(hyperperiod_ms);
1010 +
1011 + if (wcet <= 0)
1012 + usage("The worst-case execution time must be a "
1013 + "positive number.");
1014 + if (period <= 0)
1015 + usage("The period must be a positive number.");
1016 + if (!file && wcet > period) {
1017 + usage("The worst-case execution time must not "
1018 + "exceed the period.");
1019 + }
1020 +
1021 + if (!file)
1022 + duration = atof(argv[optind + 2]);
1023 + else if (file && num_jobs > 1)
1024 + duration += period_ms * 0.001 * (num_jobs - 1);
1025 +
1026 + if (migrate) {
1027 + ret = be_migrate_to_domain(cluster);
1028 + if (ret < 0)
1029 + bail_out("could not migrate to target partition or cluster.");
1030 + }
1031 +
1032 + /* reservation config */
1033 + config.id = gettid();
1034 +
1035 + if (hyperperiod%period != 0 ) {
1036 + ;//bail_out("hyperperiod must be multiple of period");
1037 + }
1038 +
1039 + config.polling_params.budget = budget;
1040 + config.polling_params.period = period;
1041 + config.polling_params.offset = 0;
1042 + config.polling_params.relative_deadline = 0;
1043 + if (config.polling_params.budget > config.polling_params.period) {
1044 + usage("The budget must not exceed the period.");
1045 + }
1046 +
1047 + /* create a reservation */
1048 + ret = reservation_create(res_type, &config);
1049 + if (ret < 0) {
1050 + bail_out("failed to create reservation.");
1051 + }
1052 +
1053 + init_rt_task_param(¶m);
1054 + param.exec_cost = wcet;
1055 + param.period = period;
1056 + param.priority = priority;
1057 + param.cls = class;
1058 + param.release_policy = TASK_PERIODIC;
1059 + param.budget_policy = (want_enforcement) ?
1060 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
1061 + if (migrate) {
1062 + param.cpu = gettid();
1063 + }
1064 + ret = set_rt_task_param(gettid(), ¶m);
1065 +//printf("SET_RT_TASK\n");
1066 + if (ret < 0)
1067 + bail_out("could not setup rt task params");
1068 +
1069 + mc2_param.res_id = gettid();
1070 + ret = set_mc2_task_param(gettid(), &mc2_param);
1071 +//printf("SET_MC2_TASK\n");
1072 + if (ret < 0)
1073 + bail_out("could not setup mc2 task params");
1074 +
1075 + pages = (int*)malloc(sizeof(int)*NUM_ITEMS);
1076 + access_order = (unsigned long*)malloc(sizeof(unsigned long)*NUM_ITEMS);
1077 + sattolo(access_order, NUM_ITEMS);
1078 +
1079 + init_litmus();
1080 +printf("CALL\n");
1081 + set_page_color(config.cpu);
1082 +printf("CALL\n");
1083 +
1084 +//printf("INIT_LITMUS\n");
1085 + start = wctime();
1086 + ret = task_mode(LITMUS_RT_TASK);
1087 +//printf("TASK_MODE\n");
1088 + if (ret != 0)
1089 + bail_out("could not become RT task");
1090 +
1091 + if (protocol >= 0) {
1092 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
1093 + if (lock_od < 0) {
1094 + perror("litmus_open_lock");
1095 + usage("Could not open lock.");
1096 + }
1097 + }
1098 +
1099 +
1100 + if (wait) {
1101 +//printf("BEFORE WAIT\n");
1102 + ret = wait_for_ts_release();
1103 + if (ret != 0)
1104 + bail_out("wait_for_ts_release()");
1105 + start = wctime();
1106 + }
1107 +
1108 + if (file) {
1109 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1110 + job(exec_times[cur_job] * 0.001 * scale,
1111 + start + duration,
1112 + lock_od, cs_length * 0.001);
1113 + }
1114 + } else {
1115 + do {
1116 + if (verbose) {
1117 + get_job_no(&job_no);
1118 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
1119 + job_no, (wctime() - start) * 1000);
1120 + }
1121 + } while (job(wcet_ms * 0.001 * scale, start + duration,
1122 + lock_od, cs_length * 0.001));
1123 + }
1124 +printf("BEFORE BACK_TASK\n");
1125 + ret = task_mode(BACKGROUND_TASK);
1126 + if (ret != 0)
1127 + bail_out("could not become regular task (huh?)");
1128 +
1129 + if (file)
1130 + free(exec_times);
1131 +
1132 + reservation_destroy(gettid(), config.cpu);
1133 +
1134 +printf("CALL\n");
1135 + set_page_color(config.cpu);
1136 +printf("CALL\n");
1137 + free(pages);
1138 + free(access_order);
1139 + return 0;
1140 +}
1141 diff --git bin/mc2thrash.c bin/mc2thrash.c
1142 new file mode 100644
1143 index 0000000..044dc03
1144 --- /dev/null
1145 +++ bin/mc2thrash.c
1146 @@ -0,0 +1,272 @@
1147 +#include <sys/time.h>
1148 +#include <sys/mman.h>
1149 +
1150 +#include <stdio.h>
1151 +#include <stdlib.h>
1152 +#include <unistd.h>
1153 +#include <time.h>
1154 +#include <string.h>
1155 +#include <assert.h>
1156 +#include <limits.h>
1157 +
1158 +#include "litmus.h"
1159 +#include "common.h"
1160 +#include "cache_common.h"
1161 +
1162 +#define PAGE_SIZE (4096)
1163 +#define CACHELINE_SIZE 32
1164 +#define WSS 2048
1165 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
1166 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
1167 +#define INTS_IN_1KB (1024 / sizeof(int))
1168 +
1169 +static cacheline_t* arena = NULL;
1170 +
1171 +static int random_walk(cacheline_t *mem, int write_cycle)
1172 +{
1173 + /* a random cycle among the cache lines was set up by init_arena(). */
1174 + int sum, i, next;
1175 +
1176 + int numlines = WSS * CACHELINES_IN_1KB;
1177 +
1178 + sum = 0;
1179 +
1180 + next = mem - arena;
1181 +
1182 + if (write_cycle == 0) {
1183 + for (i = 0; i < numlines; i++) {
1184 + /* every element in the cacheline has the same value */
1185 + next = arena[next].line[0];
1186 + sum += next;
1187 + }
1188 + }
1189 +
1190 + else {
1191 + int w, which_line;
1192 + for (i = 0, w = 0; i < numlines; i++) {
1193 + which_line = next;
1194 + next = arena[next].line[0];
1195 + if((w % write_cycle) != (write_cycle - 1)) {
1196 + sum += next;
1197 + }
1198 + else {
1199 + ((volatile cacheline_t*)arena)[which_line].line[0] = next;
1200 + }
1201 + }
1202 + }
1203 + return sum;
1204 +}
1205 +
1206 +static cacheline_t* random_start(void)
1207 +{
1208 + return arena + randrange(0, ((WSS * 1024)/sizeof(cacheline_t)));
1209 +}
1210 +
1211 +static volatile int dont_optimize_me = 0;
1212 +
1213 +static void usage(char *error) {
1214 + fprintf(stderr, "Error: %s\n", error);
1215 + fprintf(stderr,
1216 + "Usage:\n"
1217 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
1218 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
1219 + " rt_spin -l\n"
1220 + "\n"
1221 + "COMMON-OPTS = [-w] [-s SCALE]\n"
1222 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
1223 + " [-k WSS] [-l LOOPS] [-b BUDGET]\n"
1224 + "\n"
1225 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
1226 + exit(EXIT_FAILURE);
1227 +}
1228 +
1229 +static int loop_once(void)
1230 +{
1231 + cacheline_t *mem;
1232 + int temp;
1233 +
1234 + mem = random_start();
1235 + temp = random_walk(mem, 1);
1236 +
1237 + //mem = sequential_start(wss);
1238 + //temp = sequential_walk(mem, wss, 0);
1239 + dont_optimize_me = temp;
1240 +
1241 + return dont_optimize_me;
1242 +}
1243 +
1244 +static int job(double exec_time, double program_end)
1245 +{
1246 + if (wctime() > program_end)
1247 + return 0;
1248 + else {
1249 + double last_loop = 0, loop_start;
1250 + double start = cputime();
1251 + double now = cputime();
1252 + while(now + last_loop < start + exec_time) {
1253 + loop_start = now;
1254 + loop_once();
1255 + now = cputime();
1256 + last_loop = now - loop_start;
1257 + }
1258 + sleep_next_period();
1259 + return 1;
1260 + }
1261 +}
1262 +
1263 +#define OPTSTR "p:wm:i:k:"
1264 +int main(int argc, char** argv)
1265 +{
1266 + int ret, i;
1267 + lt_t wcet, period, budget;
1268 + double wcet_ms, period_ms;
1269 + unsigned int priority = LITMUS_NO_PRIORITY;
1270 + int migrate = 0;
1271 + int cluster = 0;
1272 + int opt;
1273 + int wait = 0;
1274 + double duration = 0, start = 0;
1275 + struct rt_task param;
1276 + struct mc2_task mc2_param;
1277 + struct reservation_config config;
1278 + int res_type = PERIODIC_POLLING;
1279 + size_t arena_sz;
1280 +
1281 + /* default for reservation */
1282 + config.id = 0;
1283 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
1284 + config.cpu = -1;
1285 + mc2_param.crit = CRIT_LEVEL_C;
1286 +
1287 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1288 + switch (opt) {
1289 + case 'w':
1290 + wait = 1;
1291 + break;
1292 + case 'p':
1293 + cluster = atoi(optarg);
1294 + migrate = 1;
1295 + config.cpu = cluster;
1296 + break;
1297 + case 'm':
1298 + mc2_param.crit = atoi(optarg);
1299 + if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
1300 + res_type = PERIODIC_POLLING;
1301 + }
1302 + else
1303 + usage("Invalid criticality level.");
1304 + break;
1305 + case 'i':
1306 + config.priority = atoi(optarg);
1307 + break;
1308 + case ':':
1309 + usage("Argument missing.");
1310 + break;
1311 + case '?':
1312 + default:
1313 + usage("Bad argument.");
1314 + break;
1315 + }
1316 + }
1317 + srand(getpid());
1318 + /* We need three parameters */
1319 + if (argc - optind < 3)
1320 + usage("Arguments missing.");
1321 +
1322 + wcet_ms = atof(argv[optind + 0]);
1323 + period_ms = atof(argv[optind + 1]);
1324 +
1325 + wcet = ms2ns(wcet_ms);
1326 + period = ms2ns(period_ms);
1327 + budget = ms2ns(period_ms);
1328 + if (wcet <= 0)
1329 + usage("The worst-case execution time must be a "
1330 + "positive number.");
1331 + if (period <= 0)
1332 + usage("The period must be a positive number.");
1333 + if (wcet > period) {
1334 + usage("The worst-case execution time must not "
1335 + "exceed the period.");
1336 + }
1337 +
1338 + duration = atof(argv[optind + 2]);
1339 +
1340 + if (migrate) {
1341 + ret = be_migrate_to_domain(cluster);
1342 + if (ret < 0)
1343 + bail_out("could not migrate to target partition or cluster.");
1344 + }
1345 +
1346 + /* reservation config */
1347 + config.id = gettid();
1348 + config.polling_params.budget = budget;
1349 + config.polling_params.period = period;
1350 + config.polling_params.offset = 0;
1351 + config.polling_params.relative_deadline = 0;
1352 +
1353 + if (config.polling_params.budget > config.polling_params.period) {
1354 + usage("The budget must not exceed the period.");
1355 + }
1356 +
1357 + /* create a reservation */
1358 + ret = reservation_create(res_type, &config);
1359 + if (ret < 0) {
1360 + bail_out("failed to create reservation.");
1361 + }
1362 +
1363 + init_rt_task_param(¶m);
1364 + param.exec_cost = wcet;
1365 + param.period = period;
1366 + param.priority = priority;
1367 + param.cls = RT_CLASS_HARD;
1368 + param.release_policy = TASK_PERIODIC;
1369 + param.budget_policy = NO_ENFORCEMENT;
1370 + if (migrate) {
1371 + param.cpu = gettid();
1372 + }
1373 + ret = set_rt_task_param(gettid(), ¶m);
1374 + if (ret < 0)
1375 + bail_out("could not setup rt task params");
1376 +
1377 + mc2_param.res_id = gettid();
1378 + ret = set_mc2_task_param(gettid(), &mc2_param);
1379 + if (ret < 0)
1380 + bail_out("could not setup mc2 task params");
1381 +
1382 + arena_sz = WSS*1024;
1383 + arena = alloc_arena(arena_sz, 0, 1);
1384 + init_arena(arena, arena_sz);
1385 +
1386 + ret = init_litmus();
1387 + if (ret != 0)
1388 + bail_out("init_litmus() failed\n");
1389 +
1390 + start = wctime();
1391 + ret = task_mode(LITMUS_RT_TASK);
1392 + if (ret != 0)
1393 + bail_out("could not become RT task");
1394 +
1395 + if (mc2_param.crit == CRIT_LEVEL_C)
1396 + set_page_color(-1);
1397 + else
1398 + set_page_color(config.cpu);
1399 +
1400 + lock_memory();
1401 +
1402 + if (wait) {
1403 + ret = wait_for_ts_release();
1404 + if (ret != 0)
1405 + bail_out("wait_for_ts_release()");
1406 + start = wctime();
1407 + }
1408 +
1409 + while (job(wcet_ms * 0.001, start + duration)) {};
1410 +
1411 + ret = task_mode(BACKGROUND_TASK);
1412 + if (ret != 0)
1413 + bail_out("could not become regular task (huh?)");
1414 +
1415 + reservation_destroy(gettid(), config.cpu);
1416 + dealloc_arena(arena, arena_sz);
1417 + return 0;
1418 +}
1419 diff --git bin/resctrl.c bin/resctrl.c
1420 new file mode 100644
1421 index 0000000..63b5054
1422 --- /dev/null
1423 +++ bin/resctrl.c
1424 @@ -0,0 +1,242 @@
1425 +#include <stdio.h>
1426 +#include <stdlib.h>
1427 +#include <string.h>
1428 +#include <unistd.h>
1429 +#include <limits.h>
1430 +#include <signal.h>
1431 +
1432 +#include <sched.h>
1433 +
1434 +#include "litmus.h"
1435 +#include "common.h"
1436 +
1437 +const char *usage_msg =
1438 + "Usage: resctrl OPTIONS [INTERVAL-START,INTERVAL-END]*\n"
1439 + " -n ID create new reservation with id ID\n"
1440 + " -a PID attach already-running process PID to reservation\n"
1441 + " -r ID specify which reservation to attach to (not needed with -n)\n"
1442 + " -t TYPE type of reservation (polling-periodic, polling-sporadic, table-driven)\n"
1443 + " -c CPU physical partition or cluster to assign to\n"
1444 + " -b BUDGET polling reservation budget (in ms, default: 10ms)\n"
1445 + " -p PERIOD polling reservation period (in ms, default: 100ms)\n"
1446 + " -d DEADLINE relative deadline, implicit by default (in ms)\n"
1447 + " -o OFFSET offset (also known as phase), zero by default (in ms)\n"
1448 + " -q PRIORITY priority to use (EDF by default, highest priority = 1)\n"
1449 + " -m MAJOR-CYCLE major cycle length (in ms, for table-driven reservations) \n"
1450 + "\n";
1451 +
1452 +void usage(char *error) {
1453 + fprintf(stderr, "%s\n%s", error, usage_msg);
1454 + exit(1);
1455 +}
1456 +
1457 +
1458 +static void attach_task(int attach_pid, struct reservation_config *config)
1459 +{
1460 + int ret;
1461 + struct rt_task param;
1462 + struct sched_param linux_param;
1463 +
1464 + ret = be_migrate_thread_to_cpu(attach_pid, config->cpu);
1465 + if (ret < 0) {
1466 + fprintf(stderr, "failed to migrate task %d to CPU %d\n",
1467 + attach_pid, config->cpu);
1468 + exit(4);
1469 + }
1470 +
1471 + init_rt_task_param(¶m);
1472 + /* dummy values */
1473 + param.exec_cost = ms2ns(100);
1474 + param.period = ms2ns(100);
1475 + /* specify reservation as "virtual" CPU */
1476 + param.cpu = config->id;
1477 +
1478 + ret = set_rt_task_param(attach_pid, ¶m);
1479 + if (ret < 0) {
1480 + fprintf(stderr, "failed to set RT task parameters for task %d (%m)\n",
1481 + attach_pid);
1482 + exit(2);
1483 + }
1484 +
1485 + linux_param.sched_priority = 0;
1486 + ret = sched_setscheduler(attach_pid, SCHED_LITMUS, &linux_param);
1487 + if (ret < 0) {
1488 + fprintf(stderr, "failed to transition task %d to LITMUS^RT class (%m)\n",
1489 + attach_pid);
1490 + exit(3);
1491 + }
1492 +}
1493 +
1494 +static struct lt_interval* parse_td_intervals(int argc, char** argv,
1495 + unsigned int *num_intervals, lt_t major_cycle)
1496 +{
1497 + int i, matched;
1498 + struct lt_interval *slots = malloc(sizeof(slots[0]) * argc);
1499 + double start, end;
1500 +
1501 + *num_intervals = 0;
1502 + for (i = 0; i < argc; i++) {
1503 + matched = sscanf(argv[i], "[%lf,%lf]", &start, &end);
1504 + if (matched != 2) {
1505 + fprintf(stderr, "could not parse '%s' as interval\n", argv[i]);
1506 + exit(5);
1507 + }
1508 + if (start < 0) {
1509 + fprintf(stderr, "interval %s: must not start before zero\n", argv[i]);
1510 + exit(5);
1511 + }
1512 + if (end <= start) {
1513 + fprintf(stderr, "interval %s: end before start\n", argv[i]);
1514 + exit(5);
1515 + }
1516 +
1517 + slots[i].start = ms2ns(start);
1518 + slots[i].end = ms2ns(end);
1519 +
1520 + if (i > 0 && slots[i - 1].end >= slots[i].start) {
1521 + fprintf(stderr, "interval %s: overlaps with previous interval\n", argv[i]);
1522 + exit(5);
1523 + }
1524 +
1525 + if (slots[i].end >= major_cycle) {
1526 + fprintf(stderr, "interval %s: exceeds major cycle length\n", argv[i]);
1527 + exit(5);
1528 + }
1529 +
1530 + (*num_intervals)++;
1531 + }
1532 +
1533 + return slots;
1534 +}
1535 +
1536 +#define OPTSTR "n:a:r:t:c:b:p:d:o:q:m:h"
1537 +
1538 +int main(int argc, char** argv)
1539 +{
1540 + int ret, opt;
1541 + double budget_ms, period_ms, offset_ms, deadline_ms, major_cycle_ms;
1542 + int create_new = 0;
1543 + int attach_pid = 0;
1544 + int res_type = SPORADIC_POLLING;
1545 +
1546 + struct reservation_config config;
1547 +
1548 + /* Reasonable defaults */
1549 + offset_ms = 0;
1550 + deadline_ms = 0;
1551 + budget_ms = 10;
1552 + period_ms = 100;
1553 + major_cycle_ms = 1000;
1554 +
1555 + config.id = 0;
1556 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
1557 + config.cpu = 0;
1558 +
1559 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1560 + switch (opt) {
1561 + case 'b':
1562 + budget_ms = atof(optarg);
1563 + break;
1564 + case 'p':
1565 + period_ms = atof(optarg);
1566 + break;
1567 + case 'd':
1568 + deadline_ms = atof(optarg);
1569 + if (deadline_ms <= 0) {
1570 + usage("The relative deadline must be a positive"
1571 + " number.");
1572 + }
1573 + break;
1574 + case 'o':
1575 + offset_ms = atof(optarg);
1576 + break;
1577 + case 'm':
1578 + major_cycle_ms = atof(optarg);
1579 + break;
1580 +
1581 + case 'q':
1582 + config.priority = atoi(optarg);
1583 + if (!config.priority)
1584 + usage("-q: invalid priority");
1585 + break;
1586 + case 'c':
1587 + config.cpu = atoi(optarg);
1588 + break;
1589 +
1590 + case 'n':
1591 + create_new = 1;
1592 + config.id = atoi(optarg);
1593 + break;
1594 + case 'a':
1595 + attach_pid = atoi(optarg);
1596 + if (!attach_pid)
1597 + usage("-a: invalid PID");
1598 + break;
1599 +
1600 + case 'r':
1601 + config.id = atoi(optarg);
1602 + break;
1603 +
1604 + case 't':
1605 + if (strcmp(optarg, "polling-periodic") == 0) {
1606 + res_type = PERIODIC_POLLING;
1607 + } else if (strcmp(optarg, "polling-sporadic") == 0) {
1608 + res_type = SPORADIC_POLLING;
1609 + } else if (strcmp(optarg, "table-driven") == 0) {
1610 + res_type = TABLE_DRIVEN;
1611 + /* Default for table-driven reservations to
1612 + * maximum priority. EDF has not meaning for
1613 + * table-driven reservations. */
1614 + if (config.priority == LITMUS_NO_PRIORITY)
1615 + config.priority = LITMUS_HIGHEST_PRIORITY;
1616 + } else {
1617 + usage("Unknown reservation type.");
1618 + }
1619 + break;
1620 +
1621 + case 'h':
1622 + usage("");
1623 + break;
1624 + case ':':
1625 + usage("Argument missing.");
1626 + break;
1627 + case '?':
1628 + default:
1629 + usage("Bad argument.");
1630 + break;
1631 + }
1632 + }
1633 +
1634 + if (res_type != TABLE_DRIVEN) {
1635 + config.polling_params.budget = ms2ns(budget_ms);
1636 + config.polling_params.period = ms2ns(period_ms);
1637 + config.polling_params.offset = ms2ns(offset_ms);
1638 + config.polling_params.relative_deadline = ms2ns(deadline_ms);
1639 + if (config.polling_params.budget > config.polling_params.period) {
1640 + usage("The budget must not exceed the period.");
1641 + }
1642 + } else {
1643 + config.table_driven_params.major_cycle_length = ms2ns(major_cycle_ms);
1644 + argc -= optind;
1645 + argv += optind;
1646 + config.table_driven_params.intervals = parse_td_intervals(
1647 + argc, argv, &config.table_driven_params.num_intervals,
1648 + config.table_driven_params.major_cycle_length);
1649 + if (!config.table_driven_params.num_intervals)
1650 + usage("Table-driven reservations require at least one interval to be specified.");
1651 + }
1652 +
1653 + if (create_new) {
1654 + ret = reservation_create(res_type, &config);
1655 + if (ret < 0) {
1656 + fprintf(stderr, "failed to create reservation %u (%m)\n",
1657 + config.id);
1658 + exit(1);
1659 + }
1660 + }
1661 +
1662 + if (attach_pid)
1663 + attach_task(attach_pid, &config);
1664 +
1665 + return 0;
1666 +}
1667 diff --git bin/rtspin.c bin/rtspin.c
1668 index b4156cc..fd57c45 100644
1669 --- bin/rtspin.c
1670 +++ bin/rtspin.c
1671 @@ -6,7 +6,7 @@
1672 #include <time.h>
1673 #include <string.h>
1674 #include <assert.h>
1675 -
1676 +#include <limits.h>
1677
1678 #include "litmus.h"
1679 #include "common.h"
1680 @@ -184,16 +184,17 @@ static int job(double exec_time, double program_end, int lock_od, double cs_leng
1681 }
1682 }
1683
1684 -#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:"
1685 +#define OPTSTR "p:c:wlveo:f:s:q:r:X:L:Q:v"
1686 int main(int argc, char** argv)
1687 {
1688 int ret;
1689 lt_t wcet;
1690 lt_t period;
1691 double wcet_ms, period_ms;
1692 - unsigned int priority = LITMUS_LOWEST_PRIORITY;
1693 + unsigned int priority = LITMUS_NO_PRIORITY;
1694 int migrate = 0;
1695 int cluster = 0;
1696 + int reservation = -1;
1697 int opt;
1698 int wait = 0;
1699 int test_loop = 0;
1700 @@ -207,6 +208,9 @@ int main(int argc, char** argv)
1701 int cur_job = 0, num_jobs = 0;
1702 struct rt_task param;
1703
1704 + int verbose = 0;
1705 + unsigned int job_no;
1706 +
1707 /* locking */
1708 int lock_od = -1;
1709 int resource_id = 0;
1710 @@ -225,6 +229,9 @@ int main(int argc, char** argv)
1711 cluster = atoi(optarg);
1712 migrate = 1;
1713 break;
1714 + case 'r':
1715 + reservation = atoi(optarg);
1716 + break;
1717 case 'q':
1718 priority = atoi(optarg);
1719 if (!litmus_is_valid_fixed_prio(priority))
1720 @@ -265,6 +272,9 @@ int main(int argc, char** argv)
1721 if (resource_id <= 0 && strcmp(optarg, "0"))
1722 usage("Invalid resource ID.");
1723 break;
1724 + case 'v':
1725 + verbose = 1;
1726 + break;
1727 case ':':
1728 usage("Argument missing.");
1729 break;
1730 @@ -334,14 +344,19 @@ int main(int argc, char** argv)
1731 param.cls = class;
1732 param.budget_policy = (want_enforcement) ?
1733 PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
1734 - if (migrate)
1735 - param.cpu = domain_to_first_cpu(cluster);
1736 + if (migrate) {
1737 + if (reservation >= 0)
1738 + param.cpu = reservation;
1739 + else
1740 + param.cpu = domain_to_first_cpu(cluster);
1741 + }
1742 ret = set_rt_task_param(gettid(), ¶m);
1743 if (ret < 0)
1744 bail_out("could not setup rt task params");
1745
1746 init_litmus();
1747
1748 + start = wctime();
1749 ret = task_mode(LITMUS_RT_TASK);
1750 if (ret != 0)
1751 bail_out("could not become RT task");
1752 @@ -355,14 +370,14 @@ int main(int argc, char** argv)
1753 }
1754 }
1755
1756 +
1757 if (wait) {
1758 ret = wait_for_ts_release();
1759 if (ret != 0)
1760 bail_out("wait_for_ts_release()");
1761 + start = wctime();
1762 }
1763
1764 - start = wctime();
1765 -
1766 if (file) {
1767 /* use times read from the CSV file */
1768 for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1769 @@ -372,8 +387,14 @@ int main(int argc, char** argv)
1770 lock_od, cs_length * 0.001);
1771 }
1772 } else {
1773 - /* convert to seconds and scale */
1774 - while (job(wcet_ms * 0.001 * scale, start + duration,
1775 + do {
1776 + if (verbose) {
1777 + get_job_no(&job_no);
1778 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
1779 + job_no, (wctime() - start) * 1000);
1780 + }
1781 + /* convert to seconds and scale */
1782 + } while (job(wcet_ms * 0.001 * scale, start + duration,
1783 lock_od, cs_length * 0.001));
1784 }
1785
1786 diff --git include/cache_common.h include/cache_common.h
1787 new file mode 100644
1788 index 0000000..2957dd3
1789 --- /dev/null
1790 +++ include/cache_common.h
1791 @@ -0,0 +1,213 @@
1792 +#ifndef __CACHE_COMMON_H__
1793 +#define __CACHE_COMMON_H__
1794 +
1795 +#include <stdio.h>
1796 +#include <stdlib.h>
1797 +#include <time.h>
1798 +#include <string.h>
1799 +#include <assert.h>
1800 +
1801 +#include <signal.h>
1802 +#include <sys/mman.h>
1803 +#include <sys/types.h>
1804 +#include <sys/stat.h>
1805 +#include <fcntl.h>
1806 +#include <unistd.h>
1807 +
1808 +#include <sys/io.h>
1809 +#include <sys/utsname.h>
1810 +
1811 +#include <sched.h>
1812 +#include <sys/time.h>
1813 +#include <sys/resource.h>
1814 +
1815 +#include "litmus.h"
1816 +#include "asm/cycles.h"
1817 +
1818 +#if defined(__i386__) || defined(__x86_64__)
1819 +#include "asm/irq.h"
1820 +#endif
1821 +
1822 +
1823 +#define UNCACHE_DEV "/dev/litmus/uncache"
1824 +
1825 +static void die(char *error)
1826 +{
1827 + fprintf(stderr, "Error: %s (errno: %m)\n",
1828 + error);
1829 + exit(1);
1830 +}
1831 +
1832 +static int migrate_to(int cpu)
1833 +{
1834 + int ret;
1835 +
1836 + static __thread cpu_set_t* cpu_set = NULL;
1837 + static __thread size_t cpu_set_sz;
1838 + static __thread int num_cpus;
1839 + if(!cpu_set)
1840 + {
1841 + num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1842 + cpu_set = CPU_ALLOC(num_cpus);
1843 + cpu_set_sz = CPU_ALLOC_SIZE(num_cpus);
1844 + }
1845 +
1846 + CPU_ZERO_S(cpu_set_sz, cpu_set);
1847 + CPU_SET_S(cpu, cpu_set_sz, cpu_set);
1848 + ret = sched_setaffinity(0 /* self */, cpu_set_sz, cpu_set);
1849 + return ret;
1850 +}
1851 +
1852 +static int check_migrations(int num_cpus)
1853 +{
1854 + int cpu, err;
1855 +
1856 + for (cpu = 0; cpu < num_cpus; cpu++) {
1857 + err = migrate_to(cpu);
1858 + if (err != 0) {
1859 + fprintf(stderr, "Migration to CPU %d failed: %m.\n",
1860 + cpu + 1);
1861 + return 1;
1862 + }
1863 + }
1864 + return 0;
1865 +}
1866 +
1867 +static int become_posix_realtime_task(int prio)
1868 +{
1869 + struct sched_param param;
1870 + memset(¶m, 0, sizeof(param));
1871 + param.sched_priority = prio;
1872 + return sched_setscheduler(0 /* self */, SCHED_FIFO, ¶m);
1873 +}
1874 +
1875 +static int renice(int nice_val)
1876 +{
1877 + return setpriority(PRIO_PROCESS, 0 /* self */, nice_val);
1878 +}
1879 +
1880 +static int lock_memory(void)
1881 +{
1882 + return mlockall(MCL_CURRENT | MCL_FUTURE);
1883 +}
1884 +
1885 +/* define CACHELINE_SIZE if not provided by compiler args */
1886 +#ifndef CACHELINE_SIZE
1887 +#if defined(__i386__) || defined(__x86_64__)
1888 +/* recent intel cpus */
1889 +#define CACHELINE_SIZE 64
1890 +#elif defined(__arm__)
1891 +/* at least with Cortex-A9 cpus ("8 words") */
1892 +#define CACHELINE_SIZE 32
1893 +#else
1894 +#error "Could not determine cacheline size!"
1895 +#endif
1896 +#endif
1897 +
1898 +//#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
1899 +//typedef struct cacheline
1900 +//{
1901 +// int line[INTS_IN_CACHELINE];
1902 +//} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
1903 +
1904 +static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages)
1905 +{
1906 + int flags = MAP_PRIVATE | MAP_POPULATE;
1907 + cacheline_t* arena = NULL;
1908 + int fd;
1909 +
1910 + if(use_huge_pages)
1911 + flags |= MAP_HUGETLB;
1912 +
1913 + if(use_uncache_pages) {
1914 + fd = open(UNCACHE_DEV, O_RDWR);
1915 + if (fd == -1)
1916 + die("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
1917 + }
1918 + else {
1919 + fd = -1;
1920 + flags |= MAP_ANONYMOUS;
1921 + }
1922 +
1923 + arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
1924 +
1925 + if(use_uncache_pages)
1926 + close(fd);
1927 +
1928 + assert(arena);
1929 +
1930 + return arena;
1931 +}
1932 +
1933 +static void dealloc_arena(cacheline_t* arena, size_t size)
1934 +{
1935 + int ret = munmap((void*)arena, size);
1936 + if(ret != 0)
1937 + die("munmap() error");
1938 +}
1939 +
1940 +static int randrange(int min, int max)
1941 +{
1942 + /* generate a random number on the range [min, max) w/o skew */
1943 + int limit = max - min;
1944 + int devisor = RAND_MAX/limit;
1945 + int retval;
1946 +
1947 + do {
1948 + retval = rand() / devisor;
1949 + } while(retval == limit);
1950 + retval += min;
1951 +
1952 + return retval;
1953 +}
1954 +
1955 +static void init_arena(cacheline_t* arena, size_t size)
1956 +{
1957 + int i;
1958 + size_t num_arena_elem = size / sizeof(cacheline_t);
1959 +
1960 + /* Generate a cycle among the cache lines using Sattolo's algorithm.
1961 + Every int in the cache line points to the same cache line.
1962 + Note: Sequential walk doesn't care about these values. */
1963 + for (i = 0; i < num_arena_elem; i++) {
1964 + int j;
1965 + for(j = 0; j < INTS_IN_CACHELINE; ++j)
1966 + arena[i].line[j] = i;
1967 + }
1968 + while(1 < i--) {
1969 + int j = randrange(0, i);
1970 + cacheline_t temp = arena[j];
1971 + arena[j] = arena[i];
1972 + arena[i] = temp;
1973 + }
1974 +}
1975 +
1976 +static void sleep_us(int microseconds)
1977 +{
1978 + struct timespec delay;
1979 +
1980 + delay.tv_sec = 0;
1981 + delay.tv_nsec = microseconds * 1000;
1982 + if (nanosleep(&delay, NULL) != 0)
1983 + die("sleep failed");
1984 +}
1985 +
1986 +static int completed(int nSamples, int* history, int nCategories)
1987 +{
1988 + int i;
1989 + for(i = 0; i < nCategories; ++i)
1990 + if(history[i] < nSamples)
1991 + return 0;
1992 + return 1;
1993 +}
1994 +
1995 +inline unsigned long get_cyclecount (void)
1996 +{
1997 + unsigned long value;
1998 + // Read CCNT Register
1999 + asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
2000 + return value;
2001 +}
2002 +
2003 +
2004 +#endif
2005 diff --git include/color_shm.h include/color_shm.h
2006 new file mode 100644
2007 index 0000000..449ec9d
2008 --- /dev/null
2009 +++ include/color_shm.h
2010 @@ -0,0 +1,20 @@
2011 +#include <sys/types.h>
2012 +#include <sys/ioctl.h>
2013 +#include <fcntl.h>
2014 +
2015 +#define SHM_MAJOR (240)
2016 +
2017 +struct color_ioctl_cmd {
2018 + unsigned int color;
2019 + unsigned int bank;
2020 +};
2021 +
2022 +struct color_ioctl_offset {
2023 + unsigned long offset;
2024 + int lock;
2025 +};
2026 +
2027 +#define SET_COLOR_SHM_CMD _IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd)
2028 +#define SET_COLOR_SHM_OFFSET _IOW(SHM_MAJOR, 0x2, struct color_ioctl_offset)
2029 +
2030 +void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset);
2031 diff --git include/litmus.h include/litmus.h
2032 index f99ccec..f39feb6 100644
2033 --- include/litmus.h
2034 +++ include/litmus.h
2035 @@ -40,11 +40,21 @@ extern "C" {
2036
2037 #include "migration.h"
2038
2039 +#include "litmus/mc2_common.h"
2040 +
2041 /**
2042 * @private
2043 * Number of semaphore protocol object types
2044 */
2045 -#define SCHED_LITMUS 6
2046 +#define SCHED_LITMUS 7
2047 +
2048 +#define CACHELINE_SIZE 32
2049 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
2050 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
2051 +typedef struct cacheline
2052 +{
2053 + int line[INTS_IN_CACHELINE];
2054 +} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
2055
2056 /**
2057 * Initialise a real-time task param struct
2058 @@ -146,6 +156,12 @@ int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster);
2059 /** Convert microseconds to nanoseconds
2060 * @param us Time units in microseconds */
2061 #define us2ns(us) ((us)*1000LL)
2062 +#define ns2s(ns) ((ns)/1000000000LL)
2063 +#define ns2ms(ns) ((ns)/1000000LL)
2064 +#define ns2us(ns) ((ns)/1000LL)
2065 +#define us2ms(us) ((us)/1000LL)
2066 +#define us2s(us) ((us)/1000000LL)
2067 +#define ms2s(ms) ((ms)/1000LL)
2068
2069 /**
2070 * Locking protocols for allocated shared objects
2071 @@ -416,6 +432,19 @@ int null_call(cycles_t *timestamp);
2072 */
2073 struct control_page* get_ctrl_page(void);
2074
2075 +int reservation_create(int rtype, void *config);
2076 +
2077 +int reservation_destroy(unsigned int reservation_id, int cpu);
2078 +
2079 +int set_mc2_task_param(pid_t pid, struct mc2_task* param);
2080 +
2081 +int set_page_color(int cpu);
2082 +
2083 +int test_call(unsigned int param);
2084 +
2085 +int run_bench(int type, int size, cacheline_t *src, cacheline_t *dst, lt_t __user *ts);
2086 +
2087 +int lock_buffer(void* addr, size_t size, unsigned int lock_way, unsigned int unlock_way);
2088 #ifdef __cplusplus
2089 }
2090 #endif
2091 diff --git src/color_shm.c src/color_shm.c
2092 new file mode 100644
2093 index 0000000..8531445
2094 --- /dev/null
2095 +++ src/color_shm.c
2096 @@ -0,0 +1,40 @@
2097 +#include <sys/mman.h>
2098 +#include <stdio.h>
2099 +
2100 +#include "color_shm.h"
2101 +
2102 +void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset)
2103 +{
2104 + int ret, fd;
2105 + void *mem;
2106 +
2107 + fd = open("/dev/litmus/color_shm", O_RDWR);
2108 + if (fd < 0) {
2109 + printf("Device open error.\n");
2110 + return NULL;
2111 + }
2112 +
2113 + ret = ioctl(fd, SET_COLOR_SHM_CMD, &cmd);
2114 + if (ret < 0) {
2115 + printf("ioctl failed.\n");
2116 + return NULL;
2117 + }
2118 +
2119 + ret = ioctl(fd, SET_COLOR_SHM_OFFSET, &offset);
2120 + if (ret < 0) {
2121 + printf("ioctl failed.\n");
2122 + return NULL;
2123 + }
2124 +
2125 + size += offset.offset;
2126 + mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
2127 + if (mem == MAP_FAILED) {
2128 + printf("mmap failed.\n");
2129 + return MAP_FAILED;
2130 + }
2131 + close(fd);
2132 +
2133 + mem += offset.offset;
2134 +
2135 + return mem;
2136 +}
2137 \ No newline at end of file
2138 diff --git src/kernel_iface.c src/kernel_iface.c
2139 index ca874ff..a2c2104 100644
2140 --- src/kernel_iface.c
2141 +++ src/kernel_iface.c
2142 @@ -2,7 +2,7 @@
2143 #include <sys/fcntl.h> /* for O_RDWR */
2144 #include <sys/unistd.h>
2145 #include <sched.h> /* for sched_yield() */
2146 -
2147 +#include <assert.h>
2148
2149 #include <stdio.h>
2150
2151 diff --git src/syscalls.c src/syscalls.c
2152 index c68f15b..01ed57a 100644
2153 --- src/syscalls.c
2154 +++ src/syscalls.c
2155 @@ -86,3 +86,33 @@ int null_call(cycles_t *timestamp)
2156 {
2157 return syscall(__NR_null_call, timestamp);
2158 }
2159 +
2160 +int reservation_create(int rtype, void *config)
2161 +{
2162 + return syscall(__NR_reservation_create, rtype, config);
2163 +}
2164 +
2165 +int reservation_destroy(unsigned int reservation_id, int cpu)
2166 +{
2167 + return syscall(__NR_reservation_destroy, reservation_id, cpu);
2168 +}
2169 +
2170 +int set_mc2_task_param(pid_t pid, struct mc2_task *param)
2171 +{
2172 + return syscall(__NR_set_mc2_task_param, pid, param);
2173 +}
2174 +
2175 +int set_page_color(int cpu)
2176 +{
2177 + return syscall(__NR_set_page_color, cpu);
2178 +}
2179 +
2180 +int run_bench(int type, int wss, cacheline_t *src, cacheline_t *dst, lt_t *ts)
2181 +{
2182 + return syscall(__NR_run_test, type, wss, src, dst, ts);
2183 +}
2184 +
2185 +int lock_buffer(void* addr, size_t size, unsigned int lock_way, unsigned int unlock_way)
2186 +{
2187 + return syscall(__NR_lock_buffer, addr, size, lock_way, unlock_way);
2188 +}
2189
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.