Attachment 'liblitmus-rtns17.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..3e6ee15 100644
41 --- Makefile
42 +++ Makefile
43 @@ -19,7 +19,7 @@ LITMUS_KERNEL ?= ../litmus-rt
44 # Internal configuration.
45
46 # compiler flags
47 -flags-debug = -O2 -Wall -Werror -g -Wdeclaration-after-statement
48 +flags-debug = -O0 -Wall -g -Wdeclaration-after-statement
49 flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
50
51 # architecture-specific flags
52 @@ -73,11 +73,14 @@ AR := ${CROSS_COMPILE}${AR}
53
54 all = lib ${rt-apps}
55 rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
56 - base_mt_task uncache runtests
57 + base_mt_task uncache runtests resctrl mc2mem \
58 + mc2spin mtdag mode_request rt_mode_poll
59 +
60 +#mc2thrash mc2thrash1 mc2thrash2 mc2thrash3
61
62 .PHONY: all lib clean dump-config TAGS tags cscope help doc
63
64 -all: ${all} inc/config.makefile
65 +all: ${all} inc/config.makefile post-build
66
67 # Write a distilled version of the flags for clients of the library. Ideally,
68 # this should depend on liblitmus.a, but that requires LIBLITMUS to be a
69 @@ -126,6 +129,7 @@ clean:
70 rm -f inc/config.makefile
71 rm -f tags TAGS cscope.files cscope.out
72 rm -r -f docs
73 + rm -f mc2mem*
74
75 # Emacs Tags
76 TAGS:
77 @@ -143,6 +147,8 @@ cscope:
78 @find . -type f -and -iname '*.[ch]' | xargs printf "%s\n" > cscope.files
79 @cscope -b
80
81 +post-build:
82 +
83 # ##############################################################################
84 # Kernel headers.
85 # The kernel does not like being #included directly, so let's
86 @@ -168,7 +174,8 @@ litmus-headers = \
87 include/litmus/rt_param.h \
88 include/litmus/fpmath.h \
89 include/litmus/unistd_32.h \
90 - include/litmus/unistd_64.h
91 + include/litmus/unistd_64.h \
92 + include/litmus/mc2_common.h
93
94 unistd-headers = \
95 $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/$(file))
96 @@ -234,6 +241,22 @@ obj-release_ts = release_ts.o
97 obj-measure_syscall = null_call.o
98 lib-measure_syscall = -lm
99
100 +obj-resctrl = resctrl.o
101 +
102 +obj-mc2spin = mc2spin.o common.o
103 +lib-mc2spin = -lrt -static
104 +
105 +obj-mc2mem = mc2mem.o common.o
106 +lib-mc2mem = -lrt -static
107 +
108 +obj-mtdag = mtdag.o common.o
109 +ldf-mtdag = -lrt -pthread -static
110 +
111 +obj-mode_request = mode_request.o common.o
112 +lib-mode_request = -lrt -static
113 +
114 +obj-rt_mode_poll = rt_mode_poll.o common.o
115 +lib-rt_mode_poll = -lrt -static
116 # ##############################################################################
117 # Build everything that depends on liblitmus.
118
119 diff --git bin/base_mt_task.c bin/base_mt_task.c
120 index aec79a4..1665203 100644
121 --- bin/base_mt_task.c
122 +++ bin/base_mt_task.c
123 @@ -29,11 +29,13 @@
124 /* Let's create 10 threads in the example,
125 * for a total utilization of 1.
126 */
127 -#define NUM_THREADS 10
128 +#define NUM_THREADS 3
129
130 /* The information passed to each thread. Could be anything. */
131 struct thread_context {
132 int id;
133 + int cpu;
134 + int job_no;
135 };
136
137 /* The real-time thread program. Doesn't have to be the same for
138 @@ -45,7 +47,7 @@ void* rt_thread(void *tcontext);
139 * Returns 1 -> task should exit.
140 * 0 -> task should continue.
141 */
142 -int job(void);
143 +int job(struct thread_context *tcx);
144
145
146 /* Catch errors.
147 @@ -97,6 +99,8 @@ int main(int argc, char** argv)
148 */
149 for (i = 0; i < NUM_THREADS; i++) {
150 ctx[i].id = i;
151 + ctx[i].cpu = 0;
152 + ctx[i].job_no = 0;
153 pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
154 }
155
156 @@ -125,6 +129,7 @@ void* rt_thread(void *tcontext)
157 int do_exit;
158 struct thread_context *ctx = (struct thread_context *) tcontext;
159 struct rt_task param;
160 + int ret;
161
162 /* Set up task parameters */
163 init_rt_task_param(¶m);
164 @@ -157,6 +162,12 @@ void* rt_thread(void *tcontext)
165 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
166 * set_rt_task_param().
167 */
168 + param.cpu = ctx->cpu;
169 + ret = be_migrate_to_cpu(ctx->cpu);
170 + if (ret < 0) {
171 + printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
172 + return NULL;
173 + }
174 CALL( set_rt_task_param(gettid(), ¶m) );
175
176 /*****
177 @@ -176,7 +187,7 @@ void* rt_thread(void *tcontext)
178 /* Wait until the next job is released. */
179 sleep_next_period();
180 /* Invoke job. */
181 - do_exit = job();
182 + do_exit = job(ctx);
183 } while (!do_exit);
184
185
186 @@ -192,10 +203,13 @@ void* rt_thread(void *tcontext)
187
188
189
190 -int job(void)
191 +int job(struct thread_context *tcx)
192 {
193 /* Do real-time calculation. */
194 -
195 + printf("Job executinig\n");
196 + tcx->job_no++;
197 + if (tcx->job_no == 5)
198 + return 1;
199 /* Don't exit. */
200 return 0;
201 }
202 diff --git bin/mc2mem.c bin/mc2mem.c
203 new file mode 100644
204 index 0000000..1087381
205 --- /dev/null
206 +++ bin/mc2mem.c
207 @@ -0,0 +1,326 @@
208 +#include <sys/time.h>
209 +#include <sys/mman.h>
210 +
211 +#include <stdio.h>
212 +#include <stdlib.h>
213 +#include <unistd.h>
214 +#include <time.h>
215 +#include <string.h>
216 +#include <assert.h>
217 +#include <limits.h>
218 +#include <fcntl.h>
219 +#include <math.h>
220 +
221 +#include "litmus.h"
222 +#include "common.h"
223 +#include "cache_common.h"
224 +
225 +#define PAGE_SIZE (4096)
226 +#define CACHELINE_SIZE 32
227 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
228 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
229 +#define INTS_IN_1KB (1024 / sizeof(int))
230 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
231 +
232 +static int loops = 100;
233 +static cacheline_t* arena = NULL;
234 +static int verbose = 0;
235 +
236 +struct timeval t1,t2;
237 +
238 +
239 +#define UNCACHE_DEV "/dev/litmus/uncache"
240 +
241 +/* Random walk around the arena in cacheline-sized chunks.
242 + Cacheline-sized chucks ensures the same utilization of each
243 + hit line as sequential read. (Otherwise, our utilization
244 + would only be 1/INTS_IN_CACHELINE.) */
245 +static int random_walk(cacheline_t *mem, int wss, int write_cycle)
246 +{
247 + /* a random cycle among the cache lines was set up by init_arena(). */
248 + int sum, i, next;
249 +
250 + int numlines = wss * CACHELINES_IN_1KB;
251 +
252 + sum = 0;
253 +
254 + /* contents of arena is structured s.t. offsets are all
255 + w.r.t. to start of arena, so compute the initial offset */
256 + next = mem - arena;
257 +
258 + if (write_cycle == 0) {
259 + for (i = 0; i < numlines; i++) {
260 + /* every element in the cacheline has the same value */
261 + next = arena[next].line[0];
262 + sum += next;
263 + }
264 + }
265 +
266 + else {
267 + int w, which_line;
268 + for (i = 0, w = 0; i < numlines; i++) {
269 + which_line = next;
270 + next = arena[next].line[0];
271 + if((w % write_cycle) != (write_cycle - 1)) {
272 + sum += next;
273 + }
274 + else {
275 + ((volatile cacheline_t*)arena)[which_line].line[0] = next;
276 + }
277 + }
278 + }
279 + return sum;
280 +}
281 +
282 +static cacheline_t* random_start(int wss)
283 +{
284 + return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
285 +}
286 +
287 +static volatile int dont_optimize_me = 0;
288 +
289 +static void usage(char *error) {
290 + fprintf(stderr, "Error: %s\n", error);
291 + fprintf(stderr,
292 + "Usage:\n"
293 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
294 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
295 + " rt_spin -l\n"
296 + "\n"
297 + "COMMON-OPTS = [-w] [-s SCALE]\n"
298 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
299 + " [-k WSS] [-l LOOPS] [-b BUDGET]\n"
300 + "\n"
301 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
302 + exit(EXIT_FAILURE);
303 +}
304 +
305 +static int loop_once(int wss)
306 +{
307 + cacheline_t *mem;
308 + int temp;
309 +
310 + mem = random_start(wss);
311 + temp = random_walk(mem, wss, 1);
312 +
313 + //mem = sequential_start(wss);
314 + //temp = sequential_walk(mem, wss, 0);
315 + dont_optimize_me = temp;
316 +
317 + return dont_optimize_me;
318 +}
319 +
320 +static int job(int wss, double exec_time, double program_end)
321 +{
322 + if (wctime() > program_end)
323 + return 0;
324 + else {
325 + register unsigned int iter = 0;
326 + register cycles_t t;
327 + t = get_cycles();
328 + while(iter++ < loops) {
329 + loop_once(wss);
330 + }
331 + t = get_cycles() - t;
332 + if (verbose)
333 + printf("%ld cycles\n", t);
334 + sleep_next_period();
335 + return 1;
336 + }
337 +}
338 +
339 +#define OPTSTR "p:wl:m:i:b:k:vs:"
340 +int main(int argc, char** argv)
341 +{
342 + int ret, i;
343 + lt_t wcet, period, budget;
344 + double wcet_ms, period_ms, budget_ms;
345 + unsigned int priority = LITMUS_NO_PRIORITY;
346 + int migrate = 0;
347 + int cluster = 0;
348 + int opt;
349 + int wait = 0;
350 + double duration = 0, start = 0;
351 + struct rt_task param;
352 + struct mc2_task mc2_param;
353 + struct reservation_config config;
354 + int res_type = PERIODIC_POLLING;
355 + size_t arena_sz;
356 + int wss = 1;
357 + uint32_t mode_mask;
358 +
359 + /* default for reservation */
360 + config.id = 0;
361 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
362 + config.cpu = -1;
363 +
364 + mc2_param.crit = CRIT_LEVEL_C;
365 +
366 + budget_ms = 1000;
367 +
368 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
369 + switch (opt) {
370 + case 'w':
371 + wait = 1;
372 + break;
373 + case 'p':
374 + cluster = atoi(optarg);
375 + migrate = 1;
376 + config.cpu = cluster;
377 + break;
378 + case 'l':
379 + loops = atoi(optarg);
380 + break;
381 + case 's':
382 + wss = atoi(optarg);
383 + break;
384 + case 'k':
385 + mode_mask = atoi(optarg);
386 + break;
387 + case 'm':
388 + mc2_param.crit = atoi(optarg);
389 + if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
390 + res_type = PERIODIC_POLLING;
391 + }
392 + else
393 + usage("Invalid criticality level.");
394 + break;
395 + case 'b':
396 + budget_ms = atof(optarg);
397 + break;
398 + case 'i':
399 + config.priority = atoi(optarg);
400 + break;
401 + case 'v':
402 + verbose = 1;
403 + break;
404 + case ':':
405 + usage("Argument missing.");
406 + break;
407 + case '?':
408 + default:
409 + usage("Bad argument.");
410 + break;
411 + }
412 + }
413 + srand(getpid());
414 +
415 + /*
416 + * We need three parameters
417 + */
418 + if (argc - optind < 3)
419 + usage("Arguments missing.");
420 +
421 + wcet_ms = atof(argv[optind + 0]);
422 + period_ms = atof(argv[optind + 1]);
423 +
424 + wcet = ms2ns(wcet_ms);
425 + period = ms2ns(period_ms);
426 + budget = ms2ns(budget_ms);
427 + if (wcet <= 0)
428 + usage("The worst-case execution time must be a "
429 + "positive number.");
430 + if (period <= 0)
431 + usage("The period must be a positive number.");
432 + if (wcet > period) {
433 + usage("The worst-case execution time must not "
434 + "exceed the period.");
435 + }
436 + if (wss == 0) {
437 + usage("You need to specify a WSS (-k option).");
438 + }
439 +
440 + duration = atof(argv[optind + 2]);
441 +
442 + if (migrate) {
443 + ret = be_migrate_to_domain(cluster);
444 + if (ret < 0)
445 + bail_out("could not migrate to target partition or cluster.");
446 + }
447 +
448 + /* reservation config */
449 + config.id = gettid();
450 + config.polling_params.budget = budget;
451 + config.polling_params.period = period;
452 + config.polling_params.offset = 0;
453 + config.polling_params.relative_deadline = 0;
454 +
455 + if (config.polling_params.budget > config.polling_params.period) {
456 + usage("The budget must not exceed the period.");
457 + }
458 +
459 + /* create a reservation */
460 + for(i = 0; i < 32; i++){
461 + if ( !( (1 << i) & mode_mask) )
462 + continue;
463 + config.mode = i;
464 + ret = reservation_create(res_type, &config);
465 + if (ret < 0) {
466 + bail_out("failed to create reservation.");
467 + }
468 + }
469 +
470 + init_rt_task_param(¶m);
471 + param.exec_cost = wcet;
472 + param.period = period;
473 + param.priority = priority;
474 + param.cls = RT_CLASS_HARD;
475 + param.release_policy = TASK_PERIODIC;
476 + param.budget_policy = NO_ENFORCEMENT;
477 + if (migrate) {
478 + param.cpu = gettid();
479 + //param.cpu = config.cpu;
480 + }
481 + ret = set_rt_task_param(gettid(), ¶m);
482 + if (ret < 0)
483 + bail_out("could not setup rt task params");
484 +
485 + mc2_param.res_id = gettid();
486 + mc2_param.mode_mask = mode_mask;
487 + ret = set_mc2_task_param(gettid(), &mc2_param);
488 + if (ret < 0)
489 + bail_out("could not setup mc2 task params");
490 +
491 + arena_sz = wss*1024;
492 + arena = alloc_arena(arena_sz, 0, 0);
493 + init_arena(arena, arena_sz);
494 +
495 + mlockall(MCL_CURRENT | MCL_FUTURE);
496 +
497 + ret = init_litmus();
498 + if (ret != 0)
499 + bail_out("init_litmus() failed\n");
500 +
501 + start = wctime();
502 + ret = task_mode(LITMUS_RT_TASK);
503 + if (ret != 0)
504 + bail_out("could not become RT task");
505 +
506 + if (mc2_param.crit == CRIT_LEVEL_C)
507 + set_page_color(-1);
508 + else
509 + set_page_color(config.cpu);
510 +
511 + mlockall(MCL_CURRENT | MCL_FUTURE);
512 +
513 + if (wait) {
514 + ret = wait_for_ts_release();
515 + if (ret != 0)
516 + bail_out("wait_for_ts_release()");
517 + start = wctime();
518 + }
519 +
520 + while (job(wss, wcet_ms * 0.001, start + duration)) {};
521 +
522 +//set_page_color(config.cpu);
523 + //test_call(0);
524 + ret = task_mode(BACKGROUND_TASK);
525 + if (ret != 0)
526 + bail_out("could not become regular task (huh?)");
527 +
528 + reservation_destroy(gettid(), config.cpu);
529 + dealloc_arena(arena, arena_sz);
530 + printf("%s finished.\n", argv[0]);
531 + //test_call(1);
532 + return 0;
533 +}
534 diff --git bin/mc2spin.c bin/mc2spin.c
535 new file mode 100644
536 index 0000000..dfb5c80
537 --- /dev/null
538 +++ bin/mc2spin.c
539 @@ -0,0 +1,545 @@
540 +#include <sys/time.h>
541 +#include <sys/mman.h>
542 +
543 +#include <stdio.h>
544 +#include <stdlib.h>
545 +#include <unistd.h>
546 +#include <time.h>
547 +#include <string.h>
548 +#include <assert.h>
549 +#include <limits.h>
550 +
551 +
552 +#include "litmus.h"
553 +#include "common.h"
554 +
555 +#define PAGE_SIZE 4096
556 +
557 +static void usage(char *error) {
558 + fprintf(stderr, "Error: %s\n", error);
559 + fprintf(stderr,
560 + "Usage:\n"
561 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
562 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
563 + " rt_spin -l\n"
564 + "\n"
565 + "COMMON-OPTS = [-w] [-s SCALE]\n"
566 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
567 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
568 + " [-i [start,end]:[start,end]...]\n"
569 + "\n"
570 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
571 + "CRITICAL SECTION LENGTH is in milliseconds.\n");
572 + exit(EXIT_FAILURE);
573 +}
574 +
575 +/*
576 + * returns the character that made processing stop, newline or EOF
577 + */
578 +static int skip_to_next_line(FILE *fstream)
579 +{
580 + int ch;
581 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
582 + return ch;
583 +}
584 +
585 +static void skip_comments(FILE *fstream)
586 +{
587 + int ch;
588 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
589 + skip_to_next_line(fstream);
590 + ungetc(ch, fstream);
591 +}
592 +
593 +static void get_exec_times(const char *file, const int column,
594 + int *num_jobs, double **exec_times)
595 +{
596 + FILE *fstream;
597 + int cur_job, cur_col, ch;
598 + *num_jobs = 0;
599 +
600 + fstream = fopen(file, "r");
601 + if (!fstream)
602 + bail_out("could not open execution time file");
603 +
604 + /* figure out the number of jobs */
605 + do {
606 + skip_comments(fstream);
607 + ch = skip_to_next_line(fstream);
608 + if (ch != EOF)
609 + ++(*num_jobs);
610 + } while (ch != EOF);
611 +
612 + if (-1 == fseek(fstream, 0L, SEEK_SET))
613 + bail_out("rewinding file failed");
614 +
615 + /* allocate space for exec times */
616 + *exec_times = calloc(*num_jobs, sizeof(*exec_times));
617 + if (!*exec_times)
618 + bail_out("couldn't allocate memory");
619 +
620 + for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
621 +
622 + skip_comments(fstream);
623 +
624 + for (cur_col = 1; cur_col < column; ++cur_col) {
625 + /* discard input until we get to the column we want */
626 + int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
627 + }
628 +
629 + /* get the desired exec. time */
630 + if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
631 + fprintf(stderr, "invalid execution time near line %d\n",
632 + cur_job);
633 + exit(EXIT_FAILURE);
634 + }
635 +
636 + skip_to_next_line(fstream);
637 + }
638 +
639 + assert(cur_job == *num_jobs);
640 + fclose(fstream);
641 +}
642 +
643 +#define NUMS 16
644 +static int num[NUMS];
645 +static char* progname;
646 +
647 +static int loop_once(void)
648 +{
649 + int i, j = 0;
650 + for (i = 0; i < NUMS; i++)
651 + j += num[i];
652 + return j;
653 +}
654 +
655 +static int loop_for(double exec_time, double emergency_exit)
656 +{
657 + double last_loop = 0, loop_start;
658 + int tmp = 0;
659 +
660 + double start = cputime();
661 + double now = cputime();
662 +
663 + while (now + last_loop < start + exec_time) {
664 + loop_start = now;
665 + tmp += loop_once();
666 + now = cputime();
667 + last_loop = now - loop_start;
668 + if (emergency_exit && wctime() > emergency_exit) {
669 + /* Oops --- this should only be possible if the execution time tracking
670 + * is broken in the LITMUS^RT kernel. */
671 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
672 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
673 + break;
674 + }
675 + }
676 +
677 + return tmp;
678 +}
679 +
680 +
681 +static void debug_delay_loop(int count)
682 +{
683 + double start, end, delay;
684 +
685 + while (count--) {
686 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
687 + start = wctime();
688 + loop_for(delay, 0);
689 + end = wctime();
690 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
691 + delay,
692 + end - start,
693 + end - start - delay,
694 + 100 * (end - start - delay) / delay);
695 + }
696 + }
697 +}
698 +
699 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
700 +{
701 + double chunk1, chunk2;
702 +
703 + if (wctime() > program_end)
704 + return 0;
705 + else {
706 + if (lock_od >= 0) {
707 + /* simulate critical section somewhere in the middle */
708 + chunk1 = drand48() * (exec_time - cs_length);
709 + chunk2 = exec_time - cs_length - chunk1;
710 +
711 + /* non-critical section */
712 + loop_for(chunk1, program_end + 1);
713 +
714 + /* critical section */
715 + litmus_lock(lock_od);
716 + loop_for(cs_length, program_end + 1);
717 + litmus_unlock(lock_od);
718 +
719 + /* non-critical section */
720 + loop_for(chunk2, program_end + 2);
721 + } else {
722 + loop_for(exec_time, program_end + 1);
723 + }
724 + sleep_next_period();
725 + return 1;
726 + }
727 +}
728 +
729 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
730 +{
731 + int i, matched;
732 + struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
733 + char** arg = (char**)malloc(sizeof(char*) * num);
734 + char *token, *saveptr;
735 + double start, end;
736 +
737 + for (i = 0; i < num; i++) {
738 + arg[i] = (char*)malloc(sizeof(char)*100);
739 + }
740 +
741 + i = 0;
742 + token = strtok_r(optarg, ":", &saveptr);
743 + while(token != NULL) {
744 + sprintf(arg[i++], "%s", token);
745 + token = strtok_r(NULL, ":", &saveptr);
746 + }
747 +
748 + *num_intervals = 0;
749 +
750 + for (i=0; i<num; i++) {
751 + matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
752 + if (matched != 2) {
753 + fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
754 + exit(5);
755 + }
756 + if (start < 0) {
757 + fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
758 + exit(5);
759 + }
760 + if (end <= start) {
761 + fprintf(stderr, "interval %s: end before start\n", arg[i]);
762 + exit(5);
763 + }
764 +
765 + slots[i].start = ms2ns(start);
766 + slots[i].end = ms2ns(end);
767 +
768 + if (i > 0 && slots[i - 1].end >= slots[i].start) {
769 + fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
770 + exit(5);
771 + }
772 +
773 + (*num_intervals)++;
774 + }
775 +
776 + for (i=0; i<num; i++) {
777 + free(arg[i]);
778 + }
779 + free(arg);
780 + return slots;
781 +}
782 +
783 +#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:k:"
784 +int main(int argc, char** argv)
785 +{
786 + int ret;
787 + lt_t wcet;
788 + lt_t period;
789 + lt_t hyperperiod;
790 + lt_t budget;
791 + double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
792 + unsigned int priority = LITMUS_NO_PRIORITY;
793 + int migrate = 0;
794 + int cluster = 0;
795 + int opt;
796 + int wait = 0;
797 + int test_loop = 0;
798 + int column = 1;
799 + const char *file = NULL;
800 + int want_enforcement = 0;
801 + double duration = 0, start = 0;
802 + double *exec_times = NULL;
803 + double scale = 1.0;
804 + task_class_t class = RT_CLASS_HARD;
805 + int cur_job = 0, num_jobs = 0;
806 + struct rt_task param;
807 + struct mc2_task mc2_param;
808 + struct reservation_config config;
809 + int res_type = PERIODIC_POLLING;
810 + int i;
811 + uint32_t mode_mask;
812 +
813 + int verbose = 0;
814 + unsigned int job_no;
815 +
816 + /* locking */
817 + int lock_od = -1;
818 + int resource_id = 0;
819 + const char *lock_namespace = "./rtspin-locks";
820 + int protocol = -1;
821 + double cs_length = 1; /* millisecond */
822 +
823 + progname = argv[0];
824 +
825 + /* default for reservation */
826 + config.id = 0;
827 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
828 + config.cpu = -1;
829 +
830 + mc2_param.crit = CRIT_LEVEL_C;
831 +
832 + hyperperiod_ms = 1000;
833 + budget_ms = 10;
834 +
835 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
836 + switch (opt) {
837 + case 'w':
838 + wait = 1;
839 + break;
840 + case 'p':
841 + cluster = atoi(optarg);
842 + migrate = 1;
843 + config.cpu = cluster;
844 + break;
845 + case 'q':
846 + priority = atoi(optarg);
847 + if (!litmus_is_valid_fixed_prio(priority))
848 + usage("Invalid priority.");
849 + break;
850 + case 'c':
851 + class = str2class(optarg);
852 + if (class == -1)
853 + usage("Unknown task class.");
854 + break;
855 + case 'e':
856 + want_enforcement = 1;
857 + break;
858 + case 'l':
859 + test_loop = 1;
860 + break;
861 + case 'o':
862 + column = atoi(optarg);
863 + break;
864 + case 'f':
865 + file = optarg;
866 + break;
867 + case 's':
868 + scale = atof(optarg);
869 + break;
870 + case 'X':
871 + protocol = lock_protocol_for_name(optarg);
872 + if (protocol < 0)
873 + usage("Unknown locking protocol specified.");
874 + break;
875 + case 'L':
876 + cs_length = atof(optarg);
877 + if (cs_length <= 0)
878 + usage("Invalid critical section length.");
879 + break;
880 + case 'Q':
881 + resource_id = atoi(optarg);
882 + if (resource_id <= 0 && strcmp(optarg, "0"))
883 + usage("Invalid resource ID.");
884 + break;
885 + case 'v':
886 + verbose = 1;
887 + break;
888 + case 'm':
889 + mc2_param.crit = atoi(optarg);
890 + if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
891 + usage("Invalid criticality level.");
892 + }
893 + res_type = PERIODIC_POLLING;
894 + break;
895 + case 'h':
896 + hyperperiod_ms = atof(optarg);
897 + break;
898 + case 'b':
899 + budget_ms = atof(optarg);
900 + break;
901 + case 'i':
902 + config.priority = atoi(optarg);
903 + break;
904 + case 'k':
905 + mode_mask = atoi(optarg);
906 + break;
907 + case ':':
908 + usage("Argument missing.");
909 + break;
910 + case '?':
911 + default:
912 + usage("Bad argument.");
913 + break;
914 + }
915 + }
916 +
917 + if (test_loop) {
918 + debug_delay_loop(1);
919 + return 0;
920 + }
921 +
922 + if (mc2_param.crit == CRIT_LEVEL_A && config.priority == LITMUS_NO_PRIORITY)
923 + usage("Bad criticailty level or priority");
924 + if (mc2_param.crit == CRIT_LEVEL_B) {
925 + config.priority = LITMUS_NO_PRIORITY;
926 + }
927 +
928 + if (mc2_param.crit == CRIT_LEVEL_C) {
929 + config.priority = LITMUS_NO_PRIORITY;
930 + config.cpu = -1;
931 + }
932 +
933 + srand(getpid());
934 +
935 + if (file) {
936 + get_exec_times(file, column, &num_jobs, &exec_times);
937 +
938 + if (argc - optind < 2)
939 + usage("Arguments missing.");
940 +
941 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
942 + /* convert the execution time to seconds */
943 + duration += exec_times[cur_job] * 0.001;
944 + }
945 + } else {
946 + /*
947 + * if we're not reading from the CSV file, then we need
948 + * three parameters
949 + */
950 + if (argc - optind < 3)
951 + usage("Arguments missing.");
952 + }
953 +
954 + wcet_ms = atof(argv[optind + 0]);
955 + period_ms = atof(argv[optind + 1]);
956 +
957 + wcet = ms2ns(wcet_ms);
958 + period = ms2ns(period_ms);
959 + budget = ms2ns(budget_ms);
960 + hyperperiod = ms2ns(hyperperiod_ms);
961 +
962 + if (wcet <= 0)
963 + usage("The worst-case execution time must be a "
964 + "positive number.");
965 + if (period <= 0)
966 + usage("The period must be a positive number.");
967 + if (!file && wcet > period) {
968 + usage("The worst-case execution time must not "
969 + "exceed the period.");
970 + }
971 +
972 + if (!file)
973 + duration = atof(argv[optind + 2]);
974 + else if (file && num_jobs > 1)
975 + duration += period_ms * 0.001 * (num_jobs - 1);
976 +
977 + if (migrate) {
978 + ret = be_migrate_to_domain(cluster);
979 + if (ret < 0)
980 + bail_out("could not migrate to target partition or cluster.");
981 + }
982 +
983 + /* reservation config */
984 + config.id = gettid();
985 +
986 + if (hyperperiod%period != 0 ) {
987 + ;//bail_out("hyperperiod must be multiple of period");
988 + }
989 +
990 + config.polling_params.budget = budget;
991 + config.polling_params.period = period;
992 + config.polling_params.offset = 0;
993 + config.polling_params.relative_deadline = 0;
994 + if (config.polling_params.budget > config.polling_params.period) {
995 + usage("The budget must not exceed the period.");
996 + }
997 + /* create a reservation */
998 + for(i = 0; i < 32; i++){
999 + if ( !( (1 << i) & mode_mask) )
1000 + continue;
1001 + config.mode = i;
1002 + ret = reservation_create(res_type, &config);
1003 + if (ret < 0) {
1004 + bail_out("failed to create reservation.");
1005 + }
1006 + }
1007 +
1008 + init_rt_task_param(¶m);
1009 + param.exec_cost = wcet;
1010 + param.period = period;
1011 + param.priority = priority;
1012 + param.cls = class;
1013 + param.release_policy = TASK_PERIODIC;
1014 + param.budget_policy = (want_enforcement) ?
1015 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
1016 + if (migrate) {
1017 + param.cpu = gettid();
1018 + }
1019 + ret = set_rt_task_param(gettid(), ¶m);
1020 +//printf("SET_RT_TASK\n");
1021 + if (ret < 0)
1022 + bail_out("could not setup rt task params");
1023 +
1024 + mc2_param.res_id = gettid();
1025 + mc2_param.mode_mask = mode_mask;
1026 + ret = set_mc2_task_param(gettid(), &mc2_param);
1027 +//printf("SET_MC2_TASK\n");
1028 + if (ret < 0)
1029 + bail_out("could not setup mc2 task params");
1030 +
1031 + init_litmus();
1032 +
1033 +//printf("INIT_LITMUS\n");
1034 + start = wctime();
1035 + ret = task_mode(LITMUS_RT_TASK);
1036 +//printf("TASK_MODE\n");
1037 + set_page_color(config.cpu);
1038 + if (ret != 0)
1039 + bail_out("could not become RT task");
1040 +
1041 + if (protocol >= 0) {
1042 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
1043 + if (lock_od < 0) {
1044 + perror("litmus_open_lock");
1045 + usage("Could not open lock.");
1046 + }
1047 + }
1048 +
1049 +
1050 + if (wait) {
1051 +//printf("BEFORE WAIT\n");
1052 + ret = wait_for_ts_release();
1053 + if (ret != 0)
1054 + bail_out("wait_for_ts_release()");
1055 + start = wctime();
1056 + }
1057 +
1058 + if (file) {
1059 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1060 + job(exec_times[cur_job] * 0.001 * scale,
1061 + start + duration,
1062 + lock_od, cs_length * 0.001);
1063 + }
1064 + } else {
1065 + do {
1066 + if (verbose) {
1067 + get_job_no(&job_no);
1068 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
1069 + job_no, (wctime() - start) * 1000);
1070 + }
1071 + } while (job(wcet_ms * 0.001 * scale, start + duration,
1072 + lock_od, cs_length * 0.001));
1073 + }
1074 + ret = task_mode(BACKGROUND_TASK);
1075 + if (ret != 0)
1076 + bail_out("could not become regular task (huh?)");
1077 +
1078 + if (file)
1079 + free(exec_times);
1080 +
1081 + reservation_destroy(gettid(), config.cpu);
1082 +
1083 + return 0;
1084 +}
1085 diff --git bin/mode_request.c bin/mode_request.c
1086 new file mode 100644
1087 index 0000000..010add1
1088 --- /dev/null
1089 +++ bin/mode_request.c
1090 @@ -0,0 +1,49 @@
1091 +#include <stdio.h>
1092 +#include <stdlib.h>
1093 +#include <errno.h>
1094 +#include <sys/syscall.h>
1095 +#include <unistd.h>
1096 +#include <signal.h>
1097 +
1098 +#include "litmus.h"
1099 +
1100 +#define __NR_request_mode 408
1101 +
1102 +static int keep_running;
1103 +
1104 +void sig_handler(int signum) {
1105 + int ret;
1106 +
1107 + usleep(100000);
1108 + ret = syscall(__NR_request_mode, 0);
1109 + usleep(1000000);
1110 + keep_running = 0;
1111 +
1112 +}
1113 +
1114 +int main(int argc, char* argv[]) {
1115 + int ret, req_mode = 0;
1116 + int interval_ms;
1117 + int max_mode = 9;
1118 +
1119 + signal(SIGINT, sig_handler);
1120 +
1121 + if (argc == 2) {
1122 + max_mode = atoi(argv[1]);
1123 + printf("%d\n", max_mode);
1124 + }
1125 +
1126 + keep_running = 1;
1127 + usleep(500000); // ms
1128 + while (keep_running) {
1129 + req_mode = (req_mode%max_mode)+1;
1130 +
1131 + if (keep_running)
1132 + ret = syscall(__NR_request_mode, req_mode);
1133 + interval_ms = rand() % 1000 - 500; // ms
1134 + usleep(1000*(1000 + interval_ms));
1135 + }
1136 +
1137 +
1138 + return ret;
1139 +}
1140 diff --git bin/mode_skeleton.c bin/mode_skeleton.c
1141 new file mode 100644
1142 index 0000000..cae5851
1143 --- /dev/null
1144 +++ bin/mode_skeleton.c
1145 @@ -0,0 +1,256 @@
1146 +#include <sys/time.h>
1147 +#include <sys/mman.h>
1148 +
1149 +#include <stdio.h>
1150 +#include <stdlib.h>
1151 +#include <unistd.h>
1152 +#include <time.h>
1153 +#include <string.h>
1154 +#include <assert.h>
1155 +#include <limits.h>
1156 +
1157 +
1158 +#include "litmus.h"
1159 +#include "common.h"
1160 +
1161 +extern int main_job(void);
1162 +
1163 +static char* progname;
1164 +int loops = 10;
1165 +//struct timeval t1, t2;
1166 +
1167 +static void usage(char *error) {
1168 + fprintf(stderr, "Error: %s\n", error);
1169 + fprintf(stderr,
1170 + "Usage:\n"
1171 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
1172 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
1173 + " rt_spin -l\n"
1174 + "\n"
1175 + "COMMON-OPTS = [-w] [-s SCALE]\n"
1176 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
1177 + "\n"
1178 + "WCET and PERIOD are microseconds, DURATION is seconds.\n");
1179 + exit(EXIT_FAILURE);
1180 +}
1181 +
1182 +inline unsigned long get_cyclecount (void)
1183 +{
1184 + unsigned long value;
1185 + // Read CCNT Register
1186 + asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
1187 + return value;
1188 +}
1189 +
1190 +static int job(double exec_time, double program_end)
1191 +{
1192 + if (wctime() > program_end)
1193 + return 0;
1194 + else {
1195 + register int iter = 0;
1196 + //register unsigned long t;
1197 + //t = get_cyclecount();
1198 + //gettimeofday(&t1, NULL);
1199 + while (iter++ < loops) {
1200 + main_job();
1201 + }
1202 + //t = get_cyclecount() - t;
1203 + //printf("%ld cycles\n", t);
1204 + //gettimeofday(&t2, NULL);
1205 + //printf("%ld us\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec)));
1206 + sleep_next_period();
1207 + return 1;
1208 + }
1209 +}
1210 +
1211 +#define OPTSTR "p:wves:l:m:i:b:k:"
1212 +int main(int argc, char** argv)
1213 +{
1214 + int ret;
1215 + lt_t wcet;
1216 + lt_t period;
1217 + lt_t budget;
1218 + double wcet_us, period_us, budget_us;
1219 + unsigned int priority = LITMUS_NO_PRIORITY;
1220 + int migrate = 0;
1221 + int cluster = 0;
1222 + int opt;
1223 + int wait = 0;
1224 + int want_enforcement = 0;
1225 + double duration = 0, start = 0;
1226 + double scale = 1.0;
1227 + task_class_t class = RT_CLASS_HARD;
1228 + struct rt_task param;
1229 + struct mc2_task mc2_param;
1230 + struct reservation_config config;
1231 + int res_type = PERIODIC_POLLING;
1232 + uint32_t mode_mask = (1 << 0);
1233 + int i;
1234 + unsigned int job_no;
1235 +
1236 +
1237 + progname = argv[0];
1238 +
1239 + /* default for reservation */
1240 + config.id = 0;
1241 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
1242 + config.cpu = -1;
1243 +
1244 + mc2_param.crit = CRIT_LEVEL_C;
1245 +
1246 + budget_us = 10000;
1247 +
1248 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1249 + switch (opt) {
1250 + case 'w':
1251 + wait = 1;
1252 + break;
1253 + case 'p':
1254 + cluster = atoi(optarg);
1255 + migrate = 1;
1256 + config.cpu = cluster;
1257 + break;
1258 + case 'e':
1259 + want_enforcement = 1;
1260 + break;
1261 + case 's':
1262 + scale = atof(optarg);
1263 + break;
1264 + case 'l':
1265 + loops = atoi(optarg);
1266 + break;
1267 + case 'm':
1268 + mc2_param.crit = atoi(optarg);
1269 + if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
1270 + usage("Invalid criticality level.");
1271 + }
1272 + res_type = PERIODIC_POLLING;
1273 + break;
1274 + case 'b':
1275 + budget_us = atof(optarg);
1276 + break;
1277 + case 'i':
1278 + config.priority = atoi(optarg);
1279 + break;
1280 + case 'k':
1281 + mode_mask = atoi(optarg);
1282 + case ':':
1283 + usage("Argument missing.");
1284 + break;
1285 + case '?':
1286 + default:
1287 + usage("Bad argument.");
1288 + break;
1289 + }
1290 + }
1291 +
1292 + if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
1293 + usage("Bad criticailty level or priority");
1294 +
1295 + if (argc - optind < 3)
1296 + usage("Arguments missing.");
1297 +
1298 + wcet_us = atof(argv[optind + 0]);
1299 + period_us = atof(argv[optind + 1]);
1300 +
1301 + wcet = us2ns(wcet_us);
1302 + period = us2ns(period_us);
1303 + budget = us2ns(budget_us);
1304 +
1305 + if (wcet <= 0)
1306 + usage("The worst-case execution time must be a "
1307 + "positive number.");
1308 + if (period <= 0)
1309 + usage("The period must be a positive number.");
1310 + if (wcet > period) {
1311 + usage("The worst-case execution time must not "
1312 + "exceed the period.");
1313 + }
1314 +
1315 + duration = atof(argv[optind + 2]);
1316 +
1317 + if (migrate) {
1318 + ret = be_migrate_to_domain(cluster);
1319 + if (ret < 0)
1320 + bail_out("could not migrate to target partition or cluster.");
1321 + }
1322 +
1323 + /* reservation config */
1324 + config.id = gettid();
1325 +
1326 + config.polling_params.budget = budget;
1327 + config.polling_params.period = period;
1328 + config.polling_params.offset = 0;
1329 + config.polling_params.relative_deadline = 0;
1330 + if (config.polling_params.budget > config.polling_params.period) {
1331 + usage("The budget must not exceed the period.");
1332 + }
1333 +
1334 + /* create reservations */
1335 + for(i = 0; i < 32; i++){
1336 + if ( !((1 << i) & mode_mask ) )
1337 + continue;
1338 + config.mode = i;
1339 + ret = reservation_create(res_type, &config);
1340 + if (ret < 0) {
1341 + bail_out("failed to create reservation.");
1342 + }
1343 + }
1344 +
1345 + init_rt_task_param(¶m);
1346 + param.exec_cost = wcet;
1347 + param.period = period;
1348 + param.priority = priority;
1349 + param.cls = class;
1350 + param.release_policy = TASK_PERIODIC;
1351 + param.budget_policy = (want_enforcement) ?
1352 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
1353 + if (migrate) {
1354 + param.cpu = gettid();
1355 + }
1356 + ret = set_rt_task_param(gettid(), ¶m);
1357 +
1358 + if (ret < 0)
1359 + bail_out("could not setup rt task params");
1360 +
1361 + mc2_param.res_id = gettid();
1362 + mc2_param.mode_mask = mode_mask;
1363 + ret = set_mc2_task_param(gettid(), &mc2_param);
1364 +//printf("SET_MC2_TASK\n");
1365 + if (ret < 0)
1366 + bail_out("could not setup mc2 task params");
1367 +
1368 + init_litmus();
1369 +//printf("CALL\n");
1370 + if (mc2_param.crit == CRIT_LEVEL_C)
1371 + set_page_color(8);
1372 + else if (mc2_param.crit < CRIT_LEVEL_C)
1373 + set_page_color(config.cpu*2 + mc2_param.crit);
1374 +//printf("CALL\n");
1375 +
1376 +//printf("INIT_LITMUS\n");
1377 + start = wctime();
1378 + ret = task_mode(LITMUS_RT_TASK);
1379 +//printf("TASK_MODE\n");
1380 + if (ret != 0)
1381 + bail_out("could not become RT task");
1382 +
1383 +
1384 + if (wait) {
1385 +//printf("BEFORE WAIT\n");
1386 + ret = wait_for_ts_release();
1387 + if (ret != 0)
1388 + bail_out("wait_for_ts_release()");
1389 + start = wctime();
1390 + }
1391 +
1392 + while (job(wcet_us * 0.000001 * scale, start + duration)) {};
1393 +
1394 + ret = task_mode(BACKGROUND_TASK);
1395 + if (ret != 0)
1396 + bail_out("could not become regular task (huh?)");
1397 +
1398 + reservation_destroy(gettid(), config.cpu);
1399 + printf("%s/%d finished.\n",progname, gettid());
1400 + return 0;
1401 +}
1402 diff --git bin/mtdag.c bin/mtdag.c
1403 new file mode 100644
1404 index 0000000..adf6d8d
1405 --- /dev/null
1406 +++ bin/mtdag.c
1407 @@ -0,0 +1,291 @@
1408 +/* based_mt_task.c -- A basic multi-threaded real-time task skeleton.
1409 + *
1410 + * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT
1411 + * real-time task. Familiarity with the single threaded example (base_task.c)
1412 + * is assumed.
1413 + *
1414 + * Currently, liblitmus still lacks automated support for real-time
1415 + * tasks, but internaly it is thread-safe, and thus can be used together
1416 + * with pthreads.
1417 + */
1418 +
1419 +#include <stdio.h>
1420 +#include <stdlib.h>
1421 +#include <string.h>
1422 +#include <limits.h>
1423 +#include <sys/mman.h>
1424 +#include <sys/stat.h>
1425 +#include <fcntl.h>
1426 +#include <unistd.h>
1427 +/* Include gettid() */
1428 +#include <sys/types.h>
1429 +
1430 +/* Include threading support. */
1431 +#include <pthread.h>
1432 +
1433 +/* Include the LITMUS^RT API.*/
1434 +#include "litmus.h"
1435 +#include "color_shm.h"
1436 +#include "asm/cycles.h"
1437 +
1438 +#define PERIOD 100
1439 +#define RELATIVE_DEADLINE 100
1440 +#define EXEC_COST 10
1441 +
1442 +/* Let's create 10 threads in the example,
1443 + * for a total utilization of 1.
1444 + */
1445 +#define NUM_THREADS 2
1446 +
1447 +/* The information passed to each thread. Could be anything. */
1448 +struct thread_context {
1449 + int id;
1450 + int cpu;
1451 + int job_no;
1452 + char* shm1;
1453 + char* shm2;
1454 + char* shm3;
1455 +};
1456 +
1457 +/* The real-time thread program. Doesn't have to be the same for
1458 + * all threads. Here, we only have one that will invoke job().
1459 + */
1460 +void* rt_thread(void *tcontext);
1461 +
1462 +/* Declare the periodically invoked job.
1463 + * Returns 1 -> task should exit.
1464 + * 0 -> task should continue.
1465 + */
1466 +int job(struct thread_context *tcx);
1467 +
1468 +
1469 +/* Catch errors.
1470 + */
1471 +#define CALL( exp ) do { \
1472 + int ret; \
1473 + ret = exp; \
1474 + if (ret != 0) \
1475 + fprintf(stderr, "%s failed: %m\n", #exp);\
1476 + else \
1477 + fprintf(stderr, "%s ok.\n", #exp); \
1478 + } while (0)
1479 +
1480 +
1481 +/* Basic setup is the same as in the single-threaded example. However,
1482 + * we do some thread initiliazation first before invoking the job.
1483 + */
1484 +int main(int argc, char** argv)
1485 +{
1486 + int i;
1487 + struct thread_context ctx[NUM_THREADS];
1488 + pthread_t task[NUM_THREADS];
1489 + char *shm1;
1490 + char *shm2;
1491 + char *shm3;
1492 + struct color_ioctl_cmd shm_info;
1493 + struct color_ioctl_offset shm_offset;
1494 + /* The task is in background mode upon startup. */
1495 +
1496 +
1497 + /*****
1498 + * 1) Command line paramter parsing would be done here.
1499 + */
1500 +
1501 +
1502 +
1503 + /*****
1504 + * 2) Work environment (e.g., global data structures, file data, etc.) would
1505 + * be setup here.
1506 + */
1507 +
1508 + shm_info.color = 0x00000001;
1509 + shm_info.bank = 0x00000020;
1510 + shm_offset.offset = 0;
1511 + shm_offset.lock = 1;
1512 +
1513 + shm1 = (char*)color_mmap(1024, shm_info, shm_offset);
1514 + if (!shm1) {
1515 + printf("color mmap failed.\n");
1516 + exit(-1);
1517 + }
1518 + else {
1519 + printf("Mapped vaddr = %p\n", shm1);
1520 + }
1521 +
1522 + shm_info.color = 0x00000003;
1523 + shm_offset.offset = 1024;
1524 + shm2 = (char*)color_mmap(4096, shm_info, shm_offset);
1525 + if (!shm2) {
1526 + printf("color mmap failed.\n");
1527 + exit(-1);
1528 + }
1529 + else {
1530 + printf("Mapped vaddr = %p\n", shm2);
1531 + }
1532 +
1533 + mlockall(MCL_CURRENT | MCL_FUTURE);
1534 + /*****
1535 + * 3) Initialize LITMUS^RT.
1536 + * Task parameters will be specified per thread.
1537 + */
1538 + init_litmus();
1539 +
1540 +
1541 + /*****
1542 + * 4) Launch threads.
1543 + */
1544 + for (i = 0; i < NUM_THREADS; i++) {
1545 + ctx[i].id = i;
1546 + ctx[i].cpu = 0;
1547 + ctx[i].job_no = 0;
1548 + ctx[i].shm1 = shm1;
1549 + ctx[i].shm3 = shm2;
1550 + ctx[i].shm2 = shm3;
1551 + pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
1552 + }
1553 +
1554 +
1555 + /*****
1556 + * 5) Wait for RT threads to terminate.
1557 + */
1558 + for (i = 0; i < NUM_THREADS; i++)
1559 + pthread_join(task[i], NULL);
1560 +
1561 +
1562 + /*****
1563 + * 6) Clean up, maybe print results and stats, and exit.
1564 + */
1565 + return 0;
1566 +}
1567 +
1568 +
1569 +
1570 +/* A real-time thread is very similar to the main function of a single-threaded
1571 + * real-time app. Notice, that init_rt_thread() is called to initialized per-thread
1572 + * data structures of the LITMUS^RT user space libary.
1573 + */
1574 +void* rt_thread(void *tcontext)
1575 +{
1576 + int do_exit;
1577 + struct thread_context *ctx = (struct thread_context *) tcontext;
1578 + struct rt_task param;
1579 + int ret;
1580 + struct mc2_task mc2_param;
1581 + struct reservation_config res_config;
1582 +
1583 + /* Set up task parameters */
1584 + init_rt_task_param(¶m);
1585 + param.exec_cost = ms2ns(EXEC_COST);
1586 + param.period = ms2ns(PERIOD);
1587 + param.relative_deadline = ms2ns(RELATIVE_DEADLINE*(ctx->id+1));
1588 +
1589 + /* What to do in the case of budget overruns? */
1590 + param.budget_policy = NO_ENFORCEMENT;
1591 +
1592 + /* The task class parameter is ignored by most plugins. */
1593 + param.cls = RT_CLASS_SOFT;
1594 +
1595 + /* The priority parameter is only used by fixed-priority plugins. */
1596 + param.priority = LITMUS_LOWEST_PRIORITY;
1597 +
1598 + /* Make presence visible. */
1599 + printf("RT Thread %d active.\n", ctx->id);
1600 +
1601 + /* reservation config */
1602 + res_config.id = gettid();
1603 + res_config.polling_params.budget = ms2ns(EXEC_COST+1);
1604 + res_config.polling_params.period = param.period;
1605 + res_config.polling_params.offset = 0;
1606 + res_config.polling_params.relative_deadline = 0;
1607 + res_config.priority = LITMUS_MAX_PRIORITY;
1608 + res_config.cpu = ctx->cpu;
1609 + mc2_param.crit = CRIT_LEVEL_A;
1610 + mc2_param.res_id = gettid();
1611 + /*****
1612 + * 1) Initialize real-time settings.
1613 + */
1614 + CALL( init_rt_thread() );
1615 +
1616 + ret = reservation_create(PERIODIC_POLLING, &res_config);
1617 + if (ret < 0) {
1618 + printf("reservation failed.\n");
1619 + return NULL;
1620 + }
1621 +
1622 + /* To specify a partition, do
1623 + *
1624 + * param.cpu = CPU;
1625 + * be_migrate_to(CPU);
1626 + *
1627 + * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
1628 + * set_rt_task_param().
1629 + */
1630 + param.cpu = ctx->cpu;
1631 + ret = be_migrate_to_cpu(ctx->cpu);
1632 + if (ret < 0) {
1633 + printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
1634 + return NULL;
1635 + }
1636 + CALL( set_rt_task_param(gettid(), ¶m) );
1637 +
1638 + CALL( set_mc2_task_param(gettid(), &mc2_param) );
1639 + /*****
1640 + * 2) Transition to real-time mode.
1641 + */
1642 + CALL( task_mode(LITMUS_RT_TASK) );
1643 +
1644 + /* The task is now executing as a real-time task if the call didn't fail.
1645 + */
1646 +
1647 +
1648 +
1649 + /*****
1650 + * 3) Invoke real-time jobs.
1651 + */
1652 + do {
1653 + /* Wait until the next job is released. */
1654 + sleep_next_period();
1655 + /* Invoke job. */
1656 + do_exit = job(ctx);
1657 + } while (!do_exit);
1658 +
1659 +
1660 +
1661 + /*****
1662 + * 4) Transition to background mode.
1663 + */
1664 + CALL( task_mode(BACKGROUND_TASK) );
1665 + reservation_destroy(gettid(), res_config.cpu);
1666 +
1667 + return NULL;
1668 +}
1669 +
1670 +
1671 +
1672 +int job(struct thread_context *tcx)
1673 +{
1674 + int i;
1675 + char* buf1 = tcx->shm1;
1676 + char* buf2 = tcx->shm2;
1677 + char* buf3 = tcx->shm3;
1678 + char tmp = 0;
1679 + /* Do real-time calculation. */
1680 + printf("Task %d Job %d executinig\n", tcx->id, tcx->job_no);
1681 +
1682 + if (tcx->id == 0) {
1683 + printf("READ\n");
1684 + for (i=0; i<600; i++) {
1685 + char t = buf1[i];
1686 + printf("%x ", t);
1687 + }
1688 + printf("\n");
1689 +
1690 + ;
1691 + }
1692 + //test_call(0);
1693 + tcx->job_no++;
1694 + if (tcx->job_no == 10)
1695 + return 1;
1696 + /* Don't exit. */
1697 + return 0;
1698 +}
1699 diff --git bin/resctrl.c bin/resctrl.c
1700 new file mode 100644
1701 index 0000000..63b5054
1702 --- /dev/null
1703 +++ bin/resctrl.c
1704 @@ -0,0 +1,242 @@
1705 +#include <stdio.h>
1706 +#include <stdlib.h>
1707 +#include <string.h>
1708 +#include <unistd.h>
1709 +#include <limits.h>
1710 +#include <signal.h>
1711 +
1712 +#include <sched.h>
1713 +
1714 +#include "litmus.h"
1715 +#include "common.h"
1716 +
1717 +const char *usage_msg =
1718 + "Usage: resctrl OPTIONS [INTERVAL-START,INTERVAL-END]*\n"
1719 + " -n ID create new reservation with id ID\n"
1720 + " -a PID attach already-running process PID to reservation\n"
1721 + " -r ID specify which reservation to attach to (not needed with -n)\n"
1722 + " -t TYPE type of reservation (polling-periodic, polling-sporadic, table-driven)\n"
1723 + " -c CPU physical partition or cluster to assign to\n"
1724 + " -b BUDGET polling reservation budget (in ms, default: 10ms)\n"
1725 + " -p PERIOD polling reservation period (in ms, default: 100ms)\n"
1726 + " -d DEADLINE relative deadline, implicit by default (in ms)\n"
1727 + " -o OFFSET offset (also known as phase), zero by default (in ms)\n"
1728 + " -q PRIORITY priority to use (EDF by default, highest priority = 1)\n"
1729 + " -m MAJOR-CYCLE major cycle length (in ms, for table-driven reservations) \n"
1730 + "\n";
1731 +
1732 +void usage(char *error) {
1733 + fprintf(stderr, "%s\n%s", error, usage_msg);
1734 + exit(1);
1735 +}
1736 +
1737 +
1738 +static void attach_task(int attach_pid, struct reservation_config *config)
1739 +{
1740 + int ret;
1741 + struct rt_task param;
1742 + struct sched_param linux_param;
1743 +
1744 + ret = be_migrate_thread_to_cpu(attach_pid, config->cpu);
1745 + if (ret < 0) {
1746 + fprintf(stderr, "failed to migrate task %d to CPU %d\n",
1747 + attach_pid, config->cpu);
1748 + exit(4);
1749 + }
1750 +
1751 + init_rt_task_param(¶m);
1752 + /* dummy values */
1753 + param.exec_cost = ms2ns(100);
1754 + param.period = ms2ns(100);
1755 + /* specify reservation as "virtual" CPU */
1756 + param.cpu = config->id;
1757 +
1758 + ret = set_rt_task_param(attach_pid, ¶m);
1759 + if (ret < 0) {
1760 + fprintf(stderr, "failed to set RT task parameters for task %d (%m)\n",
1761 + attach_pid);
1762 + exit(2);
1763 + }
1764 +
1765 + linux_param.sched_priority = 0;
1766 + ret = sched_setscheduler(attach_pid, SCHED_LITMUS, &linux_param);
1767 + if (ret < 0) {
1768 + fprintf(stderr, "failed to transition task %d to LITMUS^RT class (%m)\n",
1769 + attach_pid);
1770 + exit(3);
1771 + }
1772 +}
1773 +
1774 +static struct lt_interval* parse_td_intervals(int argc, char** argv,
1775 + unsigned int *num_intervals, lt_t major_cycle)
1776 +{
1777 + int i, matched;
1778 + struct lt_interval *slots = malloc(sizeof(slots[0]) * argc);
1779 + double start, end;
1780 +
1781 + *num_intervals = 0;
1782 + for (i = 0; i < argc; i++) {
1783 + matched = sscanf(argv[i], "[%lf,%lf]", &start, &end);
1784 + if (matched != 2) {
1785 + fprintf(stderr, "could not parse '%s' as interval\n", argv[i]);
1786 + exit(5);
1787 + }
1788 + if (start < 0) {
1789 + fprintf(stderr, "interval %s: must not start before zero\n", argv[i]);
1790 + exit(5);
1791 + }
1792 + if (end <= start) {
1793 + fprintf(stderr, "interval %s: end before start\n", argv[i]);
1794 + exit(5);
1795 + }
1796 +
1797 + slots[i].start = ms2ns(start);
1798 + slots[i].end = ms2ns(end);
1799 +
1800 + if (i > 0 && slots[i - 1].end >= slots[i].start) {
1801 + fprintf(stderr, "interval %s: overlaps with previous interval\n", argv[i]);
1802 + exit(5);
1803 + }
1804 +
1805 + if (slots[i].end >= major_cycle) {
1806 + fprintf(stderr, "interval %s: exceeds major cycle length\n", argv[i]);
1807 + exit(5);
1808 + }
1809 +
1810 + (*num_intervals)++;
1811 + }
1812 +
1813 + return slots;
1814 +}
1815 +
1816 +#define OPTSTR "n:a:r:t:c:b:p:d:o:q:m:h"
1817 +
1818 +int main(int argc, char** argv)
1819 +{
1820 + int ret, opt;
1821 + double budget_ms, period_ms, offset_ms, deadline_ms, major_cycle_ms;
1822 + int create_new = 0;
1823 + int attach_pid = 0;
1824 + int res_type = SPORADIC_POLLING;
1825 +
1826 + struct reservation_config config;
1827 +
1828 + /* Reasonable defaults */
1829 + offset_ms = 0;
1830 + deadline_ms = 0;
1831 + budget_ms = 10;
1832 + period_ms = 100;
1833 + major_cycle_ms = 1000;
1834 +
1835 + config.id = 0;
1836 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
1837 + config.cpu = 0;
1838 +
1839 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1840 + switch (opt) {
1841 + case 'b':
1842 + budget_ms = atof(optarg);
1843 + break;
1844 + case 'p':
1845 + period_ms = atof(optarg);
1846 + break;
1847 + case 'd':
1848 + deadline_ms = atof(optarg);
1849 + if (deadline_ms <= 0) {
1850 + usage("The relative deadline must be a positive"
1851 + " number.");
1852 + }
1853 + break;
1854 + case 'o':
1855 + offset_ms = atof(optarg);
1856 + break;
1857 + case 'm':
1858 + major_cycle_ms = atof(optarg);
1859 + break;
1860 +
1861 + case 'q':
1862 + config.priority = atoi(optarg);
1863 + if (!config.priority)
1864 + usage("-q: invalid priority");
1865 + break;
1866 + case 'c':
1867 + config.cpu = atoi(optarg);
1868 + break;
1869 +
1870 + case 'n':
1871 + create_new = 1;
1872 + config.id = atoi(optarg);
1873 + break;
1874 + case 'a':
1875 + attach_pid = atoi(optarg);
1876 + if (!attach_pid)
1877 + usage("-a: invalid PID");
1878 + break;
1879 +
1880 + case 'r':
1881 + config.id = atoi(optarg);
1882 + break;
1883 +
1884 + case 't':
1885 + if (strcmp(optarg, "polling-periodic") == 0) {
1886 + res_type = PERIODIC_POLLING;
1887 + } else if (strcmp(optarg, "polling-sporadic") == 0) {
1888 + res_type = SPORADIC_POLLING;
1889 + } else if (strcmp(optarg, "table-driven") == 0) {
1890 + res_type = TABLE_DRIVEN;
1891 + /* Default for table-driven reservations to
1892 + * maximum priority. EDF has not meaning for
1893 + * table-driven reservations. */
1894 + if (config.priority == LITMUS_NO_PRIORITY)
1895 + config.priority = LITMUS_HIGHEST_PRIORITY;
1896 + } else {
1897 + usage("Unknown reservation type.");
1898 + }
1899 + break;
1900 +
1901 + case 'h':
1902 + usage("");
1903 + break;
1904 + case ':':
1905 + usage("Argument missing.");
1906 + break;
1907 + case '?':
1908 + default:
1909 + usage("Bad argument.");
1910 + break;
1911 + }
1912 + }
1913 +
1914 + if (res_type != TABLE_DRIVEN) {
1915 + config.polling_params.budget = ms2ns(budget_ms);
1916 + config.polling_params.period = ms2ns(period_ms);
1917 + config.polling_params.offset = ms2ns(offset_ms);
1918 + config.polling_params.relative_deadline = ms2ns(deadline_ms);
1919 + if (config.polling_params.budget > config.polling_params.period) {
1920 + usage("The budget must not exceed the period.");
1921 + }
1922 + } else {
1923 + config.table_driven_params.major_cycle_length = ms2ns(major_cycle_ms);
1924 + argc -= optind;
1925 + argv += optind;
1926 + config.table_driven_params.intervals = parse_td_intervals(
1927 + argc, argv, &config.table_driven_params.num_intervals,
1928 + config.table_driven_params.major_cycle_length);
1929 + if (!config.table_driven_params.num_intervals)
1930 + usage("Table-driven reservations require at least one interval to be specified.");
1931 + }
1932 +
1933 + if (create_new) {
1934 + ret = reservation_create(res_type, &config);
1935 + if (ret < 0) {
1936 + fprintf(stderr, "failed to create reservation %u (%m)\n",
1937 + config.id);
1938 + exit(1);
1939 + }
1940 + }
1941 +
1942 + if (attach_pid)
1943 + attach_task(attach_pid, &config);
1944 +
1945 + return 0;
1946 +}
1947 diff --git bin/rt_compress.c bin/rt_compress.c
1948 new file mode 100644
1949 index 0000000..9647854
1950 --- /dev/null
1951 +++ bin/rt_compress.c
1952 @@ -0,0 +1,283 @@
1953 +#include <sys/time.h>
1954 +#include <sys/mman.h>
1955 +
1956 +#include <stdio.h>
1957 +#include <stdlib.h>
1958 +#include <unistd.h>
1959 +#include <time.h>
1960 +#include <string.h>
1961 +#include <assert.h>
1962 +#include <limits.h>
1963 +
1964 +
1965 +#include "litmus.h"
1966 +#include "common.h"
1967 +
1968 +extern int main_job(void);
1969 +static char* progname;
1970 +
1971 +static void usage(char *error) {
1972 + fprintf(stderr, "Error: %s\n", error);
1973 + fprintf(stderr,
1974 + "Usage:\n"
1975 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
1976 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
1977 + " rt_spin -l\n"
1978 + "\n"
1979 + "COMMON-OPTS = [-w] [-s SCALE]\n"
1980 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
1981 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
1982 + "\n"
1983 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
1984 + "CRITICAL SECTION LENGTH is in milliseconds.\n");
1985 + exit(EXIT_FAILURE);
1986 +}
1987 +
1988 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
1989 +{
1990 + if (wctime() > program_end)
1991 + return 0;
1992 + else {
1993 + main_job();
1994 + sleep_next_period();
1995 + return 1;
1996 + }
1997 +}
1998 +
1999 +#define OPTSTR "p:c:wves:q:X:L:Q:vh:m:i:b:"
2000 +int main(int argc, char** argv)
2001 +{
2002 + int ret;
2003 + lt_t wcet;
2004 + lt_t period;
2005 + lt_t hyperperiod;
2006 + lt_t budget;
2007 + double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
2008 + unsigned int priority = LITMUS_NO_PRIORITY;
2009 + int migrate = 0;
2010 + int cluster = 0;
2011 + int opt;
2012 + int wait = 0;
2013 + int want_enforcement = 0;
2014 + double duration = 0, start = 0;
2015 + double scale = 1.0;
2016 + task_class_t class = RT_CLASS_HARD;
2017 + struct rt_task param;
2018 + struct mc2_task mc2_param;
2019 + struct reservation_config config;
2020 + int res_type = PERIODIC_POLLING;
2021 +
2022 + int verbose = 0;
2023 + unsigned int job_no;
2024 +
2025 + /* locking */
2026 + int lock_od = -1;
2027 + int resource_id = 0;
2028 + const char *lock_namespace = "./rtspin-locks";
2029 + int protocol = -1;
2030 + double cs_length = 1; /* millisecond */
2031 +
2032 + progname = argv[0];
2033 +
2034 + /* default for reservation */
2035 + config.id = 0;
2036 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
2037 + config.cpu = -1;
2038 +
2039 + mc2_param.crit = CRIT_LEVEL_C;
2040 +
2041 + hyperperiod_ms = 1000;
2042 + budget_ms = 10;
2043 +
2044 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
2045 + switch (opt) {
2046 + case 'w':
2047 + wait = 1;
2048 + break;
2049 + case 'p':
2050 + cluster = atoi(optarg);
2051 + migrate = 1;
2052 + config.cpu = cluster;
2053 + break;
2054 + case 'q':
2055 + priority = atoi(optarg);
2056 + if (!litmus_is_valid_fixed_prio(priority))
2057 + usage("Invalid priority.");
2058 + break;
2059 + case 'c':
2060 + class = str2class(optarg);
2061 + if (class == -1)
2062 + usage("Unknown task class.");
2063 + break;
2064 + case 'e':
2065 + want_enforcement = 1;
2066 + break;
2067 + case 's':
2068 + scale = atof(optarg);
2069 + break;
2070 + case 'X':
2071 + protocol = lock_protocol_for_name(optarg);
2072 + if (protocol < 0)
2073 + usage("Unknown locking protocol specified.");
2074 + break;
2075 + case 'L':
2076 + cs_length = atof(optarg);
2077 + if (cs_length <= 0)
2078 + usage("Invalid critical section length.");
2079 + break;
2080 + case 'Q':
2081 + resource_id = atoi(optarg);
2082 + if (resource_id <= 0 && strcmp(optarg, "0"))
2083 + usage("Invalid resource ID.");
2084 + break;
2085 + case 'v':
2086 + verbose = 1;
2087 + break;
2088 + case 'm':
2089 + mc2_param.crit = atoi(optarg);
2090 + if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
2091 + usage("Invalid criticality level.");
2092 + }
2093 + res_type = PERIODIC_POLLING;
2094 + break;
2095 + case 'h':
2096 + hyperperiod_ms = atof(optarg);
2097 + break;
2098 + case 'b':
2099 + budget_ms = atof(optarg);
2100 + break;
2101 + case 'i':
2102 + config.priority = atoi(optarg);
2103 + break;
2104 + case ':':
2105 + usage("Argument missing.");
2106 + break;
2107 + case '?':
2108 + default:
2109 + usage("Bad argument.");
2110 + break;
2111 + }
2112 + }
2113 +
2114 + if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
2115 + usage("Bad criticailty level or priority");
2116 +
2117 + if (argc - optind < 3)
2118 + usage("Arguments missing.");
2119 +
2120 + wcet_ms = atof(argv[optind + 0]);
2121 + period_ms = atof(argv[optind + 1]);
2122 +
2123 + wcet = ms2ns(wcet_ms);
2124 + period = ms2ns(period_ms);
2125 + budget = ms2ns(budget_ms);
2126 + hyperperiod = ms2ns(hyperperiod_ms);
2127 +
2128 + if (wcet <= 0)
2129 + usage("The worst-case execution time must be a "
2130 + "positive number.");
2131 + if (period <= 0)
2132 + usage("The period must be a positive number.");
2133 + if (wcet > period) {
2134 + usage("The worst-case execution time must not "
2135 + "exceed the period.");
2136 + }
2137 +
2138 + duration = atof(argv[optind + 2]);
2139 +
2140 + if (migrate) {
2141 + ret = be_migrate_to_domain(cluster);
2142 + if (ret < 0)
2143 + bail_out("could not migrate to target partition or cluster.");
2144 + }
2145 +
2146 + /* reservation config */
2147 + config.id = gettid();
2148 +
2149 + if (hyperperiod%period != 0 ) {
2150 + ;//bail_out("hyperperiod must be multiple of period");
2151 + }
2152 +
2153 + config.polling_params.budget = budget;
2154 + config.polling_params.period = period;
2155 + config.polling_params.offset = 0;
2156 + config.polling_params.relative_deadline = 0;
2157 + if (config.polling_params.budget > config.polling_params.period) {
2158 + usage("The budget must not exceed the period.");
2159 + }
2160 +
2161 + /* create a reservation */
2162 + ret = reservation_create(res_type, &config);
2163 + if (ret < 0) {
2164 + bail_out("failed to create reservation.");
2165 + }
2166 +
2167 + init_rt_task_param(¶m);
2168 + param.exec_cost = wcet;
2169 + param.period = period;
2170 + param.priority = priority;
2171 + param.cls = class;
2172 + param.release_policy = TASK_PERIODIC;
2173 + param.budget_policy = (want_enforcement) ?
2174 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
2175 + if (migrate) {
2176 + param.cpu = gettid();
2177 + }
2178 + ret = set_rt_task_param(gettid(), ¶m);
2179 +
2180 + if (ret < 0)
2181 + bail_out("could not setup rt task params");
2182 +
2183 + mc2_param.res_id = gettid();
2184 + ret = set_mc2_task_param(gettid(), &mc2_param);
2185 +//printf("SET_MC2_TASK\n");
2186 + if (ret < 0)
2187 + bail_out("could not setup mc2 task params");
2188 +
2189 + init_litmus();
2190 +//printf("CALL\n");
2191 + //set_page_color(config.cpu);
2192 +//printf("CALL\n");
2193 +
2194 +//printf("INIT_LITMUS\n");
2195 + start = wctime();
2196 + ret = task_mode(LITMUS_RT_TASK);
2197 +//printf("TASK_MODE\n");
2198 + if (ret != 0)
2199 + bail_out("could not become RT task");
2200 +
2201 + if (protocol >= 0) {
2202 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
2203 + if (lock_od < 0) {
2204 + perror("litmus_open_lock");
2205 + usage("Could not open lock.");
2206 + }
2207 + }
2208 +
2209 +
2210 + if (wait) {
2211 +//printf("BEFORE WAIT\n");
2212 + ret = wait_for_ts_release();
2213 + if (ret != 0)
2214 + bail_out("wait_for_ts_release()");
2215 + start = wctime();
2216 + }
2217 +
2218 + do {
2219 + if (verbose) {
2220 + get_job_no(&job_no);
2221 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
2222 + job_no, (wctime() - start) * 1000);
2223 + }
2224 + } while (job(wcet_ms * 0.001 * scale, start + duration,
2225 + lock_od, cs_length * 0.001));
2226 +
2227 +printf("BEFORE BACK_TASK\n");
2228 + ret = task_mode(BACKGROUND_TASK);
2229 + if (ret != 0)
2230 + bail_out("could not become regular task (huh?)");
2231 +
2232 + reservation_destroy(gettid(), config.cpu);
2233 +
2234 + return 0;
2235 +}
2236 diff --git bin/rt_mode_poll.c bin/rt_mode_poll.c
2237 new file mode 100644
2238 index 0000000..d05521c
2239 --- /dev/null
2240 +++ bin/rt_mode_poll.c
2241 @@ -0,0 +1,221 @@
2242 +#include <sys/time.h>
2243 +#include <sys/mman.h>
2244 +
2245 +#include <stdio.h>
2246 +#include <stdlib.h>
2247 +#include <unistd.h>
2248 +#include <time.h>
2249 +#include <string.h>
2250 +#include <assert.h>
2251 +#include <limits.h>
2252 +
2253 +
2254 +#include "litmus.h"
2255 +#include "common.h"
2256 +
2257 +#define __NR_request_mode 408
2258 +#define __NR_enact_mode 409
2259 +
2260 +int main_job(void){
2261 + return syscall(__NR_enact_mode);
2262 +}
2263 +
2264 +static char* progname;
2265 +
2266 +static void usage(char *error) {
2267 + fprintf(stderr, "Error: %s\n", error);
2268 + fprintf(stderr,
2269 + "Usage:\n"
2270 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
2271 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
2272 + " rt_spin -l\n"
2273 + "\n"
2274 + "COMMON-OPTS = [-w] [-s SCALE]\n"
2275 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
2276 + "\n"
2277 + "WCET and PERIOD are microseconds, DURATION is seconds.\n");
2278 + exit(EXIT_FAILURE);
2279 +}
2280 +
2281 +static int job(double program_end)
2282 +{
2283 + if (wctime() > program_end)
2284 + return 0;
2285 + else {
2286 + main_job();
2287 + sleep_next_period();
2288 + return 1;
2289 + }
2290 +}
2291 +
2292 +#define OPTSTR "p:wvel:b:k:"
2293 +int main(int argc, char** argv)
2294 +{
2295 + int ret;
2296 + lt_t wcet;
2297 + lt_t period;
2298 + lt_t budget;
2299 + double wcet_ms, period_ms, budget_ms;
2300 + unsigned int priority = 0; //guarantee highest priority to this task
2301 + int migrate = 0;
2302 + int cluster = 0;
2303 + int opt;
2304 + int wait = 0;
2305 + int want_enforcement = 0;
2306 + task_class_t class = RT_CLASS_HARD;
2307 + struct rt_task param;
2308 + struct mc2_task mc2_param;
2309 + struct reservation_config config;
2310 + int res_type = PERIODIC_POLLING;
2311 + uint32_t mode_mask = (1 << 0);
2312 + int i;
2313 + double duration = 0, start = 0;
2314 + struct control_page* ctl_page = NULL;
2315 +
2316 + progname = argv[0];
2317 +
2318 + /* default for reservation */
2319 + config.id = 0;
2320 + config.priority = 1;
2321 + config.cpu = -1;
2322 +
2323 + mc2_param.crit = CRIT_LEVEL_A;
2324 +
2325 + budget_ms = 10;
2326 +
2327 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
2328 + switch (opt) {
2329 + case 'w':
2330 + wait = 1;
2331 + break;
2332 + case 'p':
2333 + cluster = atoi(optarg);
2334 + migrate = 1;
2335 + config.cpu = cluster;
2336 + break;
2337 + case 'e':
2338 + want_enforcement = 1;
2339 + break;
2340 + case 'b':
2341 + budget_ms = atof(optarg);
2342 + break;
2343 + case 'k':
2344 + mode_mask = atoi(optarg);
2345 + break;
2346 + case ':':
2347 + usage("Argument missing.");
2348 + break;
2349 + case '?':
2350 + default:
2351 + usage("Bad argument.");
2352 + break;
2353 + }
2354 + }
2355 +
2356 + if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
2357 + usage("Bad criticailty level or priority");
2358 +
2359 + if (argc - optind < 2)
2360 + usage("Arguments missing.");
2361 +
2362 + wcet_ms = atof(argv[optind + 0]);
2363 + period_ms = atof(argv[optind + 1]);
2364 +
2365 + wcet = ms2ns(wcet_ms);
2366 + period = ms2ns(period_ms);
2367 + budget = ms2ns(budget_ms);
2368 +
2369 + if (wcet <= 0)
2370 + usage("The worst-case execution time must be a "
2371 + "positive number.");
2372 + if (period <= 0)
2373 + usage("The period must be a positive number.");
2374 + if (wcet > period) {
2375 + usage("The worst-case execution time must not "
2376 + "exceed the period.");
2377 + }
2378 +
2379 + duration = atof(argv[optind + 2]);
2380 +
2381 + if (migrate) {
2382 + ret = be_migrate_to_domain(cluster);
2383 + if (ret < 0)
2384 + bail_out("could not migrate to target partition or cluster.");
2385 + }
2386 + else{
2387 + bail_out("rt_mode_poll must be migrated.");
2388 + }
2389 +
2390 + /* reservation config */
2391 + config.id = gettid();
2392 +
2393 + config.polling_params.budget = budget;
2394 + config.polling_params.period = period;
2395 + config.polling_params.offset = 0;
2396 + config.polling_params.relative_deadline = 0;
2397 + if (config.polling_params.budget > config.polling_params.period) {
2398 + usage("The budget must not exceed the period.");
2399 + }
2400 +
2401 + /* create reservation's */
2402 + for( i = 0; i < 32; i++){
2403 + if ( !( (1 << i) & mode_mask ) )
2404 + continue;
2405 + config.mode = i;
2406 + ret = reservation_create(res_type, &config);
2407 + if (ret < 0) {
2408 + bail_out("failed to create reservation.");
2409 + }
2410 + }
2411 +
2412 + init_rt_task_param(¶m);
2413 + param.exec_cost = wcet;
2414 + param.period = period;
2415 + param.priority = priority;
2416 + param.cls = class;
2417 + param.release_policy = TASK_PERIODIC;
2418 + param.budget_policy = (want_enforcement) ?
2419 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
2420 + if (migrate) {
2421 + param.cpu = gettid();
2422 + }
2423 + ret = set_rt_task_param(gettid(), ¶m);
2424 +
2425 + if (ret < 0)
2426 + bail_out("could not setup rt task params");
2427 +
2428 + mc2_param.res_id = gettid();
2429 + mc2_param.mode_mask = mode_mask;
2430 + ret = set_mc2_task_param(gettid(), &mc2_param);
2431 + if (ret < 0)
2432 + bail_out("could not setup mc2 task params");
2433 +
2434 + init_litmus();
2435 + ctl_page = get_ctrl_page();
2436 + if (!ctl_page)
2437 + bail_out("could not get ctrl_page");
2438 + ctl_page->mode_poll_task = 1;
2439 +
2440 + start = wctime();
2441 + ret = task_mode(LITMUS_RT_TASK);
2442 + if (ret != 0)
2443 + bail_out("could not become RT task");
2444 +
2445 + set_page_color(config.cpu);
2446 +
2447 + if (wait) {
2448 + ret = wait_for_ts_release();
2449 + if (ret != 0)
2450 + bail_out("wait_for_ts_release()");
2451 + start = wctime();
2452 + }
2453 +
2454 + while (job(start + duration)) {};
2455 +
2456 + ret = task_mode(BACKGROUND_TASK);
2457 + if (ret != 0)
2458 + bail_out("could not become regular task (huh?)");
2459 +
2460 + reservation_destroy(gettid(), config.cpu);
2461 + return 0;
2462 +}
2463 diff --git bin/rt_skeleton.c bin/rt_skeleton.c
2464 new file mode 100644
2465 index 0000000..16e189a
2466 --- /dev/null
2467 +++ bin/rt_skeleton.c
2468 @@ -0,0 +1,247 @@
2469 +#include <sys/time.h>
2470 +#include <sys/mman.h>
2471 +
2472 +#include <stdio.h>
2473 +#include <stdlib.h>
2474 +#include <unistd.h>
2475 +#include <time.h>
2476 +#include <string.h>
2477 +#include <assert.h>
2478 +#include <limits.h>
2479 +
2480 +
2481 +#include "litmus.h"
2482 +#include "common.h"
2483 +
2484 +extern int main_job(void);
2485 +
2486 +static char* progname;
2487 +int loops = 10;
2488 +//struct timeval t1, t2;
2489 +
2490 +static void usage(char *error) {
2491 + fprintf(stderr, "Error: %s\n", error);
2492 + fprintf(stderr,
2493 + "Usage:\n"
2494 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
2495 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
2496 + " rt_spin -l\n"
2497 + "\n"
2498 + "COMMON-OPTS = [-w] [-s SCALE]\n"
2499 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
2500 + "\n"
2501 + "WCET and PERIOD are microseconds, DURATION is seconds.\n");
2502 + exit(EXIT_FAILURE);
2503 +}
2504 +
2505 +inline unsigned long get_cyclecount (void)
2506 +{
2507 + unsigned long value;
2508 + // Read CCNT Register
2509 + asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
2510 + return value;
2511 +}
2512 +
2513 +static int job(double exec_time, double program_end)
2514 +{
2515 + if (wctime() > program_end)
2516 + return 0;
2517 + else {
2518 + register int iter = 0;
2519 + //register unsigned long t;
2520 + //t = get_cyclecount();
2521 + //gettimeofday(&t1, NULL);
2522 + while (iter++ < loops) {
2523 + main_job();
2524 + }
2525 + //t = get_cyclecount() - t;
2526 + //printf("%ld cycles\n", t);
2527 + //gettimeofday(&t2, NULL);
2528 + //printf("%ld us\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec)));
2529 + sleep_next_period();
2530 + return 1;
2531 + }
2532 +}
2533 +
2534 +#define OPTSTR "p:wves:l:m:i:b:"
2535 +int main(int argc, char** argv)
2536 +{
2537 + int ret;
2538 + lt_t wcet;
2539 + lt_t period;
2540 + lt_t budget;
2541 + double wcet_us, period_us, budget_us;
2542 + unsigned int priority = LITMUS_NO_PRIORITY;
2543 + int migrate = 0;
2544 + int cluster = 0;
2545 + int opt;
2546 + int wait = 0;
2547 + int want_enforcement = 0;
2548 + double duration = 0, start = 0;
2549 + double scale = 1.0;
2550 + task_class_t class = RT_CLASS_HARD;
2551 + struct rt_task param;
2552 + struct mc2_task mc2_param;
2553 + struct reservation_config config;
2554 + int res_type = PERIODIC_POLLING;
2555 +
2556 + unsigned int job_no;
2557 +
2558 +
2559 + progname = argv[0];
2560 +
2561 + /* default for reservation */
2562 + config.id = 0;
2563 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
2564 + config.cpu = -1;
2565 +
2566 + mc2_param.crit = CRIT_LEVEL_C;
2567 +
2568 + budget_us = 10000;
2569 +
2570 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
2571 + switch (opt) {
2572 + case 'w':
2573 + wait = 1;
2574 + break;
2575 + case 'p':
2576 + cluster = atoi(optarg);
2577 + migrate = 1;
2578 + config.cpu = cluster;
2579 + break;
2580 + case 'e':
2581 + want_enforcement = 1;
2582 + break;
2583 + case 's':
2584 + scale = atof(optarg);
2585 + break;
2586 + case 'l':
2587 + loops = atoi(optarg);
2588 + break;
2589 + case 'm':
2590 + mc2_param.crit = atoi(optarg);
2591 + if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
2592 + usage("Invalid criticality level.");
2593 + }
2594 + res_type = PERIODIC_POLLING;
2595 + break;
2596 + case 'b':
2597 + budget_us = atof(optarg);
2598 + break;
2599 + case 'i':
2600 + config.priority = atoi(optarg);
2601 + break;
2602 + case ':':
2603 + usage("Argument missing.");
2604 + break;
2605 + case '?':
2606 + default:
2607 + usage("Bad argument.");
2608 + break;
2609 + }
2610 + }
2611 +
2612 + if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
2613 + usage("Bad criticailty level or priority");
2614 +
2615 + if (argc - optind < 3)
2616 + usage("Arguments missing.");
2617 +
2618 + wcet_us = atof(argv[optind + 0]);
2619 + period_us = atof(argv[optind + 1]);
2620 +
2621 + wcet = us2ns(wcet_us);
2622 + period = us2ns(period_us);
2623 + budget = us2ns(budget_us);
2624 +
2625 + if (wcet <= 0)
2626 + usage("The worst-case execution time must be a "
2627 + "positive number.");
2628 + if (period <= 0)
2629 + usage("The period must be a positive number.");
2630 + if (wcet > period) {
2631 + usage("The worst-case execution time must not "
2632 + "exceed the period.");
2633 + }
2634 +
2635 + duration = atof(argv[optind + 2]);
2636 +
2637 + if (migrate) {
2638 + ret = be_migrate_to_domain(cluster);
2639 + if (ret < 0)
2640 + bail_out("could not migrate to target partition or cluster.");
2641 + }
2642 +
2643 + /* reservation config */
2644 + config.id = gettid();
2645 +
2646 + config.polling_params.budget = budget;
2647 + config.polling_params.period = period;
2648 + config.polling_params.offset = 0;
2649 + config.polling_params.relative_deadline = 0;
2650 + if (config.polling_params.budget > config.polling_params.period) {
2651 + usage("The budget must not exceed the period.");
2652 + }
2653 +
2654 + /* create a reservation */
2655 + ret = reservation_create(res_type, &config);
2656 + if (ret < 0) {
2657 + bail_out("failed to create reservation.");
2658 + }
2659 +
2660 + init_rt_task_param(¶m);
2661 + param.exec_cost = wcet;
2662 + param.period = period;
2663 + param.priority = priority;
2664 + param.cls = class;
2665 + param.release_policy = TASK_PERIODIC;
2666 + param.budget_policy = (want_enforcement) ?
2667 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
2668 + if (migrate) {
2669 + param.cpu = gettid();
2670 + }
2671 + ret = set_rt_task_param(gettid(), ¶m);
2672 +
2673 + if (ret < 0)
2674 + bail_out("could not setup rt task params");
2675 +
2676 + mc2_param.res_id = gettid();
2677 + ret = set_mc2_task_param(gettid(), &mc2_param);
2678 +//printf("SET_MC2_TASK\n");
2679 + if (ret < 0)
2680 + bail_out("could not setup mc2 task params");
2681 +
2682 + init_litmus();
2683 +//printf("CALL\n");
2684 + if (mc2_param.crit == CRIT_LEVEL_C)
2685 + set_page_color(8);
2686 + else if (mc2_param.crit < CRIT_LEVEL_C)
2687 + set_page_color(config.cpu*2 + mc2_param.crit);
2688 +//printf("CALL\n");
2689 +
2690 +//printf("INIT_LITMUS\n");
2691 + start = wctime();
2692 + ret = task_mode(LITMUS_RT_TASK);
2693 +//printf("TASK_MODE\n");
2694 + if (ret != 0)
2695 + bail_out("could not become RT task");
2696 +
2697 +
2698 + if (wait) {
2699 +//printf("BEFORE WAIT\n");
2700 + ret = wait_for_ts_release();
2701 + if (ret != 0)
2702 + bail_out("wait_for_ts_release()");
2703 + start = wctime();
2704 + }
2705 +
2706 + while (job(wcet_us * 0.000001 * scale, start + duration)) {};
2707 +
2708 + ret = task_mode(BACKGROUND_TASK);
2709 + if (ret != 0)
2710 + bail_out("could not become regular task (huh?)");
2711 +
2712 + reservation_destroy(gettid(), config.cpu);
2713 + printf("%s/%d finished.\n",progname, gettid());
2714 + return 0;
2715 +}
2716 diff --git bin/rt_skeleton_ms.c bin/rt_skeleton_ms.c
2717 new file mode 100644
2718 index 0000000..d545635
2719 --- /dev/null
2720 +++ bin/rt_skeleton_ms.c
2721 @@ -0,0 +1,282 @@
2722 +#include <sys/time.h>
2723 +#include <sys/mman.h>
2724 +
2725 +#include <stdio.h>
2726 +#include <stdlib.h>
2727 +#include <unistd.h>
2728 +#include <time.h>
2729 +#include <string.h>
2730 +#include <assert.h>
2731 +#include <limits.h>
2732 +
2733 +
2734 +#include "litmus.h"
2735 +#include "common.h"
2736 +
2737 +extern int main_job(void);
2738 +static char* progname;
2739 +
2740 +static void usage(char *error) {
2741 + fprintf(stderr, "Error: %s\n", error);
2742 + fprintf(stderr,
2743 + "Usage:\n"
2744 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
2745 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
2746 + " rt_spin -l\n"
2747 + "\n"
2748 + "COMMON-OPTS = [-w] [-s SCALE]\n"
2749 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
2750 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
2751 + "\n"
2752 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
2753 + "CRITICAL SECTION LENGTH is in milliseconds.\n");
2754 + exit(EXIT_FAILURE);
2755 +}
2756 +
2757 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
2758 +{
2759 + if (wctime() > program_end)
2760 + return 0;
2761 + else {
2762 + main_job();
2763 + sleep_next_period();
2764 + return 1;
2765 + }
2766 +}
2767 +
2768 +#define OPTSTR "p:c:wves:q:X:L:Q:vh:m:i:b:"
2769 +int main(int argc, char** argv)
2770 +{
2771 + int ret;
2772 + lt_t wcet;
2773 + lt_t period;
2774 + lt_t hyperperiod;
2775 + lt_t budget;
2776 + double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
2777 + unsigned int priority = LITMUS_NO_PRIORITY;
2778 + int migrate = 0;
2779 + int cluster = 0;
2780 + int opt;
2781 + int wait = 0;
2782 + int want_enforcement = 0;
2783 + double duration = 0, start = 0;
2784 + double scale = 1.0;
2785 + task_class_t class = RT_CLASS_HARD;
2786 + struct rt_task param;
2787 + struct mc2_task mc2_param;
2788 + struct reservation_config config;
2789 + int res_type = PERIODIC_POLLING;
2790 +
2791 + int verbose = 0;
2792 + unsigned int job_no;
2793 +
2794 + /* locking */
2795 + int lock_od = -1;
2796 + int resource_id = 0;
2797 + const char *lock_namespace = "./rtspin-locks";
2798 + int protocol = -1;
2799 + double cs_length = 1; /* millisecond */
2800 +
2801 + progname = argv[0];
2802 +
2803 + /* default for reservation */
2804 + config.id = 0;
2805 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
2806 + config.cpu = -1;
2807 +
2808 + mc2_param.crit = CRIT_LEVEL_C;
2809 +
2810 + hyperperiod_ms = 1000;
2811 + budget_ms = 10;
2812 +
2813 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
2814 + switch (opt) {
2815 + case 'w':
2816 + wait = 1;
2817 + break;
2818 + case 'p':
2819 + cluster = atoi(optarg);
2820 + migrate = 1;
2821 + config.cpu = cluster;
2822 + break;
2823 + case 'q':
2824 + priority = atoi(optarg);
2825 + if (!litmus_is_valid_fixed_prio(priority))
2826 + usage("Invalid priority.");
2827 + break;
2828 + case 'c':
2829 + class = str2class(optarg);
2830 + if (class == -1)
2831 + usage("Unknown task class.");
2832 + break;
2833 + case 'e':
2834 + want_enforcement = 1;
2835 + break;
2836 + case 's':
2837 + scale = atof(optarg);
2838 + break;
2839 + case 'X':
2840 + protocol = lock_protocol_for_name(optarg);
2841 + if (protocol < 0)
2842 + usage("Unknown locking protocol specified.");
2843 + break;
2844 + case 'L':
2845 + cs_length = atof(optarg);
2846 + if (cs_length <= 0)
2847 + usage("Invalid critical section length.");
2848 + break;
2849 + case 'Q':
2850 + resource_id = atoi(optarg);
2851 + if (resource_id <= 0 && strcmp(optarg, "0"))
2852 + usage("Invalid resource ID.");
2853 + break;
2854 + case 'v':
2855 + verbose = 1;
2856 + break;
2857 + case 'm':
2858 + mc2_param.crit = atoi(optarg);
2859 + if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
2860 + usage("Invalid criticality level.");
2861 + }
2862 + res_type = PERIODIC_POLLING;
2863 + break;
2864 + case 'h':
2865 + hyperperiod_ms = atof(optarg);
2866 + break;
2867 + case 'b':
2868 + budget_ms = atof(optarg);
2869 + break;
2870 + case 'i':
2871 + config.priority = atoi(optarg);
2872 + break;
2873 + case ':':
2874 + usage("Argument missing.");
2875 + break;
2876 + case '?':
2877 + default:
2878 + usage("Bad argument.");
2879 + break;
2880 + }
2881 + }
2882 +
2883 + if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
2884 + usage("Bad criticailty level or priority");
2885 +
2886 + if (argc - optind < 3)
2887 + usage("Arguments missing.");
2888 +
2889 + wcet_ms = atof(argv[optind + 0]);
2890 + period_ms = atof(argv[optind + 1]);
2891 +
2892 + wcet = ms2ns(wcet_ms);
2893 + period = ms2ns(period_ms);
2894 + budget = ms2ns(budget_ms);
2895 + hyperperiod = ms2ns(hyperperiod_ms);
2896 +
2897 + if (wcet <= 0)
2898 + usage("The worst-case execution time must be a "
2899 + "positive number.");
2900 + if (period <= 0)
2901 + usage("The period must be a positive number.");
2902 + if (wcet > period) {
2903 + usage("The worst-case execution time must not "
2904 + "exceed the period.");
2905 + }
2906 +
2907 + duration = atof(argv[optind + 2]);
2908 +
2909 + if (migrate) {
2910 + ret = be_migrate_to_domain(cluster);
2911 + if (ret < 0)
2912 + bail_out("could not migrate to target partition or cluster.");
2913 + }
2914 +
2915 + /* reservation config */
2916 + config.id = gettid();
2917 +
2918 + if (hyperperiod%period != 0 ) {
2919 + ;//bail_out("hyperperiod must be multiple of period");
2920 + }
2921 +
2922 + config.polling_params.budget = budget;
2923 + config.polling_params.period = period;
2924 + config.polling_params.offset = 0;
2925 + config.polling_params.relative_deadline = 0;
2926 + if (config.polling_params.budget > config.polling_params.period) {
2927 + usage("The budget must not exceed the period.");
2928 + }
2929 +
2930 + /* create a reservation */
2931 + ret = reservation_create(res_type, &config);
2932 + if (ret < 0) {
2933 + bail_out("failed to create reservation.");
2934 + }
2935 +
2936 + init_rt_task_param(¶m);
2937 + param.exec_cost = wcet;
2938 + param.period = period;
2939 + param.priority = priority;
2940 + param.cls = class;
2941 + param.release_policy = TASK_PERIODIC;
2942 + param.budget_policy = (want_enforcement) ?
2943 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
2944 + if (migrate) {
2945 + param.cpu = gettid();
2946 + }
2947 + ret = set_rt_task_param(gettid(), ¶m);
2948 +
2949 + if (ret < 0)
2950 + bail_out("could not setup rt task params");
2951 +
2952 + mc2_param.res_id = gettid();
2953 + ret = set_mc2_task_param(gettid(), &mc2_param);
2954 +//printf("SET_MC2_TASK\n");
2955 + if (ret < 0)
2956 + bail_out("could not setup mc2 task params");
2957 +
2958 + init_litmus();
2959 +//printf("CALL\n");
2960 + set_page_color(config.cpu);
2961 +//printf("CALL\n");
2962 +
2963 +//printf("INIT_LITMUS\n");
2964 + start = wctime();
2965 + ret = task_mode(LITMUS_RT_TASK);
2966 +//printf("TASK_MODE\n");
2967 + if (ret != 0)
2968 + bail_out("could not become RT task");
2969 +
2970 + if (protocol >= 0) {
2971 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
2972 + if (lock_od < 0) {
2973 + perror("litmus_open_lock");
2974 + usage("Could not open lock.");
2975 + }
2976 + }
2977 +
2978 +
2979 + if (wait) {
2980 +//printf("BEFORE WAIT\n");
2981 + ret = wait_for_ts_release();
2982 + if (ret != 0)
2983 + bail_out("wait_for_ts_release()");
2984 + start = wctime();
2985 + }
2986 +
2987 + do {
2988 + if (verbose) {
2989 + get_job_no(&job_no);
2990 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
2991 + job_no, (wctime() - start) * 1000);
2992 + }
2993 + } while (job(wcet_ms * 0.001 * scale, start + duration,
2994 + lock_od, cs_length * 0.001));
2995 +
2996 + ret = task_mode(BACKGROUND_TASK);
2997 + if (ret != 0)
2998 + bail_out("could not become regular task (huh?)");
2999 +
3000 + reservation_destroy(gettid(), config.cpu);
3001 +printf("%s/%d finished.\n",progname, gettid());
3002 + return 0;
3003 +}
3004 diff --git bin/rt_skeleton_us.c bin/rt_skeleton_us.c
3005 new file mode 100644
3006 index 0000000..ecf3ed8
3007 --- /dev/null
3008 +++ bin/rt_skeleton_us.c
3009 @@ -0,0 +1,282 @@
3010 +#include <sys/time.h>
3011 +#include <sys/mman.h>
3012 +
3013 +#include <stdio.h>
3014 +#include <stdlib.h>
3015 +#include <unistd.h>
3016 +#include <time.h>
3017 +#include <string.h>
3018 +#include <assert.h>
3019 +#include <limits.h>
3020 +
3021 +
3022 +#include "litmus.h"
3023 +#include "common.h"
3024 +
3025 +extern int main_job(void);
3026 +static char* progname;
3027 +
3028 +static void usage(char *error) {
3029 + fprintf(stderr, "Error: %s\n", error);
3030 + fprintf(stderr,
3031 + "Usage:\n"
3032 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
3033 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
3034 + " rt_spin -l\n"
3035 + "\n"
3036 + "COMMON-OPTS = [-w] [-s SCALE]\n"
3037 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
3038 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
3039 + "\n"
3040 + "WCET and PERIOD are microseconds, DURATION is seconds.\n"
3041 + "CRITICAL SECTION LENGTH is in microseconds.\n");
3042 + exit(EXIT_FAILURE);
3043 +}
3044 +
3045 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
3046 +{
3047 + if (wctime() > program_end)
3048 + return 0;
3049 + else {
3050 + main_job();
3051 + sleep_next_period();
3052 + return 1;
3053 + }
3054 +}
3055 +
3056 +#define OPTSTR "p:c:wves:q:X:L:Q:vh:m:i:b:"
3057 +int main(int argc, char** argv)
3058 +{
3059 + int ret;
3060 + lt_t wcet;
3061 + lt_t period;
3062 + lt_t hyperperiod;
3063 + lt_t budget;
3064 + double wcet_us, period_us, hyperperiod_us, budget_us;
3065 + unsigned int priority = LITMUS_NO_PRIORITY;
3066 + int migrate = 0;
3067 + int cluster = 0;
3068 + int opt;
3069 + int wait = 0;
3070 + int want_enforcement = 0;
3071 + double duration = 0, start = 0;
3072 + double scale = 1.0;
3073 + task_class_t class = RT_CLASS_HARD;
3074 + struct rt_task param;
3075 + struct mc2_task mc2_param;
3076 + struct reservation_config config;
3077 + int res_type = PERIODIC_POLLING;
3078 +
3079 + int verbose = 0;
3080 + unsigned int job_no;
3081 +
3082 + /* locking */
3083 + int lock_od = -1;
3084 + int resource_id = 0;
3085 + const char *lock_namespace = "./rtspin-locks";
3086 + int protocol = -1;
3087 + double cs_length = 1; /* millisecond */
3088 +
3089 + progname = argv[0];
3090 +
3091 + /* default for reservation */
3092 + config.id = 0;
3093 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
3094 + config.cpu = -1;
3095 +
3096 + mc2_param.crit = CRIT_LEVEL_C;
3097 +
3098 + hyperperiod_us = 1000000;
3099 + budget_us = 10000;
3100 +
3101 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
3102 + switch (opt) {
3103 + case 'w':
3104 + wait = 1;
3105 + break;
3106 + case 'p':
3107 + cluster = atoi(optarg);
3108 + migrate = 1;
3109 + config.cpu = cluster;
3110 + break;
3111 + case 'q':
3112 + priority = atoi(optarg);
3113 + if (!litmus_is_valid_fixed_prio(priority))
3114 + usage("Invalid priority.");
3115 + break;
3116 + case 'c':
3117 + class = str2class(optarg);
3118 + if (class == -1)
3119 + usage("Unknown task class.");
3120 + break;
3121 + case 'e':
3122 + want_enforcement = 1;
3123 + break;
3124 + case 's':
3125 + scale = atof(optarg);
3126 + break;
3127 + case 'X':
3128 + protocol = lock_protocol_for_name(optarg);
3129 + if (protocol < 0)
3130 + usage("Unknown locking protocol specified.");
3131 + break;
3132 + case 'L':
3133 + cs_length = atof(optarg);
3134 + if (cs_length <= 0)
3135 + usage("Invalid critical section length.");
3136 + break;
3137 + case 'Q':
3138 + resource_id = atoi(optarg);
3139 + if (resource_id <= 0 && strcmp(optarg, "0"))
3140 + usage("Invalid resource ID.");
3141 + break;
3142 + case 'v':
3143 + verbose = 1;
3144 + break;
3145 + case 'm':
3146 + mc2_param.crit = atoi(optarg);
3147 + if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
3148 + usage("Invalid criticality level.");
3149 + }
3150 + res_type = PERIODIC_POLLING;
3151 + break;
3152 + case 'h':
3153 + hyperperiod_us = atof(optarg);
3154 + break;
3155 + case 'b':
3156 + budget_us = atof(optarg);
3157 + break;
3158 + case 'i':
3159 + config.priority = atoi(optarg);
3160 + break;
3161 + case ':':
3162 + usage("Argument missing.");
3163 + break;
3164 + case '?':
3165 + default:
3166 + usage("Bad argument.");
3167 + break;
3168 + }
3169 + }
3170 +
3171 + if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
3172 + usage("Bad criticailty level or priority");
3173 +
3174 + if (argc - optind < 3)
3175 + usage("Arguments missing.");
3176 +
3177 + wcet_us = atof(argv[optind + 0]);
3178 + period_us = atof(argv[optind + 1]);
3179 +
3180 + wcet = us2ns(wcet_us);
3181 + period = us2ns(period_us);
3182 + budget = us2ns(budget_us);
3183 + hyperperiod = us2ns(hyperperiod_us);
3184 +
3185 + if (wcet <= 0)
3186 + usage("The worst-case execution time must be a "
3187 + "positive number.");
3188 + if (period <= 0)
3189 + usage("The period must be a positive number.");
3190 + if (wcet > period) {
3191 + usage("The worst-case execution time must not "
3192 + "exceed the period.");
3193 + }
3194 +
3195 + duration = atof(argv[optind + 2]);
3196 +
3197 + if (migrate) {
3198 + ret = be_migrate_to_domain(cluster);
3199 + if (ret < 0)
3200 + bail_out("could not migrate to target partition or cluster.");
3201 + }
3202 +
3203 + /* reservation config */
3204 + config.id = gettid();
3205 +
3206 + if (hyperperiod%period != 0 ) {
3207 + ;//bail_out("hyperperiod must be multiple of period");
3208 + }
3209 +
3210 + config.polling_params.budget = budget;
3211 + config.polling_params.period = period;
3212 + config.polling_params.offset = 0;
3213 + config.polling_params.relative_deadline = 0;
3214 + if (config.polling_params.budget > config.polling_params.period) {
3215 + usage("The budget must not exceed the period.");
3216 + }
3217 +
3218 + /* create a reservation */
3219 + ret = reservation_create(res_type, &config);
3220 + if (ret < 0) {
3221 + bail_out("failed to create reservation.");
3222 + }
3223 +
3224 + init_rt_task_param(¶m);
3225 + param.exec_cost = wcet;
3226 + param.period = period;
3227 + param.priority = priority;
3228 + param.cls = class;
3229 + param.release_policy = TASK_PERIODIC;
3230 + param.budget_policy = (want_enforcement) ?
3231 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
3232 + if (migrate) {
3233 + param.cpu = gettid();
3234 + }
3235 + ret = set_rt_task_param(gettid(), ¶m);
3236 +
3237 + if (ret < 0)
3238 + bail_out("could not setup rt task params");
3239 +
3240 + mc2_param.res_id = gettid();
3241 + ret = set_mc2_task_param(gettid(), &mc2_param);
3242 +//printf("SET_MC2_TASK\n");
3243 + if (ret < 0)
3244 + bail_out("could not setup mc2 task params");
3245 +
3246 + init_litmus();
3247 +//printf("CALL\n");
3248 + set_page_color(config.cpu);
3249 +//printf("CALL\n");
3250 +
3251 +//printf("INIT_LITMUS\n");
3252 + start = wctime();
3253 + ret = task_mode(LITMUS_RT_TASK);
3254 +//printf("TASK_MODE\n");
3255 + if (ret != 0)
3256 + bail_out("could not become RT task");
3257 +
3258 + if (protocol >= 0) {
3259 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
3260 + if (lock_od < 0) {
3261 + perror("litmus_open_lock");
3262 + usage("Could not open lock.");
3263 + }
3264 + }
3265 +
3266 +
3267 + if (wait) {
3268 +//printf("BEFORE WAIT\n");
3269 + ret = wait_for_ts_release();
3270 + if (ret != 0)
3271 + bail_out("wait_for_ts_release()");
3272 + start = wctime();
3273 + }
3274 +
3275 + do {
3276 + if (verbose) {
3277 + get_job_no(&job_no);
3278 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
3279 + job_no, (wctime() - start) * 1000);
3280 + }
3281 + } while (job(wcet_us * 0.000001 * scale, start + duration,
3282 + lock_od, cs_length * 0.000001));
3283 +
3284 + ret = task_mode(BACKGROUND_TASK);
3285 + if (ret != 0)
3286 + bail_out("could not become regular task (huh?)");
3287 +
3288 + reservation_destroy(gettid(), config.cpu);
3289 +printf("%s/%d finished.\n",progname, gettid());
3290 + return 0;
3291 +}
3292 diff --git bin/rtspin.c bin/rtspin.c
3293 index ea7f192..fd57c45 100644
3294 --- bin/rtspin.c
3295 +++ bin/rtspin.c
3296 @@ -6,7 +6,7 @@
3297 #include <time.h>
3298 #include <string.h>
3299 #include <assert.h>
3300 -
3301 +#include <limits.h>
3302
3303 #include "litmus.h"
3304 #include "common.h"
3305 @@ -191,7 +191,7 @@ int main(int argc, char** argv)
3306 lt_t wcet;
3307 lt_t period;
3308 double wcet_ms, period_ms;
3309 - unsigned int priority = LITMUS_LOWEST_PRIORITY;
3310 + unsigned int priority = LITMUS_NO_PRIORITY;
3311 int migrate = 0;
3312 int cluster = 0;
3313 int reservation = -1;
3314 diff --git include/cache_common.h include/cache_common.h
3315 new file mode 100644
3316 index 0000000..2957dd3
3317 --- /dev/null
3318 +++ include/cache_common.h
3319 @@ -0,0 +1,213 @@
3320 +#ifndef __CACHE_COMMON_H__
3321 +#define __CACHE_COMMON_H__
3322 +
3323 +#include <stdio.h>
3324 +#include <stdlib.h>
3325 +#include <time.h>
3326 +#include <string.h>
3327 +#include <assert.h>
3328 +
3329 +#include <signal.h>
3330 +#include <sys/mman.h>
3331 +#include <sys/types.h>
3332 +#include <sys/stat.h>
3333 +#include <fcntl.h>
3334 +#include <unistd.h>
3335 +
3336 +#include <sys/io.h>
3337 +#include <sys/utsname.h>
3338 +
3339 +#include <sched.h>
3340 +#include <sys/time.h>
3341 +#include <sys/resource.h>
3342 +
3343 +#include "litmus.h"
3344 +#include "asm/cycles.h"
3345 +
3346 +#if defined(__i386__) || defined(__x86_64__)
3347 +#include "asm/irq.h"
3348 +#endif
3349 +
3350 +
3351 +#define UNCACHE_DEV "/dev/litmus/uncache"
3352 +
3353 +static void die(char *error)
3354 +{
3355 + fprintf(stderr, "Error: %s (errno: %m)\n",
3356 + error);
3357 + exit(1);
3358 +}
3359 +
3360 +static int migrate_to(int cpu)
3361 +{
3362 + int ret;
3363 +
3364 + static __thread cpu_set_t* cpu_set = NULL;
3365 + static __thread size_t cpu_set_sz;
3366 + static __thread int num_cpus;
3367 + if(!cpu_set)
3368 + {
3369 + num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
3370 + cpu_set = CPU_ALLOC(num_cpus);
3371 + cpu_set_sz = CPU_ALLOC_SIZE(num_cpus);
3372 + }
3373 +
3374 + CPU_ZERO_S(cpu_set_sz, cpu_set);
3375 + CPU_SET_S(cpu, cpu_set_sz, cpu_set);
3376 + ret = sched_setaffinity(0 /* self */, cpu_set_sz, cpu_set);
3377 + return ret;
3378 +}
3379 +
3380 +static int check_migrations(int num_cpus)
3381 +{
3382 + int cpu, err;
3383 +
3384 + for (cpu = 0; cpu < num_cpus; cpu++) {
3385 + err = migrate_to(cpu);
3386 + if (err != 0) {
3387 + fprintf(stderr, "Migration to CPU %d failed: %m.\n",
3388 + cpu + 1);
3389 + return 1;
3390 + }
3391 + }
3392 + return 0;
3393 +}
3394 +
3395 +static int become_posix_realtime_task(int prio)
3396 +{
3397 + struct sched_param param;
3398 + memset(¶m, 0, sizeof(param));
3399 + param.sched_priority = prio;
3400 + return sched_setscheduler(0 /* self */, SCHED_FIFO, ¶m);
3401 +}
3402 +
3403 +static int renice(int nice_val)
3404 +{
3405 + return setpriority(PRIO_PROCESS, 0 /* self */, nice_val);
3406 +}
3407 +
3408 +static int lock_memory(void)
3409 +{
3410 + return mlockall(MCL_CURRENT | MCL_FUTURE);
3411 +}
3412 +
3413 +/* define CACHELINE_SIZE if not provided by compiler args */
3414 +#ifndef CACHELINE_SIZE
3415 +#if defined(__i386__) || defined(__x86_64__)
3416 +/* recent intel cpus */
3417 +#define CACHELINE_SIZE 64
3418 +#elif defined(__arm__)
3419 +/* at least with Cortex-A9 cpus ("8 words") */
3420 +#define CACHELINE_SIZE 32
3421 +#else
3422 +#error "Could not determine cacheline size!"
3423 +#endif
3424 +#endif
3425 +
3426 +//#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
3427 +//typedef struct cacheline
3428 +//{
3429 +// int line[INTS_IN_CACHELINE];
3430 +//} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
3431 +
3432 +static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages)
3433 +{
3434 + int flags = MAP_PRIVATE | MAP_POPULATE;
3435 + cacheline_t* arena = NULL;
3436 + int fd;
3437 +
3438 + if(use_huge_pages)
3439 + flags |= MAP_HUGETLB;
3440 +
3441 + if(use_uncache_pages) {
3442 + fd = open(UNCACHE_DEV, O_RDWR);
3443 + if (fd == -1)
3444 + die("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
3445 + }
3446 + else {
3447 + fd = -1;
3448 + flags |= MAP_ANONYMOUS;
3449 + }
3450 +
3451 + arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
3452 +
3453 + if(use_uncache_pages)
3454 + close(fd);
3455 +
3456 + assert(arena);
3457 +
3458 + return arena;
3459 +}
3460 +
3461 +static void dealloc_arena(cacheline_t* arena, size_t size)
3462 +{
3463 + int ret = munmap((void*)arena, size);
3464 + if(ret != 0)
3465 + die("munmap() error");
3466 +}
3467 +
3468 +static int randrange(int min, int max)
3469 +{
3470 + /* generate a random number on the range [min, max) w/o skew */
3471 + int limit = max - min;
3472 + int devisor = RAND_MAX/limit;
3473 + int retval;
3474 +
3475 + do {
3476 + retval = rand() / devisor;
3477 + } while(retval == limit);
3478 + retval += min;
3479 +
3480 + return retval;
3481 +}
3482 +
3483 +static void init_arena(cacheline_t* arena, size_t size)
3484 +{
3485 + int i;
3486 + size_t num_arena_elem = size / sizeof(cacheline_t);
3487 +
3488 + /* Generate a cycle among the cache lines using Sattolo's algorithm.
3489 + Every int in the cache line points to the same cache line.
3490 + Note: Sequential walk doesn't care about these values. */
3491 + for (i = 0; i < num_arena_elem; i++) {
3492 + int j;
3493 + for(j = 0; j < INTS_IN_CACHELINE; ++j)
3494 + arena[i].line[j] = i;
3495 + }
3496 + while(1 < i--) {
3497 + int j = randrange(0, i);
3498 + cacheline_t temp = arena[j];
3499 + arena[j] = arena[i];
3500 + arena[i] = temp;
3501 + }
3502 +}
3503 +
3504 +static void sleep_us(int microseconds)
3505 +{
3506 + struct timespec delay;
3507 +
3508 + delay.tv_sec = 0;
3509 + delay.tv_nsec = microseconds * 1000;
3510 + if (nanosleep(&delay, NULL) != 0)
3511 + die("sleep failed");
3512 +}
3513 +
3514 +static int completed(int nSamples, int* history, int nCategories)
3515 +{
3516 + int i;
3517 + for(i = 0; i < nCategories; ++i)
3518 + if(history[i] < nSamples)
3519 + return 0;
3520 + return 1;
3521 +}
3522 +
3523 +inline unsigned long get_cyclecount (void)
3524 +{
3525 + unsigned long value;
3526 + // Read CCNT Register
3527 + asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
3528 + return value;
3529 +}
3530 +
3531 +
3532 +#endif
3533 diff --git include/color_shm.h include/color_shm.h
3534 new file mode 100644
3535 index 0000000..449ec9d
3536 --- /dev/null
3537 +++ include/color_shm.h
3538 @@ -0,0 +1,20 @@
3539 +#include <sys/types.h>
3540 +#include <sys/ioctl.h>
3541 +#include <fcntl.h>
3542 +
3543 +#define SHM_MAJOR (240)
3544 +
3545 +struct color_ioctl_cmd {
3546 + unsigned int color;
3547 + unsigned int bank;
3548 +};
3549 +
3550 +struct color_ioctl_offset {
3551 + unsigned long offset;
3552 + int lock;
3553 +};
3554 +
3555 +#define SET_COLOR_SHM_CMD _IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd)
3556 +#define SET_COLOR_SHM_OFFSET _IOW(SHM_MAJOR, 0x2, struct color_ioctl_offset)
3557 +
3558 +void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset);
3559 diff --git include/litmus.h include/litmus.h
3560 index b9dbdb5..b70917e 100644
3561 --- include/litmus.h
3562 +++ include/litmus.h
3563 @@ -40,12 +40,22 @@ extern "C" {
3564
3565 #include "migration.h"
3566
3567 +#include "litmus/mc2_common.h"
3568 +
3569 /**
3570 * @private
3571 * The numeric ID of the LITMUS^RT scheduling class.
3572 */
3573 #define SCHED_LITMUS 7
3574
3575 +#define CACHELINE_SIZE 32
3576 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
3577 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
3578 +typedef struct cacheline
3579 +{
3580 + int line[INTS_IN_CACHELINE];
3581 +} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
3582 +
3583 /**
3584 * Initialise a real-time task param struct
3585 * @param param Pointer to the struct to initialise
3586 @@ -146,6 +156,12 @@ int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster);
3587 /** Convert microseconds to nanoseconds
3588 * @param us Time units in microseconds */
3589 #define us2ns(us) ((us)*1000LL)
3590 +#define ns2s(ns) ((ns)/1000000000LL)
3591 +#define ns2ms(ns) ((ns)/1000000LL)
3592 +#define ns2us(ns) ((ns)/1000LL)
3593 +#define us2ms(us) ((us)/1000LL)
3594 +#define us2s(us) ((us)/1000000LL)
3595 +#define ms2s(ms) ((ms)/1000LL)
3596
3597 /**
3598 * Locking protocols for allocated shared objects
3599 @@ -286,6 +302,12 @@ void exit_np(void);
3600 */
3601 int requested_to_preempt(void);
3602
3603 +/* pgm support */
3604 +void enter_pgm_wait(void);
3605 +void exit_pgm_wait(void);
3606 +void enter_pgm_send(void);
3607 +void exit_pgm_send(void);
3608 +
3609 /***** Task System support *****/
3610 /**
3611 * Wait until task master releases all real-time tasks
3612 @@ -416,6 +438,20 @@ int null_call(cycles_t *timestamp);
3613 */
3614 struct control_page* get_ctrl_page(void);
3615
3616 +int reservation_create(int rtype, void *config);
3617 +
3618 +int reservation_destroy(unsigned int reservation_id, int cpu);
3619 +
3620 +int set_mc2_task_param(pid_t pid, struct mc2_task* param);
3621 +
3622 +int set_page_color(int cpu);
3623 +
3624 +int test_call(unsigned int param);
3625 +
3626 +int run_bench(int type, int size, cacheline_t *src, cacheline_t *dst, lt_t __user *ts);
3627 +
3628 +int lock_buffer(void* vaddr, size_t size, unsigned int lock_way, unsigned int unlock_way);
3629 +
3630 #ifdef __cplusplus
3631 }
3632 #endif
3633 diff --git src/color_shm.c src/color_shm.c
3634 new file mode 100644
3635 index 0000000..15332aa
3636 --- /dev/null
3637 +++ src/color_shm.c
3638 @@ -0,0 +1,42 @@
3639 +#include <sys/mman.h>
3640 +#include <stdio.h>
3641 +#include <unistd.h>
3642 +
3643 +#include "color_shm.h"
3644 +
3645 +void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset)
3646 +{
3647 + int ret, fd;
3648 + void *mem;
3649 +
3650 + fd = open("/dev/litmus/color_shm", O_RDWR);
3651 + if (fd < 0) {
3652 + printf("Device open error.\n");
3653 + return NULL;
3654 + }
3655 +
3656 + ret = ioctl(fd, SET_COLOR_SHM_CMD, &cmd);
3657 + if (ret < 0) {
3658 + printf("ioctl failed.\n");
3659 + return NULL;
3660 + }
3661 +
3662 + ret = ioctl(fd, SET_COLOR_SHM_OFFSET, &offset);
3663 + if (ret < 0) {
3664 + printf("ioctl failed.\n");
3665 + return NULL;
3666 + }
3667 +
3668 + size += offset.offset;
3669 + mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
3670 + if (mem == MAP_FAILED) {
3671 + printf("mmap failed.\n");
3672 + return MAP_FAILED;
3673 + }
3674 + close(fd);
3675 +
3676 + mem += offset.offset;
3677 +
3678 + return mem;
3679 +}
3680 +
3681 diff --git src/kernel_iface.c src/kernel_iface.c
3682 index ca874ff..273ecb2 100644
3683 --- src/kernel_iface.c
3684 +++ src/kernel_iface.c
3685 @@ -2,7 +2,7 @@
3686 #include <sys/fcntl.h> /* for O_RDWR */
3687 #include <sys/unistd.h>
3688 #include <sched.h> /* for sched_yield() */
3689 -
3690 +#include <assert.h>
3691
3692 #include <stdio.h>
3693
3694 @@ -98,6 +98,8 @@ int init_kernel_iface(void)
3695 != LITMUS_CP_OFFSET_TS_SC_START);
3696 BUILD_BUG_ON(offsetof(struct control_page, irq_syscall_start)
3697 != LITMUS_CP_OFFSET_IRQ_SC_START);
3698 + BUILD_BUG_ON(offsetof(struct control_page, mode_poll_task)
3699 + != LITMUS_CP_OFFSET_MODE_POLL_TASK);
3700
3701 err = map_file(LITMUS_CTRL_DEVICE, &mapped_at, CTRL_PAGES * page_size);
3702
3703 @@ -110,7 +112,7 @@ int init_kernel_iface(void)
3704 fprintf(stderr, "%s: cannot open LITMUS^RT control page (%m)\n",
3705 __FUNCTION__);
3706 }
3707 -
3708 + ctrl_page->mode_poll_task = 0;
3709 return err;
3710 }
3711
3712 @@ -140,6 +142,63 @@ int requested_to_preempt(void)
3713 return (likely(ctrl_page != NULL) && ctrl_page->sched.np.preempt);
3714 }
3715
3716 +#ifdef CONFIG_PGMRT_SUPPORT
3717 +void enter_pgm_wait(void)
3718 +{
3719 + if (likely(ctrl_page != NULL) || init_kernel_iface() == 0) {
3720 + assert(!ctrl_page->pgm_waiting);
3721 + ctrl_page->pgm_waiting = 1;
3722 + __sync_synchronize();
3723 + }
3724 + else {
3725 + fprintf(stderr, "enter_pgm_wait: control page not mapped!\n");
3726 + }
3727 +}
3728 +
3729 +void exit_pgm_wait(void)
3730 +{
3731 + if (likely(ctrl_page != NULL)) {
3732 + assert(ctrl_page->pgm_waiting);
3733 + ctrl_page->pgm_waiting = 0;
3734 + __sync_synchronize();
3735 + }
3736 + else {
3737 + fprintf(stderr, "exit_pgm_wait: control page not mapped!\n");
3738 + }
3739 +}
3740 +
3741 +void enter_pgm_send(void)
3742 +{
3743 + if (likely(ctrl_page != NULL) || init_kernel_iface() == 0) {
3744 + assert(!ctrl_page->pgm_sending);
3745 + ctrl_page->pgm_sending = 1; /* we will become boosted if
3746 + anyone tries to preempt us. */
3747 + __sync_synchronize();
3748 + }
3749 + else {
3750 + fprintf(stderr, "enter_pgm_send: control page not mapped!\n");
3751 + }
3752 +}
3753 +
3754 +void exit_pgm_send(void)
3755 +{
3756 + if (likely(ctrl_page != NULL)) {
3757 + assert(ctrl_page->pgm_sending);
3758 +
3759 + ctrl_page->pgm_satisfied = 1;
3760 + __sync_synchronize();
3761 +
3762 + /* re-eval priority. Should clear pgm_sending and pgm_satisfied. */
3763 + sched_yield();
3764 +
3765 + /* double check that Litmus is doing its job */
3766 + assert(!ctrl_page->pgm_sending && !ctrl_page->pgm_satisfied);
3767 + }
3768 + else {
3769 + fprintf(stderr, "exit_pgm_send: control page not mapped!\n");
3770 + }
3771 +}
3772 +#endif
3773 /* init and return a ptr to the control page for
3774 * preemption and migration overhead analysis
3775 *
3776 diff --git src/syscalls.c src/syscalls.c
3777 index c68f15b..6ec0cd9 100644
3778 --- src/syscalls.c
3779 +++ src/syscalls.c
3780 @@ -86,3 +86,34 @@ int null_call(cycles_t *timestamp)
3781 {
3782 return syscall(__NR_null_call, timestamp);
3783 }
3784 +
3785 +int reservation_create(int rtype, void *config)
3786 +{
3787 + return syscall(__NR_reservation_create, rtype, config);
3788 +}
3789 +
3790 +int reservation_destroy(unsigned int reservation_id, int cpu)
3791 +{
3792 + return syscall(__NR_reservation_destroy, reservation_id, cpu);
3793 +}
3794 +
3795 +int set_mc2_task_param(pid_t pid, struct mc2_task *param)
3796 +{
3797 + return syscall(__NR_set_mc2_task_param, pid, param);
3798 +}
3799 +
3800 +int set_page_color(int cpu)
3801 +{
3802 + return syscall(__NR_set_page_color, cpu);
3803 +}
3804 +
3805 +int run_bench(int type, int wss, cacheline_t *src, cacheline_t *dst, lt_t *ts)
3806 +{
3807 + return syscall(__NR_run_test, type, wss, src, dst, ts);
3808 +}
3809 +
3810 +int lock_buffer(void* vaddr, size_t size, unsigned int lock_way, unsigned int unlock_way)
3811 +{
3812 + return syscall(__NR_lock_buffer, vaddr, size, lock_way, unlock_way);
3813 +}
3814 +
3815
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.