aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNamhoon Kim <namhoonk@cs.unc.edu>2016-04-30 17:45:01 -0400
committerNamhoon Kim <namhoonk@cs.unc.edu>2016-04-30 17:45:01 -0400
commit03e9cedc1879ffacc8f28a6fd38f0b73888b2826 (patch)
tree276bde2e69d557201bea4c9707cc03349a892511
parentcc61f79e3a7f5b28c8731d0e041dd57cdcd812ca (diff)
RTSS16 microbench
-rw-r--r--Makefile35
-rw-r--r--bin/mc2bench.c503
-rw-r--r--bin/mc2shm.c502
-rw-r--r--bin/mtdag.c (renamed from bin/mttest.c)125
-rw-r--r--bin/test1.c453
-rw-r--r--include/cache_common.h213
-rw-r--r--include/color_shm.h11
-rw-r--r--include/litmus.h12
-rw-r--r--src/color_shm.c40
-rw-r--r--src/kernel_iface.c56
-rw-r--r--src/syscalls.c4
11 files changed, 1865 insertions, 89 deletions
diff --git a/Makefile b/Makefile
index 5ceaedf..b4df5da 100644
--- a/Makefile
+++ b/Makefile
@@ -73,7 +73,9 @@ AR := ${CROSS_COMPILE}${AR}
73 73
74all = lib ${rt-apps} 74all = lib ${rt-apps}
75rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ 75rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
76 base_mt_task uncache runtests resctrl mc2spin test1 mttest 76 base_mt_task uncache runtests resctrl mc2spin test1 \
77 mc2thrash mc2shm mc2thrash1 mc2thrash2 mc2thrash3 mc2bench\
78 mc2memthrash1 mc2memthrash2 mc2memthrash3 mtdag
77 79
78.PHONY: all lib clean dump-config TAGS tags cscope help doc 80.PHONY: all lib clean dump-config TAGS tags cscope help doc
79 81
@@ -252,8 +254,35 @@ lib-memthrash = -lrt
252obj-test1 = test1.o common.o 254obj-test1 = test1.o common.o
253lib-test1 = -lrt -static 255lib-test1 = -lrt -static
254 256
255obj-mttest = mttest.o 257obj-mc2thrash = mc2thrash.o common.o
256ldf-mttest = -pthread 258lib-mc2thrash = -lrt -static
259
260obj-mc2thrash1 = mc2thrash.o common.o
261lib-mc2thrash1 = -lrt -static
262
263obj-mc2thrash2 = mc2thrash.o common.o
264lib-mc2thrash2 = -lrt -static
265
266obj-mc2thrash3 = mc2thrash.o common.o
267lib-mc2thrash3 = -lrt -static
268
269obj-mc2shm = mc2shm.o common.o
270lib-mc2shm = -lrt -static
271
272obj-mc2memthrash1 = mc2memthrash.o common.o
273lib-mc2memthrash1 = -lrt -static
274
275obj-mc2memthrash2 = mc2memthrash.o common.o
276lib-mc2memthrash2 = -lrt -static
277
278obj-mc2memthrash3 = mc2memthrash.o common.o
279lib-mc2memthrash3 = -lrt -static
280
281obj-mtdag = mtdag.o common.o
282ldf-mtdag = -lrt -pthread -static
283
284obj-mc2bench = mc2bench.o common.o
285lib-mc2bench = -lrt -static
257# ############################################################################## 286# ##############################################################################
258# Build everything that depends on liblitmus. 287# Build everything that depends on liblitmus.
259 288
diff --git a/bin/mc2bench.c b/bin/mc2bench.c
new file mode 100644
index 0000000..dfb4f15
--- /dev/null
+++ b/bin/mc2bench.c
@@ -0,0 +1,503 @@
1#include <sys/time.h>
2#include <sys/mman.h>
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <time.h>
8#include <string.h>
9#include <assert.h>
10#include <limits.h>
11#include <fcntl.h>
12
13#include "litmus.h"
14#include "common.h"
15#include "color_shm.h"
16
17#define PAGE_SIZE (4096)
18//#define CACHELINE_SIZE 32
19//#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
20//#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
21#define INTS_IN_1KB (1024 / sizeof(int))
22
23//typedef struct cacheline
24//{
25// int line[INTS_IN_CACHELINE];
26//} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
27
28static int loops = 100000;
29static cacheline_t* arena = NULL;
30static cacheline_t* local_buf = NULL;
31
32struct timeval t1,t2;
33
34lt_t exectime[100000];
35
36inline unsigned long get_cyclecount (void)
37{
38 unsigned long value;
39 // Read CCNT Register
40 asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
41 return value;
42}
43
44#define UNCACHE_DEV "/dev/litmus/uncache"
45
46static cacheline_t* alloc_shm(int cs, size_t size, int use_huge_pages, int use_uncache_pages)
47{
48 struct color_ioctl_cmd shm_info;
49 struct color_ioctl_offset shm_offset;
50 cacheline_t* arena = NULL;
51
52
53 shm_info.color = 0x0000ffff;
54
55 if (cs == 1 || cs == 2)
56 shm_info.bank = 0x00000020; // hi crit. bank
57 else if (cs == 3)
58 shm_info.bank = 0x00000040; // levelC
59
60 shm_offset.offset = 0;
61 shm_offset.lock = 1;
62
63 arena = color_mmap(size, shm_info, shm_offset);
64 if (arena == MAP_FAILED) {
65 printf("mmap failed.\n");
66 return NULL;
67 }
68
69 mlockall(MCL_CURRENT | MCL_FUTURE);
70 /* finish allocation */
71
72 assert(arena);
73
74 return arena;
75}
76
77static cacheline_t* alloc_local(size_t size, int use_huge_pages, int use_uncache_pages)
78{
79 int flags = MAP_PRIVATE | MAP_POPULATE;
80 cacheline_t* arena = NULL;
81 int fd;
82
83 if(use_huge_pages)
84 flags |= MAP_HUGETLB;
85
86 if(use_uncache_pages) {
87 fd = open(UNCACHE_DEV, O_RDWR|O_SYNC);
88 if (fd == -1)
89 bail_out("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
90 }
91 else {
92 fd = -1;
93 flags |= MAP_ANONYMOUS;
94 }
95
96 arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
97
98 if(use_uncache_pages)
99 close(fd);
100
101 assert(arena);
102
103 return arena;
104}
105
106static void dealloc_arena(cacheline_t* arena, size_t size)
107{
108 int ret = munmap((void*)arena, size);
109 if(ret != 0)
110 bail_out("munmap() error");
111}
112
113static int randrange(int min, int max)
114{
115 /* generate a random number on the range [min, max) w/o skew */
116 int limit = max - min;
117 int devisor = RAND_MAX/limit;
118 int retval;
119
120 do {
121 retval = rand() / devisor;
122 } while(retval == limit);
123 retval += min;
124
125 return retval;
126}
127
128static void init_arena(cacheline_t* arena, size_t size)
129{
130 int i;
131 size_t num_arena_elem = size / sizeof(cacheline_t);
132
133 /* Generate a cycle among the cache lines using Sattolo's algorithm.
134 Every int in the cache line points to the same cache line.
135 Note: Sequential walk doesn't care about these values. */
136 for (i = 0; i < num_arena_elem; i++) {
137 int j;
138 for(j = 0; j < INTS_IN_CACHELINE; ++j)
139 arena[i].line[j] = i;
140 }
141 while(1 < i--) {
142 int j = randrange(0, i);
143 cacheline_t temp = arena[j];
144 arena[j] = arena[i];
145 arena[i] = temp;
146 }
147}
148
149/* Random walk around the arena in cacheline-sized chunks.
150 Cacheline-sized chucks ensures the same utilization of each
151 hit line as sequential read. (Otherwise, our utilization
152 would only be 1/INTS_IN_CACHELINE.) */
153static int random_walk(cacheline_t *mem, int wss, int write_cycle)
154{
155 /* a random cycle among the cache lines was set up by init_arena(). */
156 int sum, i, next, j;
157
158 int numlines = wss * CACHELINES_IN_1KB;
159
160 sum = 0;
161
162 /* contents of arena is structured s.t. offsets are all
163 w.r.t. to start of arena, so compute the initial offset */
164 next = mem - arena;
165
166 if (write_cycle == 0) {
167 for (i = 0; i < numlines; i++) {
168 for (j = 0; j < INTS_IN_CACHELINE; j++) {
169 /* every element in the cacheline has the same value */
170 //next = arena[next].line[j];
171 local_buf[next].line[j] = arena[next].line[j];
172 //sum += next;
173 //local_buf[next].line[j] = next;
174 }
175 }
176 }
177
178 else {
179 int w, which_line;
180 for (i = 0, w = 0; i < numlines; i++) {
181 for (j = 0; j < INTS_IN_CACHELINE; j++) {
182 which_line = next;
183 next = local_buf[next].line[j];
184 ((volatile cacheline_t*)arena)[which_line].line[j] = next;
185 //sum += next;
186 }
187 }
188 }
189 return sum;
190}
191
192static cacheline_t* random_start(int wss)
193{
194 return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
195}
196
197static int sequential_walk(cacheline_t *mem, int wss, int write_cycle)
198{
199 int sum = 0, i, j;
200 //int* mem = (int*)_mem; /* treat as raw buffer of ints */
201 int num_ints = wss * CACHELINES_IN_1KB;
202
203 if (write_cycle > 0) {
204 for (i = 0; i < num_ints; i++) {
205 //if (i % write_cycle == (write_cycle - 1)) {
206 //mem[i]++;
207 for (j = 0; j < INTS_IN_CACHELINE; j++) {
208 //sum += local_buf[i].line[j];
209 mem[i].line[j] = local_buf[i].line[j];;
210 }
211 //}
212 //else {
213 // sum += mem[i];
214 //}
215 }
216 } else {
217 /* sequential access, pure read */
218 for (i = 0; i < num_ints; i++) {
219 for (j = 0; j < INTS_IN_CACHELINE; j++) {
220 //sum += mem[i];
221 local_buf[i].line[j] = mem[i].line[j];
222 //sum += mem[i];
223 }
224 }
225 }
226 return sum;
227}
228
229static cacheline_t* sequential_start(int wss)
230{
231 return arena;
232/* static int pos = 0;
233
234 int num_cachelines = wss * CACHELINES_IN_1KB;
235 size_t num_arena_elem = wss * 1024 / sizeof(cacheline_t);
236 cacheline_t *mem;
237*/
238
239 /* Don't allow re-use between allocations.
240 * At most half of the arena may be used
241 * at any one time.
242 */
243/* if (num_cachelines * 2 > num_arena_elem)
244 bail_out("static memory arena too small");
245
246 if (pos + num_cachelines > num_arena_elem) {
247 mem = arena;
248 pos = num_cachelines;
249 } else {
250 mem = arena + pos;
251 pos += num_cachelines;
252 }
253
254 return mem;*/
255}
256
257static volatile int dont_optimize_me = 0;
258
259static void usage(char *error) {
260 fprintf(stderr, "Error: %s\n", error);
261 fprintf(stderr,
262 "Usage:\n"
263 " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
264 " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
265 " rt_spin -l\n"
266 "\n"
267 "COMMON-OPTS = [-w] [-s SCALE]\n"
268 " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
269 " [-k WSS] [-l LOOPS] [-b BUDGET]\n"
270 "\n"
271 "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
272 exit(EXIT_FAILURE);
273}
274
275static int loop_once(int cs, int wss, unsigned int iter)
276{
277 //cacheline_t *mem;
278 //int temp;
279
280 //mem = random_start(wss);
281 //temp = random_walk(mem, wss, 1);
282
283 //mem = sequential_start(wss);
284 //temp = sequential_walk(arena, wss, 1);
285 run_bench(cs, wss, arena, local_buf, &exectime[iter]);
286 dont_optimize_me = (int)exectime[iter];
287
288 return dont_optimize_me;
289}
290
291static int job(int cs, int wss, double exec_time, double program_end)
292{
293 if (wctime() > program_end)
294 return 0;
295 else {
296 register unsigned long t;
297 register unsigned int iter = 0;
298 //t = get_cyclecount();
299 //gettimeofday(&t1, NULL);
300 while(iter < loops) {
301 loop_once(cs, wss, iter++);
302 }
303 //gettimeofday(&t2, NULL);
304 //printf("%ld cycles\n", get_cyclecount() - t);
305 //printf("%ld\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec)));
306 sleep_next_period();
307 return 1;
308 }
309}
310
311#define OPTSTR "p:wl:m:i:b:k:c:"
312int main(int argc, char** argv)
313{
314 int ret, i;
315 lt_t wcet, period, budget;
316 double wcet_ms, period_ms, budget_ms;
317 unsigned int priority = LITMUS_NO_PRIORITY;
318 int migrate = 0;
319 int cluster = 0;
320 int opt;
321 int wait = 0;
322 double duration = 0, start = 0;
323 struct rt_task param;
324 struct mc2_task mc2_param;
325 struct reservation_config config;
326 int res_type = PERIODIC_POLLING;
327 size_t arena_sz;
328 int wss, cs;
329
330 /* default for reservation */
331 config.id = 0;
332 config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
333 config.cpu = -1;
334
335 mc2_param.crit = CRIT_LEVEL_C;
336
337 budget_ms = 1000;
338
339 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
340 switch (opt) {
341 case 'w':
342 wait = 1;
343 break;
344 case 'p':
345 cluster = atoi(optarg);
346 migrate = 1;
347 config.cpu = cluster;
348 break;
349 case 'l':
350 loops = atoi(optarg);
351 break;
352 case 'k':
353 wss = atoi(optarg);
354 break;
355 case 'm':
356 mc2_param.crit = atoi(optarg);
357 if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
358 res_type = PERIODIC_POLLING;
359 }
360 else
361 usage("Invalid criticality level.");
362 break;
363 case 'b':
364 budget_ms = atof(optarg);
365 break;
366 case 'i':
367 config.priority = atoi(optarg);
368 break;
369 case 'c':
370 cs = atoi(optarg);
371 break;
372 case ':':
373 usage("Argument missing.");
374 break;
375 case '?':
376 default:
377 usage("Bad argument.");
378 break;
379 }
380 }
381 srand(getpid());
382
383 /*
384 * We need three parameters
385 */
386 if (argc - optind < 3)
387 usage("Arguments missing.");
388
389 wcet_ms = atof(argv[optind + 0]);
390 period_ms = atof(argv[optind + 1]);
391
392 wcet = ms2ns(wcet_ms);
393 period = ms2ns(period_ms);
394 budget = ms2ns(budget_ms);
395 if (wcet <= 0)
396 usage("The worst-case execution time must be a "
397 "positive number.");
398 if (period <= 0)
399 usage("The period must be a positive number.");
400 if (wcet > period) {
401 usage("The worst-case execution time must not "
402 "exceed the period.");
403 }
404
405 duration = atof(argv[optind + 2]);
406
407 if (migrate) {
408 ret = be_migrate_to_domain(cluster);
409 if (ret < 0)
410 bail_out("could not migrate to target partition or cluster.");
411 }
412
413 /* reservation config */
414 config.id = gettid();
415 config.polling_params.budget = budget;
416 config.polling_params.period = period;
417 config.polling_params.offset = 0;
418 config.polling_params.relative_deadline = 0;
419
420 if (config.polling_params.budget > config.polling_params.period) {
421 usage("The budget must not exceed the period.");
422 }
423
424 /* create a reservation */
425 ret = reservation_create(res_type, &config);
426 if (ret < 0) {
427 bail_out("failed to create reservation.");
428 }
429
430 init_rt_task_param(&param);
431 param.exec_cost = wcet;
432 param.period = period;
433 param.priority = priority;
434 param.cls = RT_CLASS_HARD;
435 param.release_policy = TASK_PERIODIC;
436 param.budget_policy = NO_ENFORCEMENT;
437 if (migrate) {
438 param.cpu = gettid();
439 }
440 ret = set_rt_task_param(gettid(), &param);
441 if (ret < 0)
442 bail_out("could not setup rt task params");
443
444 mc2_param.res_id = gettid();
445 ret = set_mc2_task_param(gettid(), &mc2_param);
446 if (ret < 0)
447 bail_out("could not setup mc2 task params");
448
449
450 arena_sz = wss*1024;
451
452 arena = alloc_shm(cs, arena_sz, 0, 0);
453 if (!arena)
454 bail_out("alloc_shm failed.\n");
455 init_arena(arena, arena_sz);
456
457 local_buf = alloc_local(arena_sz, 0, 0);
458 if (!local_buf)
459 bail_out("alloc_local failed.\n");
460 init_arena(local_buf, arena_sz);
461
462 ret = init_litmus();
463 if (ret != 0)
464 bail_out("init_litmus() failed\n");
465
466 start = wctime();
467 ret = task_mode(LITMUS_RT_TASK);
468 if (ret != 0)
469 bail_out("could not become RT task");
470
471 if (mc2_param.crit == CRIT_LEVEL_C)
472 set_page_color(-1);
473 else
474 set_page_color(config.cpu);
475
476 mlockall(MCL_CURRENT | MCL_FUTURE);
477// init_arena(local_buf, arena_sz);
478// test_call(1);
479// init_arena(arena, arena_sz);
480// test_call(2);
481
482 if (wait) {
483 ret = wait_for_ts_release();
484 if (ret != 0)
485 bail_out("wait_for_ts_release()");
486 start = wctime();
487 }
488
489 //while (job(wss, wcet_ms * 0.001, start + duration)) {};
490 job(cs, wss, wcet_ms * 0.001, start + duration);
491
492 ret = task_mode(BACKGROUND_TASK);
493 if (ret != 0)
494 bail_out("could not become regular task (huh?)");
495
496 reservation_destroy(gettid(), config.cpu);
497 dealloc_arena(arena, arena_sz);
498 dealloc_arena(local_buf, arena_sz);
499 printf("%s finished.\n", argv[0]);
500 for (i = 0; i<loops; i++)
501 printf("%llu\n", exectime[i]);
502 return 0;
503}
diff --git a/bin/mc2shm.c b/bin/mc2shm.c
new file mode 100644
index 0000000..4cc974a
--- /dev/null
+++ b/bin/mc2shm.c
@@ -0,0 +1,502 @@
1#include <sys/time.h>
2#include <sys/mman.h>
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <time.h>
8#include <string.h>
9#include <assert.h>
10#include <limits.h>
11#include <fcntl.h>
12
13#include "litmus.h"
14#include "common.h"
15#include "color_shm.h"
16
17#define PAGE_SIZE (4096)
18#define CACHELINE_SIZE 32
19#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
20#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
21#define INTS_IN_1KB (1024 / sizeof(int))
22#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
23
24//typedef struct cacheline
25//{
26// int line[INTS_IN_CACHELINE];
27//} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
28
29static int loops = 10;
30static cacheline_t* arena = NULL;
31static cacheline_t* local_buf = NULL;
32
33struct timeval t1,t2;
34
35inline unsigned long get_cyclecount (void)
36{
37 unsigned long value;
38 // Read CCNT Register
39 asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
40 return value;
41}
42
43#define UNCACHE_DEV "/dev/litmus/uncache"
44
45static cacheline_t* alloc_shm(size_t size, int use_huge_pages, int use_uncache_pages)
46{
47 int ret, fd;
48 struct color_ioctl_cmd shm_info;
49 cacheline_t* arena = NULL;
50
51 /* allocate shm */
52 fd = open("/dev/litmus/color_shm", O_RDWR);
53 if (fd < 0) {
54 printf("Device open error.\n");
55 return NULL;
56 }
57
58 shm_info.color = 0x00000f00;
59 //shm_info.bank = 0x00000020; // hi crit. bank
60 shm_info.bank = 0x00000040; // levelC
61
62 ret = ioctl(fd, SET_COLOR_SHM_CMD, &shm_info);
63 if (ret < 0) {
64 printf("ioctl failed.\n");
65 return NULL;
66 }
67
68 arena = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
69 if (arena == MAP_FAILED) {
70 printf("mmap failed.\n");
71 return NULL;
72 }
73 close(fd);
74
75 mlockall(MCL_CURRENT | MCL_FUTURE);
76 /* finish allocation */
77
78 assert(arena);
79
80 return arena;
81}
82
83static cacheline_t* alloc_local(size_t size, int use_huge_pages, int use_uncache_pages)
84{
85 int flags = MAP_PRIVATE | MAP_POPULATE;
86 cacheline_t* arena = NULL;
87 int fd;
88
89 if(use_huge_pages)
90 flags |= MAP_HUGETLB;
91
92 if(use_uncache_pages) {
93 fd = open(UNCACHE_DEV, O_RDWR|O_SYNC);
94 if (fd == -1)
95 bail_out("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
96 }
97 else {
98 fd = -1;
99 flags |= MAP_ANONYMOUS;
100 }
101
102 arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
103
104 if(use_uncache_pages)
105 close(fd);
106
107 assert(arena);
108
109 return arena;
110}
111
112static void dealloc_arena(cacheline_t* arena, size_t size)
113{
114 int ret = munmap((void*)arena, size);
115 if(ret != 0)
116 bail_out("munmap() error");
117}
118
119static int randrange(int min, int max)
120{
121 /* generate a random number on the range [min, max) w/o skew */
122 int limit = max - min;
123 int devisor = RAND_MAX/limit;
124 int retval;
125
126 do {
127 retval = rand() / devisor;
128 } while(retval == limit);
129 retval += min;
130
131 return retval;
132}
133
134static void init_arena(cacheline_t* arena, size_t size)
135{
136 int i;
137 size_t num_arena_elem = size / sizeof(cacheline_t);
138
139 /* Generate a cycle among the cache lines using Sattolo's algorithm.
140 Every int in the cache line points to the same cache line.
141 Note: Sequential walk doesn't care about these values. */
142 for (i = 0; i < num_arena_elem; i++) {
143 int j;
144 for(j = 0; j < INTS_IN_CACHELINE; ++j)
145 arena[i].line[j] = i;
146 }
147 while(1 < i--) {
148 int j = randrange(0, i);
149 cacheline_t temp = arena[j];
150 arena[j] = arena[i];
151 arena[i] = temp;
152 }
153}
154
155/* Random walk around the arena in cacheline-sized chunks.
156 Cacheline-sized chucks ensures the same utilization of each
157 hit line as sequential read. (Otherwise, our utilization
158 would only be 1/INTS_IN_CACHELINE.) */
159static int random_walk(cacheline_t *mem, int wss, int write_cycle)
160{
161 /* a random cycle among the cache lines was set up by init_arena(). */
162 int sum, i, next, j;
163
164 int numlines = wss * CACHELINES_IN_1KB;
165
166 sum = 0;
167
168 /* contents of arena is structured s.t. offsets are all
169 w.r.t. to start of arena, so compute the initial offset */
170 next = mem - arena;
171
172 if (write_cycle == 0) {
173 for (i = 0; i < numlines; i++) {
174 for (j = 0; j < INTS_IN_CACHELINE; j++) {
175 /* every element in the cacheline has the same value */
176 //next = arena[next].line[j];
177 local_buf[next].line[j] = arena[next].line[j];
178 //sum += next;
179 //local_buf[next].line[j] = next;
180 }
181 }
182 }
183
184 else {
185 int w, which_line;
186 for (i = 0, w = 0; i < numlines; i++) {
187 for (j = 0; j < INTS_IN_CACHELINE; j++) {
188 which_line = next;
189 next = local_buf[next].line[j];
190 ((volatile cacheline_t*)arena)[which_line].line[j] = next;
191 //sum += next;
192 }
193 }
194 }
195 return sum;
196}
197
198static cacheline_t* random_start(int wss)
199{
200 return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
201}
202
203static int sequential_walk(cacheline_t *mem, int wss, int write_cycle)
204{
205 int sum = 0, i, j;
206 //int* mem = (int*)_mem; /* treat as raw buffer of ints */
207 int num_ints = wss * CACHELINES_IN_1KB;
208
209 if (write_cycle > 0) {
210 for (i = 0; i < num_ints; i++) {
211 //if (i % write_cycle == (write_cycle - 1)) {
212 //mem[i]++;
213 for (j = 0; j < INTS_IN_CACHELINE; j++) {
214 //sum += local_buf[i].line[j];
215 mem[i].line[j] = local_buf[i].line[j];;
216 }
217 //}
218 //else {
219 // sum += mem[i];
220 //}
221 }
222 } else {
223 /* sequential access, pure read */
224 for (i = 0; i < num_ints; i++) {
225 for (j = 0; j < INTS_IN_CACHELINE; j++) {
226 //sum += mem[i];
227 local_buf[i].line[j] = mem[i].line[j];
228 //sum += mem[i];
229 }
230 }
231 }
232 return sum;
233}
234
235static cacheline_t* sequential_start(int wss)
236{
237 return arena;
238/* static int pos = 0;
239
240 int num_cachelines = wss * CACHELINES_IN_1KB;
241 size_t num_arena_elem = wss * 1024 / sizeof(cacheline_t);
242 cacheline_t *mem;
243*/
244
245 /* Don't allow re-use between allocations.
246 * At most half of the arena may be used
247 * at any one time.
248 */
249/* if (num_cachelines * 2 > num_arena_elem)
250 bail_out("static memory arena too small");
251
252 if (pos + num_cachelines > num_arena_elem) {
253 mem = arena;
254 pos = num_cachelines;
255 } else {
256 mem = arena + pos;
257 pos += num_cachelines;
258 }
259
260 return mem;*/
261}
262
263static volatile int dont_optimize_me = 0;
264
265static void usage(char *error) {
266 fprintf(stderr, "Error: %s\n", error);
267 fprintf(stderr,
268 "Usage:\n"
269 " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
270 " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
271 " rt_spin -l\n"
272 "\n"
273 "COMMON-OPTS = [-w] [-s SCALE]\n"
274 " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
275 " [-k WSS] [-l LOOPS] [-b BUDGET]\n"
276 "\n"
277 "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
278 exit(EXIT_FAILURE);
279}
280
281static int loop_once(int wss)
282{
283 cacheline_t *mem;
284 int temp;
285
286 mem = random_start(wss);
287 temp = random_walk(mem, wss, 1);
288
289 //mem = sequential_start(wss);
290 //temp = sequential_walk(arena, wss, 1);
291 dont_optimize_me = temp;
292
293 return dont_optimize_me;
294}
295
296static int job(int wss, double exec_time, double program_end)
297{
298 if (wctime() > program_end)
299 return 0;
300 else {
301 register unsigned long t;
302 register unsigned int iter = 0;
303 //t = get_cyclecount();
304 //gettimeofday(&t1, NULL);
305 while(iter++ < loops) {
306 loop_once(wss);
307 }
308 //gettimeofday(&t2, NULL);
309 //printf("%ld cycles\n", get_cyclecount() - t);
310 //printf("%ld\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec)));
311 sleep_next_period();
312 return 1;
313 }
314}
315
316#define OPTSTR "p:wl:m:i:b:k:"
317int main(int argc, char** argv)
318{
319 int ret;
320 lt_t wcet, period, budget;
321 double wcet_ms, period_ms, budget_ms;
322 unsigned int priority = LITMUS_NO_PRIORITY;
323 int migrate = 0;
324 int cluster = 0;
325 int opt;
326 int wait = 0;
327 double duration = 0, start = 0;
328 struct rt_task param;
329 struct mc2_task mc2_param;
330 struct reservation_config config;
331 int res_type = PERIODIC_POLLING;
332 size_t arena_sz;
333 int wss;
334
335 /* default for reservation */
336 config.id = 0;
337 config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
338 config.cpu = -1;
339
340 mc2_param.crit = CRIT_LEVEL_C;
341
342 budget_ms = 1000;
343
344 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
345 switch (opt) {
346 case 'w':
347 wait = 1;
348 break;
349 case 'p':
350 cluster = atoi(optarg);
351 migrate = 1;
352 config.cpu = cluster;
353 break;
354 case 'l':
355 loops = atoi(optarg);
356 break;
357 case 'k':
358 wss = atoi(optarg);
359 break;
360 case 'm':
361 mc2_param.crit = atoi(optarg);
362 if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
363 res_type = PERIODIC_POLLING;
364 }
365 else
366 usage("Invalid criticality level.");
367 break;
368 case 'b':
369 budget_ms = atof(optarg);
370 break;
371 case 'i':
372 config.priority = atoi(optarg);
373 break;
374 case ':':
375 usage("Argument missing.");
376 break;
377 case '?':
378 default:
379 usage("Bad argument.");
380 break;
381 }
382 }
383 srand(getpid());
384
385 /*
386 * We need three parameters
387 */
388 if (argc - optind < 3)
389 usage("Arguments missing.");
390
391 wcet_ms = atof(argv[optind + 0]);
392 period_ms = atof(argv[optind + 1]);
393
394 wcet = ms2ns(wcet_ms);
395 period = ms2ns(period_ms);
396 budget = ms2ns(budget_ms);
397 if (wcet <= 0)
398 usage("The worst-case execution time must be a "
399 "positive number.");
400 if (period <= 0)
401 usage("The period must be a positive number.");
402 if (wcet > period) {
403 usage("The worst-case execution time must not "
404 "exceed the period.");
405 }
406
407 duration = atof(argv[optind + 2]);
408
409 if (migrate) {
410 ret = be_migrate_to_domain(cluster);
411 if (ret < 0)
412 bail_out("could not migrate to target partition or cluster.");
413 }
414
415 /* reservation config */
416 config.id = gettid();
417 config.polling_params.budget = budget;
418 config.polling_params.period = period;
419 config.polling_params.offset = 0;
420 config.polling_params.relative_deadline = 0;
421
422 if (config.polling_params.budget > config.polling_params.period) {
423 usage("The budget must not exceed the period.");
424 }
425
426 /* create a reservation */
427 ret = reservation_create(res_type, &config);
428 if (ret < 0) {
429 bail_out("failed to create reservation.");
430 }
431
432 init_rt_task_param(&param);
433 param.exec_cost = wcet;
434 param.period = period;
435 param.priority = priority;
436 param.cls = RT_CLASS_HARD;
437 param.release_policy = TASK_PERIODIC;
438 param.budget_policy = NO_ENFORCEMENT;
439 if (migrate) {
440 param.cpu = gettid();
441 }
442 ret = set_rt_task_param(gettid(), &param);
443 if (ret < 0)
444 bail_out("could not setup rt task params");
445
446 mc2_param.res_id = gettid();
447 ret = set_mc2_task_param(gettid(), &mc2_param);
448 if (ret < 0)
449 bail_out("could not setup mc2 task params");
450
451
452 arena_sz = wss*1024;
453
454 arena = alloc_shm(arena_sz, 0, 0);
455 if (!arena)
456 bail_out("alloc_shm failed.\n");
457 init_arena(arena, arena_sz);
458
459 local_buf = alloc_local(arena_sz, 0, 0);
460 if (!local_buf)
461 bail_out("alloc_local failed.\n");
462 init_arena(local_buf, arena_sz);
463
464 ret = init_litmus();
465 if (ret != 0)
466 bail_out("init_litmus() failed\n");
467
468 start = wctime();
469 ret = task_mode(LITMUS_RT_TASK);
470 if (ret != 0)
471 bail_out("could not become RT task");
472
473 if (mc2_param.crit == CRIT_LEVEL_C)
474 set_page_color(-1);
475 else
476 set_page_color(config.cpu);
477
478 mlockall(MCL_CURRENT | MCL_FUTURE);
479// init_arena(local_buf, arena_sz);
480// test_call(1);
481// init_arena(arena, arena_sz);
482// test_call(2);
483
484 if (wait) {
485 ret = wait_for_ts_release();
486 if (ret != 0)
487 bail_out("wait_for_ts_release()");
488 start = wctime();
489 }
490
491 while (job(wss, wcet_ms * 0.001, start + duration)) {};
492
493 ret = task_mode(BACKGROUND_TASK);
494 if (ret != 0)
495 bail_out("could not become regular task (huh?)");
496
497 reservation_destroy(gettid(), config.cpu);
498 dealloc_arena(arena, arena_sz);
499 dealloc_arena(local_buf, arena_sz);
500 printf("%s finished.\n", argv[0]);
501 return 0;
502}
diff --git a/bin/mttest.c b/bin/mtdag.c
index 7d573cc..4c6cf9a 100644
--- a/bin/mttest.c
+++ b/bin/mtdag.c
@@ -26,6 +26,7 @@
26/* Include the LITMUS^RT API.*/ 26/* Include the LITMUS^RT API.*/
27#include "litmus.h" 27#include "litmus.h"
28#include "color_shm.h" 28#include "color_shm.h"
29#include "asm/cycles.h"
29 30
30#define PERIOD 100 31#define PERIOD 100
31#define RELATIVE_DEADLINE 100 32#define RELATIVE_DEADLINE 100
@@ -41,7 +42,9 @@ struct thread_context {
41 int id; 42 int id;
42 int cpu; 43 int cpu;
43 int job_no; 44 int job_no;
44 char* shm; 45 char* shm1;
46 char* shm2;
47 char* shm3;
45}; 48};
46 49
47/* The real-time thread program. Doesn't have to be the same for 50/* The real-time thread program. Doesn't have to be the same for
@@ -73,11 +76,14 @@ int job(struct thread_context *tcx);
73 */ 76 */
74int main(int argc, char** argv) 77int main(int argc, char** argv)
75{ 78{
76 int i, ret, fd; 79 int i;
77 struct thread_context ctx[NUM_THREADS]; 80 struct thread_context ctx[NUM_THREADS];
78 pthread_t task[NUM_THREADS]; 81 pthread_t task[NUM_THREADS];
79 char *shm; 82 char *shm1;
83 char *shm2;
84 char *shm3;
80 struct color_ioctl_cmd shm_info; 85 struct color_ioctl_cmd shm_info;
86 struct color_ioctl_offset shm_offset;
81 /* The task is in background mode upon startup. */ 87 /* The task is in background mode upon startup. */
82 88
83 89
@@ -91,23 +97,43 @@ int main(int argc, char** argv)
91 * 2) Work environment (e.g., global data structures, file data, etc.) would 97 * 2) Work environment (e.g., global data structures, file data, etc.) would
92 * be setup here. 98 * be setup here.
93 */ 99 */
94 fd = open("/dev/litmus/color_shm", O_RDWR); 100
95 if (fd < 0) { 101 shm_info.color = 0x00000001;
96 printf("Device open error.\n"); 102 shm_info.bank = 0x00000020;
97 return -1; 103 shm_offset.offset = 0;
104 shm_offset.lock = 1;
105
106 shm1 = (char*)color_mmap(1024, shm_info, shm_offset);
107 if (!shm1) {
108 printf("color mmap failed.\n");
109 exit(-1);
110 }
111 else {
112 printf("Mapped vaddr = %p\n", shm1);
98 } 113 }
99 114
100 shm_info.color = 0x0000cccc; 115 shm_info.color = 0x00000003;
101 shm_info.bank = 0x000000ac; 116 shm_offset.offset = 1024;
117 shm2 = (char*)color_mmap(4096, shm_info, shm_offset);
102 118
103 ret = ioctl(fd, SET_COLOR_SHM_CMD, &shm_info); 119 if (!shm2) {
120 printf("color mmap failed.\n");
121 exit(-1);
122 }
123 else {
124 printf("Mapped vaddr = %p\n", shm2);
125 }
104 126
105 shm = mmap(NULL, 6000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 127 shm_info.color = 0x00000002;
106 if (shm == MAP_FAILED) { 128 shm_offset.offset = 1024;
107 printf("mmap failed.\n"); 129 shm3 = (char*)color_mmap(3072, shm_info, shm_offset);
108 return -1; 130 if (!shm3) {
131 printf("color mmap failed.\n");
132 exit(-1);
133 }
134 else {
135 printf("Mapped vaddr = %p\n", shm3);
109 } 136 }
110 close(fd);
111 137
112 mlockall(MCL_CURRENT | MCL_FUTURE); 138 mlockall(MCL_CURRENT | MCL_FUTURE);
113 /***** 139 /*****
@@ -124,7 +150,9 @@ int main(int argc, char** argv)
124 ctx[i].id = i; 150 ctx[i].id = i;
125 ctx[i].cpu = 0; 151 ctx[i].cpu = 0;
126 ctx[i].job_no = 0; 152 ctx[i].job_no = 0;
127 ctx[i].shm = shm; 153 ctx[i].shm1 = shm1;
154 ctx[i].shm3 = shm2;
155 ctx[i].shm2 = shm3;
128 pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i)); 156 pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
129 } 157 }
130 158
@@ -154,6 +182,8 @@ void* rt_thread(void *tcontext)
154 struct thread_context *ctx = (struct thread_context *) tcontext; 182 struct thread_context *ctx = (struct thread_context *) tcontext;
155 struct rt_task param; 183 struct rt_task param;
156 int ret; 184 int ret;
185 struct mc2_task mc2_param;
186 struct reservation_config res_config;
157 187
158 /* Set up task parameters */ 188 /* Set up task parameters */
159 init_rt_task_param(&param); 189 init_rt_task_param(&param);
@@ -173,11 +203,27 @@ void* rt_thread(void *tcontext)
173 /* Make presence visible. */ 203 /* Make presence visible. */
174 printf("RT Thread %d active.\n", ctx->id); 204 printf("RT Thread %d active.\n", ctx->id);
175 205
206 /* reservation config */
207 res_config.id = gettid();
208 res_config.polling_params.budget = ms2ns(EXEC_COST+1);
209 res_config.polling_params.period = param.period;
210 res_config.polling_params.offset = 0;
211 res_config.polling_params.relative_deadline = 0;
212 res_config.priority = LITMUS_MAX_PRIORITY;
213 res_config.cpu = ctx->cpu;
214 mc2_param.crit = CRIT_LEVEL_A;
215 mc2_param.res_id = gettid();
176 /***** 216 /*****
177 * 1) Initialize real-time settings. 217 * 1) Initialize real-time settings.
178 */ 218 */
179 CALL( init_rt_thread() ); 219 CALL( init_rt_thread() );
180 220
221 ret = reservation_create(PERIODIC_POLLING, &res_config);
222 if (ret < 0) {
223 printf("reservation failed.\n");
224 return NULL;
225 }
226
181 /* To specify a partition, do 227 /* To specify a partition, do
182 * 228 *
183 * param.cpu = CPU; 229 * param.cpu = CPU;
@@ -194,6 +240,7 @@ void* rt_thread(void *tcontext)
194 } 240 }
195 CALL( set_rt_task_param(gettid(), &param) ); 241 CALL( set_rt_task_param(gettid(), &param) );
196 242
243 CALL( set_mc2_task_param(gettid(), &mc2_param) );
197 /***** 244 /*****
198 * 2) Transition to real-time mode. 245 * 2) Transition to real-time mode.
199 */ 246 */
@@ -220,7 +267,7 @@ void* rt_thread(void *tcontext)
220 * 4) Transition to background mode. 267 * 4) Transition to background mode.
221 */ 268 */
222 CALL( task_mode(BACKGROUND_TASK) ); 269 CALL( task_mode(BACKGROUND_TASK) );
223 270 reservation_destroy(gettid(), res_config.cpu);
224 271
225 return NULL; 272 return NULL;
226} 273}
@@ -230,28 +277,56 @@ void* rt_thread(void *tcontext)
230int job(struct thread_context *tcx) 277int job(struct thread_context *tcx)
231{ 278{
232 int i; 279 int i;
233 char* buf = tcx->shm; 280 char* buf1 = tcx->shm1;
281 char* buf2 = tcx->shm2;
282 char* buf3 = tcx->shm3;
283 char tmp = 0;
234 /* Do real-time calculation. */ 284 /* Do real-time calculation. */
235 printf("Task %d Job %d executinig\n", tcx->id, tcx->job_no); 285 printf("Task %d Job %d executinig\n", tcx->id, tcx->job_no);
236 286
237 if (tcx->id == 0) { 287 if (tcx->id == 0) {
238 printf("WRITE\n"); 288 cycles_t t1, t2;
239 for (i=0; i<6000; i++) { 289 t1 = get_cycles();
240 buf[i] = rand()%255; 290 for (i = 0; i < 1024; i+=32) {
291 tmp += buf1[i];
292 }
293 t2 = get_cycles();
294 printf("%lu\n", t2 = t2 - t1);
295
296 t1 = get_cycles();
297 for (i = 0; i < 4096; i+=32) {
298 tmp += buf2[i];
299 }
300 t2 = get_cycles();
301 printf("%lu\n", t2 = t2 - t1);
302
303 t1 = get_cycles();
304 for (i = 0; i < 3072; i+=32) {
305 tmp += buf3[i];
306 }
307 t2 = get_cycles();
308 printf("%lu\n", t2 = t2 - t1);
309
310/* printf("WRITE\n");
311 for (i=0; i<600; i++) {
312 buf1[i] = rand()%255;
241 printf("%x ",buf[i]); 313 printf("%x ",buf[i]);
242 } 314 }
243 printf("\n"); 315*/
316// printf("\n");
244 } else if (tcx->id == 1) { 317 } else if (tcx->id == 1) {
245 printf("READ\n"); 318/* printf("READ\n");
246 for (i=0; i<6000; i++) { 319 for (i=0; i<600; i++) {
247 char t = buf[i]; 320 char t = buf[i];
248 printf("%x ", t); 321 printf("%x ", t);
249 } 322 }
250 printf("\n"); 323 printf("\n");
324*/
325 ;
251 } 326 }
252 //test_call(0); 327 //test_call(0);
253 tcx->job_no++; 328 tcx->job_no++;
254 if (tcx->job_no == 1) 329 if (tcx->job_no == 10)
255 return 1; 330 return 1;
256 /* Don't exit. */ 331 /* Don't exit. */
257 return 0; 332 return 0;
diff --git a/bin/test1.c b/bin/test1.c
new file mode 100644
index 0000000..a38d402
--- /dev/null
+++ b/bin/test1.c
@@ -0,0 +1,453 @@
1#include <sys/time.h>
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <time.h>
7#include <string.h>
8#include <assert.h>
9#include <limits.h>
10#include <sys/mman.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14
15#include "litmus.h"
16#include "common.h"
17
18
19
20static void usage(char *error) {
21 fprintf(stderr, "Error: %s\n", error);
22 fprintf(stderr,
23 "Usage:\n"
24 " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
25 " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
26 " rt_spin -l\n"
27 "\n"
28 "COMMON-OPTS = [-w] [-s SCALE]\n"
29 " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS]\n"
30 " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]"
31 "\n"
32 "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
33 "CRITICAL SECTION LENGTH is in milliseconds.\n");
34 exit(EXIT_FAILURE);
35}
36
37/*
38 * returns the character that made processing stop, newline or EOF
39 */
40static int skip_to_next_line(FILE *fstream)
41{
42 int ch;
43 for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
44 return ch;
45}
46
47static void skip_comments(FILE *fstream)
48{
49 int ch;
50 for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
51 skip_to_next_line(fstream);
52 ungetc(ch, fstream);
53}
54
55static void get_exec_times(const char *file, const int column,
56 int *num_jobs, double **exec_times)
57{
58 FILE *fstream;
59 int cur_job, cur_col, ch;
60 *num_jobs = 0;
61
62 fstream = fopen(file, "r");
63 if (!fstream)
64 bail_out("could not open execution time file");
65
66 /* figure out the number of jobs */
67 do {
68 skip_comments(fstream);
69 ch = skip_to_next_line(fstream);
70 if (ch != EOF)
71 ++(*num_jobs);
72 } while (ch != EOF);
73
74 if (-1 == fseek(fstream, 0L, SEEK_SET))
75 bail_out("rewinding file failed");
76
77 /* allocate space for exec times */
78 *exec_times = calloc(*num_jobs, sizeof(*exec_times));
79 if (!*exec_times)
80 bail_out("couldn't allocate memory");
81
82 for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
83
84 skip_comments(fstream);
85
86 for (cur_col = 1; cur_col < column; ++cur_col) {
87 /* discard input until we get to the column we want */
88 int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
89 }
90
91 /* get the desired exec. time */
92 if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
93 fprintf(stderr, "invalid execution time near line %d\n",
94 cur_job);
95 exit(EXIT_FAILURE);
96 }
97
98 skip_to_next_line(fstream);
99 }
100
101 assert(cur_job == *num_jobs);
102 fclose(fstream);
103}
104
105#define NUMS 4096
106static int num[NUMS];
107static char* progname;
108static char* smem;
109static int access_type; /* 0: read 1: write */
110
111static int loop_once(void)
112{
113 int i, j = 0;
114 for (i = 0; i < NUMS; i++) {
115 j += num[i]++;
116 if (access_type == 1) {
117 smem[i] = j%255;
118 printf("Write %d at [%d]\n", smem[i], i);
119 } else {
120 char tmp = smem[i];
121 printf("Read %d at [%d]\n", tmp, i);
122 }
123 }
124 return j;
125}
126
127static int loop_for(double exec_time, double emergency_exit)
128{
129 double last_loop = 0, loop_start;
130 int tmp = 0;
131
132 double start = cputime();
133 double now = cputime();
134
135 while (now + last_loop < start + exec_time) {
136 loop_start = now;
137 tmp += loop_once();
138 now = cputime();
139 last_loop = now - loop_start;
140 if (emergency_exit && wctime() > emergency_exit) {
141 /* Oops --- this should only be possible if the execution time tracking
142 * is broken in the LITMUS^RT kernel. */
143 fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
144 fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
145 break;
146 }
147 }
148
149 return tmp;
150}
151
152
153static void debug_delay_loop(void)
154{
155 double start, end, delay;
156
157 while (1) {
158 for (delay = 0.5; delay > 0.01; delay -= 0.01) {
159 start = wctime();
160 loop_for(delay, 0);
161 end = wctime();
162 printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
163 delay,
164 end - start,
165 end - start - delay,
166 100 * (end - start - delay) / delay);
167 }
168 }
169}
170
171static int job(double exec_time, double program_end, int lock_od, double cs_length)
172{
173 double chunk1, chunk2;
174
175 if (wctime() > program_end)
176 return 0;
177 else {
178 if (lock_od >= 0) {
179 /* simulate critical section somewhere in the middle */
180 chunk1 = drand48() * (exec_time - cs_length);
181 chunk2 = exec_time - cs_length - chunk1;
182
183 /* non-critical section */
184 loop_for(chunk1, program_end + 1);
185
186 /* critical section */
187 litmus_lock(lock_od);
188 loop_for(cs_length, program_end + 1);
189 litmus_unlock(lock_od);
190
191 /* non-critical section */
192 loop_for(chunk2, program_end + 2);
193 } else {
194 //loop_for(exec_time, program_end + 1);
195 loop_once();
196 }
197 sleep_next_period();
198 return 1;
199 }
200}
201
202#define OPTSTR "p:c:wlveo:f:s:q:r:X:L:Q:vt:"
203int main(int argc, char** argv)
204{
205 int ret;
206 lt_t wcet;
207 lt_t period;
208 double wcet_ms, period_ms;
209 unsigned int priority = LITMUS_NO_PRIORITY;
210 int migrate = 0;
211 int cluster = 0;
212 int reservation = -1;
213 int opt;
214 int wait = 0;
215 int test_loop = 0;
216 int column = 1;
217 const char *file = NULL;
218 int want_enforcement = 0;
219 double duration = 0, start = 0;
220 double *exec_times = NULL;
221 double scale = 1.0;
222 task_class_t class = RT_CLASS_HARD;
223 int cur_job = 0, num_jobs = 0;
224 struct rt_task param;
225
226 int verbose = 0;
227 unsigned int job_no;
228
229 /* locking */
230 int lock_od = -1;
231 int resource_id = 0;
232 const char *lock_namespace = "./rtspin-locks";
233 int protocol = -1;
234 double cs_length = 1; /* millisecond */
235 int fd;
236
237 progname = argv[0];
238
239 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
240 switch (opt) {
241 case 'w':
242 wait = 1;
243 break;
244 case 'p':
245 cluster = atoi(optarg);
246 migrate = 1;
247 break;
248 case 'r':
249 reservation = atoi(optarg);
250 break;
251 case 'q':
252 priority = atoi(optarg);
253 if (!litmus_is_valid_fixed_prio(priority))
254 usage("Invalid priority.");
255 break;
256 case 'c':
257 class = str2class(optarg);
258 if (class == -1)
259 usage("Unknown task class.");
260 break;
261 case 'e':
262 want_enforcement = 1;
263 break;
264 case 'l':
265 test_loop = 1;
266 break;
267 case 'o':
268 column = atoi(optarg);
269 break;
270 case 'f':
271 file = optarg;
272 break;
273 case 's':
274 scale = atof(optarg);
275 break;
276 case 'X':
277 protocol = lock_protocol_for_name(optarg);
278 if (protocol < 0)
279 usage("Unknown locking protocol specified.");
280 break;
281 case 'L':
282 cs_length = atof(optarg);
283 if (cs_length <= 0)
284 usage("Invalid critical section length.");
285 break;
286 case 'Q':
287 resource_id = atoi(optarg);
288 if (resource_id <= 0 && strcmp(optarg, "0"))
289 usage("Invalid resource ID.");
290 break;
291 case 'v':
292 verbose = 1;
293 break;
294 case 't':
295 access_type = atoi(optarg);
296 if (access_type != 0 && access_type != 1)
297 usage("Wrong SHM access type.");
298 break;
299 case ':':
300 usage("Argument missing.");
301 break;
302 case '?':
303 default:
304 usage("Bad argument.");
305 break;
306 }
307 }
308
309 if (test_loop) {
310 debug_delay_loop();
311 return 0;
312 }
313
314 srand(getpid());
315
316 if (file) {
317 get_exec_times(file, column, &num_jobs, &exec_times);
318
319 if (argc - optind < 2)
320 usage("Arguments missing.");
321
322 for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
323 /* convert the execution time to seconds */
324 duration += exec_times[cur_job] * 0.001;
325 }
326 } else {
327 /*
328 * if we're not reading from the CSV file, then we need
329 * three parameters
330 */
331 if (argc - optind < 3)
332 usage("Arguments missing.");
333 }
334
335 wcet_ms = atof(argv[optind + 0]);
336 period_ms = atof(argv[optind + 1]);
337
338 wcet = ms2ns(wcet_ms);
339 period = ms2ns(period_ms);
340 if (wcet <= 0)
341 usage("The worst-case execution time must be a "
342 "positive number.");
343 if (period <= 0)
344 usage("The period must be a positive number.");
345 if (!file && wcet > period) {
346 usage("The worst-case execution time must not "
347 "exceed the period.");
348 }
349
350 if (!file)
351 duration = atof(argv[optind + 2]);
352 else if (file && num_jobs > 1)
353 duration += period_ms * 0.001 * (num_jobs - 1);
354
355 if (migrate) {
356 ret = be_migrate_to_domain(cluster);
357 if (ret < 0)
358 bail_out("could not migrate to target partition or cluster.");
359 }
360
361
362 /* allocate shared memory */
363 fd = open("/dev/shm/region1", O_CREAT|O_RDWR|O_TRUNC, 0666);
364 if (fd == -1)
365 bail_out("could not open /dev/shm.");
366
367 fallocate(fd, 0, 0, 4096);
368 smem = NULL;
369 if (access_type == 1) {
370 printf("open write mmap now.\n");
371 smem = (char*) mmap(NULL, 4096, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
372 if (smem == MAP_FAILED)
373 bail_out("mmap error.");
374 close(fd);
375 }
376 else {
377 printf("open read mmap now.\n");
378 smem = (char*) mmap(NULL, 4096, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
379 if (smem == MAP_FAILED)
380 bail_out("mmap error.");
381 close(fd);
382 }
383 printf("smem addr = %p\n", smem);
384 init_rt_task_param(&param);
385 param.exec_cost = wcet;
386 param.period = period;
387 param.priority = priority;
388 param.cls = class;
389 param.budget_policy = (want_enforcement) ?
390 PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
391 if (migrate) {
392 if (reservation >= 0)
393 param.cpu = reservation;
394 else
395 param.cpu = domain_to_first_cpu(cluster);
396 }
397 ret = set_rt_task_param(gettid(), &param);
398 if (ret < 0)
399 bail_out("could not setup rt task params");
400
401 init_litmus();
402//test_call(0);
403 start = wctime();
404 ret = task_mode(LITMUS_RT_TASK);
405 if (ret != 0)
406 bail_out("could not become RT task");
407
408 if (protocol >= 0) {
409 /* open reference to semaphore */
410 lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
411 if (lock_od < 0) {
412 perror("litmus_open_lock");
413 usage("Could not open lock.");
414 }
415 }
416
417
418 if (wait) {
419 ret = wait_for_ts_release();
420 if (ret != 0)
421 bail_out("wait_for_ts_release()");
422 start = wctime();
423 }
424
425 if (file) {
426 /* use times read from the CSV file */
427 for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
428 /* convert job's length to seconds */
429 job(exec_times[cur_job] * 0.001 * scale,
430 start + duration,
431 lock_od, cs_length * 0.001);
432 }
433 } else {
434 do {
435 if (verbose) {
436 get_job_no(&job_no);
437 printf("rtspin/%d:%u @ %.4fms\n", gettid(),
438 job_no, (wctime() - start) * 1000);
439 }
440 /* convert to seconds and scale */
441 } while (job(wcet_ms * 0.001 * scale, start + duration,
442 lock_od, cs_length * 0.001));
443 }
444
445 ret = task_mode(BACKGROUND_TASK);
446 if (ret != 0)
447 bail_out("could not become regular task (huh?)");
448
449 if (file)
450 free(exec_times);
451
452 return 0;
453}
diff --git a/include/cache_common.h b/include/cache_common.h
new file mode 100644
index 0000000..2957dd3
--- /dev/null
+++ b/include/cache_common.h
@@ -0,0 +1,213 @@
1#ifndef __CACHE_COMMON_H__
2#define __CACHE_COMMON_H__
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <time.h>
7#include <string.h>
8#include <assert.h>
9
10#include <signal.h>
11#include <sys/mman.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include <sys/io.h>
18#include <sys/utsname.h>
19
20#include <sched.h>
21#include <sys/time.h>
22#include <sys/resource.h>
23
24#include "litmus.h"
25#include "asm/cycles.h"
26
27#if defined(__i386__) || defined(__x86_64__)
28#include "asm/irq.h"
29#endif
30
31
32#define UNCACHE_DEV "/dev/litmus/uncache"
33
34static void die(char *error)
35{
36 fprintf(stderr, "Error: %s (errno: %m)\n",
37 error);
38 exit(1);
39}
40
41static int migrate_to(int cpu)
42{
43 int ret;
44
45 static __thread cpu_set_t* cpu_set = NULL;
46 static __thread size_t cpu_set_sz;
47 static __thread int num_cpus;
48 if(!cpu_set)
49 {
50 num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
51 cpu_set = CPU_ALLOC(num_cpus);
52 cpu_set_sz = CPU_ALLOC_SIZE(num_cpus);
53 }
54
55 CPU_ZERO_S(cpu_set_sz, cpu_set);
56 CPU_SET_S(cpu, cpu_set_sz, cpu_set);
57 ret = sched_setaffinity(0 /* self */, cpu_set_sz, cpu_set);
58 return ret;
59}
60
61static int check_migrations(int num_cpus)
62{
63 int cpu, err;
64
65 for (cpu = 0; cpu < num_cpus; cpu++) {
66 err = migrate_to(cpu);
67 if (err != 0) {
68 fprintf(stderr, "Migration to CPU %d failed: %m.\n",
69 cpu + 1);
70 return 1;
71 }
72 }
73 return 0;
74}
75
76static int become_posix_realtime_task(int prio)
77{
78 struct sched_param param;
79 memset(&param, 0, sizeof(param));
80 param.sched_priority = prio;
81 return sched_setscheduler(0 /* self */, SCHED_FIFO, &param);
82}
83
84static int renice(int nice_val)
85{
86 return setpriority(PRIO_PROCESS, 0 /* self */, nice_val);
87}
88
89static int lock_memory(void)
90{
91 return mlockall(MCL_CURRENT | MCL_FUTURE);
92}
93
94/* define CACHELINE_SIZE if not provided by compiler args */
95#ifndef CACHELINE_SIZE
96#if defined(__i386__) || defined(__x86_64__)
97/* recent intel cpus */
98#define CACHELINE_SIZE 64
99#elif defined(__arm__)
100/* at least with Cortex-A9 cpus ("8 words") */
101#define CACHELINE_SIZE 32
102#else
103#error "Could not determine cacheline size!"
104#endif
105#endif
106
107//#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
108//typedef struct cacheline
109//{
110// int line[INTS_IN_CACHELINE];
111//} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
112
113static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages)
114{
115 int flags = MAP_PRIVATE | MAP_POPULATE;
116 cacheline_t* arena = NULL;
117 int fd;
118
119 if(use_huge_pages)
120 flags |= MAP_HUGETLB;
121
122 if(use_uncache_pages) {
123 fd = open(UNCACHE_DEV, O_RDWR);
124 if (fd == -1)
125 die("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
126 }
127 else {
128 fd = -1;
129 flags |= MAP_ANONYMOUS;
130 }
131
132 arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
133
134 if(use_uncache_pages)
135 close(fd);
136
137 assert(arena);
138
139 return arena;
140}
141
142static void dealloc_arena(cacheline_t* arena, size_t size)
143{
144 int ret = munmap((void*)arena, size);
145 if(ret != 0)
146 die("munmap() error");
147}
148
149static int randrange(int min, int max)
150{
151 /* generate a random number on the range [min, max) w/o skew */
152 int limit = max - min;
153 int devisor = RAND_MAX/limit;
154 int retval;
155
156 do {
157 retval = rand() / devisor;
158 } while(retval == limit);
159 retval += min;
160
161 return retval;
162}
163
164static void init_arena(cacheline_t* arena, size_t size)
165{
166 int i;
167 size_t num_arena_elem = size / sizeof(cacheline_t);
168
169 /* Generate a cycle among the cache lines using Sattolo's algorithm.
170 Every int in the cache line points to the same cache line.
171 Note: Sequential walk doesn't care about these values. */
172 for (i = 0; i < num_arena_elem; i++) {
173 int j;
174 for(j = 0; j < INTS_IN_CACHELINE; ++j)
175 arena[i].line[j] = i;
176 }
177 while(1 < i--) {
178 int j = randrange(0, i);
179 cacheline_t temp = arena[j];
180 arena[j] = arena[i];
181 arena[i] = temp;
182 }
183}
184
185static void sleep_us(int microseconds)
186{
187 struct timespec delay;
188
189 delay.tv_sec = 0;
190 delay.tv_nsec = microseconds * 1000;
191 if (nanosleep(&delay, NULL) != 0)
192 die("sleep failed");
193}
194
195static int completed(int nSamples, int* history, int nCategories)
196{
197 int i;
198 for(i = 0; i < nCategories; ++i)
199 if(history[i] < nSamples)
200 return 0;
201 return 1;
202}
203
204inline unsigned long get_cyclecount (void)
205{
206 unsigned long value;
207 // Read CCNT Register
208 asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
209 return value;
210}
211
212
213#endif
diff --git a/include/color_shm.h b/include/color_shm.h
index f6ad8a5..449ec9d 100644
--- a/include/color_shm.h
+++ b/include/color_shm.h
@@ -1,3 +1,4 @@
1#include <sys/types.h>
1#include <sys/ioctl.h> 2#include <sys/ioctl.h>
2#include <fcntl.h> 3#include <fcntl.h>
3 4
@@ -8,6 +9,12 @@ struct color_ioctl_cmd {
8 unsigned int bank; 9 unsigned int bank;
9}; 10};
10 11
11#define SET_COLOR_SHM_CMD \ 12struct color_ioctl_offset {
12 _IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd) 13 unsigned long offset;
14 int lock;
15};
16
17#define SET_COLOR_SHM_CMD _IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd)
18#define SET_COLOR_SHM_OFFSET _IOW(SHM_MAJOR, 0x2, struct color_ioctl_offset)
13 19
20void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset);
diff --git a/include/litmus.h b/include/litmus.h
index aaa8d1c..1ef48e8 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -46,7 +46,15 @@ extern "C" {
46 * @private 46 * @private
47 * Number of semaphore protocol object types 47 * Number of semaphore protocol object types
48 */ 48 */
49#define SCHED_LITMUS 7 49#define SCHED_LITMUS 6
50
51#define CACHELINE_SIZE 32
52#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
53#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
54typedef struct cacheline
55{
56 int line[INTS_IN_CACHELINE];
57} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
50 58
51/** 59/**
52 * Initialise a real-time task param struct 60 * Initialise a real-time task param struct
@@ -440,6 +448,8 @@ int set_page_color(int cpu);
440 448
441int test_call(unsigned int param); 449int test_call(unsigned int param);
442 450
451int run_bench(int type, int size, cacheline_t *src, cacheline_t *dst, lt_t __user *ts);
452
443#ifdef __cplusplus 453#ifdef __cplusplus
444} 454}
445#endif 455#endif
diff --git a/src/color_shm.c b/src/color_shm.c
new file mode 100644
index 0000000..8531445
--- /dev/null
+++ b/src/color_shm.c
@@ -0,0 +1,40 @@
1#include <sys/mman.h>
2#include <stdio.h>
3
4#include "color_shm.h"
5
6void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset)
7{
8 int ret, fd;
9 void *mem;
10
11 fd = open("/dev/litmus/color_shm", O_RDWR);
12 if (fd < 0) {
13 printf("Device open error.\n");
14 return NULL;
15 }
16
17 ret = ioctl(fd, SET_COLOR_SHM_CMD, &cmd);
18 if (ret < 0) {
19 printf("ioctl failed.\n");
20 return NULL;
21 }
22
23 ret = ioctl(fd, SET_COLOR_SHM_OFFSET, &offset);
24 if (ret < 0) {
25 printf("ioctl failed.\n");
26 return NULL;
27 }
28
29 size += offset.offset;
30 mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
31 if (mem == MAP_FAILED) {
32 printf("mmap failed.\n");
33 return MAP_FAILED;
34 }
35 close(fd);
36
37 mem += offset.offset;
38
39 return mem;
40} \ No newline at end of file
diff --git a/src/kernel_iface.c b/src/kernel_iface.c
index 49cef2a..a2c2104 100644
--- a/src/kernel_iface.c
+++ b/src/kernel_iface.c
@@ -140,62 +140,6 @@ int requested_to_preempt(void)
140 return (likely(ctrl_page != NULL) && ctrl_page->sched.np.preempt); 140 return (likely(ctrl_page != NULL) && ctrl_page->sched.np.preempt);
141} 141}
142 142
143void enter_pgm_wait(void)
144{
145 if (likely(ctrl_page != NULL) || init_kernel_iface() == 0) {
146 assert(!ctrl_page->pgm_waiting);
147 ctrl_page->pgm_waiting = 1;
148 __sync_synchronize();
149 }
150 else {
151 fprintf(stderr, "enter_pgm_wait: control page not mapped!\n");
152 }
153}
154
155void exit_pgm_wait(void)
156{
157 if (likely(ctrl_page != NULL)) {
158 assert(ctrl_page->pgm_waiting);
159 ctrl_page->pgm_waiting = 0;
160 __sync_synchronize();
161 }
162 else {
163 fprintf(stderr, "exit_pgm_wait: control page not mapped!\n");
164 }
165}
166
167void enter_pgm_send(void)
168{
169 if (likely(ctrl_page != NULL) || init_kernel_iface() == 0) {
170 assert(!ctrl_page->pgm_sending);
171 ctrl_page->pgm_sending = 1; /* we will become boosted if
172 anyone tries to preempt us. */
173 __sync_synchronize();
174 }
175 else {
176 fprintf(stderr, "enter_pgm_send: control page not mapped!\n");
177 }
178}
179
180void exit_pgm_send(void)
181{
182 if (likely(ctrl_page != NULL)) {
183 assert(ctrl_page->pgm_sending);
184
185 ctrl_page->pgm_satisfied = 1;
186 __sync_synchronize();
187
188 /* re-eval priority. Should clear pgm_sending and pgm_satisfied. */
189 sched_yield();
190
191 /* double check that Litmus is doing its job */
192 assert(!ctrl_page->pgm_sending && !ctrl_page->pgm_satisfied);
193 }
194 else {
195 fprintf(stderr, "exit_pgm_send: control page not mapped!\n");
196 }
197}
198
199/* init and return a ptr to the control page for 143/* init and return a ptr to the control page for
200 * preemption and migration overhead analysis 144 * preemption and migration overhead analysis
201 * 145 *
diff --git a/src/syscalls.c b/src/syscalls.c
index ab064ad..31fd62f 100644
--- a/src/syscalls.c
+++ b/src/syscalls.c
@@ -107,7 +107,7 @@ int set_page_color(int cpu)
107 return syscall(__NR_set_page_color, cpu); 107 return syscall(__NR_set_page_color, cpu);
108} 108}
109 109
110int test_call(unsigned int param) 110int run_bench(int type, int wss, cacheline_t *src, cacheline_t *dst, lt_t *ts)
111{ 111{
112 return syscall(__NR_test_call, param); 112 return syscall(__NR_run_test, type, wss, src, dst, ts);
113} 113}