Attachment 'MC2-liblitmus-imx6-rtss15.patch'
Download 1 From 54ab0e29794e9f22aacd206102d9e4d643e28efe Mon Sep 17 00:00:00 2001
2 From: Bjoern Brandenburg <bbb@mpi-sws.org>
3 Date: Thu, 12 Jun 2014 13:32:21 +0200
4 Subject: [PATCH 1/7] Add test cases for enforcement of periods of periodic
5 tasks
6
7 ---
8 tests/sched.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 1 file changed, 83 insertions(+)
10
11 diff --git a/tests/sched.c b/tests/sched.c
12 index 6fd6d89..a91e736 100644
13 --- a/tests/sched.c
14 +++ b/tests/sched.c
15 @@ -1,6 +1,7 @@
16 #include <sys/wait.h> /* for waitpid() */
17 #include <unistd.h>
18 #include <stdio.h>
19 +#include <math.h>
20
21 #include "tests.h"
22 #include "litmus.h"
23 @@ -76,4 +77,86 @@ TESTCASE(preempt_on_resume, P_FP | PSN_EDF,
24 ASSERT( status == SIGUSR2);
25 }
26
27 +#define PERIOD 100 /* in ms */
28 +#define JOBS 10
29 +#define ACCEPTABLE_MARGIN 5 /* in ms --- must be largish for QEMU */
30
31 +TESTCASE(jobs_are_rate_limited, LITMUS,
32 + "periodic jobs are rate-limited (w/o synchronous release)")
33 +{
34 + struct rt_task params;
35 + double start, end, actual_delta_ms;
36 + int i;
37 +
38 + init_rt_task_param(¶ms);
39 + params.cpu = 0;
40 + params.exec_cost = ms2ns(40);
41 + params.period = ms2ns(PERIOD);
42 + params.release_policy = TASK_PERIODIC;
43 +
44 + SYSCALL( set_rt_task_param(gettid(), ¶ms) );
45 + SYSCALL( be_migrate_to_cpu(params.cpu) );
46 + SYSCALL( task_mode(LITMUS_RT_TASK) );
47 +
48 + start = wctime();
49 + for (i = 0; i < JOBS; i++)
50 + SYSCALL( sleep_next_period() );
51 + end = wctime();
52 +
53 + SYSCALL( task_mode(BACKGROUND_TASK) );
54 +
55 + actual_delta_ms = (end - start) * 1000.0;
56 + if (fabs(JOBS * PERIOD - actual_delta_ms) > ACCEPTABLE_MARGIN)
57 + fprintf(stderr, "actual_delta_ms:%.4f expected:%.4f\n",
58 + actual_delta_ms, (double) (JOBS * PERIOD));
59 + ASSERT( fabs(JOBS * PERIOD - actual_delta_ms) <= ACCEPTABLE_MARGIN);
60 +}
61 +
62 +TESTCASE(jobs_are_rate_limited_synch, LITMUS,
63 + "periodic jobs are rate-limited (w/ synchronous release)")
64 +{
65 + struct rt_task params;
66 + double start, end, actual_delta_ms;
67 + int i;
68 + int child, status, waiters;
69 + lt_t delay = ms2ns(100);
70 +
71 + child = FORK_TASK(
72 + init_rt_task_param(¶ms);
73 + params.cpu = 0;
74 + params.exec_cost = ms2ns(5);
75 + params.period = ms2ns(PERIOD);
76 + params.release_policy = TASK_PERIODIC;
77 +
78 + SYSCALL( set_rt_task_param(gettid(), ¶ms) );
79 + SYSCALL( be_migrate_to_cpu(params.cpu) );
80 + SYSCALL( task_mode(LITMUS_RT_TASK) );
81 +
82 + SYSCALL( wait_for_ts_release() );
83 +
84 + start = wctime();
85 + for (i = 0; i < JOBS; i++)
86 + SYSCALL( sleep_next_period() );
87 + end = wctime();
88 +
89 + SYSCALL( task_mode(BACKGROUND_TASK) );
90 +
91 + actual_delta_ms = (end - start) * 1000.0;
92 + if (fabs(JOBS * PERIOD - actual_delta_ms) > ACCEPTABLE_MARGIN)
93 + fprintf(stderr, "actual_delta_ms:%.4f expected:%.4f\n",
94 + actual_delta_ms, (double) (JOBS * PERIOD));
95 + ASSERT( fabs(JOBS * PERIOD - actual_delta_ms) <= ACCEPTABLE_MARGIN);
96 + );
97 +
98 + do {
99 + waiters = get_nr_ts_release_waiters();
100 + ASSERT( waiters >= 0 );
101 + } while (waiters != 1);
102 +
103 + waiters = release_ts(&delay);
104 +
105 +
106 + /* wait for child to exit */
107 + SYSCALL( waitpid(child, &status, 0) );
108 + ASSERT( status == 0 );
109 +}
110 --
111 1.9.1
112
113
114 From a83d1f59605a06fc22b399b38ce4b831d38b6442 Mon Sep 17 00:00:00 2001
115 From: Bjoern Brandenburg <bbb@mpi-sws.org>
116 Date: Thu, 17 Jul 2014 18:01:42 +0200
117 Subject: [PATCH 2/7] Add reservation-related system calls
118
119 ---
120 include/litmus.h | 5 +++++
121 src/syscalls.c | 10 ++++++++++
122 2 files changed, 15 insertions(+)
123
124 diff --git a/include/litmus.h b/include/litmus.h
125 index f99ccec..3bd6b92 100644
126 --- a/include/litmus.h
127 +++ b/include/litmus.h
128 @@ -416,6 +416,11 @@ int null_call(cycles_t *timestamp);
129 */
130 struct control_page* get_ctrl_page(void);
131
132 +int reservation_create(int rtype, void *config);
133 +
134 +int reservation_destroy(unsigned int reservation_id, int cpu);
135 +
136 +
137 #ifdef __cplusplus
138 }
139 #endif
140 diff --git a/src/syscalls.c b/src/syscalls.c
141 index c68f15b..fbb8604 100644
142 --- a/src/syscalls.c
143 +++ b/src/syscalls.c
144 @@ -86,3 +86,13 @@ int null_call(cycles_t *timestamp)
145 {
146 return syscall(__NR_null_call, timestamp);
147 }
148 +
149 +int reservation_create(int rtype, void *config)
150 +{
151 + return syscall(__NR_reservation_create, rtype, config);
152 +}
153 +
154 +int reservation_destroy(unsigned int reservation_id, int cpu)
155 +{
156 + return syscall(__NR_reservation_destroy, reservation_id, cpu);
157 +}
158 --
159 1.9.1
160
161
162 From 8d323049edd004c25f370468aa30cdf1ba76e735 Mon Sep 17 00:00:00 2001
163 From: Bjoern Brandenburg <bbb@mpi-sws.org>
164 Date: Tue, 22 Jul 2014 07:46:57 +0200
165 Subject: [PATCH 3/7] Add -r (reservation) and -v (verbose) flags to rtspin
166
167 The -r flag allows specifying a "virtual CPU" (in addition to a
168 physcial CPU to migrate to) that may be interpreted by a scheduler
169 plugin to refer to a reservation to which the task should be added.
170
171 The -v flag causes rtspin to output timing information on stdout and
172 can be useful for early-stage plugin debugging (to see that something
173 is happening at all).
174 ---
175 bin/rtspin.c | 35 ++++++++++++++++++++++++++++-------
176 1 file changed, 28 insertions(+), 7 deletions(-)
177
178 diff --git a/bin/rtspin.c b/bin/rtspin.c
179 index b4156cc..ea7f192 100644
180 --- a/bin/rtspin.c
181 +++ b/bin/rtspin.c
182 @@ -184,7 +184,7 @@ static int job(double exec_time, double program_end, int lock_od, double cs_leng
183 }
184 }
185
186 -#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:"
187 +#define OPTSTR "p:c:wlveo:f:s:q:r:X:L:Q:v"
188 int main(int argc, char** argv)
189 {
190 int ret;
191 @@ -194,6 +194,7 @@ int main(int argc, char** argv)
192 unsigned int priority = LITMUS_LOWEST_PRIORITY;
193 int migrate = 0;
194 int cluster = 0;
195 + int reservation = -1;
196 int opt;
197 int wait = 0;
198 int test_loop = 0;
199 @@ -207,6 +208,9 @@ int main(int argc, char** argv)
200 int cur_job = 0, num_jobs = 0;
201 struct rt_task param;
202
203 + int verbose = 0;
204 + unsigned int job_no;
205 +
206 /* locking */
207 int lock_od = -1;
208 int resource_id = 0;
209 @@ -225,6 +229,9 @@ int main(int argc, char** argv)
210 cluster = atoi(optarg);
211 migrate = 1;
212 break;
213 + case 'r':
214 + reservation = atoi(optarg);
215 + break;
216 case 'q':
217 priority = atoi(optarg);
218 if (!litmus_is_valid_fixed_prio(priority))
219 @@ -265,6 +272,9 @@ int main(int argc, char** argv)
220 if (resource_id <= 0 && strcmp(optarg, "0"))
221 usage("Invalid resource ID.");
222 break;
223 + case 'v':
224 + verbose = 1;
225 + break;
226 case ':':
227 usage("Argument missing.");
228 break;
229 @@ -334,14 +344,19 @@ int main(int argc, char** argv)
230 param.cls = class;
231 param.budget_policy = (want_enforcement) ?
232 PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
233 - if (migrate)
234 - param.cpu = domain_to_first_cpu(cluster);
235 + if (migrate) {
236 + if (reservation >= 0)
237 + param.cpu = reservation;
238 + else
239 + param.cpu = domain_to_first_cpu(cluster);
240 + }
241 ret = set_rt_task_param(gettid(), ¶m);
242 if (ret < 0)
243 bail_out("could not setup rt task params");
244
245 init_litmus();
246
247 + start = wctime();
248 ret = task_mode(LITMUS_RT_TASK);
249 if (ret != 0)
250 bail_out("could not become RT task");
251 @@ -355,14 +370,14 @@ int main(int argc, char** argv)
252 }
253 }
254
255 +
256 if (wait) {
257 ret = wait_for_ts_release();
258 if (ret != 0)
259 bail_out("wait_for_ts_release()");
260 + start = wctime();
261 }
262
263 - start = wctime();
264 -
265 if (file) {
266 /* use times read from the CSV file */
267 for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
268 @@ -372,8 +387,14 @@ int main(int argc, char** argv)
269 lock_od, cs_length * 0.001);
270 }
271 } else {
272 - /* convert to seconds and scale */
273 - while (job(wcet_ms * 0.001 * scale, start + duration,
274 + do {
275 + if (verbose) {
276 + get_job_no(&job_no);
277 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
278 + job_no, (wctime() - start) * 1000);
279 + }
280 + /* convert to seconds and scale */
281 + } while (job(wcet_ms * 0.001 * scale, start + duration,
282 lock_od, cs_length * 0.001));
283 }
284
285 --
286 1.9.1
287
288
289 From a2675ecbfb665f5f9de5f541d7d22c6710b4ff97 Mon Sep 17 00:00:00 2001
290 From: Bjoern Brandenburg <bbb@mpi-sws.org>
291 Date: Tue, 22 Jul 2014 07:53:03 +0200
292 Subject: [PATCH 4/7] Add resctrl, a tool for setting up reservations
293
294 resctrl is a new tool intended to configure reservations in
295 reservation-aware plugins. For now, it only supports the partitioned
296 reservations (P-RES) plugin.
297
298 (While at it, also update .gitignore)
299 ---
300 .gitignore | 7 ++
301 Makefile | 5 +-
302 bin/resctrl.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
303 3 files changed, 246 insertions(+), 1 deletion(-)
304 create mode 100644 bin/resctrl.c
305
306 diff --git a/.gitignore b/.gitignore
307 index a52500b..f79d4fa 100644
308 --- a/.gitignore
309 +++ b/.gitignore
310 @@ -3,10 +3,13 @@
311 *.a
312
313
314 +# editor backup files
315 +*~
316
317 # generated files
318 tests/test_catalog.inc
319 *.d
320 +*.d.*
321 docs/
322
323 # executables
324 @@ -23,6 +26,8 @@ showst
325 rtspin
326 cycles
327 measure_syscall
328 +uncache
329 +resctrl
330
331 # build system files
332 .config
333 @@ -32,3 +37,5 @@ test_catalog.inc
334 # files copied in from the kernel tree
335 include/litmus
336 arch/*/include/asm
337 +arch/x86/include/generated
338 +arch/x86/include/uapi
339 diff --git a/Makefile b/Makefile
340 index 4742fd2..34c428f 100644
341 --- a/Makefile
342 +++ b/Makefile
343 @@ -73,7 +73,7 @@ AR := ${CROSS_COMPILE}${AR}
344
345 all = lib ${rt-apps}
346 rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
347 - base_mt_task uncache runtests
348 + base_mt_task uncache runtests resctrl
349
350 .PHONY: all lib clean dump-config TAGS tags cscope help doc
351
352 @@ -234,6 +234,9 @@ obj-release_ts = release_ts.o
353 obj-measure_syscall = null_call.o
354 lib-measure_syscall = -lm
355
356 +obj-resctrl = resctrl.o
357 +
358 +
359 # ##############################################################################
360 # Build everything that depends on liblitmus.
361
362 diff --git a/bin/resctrl.c b/bin/resctrl.c
363 new file mode 100644
364 index 0000000..917f49a
365 --- /dev/null
366 +++ b/bin/resctrl.c
367 @@ -0,0 +1,235 @@
368 +#include <stdio.h>
369 +#include <stdlib.h>
370 +#include <string.h>
371 +#include <unistd.h>
372 +#include <limits.h>
373 +#include <signal.h>
374 +
375 +#include <sched.h>
376 +
377 +#include "litmus.h"
378 +#include "common.h"
379 +
380 +const char *usage_msg =
381 + "Usage: resctrl OPTIONS [INTERVAL-START,INTERVAL-END]*\n"
382 + " -n ID create new reservation with id ID\n"
383 + " -a PID attach already-running process PID to reservation\n"
384 + " -r ID specify which reservation to attach to (not needed with -n)\n"
385 + " -t TYPE type of reservation (polling-periodic, polling-sporadic, table-driven)\n"
386 + " -c CPU physical partition or cluster to assign to\n"
387 + " -b BUDGET polling reservation budget (in ms, default: 10ms)\n"
388 + " -p PERIOD polling reservation period (in ms, default: 100ms)\n"
389 + " -d DEADLINE relative deadline, implicit by default (in ms)\n"
390 + " -o OFFSET offset (also known as phase), zero by default (in ms)\n"
391 + " -q PRIORITY priority to use (EDF by default, max=0)\n"
392 + " -m MAJOR-CYCLE major cycle length (in ms, for table-driven reservations) \n"
393 + "\n";
394 +
395 +void usage(char *error) {
396 + fprintf(stderr, "%s\n%s", error, usage_msg);
397 + exit(1);
398 +}
399 +
400 +
401 +static void attach_task(int attach_pid, struct reservation_config *config)
402 +{
403 + int ret;
404 + struct rt_task param;
405 + struct sched_param linux_param;
406 +
407 + ret = be_migrate_thread_to_cpu(attach_pid, config->cpu);
408 + if (ret < 0) {
409 + fprintf(stderr, "failed to migrate task %d to CPU %d\n",
410 + attach_pid, config->cpu);
411 + exit(4);
412 + }
413 +
414 + init_rt_task_param(¶m);
415 + /* dummy values */
416 + param.exec_cost = ms2ns(100);
417 + param.period = ms2ns(100);
418 + /* specify reservation as "virtual" CPU */
419 + param.cpu = config->id;
420 +
421 + ret = set_rt_task_param(attach_pid, ¶m);
422 + if (ret < 0) {
423 + fprintf(stderr, "failed to set RT task parameters for task %d (%m)\n",
424 + attach_pid);
425 + exit(2);
426 + }
427 +
428 + linux_param.sched_priority = 0;
429 + ret = sched_setscheduler(attach_pid, SCHED_LITMUS, &linux_param);
430 + if (ret < 0) {
431 + fprintf(stderr, "failed to transition task %d to LITMUS^RT class (%m)\n",
432 + attach_pid);
433 + exit(3);
434 + }
435 +}
436 +
437 +static struct lt_interval* parse_td_intervals(int argc, char** argv,
438 + unsigned int *num_intervals, lt_t major_cycle)
439 +{
440 + int i, matched;
441 + struct lt_interval *slots = malloc(sizeof(slots[0]) * argc);
442 + double start, end;
443 +
444 + *num_intervals = 0;
445 + for (i = 0; i < argc; i++) {
446 + matched = sscanf(argv[i], "[%lf,%lf]", &start, &end);
447 + if (matched != 2) {
448 + fprintf(stderr, "could not parse '%s' as interval\n", argv[i]);
449 + exit(5);
450 + }
451 + if (start < 0) {
452 + fprintf(stderr, "interval %s: must not start before zero\n", argv[i]);
453 + exit(5);
454 + }
455 + if (end <= start) {
456 + fprintf(stderr, "interval %s: end before start\n", argv[i]);
457 + exit(5);
458 + }
459 +
460 + slots[i].start = ms2ns(start);
461 + slots[i].end = ms2ns(end);
462 +
463 + if (i > 0 && slots[i - 1].end >= slots[i].start) {
464 + fprintf(stderr, "interval %s: overlaps with previous interval\n", argv[i]);
465 + exit(5);
466 + }
467 +
468 + if (slots[i].end >= major_cycle) {
469 + fprintf(stderr, "interval %s: exceeds major cycle length\n", argv[i]);
470 + exit(5);
471 + }
472 +
473 + (*num_intervals)++;
474 + }
475 +
476 + return slots;
477 +}
478 +
479 +#define OPTSTR "n:a:r:t:c:b:p:d:o:q:m:h"
480 +
481 +int main(int argc, char** argv)
482 +{
483 + int ret, opt;
484 + double budget_ms, period_ms, offset_ms, deadline_ms, major_cycle_ms;
485 + int create_new = 0;
486 + int attach_pid = 0;
487 + int res_type = SPORADIC_POLLING;
488 +
489 + struct reservation_config config;
490 +
491 + /* Reasonable defaults */
492 + offset_ms = 0;
493 + deadline_ms = 0;
494 + budget_ms = 10;
495 + period_ms = 100;
496 + major_cycle_ms = 1000;
497 +
498 + config.id = 0;
499 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
500 + config.cpu = 0;
501 +
502 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
503 + switch (opt) {
504 + case 'b':
505 + budget_ms = atof(optarg);
506 + break;
507 + case 'p':
508 + period_ms = atof(optarg);
509 + break;
510 + case 'd':
511 + deadline_ms = atof(optarg);
512 + if (deadline_ms <= 0) {
513 + usage("The relative deadline must be a positive"
514 + " number.");
515 + }
516 + break;
517 + case 'o':
518 + offset_ms = atof(optarg);
519 + break;
520 + case 'm':
521 + major_cycle_ms = atof(optarg);
522 + break;
523 +
524 + case 'q':
525 + config.priority = atoi(optarg);
526 + break;
527 + case 'c':
528 + config.cpu = atoi(optarg);
529 + break;
530 +
531 + case 'n':
532 + create_new = 1;
533 + config.id = atoi(optarg);
534 + break;
535 + case 'a':
536 + attach_pid = atoi(optarg);
537 + if (!attach_pid)
538 + usage("-a: invalid PID");
539 + break;
540 +
541 + case 'r':
542 + config.id = atoi(optarg);
543 + break;
544 +
545 + case 't':
546 + if (strcmp(optarg, "polling-periodic") == 0) {
547 + res_type = PERIODIC_POLLING;
548 + } else if (strcmp(optarg, "polling-sporadic") == 0) {
549 + res_type = SPORADIC_POLLING;
550 + } else if (strcmp(optarg, "table-driven") == 0) {
551 + res_type = TABLE_DRIVEN;
552 + } else {
553 + usage("Unknown reservation type.");
554 + }
555 + break;
556 +
557 + case 'h':
558 + usage("");
559 + break;
560 + case ':':
561 + usage("Argument missing.");
562 + break;
563 + case '?':
564 + default:
565 + usage("Bad argument.");
566 + break;
567 + }
568 + }
569 +
570 + if (res_type != TABLE_DRIVEN) {
571 + config.polling_params.budget = ms2ns(budget_ms);
572 + config.polling_params.period = ms2ns(period_ms);
573 + config.polling_params.offset = ms2ns(offset_ms);
574 + config.polling_params.relative_deadline = ms2ns(deadline_ms);
575 + if (config.polling_params.budget > config.polling_params.period) {
576 + usage("The budget must not exceed the period.");
577 + }
578 + } else {
579 + config.table_driven_params.major_cycle_length = ms2ns(major_cycle_ms);
580 + argc -= optind;
581 + argv += optind;
582 + config.table_driven_params.intervals = parse_td_intervals(
583 + argc, argv, &config.table_driven_params.num_intervals,
584 + config.table_driven_params.major_cycle_length);
585 + if (!config.table_driven_params.num_intervals)
586 + usage("Table-driven reservations require at least one interval to be specified.");
587 + }
588 +
589 + if (create_new) {
590 + ret = reservation_create(res_type, &config);
591 + if (ret < 0) {
592 + fprintf(stderr, "failed to create reservation %u (%m)\n",
593 + config.id);
594 + exit(1);
595 + }
596 + }
597 +
598 + if (attach_pid)
599 + attach_task(attach_pid, &config);
600 +
601 + return 0;
602 +}
603 --
604 1.9.1
605
606
607 From d7d397d028d6c755cff140f2ef54537f608d3e62 Mon Sep 17 00:00:00 2001
608 From: Bjoern Brandenburg <bbb@mpi-sws.org>
609 Date: Mon, 8 Sep 2014 17:42:49 +0200
610 Subject: [PATCH 5/7] resctrl: default to max. priority for table-driven
611 reservations
612
613 Table-driven reservations should always have the maximum fixed
614 priority. Thus default to this behavior, both for convenience and to
615 avoid accidental misconfiguration.
616 ---
617 bin/resctrl.c | 9 ++++++++-
618 1 file changed, 8 insertions(+), 1 deletion(-)
619
620 diff --git a/bin/resctrl.c b/bin/resctrl.c
621 index 917f49a..63b5054 100644
622 --- a/bin/resctrl.c
623 +++ b/bin/resctrl.c
624 @@ -21,7 +21,7 @@ const char *usage_msg =
625 " -p PERIOD polling reservation period (in ms, default: 100ms)\n"
626 " -d DEADLINE relative deadline, implicit by default (in ms)\n"
627 " -o OFFSET offset (also known as phase), zero by default (in ms)\n"
628 - " -q PRIORITY priority to use (EDF by default, max=0)\n"
629 + " -q PRIORITY priority to use (EDF by default, highest priority = 1)\n"
630 " -m MAJOR-CYCLE major cycle length (in ms, for table-driven reservations) \n"
631 "\n";
632
633 @@ -156,6 +156,8 @@ int main(int argc, char** argv)
634
635 case 'q':
636 config.priority = atoi(optarg);
637 + if (!config.priority)
638 + usage("-q: invalid priority");
639 break;
640 case 'c':
641 config.cpu = atoi(optarg);
642 @@ -182,6 +184,11 @@ int main(int argc, char** argv)
643 res_type = SPORADIC_POLLING;
644 } else if (strcmp(optarg, "table-driven") == 0) {
645 res_type = TABLE_DRIVEN;
646 + /* Default for table-driven reservations to
647 + * maximum priority. EDF has not meaning for
648 + * table-driven reservations. */
649 + if (config.priority == LITMUS_NO_PRIORITY)
650 + config.priority = LITMUS_HIGHEST_PRIORITY;
651 } else {
652 usage("Unknown reservation type.");
653 }
654 --
655 1.9.1
656
657
658 From 5fd42b4dc877890668affe69f8cecc968e277148 Mon Sep 17 00:00:00 2001
659 From: Namhoon Kim <namhoonk@cs.unc.edu>
660 Date: Thu, 8 Jan 2015 14:04:12 -0500
661 Subject: [PATCH 6/7] Added mc2spin
662
663 ---
664 Makefile | 7 +-
665 bin/mc2spin.c | 541 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
666 include/litmus.h | 3 +
667 mc2spin | Bin 0 -> 102692 bytes
668 src/syscalls.c | 5 +
669 5 files changed, 554 insertions(+), 2 deletions(-)
670 create mode 100644 bin/mc2spin.c
671 create mode 100755 mc2spin
672
673 diff --git a/Makefile b/Makefile
674 index 34c428f..70e79d4 100644
675 --- a/Makefile
676 +++ b/Makefile
677 @@ -73,7 +73,7 @@ AR := ${CROSS_COMPILE}${AR}
678
679 all = lib ${rt-apps}
680 rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
681 - base_mt_task uncache runtests resctrl
682 + base_mt_task uncache runtests resctrl mc2spin
683
684 .PHONY: all lib clean dump-config TAGS tags cscope help doc
685
686 @@ -168,7 +168,8 @@ litmus-headers = \
687 include/litmus/rt_param.h \
688 include/litmus/fpmath.h \
689 include/litmus/unistd_32.h \
690 - include/litmus/unistd_64.h
691 + include/litmus/unistd_64.h \
692 + include/litmus/mc2_common.h
693
694 unistd-headers = \
695 $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/$(file))
696 @@ -236,6 +237,8 @@ lib-measure_syscall = -lm
697
698 obj-resctrl = resctrl.o
699
700 +obj-mc2spin = mc2spin.o common.o
701 +lib-mc2spin = -lrt
702
703 # ##############################################################################
704 # Build everything that depends on liblitmus.
705 diff --git a/bin/mc2spin.c b/bin/mc2spin.c
706 new file mode 100644
707 index 0000000..1ef3082
708 --- /dev/null
709 +++ b/bin/mc2spin.c
710 @@ -0,0 +1,541 @@
711 +#include <sys/time.h>
712 +
713 +#include <stdio.h>
714 +#include <stdlib.h>
715 +#include <unistd.h>
716 +#include <time.h>
717 +#include <string.h>
718 +#include <assert.h>
719 +#include <limits.h>
720 +
721 +
722 +#include "litmus.h"
723 +#include "common.h"
724 +
725 +
726 +
727 +static void usage(char *error) {
728 + fprintf(stderr, "Error: %s\n", error);
729 + fprintf(stderr,
730 + "Usage:\n"
731 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
732 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
733 + " rt_spin -l\n"
734 + "\n"
735 + "COMMON-OPTS = [-w] [-s SCALE]\n"
736 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
737 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
738 + " [-i [start,end]:[start,end]...]\n"
739 + "\n"
740 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
741 + "CRITICAL SECTION LENGTH is in milliseconds.\n");
742 + exit(EXIT_FAILURE);
743 +}
744 +
745 +/*
746 + * returns the character that made processing stop, newline or EOF
747 + */
748 +static int skip_to_next_line(FILE *fstream)
749 +{
750 + int ch;
751 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
752 + return ch;
753 +}
754 +
755 +static void skip_comments(FILE *fstream)
756 +{
757 + int ch;
758 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
759 + skip_to_next_line(fstream);
760 + ungetc(ch, fstream);
761 +}
762 +
763 +static void get_exec_times(const char *file, const int column,
764 + int *num_jobs, double **exec_times)
765 +{
766 + FILE *fstream;
767 + int cur_job, cur_col, ch;
768 + *num_jobs = 0;
769 +
770 + fstream = fopen(file, "r");
771 + if (!fstream)
772 + bail_out("could not open execution time file");
773 +
774 + /* figure out the number of jobs */
775 + do {
776 + skip_comments(fstream);
777 + ch = skip_to_next_line(fstream);
778 + if (ch != EOF)
779 + ++(*num_jobs);
780 + } while (ch != EOF);
781 +
782 + if (-1 == fseek(fstream, 0L, SEEK_SET))
783 + bail_out("rewinding file failed");
784 +
785 + /* allocate space for exec times */
786 + *exec_times = calloc(*num_jobs, sizeof(*exec_times));
787 + if (!*exec_times)
788 + bail_out("couldn't allocate memory");
789 +
790 + for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
791 +
792 + skip_comments(fstream);
793 +
794 + for (cur_col = 1; cur_col < column; ++cur_col) {
795 + /* discard input until we get to the column we want */
796 + int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
797 + }
798 +
799 + /* get the desired exec. time */
800 + if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
801 + fprintf(stderr, "invalid execution time near line %d\n",
802 + cur_job);
803 + exit(EXIT_FAILURE);
804 + }
805 +
806 + skip_to_next_line(fstream);
807 + }
808 +
809 + assert(cur_job == *num_jobs);
810 + fclose(fstream);
811 +}
812 +
813 +#define NUMS 4096
814 +static int num[NUMS];
815 +static char* progname;
816 +
817 +static int loop_once(void)
818 +{
819 + int i, j = 0;
820 + for (i = 0; i < NUMS; i++)
821 + j += num[i]++;
822 + return j;
823 +}
824 +
825 +static int loop_for(double exec_time, double emergency_exit)
826 +{
827 + double last_loop = 0, loop_start;
828 + int tmp = 0;
829 +
830 + double start = cputime();
831 + double now = cputime();
832 +
833 + while (now + last_loop < start + exec_time) {
834 + loop_start = now;
835 + tmp += loop_once();
836 + now = cputime();
837 + last_loop = now - loop_start;
838 + if (emergency_exit && wctime() > emergency_exit) {
839 + /* Oops --- this should only be possible if the execution time tracking
840 + * is broken in the LITMUS^RT kernel. */
841 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
842 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
843 + break;
844 + }
845 + }
846 +
847 + return tmp;
848 +}
849 +
850 +
851 +static void debug_delay_loop(void)
852 +{
853 + double start, end, delay;
854 +
855 + while (1) {
856 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
857 + start = wctime();
858 + loop_for(delay, 0);
859 + end = wctime();
860 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
861 + delay,
862 + end - start,
863 + end - start - delay,
864 + 100 * (end - start - delay) / delay);
865 + }
866 + }
867 +}
868 +
869 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
870 +{
871 + double chunk1, chunk2;
872 +
873 + if (wctime() > program_end)
874 + return 0;
875 + else {
876 + if (lock_od >= 0) {
877 + /* simulate critical section somewhere in the middle */
878 + chunk1 = drand48() * (exec_time - cs_length);
879 + chunk2 = exec_time - cs_length - chunk1;
880 +
881 + /* non-critical section */
882 + loop_for(chunk1, program_end + 1);
883 +
884 + /* critical section */
885 + litmus_lock(lock_od);
886 + loop_for(cs_length, program_end + 1);
887 + litmus_unlock(lock_od);
888 +
889 + /* non-critical section */
890 + loop_for(chunk2, program_end + 2);
891 + } else {
892 + loop_for(exec_time, program_end + 1);
893 + }
894 + sleep_next_period();
895 + return 1;
896 + }
897 +}
898 +
899 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
900 +{
901 + int i, matched;
902 + struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
903 + char** arg = (char**)malloc(sizeof(char*) * num);
904 + char *token, *saveptr;
905 + double start, end;
906 +
907 + for (i = 0; i < num; i++) {
908 + arg[i] = (char*)malloc(sizeof(char)*100);
909 + }
910 +
911 + i = 0;
912 + token = strtok_r(optarg, ":", &saveptr);
913 + while(token != NULL) {
914 + sprintf(arg[i++], "%s", token);
915 + token = strtok_r(NULL, ":", &saveptr);
916 + }
917 +
918 + *num_intervals = 0;
919 +
920 + for (i=0; i<num; i++) {
921 + matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
922 + if (matched != 2) {
923 + fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
924 + exit(5);
925 + }
926 + if (start < 0) {
927 + fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
928 + exit(5);
929 + }
930 + if (end <= start) {
931 + fprintf(stderr, "interval %s: end before start\n", arg[i]);
932 + exit(5);
933 + }
934 +
935 + slots[i].start = ms2ns(start);
936 + slots[i].end = ms2ns(end);
937 +
938 + if (i > 0 && slots[i - 1].end >= slots[i].start) {
939 + fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
940 + exit(5);
941 + }
942 +
943 + (*num_intervals)++;
944 + }
945 +
946 + for (i=0; i<num; i++) {
947 + free(arg[i]);
948 + }
949 + free(arg);
950 + return slots;
951 +}
952 +
953 +#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:"
954 +int main(int argc, char** argv)
955 +{
956 + int ret;
957 + lt_t wcet;
958 + lt_t period;
959 + lt_t hyperperiod;
960 + lt_t budget;
961 + double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
962 + unsigned int priority = LITMUS_LOWEST_PRIORITY;
963 + int migrate = 0;
964 + int cluster = 0;
965 + int opt;
966 + int wait = 0;
967 + int test_loop = 0;
968 + int column = 1;
969 + const char *file = NULL;
970 + int want_enforcement = 0;
971 + double duration = 0, start = 0;
972 + double *exec_times = NULL;
973 + double scale = 1.0;
974 + task_class_t class = RT_CLASS_HARD;
975 + int cur_job = 0, num_jobs = 0;
976 + struct rt_task param;
977 + struct mc2_task mc2_param;
978 + struct reservation_config config;
979 + int res_type = SPORADIC_POLLING;
980 + int n_str, num_int = 0;
981 +
982 + int verbose = 0;
983 + unsigned int job_no;
984 +
985 + /* locking */
986 + int lock_od = -1;
987 + int resource_id = 0;
988 + const char *lock_namespace = "./rtspin-locks";
989 + int protocol = -1;
990 + double cs_length = 1; /* millisecond */
991 +
992 + progname = argv[0];
993 +
994 + /* default for reservation */
995 + config.id = 0;
996 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
997 + config.cpu = 0;
998 +
999 + mc2_param.crit = CRIT_LEVEL_C;
1000 +
1001 + hyperperiod_ms = 1000;
1002 + budget_ms = 10;
1003 +
1004 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1005 + switch (opt) {
1006 + case 'w':
1007 + wait = 1;
1008 + break;
1009 + case 'p':
1010 + cluster = atoi(optarg);
1011 + migrate = 1;
1012 + config.cpu = cluster;
1013 + break;
1014 + case 'q':
1015 + priority = atoi(optarg);
1016 + if (!litmus_is_valid_fixed_prio(priority))
1017 + usage("Invalid priority.");
1018 + break;
1019 + case 'c':
1020 + class = str2class(optarg);
1021 + if (class == -1)
1022 + usage("Unknown task class.");
1023 + break;
1024 + case 'e':
1025 + want_enforcement = 1;
1026 + break;
1027 + case 'l':
1028 + test_loop = 1;
1029 + break;
1030 + case 'o':
1031 + column = atoi(optarg);
1032 + break;
1033 + case 'f':
1034 + file = optarg;
1035 + break;
1036 + case 's':
1037 + scale = atof(optarg);
1038 + break;
1039 + case 'X':
1040 + protocol = lock_protocol_for_name(optarg);
1041 + if (protocol < 0)
1042 + usage("Unknown locking protocol specified.");
1043 + break;
1044 + case 'L':
1045 + cs_length = atof(optarg);
1046 + if (cs_length <= 0)
1047 + usage("Invalid critical section length.");
1048 + break;
1049 + case 'Q':
1050 + resource_id = atoi(optarg);
1051 + if (resource_id <= 0 && strcmp(optarg, "0"))
1052 + usage("Invalid resource ID.");
1053 + break;
1054 + case 'v':
1055 + verbose = 1;
1056 + break;
1057 + case 'm':
1058 + mc2_param.crit = atoi(optarg);
1059 + if (mc2_param.crit == CRIT_LEVEL_A) {
1060 + res_type = TABLE_DRIVEN;
1061 + }
1062 + else if (mc2_param.crit == CRIT_LEVEL_B) {
1063 + res_type = PERIODIC_POLLING;
1064 + }
1065 + else
1066 + usage("Invalid criticality level.");
1067 + break;
1068 + case 'h':
1069 + hyperperiod_ms = atof(optarg);
1070 + break;
1071 + case 'b':
1072 + budget_ms = atof(optarg);
1073 + break;
1074 + case 'i':
1075 + n_str = strlen(optarg);
1076 + while(n_str--) {
1077 + if (optarg[n_str] == ',')
1078 + num_int++;
1079 + }
1080 + if (!num_int)
1081 + usage("Bad argument.");
1082 + config.table_driven_params.intervals = parse_td_intervals(num_int, optarg, &config.table_driven_params.num_intervals);
1083 + break;
1084 + case ':':
1085 + usage("Argument missing.");
1086 + break;
1087 + case '?':
1088 + default:
1089 + usage("Bad argument.");
1090 + break;
1091 + }
1092 + }
1093 +
1094 + if (test_loop) {
1095 + debug_delay_loop();
1096 + return 0;
1097 + }
1098 +
1099 + srand(getpid());
1100 +
1101 + if (file) {
1102 + get_exec_times(file, column, &num_jobs, &exec_times);
1103 +
1104 + if (argc - optind < 2)
1105 + usage("Arguments missing.");
1106 +
1107 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1108 + /* convert the execution time to seconds */
1109 + duration += exec_times[cur_job] * 0.001;
1110 + }
1111 + } else {
1112 + /*
1113 + * if we're not reading from the CSV file, then we need
1114 + * three parameters
1115 + */
1116 + if (argc - optind < 3)
1117 + usage("Arguments missing.");
1118 + }
1119 +
1120 + wcet_ms = atof(argv[optind + 0]);
1121 + period_ms = atof(argv[optind + 1]);
1122 +
1123 + wcet = ms2ns(wcet_ms);
1124 + period = ms2ns(period_ms);
1125 + budget = ms2ns(budget_ms);
1126 + hyperperiod = ms2ns(hyperperiod_ms);
1127 +
1128 + if (wcet <= 0)
1129 + usage("The worst-case execution time must be a "
1130 + "positive number.");
1131 + if (period <= 0)
1132 + usage("The period must be a positive number.");
1133 + if (!file && wcet > period) {
1134 + usage("The worst-case execution time must not "
1135 + "exceed the period.");
1136 + }
1137 +
1138 + if (!file)
1139 + duration = atof(argv[optind + 2]);
1140 + else if (file && num_jobs > 1)
1141 + duration += period_ms * 0.001 * (num_jobs - 1);
1142 +
1143 + if (migrate) {
1144 + ret = be_migrate_to_domain(cluster);
1145 + if (ret < 0)
1146 + bail_out("could not migrate to target partition or cluster.");
1147 + }
1148 +
1149 + /* reservation config */
1150 + config.id = gettid();
1151 +
1152 + if (hyperperiod%period != 0 ) {
1153 + bail_out("hyperperiod must be multiple of period");
1154 + }
1155 +
1156 + if (mc2_param.crit == CRIT_LEVEL_A) {
1157 + config.table_driven_params.major_cycle_length = period;
1158 + }
1159 + else if (mc2_param.crit == CRIT_LEVEL_B) {
1160 + config.polling_params.budget = budget;
1161 + config.polling_params.period = period;
1162 + config.polling_params.offset = 0;
1163 + config.polling_params.relative_deadline = 0;
1164 + if (config.polling_params.budget > config.polling_params.period) {
1165 + usage("The budget must not exceed the period.");
1166 + }
1167 + }
1168 +
1169 + /* create a reservation */
1170 + ret = reservation_create(res_type, &config);
1171 + if (ret < 0) {
1172 + bail_out("failed to create reservation.");
1173 + }
1174 +
1175 + init_rt_task_param(¶m);
1176 + param.exec_cost = wcet;
1177 + param.period = period;
1178 + param.priority = priority;
1179 + param.cls = class;
1180 + param.release_policy = TASK_PERIODIC;
1181 + param.budget_policy = (want_enforcement) ?
1182 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
1183 + if (migrate) {
1184 + param.cpu = gettid();
1185 + }
1186 + ret = set_rt_task_param(gettid(), ¶m);
1187 + if (ret < 0)
1188 + bail_out("could not setup rt task params");
1189 +
1190 + mc2_param.pid = gettid();
1191 + mc2_param.hyperperiod = hyperperiod;
1192 + ret = set_mc2_task_param(gettid(), &mc2_param);
1193 + if (ret < 0)
1194 + bail_out("could not setup mc2 task params");
1195 + init_litmus();
1196 +
1197 + start = wctime();
1198 + ret = task_mode(LITMUS_RT_TASK);
1199 + if (ret != 0)
1200 + bail_out("could not become RT task");
1201 +
1202 + if (protocol >= 0) {
1203 + /* open reference to semaphore */
1204 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
1205 + if (lock_od < 0) {
1206 + perror("litmus_open_lock");
1207 + usage("Could not open lock.");
1208 + }
1209 + }
1210 +
1211 +
1212 + if (wait) {
1213 + ret = wait_for_ts_release();
1214 + if (ret != 0)
1215 + bail_out("wait_for_ts_release()");
1216 + start = wctime();
1217 + }
1218 +
1219 + if (file) {
1220 + /* use times read from the CSV file */
1221 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1222 + /* convert job's length to seconds */
1223 + job(exec_times[cur_job] * 0.001 * scale,
1224 + start + duration,
1225 + lock_od, cs_length * 0.001);
1226 + }
1227 + } else {
1228 + do {
1229 + if (verbose) {
1230 + get_job_no(&job_no);
1231 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
1232 + job_no, (wctime() - start) * 1000);
1233 + }
1234 + /* convert to seconds and scale */
1235 + } while (job(wcet_ms * 0.001 * scale, start + duration,
1236 + lock_od, cs_length * 0.001));
1237 + }
1238 +
1239 + ret = task_mode(BACKGROUND_TASK);
1240 + if (ret != 0)
1241 + bail_out("could not become regular task (huh?)");
1242 +
1243 + if (file)
1244 + free(exec_times);
1245 +
1246 + reservation_destroy(gettid(), config.cpu);
1247 + if (mc2_param.crit == CRIT_LEVEL_A) {
1248 + free(config.table_driven_params.intervals);
1249 + }
1250 + return 0;
1251 +}
1252 diff --git a/include/litmus.h b/include/litmus.h
1253 index 3bd6b92..b90a83d 100644
1254 --- a/include/litmus.h
1255 +++ b/include/litmus.h
1256 @@ -40,6 +40,8 @@ extern "C" {
1257
1258 #include "migration.h"
1259
1260 +#include "litmus/mc2_common.h"
1261 +
1262 /**
1263 * @private
1264 * Number of semaphore protocol object types
1265 @@ -420,6 +422,7 @@ int reservation_create(int rtype, void *config);
1266
1267 int reservation_destroy(unsigned int reservation_id, int cpu);
1268
1269 +int set_mc2_task_param(pid_t pid, struct mc2_task* param);
1270
1271 #ifdef __cplusplus
1272 }
1273 diff --git a/mc2spin b/mc2spin
1274 new file mode 100755
1275 index 0000000000000000000000000000000000000000..00b20c0223e92547cde52d2546b7ddbcb349c1a1
1276 GIT binary patch
1277 literal 102692
1278 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
2102 RC~&S^73oPH3wvb1{udehT~z=8
2103
2104 literal 0
2105 HcmV?d00001
2106
2107 diff --git a/src/syscalls.c b/src/syscalls.c
2108 index fbb8604..b07d135 100644
2109 --- a/src/syscalls.c
2110 +++ b/src/syscalls.c
2111 @@ -96,3 +96,8 @@ int reservation_destroy(unsigned int reservation_id, int cpu)
2112 {
2113 return syscall(__NR_reservation_destroy, reservation_id, cpu);
2114 }
2115 +
2116 +int set_mc2_task_param(pid_t pid, struct mc2_task *param)
2117 +{
2118 + return syscall(__NR_set_mc2_task_param, pid, param);
2119 +}
2120 \ No newline at end of file
2121 --
2122 1.9.1
2123
2124
2125 From 67b3a5139287b153a4bd07899f3a17ea07810e98 Mon Sep 17 00:00:00 2001
2126 From: Namhoon Kim <namhoonk@cs.unc.edu>
2127 Date: Thu, 4 Jun 2015 21:03:19 +0000
2128 Subject: [PATCH 7/7] MC2 for imx6
2129
2130 ---
2131 Makefile | 30 ++-
2132 bin/mc2pollute.c | 400 +++++++++++++++++++++++++++++++
2133 bin/mc2spin.c | 119 ++++++----
2134 bin/mc2spin_td.c | 585 +++++++++++++++++++++++++++++++++++++++++++++
2135 bin/mc2syn.c | 575 +++++++++++++++++++++++++++++++++++++++++++++
2136 bin/mc2sys.c | 557 +++++++++++++++++++++++++++++++++++++++++++
2137 bin/mc2thrash.c | 272 +++++++++++++++++++++
2138 bin/mc2thrash2.c | 626 +++++++++++++++++++++++++++++++++++++++++++++++++
2139 bin/memthrash.c | 62 +++++
2140 bin/portab.h | 41 ++++
2141 bin/resspin.c | 576 +++++++++++++++++++++++++++++++++++++++++++++
2142 bin/rtspin.c | 4 +-
2143 include/cache_common.h | 213 +++++++++++++++++
2144 include/litmus.h | 2 +
2145 mc2spin | Bin 102692 -> 0 bytes
2146 src/syscalls.c | 7 +-
2147 16 files changed, 4020 insertions(+), 49 deletions(-)
2148 create mode 100644 bin/mc2pollute.c
2149 create mode 100644 bin/mc2spin_td.c
2150 create mode 100644 bin/mc2syn.c
2151 create mode 100644 bin/mc2sys.c
2152 create mode 100644 bin/mc2thrash.c
2153 create mode 100644 bin/mc2thrash2.c
2154 create mode 100644 bin/memthrash.c
2155 create mode 100644 bin/portab.h
2156 create mode 100644 bin/resspin.c
2157 create mode 100644 include/cache_common.h
2158 delete mode 100755 mc2spin
2159
2160 diff --git a/Makefile b/Makefile
2161 index 70e79d4..0dfc121 100644
2162 --- a/Makefile
2163 +++ b/Makefile
2164 @@ -19,7 +19,7 @@ LITMUS_KERNEL ?= ../litmus-rt
2165 # Internal configuration.
2166
2167 # compiler flags
2168 -flags-debug = -O2 -Wall -Werror -g -Wdeclaration-after-statement
2169 +flags-debug = -O0 -Wall -g -Wdeclaration-after-statement
2170 flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
2171
2172 # architecture-specific flags
2173 @@ -73,7 +73,8 @@ AR := ${CROSS_COMPILE}${AR}
2174
2175 all = lib ${rt-apps}
2176 rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
2177 - base_mt_task uncache runtests resctrl mc2spin
2178 + base_mt_task uncache runtests resctrl mc2spin mc2pollute \
2179 + mc2syn memthrash mc2sys mc2thrash mc2thrash0 mc2thrash1 mc2thrash2
2180
2181 .PHONY: all lib clean dump-config TAGS tags cscope help doc
2182
2183 @@ -238,8 +239,31 @@ lib-measure_syscall = -lm
2184 obj-resctrl = resctrl.o
2185
2186 obj-mc2spin = mc2spin.o common.o
2187 -lib-mc2spin = -lrt
2188 +lib-mc2spin = -lrt -static
2189
2190 +obj-mc2pollute = mc2pollute.o common.o
2191 +lib-mc2pollute = -lrt -static
2192 +
2193 +obj-mc2sys = mc2sys.o common.o
2194 +lib-mc2sys = -lrt -static
2195 +
2196 +obj-mc2syn = mc2syn.o common.o
2197 +lib-mc2syn = -lrt -static
2198 +
2199 +obj-mc2thrash = mc2thrash.o common.o
2200 +lib-mc2thrash = -lrt -static
2201 +
2202 +obj-mc2thrash0 = mc2thrash.o common.o
2203 +lib-mc2thrash0 = -lrt -static
2204 +
2205 +obj-mc2thrash1 = mc2thrash.o common.o
2206 +lib-mc2thrash1 = -lrt -static
2207 +
2208 +obj-mc2thrash2 = mc2thrash.o common.o
2209 +lib-mc2thrash2 = -lrt -static
2210 +
2211 +obj-memthrash = memthrash.o
2212 +lib-memthrash = -lrt
2213 # ##############################################################################
2214 # Build everything that depends on liblitmus.
2215
2216 diff --git a/bin/mc2pollute.c b/bin/mc2pollute.c
2217 new file mode 100644
2218 index 0000000..63d3503
2219 --- /dev/null
2220 +++ b/bin/mc2pollute.c
2221 @@ -0,0 +1,400 @@
2222 +#include <sys/time.h>
2223 +#include <sys/mman.h>
2224 +
2225 +#include <stdio.h>
2226 +#include <stdlib.h>
2227 +#include <unistd.h>
2228 +#include <time.h>
2229 +#include <string.h>
2230 +#include <assert.h>
2231 +#include <limits.h>
2232 +#include <fcntl.h>
2233 +
2234 +#include "litmus.h"
2235 +#include "common.h"
2236 +
2237 +#define PAGE_SIZE (4096)
2238 +#define CACHELINE_SIZE 32
2239 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
2240 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
2241 +#define INTS_IN_1KB (1024 / sizeof(int))
2242 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
2243 +
2244 +typedef struct cacheline
2245 +{
2246 + int line[INTS_IN_CACHELINE];
2247 +} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
2248 +
2249 +static int loops = 10;
2250 +static cacheline_t* arena = NULL;
2251 +
2252 +struct timeval t1,t2;
2253 +
2254 +inline unsigned long get_cyclecount (void)
2255 +{
2256 + unsigned long value;
2257 + // Read CCNT Register
2258 + asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
2259 + return value;
2260 +}
2261 +
2262 +#if 1
2263 +#define UNCACHE_DEV "/dev/litmus/uncache"
2264 +
2265 +static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages)
2266 +{
2267 + int flags = MAP_PRIVATE | MAP_POPULATE;
2268 + cacheline_t* arena = NULL;
2269 + int fd;
2270 +
2271 + if(use_huge_pages)
2272 + flags |= MAP_HUGETLB;
2273 +
2274 + if(use_uncache_pages) {
2275 + fd = open(UNCACHE_DEV, O_RDWR|O_SYNC);
2276 + if (fd == -1)
2277 + bail_out("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
2278 + }
2279 + else {
2280 + fd = -1;
2281 + flags |= MAP_ANONYMOUS;
2282 + }
2283 +
2284 + arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
2285 +
2286 + if(use_uncache_pages)
2287 + close(fd);
2288 +
2289 + assert(arena);
2290 +
2291 + return arena;
2292 +}
2293 +#else
2294 +static cacheline_t* alloc_arena(size_t size)
2295 +{
2296 + int flags = MAP_PRIVATE | MAP_POPULATE | MAP_ANONYMOUS;
2297 + cacheline_t* arena = NULL;
2298 +
2299 + arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, -1, 0);
2300 +
2301 + assert(arena);
2302 + return arena;
2303 +}
2304 +#endif
2305 +
2306 +static void dealloc_arena(cacheline_t* arena, size_t size)
2307 +{
2308 + int ret = munmap((void*)arena, size);
2309 + if(ret != 0)
2310 + bail_out("munmap() error");
2311 +}
2312 +
2313 +static int randrange(int min, int max)
2314 +{
2315 + /* generate a random number on the range [min, max) w/o skew */
2316 + int limit = max - min;
2317 + int devisor = RAND_MAX/limit;
2318 + int retval;
2319 +
2320 + do {
2321 + retval = rand() / devisor;
2322 + } while(retval == limit);
2323 + retval += min;
2324 +
2325 + return retval;
2326 +}
2327 +
2328 +static void init_arena(cacheline_t* arena, size_t size)
2329 +{
2330 + int i;
2331 + size_t num_arena_elem = size / sizeof(cacheline_t);
2332 +
2333 + /* Generate a cycle among the cache lines using Sattolo's algorithm.
2334 + Every int in the cache line points to the same cache line.
2335 + Note: Sequential walk doesn't care about these values. */
2336 + for (i = 0; i < num_arena_elem; i++) {
2337 + int j;
2338 + for(j = 0; j < INTS_IN_CACHELINE; ++j)
2339 + arena[i].line[j] = i;
2340 + }
2341 + while(1 < i--) {
2342 + int j = randrange(0, i);
2343 + cacheline_t temp = arena[j];
2344 + arena[j] = arena[i];
2345 + arena[i] = temp;
2346 + }
2347 +}
2348 +
2349 +/* Random walk around the arena in cacheline-sized chunks.
2350 + Cacheline-sized chucks ensures the same utilization of each
2351 + hit line as sequential read. (Otherwise, our utilization
2352 + would only be 1/INTS_IN_CACHELINE.) */
2353 +static int random_walk(cacheline_t *mem, int wss, int write_cycle)
2354 +{
2355 + /* a random cycle among the cache lines was set up by init_arena(). */
2356 + int sum, i, next;
2357 +
2358 + int numlines = wss * CACHELINES_IN_1KB;
2359 +
2360 + sum = 0;
2361 +
2362 + /* contents of arena is structured s.t. offsets are all
2363 + w.r.t. to start of arena, so compute the initial offset */
2364 + next = mem - arena;
2365 +
2366 + if (write_cycle == 0) {
2367 + for (i = 0; i < numlines; i++) {
2368 + /* every element in the cacheline has the same value */
2369 + next = arena[next].line[0];
2370 + sum += next;
2371 + }
2372 + }
2373 +
2374 + else {
2375 + int w, which_line;
2376 + for (i = 0, w = 0; i < numlines; i++) {
2377 + which_line = next;
2378 + next = arena[next].line[0];
2379 + if((w % write_cycle) != (write_cycle - 1)) {
2380 + sum += next;
2381 + }
2382 + else {
2383 + ((volatile cacheline_t*)arena)[which_line].line[0] = next;
2384 + }
2385 + }
2386 + }
2387 + return sum;
2388 +}
2389 +
2390 +static cacheline_t* random_start(int wss)
2391 +{
2392 + return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
2393 +}
2394 +
2395 +static volatile int dont_optimize_me = 0;
2396 +
2397 +static void usage(char *error) {
2398 + fprintf(stderr, "Error: %s\n", error);
2399 + fprintf(stderr,
2400 + "Usage:\n"
2401 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
2402 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
2403 + " rt_spin -l\n"
2404 + "\n"
2405 + "COMMON-OPTS = [-w] [-s SCALE]\n"
2406 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
2407 + " [-k WSS] [-l LOOPS] [-b BUDGET]\n"
2408 + "\n"
2409 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
2410 + exit(EXIT_FAILURE);
2411 +}
2412 +
2413 +static int loop_once(int wss)
2414 +{
2415 + cacheline_t *mem;
2416 + int temp;
2417 +
2418 + mem = random_start(wss);
2419 + temp = random_walk(mem, wss, 0);
2420 +
2421 + //mem = sequential_start(wss);
2422 + //temp = sequential_walk(mem, wss, 0);
2423 + dont_optimize_me = temp;
2424 +
2425 + return dont_optimize_me;
2426 +}
2427 +
2428 +static int job(int wss, double exec_time, double program_end)
2429 +{
2430 + if (wctime() > program_end)
2431 + return 0;
2432 + else {
2433 + //register unsigned long t;
2434 + register unsigned int iter = 0;
2435 + //t = get_cyclecount();
2436 + //gettimeofday(&t1, NULL);
2437 + while(iter++ < loops) {
2438 + loop_once(wss);
2439 + }
2440 + //gettimeofday(&t2, NULL);
2441 + //t = get_cyclecount() - t;
2442 + //printf("%ld cycles\n", t);
2443 + //printf("%ld us\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec)));
2444 + sleep_next_period();
2445 + return 1;
2446 + }
2447 +}
2448 +
2449 +#define OPTSTR "p:wl:m:i:b:k:"
2450 +int main(int argc, char** argv)
2451 +{
2452 + int ret, i;
2453 + lt_t wcet, period, budget;
2454 + double wcet_ms, period_ms, budget_ms;
2455 + unsigned int priority = LITMUS_NO_PRIORITY;
2456 + int migrate = 0;
2457 + int cluster = 0;
2458 + int opt;
2459 + int wait = 0;
2460 + double duration = 0, start = 0;
2461 + struct rt_task param;
2462 + struct mc2_task mc2_param;
2463 + struct reservation_config config;
2464 + int res_type = PERIODIC_POLLING;
2465 + size_t arena_sz;
2466 + int wss;
2467 +
2468 + /* default for reservation */
2469 + config.id = 0;
2470 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
2471 + config.cpu = -1;
2472 +
2473 + mc2_param.crit = CRIT_LEVEL_C;
2474 +
2475 + budget_ms = 1000;
2476 +
2477 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
2478 + switch (opt) {
2479 + case 'w':
2480 + wait = 1;
2481 + break;
2482 + case 'p':
2483 + cluster = atoi(optarg);
2484 + migrate = 1;
2485 + config.cpu = cluster;
2486 + break;
2487 + case 'l':
2488 + loops = atoi(optarg);
2489 + break;
2490 + case 'k':
2491 + wss = atoi(optarg);
2492 + break;
2493 + case 'm':
2494 + mc2_param.crit = atoi(optarg);
2495 + if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
2496 + res_type = PERIODIC_POLLING;
2497 + }
2498 + else
2499 + usage("Invalid criticality level.");
2500 + break;
2501 + case 'b':
2502 + budget_ms = atof(optarg);
2503 + break;
2504 + case 'i':
2505 + config.priority = atoi(optarg);
2506 + break;
2507 + case ':':
2508 + usage("Argument missing.");
2509 + break;
2510 + case '?':
2511 + default:
2512 + usage("Bad argument.");
2513 + break;
2514 + }
2515 + }
2516 + srand(getpid());
2517 +
2518 + /*
2519 + * We need three parameters
2520 + */
2521 + if (argc - optind < 3)
2522 + usage("Arguments missing.");
2523 +
2524 + wcet_ms = atof(argv[optind + 0]);
2525 + period_ms = atof(argv[optind + 1]);
2526 +
2527 + wcet = ms2ns(wcet_ms);
2528 + period = ms2ns(period_ms);
2529 + budget = ms2ns(budget_ms);
2530 + if (wcet <= 0)
2531 + usage("The worst-case execution time must be a "
2532 + "positive number.");
2533 + if (period <= 0)
2534 + usage("The period must be a positive number.");
2535 + if (wcet > period) {
2536 + usage("The worst-case execution time must not "
2537 + "exceed the period.");
2538 + }
2539 +
2540 + duration = atof(argv[optind + 2]);
2541 +
2542 + if (migrate) {
2543 + ret = be_migrate_to_domain(cluster);
2544 + if (ret < 0)
2545 + bail_out("could not migrate to target partition or cluster.");
2546 + }
2547 +
2548 + /* reservation config */
2549 + config.id = gettid();
2550 + config.polling_params.budget = budget;
2551 + config.polling_params.period = period;
2552 + config.polling_params.offset = 0;
2553 + config.polling_params.relative_deadline = 0;
2554 +
2555 + if (config.polling_params.budget > config.polling_params.period) {
2556 + usage("The budget must not exceed the period.");
2557 + }
2558 +
2559 + /* create a reservation */
2560 + ret = reservation_create(res_type, &config);
2561 + if (ret < 0) {
2562 + bail_out("failed to create reservation.");
2563 + }
2564 +
2565 + init_rt_task_param(¶m);
2566 + param.exec_cost = wcet;
2567 + param.period = period;
2568 + param.priority = priority;
2569 + param.cls = RT_CLASS_HARD;
2570 + param.release_policy = TASK_PERIODIC;
2571 + param.budget_policy = NO_ENFORCEMENT;
2572 + if (migrate) {
2573 + param.cpu = gettid();
2574 + }
2575 + ret = set_rt_task_param(gettid(), ¶m);
2576 + if (ret < 0)
2577 + bail_out("could not setup rt task params");
2578 +
2579 + mc2_param.res_id = gettid();
2580 + ret = set_mc2_task_param(gettid(), &mc2_param);
2581 + if (ret < 0)
2582 + bail_out("could not setup mc2 task params");
2583 +
2584 + arena_sz = wss*1024;
2585 + arena = alloc_arena(arena_sz, 0, 0);
2586 + init_arena(arena, arena_sz);
2587 +
2588 + ret = init_litmus();
2589 + if (ret != 0)
2590 + bail_out("init_litmus() failed\n");
2591 +
2592 + start = wctime();
2593 + ret = task_mode(LITMUS_RT_TASK);
2594 + if (ret != 0)
2595 + bail_out("could not become RT task");
2596 +
2597 + if (mc2_param.crit == CRIT_LEVEL_C)
2598 + set_page_color(-1);
2599 + else
2600 + set_page_color(config.cpu);
2601 +
2602 + mlockall(MCL_CURRENT | MCL_FUTURE);
2603 +
2604 + if (wait) {
2605 + ret = wait_for_ts_release();
2606 + if (ret != 0)
2607 + bail_out("wait_for_ts_release()");
2608 + start = wctime();
2609 + }
2610 +
2611 + while (job(wss, wcet_ms * 0.001, start + duration)) {};
2612 +
2613 + ret = task_mode(BACKGROUND_TASK);
2614 + if (ret != 0)
2615 + bail_out("could not become regular task (huh?)");
2616 +
2617 + reservation_destroy(gettid(), config.cpu);
2618 + dealloc_arena(arena, arena_sz);
2619 + printf("%s finished.\n", argv[0]);
2620 + return 0;
2621 +}
2622 diff --git a/bin/mc2spin.c b/bin/mc2spin.c
2623 index 1ef3082..25b1c58 100644
2624 --- a/bin/mc2spin.c
2625 +++ b/bin/mc2spin.c
2626 @@ -1,4 +1,5 @@
2627 #include <sys/time.h>
2628 +#include <sys/mman.h>
2629
2630 #include <stdio.h>
2631 #include <stdlib.h>
2632 @@ -12,7 +13,11 @@
2633 #include "litmus.h"
2634 #include "common.h"
2635
2636 +#define PAGE_SIZE 4096
2637 +#define NUM_ITEMS 8192
2638
2639 +int *pages;
2640 +unsigned long *access_order;
2641
2642 static void usage(char *error) {
2643 fprintf(stderr, "Error: %s\n", error);
2644 @@ -104,12 +109,42 @@ static void get_exec_times(const char *file, const int column,
2645 static int num[NUMS];
2646 static char* progname;
2647
2648 +static int randrange(const int max)
2649 +{
2650 + return (rand() / (RAND_MAX / max + 1));
2651 +}
2652 +
2653 +static void sattolo(unsigned long *items, const unsigned long len)
2654 +{
2655 + unsigned long i;
2656 + /* first set up 0, 1, ..., n - 1 */
2657 + for (i = 0; i < len; i++)
2658 + items[i] = i;
2659 + /* note: i is now n */
2660 + while (1 < i--) {
2661 + /* 0 <= j < i */
2662 + int t, j = randrange(i);
2663 + t = items[i];
2664 + items[i] = items[j];
2665 + items[j] = t;
2666 + }
2667 +}
2668 +
2669 static int loop_once(void)
2670 {
2671 int i, j = 0;
2672 for (i = 0; i < NUMS; i++)
2673 j += num[i]++;
2674 return j;
2675 +/*
2676 + int i, tmp;
2677 + for (i = 0; i < NUM_ITEMS; i++) {
2678 + tmp = pages[access_order[i]];
2679 + if (access_order[i] % 3 == 0)
2680 + pages[access_order[i]] = i+tmp;
2681 + }
2682 + return 1;
2683 +*/
2684 }
2685
2686 static int loop_for(double exec_time, double emergency_exit)
2687 @@ -138,11 +173,11 @@ static int loop_for(double exec_time, double emergency_exit)
2688 }
2689
2690
2691 -static void debug_delay_loop(void)
2692 +static void debug_delay_loop(int count)
2693 {
2694 double start, end, delay;
2695
2696 - while (1) {
2697 + while (count--) {
2698 for (delay = 0.5; delay > 0.01; delay -= 0.01) {
2699 start = wctime();
2700 loop_for(delay, 0);
2701 @@ -249,7 +284,7 @@ int main(int argc, char** argv)
2702 lt_t hyperperiod;
2703 lt_t budget;
2704 double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
2705 - unsigned int priority = LITMUS_LOWEST_PRIORITY;
2706 + unsigned int priority = LITMUS_NO_PRIORITY;
2707 int migrate = 0;
2708 int cluster = 0;
2709 int opt;
2710 @@ -266,7 +301,7 @@ int main(int argc, char** argv)
2711 struct rt_task param;
2712 struct mc2_task mc2_param;
2713 struct reservation_config config;
2714 - int res_type = SPORADIC_POLLING;
2715 + int res_type = PERIODIC_POLLING;
2716 int n_str, num_int = 0;
2717
2718 int verbose = 0;
2719 @@ -284,7 +319,7 @@ int main(int argc, char** argv)
2720 /* default for reservation */
2721 config.id = 0;
2722 config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
2723 - config.cpu = 0;
2724 + config.cpu = -1;
2725
2726 mc2_param.crit = CRIT_LEVEL_C;
2727
2728 @@ -346,14 +381,10 @@ int main(int argc, char** argv)
2729 break;
2730 case 'm':
2731 mc2_param.crit = atoi(optarg);
2732 - if (mc2_param.crit == CRIT_LEVEL_A) {
2733 - res_type = TABLE_DRIVEN;
2734 - }
2735 - else if (mc2_param.crit == CRIT_LEVEL_B) {
2736 - res_type = PERIODIC_POLLING;
2737 - }
2738 - else
2739 + if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
2740 usage("Invalid criticality level.");
2741 + }
2742 + res_type = PERIODIC_POLLING;
2743 break;
2744 case 'h':
2745 hyperperiod_ms = atof(optarg);
2746 @@ -362,14 +393,7 @@ int main(int argc, char** argv)
2747 budget_ms = atof(optarg);
2748 break;
2749 case 'i':
2750 - n_str = strlen(optarg);
2751 - while(n_str--) {
2752 - if (optarg[n_str] == ',')
2753 - num_int++;
2754 - }
2755 - if (!num_int)
2756 - usage("Bad argument.");
2757 - config.table_driven_params.intervals = parse_td_intervals(num_int, optarg, &config.table_driven_params.num_intervals);
2758 + config.priority = atoi(optarg);
2759 break;
2760 case ':':
2761 usage("Argument missing.");
2762 @@ -382,10 +406,13 @@ int main(int argc, char** argv)
2763 }
2764
2765 if (test_loop) {
2766 - debug_delay_loop();
2767 + debug_delay_loop(1);
2768 return 0;
2769 }
2770
2771 + if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
2772 + usage("Bad criticailty level or priority");
2773 +
2774 srand(getpid());
2775
2776 if (file) {
2777 @@ -440,20 +467,15 @@ int main(int argc, char** argv)
2778 config.id = gettid();
2779
2780 if (hyperperiod%period != 0 ) {
2781 - bail_out("hyperperiod must be multiple of period");
2782 + ;//bail_out("hyperperiod must be multiple of period");
2783 }
2784
2785 - if (mc2_param.crit == CRIT_LEVEL_A) {
2786 - config.table_driven_params.major_cycle_length = period;
2787 - }
2788 - else if (mc2_param.crit == CRIT_LEVEL_B) {
2789 - config.polling_params.budget = budget;
2790 - config.polling_params.period = period;
2791 - config.polling_params.offset = 0;
2792 - config.polling_params.relative_deadline = 0;
2793 - if (config.polling_params.budget > config.polling_params.period) {
2794 - usage("The budget must not exceed the period.");
2795 - }
2796 + config.polling_params.budget = budget;
2797 + config.polling_params.period = period;
2798 + config.polling_params.offset = 0;
2799 + config.polling_params.relative_deadline = 0;
2800 + if (config.polling_params.budget > config.polling_params.period) {
2801 + usage("The budget must not exceed the period.");
2802 }
2803
2804 /* create a reservation */
2805 @@ -474,23 +496,33 @@ int main(int argc, char** argv)
2806 param.cpu = gettid();
2807 }
2808 ret = set_rt_task_param(gettid(), ¶m);
2809 +//printf("SET_RT_TASK\n");
2810 if (ret < 0)
2811 bail_out("could not setup rt task params");
2812
2813 - mc2_param.pid = gettid();
2814 - mc2_param.hyperperiod = hyperperiod;
2815 + mc2_param.res_id = gettid();
2816 ret = set_mc2_task_param(gettid(), &mc2_param);
2817 +//printf("SET_MC2_TASK\n");
2818 if (ret < 0)
2819 bail_out("could not setup mc2 task params");
2820 +
2821 + pages = (int*)malloc(sizeof(int)*NUM_ITEMS);
2822 + access_order = (unsigned long*)malloc(sizeof(unsigned long)*NUM_ITEMS);
2823 + sattolo(access_order, NUM_ITEMS);
2824 +
2825 init_litmus();
2826 +printf("CALL\n");
2827 + set_page_color(config.cpu);
2828 +printf("CALL\n");
2829
2830 +//printf("INIT_LITMUS\n");
2831 start = wctime();
2832 ret = task_mode(LITMUS_RT_TASK);
2833 +//printf("TASK_MODE\n");
2834 if (ret != 0)
2835 bail_out("could not become RT task");
2836
2837 if (protocol >= 0) {
2838 - /* open reference to semaphore */
2839 lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
2840 if (lock_od < 0) {
2841 perror("litmus_open_lock");
2842 @@ -500,6 +532,7 @@ int main(int argc, char** argv)
2843
2844
2845 if (wait) {
2846 +//printf("BEFORE WAIT\n");
2847 ret = wait_for_ts_release();
2848 if (ret != 0)
2849 bail_out("wait_for_ts_release()");
2850 @@ -507,9 +540,7 @@ int main(int argc, char** argv)
2851 }
2852
2853 if (file) {
2854 - /* use times read from the CSV file */
2855 for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
2856 - /* convert job's length to seconds */
2857 job(exec_times[cur_job] * 0.001 * scale,
2858 start + duration,
2859 lock_od, cs_length * 0.001);
2860 @@ -521,11 +552,10 @@ int main(int argc, char** argv)
2861 printf("rtspin/%d:%u @ %.4fms\n", gettid(),
2862 job_no, (wctime() - start) * 1000);
2863 }
2864 - /* convert to seconds and scale */
2865 } while (job(wcet_ms * 0.001 * scale, start + duration,
2866 lock_od, cs_length * 0.001));
2867 }
2868 -
2869 +printf("BEFORE BACK_TASK\n");
2870 ret = task_mode(BACKGROUND_TASK);
2871 if (ret != 0)
2872 bail_out("could not become regular task (huh?)");
2873 @@ -534,8 +564,11 @@ int main(int argc, char** argv)
2874 free(exec_times);
2875
2876 reservation_destroy(gettid(), config.cpu);
2877 - if (mc2_param.crit == CRIT_LEVEL_A) {
2878 - free(config.table_driven_params.intervals);
2879 - }
2880 +
2881 +printf("CALL\n");
2882 + set_page_color(config.cpu);
2883 +printf("CALL\n");
2884 + free(pages);
2885 + free(access_order);
2886 return 0;
2887 }
2888 diff --git a/bin/mc2spin_td.c b/bin/mc2spin_td.c
2889 new file mode 100644
2890 index 0000000..79704a5
2891 --- /dev/null
2892 +++ b/bin/mc2spin_td.c
2893 @@ -0,0 +1,585 @@
2894 +#include <sys/time.h>
2895 +#include <sys/mman.h>
2896 +
2897 +#include <stdio.h>
2898 +#include <stdlib.h>
2899 +#include <unistd.h>
2900 +#include <time.h>
2901 +#include <string.h>
2902 +#include <assert.h>
2903 +#include <limits.h>
2904 +
2905 +
2906 +#include "litmus.h"
2907 +#include "common.h"
2908 +
2909 +#define PAGE_SIZE 4096
2910 +#define NUM_ITEMS 8192
2911 +
2912 +int *pages;
2913 +unsigned long *access_order;
2914 +
2915 +static void usage(char *error) {
2916 + fprintf(stderr, "Error: %s\n", error);
2917 + fprintf(stderr,
2918 + "Usage:\n"
2919 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
2920 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
2921 + " rt_spin -l\n"
2922 + "\n"
2923 + "COMMON-OPTS = [-w] [-s SCALE]\n"
2924 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
2925 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
2926 + " [-i [start,end]:[start,end]...]\n"
2927 + "\n"
2928 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
2929 + "CRITICAL SECTION LENGTH is in milliseconds.\n");
2930 + exit(EXIT_FAILURE);
2931 +}
2932 +
2933 +/*
2934 + * returns the character that made processing stop, newline or EOF
2935 + */
2936 +static int skip_to_next_line(FILE *fstream)
2937 +{
2938 + int ch;
2939 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
2940 + return ch;
2941 +}
2942 +
2943 +static void skip_comments(FILE *fstream)
2944 +{
2945 + int ch;
2946 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
2947 + skip_to_next_line(fstream);
2948 + ungetc(ch, fstream);
2949 +}
2950 +
2951 +static void get_exec_times(const char *file, const int column,
2952 + int *num_jobs, double **exec_times)
2953 +{
2954 + FILE *fstream;
2955 + int cur_job, cur_col, ch;
2956 + *num_jobs = 0;
2957 +
2958 + fstream = fopen(file, "r");
2959 + if (!fstream)
2960 + bail_out("could not open execution time file");
2961 +
2962 + /* figure out the number of jobs */
2963 + do {
2964 + skip_comments(fstream);
2965 + ch = skip_to_next_line(fstream);
2966 + if (ch != EOF)
2967 + ++(*num_jobs);
2968 + } while (ch != EOF);
2969 +
2970 + if (-1 == fseek(fstream, 0L, SEEK_SET))
2971 + bail_out("rewinding file failed");
2972 +
2973 + /* allocate space for exec times */
2974 + *exec_times = calloc(*num_jobs, sizeof(*exec_times));
2975 + if (!*exec_times)
2976 + bail_out("couldn't allocate memory");
2977 +
2978 + for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
2979 +
2980 + skip_comments(fstream);
2981 +
2982 + for (cur_col = 1; cur_col < column; ++cur_col) {
2983 + /* discard input until we get to the column we want */
2984 + int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
2985 + }
2986 +
2987 + /* get the desired exec. time */
2988 + if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
2989 + fprintf(stderr, "invalid execution time near line %d\n",
2990 + cur_job);
2991 + exit(EXIT_FAILURE);
2992 + }
2993 +
2994 + skip_to_next_line(fstream);
2995 + }
2996 +
2997 + assert(cur_job == *num_jobs);
2998 + fclose(fstream);
2999 +}
3000 +
3001 +#define NUMS 4096
3002 +static int num[NUMS];
3003 +static char* progname;
3004 +
3005 +static int randrange(const int max)
3006 +{
3007 + return (rand() / (RAND_MAX / max + 1));
3008 +}
3009 +
3010 +static void sattolo(unsigned long *items, const unsigned long len)
3011 +{
3012 + unsigned long i;
3013 + /* first set up 0, 1, ..., n - 1 */
3014 + for (i = 0; i < len; i++)
3015 + items[i] = i;
3016 + /* note: i is now n */
3017 + while (1 < i--) {
3018 + /* 0 <= j < i */
3019 + int t, j = randrange(i);
3020 + t = items[i];
3021 + items[i] = items[j];
3022 + items[j] = t;
3023 + }
3024 +}
3025 +
3026 +static int loop_once(void)
3027 +{
3028 + int i, j = 0;
3029 + for (i = 0; i < NUMS; i++)
3030 + j += num[i]++;
3031 + return j;
3032 +/*
3033 + int i, tmp;
3034 + for (i = 0; i < NUM_ITEMS; i++) {
3035 + tmp = pages[access_order[i]];
3036 + if (access_order[i] % 3 == 0)
3037 + pages[access_order[i]] = i+tmp;
3038 + }
3039 + return 1;
3040 +*/
3041 +}
3042 +
3043 +static int loop_for(double exec_time, double emergency_exit)
3044 +{
3045 + double last_loop = 0, loop_start;
3046 + int tmp = 0;
3047 +
3048 + double start = cputime();
3049 + double now = cputime();
3050 +
3051 + while (now + last_loop < start + exec_time) {
3052 + loop_start = now;
3053 + tmp += loop_once();
3054 + now = cputime();
3055 + last_loop = now - loop_start;
3056 + if (emergency_exit && wctime() > emergency_exit) {
3057 + /* Oops --- this should only be possible if the execution time tracking
3058 + * is broken in the LITMUS^RT kernel. */
3059 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
3060 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
3061 + break;
3062 + }
3063 + }
3064 +
3065 + return tmp;
3066 +}
3067 +
3068 +
3069 +static void debug_delay_loop(void)
3070 +{
3071 + double start, end, delay;
3072 +
3073 + while (1) {
3074 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
3075 + start = wctime();
3076 + loop_for(delay, 0);
3077 + end = wctime();
3078 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
3079 + delay,
3080 + end - start,
3081 + end - start - delay,
3082 + 100 * (end - start - delay) / delay);
3083 + }
3084 + }
3085 +}
3086 +
3087 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
3088 +{
3089 + double chunk1, chunk2;
3090 +
3091 + if (wctime() > program_end)
3092 + return 0;
3093 + else {
3094 + if (lock_od >= 0) {
3095 + /* simulate critical section somewhere in the middle */
3096 + chunk1 = drand48() * (exec_time - cs_length);
3097 + chunk2 = exec_time - cs_length - chunk1;
3098 +
3099 + /* non-critical section */
3100 + loop_for(chunk1, program_end + 1);
3101 +
3102 + /* critical section */
3103 + litmus_lock(lock_od);
3104 + loop_for(cs_length, program_end + 1);
3105 + litmus_unlock(lock_od);
3106 +
3107 + /* non-critical section */
3108 + loop_for(chunk2, program_end + 2);
3109 + } else {
3110 + loop_for(exec_time, program_end + 1);
3111 + }
3112 + sleep_next_period();
3113 + return 1;
3114 + }
3115 +}
3116 +
3117 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
3118 +{
3119 + int i, matched;
3120 + struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
3121 + char** arg = (char**)malloc(sizeof(char*) * num);
3122 + char *token, *saveptr;
3123 + double start, end;
3124 +
3125 + for (i = 0; i < num; i++) {
3126 + arg[i] = (char*)malloc(sizeof(char)*100);
3127 + }
3128 +
3129 + i = 0;
3130 + token = strtok_r(optarg, ":", &saveptr);
3131 + while(token != NULL) {
3132 + sprintf(arg[i++], "%s", token);
3133 + token = strtok_r(NULL, ":", &saveptr);
3134 + }
3135 +
3136 + *num_intervals = 0;
3137 +
3138 + for (i=0; i<num; i++) {
3139 + matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
3140 + if (matched != 2) {
3141 + fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
3142 + exit(5);
3143 + }
3144 + if (start < 0) {
3145 + fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
3146 + exit(5);
3147 + }
3148 + if (end <= start) {
3149 + fprintf(stderr, "interval %s: end before start\n", arg[i]);
3150 + exit(5);
3151 + }
3152 +
3153 + slots[i].start = ms2ns(start);
3154 + slots[i].end = ms2ns(end);
3155 +
3156 + if (i > 0 && slots[i - 1].end >= slots[i].start) {
3157 + fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
3158 + exit(5);
3159 + }
3160 +
3161 + (*num_intervals)++;
3162 + }
3163 +
3164 + for (i=0; i<num; i++) {
3165 + free(arg[i]);
3166 + }
3167 + free(arg);
3168 + return slots;
3169 +}
3170 +
3171 +#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:"
3172 +int main(int argc, char** argv)
3173 +{
3174 + int ret;
3175 + lt_t wcet;
3176 + lt_t period;
3177 + lt_t hyperperiod;
3178 + lt_t budget;
3179 + double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
3180 + unsigned int priority = LITMUS_NO_PRIORITY;
3181 + int migrate = 0;
3182 + int cluster = 0;
3183 + int opt;
3184 + int wait = 0;
3185 + int test_loop = 0;
3186 + int column = 1;
3187 + const char *file = NULL;
3188 + int want_enforcement = 0;
3189 + double duration = 0, start = 0;
3190 + double *exec_times = NULL;
3191 + double scale = 1.0;
3192 + task_class_t class = RT_CLASS_HARD;
3193 + int cur_job = 0, num_jobs = 0;
3194 + struct rt_task param;
3195 + struct mc2_task mc2_param;
3196 + struct reservation_config config;
3197 + int res_type = PERIODIC_POLLING;
3198 + int n_str, num_int = 0;
3199 +
3200 + int verbose = 0;
3201 + unsigned int job_no;
3202 +
3203 + /* locking */
3204 + int lock_od = -1;
3205 + int resource_id = 0;
3206 + const char *lock_namespace = "./rtspin-locks";
3207 + int protocol = -1;
3208 + double cs_length = 1; /* millisecond */
3209 +
3210 + progname = argv[0];
3211 +
3212 + /* default for reservation */
3213 + config.id = 0;
3214 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
3215 + config.cpu = -1;
3216 +
3217 + mc2_param.crit = CRIT_LEVEL_C;
3218 +
3219 + hyperperiod_ms = 1000;
3220 + budget_ms = 10;
3221 +
3222 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
3223 + switch (opt) {
3224 + case 'w':
3225 + wait = 1;
3226 + break;
3227 + case 'p':
3228 + cluster = atoi(optarg);
3229 + migrate = 1;
3230 + config.cpu = cluster;
3231 + break;
3232 + case 'q':
3233 + priority = atoi(optarg);
3234 + if (!litmus_is_valid_fixed_prio(priority))
3235 + usage("Invalid priority.");
3236 + break;
3237 + case 'c':
3238 + class = str2class(optarg);
3239 + if (class == -1)
3240 + usage("Unknown task class.");
3241 + break;
3242 + case 'e':
3243 + want_enforcement = 1;
3244 + break;
3245 + case 'l':
3246 + test_loop = 1;
3247 + break;
3248 + case 'o':
3249 + column = atoi(optarg);
3250 + break;
3251 + case 'f':
3252 + file = optarg;
3253 + break;
3254 + case 's':
3255 + scale = atof(optarg);
3256 + break;
3257 + case 'X':
3258 + protocol = lock_protocol_for_name(optarg);
3259 + if (protocol < 0)
3260 + usage("Unknown locking protocol specified.");
3261 + break;
3262 + case 'L':
3263 + cs_length = atof(optarg);
3264 + if (cs_length <= 0)
3265 + usage("Invalid critical section length.");
3266 + break;
3267 + case 'Q':
3268 + resource_id = atoi(optarg);
3269 + if (resource_id <= 0 && strcmp(optarg, "0"))
3270 + usage("Invalid resource ID.");
3271 + break;
3272 + case 'v':
3273 + verbose = 1;
3274 + break;
3275 + case 'm':
3276 + mc2_param.crit = atoi(optarg);
3277 + if (mc2_param.crit == CRIT_LEVEL_A) {
3278 + res_type = TABLE_DRIVEN;
3279 + config.priority = LITMUS_HIGHEST_PRIORITY;
3280 + }
3281 + else if (mc2_param.crit == CRIT_LEVEL_B || mc2_param.crit == CRIT_LEVEL_C) {
3282 + res_type = PERIODIC_POLLING;
3283 + }
3284 + else
3285 + usage("Invalid criticality level.");
3286 + break;
3287 + case 'h':
3288 + hyperperiod_ms = atof(optarg);
3289 + break;
3290 + case 'b':
3291 + budget_ms = atof(optarg);
3292 + break;
3293 + case 'i':
3294 + n_str = strlen(optarg);
3295 + while(n_str--) {
3296 + if (optarg[n_str] == ',')
3297 + num_int++;
3298 + }
3299 + if (!num_int)
3300 + usage("Bad argument.");
3301 + config.table_driven_params.intervals = parse_td_intervals(num_int, optarg, &config.table_driven_params.num_intervals);
3302 + break;
3303 + case ':':
3304 + usage("Argument missing.");
3305 + break;
3306 + case '?':
3307 + default:
3308 + usage("Bad argument.");
3309 + break;
3310 + }
3311 + }
3312 +
3313 + if (test_loop) {
3314 + debug_delay_loop();
3315 + return 0;
3316 + }
3317 +
3318 + srand(getpid());
3319 +
3320 + if (file) {
3321 + get_exec_times(file, column, &num_jobs, &exec_times);
3322 +
3323 + if (argc - optind < 2)
3324 + usage("Arguments missing.");
3325 +
3326 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
3327 + /* convert the execution time to seconds */
3328 + duration += exec_times[cur_job] * 0.001;
3329 + }
3330 + } else {
3331 + /*
3332 + * if we're not reading from the CSV file, then we need
3333 + * three parameters
3334 + */
3335 + if (argc - optind < 3)
3336 + usage("Arguments missing.");
3337 + }
3338 +
3339 + wcet_ms = atof(argv[optind + 0]);
3340 + period_ms = atof(argv[optind + 1]);
3341 +
3342 + wcet = ms2ns(wcet_ms);
3343 + period = ms2ns(period_ms);
3344 + budget = ms2ns(budget_ms);
3345 + hyperperiod = ms2ns(hyperperiod_ms);
3346 +
3347 + if (wcet <= 0)
3348 + usage("The worst-case execution time must be a "
3349 + "positive number.");
3350 + if (period <= 0)
3351 + usage("The period must be a positive number.");
3352 + if (!file && wcet > period) {
3353 + usage("The worst-case execution time must not "
3354 + "exceed the period.");
3355 + }
3356 +
3357 + if (!file)
3358 + duration = atof(argv[optind + 2]);
3359 + else if (file && num_jobs > 1)
3360 + duration += period_ms * 0.001 * (num_jobs - 1);
3361 +
3362 + if (migrate) {
3363 + ret = be_migrate_to_domain(cluster);
3364 + if (ret < 0)
3365 + bail_out("could not migrate to target partition or cluster.");
3366 + }
3367 +
3368 + /* reservation config */
3369 + config.id = gettid();
3370 +
3371 + if (hyperperiod%period != 0 ) {
3372 + ;//bail_out("hyperperiod must be multiple of period");
3373 + }
3374 +
3375 + if (mc2_param.crit == CRIT_LEVEL_A) {
3376 + config.table_driven_params.major_cycle_length = period;
3377 + } else if (mc2_param.crit == CRIT_LEVEL_B || mc2_param.crit == CRIT_LEVEL_C) {
3378 + config.polling_params.budget = budget;
3379 + config.polling_params.period = period;
3380 + config.polling_params.offset = 0;
3381 + config.polling_params.relative_deadline = 0;
3382 + if (config.polling_params.budget > config.polling_params.period) {
3383 + usage("The budget must not exceed the period.");
3384 + }
3385 + }
3386 +
3387 + /* create a reservation */
3388 + ret = reservation_create(res_type, &config);
3389 + if (ret < 0) {
3390 + bail_out("failed to create reservation.");
3391 + }
3392 +
3393 + init_rt_task_param(¶m);
3394 + param.exec_cost = wcet;
3395 + param.period = period;
3396 + param.priority = priority;
3397 + param.cls = class;
3398 + param.release_policy = TASK_PERIODIC;
3399 + param.budget_policy = (want_enforcement) ?
3400 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
3401 + if (migrate) {
3402 + param.cpu = gettid();
3403 + }
3404 + ret = set_rt_task_param(gettid(), ¶m);
3405 +//printf("SET_RT_TASK\n");
3406 + if (ret < 0)
3407 + bail_out("could not setup rt task params");
3408 +
3409 + mc2_param.res_id = gettid();
3410 + ret = set_mc2_task_param(gettid(), &mc2_param);
3411 +//printf("SET_MC2_TASK\n");
3412 + if (ret < 0)
3413 + bail_out("could not setup mc2 task params");
3414 +
3415 + pages = (int*)malloc(sizeof(int)*NUM_ITEMS);
3416 + access_order = (unsigned long*)malloc(sizeof(unsigned long)*NUM_ITEMS);
3417 + sattolo(access_order, NUM_ITEMS);
3418 +
3419 +// mlockall(MCL_CURRENT | MCL_FUTURE);
3420 +// set_page_color(config.cpu);
3421 +
3422 + init_litmus();
3423 +//printf("INIT_LITMUS\n");
3424 + start = wctime();
3425 + ret = task_mode(LITMUS_RT_TASK);
3426 +//printf("TASK_MODE\n");
3427 + if (ret != 0)
3428 + bail_out("could not become RT task");
3429 +
3430 + if (protocol >= 0) {
3431 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
3432 + if (lock_od < 0) {
3433 + perror("litmus_open_lock");
3434 + usage("Could not open lock.");
3435 + }
3436 + }
3437 +
3438 +
3439 + if (wait) {
3440 +//printf("BEFORE WAIT\n");
3441 + ret = wait_for_ts_release();
3442 + if (ret != 0)
3443 + bail_out("wait_for_ts_release()");
3444 + start = wctime();
3445 + }
3446 +
3447 + if (file) {
3448 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
3449 + job(exec_times[cur_job] * 0.001 * scale,
3450 + start + duration,
3451 + lock_od, cs_length * 0.001);
3452 + }
3453 + } else {
3454 + do {
3455 + if (verbose) {
3456 + get_job_no(&job_no);
3457 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
3458 + job_no, (wctime() - start) * 1000);
3459 + }
3460 + } while (job(wcet_ms * 0.001 * scale, start + duration,
3461 + lock_od, cs_length * 0.001));
3462 + }
3463 +printf("BEFORE BACK_TASK\n");
3464 + ret = task_mode(BACKGROUND_TASK);
3465 + if (ret != 0)
3466 + bail_out("could not become regular task (huh?)");
3467 +
3468 + if (file)
3469 + free(exec_times);
3470 +
3471 + reservation_destroy(gettid(), config.cpu);
3472 + if (mc2_param.crit == CRIT_LEVEL_A) {
3473 + free(config.table_driven_params.intervals);
3474 + }
3475 + free(pages);
3476 + free(access_order);
3477 + return 0;
3478 +}
3479 diff --git a/bin/mc2syn.c b/bin/mc2syn.c
3480 new file mode 100644
3481 index 0000000..020653c
3482 --- /dev/null
3483 +++ b/bin/mc2syn.c
3484 @@ -0,0 +1,575 @@
3485 +#include <sys/time.h>
3486 +#include <sys/mman.h>
3487 +
3488 +#include <stdio.h>
3489 +#include <stdlib.h>
3490 +#include <unistd.h>
3491 +#include <time.h>
3492 +#include <string.h>
3493 +#include <assert.h>
3494 +#include <limits.h>
3495 +
3496 +
3497 +#include "litmus.h"
3498 +#include "common.h"
3499 +
3500 +#define PAGE_SIZE (4096)
3501 +#define WSS_KB (64)
3502 +#define NUM_ITEMS ((WSS_KB*1024)/sizeof(unsigned long))
3503 +
3504 +unsigned long *pages;
3505 +unsigned long *access_order;
3506 +static int loops;
3507 +
3508 +static int randrange(const int max)
3509 +{
3510 + return (rand() / (RAND_MAX / max + 1));
3511 +}
3512 +
3513 +/*
3514 + * Sattolo's algorithm makes a random cycle that includes all the elements
3515 + * in the items array.
3516 + */
3517 +static void sattolo(unsigned long *items, const unsigned long len)
3518 +{
3519 + unsigned long i;
3520 + /* first set up 0, 1, ..., n - 1 */
3521 + for (i = 0; i < len; i++)
3522 + items[i] = i;
3523 + /* note: i is now n */
3524 + while (1 < i--) {
3525 + /* 0 <= j < i */
3526 + int t, j = randrange(i);
3527 + t = items[i];
3528 + items[i] = items[j];
3529 + items[j] = t;
3530 + }
3531 +}
3532 +
3533 +static void usage(char *error) {
3534 + fprintf(stderr, "Error: %s\n", error);
3535 + fprintf(stderr,
3536 + "Usage:\n"
3537 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
3538 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
3539 + " rt_spin -l\n"
3540 + "\n"
3541 + "COMMON-OPTS = [-w] [-s SCALE]\n"
3542 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
3543 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
3544 + " [-i [start,end]:[start,end]...]\n"
3545 + "\n"
3546 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
3547 + "CRITICAL SECTION LENGTH is in milliseconds.\n");
3548 + exit(EXIT_FAILURE);
3549 +}
3550 +
3551 +/*
3552 + * returns the character that made processing stop, newline or EOF
3553 + */
3554 +static int skip_to_next_line(FILE *fstream)
3555 +{
3556 + int ch;
3557 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
3558 + return ch;
3559 +}
3560 +
3561 +static void skip_comments(FILE *fstream)
3562 +{
3563 + int ch;
3564 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
3565 + skip_to_next_line(fstream);
3566 + ungetc(ch, fstream);
3567 +}
3568 +
3569 +static void get_exec_times(const char *file, const int column,
3570 + int *num_jobs, double **exec_times)
3571 +{
3572 + FILE *fstream;
3573 + int cur_job, cur_col, ch;
3574 + *num_jobs = 0;
3575 +
3576 + fstream = fopen(file, "r");
3577 + if (!fstream)
3578 + bail_out("could not open execution time file");
3579 +
3580 + /* figure out the number of jobs */
3581 + do {
3582 + skip_comments(fstream);
3583 + ch = skip_to_next_line(fstream);
3584 + if (ch != EOF)
3585 + ++(*num_jobs);
3586 + } while (ch != EOF);
3587 +
3588 + if (-1 == fseek(fstream, 0L, SEEK_SET))
3589 + bail_out("rewinding file failed");
3590 +
3591 + /* allocate space for exec times */
3592 + *exec_times = calloc(*num_jobs, sizeof(*exec_times));
3593 + if (!*exec_times)
3594 + bail_out("couldn't allocate memory");
3595 +
3596 + for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
3597 +
3598 + skip_comments(fstream);
3599 +
3600 + for (cur_col = 1; cur_col < column; ++cur_col) {
3601 + /* discard input until we get to the column we want */
3602 + int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
3603 + }
3604 +
3605 + /* get the desired exec. time */
3606 + if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
3607 + fprintf(stderr, "invalid execution time near line %d\n",
3608 + cur_job);
3609 + exit(EXIT_FAILURE);
3610 + }
3611 +
3612 + skip_to_next_line(fstream);
3613 + }
3614 +
3615 + assert(cur_job == *num_jobs);
3616 + fclose(fstream);
3617 +}
3618 +
3619 +#define NUMS 4096
3620 +static int num[NUMS];
3621 +static char* progname;
3622 +
3623 +int index_s = 0;
3624 +
3625 +static int loop_once(void)
3626 +{
3627 +/* int i, j = 0;
3628 + for (i = 0; i < NUMS; i++)
3629 + j += num[i]++;
3630 + return j;
3631 +*/
3632 + unsigned long i;
3633 + unsigned long tmp;
3634 + for (i = 0; i < NUM_ITEMS; i++) {
3635 + tmp = access_order[i];
3636 + ((volatile unsigned long*)access_order)[i] = tmp++;
3637 + ((volatile unsigned long*)access_order)[i] = access_order[i]%NUM_ITEMS;
3638 + }
3639 +
3640 + return tmp;
3641 +}
3642 +
3643 +static int loop_for(double exec_time, double emergency_exit)
3644 +{
3645 + double last_loop = 0, loop_start;
3646 + int tmp = 0;
3647 + int iter = 0;
3648 +
3649 + double start = cputime();
3650 + double now = cputime();
3651 +
3652 + //while (now + last_loop < start + exec_time) {
3653 + while(iter++ < loops) {
3654 + loop_start = now;
3655 + tmp = loop_once();
3656 + now = cputime();
3657 + last_loop = now - loop_start;
3658 + if (emergency_exit && wctime() > emergency_exit) {
3659 + /* Oops --- this should only be possible if the execution time tracking
3660 + * is broken in the LITMUS^RT kernel. */
3661 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
3662 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
3663 + break;
3664 + }
3665 + }
3666 +
3667 + return tmp;
3668 +}
3669 +
3670 +
3671 +static void debug_delay_loop(void)
3672 +{
3673 + double start, end, delay;
3674 +
3675 + while (1) {
3676 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
3677 + start = wctime();
3678 + loop_for(delay, 0);
3679 + end = wctime();
3680 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
3681 + delay,
3682 + end - start,
3683 + end - start - delay,
3684 + 100 * (end - start - delay) / delay);
3685 + }
3686 + }
3687 +}
3688 +
3689 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
3690 +{
3691 + double chunk1, chunk2;
3692 +
3693 + if (wctime() > program_end)
3694 + return 0;
3695 + else {
3696 + if (lock_od >= 0) {
3697 + /* simulate critical section somewhere in the middle */
3698 + chunk1 = drand48() * (exec_time - cs_length);
3699 + chunk2 = exec_time - cs_length - chunk1;
3700 +
3701 + /* non-critical section */
3702 + loop_for(chunk1, program_end + 1);
3703 +
3704 + /* critical section */
3705 + litmus_lock(lock_od);
3706 + loop_for(cs_length, program_end + 1);
3707 + litmus_unlock(lock_od);
3708 +
3709 + /* non-critical section */
3710 + loop_for(chunk2, program_end + 2);
3711 + } else {
3712 + loop_for(exec_time, program_end + 1);
3713 + }
3714 + sleep_next_period();
3715 + return 1;
3716 + }
3717 +}
3718 +
3719 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
3720 +{
3721 + int i, matched;
3722 + struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
3723 + char** arg = (char**)malloc(sizeof(char*) * num);
3724 + char *token, *saveptr;
3725 + double start, end;
3726 +
3727 + for (i = 0; i < num; i++) {
3728 + arg[i] = (char*)malloc(sizeof(char)*100);
3729 + }
3730 +
3731 + i = 0;
3732 + token = strtok_r(optarg, ":", &saveptr);
3733 + while(token != NULL) {
3734 + sprintf(arg[i++], "%s", token);
3735 + token = strtok_r(NULL, ":", &saveptr);
3736 + }
3737 +
3738 + *num_intervals = 0;
3739 +
3740 + for (i=0; i<num; i++) {
3741 + matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
3742 + if (matched != 2) {
3743 + fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
3744 + exit(5);
3745 + }
3746 + if (start < 0) {
3747 + fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
3748 + exit(5);
3749 + }
3750 + if (end <= start) {
3751 + fprintf(stderr, "interval %s: end before start\n", arg[i]);
3752 + exit(5);
3753 + }
3754 +
3755 + slots[i].start = ms2ns(start);
3756 + slots[i].end = ms2ns(end);
3757 +
3758 + if (i > 0 && slots[i - 1].end >= slots[i].start) {
3759 + fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
3760 + exit(5);
3761 + }
3762 +
3763 + (*num_intervals)++;
3764 + }
3765 +
3766 + for (i=0; i<num; i++) {
3767 + free(arg[i]);
3768 + }
3769 + free(arg);
3770 + return slots;
3771 +}
3772 +
3773 +#define OPTSTR "p:c:wl:veo:f:s:q:X:L:Q:vh:m:i:b:"
3774 +int main(int argc, char** argv)
3775 +{
3776 + int ret, i;
3777 + lt_t wcet;
3778 + lt_t period;
3779 + lt_t hyperperiod;
3780 + lt_t budget;
3781 + double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
3782 + unsigned int priority = LITMUS_NO_PRIORITY;
3783 + int migrate = 0;
3784 + int cluster = 0;
3785 + int opt;
3786 + int wait = 0;
3787 + int test_loop = 0;
3788 + int column = 1;
3789 + const char *file = NULL;
3790 + int want_enforcement = 0;
3791 + double duration = 0, start = 0;
3792 + double *exec_times = NULL;
3793 + double scale = 1.0;
3794 + task_class_t class = RT_CLASS_HARD;
3795 + int cur_job = 0, num_jobs = 0;
3796 + struct rt_task param;
3797 + struct mc2_task mc2_param;
3798 + struct reservation_config config;
3799 + int res_type = PERIODIC_POLLING;
3800 + int n_str, num_int = 0;
3801 +
3802 + int verbose = 0;
3803 + unsigned int job_no;
3804 +
3805 + /* locking */
3806 + int lock_od = -1;
3807 + int resource_id = 0;
3808 + const char *lock_namespace = "./rtspin-locks";
3809 + int protocol = -1;
3810 + double cs_length = 1; /* millisecond */
3811 +
3812 + progname = argv[0];
3813 +
3814 + /* default for reservation */
3815 + config.id = 0;
3816 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
3817 + config.cpu = -1;
3818 +
3819 + mc2_param.crit = CRIT_LEVEL_C;
3820 +
3821 + hyperperiod_ms = 1000;
3822 + budget_ms = 10;
3823 +
3824 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
3825 + switch (opt) {
3826 + case 'w':
3827 + wait = 1;
3828 + break;
3829 + case 'p':
3830 + cluster = atoi(optarg);
3831 + migrate = 1;
3832 + config.cpu = cluster;
3833 + break;
3834 + case 'q':
3835 + priority = atoi(optarg);
3836 + if (!litmus_is_valid_fixed_prio(priority))
3837 + usage("Invalid priority.");
3838 + break;
3839 + case 'c':
3840 + class = str2class(optarg);
3841 + if (class == -1)
3842 + usage("Unknown task class.");
3843 + break;
3844 + case 'e':
3845 + want_enforcement = 1;
3846 + break;
3847 + case 'l':
3848 + loops = atoi(optarg);
3849 + break;
3850 + case 'o':
3851 + column = atoi(optarg);
3852 + break;
3853 + case 'f':
3854 + file = optarg;
3855 + break;
3856 + case 's':
3857 + scale = atof(optarg);
3858 + break;
3859 + case 'X':
3860 + protocol = lock_protocol_for_name(optarg);
3861 + if (protocol < 0)
3862 + usage("Unknown locking protocol specified.");
3863 + break;
3864 + case 'L':
3865 + cs_length = atof(optarg);
3866 + if (cs_length <= 0)
3867 + usage("Invalid critical section length.");
3868 + break;
3869 + case 'Q':
3870 + resource_id = atoi(optarg);
3871 + if (resource_id <= 0 && strcmp(optarg, "0"))
3872 + usage("Invalid resource ID.");
3873 + break;
3874 + case 'v':
3875 + verbose = 1;
3876 + break;
3877 + case 'm':
3878 + mc2_param.crit = atoi(optarg);
3879 + if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
3880 + res_type = PERIODIC_POLLING;
3881 + }
3882 + else
3883 + usage("Invalid criticality level.");
3884 + break;
3885 + case 'h':
3886 + hyperperiod_ms = atof(optarg);
3887 + break;
3888 + case 'b':
3889 + budget_ms = atof(optarg);
3890 + break;
3891 + case 'i':
3892 + config.priority = atoi(optarg);
3893 + break;
3894 + case ':':
3895 + usage("Argument missing.");
3896 + break;
3897 + case '?':
3898 + default:
3899 + usage("Bad argument.");
3900 + break;
3901 + }
3902 + }
3903 +
3904 + if (test_loop) {
3905 + debug_delay_loop();
3906 + return 0;
3907 + }
3908 +
3909 + srand(getpid());
3910 +
3911 + if (file) {
3912 + get_exec_times(file, column, &num_jobs, &exec_times);
3913 +
3914 + if (argc - optind < 2)
3915 + usage("Arguments missing.");
3916 +
3917 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
3918 + /* convert the execution time to seconds */
3919 + duration += exec_times[cur_job] * 0.001;
3920 + }
3921 + } else {
3922 + /*
3923 + * if we're not reading from the CSV file, then we need
3924 + * three parameters
3925 + */
3926 + if (argc - optind < 3)
3927 + usage("Arguments missing.");
3928 + }
3929 +
3930 + wcet_ms = atof(argv[optind + 0]);
3931 + period_ms = atof(argv[optind + 1]);
3932 +
3933 + wcet = ms2ns(wcet_ms);
3934 + period = ms2ns(period_ms);
3935 + budget = ms2ns(budget_ms);
3936 + hyperperiod = ms2ns(hyperperiod_ms);
3937 + if (wcet <= 0)
3938 + usage("The worst-case execution time must be a "
3939 + "positive number.");
3940 + if (period <= 0)
3941 + usage("The period must be a positive number.");
3942 + if (!file && wcet > period) {
3943 + usage("The worst-case execution time must not "
3944 + "exceed the period.");
3945 + }
3946 +
3947 + if (!file)
3948 + duration = atof(argv[optind + 2]);
3949 + else if (file && num_jobs > 1)
3950 + duration += period_ms * 0.001 * (num_jobs - 1);
3951 +
3952 + if (migrate) {
3953 + ret = be_migrate_to_domain(cluster);
3954 + if (ret < 0)
3955 + bail_out("could not migrate to target partition or cluster.");
3956 + }
3957 +
3958 + /* reservation config */
3959 + config.id = gettid();
3960 +
3961 + if (hyperperiod%period != 0 ) {
3962 + ;//bail_out("hyperperiod must be multiple of period");
3963 + }
3964 +
3965 + config.polling_params.budget = budget;
3966 + config.polling_params.period = period;
3967 + config.polling_params.offset = 0;
3968 + config.polling_params.relative_deadline = 0;
3969 +
3970 + if (config.polling_params.budget > config.polling_params.period) {
3971 + usage("The budget must not exceed the period.");
3972 + }
3973 +
3974 + /* create a reservation */
3975 + ret = reservation_create(res_type, &config);
3976 + if (ret < 0) {
3977 + bail_out("failed to create reservation.");
3978 + }
3979 +
3980 + init_rt_task_param(¶m);
3981 + param.exec_cost = wcet;
3982 + param.period = period;
3983 + param.priority = priority;
3984 + param.cls = class;
3985 + param.release_policy = TASK_PERIODIC;
3986 + param.budget_policy = (want_enforcement) ?
3987 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
3988 + if (migrate) {
3989 + param.cpu = gettid();
3990 + }
3991 + ret = set_rt_task_param(gettid(), ¶m);
3992 + if (ret < 0)
3993 + bail_out("could not setup rt task params");
3994 +
3995 + mc2_param.res_id = gettid();
3996 + ret = set_mc2_task_param(gettid(), &mc2_param);
3997 + if (ret < 0)
3998 + bail_out("could not setup mc2 task params");
3999 +
4000 + pages = (unsigned long*)malloc(WSS_KB * 1024);
4001 + access_order = (unsigned long*)malloc(NUM_ITEMS*sizeof(unsigned long));
4002 +
4003 + srand(0);
4004 + sattolo(access_order, NUM_ITEMS);
4005 +
4006 + ret = init_litmus();
4007 + if (ret != 0)
4008 + bail_out("init_litmus() failed\n");
4009 +
4010 + start = wctime();
4011 + ret = task_mode(LITMUS_RT_TASK);
4012 + if (ret != 0)
4013 + bail_out("could not become RT task");
4014 +
4015 + if (protocol >= 0) {
4016 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
4017 + if (lock_od < 0) {
4018 + perror("litmus_open_lock");
4019 + usage("Could not open lock.");
4020 + }
4021 + }
4022 +
4023 +
4024 + if (wait) {
4025 + ret = wait_for_ts_release();
4026 + if (ret != 0)
4027 + bail_out("wait_for_ts_release()");
4028 + start = wctime();
4029 + }
4030 +
4031 + if (file) {
4032 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
4033 + job(exec_times[cur_job] * 0.001 * scale,
4034 + start + duration,
4035 + lock_od, cs_length * 0.001);
4036 + }
4037 + } else {
4038 + do {
4039 + if (verbose) {
4040 + get_job_no(&job_no);
4041 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
4042 + job_no, (wctime() - start) * 1000);
4043 + }
4044 + } while (job(wcet_ms * 0.001 * scale, start + duration,
4045 + lock_od, cs_length * 0.001));
4046 + }
4047 +
4048 + ret = task_mode(BACKGROUND_TASK);
4049 + if (ret != 0)
4050 + bail_out("could not become regular task (huh?)");
4051 +
4052 + if (file)
4053 + free(exec_times);
4054 +
4055 + reservation_destroy(gettid(), config.cpu);
4056 + free(pages);
4057 + free(access_order);
4058 + return 0;
4059 +}
4060 diff --git a/bin/mc2sys.c b/bin/mc2sys.c
4061 new file mode 100644
4062 index 0000000..b8f1e2f
4063 --- /dev/null
4064 +++ b/bin/mc2sys.c
4065 @@ -0,0 +1,557 @@
4066 +#include <sys/time.h>
4067 +#include <sys/mman.h>
4068 +
4069 +#include <stdio.h>
4070 +#include <stdlib.h>
4071 +#include <unistd.h>
4072 +#include <time.h>
4073 +#include <string.h>
4074 +#include <assert.h>
4075 +#include <limits.h>
4076 +
4077 +
4078 +#include "litmus.h"
4079 +#include "common.h"
4080 +
4081 +static void usage(char *error) {
4082 + fprintf(stderr, "Error: %s\n", error);
4083 + fprintf(stderr,
4084 + "Usage:\n"
4085 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
4086 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
4087 + " rt_spin -l\n"
4088 + "\n"
4089 + "COMMON-OPTS = [-w] [-s SCALE]\n"
4090 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
4091 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
4092 + " [-i [start,end]:[start,end]...]\n"
4093 + "\n"
4094 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
4095 + "CRITICAL SECTION LENGTH is in milliseconds.\n");
4096 + exit(EXIT_FAILURE);
4097 +}
4098 +
4099 +/*
4100 + * returns the character that made processing stop, newline or EOF
4101 + */
4102 +static int skip_to_next_line(FILE *fstream)
4103 +{
4104 + int ch;
4105 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
4106 + return ch;
4107 +}
4108 +
4109 +static void skip_comments(FILE *fstream)
4110 +{
4111 + int ch;
4112 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
4113 + skip_to_next_line(fstream);
4114 + ungetc(ch, fstream);
4115 +}
4116 +
4117 +static void get_exec_times(const char *file, const int column,
4118 + int *num_jobs, double **exec_times)
4119 +{
4120 + FILE *fstream;
4121 + int cur_job, cur_col, ch;
4122 + *num_jobs = 0;
4123 +
4124 + fstream = fopen(file, "r");
4125 + if (!fstream)
4126 + bail_out("could not open execution time file");
4127 +
4128 + /* figure out the number of jobs */
4129 + do {
4130 + skip_comments(fstream);
4131 + ch = skip_to_next_line(fstream);
4132 + if (ch != EOF)
4133 + ++(*num_jobs);
4134 + } while (ch != EOF);
4135 +
4136 + if (-1 == fseek(fstream, 0L, SEEK_SET))
4137 + bail_out("rewinding file failed");
4138 +
4139 + /* allocate space for exec times */
4140 + *exec_times = calloc(*num_jobs, sizeof(*exec_times));
4141 + if (!*exec_times)
4142 + bail_out("couldn't allocate memory");
4143 +
4144 + for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
4145 +
4146 + skip_comments(fstream);
4147 +
4148 + for (cur_col = 1; cur_col < column; ++cur_col) {
4149 + /* discard input until we get to the column we want */
4150 + int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
4151 + }
4152 +
4153 + /* get the desired exec. time */
4154 + if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
4155 + fprintf(stderr, "invalid execution time near line %d\n",
4156 + cur_job);
4157 + exit(EXIT_FAILURE);
4158 + }
4159 +
4160 + skip_to_next_line(fstream);
4161 + }
4162 +
4163 + assert(cur_job == *num_jobs);
4164 + fclose(fstream);
4165 +}
4166 +// 4096 = 32KB
4167 +// 8192 = 64KB
4168 +// 16384 = 128KB
4169 +// 32768 = 256KB
4170 +
4171 +#define NUMS 32768
4172 +static int num[NUMS];
4173 +static long unsigned int order[NUMS];
4174 +static char* progname;
4175 +
4176 +static int randrange(const int max)
4177 +{
4178 + return (rand() / (RAND_MAX / max + 1));
4179 +}
4180 +
4181 +static void sattolo(unsigned long *items, const unsigned long len)
4182 +{
4183 + unsigned long i;
4184 + /* first set up 0, 1, ..., n - 1 */
4185 + for (i = 0; i < len; i++)
4186 + items[i] = i;
4187 + /* note: i is now n */
4188 + while (1 < i--) {
4189 + /* 0 <= j < i */
4190 + int t, j = randrange(i);
4191 + t = items[i];
4192 + items[i] = items[j];
4193 + items[j] = t;
4194 + }
4195 +}
4196 +
4197 +static int loop_once(void)
4198 +{
4199 + int n, i, j = 0;
4200 + for (n = 0; n < 2; n++) {
4201 + for (i = 0; i < NUMS; i++) {
4202 + j += num[order[i]]++;
4203 + }
4204 + }
4205 + return j;
4206 +}
4207 +
4208 +static int loop_for(double exec_time, double emergency_exit)
4209 +{
4210 + double last_loop = 10, loop_start;
4211 + int tmp = 0;
4212 +
4213 + double start = cputime();
4214 + double now = cputime();
4215 +/*
4216 + while (now + last_loop < start + exec_time) {
4217 + loop_start = now;
4218 + tmp += loop_once();
4219 + now = cputime();
4220 + last_loop = now - loop_start;
4221 + if (emergency_exit && wctime() > emergency_exit) {
4222 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
4223 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
4224 + break;
4225 + }
4226 + }
4227 +*/
4228 + while (last_loop--) {
4229 + tmp += loop_once();
4230 + null_call(NULL);
4231 + }
4232 + return tmp;
4233 +}
4234 +
4235 +
4236 +static void debug_delay_loop(int count)
4237 +{
4238 + double start, end, delay;
4239 +
4240 + while (count--) {
4241 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
4242 + start = wctime();
4243 + loop_for(delay, 0);
4244 + end = wctime();
4245 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
4246 + delay,
4247 + end - start,
4248 + end - start - delay,
4249 + 100 * (end - start - delay) / delay);
4250 + }
4251 + }
4252 +}
4253 +
4254 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
4255 +{
4256 + double chunk1, chunk2;
4257 +
4258 + if (wctime() > program_end)
4259 + return 0;
4260 + else {
4261 + if (lock_od >= 0) {
4262 + /* simulate critical section somewhere in the middle */
4263 + chunk1 = drand48() * (exec_time - cs_length);
4264 + chunk2 = exec_time - cs_length - chunk1;
4265 +
4266 + /* non-critical section */
4267 + loop_for(chunk1, program_end + 1);
4268 +
4269 + /* critical section */
4270 + litmus_lock(lock_od);
4271 + loop_for(cs_length, program_end + 1);
4272 + litmus_unlock(lock_od);
4273 +
4274 + /* non-critical section */
4275 + loop_for(chunk2, program_end + 2);
4276 + } else {
4277 + loop_for(exec_time, program_end + 1);
4278 + }
4279 + sleep_next_period();
4280 + return 1;
4281 + }
4282 +}
4283 +
4284 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
4285 +{
4286 + int i, matched;
4287 + struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
4288 + char** arg = (char**)malloc(sizeof(char*) * num);
4289 + char *token, *saveptr;
4290 + double start, end;
4291 +
4292 + for (i = 0; i < num; i++) {
4293 + arg[i] = (char*)malloc(sizeof(char)*100);
4294 + }
4295 +
4296 + i = 0;
4297 + token = strtok_r(optarg, ":", &saveptr);
4298 + while(token != NULL) {
4299 + sprintf(arg[i++], "%s", token);
4300 + token = strtok_r(NULL, ":", &saveptr);
4301 + }
4302 +
4303 + *num_intervals = 0;
4304 +
4305 + for (i=0; i<num; i++) {
4306 + matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
4307 + if (matched != 2) {
4308 + fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
4309 + exit(5);
4310 + }
4311 + if (start < 0) {
4312 + fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
4313 + exit(5);
4314 + }
4315 + if (end <= start) {
4316 + fprintf(stderr, "interval %s: end before start\n", arg[i]);
4317 + exit(5);
4318 + }
4319 +
4320 + slots[i].start = ms2ns(start);
4321 + slots[i].end = ms2ns(end);
4322 +
4323 + if (i > 0 && slots[i - 1].end >= slots[i].start) {
4324 + fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
4325 + exit(5);
4326 + }
4327 +
4328 + (*num_intervals)++;
4329 + }
4330 +
4331 + for (i=0; i<num; i++) {
4332 + free(arg[i]);
4333 + }
4334 + free(arg);
4335 + return slots;
4336 +}
4337 +
4338 +#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:"
4339 +int main(int argc, char** argv)
4340 +{
4341 + int ret;
4342 + lt_t wcet;
4343 + lt_t period;
4344 + lt_t hyperperiod;
4345 + lt_t budget;
4346 + double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
4347 + unsigned int priority = LITMUS_NO_PRIORITY;
4348 + int migrate = 0;
4349 + int cluster = 0;
4350 + int opt;
4351 + int wait = 0;
4352 + int test_loop = 0;
4353 + int column = 1;
4354 + const char *file = NULL;
4355 + int want_enforcement = 0;
4356 + double duration = 0, start = 0;
4357 + double *exec_times = NULL;
4358 + double scale = 1.0;
4359 + task_class_t class = RT_CLASS_HARD;
4360 + int cur_job = 0, num_jobs = 0;
4361 + struct rt_task param;
4362 + struct mc2_task mc2_param;
4363 + struct reservation_config config;
4364 + int res_type = PERIODIC_POLLING;
4365 + int n_str, num_int = 0;
4366 +
4367 + int verbose = 0;
4368 + unsigned int job_no;
4369 +
4370 + /* locking */
4371 + int lock_od = -1;
4372 + int resource_id = 0;
4373 + const char *lock_namespace = "./rtspin-locks";
4374 + int protocol = -1;
4375 + double cs_length = 1; /* millisecond */
4376 +
4377 + progname = argv[0];
4378 +
4379 + /* default for reservation */
4380 + config.id = 0;
4381 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
4382 + config.cpu = -1;
4383 +
4384 + mc2_param.crit = CRIT_LEVEL_C;
4385 +
4386 + hyperperiod_ms = 1000;
4387 + budget_ms = 10;
4388 +
4389 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
4390 + switch (opt) {
4391 + case 'w':
4392 + wait = 1;
4393 + break;
4394 + case 'p':
4395 + cluster = atoi(optarg);
4396 + migrate = 1;
4397 + config.cpu = cluster;
4398 + break;
4399 + case 'q':
4400 + priority = atoi(optarg);
4401 + if (!litmus_is_valid_fixed_prio(priority))
4402 + usage("Invalid priority.");
4403 + break;
4404 + case 'c':
4405 + class = str2class(optarg);
4406 + if (class == -1)
4407 + usage("Unknown task class.");
4408 + break;
4409 + case 'e':
4410 + want_enforcement = 1;
4411 + break;
4412 + case 'l':
4413 + test_loop = 1;
4414 + break;
4415 + case 'o':
4416 + column = atoi(optarg);
4417 + break;
4418 + case 'f':
4419 + file = optarg;
4420 + break;
4421 + case 's':
4422 + scale = atof(optarg);
4423 + break;
4424 + case 'X':
4425 + protocol = lock_protocol_for_name(optarg);
4426 + if (protocol < 0)
4427 + usage("Unknown locking protocol specified.");
4428 + break;
4429 + case 'L':
4430 + cs_length = atof(optarg);
4431 + if (cs_length <= 0)
4432 + usage("Invalid critical section length.");
4433 + break;
4434 + case 'Q':
4435 + resource_id = atoi(optarg);
4436 + if (resource_id <= 0 && strcmp(optarg, "0"))
4437 + usage("Invalid resource ID.");
4438 + break;
4439 + case 'v':
4440 + verbose = 1;
4441 + break;
4442 + case 'm':
4443 + mc2_param.crit = atoi(optarg);
4444 + if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
4445 + usage("Invalid criticality level.");
4446 + }
4447 + res_type = PERIODIC_POLLING;
4448 + break;
4449 + case 'h':
4450 + hyperperiod_ms = atof(optarg);
4451 + break;
4452 + case 'b':
4453 + budget_ms = atof(optarg);
4454 + break;
4455 + case 'i':
4456 + config.priority = atoi(optarg);
4457 + break;
4458 + case ':':
4459 + usage("Argument missing.");
4460 + break;
4461 + case '?':
4462 + default:
4463 + usage("Bad argument.");
4464 + break;
4465 + }
4466 + }
4467 +
4468 + if (test_loop) {
4469 + debug_delay_loop(1);
4470 + return 0;
4471 + }
4472 +
4473 + if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
4474 + usage("Bad criticailty level or priority");
4475 +
4476 + srand(getpid());
4477 +
4478 + if (file) {
4479 + get_exec_times(file, column, &num_jobs, &exec_times);
4480 +
4481 + if (argc - optind < 2)
4482 + usage("Arguments missing.");
4483 +
4484 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
4485 + /* convert the execution time to seconds */
4486 + duration += exec_times[cur_job] * 0.001;
4487 + }
4488 + } else {
4489 + /*
4490 + * if we're not reading from the CSV file, then we need
4491 + * three parameters
4492 + */
4493 + if (argc - optind < 3)
4494 + usage("Arguments missing.");
4495 + }
4496 +
4497 + wcet_ms = atof(argv[optind + 0]);
4498 + period_ms = atof(argv[optind + 1]);
4499 +
4500 + wcet = ms2ns(wcet_ms);
4501 + period = ms2ns(period_ms);
4502 + budget = ms2ns(budget_ms);
4503 + hyperperiod = ms2ns(hyperperiod_ms);
4504 +
4505 + if (wcet <= 0)
4506 + usage("The worst-case execution time must be a "
4507 + "positive number.");
4508 + if (period <= 0)
4509 + usage("The period must be a positive number.");
4510 + if (!file && wcet > period) {
4511 + usage("The worst-case execution time must not "
4512 + "exceed the period.");
4513 + }
4514 +
4515 + if (!file)
4516 + duration = atof(argv[optind + 2]);
4517 + else if (file && num_jobs > 1)
4518 + duration += period_ms * 0.001 * (num_jobs - 1);
4519 +
4520 + if (migrate) {
4521 + ret = be_migrate_to_domain(cluster);
4522 + if (ret < 0)
4523 + bail_out("could not migrate to target partition or cluster.");
4524 + }
4525 +
4526 + sattolo(order, NUMS);
4527 +
4528 + /* reservation config */
4529 + config.id = gettid();
4530 +
4531 + if (hyperperiod%period != 0 ) {
4532 + ;//bail_out("hyperperiod must be multiple of period");
4533 + }
4534 +
4535 + config.polling_params.budget = budget;
4536 + config.polling_params.period = period;
4537 + config.polling_params.offset = 0;
4538 + config.polling_params.relative_deadline = 0;
4539 + if (config.polling_params.budget > config.polling_params.period) {
4540 + usage("The budget must not exceed the period.");
4541 + }
4542 +
4543 + /* create a reservation */
4544 + ret = reservation_create(res_type, &config);
4545 + if (ret < 0) {
4546 + bail_out("failed to create reservation.");
4547 + }
4548 +
4549 + init_rt_task_param(¶m);
4550 + param.exec_cost = wcet;
4551 + param.period = period;
4552 + param.priority = priority;
4553 + param.cls = class;
4554 + param.release_policy = TASK_PERIODIC;
4555 + param.budget_policy = (want_enforcement) ?
4556 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
4557 + if (migrate) {
4558 + param.cpu = gettid();
4559 + }
4560 + ret = set_rt_task_param(gettid(), ¶m);
4561 +//printf("SET_RT_TASK\n");
4562 + if (ret < 0)
4563 + bail_out("could not setup rt task params");
4564 +
4565 + mc2_param.res_id = gettid();
4566 + ret = set_mc2_task_param(gettid(), &mc2_param);
4567 +//printf("SET_MC2_TASK\n");
4568 + if (ret < 0)
4569 + bail_out("could not setup mc2 task params");
4570 +
4571 + init_litmus();
4572 +
4573 +//printf("INIT_LITMUS\n");
4574 + start = wctime();
4575 + ret = task_mode(LITMUS_RT_TASK);
4576 +//printf("TASK_MODE\n");
4577 + if (ret != 0)
4578 + bail_out("could not become RT task");
4579 +
4580 + if (protocol >= 0) {
4581 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
4582 + if (lock_od < 0) {
4583 + perror("litmus_open_lock");
4584 + usage("Could not open lock.");
4585 + }
4586 + }
4587 +
4588 +
4589 + if (wait) {
4590 + ret = wait_for_ts_release();
4591 + if (ret != 0)
4592 + bail_out("wait_for_ts_release()");
4593 + start = wctime();
4594 + }
4595 +
4596 + if (file) {
4597 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
4598 + job(exec_times[cur_job] * 0.001 * scale,
4599 + start + duration,
4600 + lock_od, cs_length * 0.001);
4601 + }
4602 + } else {
4603 + do {
4604 + if (verbose) {
4605 + get_job_no(&job_no);
4606 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
4607 + job_no, (wctime() - start) * 1000);
4608 + }
4609 + } while (job(wcet_ms * 0.001 * scale, start + duration,
4610 + lock_od, cs_length * 0.001));
4611 + }
4612 + ret = task_mode(BACKGROUND_TASK);
4613 + if (ret != 0)
4614 + bail_out("could not become regular task (huh?)");
4615 +
4616 + if (file)
4617 + free(exec_times);
4618 +
4619 + reservation_destroy(gettid(), config.cpu);
4620 +
4621 + return 0;
4622 +}
4623 diff --git a/bin/mc2thrash.c b/bin/mc2thrash.c
4624 new file mode 100644
4625 index 0000000..813f74f
4626 --- /dev/null
4627 +++ b/bin/mc2thrash.c
4628 @@ -0,0 +1,272 @@
4629 +#include <sys/time.h>
4630 +#include <sys/mman.h>
4631 +
4632 +#include <stdio.h>
4633 +#include <stdlib.h>
4634 +#include <unistd.h>
4635 +#include <time.h>
4636 +#include <string.h>
4637 +#include <assert.h>
4638 +#include <limits.h>
4639 +
4640 +#include "litmus.h"
4641 +#include "common.h"
4642 +#include "cache_common.h"
4643 +
4644 +#define PAGE_SIZE (4096)
4645 +#define CACHELINE_SIZE 32
4646 +#define WSS 1024
4647 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
4648 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
4649 +#define INTS_IN_1KB (1024 / sizeof(int))
4650 +
4651 +static cacheline_t* arena = NULL;
4652 +
4653 +static int random_walk(cacheline_t *mem, int write_cycle)
4654 +{
4655 + /* a random cycle among the cache lines was set up by init_arena(). */
4656 + int sum, i, next;
4657 +
4658 + int numlines = WSS * CACHELINES_IN_1KB;
4659 +
4660 + sum = 0;
4661 +
4662 + next = mem - arena;
4663 +
4664 + if (write_cycle == 0) {
4665 + for (i = 0; i < numlines; i++) {
4666 + /* every element in the cacheline has the same value */
4667 + next = arena[next].line[0];
4668 + sum += next;
4669 + }
4670 + }
4671 +
4672 + else {
4673 + int w, which_line;
4674 + for (i = 0, w = 0; i < numlines; i++) {
4675 + which_line = next;
4676 + next = arena[next].line[0];
4677 + if((w % write_cycle) != (write_cycle - 1)) {
4678 + sum += next;
4679 + }
4680 + else {
4681 + ((volatile cacheline_t*)arena)[which_line].line[0] = next;
4682 + }
4683 + }
4684 + }
4685 + return sum;
4686 +}
4687 +
4688 +static cacheline_t* random_start(void)
4689 +{
4690 + return arena + randrange(0, ((WSS * 1024)/sizeof(cacheline_t)));
4691 +}
4692 +
4693 +static volatile int dont_optimize_me = 0;
4694 +
4695 +static void usage(char *error) {
4696 + fprintf(stderr, "Error: %s\n", error);
4697 + fprintf(stderr,
4698 + "Usage:\n"
4699 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
4700 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
4701 + " rt_spin -l\n"
4702 + "\n"
4703 + "COMMON-OPTS = [-w] [-s SCALE]\n"
4704 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
4705 + " [-k WSS] [-l LOOPS] [-b BUDGET]\n"
4706 + "\n"
4707 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
4708 + exit(EXIT_FAILURE);
4709 +}
4710 +
4711 +static int loop_once(void)
4712 +{
4713 + cacheline_t *mem;
4714 + int temp;
4715 +
4716 + mem = random_start();
4717 + temp = random_walk(mem, 1);
4718 +
4719 + //mem = sequential_start(wss);
4720 + //temp = sequential_walk(mem, wss, 0);
4721 + dont_optimize_me = temp;
4722 +
4723 + return dont_optimize_me;
4724 +}
4725 +
4726 +static int job(double exec_time, double program_end)
4727 +{
4728 + if (wctime() > program_end)
4729 + return 0;
4730 + else {
4731 + double last_loop = 0, loop_start;
4732 + double start = cputime();
4733 + double now = cputime();
4734 + while(now + last_loop < start + exec_time) {
4735 + loop_start = now;
4736 + loop_once();
4737 + now = cputime();
4738 + last_loop = now - loop_start;
4739 + }
4740 + sleep_next_period();
4741 + return 1;
4742 + }
4743 +}
4744 +
4745 +#define OPTSTR "p:wm:i:k:"
4746 +int main(int argc, char** argv)
4747 +{
4748 + int ret, i;
4749 + lt_t wcet, period, budget;
4750 + double wcet_ms, period_ms;
4751 + unsigned int priority = LITMUS_NO_PRIORITY;
4752 + int migrate = 0;
4753 + int cluster = 0;
4754 + int opt;
4755 + int wait = 0;
4756 + double duration = 0, start = 0;
4757 + struct rt_task param;
4758 + struct mc2_task mc2_param;
4759 + struct reservation_config config;
4760 + int res_type = PERIODIC_POLLING;
4761 + size_t arena_sz;
4762 +
4763 + /* default for reservation */
4764 + config.id = 0;
4765 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
4766 + config.cpu = -1;
4767 + mc2_param.crit = CRIT_LEVEL_C;
4768 +
4769 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
4770 + switch (opt) {
4771 + case 'w':
4772 + wait = 1;
4773 + break;
4774 + case 'p':
4775 + cluster = atoi(optarg);
4776 + migrate = 1;
4777 + config.cpu = cluster;
4778 + break;
4779 + case 'm':
4780 + mc2_param.crit = atoi(optarg);
4781 + if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
4782 + res_type = PERIODIC_POLLING;
4783 + }
4784 + else
4785 + usage("Invalid criticality level.");
4786 + break;
4787 + case 'i':
4788 + config.priority = atoi(optarg);
4789 + break;
4790 + case ':':
4791 + usage("Argument missing.");
4792 + break;
4793 + case '?':
4794 + default:
4795 + usage("Bad argument.");
4796 + break;
4797 + }
4798 + }
4799 + srand(getpid());
4800 + /* We need three parameters */
4801 + if (argc - optind < 3)
4802 + usage("Arguments missing.");
4803 +
4804 + wcet_ms = atof(argv[optind + 0]);
4805 + period_ms = atof(argv[optind + 1]);
4806 +
4807 + wcet = ms2ns(wcet_ms);
4808 + period = ms2ns(period_ms);
4809 + budget = ms2ns(period_ms);
4810 + if (wcet <= 0)
4811 + usage("The worst-case execution time must be a "
4812 + "positive number.");
4813 + if (period <= 0)
4814 + usage("The period must be a positive number.");
4815 + if (wcet > period) {
4816 + usage("The worst-case execution time must not "
4817 + "exceed the period.");
4818 + }
4819 +
4820 + duration = atof(argv[optind + 2]);
4821 +
4822 + if (migrate) {
4823 + ret = be_migrate_to_domain(cluster);
4824 + if (ret < 0)
4825 + bail_out("could not migrate to target partition or cluster.");
4826 + }
4827 +
4828 + /* reservation config */
4829 + config.id = gettid();
4830 + config.polling_params.budget = budget;
4831 + config.polling_params.period = period;
4832 + config.polling_params.offset = 0;
4833 + config.polling_params.relative_deadline = 0;
4834 +
4835 + if (config.polling_params.budget > config.polling_params.period) {
4836 + usage("The budget must not exceed the period.");
4837 + }
4838 +
4839 + /* create a reservation */
4840 + ret = reservation_create(res_type, &config);
4841 + if (ret < 0) {
4842 + bail_out("failed to create reservation.");
4843 + }
4844 +
4845 + init_rt_task_param(¶m);
4846 + param.exec_cost = wcet;
4847 + param.period = period;
4848 + param.priority = priority;
4849 + param.cls = RT_CLASS_HARD;
4850 + param.release_policy = TASK_PERIODIC;
4851 + param.budget_policy = NO_ENFORCEMENT;
4852 + if (migrate) {
4853 + param.cpu = gettid();
4854 + }
4855 + ret = set_rt_task_param(gettid(), ¶m);
4856 + if (ret < 0)
4857 + bail_out("could not setup rt task params");
4858 +
4859 + mc2_param.res_id = gettid();
4860 + ret = set_mc2_task_param(gettid(), &mc2_param);
4861 + if (ret < 0)
4862 + bail_out("could not setup mc2 task params");
4863 +
4864 + arena_sz = WSS*1024;
4865 + arena = alloc_arena(arena_sz, 0, 0);
4866 + init_arena(arena, arena_sz);
4867 +
4868 + ret = init_litmus();
4869 + if (ret != 0)
4870 + bail_out("init_litmus() failed\n");
4871 +
4872 + start = wctime();
4873 + ret = task_mode(LITMUS_RT_TASK);
4874 + if (ret != 0)
4875 + bail_out("could not become RT task");
4876 +
4877 + if (mc2_param.crit == CRIT_LEVEL_C)
4878 + set_page_color(-1);
4879 + else
4880 + set_page_color(config.cpu);
4881 +
4882 + lock_memory();
4883 +
4884 + if (wait) {
4885 + ret = wait_for_ts_release();
4886 + if (ret != 0)
4887 + bail_out("wait_for_ts_release()");
4888 + start = wctime();
4889 + }
4890 +
4891 + while (job(wcet_ms * 0.001, start + duration)) {};
4892 +
4893 + ret = task_mode(BACKGROUND_TASK);
4894 + if (ret != 0)
4895 + bail_out("could not become regular task (huh?)");
4896 +
4897 + reservation_destroy(gettid(), config.cpu);
4898 + dealloc_arena(arena, arena_sz);
4899 + return 0;
4900 +}
4901 diff --git a/bin/mc2thrash2.c b/bin/mc2thrash2.c
4902 new file mode 100644
4903 index 0000000..89af23e
4904 --- /dev/null
4905 +++ b/bin/mc2thrash2.c
4906 @@ -0,0 +1,626 @@
4907 +#include <sys/time.h>
4908 +#include <sys/mman.h>
4909 +
4910 +#include <stdio.h>
4911 +#include <stdlib.h>
4912 +#include <unistd.h>
4913 +#include <time.h>
4914 +#include <string.h>
4915 +#include <assert.h>
4916 +#include <limits.h>
4917 +
4918 +
4919 +#include "litmus.h"
4920 +#include "common.h"
4921 +#include "cache_common.h"
4922 +
4923 +#define PAGE_SIZE (4096)
4924 +
4925 +#define CACHELINE_SIZE 32
4926 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
4927 +//#define ARENA_SIZE_MB 4
4928 +#define ARENA_SIZE_KB 1024
4929 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
4930 +#define INTS_IN_1KB (1024 / sizeof(int))
4931 +#define NUM_ARENA_ELEM ((ARENA_SIZE_KB * 1024)/sizeof(cacheline_t))
4932 +
4933 +//static int wss = ARENA_SIZE_MB * 1024;
4934 +static int wss = ARENA_SIZE_KB;
4935 +static int write_cycle = 1; /* every nth cycle is a write; 0 means read-only */
4936 +static int loops = 10;
4937 +
4938 +static cacheline_t* arena = NULL;
4939 +
4940 +typedef int (*walk_t)(cacheline_t *mem, int wss, int write_cycle);
4941 +typedef cacheline_t* (*walk_start_t)(int wss);
4942 +
4943 +struct walk_method
4944 +{
4945 + const walk_t walk;
4946 + const walk_start_t walk_start;
4947 +};
4948 +
4949 +static int sequential_walk(cacheline_t *_mem, int wss, int write_cycle)
4950 +{
4951 + int sum = 0, i;
4952 + int* mem = (int*)_mem; /* treat as raw buffer of ints */
4953 + int num_ints = wss * INTS_IN_1KB;
4954 +
4955 + if (write_cycle > 0) {
4956 + for (i = 0; i < num_ints; i++) {
4957 + if (i % write_cycle == (write_cycle - 1))
4958 + mem[i]++;
4959 + else
4960 + sum += mem[i];
4961 + }
4962 + } else {
4963 + /* sequential access, pure read */
4964 + for (i = 0; i < num_ints; i++)
4965 + sum += mem[i];
4966 + }
4967 + return sum;
4968 +}
4969 +
4970 +static cacheline_t* sequential_start(int wss)
4971 +{
4972 + static int pos = 0;
4973 +
4974 + int num_cachelines = wss * CACHELINES_IN_1KB;
4975 +
4976 + cacheline_t *mem;
4977 +
4978 + /* Don't allow re-use between allocations.
4979 + * At most half of the arena may be used
4980 + * at any one time.
4981 + */
4982 + if (num_cachelines * 2 > NUM_ARENA_ELEM)
4983 + die("static memory arena too small");
4984 +
4985 + if (pos + num_cachelines > NUM_ARENA_ELEM) {
4986 + /* wrap to beginning */
4987 + mem = arena;
4988 + pos = num_cachelines;
4989 + } else {
4990 + mem = arena + pos;
4991 + pos += num_cachelines;
4992 + }
4993 +
4994 + return mem;
4995 +}
4996 +
4997 +static const struct walk_method sequential_method =
4998 +{
4999 + .walk = sequential_walk,
5000 + .walk_start = sequential_start
5001 +};
5002 +
5003 +
5004 +/* Random walk around the arena in cacheline-sized chunks.
5005 + Cacheline-sized chucks ensures the same utilization of each
5006 + hit line as sequential read. (Otherwise, our utilization
5007 + would only be 1/INTS_IN_CACHELINE.) */
5008 +static int random_walk(cacheline_t *mem, int wss, int write_cycle)
5009 +{
5010 + /* a random cycle among the cache lines was set up by init_arena(). */
5011 + int sum, i, j, next, which_line;
5012 +
5013 + int numlines = wss * CACHELINES_IN_1KB;
5014 +
5015 + sum = 0;
5016 +
5017 + /* contents of arena is structured s.t. offsets are all
5018 + w.r.t. to start of arena, so compute the initial offset */
5019 + next = mem - arena;
5020 +
5021 + if (write_cycle == 0) {
5022 + for (i = 0; i < numlines; i++) {
5023 + which_line = next;
5024 + /* every element in the cacheline has the same value */
5025 + for(j = 0; j < INTS_IN_CACHELINE; j++) {
5026 + next = arena[which_line].line[j];
5027 + sum += next;
5028 + }
5029 + }
5030 + }
5031 +
5032 + else {
5033 + int w;
5034 + for (i = 0, w = 0; i < numlines; i++) {
5035 + which_line = next;
5036 + /* count down s.t. next has value of 0th int
5037 + when the loop exits */
5038 + for(j = 0; j < INTS_IN_CACHELINE; j++) {
5039 + next = arena[which_line].line[j];
5040 + if((w % write_cycle) != (write_cycle - 1)) {
5041 + sum += next;
5042 + }
5043 + else {
5044 + /* Write back what we just read. We can't write back a
5045 + different value without destroying the walk-cycle, so
5046 + cast the write to volatile to ensure the write is
5047 + performed. Note: Volatiles are still cached. */
5048 + ((volatile cacheline_t*)arena)[which_line].line[j] = next;
5049 + }
5050 + }
5051 + }
5052 + }
5053 + return sum;
5054 +}
5055 +
5056 +static cacheline_t* random_start(int wss)
5057 +{
5058 + return arena + randrange(0, NUM_ARENA_ELEM);
5059 +}
5060 +
5061 +static const struct walk_method random_method =
5062 +{
5063 + .walk = random_walk,
5064 + .walk_start = random_start
5065 +};
5066 +
5067 +static volatile int dont_optimize_me = 0;
5068 +
5069 +static void usage(char *error) {
5070 + fprintf(stderr, "Error: %s\n", error);
5071 + fprintf(stderr,
5072 + "Usage:\n"
5073 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
5074 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
5075 + " rt_spin -l\n"
5076 + "\n"
5077 + "COMMON-OPTS = [-w] [-s SCALE]\n"
5078 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
5079 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
5080 + " [-i [start,end]:[start,end]...]\n"
5081 + "\n"
5082 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
5083 + "CRITICAL SECTION LENGTH is in milliseconds.\n");
5084 + exit(EXIT_FAILURE);
5085 +}
5086 +
5087 +/*
5088 + * returns the character that made processing stop, newline or EOF
5089 + */
5090 +static int skip_to_next_line(FILE *fstream)
5091 +{
5092 + int ch;
5093 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
5094 + return ch;
5095 +}
5096 +
5097 +static void skip_comments(FILE *fstream)
5098 +{
5099 + int ch;
5100 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
5101 + skip_to_next_line(fstream);
5102 + ungetc(ch, fstream);
5103 +}
5104 +
5105 +static void get_exec_times(const char *file, const int column,
5106 + int *num_jobs, double **exec_times)
5107 +{
5108 + FILE *fstream;
5109 + int cur_job, cur_col, ch;
5110 + *num_jobs = 0;
5111 +
5112 + fstream = fopen(file, "r");
5113 + if (!fstream)
5114 + bail_out("could not open execution time file");
5115 +
5116 + /* figure out the number of jobs */
5117 + do {
5118 + skip_comments(fstream);
5119 + ch = skip_to_next_line(fstream);
5120 + if (ch != EOF)
5121 + ++(*num_jobs);
5122 + } while (ch != EOF);
5123 +
5124 + if (-1 == fseek(fstream, 0L, SEEK_SET))
5125 + bail_out("rewinding file failed");
5126 +
5127 + /* allocate space for exec times */
5128 + *exec_times = calloc(*num_jobs, sizeof(*exec_times));
5129 + if (!*exec_times)
5130 + bail_out("couldn't allocate memory");
5131 +
5132 + for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
5133 +
5134 + skip_comments(fstream);
5135 +
5136 + for (cur_col = 1; cur_col < column; ++cur_col) {
5137 + /* discard input until we get to the column we want */
5138 + int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
5139 + }
5140 +
5141 + /* get the desired exec. time */
5142 + if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
5143 + fprintf(stderr, "invalid execution time near line %d\n",
5144 + cur_job);
5145 + exit(EXIT_FAILURE);
5146 + }
5147 +
5148 + skip_to_next_line(fstream);
5149 + }
5150 +
5151 + assert(cur_job == *num_jobs);
5152 + fclose(fstream);
5153 +}
5154 +
5155 +static char* progname;
5156 +
5157 +static int loop_once(void)
5158 +{
5159 + cacheline_t *mem;
5160 + int temp;
5161 +
5162 + mem = random_method.walk_start(wss);
5163 + temp = random_method.walk(mem, wss, 4);
5164 + dont_optimize_me = temp;
5165 +}
5166 +
5167 +static int loop_for(double exec_time, double emergency_exit)
5168 +{
5169 + double last_loop = 0, loop_start;
5170 + int tmp = 0;
5171 + int cur_loop = 0;
5172 +
5173 + double start = cputime();
5174 + double now = cputime();
5175 +
5176 + while (now + last_loop < start + exec_time) {
5177 + loop_start = now;
5178 + tmp = loop_once();
5179 + now = cputime();
5180 + last_loop = now - loop_start;
5181 + if (emergency_exit && wctime() > emergency_exit) {
5182 + /* Oops --- this should only be possible if the execution time tracking
5183 + * is broken in the LITMUS^RT kernel. */
5184 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
5185 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
5186 + break;
5187 + }
5188 + }
5189 +
5190 + return tmp;
5191 +}
5192 +
5193 +
5194 +static void debug_delay_loop(void)
5195 +{
5196 + double start, end, delay;
5197 +
5198 + while (1) {
5199 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
5200 + start = wctime();
5201 + loop_for(delay, 0);
5202 + end = wctime();
5203 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
5204 + delay,
5205 + end - start,
5206 + end - start - delay,
5207 + 100 * (end - start - delay) / delay);
5208 + }
5209 + }
5210 +}
5211 +
5212 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
5213 +{
5214 + double chunk1, chunk2;
5215 +
5216 + if (wctime() > program_end)
5217 + return 0;
5218 + else {
5219 + if (lock_od >= 0) {
5220 + /* simulate critical section somewhere in the middle */
5221 + chunk1 = drand48() * (exec_time - cs_length);
5222 + chunk2 = exec_time - cs_length - chunk1;
5223 +
5224 + /* non-critical section */
5225 + loop_for(chunk1, program_end + 1);
5226 +
5227 + /* critical section */
5228 + litmus_lock(lock_od);
5229 + loop_for(cs_length, program_end + 1);
5230 + litmus_unlock(lock_od);
5231 +
5232 + /* non-critical section */
5233 + loop_for(chunk2, program_end + 2);
5234 + } else {
5235 + loop_for(exec_time, program_end + 1);
5236 + }
5237 + sleep_next_period();
5238 + return 1;
5239 + }
5240 +}
5241 +
5242 +#define OPTSTR "p:c:wl:veo:f:s:q:X:L:Q:vh:m:i:b:"
5243 +int main(int argc, char** argv)
5244 +{
5245 + int ret, i;
5246 + lt_t wcet;
5247 + lt_t period;
5248 + lt_t hyperperiod;
5249 + lt_t budget;
5250 + double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
5251 + unsigned int priority = LITMUS_NO_PRIORITY;
5252 + int migrate = 0;
5253 + int cluster = 0;
5254 + int opt;
5255 + int wait = 0;
5256 + int test_loop = 0;
5257 + int column = 1;
5258 + const char *file = NULL;
5259 + int want_enforcement = 0;
5260 + double duration = 0, start = 0;
5261 + double *exec_times = NULL;
5262 + double scale = 1.0;
5263 + task_class_t class = RT_CLASS_HARD;
5264 + int cur_job = 0, num_jobs = 0;
5265 + struct rt_task param;
5266 + struct mc2_task mc2_param;
5267 + struct reservation_config config;
5268 + int res_type = PERIODIC_POLLING;
5269 + int n_str, num_int = 0;
5270 + size_t arena_sz;
5271 + int verbose = 0;
5272 + unsigned int job_no;
5273 +
5274 + /* locking */
5275 + int lock_od = -1;
5276 + int resource_id = 0;
5277 + const char *lock_namespace = "./rtspin-locks";
5278 + int protocol = -1;
5279 + double cs_length = 1; /* millisecond */
5280 +
5281 + progname = argv[0];
5282 +
5283 + /* default for reservation */
5284 + config.id = 0;
5285 + config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
5286 + config.cpu = -1;
5287 +
5288 + mc2_param.crit = CRIT_LEVEL_C;
5289 +
5290 + hyperperiod_ms = 1000;
5291 + budget_ms = 10;
5292 +
5293 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
5294 + switch (opt) {
5295 + case 'w':
5296 + wait = 1;
5297 + break;
5298 + case 'p':
5299 + cluster = atoi(optarg);
5300 + migrate = 1;
5301 + config.cpu = cluster;
5302 + break;
5303 + case 'q':
5304 + priority = atoi(optarg);
5305 + if (!litmus_is_valid_fixed_prio(priority))
5306 + usage("Invalid priority.");
5307 + break;
5308 + case 'c':
5309 + class = str2class(optarg);
5310 + if (class == -1)
5311 + usage("Unknown task class.");
5312 + break;
5313 + case 'e':
5314 + want_enforcement = 1;
5315 + break;
5316 + case 'l':
5317 + loops = atoi(optarg);
5318 + break;
5319 + case 'o':
5320 + column = atoi(optarg);
5321 + break;
5322 + case 'f':
5323 + file = optarg;
5324 + break;
5325 + case 's':
5326 + scale = atof(optarg);
5327 + break;
5328 + case 'X':
5329 + protocol = lock_protocol_for_name(optarg);
5330 + if (protocol < 0)
5331 + usage("Unknown locking protocol specified.");
5332 + break;
5333 + case 'L':
5334 + cs_length = atof(optarg);
5335 + if (cs_length <= 0)
5336 + usage("Invalid critical section length.");
5337 + break;
5338 + case 'Q':
5339 + resource_id = atoi(optarg);
5340 + if (resource_id <= 0 && strcmp(optarg, "0"))
5341 + usage("Invalid resource ID.");
5342 + break;
5343 + case 'v':
5344 + verbose = 1;
5345 + break;
5346 + case 'm':
5347 + mc2_param.crit = atoi(optarg);
5348 + if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
5349 + res_type = PERIODIC_POLLING;
5350 + }
5351 + else
5352 + usage("Invalid criticality level.");
5353 + break;
5354 + case 'h':
5355 + hyperperiod_ms = atof(optarg);
5356 + break;
5357 + case 'b':
5358 + budget_ms = atof(optarg);
5359 + break;
5360 + case 'i':
5361 + config.priority = atoi(optarg);
5362 + break;
5363 + case ':':
5364 + usage("Argument missing.");
5365 + break;
5366 + case '?':
5367 + default:
5368 + usage("Bad argument.");
5369 + break;
5370 + }
5371 + }
5372 +
5373 + if (test_loop) {
5374 + debug_delay_loop();
5375 + return 0;
5376 + }
5377 +
5378 + srand(getpid());
5379 +
5380 + if (file) {
5381 + get_exec_times(file, column, &num_jobs, &exec_times);
5382 +
5383 + if (argc - optind < 2)
5384 + usage("Arguments missing.");
5385 +
5386 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
5387 + /* convert the execution time to seconds */
5388 + duration += exec_times[cur_job] * 0.001;
5389 + }
5390 + } else {
5391 + /*
5392 + * if we're not reading from the CSV file, then we need
5393 + * three parameters
5394 + */
5395 + if (argc - optind < 3)
5396 + usage("Arguments missing.");
5397 + }
5398 +
5399 + wcet_ms = atof(argv[optind + 0]);
5400 + period_ms = atof(argv[optind + 1]);
5401 +
5402 + wcet = ms2ns(wcet_ms);
5403 + period = ms2ns(period_ms);
5404 + budget = ms2ns(budget_ms);
5405 + hyperperiod = ms2ns(hyperperiod_ms);
5406 + if (wcet <= 0)
5407 + usage("The worst-case execution time must be a "
5408 + "positive number.");
5409 + if (period <= 0)
5410 + usage("The period must be a positive number.");
5411 + if (!file && wcet > period) {
5412 + usage("The worst-case execution time must not "
5413 + "exceed the period.");
5414 + }
5415 +
5416 + if (!file)
5417 + duration = atof(argv[optind + 2]);
5418 + else if (file && num_jobs > 1)
5419 + duration += period_ms * 0.001 * (num_jobs - 1);
5420 +
5421 + if (migrate) {
5422 + ret = be_migrate_to_domain(cluster);
5423 + if (ret < 0)
5424 + bail_out("could not migrate to target partition or cluster.");
5425 + }
5426 +
5427 + /* reservation config */
5428 + config.id = gettid();
5429 +
5430 + if (hyperperiod%period != 0 ) {
5431 + ;//bail_out("hyperperiod must be multiple of period");
5432 + }
5433 +
5434 + config.polling_params.budget = budget;
5435 + config.polling_params.period = period;
5436 + config.polling_params.offset = 0;
5437 + config.polling_params.relative_deadline = 0;
5438 +
5439 + if (config.polling_params.budget > config.polling_params.period) {
5440 + usage("The budget must not exceed the period.");
5441 + }
5442 +
5443 + /* create a reservation */
5444 + ret = reservation_create(res_type, &config);
5445 + if (ret < 0) {
5446 + bail_out("failed to create reservation.");
5447 + }
5448 +
5449 + init_rt_task_param(¶m);
5450 + param.exec_cost = wcet;
5451 + param.period = period;
5452 + param.priority = priority;
5453 + param.cls = class;
5454 + param.release_policy = TASK_PERIODIC;
5455 + param.budget_policy = (want_enforcement) ?
5456 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
5457 + if (migrate) {
5458 + param.cpu = gettid();
5459 + }
5460 + ret = set_rt_task_param(gettid(), ¶m);
5461 + if (ret < 0)
5462 + bail_out("could not setup rt task params");
5463 +
5464 + mc2_param.res_id = gettid();
5465 + ret = set_mc2_task_param(gettid(), &mc2_param);
5466 + if (ret < 0)
5467 + bail_out("could not setup mc2 task params");
5468 +
5469 + arena_sz = ARENA_SIZE_KB*1024;
5470 + arena = alloc_arena(arena_sz, 0, 0);
5471 + init_arena(arena, arena_sz);
5472 +
5473 + if (mc2_param.crit == CRIT_LEVEL_C)
5474 + set_page_color(-1);
5475 + else
5476 + set_page_color(config.cpu);
5477 +
5478 + lock_memory();
5479 +
5480 + ret = init_litmus();
5481 + if (ret != 0)
5482 + bail_out("init_litmus() failed\n");
5483 +
5484 + start = wctime();
5485 + ret = task_mode(LITMUS_RT_TASK);
5486 + if (ret != 0)
5487 + bail_out("could not become RT task");
5488 +
5489 + if (protocol >= 0) {
5490 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
5491 + if (lock_od < 0) {
5492 + perror("litmus_open_lock");
5493 + usage("Could not open lock.");
5494 + }
5495 + }
5496 +
5497 +
5498 + if (wait) {
5499 + ret = wait_for_ts_release();
5500 + if (ret != 0)
5501 + bail_out("wait_for_ts_release()");
5502 + start = wctime();
5503 + }
5504 +
5505 + if (file) {
5506 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
5507 + job(exec_times[cur_job] * 0.001 * scale,
5508 + start + duration,
5509 + lock_od, cs_length * 0.001);
5510 + }
5511 + } else {
5512 + do {
5513 + if (verbose) {
5514 + get_job_no(&job_no);
5515 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
5516 + job_no, (wctime() - start) * 1000);
5517 + }
5518 + } while (job(wcet_ms * 0.001 * scale, start + duration,
5519 + lock_od, cs_length * 0.001));
5520 + }
5521 +
5522 + ret = task_mode(BACKGROUND_TASK);
5523 + if (ret != 0)
5524 + bail_out("could not become regular task (huh?)");
5525 +
5526 + if (file)
5527 + free(exec_times);
5528 +
5529 + reservation_destroy(gettid(), config.cpu);
5530 + dealloc_arena(arena, arena_sz);
5531 + return 0;
5532 +}
5533 diff --git a/bin/memthrash.c b/bin/memthrash.c
5534 new file mode 100644
5535 index 0000000..5eed3cc
5536 --- /dev/null
5537 +++ b/bin/memthrash.c
5538 @@ -0,0 +1,62 @@
5539 +#include <stdio.h>
5540 +#include <stdlib.h>
5541 +#include <stdint.h>
5542 +#include <string.h>
5543 +
5544 +#include <sys/mman.h>
5545 +#include <sys/resource.h>
5546 +#include <unistd.h>
5547 +#include <sched.h>
5548 +
5549 +#include <time.h>
5550 +
5551 +#include "cache_common.h"
5552 +
5553 +#define NUM_VARS (8388608*2)
5554 +
5555 +int64_t data[NUM_VARS];
5556 +
5557 +#define OPTSTR "m:"
5558 +int main(int argc, char** argv)
5559 +{
5560 + int i;
5561 + int64_t sum;
5562 +
5563 + int cpu = -1;
5564 + int opt;
5565 +
5566 + while ((opt = getopt(argc, argv, OPTSTR)) != -1)
5567 + {
5568 + switch(opt)
5569 + {
5570 + case 'm':
5571 + cpu = atoi(optarg);
5572 + break;
5573 + case ':':
5574 + case '?':
5575 + default:
5576 + printf("Bad or missing argument.\n");
5577 + exit(-1);
5578 + }
5579 + }
5580 +
5581 + srand(time(NULL));
5582 +
5583 + if(cpu != -1)
5584 + migrate_to(cpu);
5585 +
5586 + lock_memory();
5587 + renice(-20); /* meanest task around */
5588 +
5589 + while (1) {
5590 + for (i = 0; i < NUM_VARS; i++)
5591 + data[i] = rand();
5592 + sum = 0;
5593 + for (i = 0; i < NUM_VARS; i++)
5594 + sum += (i % 2 ? 1 : -1) * data[i];
5595 + for (i = NUM_VARS - 1; i >= 0; i--)
5596 + sum += (i % 2 ? -1 : 1) * 100 / (data[i] ? data[i] : 1);
5597 + }
5598 +
5599 + return 0;
5600 +}
5601 \ No newline at end of file
5602 diff --git a/bin/portab.h b/bin/portab.h
5603 new file mode 100644
5604 index 0000000..f0222b1
5605 --- /dev/null
5606 +++ b/bin/portab.h
5607 @@ -0,0 +1,41 @@
5608 +#ifndef __PORTAB_H__
5609 +#define __PORTAB_H__
5610 +
5611 +#define IF_ELSE(a,b,c) ((a) ? (b) : (c))
5612 +
5613 +#if defined(__DSP5600x__)
5614 +
5615 +#define S16BIT int
5616 +#define U16BIT unsigned int
5617 +#define S24BIT int
5618 +#define U24BIT unsigned int
5619 +#define S32BIT long
5620 +#define U32BIT unsigned long
5621 +
5622 +#elif defined(__ADSP2101__) || defined(__TMS320C50__) || \
5623 + defined(__DSP16xx__) || defined(__DSP56156__) || \
5624 + defined(__uPD77016__)
5625 +
5626 +#define S16BIT int
5627 +#define U16BIT unsigned int
5628 +#define S24BIT long
5629 +#define U24BIT unsigned long
5630 +#define S32BIT long
5631 +#define U32BIT unsigned long
5632 +
5633 +#else
5634 +
5635 +#define S16BIT short
5636 +#define U16BIT unsigned short
5637 +#define S24BIT int
5638 +#define U24BIT unsigned int
5639 +#define S32BIT int
5640 +#define U32BIT unsigned int
5641 +/*
5642 +#include "mocad.H" // use this with ObjectCenter only!
5643 +*/
5644 +#endif
5645 +#endif
5646 +
5647 +
5648 +
5649 diff --git a/bin/resspin.c b/bin/resspin.c
5650 new file mode 100644
5651 index 0000000..8848d8b
5652 --- /dev/null
5653 +++ b/bin/resspin.c
5654 @@ -0,0 +1,576 @@
5655 +#include <sys/time.h>
5656 +#include <sys/mman.h>
5657 +
5658 +#include <stdio.h>
5659 +#include <stdlib.h>
5660 +#include <unistd.h>
5661 +#include <time.h>
5662 +#include <string.h>
5663 +#include <assert.h>
5664 +#include <limits.h>
5665 +
5666 +
5667 +#include "litmus.h"
5668 +#include "common.h"
5669 +#include "cache_common.h"
5670 +
5671 +#define PAGE_SIZE (4096)
5672 +
5673 +#define CACHELINE_SIZE 32
5674 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
5675 +#define ARENA_SIZE_KB 64
5676 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
5677 +#define INTS_IN_1KB (1024 / sizeof(int))
5678 +#define NUM_ARENA_ELEM ((ARENA_SIZE_KB * 1024)/sizeof(cacheline_t))
5679 +
5680 +//static int wss = ARENA_SIZE_KB;
5681 +static int loops = 10;
5682 +
5683 +static cacheline_t* arena = NULL;
5684 +
5685 +struct timeval tm1, tm2;
5686 +
5687 +typedef int (*walk_t)(cacheline_t *mem, int wss, int write_cycle);
5688 +typedef cacheline_t* (*walk_start_t)(int wss);
5689 +
5690 +struct walk_method
5691 +{
5692 + const walk_t walk;
5693 + const walk_start_t walk_start;
5694 +};
5695 +
5696 +static int sequential_walk(cacheline_t *_mem, int wss, int write_cycle)
5697 +{
5698 + int sum = 0, i;
5699 + int* mem = (int*)_mem; /* treat as raw buffer of ints */
5700 + int num_ints = wss * INTS_IN_1KB;
5701 +
5702 + if (write_cycle > 0) {
5703 + for (i = 0; i < num_ints; i++) {
5704 + if (i % write_cycle == (write_cycle - 1))
5705 + mem[i]++;
5706 + else
5707 + sum += mem[i];
5708 + }
5709 + } else {
5710 + /* sequential access, pure read */
5711 + for (i = 0; i < num_ints; i++)
5712 + sum += mem[i];
5713 + }
5714 + return sum;
5715 +}
5716 +
5717 +static cacheline_t* sequential_start(int wss)
5718 +{
5719 + static int pos = 0;
5720 +
5721 + int num_cachelines = wss * CACHELINES_IN_1KB;
5722 +
5723 + cacheline_t *mem;
5724 +
5725 + /* Don't allow re-use between allocations.
5726 + * At most half of the arena may be used
5727 + * at any one time.
5728 + */
5729 + //if (num_cachelines * 2 > NUM_ARENA_ELEM)
5730 + //die("static memory arena too small");
5731 +
5732 + if (pos + num_cachelines > ((wss * 1024)/sizeof(cacheline_t))) {
5733 + /* wrap to beginning */
5734 + mem = arena;
5735 + pos = num_cachelines;
5736 + } else {
5737 + mem = arena + pos;
5738 + pos += num_cachelines;
5739 + }
5740 +
5741 + return mem;
5742 +}
5743 +
5744 +static const struct walk_method sequential_method =
5745 +{
5746 + .walk = sequential_walk,
5747 + .walk_start = sequential_start
5748 +};
5749 +
5750 +
5751 +/* Random walk around the arena in cacheline-sized chunks.
5752 + Cacheline-sized chucks ensures the same utilization of each
5753 + hit line as sequential read. (Otherwise, our utilization
5754 + would only be 1/INTS_IN_CACHELINE.) */
5755 +static int random_walk(cacheline_t *mem, int wss, int write_cycle)
5756 +{
5757 + /* a random cycle among the cache lines was set up by init_arena(). */
5758 + int sum, i, j, next, which_line;
5759 +
5760 + int numlines = wss * CACHELINES_IN_1KB;
5761 +
5762 + sum = 0;
5763 +
5764 + /* contents of arena is structured s.t. offsets are all
5765 + w.r.t. to start of arena, so compute the initial offset */
5766 + next = mem - arena;
5767 +
5768 + if (write_cycle == 0) {
5769 + for (i = 0; i < numlines; i++) {
5770 + which_line = next;
5771 + /* every element in the cacheline has the same value */
5772 + for(j = 0; j < INTS_IN_CACHELINE; j++) {
5773 + next = arena[which_line].line[j];
5774 + sum += next;
5775 + }
5776 + }
5777 + }
5778 +
5779 + else {
5780 + int w;
5781 + for (i = 0, w = 0; i < numlines; i++) {
5782 + which_line = next;
5783 + /* count down s.t. next has value of 0th int
5784 + when the loop exits */
5785 + for(j = 0; j < INTS_IN_CACHELINE; j++) {
5786 + next = arena[which_line].line[j];
5787 + if((w % write_cycle) != (write_cycle - 1)) {
5788 + sum += next;
5789 + }
5790 + else {
5791 + /* Write back what we just read. We can't write back a
5792 + different value without destroying the walk-cycle, so
5793 + cast the write to volatile to ensure the write is
5794 + performed. Note: Volatiles are still cached. */
5795 + ((volatile cacheline_t*)arena)[which_line].line[j] = next;
5796 + }
5797 + }
5798 + }
5799 + }
5800 + return sum;
5801 +}
5802 +
5803 +static cacheline_t* random_start(int wss)
5804 +{
5805 + return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
5806 +}
5807 +
5808 +static const struct walk_method random_method =
5809 +{
5810 + .walk = random_walk,
5811 + .walk_start = random_start
5812 +};
5813 +
5814 +static volatile int dont_optimize_me = 0;
5815 +
5816 +static void usage(char *error) {
5817 + fprintf(stderr, "Error: %s\n", error);
5818 + fprintf(stderr,
5819 + "Usage:\n"
5820 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
5821 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
5822 + " rt_spin -l\n"
5823 + "\n"
5824 + "COMMON-OPTS = [-w] [-s SCALE]\n"
5825 + " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
5826 + " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
5827 + " [-i [start,end]:[start,end]...]\n"
5828 + "\n"
5829 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
5830 + "CRITICAL SECTION LENGTH is in milliseconds.\n");
5831 + exit(EXIT_FAILURE);
5832 +}
5833 +
5834 +/*
5835 + * returns the character that made processing stop, newline or EOF
5836 + */
5837 +static int skip_to_next_line(FILE *fstream)
5838 +{
5839 + int ch;
5840 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
5841 + return ch;
5842 +}
5843 +
5844 +static void skip_comments(FILE *fstream)
5845 +{
5846 + int ch;
5847 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
5848 + skip_to_next_line(fstream);
5849 + ungetc(ch, fstream);
5850 +}
5851 +
5852 +static void get_exec_times(const char *file, const int column,
5853 + int *num_jobs, double **exec_times)
5854 +{
5855 + FILE *fstream;
5856 + int cur_job, cur_col, ch;
5857 + *num_jobs = 0;
5858 +
5859 + fstream = fopen(file, "r");
5860 + if (!fstream)
5861 + bail_out("could not open execution time file");
5862 +
5863 + /* figure out the number of jobs */
5864 + do {
5865 + skip_comments(fstream);
5866 + ch = skip_to_next_line(fstream);
5867 + if (ch != EOF)
5868 + ++(*num_jobs);
5869 + } while (ch != EOF);
5870 +
5871 + if (-1 == fseek(fstream, 0L, SEEK_SET))
5872 + bail_out("rewinding file failed");
5873 +
5874 + /* allocate space for exec times */
5875 + *exec_times = calloc(*num_jobs, sizeof(*exec_times));
5876 + if (!*exec_times)
5877 + bail_out("couldn't allocate memory");
5878 +
5879 + for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
5880 +
5881 + skip_comments(fstream);
5882 +
5883 + for (cur_col = 1; cur_col < column; ++cur_col) {
5884 + /* discard input until we get to the column we want */
5885 + int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
5886 + }
5887 +
5888 + /* get the desired exec. time */
5889 + if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
5890 + fprintf(stderr, "invalid execution time near line %d\n",
5891 + cur_job);
5892 + exit(EXIT_FAILURE);
5893 + }
5894 +
5895 + skip_to_next_line(fstream);
5896 + }
5897 +
5898 + assert(cur_job == *num_jobs);
5899 + fclose(fstream);
5900 +}
5901 +
5902 +static char* progname;
5903 +
5904 +static int loop_once(int wss)
5905 +{
5906 + cacheline_t *mem;
5907 + int temp;
5908 +
5909 + //mem = random_method.walk_start(wss);
5910 + //temp = random_method.walk(mem, wss, 0);
5911 + mem = sequential_method.walk_start(wss);
5912 + temp = sequential_method.walk(mem, wss, 0);
5913 + dont_optimize_me = temp;
5914 +
5915 + return dont_optimize_me;
5916 +}
5917 +
5918 +static int loop_for(int wss, double exec_time, double emergency_exit)
5919 +{
5920 + double last_loop = 0, loop_start;
5921 + int tmp = 0;
5922 + int cur_loop = 0;
5923 +
5924 + double start = cputime();
5925 + double now = cputime();
5926 +
5927 + //while (now + last_loop < start + exec_time) {
5928 + while(cur_loop++ < loops) {
5929 + loop_start = now;
5930 + tmp = loop_once(wss);
5931 + now = cputime();
5932 + last_loop = now - loop_start;
5933 + if (emergency_exit && wctime() > emergency_exit) {
5934 + /* Oops --- this should only be possible if the execution time tracking
5935 + * is broken in the LITMUS^RT kernel. */
5936 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
5937 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
5938 + break;
5939 + }
5940 + }
5941 +
5942 + return tmp;
5943 +}
5944 +
5945 +
5946 +static void debug_delay_loop(int wss)
5947 +{
5948 + double start, end, delay;
5949 +
5950 + while (1) {
5951 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
5952 + start = wctime();
5953 + loop_for(wss, delay, 0);
5954 + end = wctime();
5955 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
5956 + delay,
5957 + end - start,
5958 + end - start - delay,
5959 + 100 * (end - start - delay) / delay);
5960 + }
5961 + }
5962 +}
5963 +
5964 +static int job(int wss, double exec_time, double program_end, int lock_od, double cs_length)
5965 +{
5966 + double chunk1, chunk2;
5967 +
5968 + if (wctime() > program_end)
5969 + return 0;
5970 + else {
5971 + if (lock_od >= 0) {
5972 + /* simulate critical section somewhere in the middle */
5973 + chunk1 = drand48() * (exec_time - cs_length);
5974 + chunk2 = exec_time - cs_length - chunk1;
5975 +
5976 + /* non-critical section */
5977 + loop_for(wss, chunk1, program_end + 1);
5978 +
5979 + /* critical section */
5980 + litmus_lock(lock_od);
5981 + loop_for(wss, cs_length, program_end + 1);
5982 + litmus_unlock(lock_od);
5983 +
5984 + /* non-critical section */
5985 + loop_for(wss, chunk2, program_end + 2);
5986 + } else {
5987 + register unsigned long t;
5988 + register unsigned long overhead = get_cyclecount();
5989 + overhead = get_cyclecount() - overhead;
5990 +
5991 + //gettimeofday(&tm1, NULL);
5992 + t = get_cyclecount();
5993 + loop_for(wss, exec_time, program_end + 1);
5994 + t = get_cyclecount() - t;
5995 + printf("%ld cycles (%ld overhead))\n", t, overhead);
5996 + //gettimeofday(&tm2, NULL);
5997 + //printf("%ld\n", ((tm2.tv_sec * 1000000 + tm2.tv_usec) - (tm1.tv_sec * 1000000 + tm1.tv_usec)));
5998 + }
5999 + sleep_next_period();
6000 + return 1;
6001 + }
6002 +}
6003 +
6004 +#define OPTSTR "p:c:wl:veo:f:s:q:X:L:Q:vh:k:"
6005 +int main(int argc, char** argv)
6006 +{
6007 + int ret, i;
6008 + lt_t wcet;
6009 + lt_t period;
6010 + double wcet_ms, period_ms;
6011 + unsigned int priority = LITMUS_NO_PRIORITY;
6012 + int migrate = 0;
6013 + int cluster = 0;
6014 + int opt;
6015 + int wait = 0;
6016 + int test_loop = 0;
6017 + int column = 1;
6018 + const char *file = NULL;
6019 + int want_enforcement = 0;
6020 + double duration = 0, start = 0;
6021 + double *exec_times = NULL;
6022 + double scale = 1.0;
6023 + task_class_t class = RT_CLASS_HARD;
6024 + int cur_job = 0, num_jobs = 0;
6025 + struct rt_task param;
6026 + int n_str, num_int = 0;
6027 + size_t arena_sz;
6028 + int verbose = 0;
6029 + unsigned int job_no;
6030 + int wss;
6031 +
6032 + /* locking */
6033 + int lock_od = -1;
6034 + int resource_id = 0;
6035 + const char *lock_namespace = "./rtspin-locks";
6036 + int protocol = -1;
6037 + double cs_length = 1; /* millisecond */
6038 +
6039 + progname = argv[0];
6040 +
6041 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
6042 + switch (opt) {
6043 + case 'w':
6044 + wait = 1;
6045 + break;
6046 + case 'p':
6047 + cluster = atoi(optarg);
6048 + migrate = 1;
6049 + break;
6050 + case 'q':
6051 + priority = atoi(optarg);
6052 + if (!litmus_is_valid_fixed_prio(priority))
6053 + usage("Invalid priority.");
6054 + break;
6055 + case 'c':
6056 + class = str2class(optarg);
6057 + if (class == -1)
6058 + usage("Unknown task class.");
6059 + break;
6060 + case 'e':
6061 + want_enforcement = 1;
6062 + break;
6063 + case 'l':
6064 + loops = atoi(optarg);
6065 + break;
6066 + case 'k':
6067 + wss = atoi(optarg);
6068 + break;
6069 + case 'o':
6070 + column = atoi(optarg);
6071 + break;
6072 + case 'f':
6073 + file = optarg;
6074 + break;
6075 + case 's':
6076 + scale = atof(optarg);
6077 + break;
6078 + case 'X':
6079 + protocol = lock_protocol_for_name(optarg);
6080 + if (protocol < 0)
6081 + usage("Unknown locking protocol specified.");
6082 + break;
6083 + case 'L':
6084 + cs_length = atof(optarg);
6085 + if (cs_length <= 0)
6086 + usage("Invalid critical section length.");
6087 + break;
6088 + case 'Q':
6089 + resource_id = atoi(optarg);
6090 + if (resource_id <= 0 && strcmp(optarg, "0"))
6091 + usage("Invalid resource ID.");
6092 + break;
6093 + case 'v':
6094 + verbose = 1;
6095 + break;
6096 + case ':':
6097 + usage("Argument missing.");
6098 + break;
6099 + case '?':
6100 + default:
6101 + usage("Bad argument.");
6102 + break;
6103 + }
6104 + }
6105 +
6106 + if (test_loop) {
6107 + debug_delay_loop(wss);
6108 + return 0;
6109 + }
6110 +
6111 + srand(getpid());
6112 +
6113 + if (file) {
6114 + get_exec_times(file, column, &num_jobs, &exec_times);
6115 +
6116 + if (argc - optind < 2)
6117 + usage("Arguments missing.");
6118 +
6119 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
6120 + /* convert the execution time to seconds */
6121 + duration += exec_times[cur_job] * 0.001;
6122 + }
6123 + } else {
6124 + /*
6125 + * if we're not reading from the CSV file, then we need
6126 + * three parameters
6127 + */
6128 + if (argc - optind < 3)
6129 + usage("Arguments missing.");
6130 + }
6131 +
6132 + wcet_ms = atof(argv[optind + 0]);
6133 + period_ms = atof(argv[optind + 1]);
6134 +
6135 + wcet = ms2ns(wcet_ms);
6136 + period = ms2ns(period_ms);
6137 + if (wcet <= 0)
6138 + usage("The worst-case execution time must be a "
6139 + "positive number.");
6140 + if (period <= 0)
6141 + usage("The period must be a positive number.");
6142 + if (!file && wcet > period) {
6143 + usage("The worst-case execution time must not "
6144 + "exceed the period.");
6145 + }
6146 +
6147 + if (!file)
6148 + duration = atof(argv[optind + 2]);
6149 + else if (file && num_jobs > 1)
6150 + duration += period_ms * 0.001 * (num_jobs - 1);
6151 +
6152 + if (migrate) {
6153 + ret = be_migrate_to_domain(cluster);
6154 + if (ret < 0)
6155 + bail_out("could not migrate to target partition or cluster.");
6156 + }
6157 +
6158 + init_rt_task_param(¶m);
6159 + param.exec_cost = wcet;
6160 + param.period = period;
6161 + param.priority = priority;
6162 + param.cls = class;
6163 + param.budget_policy = (want_enforcement) ?
6164 + PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
6165 + if (migrate) {
6166 + param.cpu = domain_to_first_cpu(cluster);
6167 + }
6168 + ret = set_rt_task_param(gettid(), ¶m);
6169 + if (ret < 0)
6170 + bail_out("could not setup rt task params");
6171 +
6172 +
6173 + arena_sz = wss*1024;
6174 + arena = alloc_arena(arena_sz, 0, 0);
6175 + init_arena(arena, arena_sz);
6176 +
6177 + lock_memory();
6178 +
6179 + ret = init_litmus();
6180 + if (ret != 0)
6181 + bail_out("init_litmus() failed\n");
6182 +
6183 + start = wctime();
6184 + ret = task_mode(LITMUS_RT_TASK);
6185 + if (ret != 0)
6186 + bail_out("could not become RT task");
6187 +
6188 + if (protocol >= 0) {
6189 + lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
6190 + if (lock_od < 0) {
6191 + perror("litmus_open_lock");
6192 + usage("Could not open lock.");
6193 + }
6194 + }
6195 +
6196 +
6197 + if (wait) {
6198 + ret = wait_for_ts_release();
6199 + if (ret != 0)
6200 + bail_out("wait_for_ts_release()");
6201 + start = wctime();
6202 + }
6203 +
6204 + if (file) {
6205 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
6206 + job(wss, exec_times[cur_job] * 0.001 * scale,
6207 + start + duration,
6208 + lock_od, cs_length * 0.001);
6209 + }
6210 + } else {
6211 + do {
6212 + if (verbose) {
6213 + get_job_no(&job_no);
6214 + printf("rtspin/%d:%u @ %.4fms\n", gettid(),
6215 + job_no, (wctime() - start) * 1000);
6216 + }
6217 + } while (job(wss, wcet_ms * 0.001 * scale, start + duration,
6218 + lock_od, cs_length * 0.001));
6219 + }
6220 +
6221 + ret = task_mode(BACKGROUND_TASK);
6222 + if (ret != 0)
6223 + bail_out("could not become regular task (huh?)");
6224 +
6225 + if (file)
6226 + free(exec_times);
6227 +
6228 + dealloc_arena(arena, arena_sz);
6229 + return 0;
6230 +}
6231 diff --git a/bin/rtspin.c b/bin/rtspin.c
6232 index ea7f192..fd57c45 100644
6233 --- a/bin/rtspin.c
6234 +++ b/bin/rtspin.c
6235 @@ -6,7 +6,7 @@
6236 #include <time.h>
6237 #include <string.h>
6238 #include <assert.h>
6239 -
6240 +#include <limits.h>
6241
6242 #include "litmus.h"
6243 #include "common.h"
6244 @@ -191,7 +191,7 @@ int main(int argc, char** argv)
6245 lt_t wcet;
6246 lt_t period;
6247 double wcet_ms, period_ms;
6248 - unsigned int priority = LITMUS_LOWEST_PRIORITY;
6249 + unsigned int priority = LITMUS_NO_PRIORITY;
6250 int migrate = 0;
6251 int cluster = 0;
6252 int reservation = -1;
6253 diff --git a/include/cache_common.h b/include/cache_common.h
6254 new file mode 100644
6255 index 0000000..7e9646c
6256 --- /dev/null
6257 +++ b/include/cache_common.h
6258 @@ -0,0 +1,213 @@
6259 +#ifndef __CACHE_COMMON_H__
6260 +#define __CACHE_COMMON_H__
6261 +
6262 +#include <stdio.h>
6263 +#include <stdlib.h>
6264 +#include <time.h>
6265 +#include <string.h>
6266 +#include <assert.h>
6267 +
6268 +#include <signal.h>
6269 +#include <sys/mman.h>
6270 +#include <sys/types.h>
6271 +#include <sys/stat.h>
6272 +#include <fcntl.h>
6273 +#include <unistd.h>
6274 +
6275 +#include <sys/io.h>
6276 +#include <sys/utsname.h>
6277 +
6278 +#include <sched.h>
6279 +#include <sys/time.h>
6280 +#include <sys/resource.h>
6281 +
6282 +#include "litmus.h"
6283 +#include "asm/cycles.h"
6284 +
6285 +#if defined(__i386__) || defined(__x86_64__)
6286 +#include "asm/irq.h"
6287 +#endif
6288 +
6289 +
6290 +#define UNCACHE_DEV "/dev/litmus/uncache"
6291 +
6292 +static void die(char *error)
6293 +{
6294 + fprintf(stderr, "Error: %s (errno: %m)\n",
6295 + error);
6296 + exit(1);
6297 +}
6298 +
6299 +static int migrate_to(int cpu)
6300 +{
6301 + int ret;
6302 +
6303 + static __thread cpu_set_t* cpu_set = NULL;
6304 + static __thread size_t cpu_set_sz;
6305 + static __thread int num_cpus;
6306 + if(!cpu_set)
6307 + {
6308 + num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
6309 + cpu_set = CPU_ALLOC(num_cpus);
6310 + cpu_set_sz = CPU_ALLOC_SIZE(num_cpus);
6311 + }
6312 +
6313 + CPU_ZERO_S(cpu_set_sz, cpu_set);
6314 + CPU_SET_S(cpu, cpu_set_sz, cpu_set);
6315 + ret = sched_setaffinity(0 /* self */, cpu_set_sz, cpu_set);
6316 + return ret;
6317 +}
6318 +
6319 +static int check_migrations(int num_cpus)
6320 +{
6321 + int cpu, err;
6322 +
6323 + for (cpu = 0; cpu < num_cpus; cpu++) {
6324 + err = migrate_to(cpu);
6325 + if (err != 0) {
6326 + fprintf(stderr, "Migration to CPU %d failed: %m.\n",
6327 + cpu + 1);
6328 + return 1;
6329 + }
6330 + }
6331 + return 0;
6332 +}
6333 +
6334 +static int become_posix_realtime_task(int prio)
6335 +{
6336 + struct sched_param param;
6337 + memset(¶m, 0, sizeof(param));
6338 + param.sched_priority = prio;
6339 + return sched_setscheduler(0 /* self */, SCHED_FIFO, ¶m);
6340 +}
6341 +
6342 +static int renice(int nice_val)
6343 +{
6344 + return setpriority(PRIO_PROCESS, 0 /* self */, nice_val);
6345 +}
6346 +
6347 +static int lock_memory(void)
6348 +{
6349 + return mlockall(MCL_CURRENT | MCL_FUTURE);
6350 +}
6351 +
6352 +/* define CACHELINE_SIZE if not provided by compiler args */
6353 +#ifndef CACHELINE_SIZE
6354 +#if defined(__i386__) || defined(__x86_64__)
6355 +/* recent intel cpus */
6356 +#define CACHELINE_SIZE 64
6357 +#elif defined(__arm__)
6358 +/* at least with Cortex-A9 cpus ("8 words") */
6359 +#define CACHELINE_SIZE 32
6360 +#else
6361 +#error "Could not determine cacheline size!"
6362 +#endif
6363 +#endif
6364 +
6365 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
6366 +typedef struct cacheline
6367 +{
6368 + int line[INTS_IN_CACHELINE];
6369 +} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
6370 +
6371 +static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages)
6372 +{
6373 + int flags = MAP_PRIVATE | MAP_POPULATE;
6374 + cacheline_t* arena = NULL;
6375 + int fd;
6376 +
6377 + if(use_huge_pages)
6378 + flags |= MAP_HUGETLB;
6379 +
6380 + if(use_uncache_pages) {
6381 + fd = open(UNCACHE_DEV, O_RDWR);
6382 + if (fd == -1)
6383 + die("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
6384 + }
6385 + else {
6386 + fd = -1;
6387 + flags |= MAP_ANONYMOUS;
6388 + }
6389 +
6390 + arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
6391 +
6392 + if(use_uncache_pages)
6393 + close(fd);
6394 +
6395 + assert(arena);
6396 +
6397 + return arena;
6398 +}
6399 +
6400 +static void dealloc_arena(cacheline_t* arena, size_t size)
6401 +{
6402 + int ret = munmap((void*)arena, size);
6403 + if(ret != 0)
6404 + die("munmap() error");
6405 +}
6406 +
6407 +static int randrange(int min, int max)
6408 +{
6409 + /* generate a random number on the range [min, max) w/o skew */
6410 + int limit = max - min;
6411 + int devisor = RAND_MAX/limit;
6412 + int retval;
6413 +
6414 + do {
6415 + retval = rand() / devisor;
6416 + } while(retval == limit);
6417 + retval += min;
6418 +
6419 + return retval;
6420 +}
6421 +
6422 +static void init_arena(cacheline_t* arena, size_t size)
6423 +{
6424 + int i;
6425 + size_t num_arena_elem = size / sizeof(cacheline_t);
6426 +
6427 + /* Generate a cycle among the cache lines using Sattolo's algorithm.
6428 + Every int in the cache line points to the same cache line.
6429 + Note: Sequential walk doesn't care about these values. */
6430 + for (i = 0; i < num_arena_elem; i++) {
6431 + int j;
6432 + for(j = 0; j < INTS_IN_CACHELINE; ++j)
6433 + arena[i].line[j] = i;
6434 + }
6435 + while(1 < i--) {
6436 + int j = randrange(0, i);
6437 + cacheline_t temp = arena[j];
6438 + arena[j] = arena[i];
6439 + arena[i] = temp;
6440 + }
6441 +}
6442 +
6443 +static void sleep_us(int microseconds)
6444 +{
6445 + struct timespec delay;
6446 +
6447 + delay.tv_sec = 0;
6448 + delay.tv_nsec = microseconds * 1000;
6449 + if (nanosleep(&delay, NULL) != 0)
6450 + die("sleep failed");
6451 +}
6452 +
6453 +static int completed(int nSamples, int* history, int nCategories)
6454 +{
6455 + int i;
6456 + for(i = 0; i < nCategories; ++i)
6457 + if(history[i] < nSamples)
6458 + return 0;
6459 + return 1;
6460 +}
6461 +
6462 +inline unsigned long get_cyclecount (void)
6463 +{
6464 + unsigned long value;
6465 + // Read CCNT Register
6466 + asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
6467 + return value;
6468 +}
6469 +
6470 +
6471 +#endif
6472 \ No newline at end of file
6473 diff --git a/include/litmus.h b/include/litmus.h
6474 index b90a83d..b8e32a4 100644
6475 --- a/include/litmus.h
6476 +++ b/include/litmus.h
6477 @@ -424,6 +424,8 @@ int reservation_destroy(unsigned int reservation_id, int cpu);
6478
6479 int set_mc2_task_param(pid_t pid, struct mc2_task* param);
6480
6481 +int set_page_color(int cpu);
6482 +
6483 #ifdef __cplusplus
6484 }
6485 #endif
6486 diff --git a/mc2spin b/mc2spin
6487 deleted file mode 100755
6488 index 00b20c0223e92547cde52d2546b7ddbcb349c1a1..0000000000000000000000000000000000000000
6489 GIT binary patch
6490 literal 0
6491 HcmV?d00001
6492
6493 literal 102692
6494 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
7318 RC~&S^73oPH3wvb1{udehT~z=8
7319
7320 diff --git a/src/syscalls.c b/src/syscalls.c
7321 index b07d135..a58f55b 100644
7322 --- a/src/syscalls.c
7323 +++ b/src/syscalls.c
7324 @@ -100,4 +100,9 @@ int reservation_destroy(unsigned int reservation_id, int cpu)
7325 int set_mc2_task_param(pid_t pid, struct mc2_task *param)
7326 {
7327 return syscall(__NR_set_mc2_task_param, pid, param);
7328 -}
7329 \ No newline at end of file
7330 +}
7331 +
7332 +int set_page_color(int cpu)
7333 +{
7334 + return syscall(__NR_set_page_color, cpu);
7335 +}
7336 --
7337 1.9.1
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.