diff options
author | Namhoon Kim <namhoonk@cs.unc.edu> | 2016-04-05 13:58:55 -0400 |
---|---|---|
committer | Namhoon Kim <namhoonk@cs.unc.edu> | 2016-04-05 13:58:55 -0400 |
commit | e616da1f87a23afe1f154dfddc0e2682d2c2835d (patch) | |
tree | 221dbd230e9dc63acd1556d1b8e23e4c96d9d6db | |
parent | 5fd42b4dc877890668affe69f8cecc968e277148 (diff) |
Colored SHM test program. bin/mttest.c
-rw-r--r-- | Makefile | 20 | ||||
-rw-r--r-- | bin/base_mt_task.c | 24 | ||||
-rw-r--r-- | bin/mc2spin.c | 119 | ||||
-rw-r--r-- | bin/mttest.c | 256 | ||||
-rw-r--r-- | bin/rtspin.c | 4 | ||||
-rw-r--r-- | include/color_shm.h | 13 | ||||
-rw-r--r-- | include/litmus.h | 6 | ||||
-rw-r--r-- | src/syscalls.c | 12 |
8 files changed, 399 insertions, 55 deletions
@@ -19,7 +19,7 @@ LITMUS_KERNEL ?= ../litmus-rt | |||
19 | # Internal configuration. | 19 | # Internal configuration. |
20 | 20 | ||
21 | # compiler flags | 21 | # compiler flags |
22 | flags-debug = -O2 -Wall -Werror -g -Wdeclaration-after-statement | 22 | flags-debug = -O0 -Wall -g -Wdeclaration-after-statement |
23 | flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE | 23 | flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE |
24 | 24 | ||
25 | # architecture-specific flags | 25 | # architecture-specific flags |
@@ -73,7 +73,7 @@ AR := ${CROSS_COMPILE}${AR} | |||
73 | 73 | ||
74 | all = lib ${rt-apps} | 74 | all = lib ${rt-apps} |
75 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ | 75 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ |
76 | base_mt_task uncache runtests resctrl mc2spin | 76 | base_mt_task uncache runtests resctrl mc2spin test1 mttest |
77 | 77 | ||
78 | .PHONY: all lib clean dump-config TAGS tags cscope help doc | 78 | .PHONY: all lib clean dump-config TAGS tags cscope help doc |
79 | 79 | ||
@@ -238,8 +238,22 @@ lib-measure_syscall = -lm | |||
238 | obj-resctrl = resctrl.o | 238 | obj-resctrl = resctrl.o |
239 | 239 | ||
240 | obj-mc2spin = mc2spin.o common.o | 240 | obj-mc2spin = mc2spin.o common.o |
241 | lib-mc2spin = -lrt | 241 | lib-mc2spin = -lrt -static |
242 | 242 | ||
243 | obj-mc2pollute = mc2pollute.o common.o | ||
244 | lib-mc2pollute = -lrt -static | ||
245 | |||
246 | obj-mc2syn = mc2syn.o common.o | ||
247 | lib-mc2syn = -lrt -static | ||
248 | |||
249 | obj-memthrash = memthrash.o | ||
250 | lib-memthrash = -lrt | ||
251 | |||
252 | obj-test1 = test1.o common.o | ||
253 | lib-test1 = -lrt -static | ||
254 | |||
255 | obj-mttest = mttest.o | ||
256 | ldf-mttest = -pthread | ||
243 | # ############################################################################## | 257 | # ############################################################################## |
244 | # Build everything that depends on liblitmus. | 258 | # Build everything that depends on liblitmus. |
245 | 259 | ||
diff --git a/bin/base_mt_task.c b/bin/base_mt_task.c index aec79a4..1665203 100644 --- a/bin/base_mt_task.c +++ b/bin/base_mt_task.c | |||
@@ -29,11 +29,13 @@ | |||
29 | /* Let's create 10 threads in the example, | 29 | /* Let's create 10 threads in the example, |
30 | * for a total utilization of 1. | 30 | * for a total utilization of 1. |
31 | */ | 31 | */ |
32 | #define NUM_THREADS 10 | 32 | #define NUM_THREADS 3 |
33 | 33 | ||
34 | /* The information passed to each thread. Could be anything. */ | 34 | /* The information passed to each thread. Could be anything. */ |
35 | struct thread_context { | 35 | struct thread_context { |
36 | int id; | 36 | int id; |
37 | int cpu; | ||
38 | int job_no; | ||
37 | }; | 39 | }; |
38 | 40 | ||
39 | /* The real-time thread program. Doesn't have to be the same for | 41 | /* The real-time thread program. Doesn't have to be the same for |
@@ -45,7 +47,7 @@ void* rt_thread(void *tcontext); | |||
45 | * Returns 1 -> task should exit. | 47 | * Returns 1 -> task should exit. |
46 | * 0 -> task should continue. | 48 | * 0 -> task should continue. |
47 | */ | 49 | */ |
48 | int job(void); | 50 | int job(struct thread_context *tcx); |
49 | 51 | ||
50 | 52 | ||
51 | /* Catch errors. | 53 | /* Catch errors. |
@@ -97,6 +99,8 @@ int main(int argc, char** argv) | |||
97 | */ | 99 | */ |
98 | for (i = 0; i < NUM_THREADS; i++) { | 100 | for (i = 0; i < NUM_THREADS; i++) { |
99 | ctx[i].id = i; | 101 | ctx[i].id = i; |
102 | ctx[i].cpu = 0; | ||
103 | ctx[i].job_no = 0; | ||
100 | pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i)); | 104 | pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i)); |
101 | } | 105 | } |
102 | 106 | ||
@@ -125,6 +129,7 @@ void* rt_thread(void *tcontext) | |||
125 | int do_exit; | 129 | int do_exit; |
126 | struct thread_context *ctx = (struct thread_context *) tcontext; | 130 | struct thread_context *ctx = (struct thread_context *) tcontext; |
127 | struct rt_task param; | 131 | struct rt_task param; |
132 | int ret; | ||
128 | 133 | ||
129 | /* Set up task parameters */ | 134 | /* Set up task parameters */ |
130 | init_rt_task_param(¶m); | 135 | init_rt_task_param(¶m); |
@@ -157,6 +162,12 @@ void* rt_thread(void *tcontext) | |||
157 | * where CPU ranges from 0 to "Number of CPUs" - 1 before calling | 162 | * where CPU ranges from 0 to "Number of CPUs" - 1 before calling |
158 | * set_rt_task_param(). | 163 | * set_rt_task_param(). |
159 | */ | 164 | */ |
165 | param.cpu = ctx->cpu; | ||
166 | ret = be_migrate_to_cpu(ctx->cpu); | ||
167 | if (ret < 0) { | ||
168 | printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu); | ||
169 | return NULL; | ||
170 | } | ||
160 | CALL( set_rt_task_param(gettid(), ¶m) ); | 171 | CALL( set_rt_task_param(gettid(), ¶m) ); |
161 | 172 | ||
162 | /***** | 173 | /***** |
@@ -176,7 +187,7 @@ void* rt_thread(void *tcontext) | |||
176 | /* Wait until the next job is released. */ | 187 | /* Wait until the next job is released. */ |
177 | sleep_next_period(); | 188 | sleep_next_period(); |
178 | /* Invoke job. */ | 189 | /* Invoke job. */ |
179 | do_exit = job(); | 190 | do_exit = job(ctx); |
180 | } while (!do_exit); | 191 | } while (!do_exit); |
181 | 192 | ||
182 | 193 | ||
@@ -192,10 +203,13 @@ void* rt_thread(void *tcontext) | |||
192 | 203 | ||
193 | 204 | ||
194 | 205 | ||
195 | int job(void) | 206 | int job(struct thread_context *tcx) |
196 | { | 207 | { |
197 | /* Do real-time calculation. */ | 208 | /* Do real-time calculation. */ |
198 | 209 | printf("Job executinig\n"); | |
210 | tcx->job_no++; | ||
211 | if (tcx->job_no == 5) | ||
212 | return 1; | ||
199 | /* Don't exit. */ | 213 | /* Don't exit. */ |
200 | return 0; | 214 | return 0; |
201 | } | 215 | } |
diff --git a/bin/mc2spin.c b/bin/mc2spin.c index 1ef3082..25b1c58 100644 --- a/bin/mc2spin.c +++ b/bin/mc2spin.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <sys/time.h> | 1 | #include <sys/time.h> |
2 | #include <sys/mman.h> | ||
2 | 3 | ||
3 | #include <stdio.h> | 4 | #include <stdio.h> |
4 | #include <stdlib.h> | 5 | #include <stdlib.h> |
@@ -12,7 +13,11 @@ | |||
12 | #include "litmus.h" | 13 | #include "litmus.h" |
13 | #include "common.h" | 14 | #include "common.h" |
14 | 15 | ||
16 | #define PAGE_SIZE 4096 | ||
17 | #define NUM_ITEMS 8192 | ||
15 | 18 | ||
19 | int *pages; | ||
20 | unsigned long *access_order; | ||
16 | 21 | ||
17 | static void usage(char *error) { | 22 | static void usage(char *error) { |
18 | fprintf(stderr, "Error: %s\n", error); | 23 | fprintf(stderr, "Error: %s\n", error); |
@@ -104,12 +109,42 @@ static void get_exec_times(const char *file, const int column, | |||
104 | static int num[NUMS]; | 109 | static int num[NUMS]; |
105 | static char* progname; | 110 | static char* progname; |
106 | 111 | ||
112 | static int randrange(const int max) | ||
113 | { | ||
114 | return (rand() / (RAND_MAX / max + 1)); | ||
115 | } | ||
116 | |||
117 | static void sattolo(unsigned long *items, const unsigned long len) | ||
118 | { | ||
119 | unsigned long i; | ||
120 | /* first set up 0, 1, ..., n - 1 */ | ||
121 | for (i = 0; i < len; i++) | ||
122 | items[i] = i; | ||
123 | /* note: i is now n */ | ||
124 | while (1 < i--) { | ||
125 | /* 0 <= j < i */ | ||
126 | int t, j = randrange(i); | ||
127 | t = items[i]; | ||
128 | items[i] = items[j]; | ||
129 | items[j] = t; | ||
130 | } | ||
131 | } | ||
132 | |||
107 | static int loop_once(void) | 133 | static int loop_once(void) |
108 | { | 134 | { |
109 | int i, j = 0; | 135 | int i, j = 0; |
110 | for (i = 0; i < NUMS; i++) | 136 | for (i = 0; i < NUMS; i++) |
111 | j += num[i]++; | 137 | j += num[i]++; |
112 | return j; | 138 | return j; |
139 | /* | ||
140 | int i, tmp; | ||
141 | for (i = 0; i < NUM_ITEMS; i++) { | ||
142 | tmp = pages[access_order[i]]; | ||
143 | if (access_order[i] % 3 == 0) | ||
144 | pages[access_order[i]] = i+tmp; | ||
145 | } | ||
146 | return 1; | ||
147 | */ | ||
113 | } | 148 | } |
114 | 149 | ||
115 | static int loop_for(double exec_time, double emergency_exit) | 150 | static int loop_for(double exec_time, double emergency_exit) |
@@ -138,11 +173,11 @@ static int loop_for(double exec_time, double emergency_exit) | |||
138 | } | 173 | } |
139 | 174 | ||
140 | 175 | ||
141 | static void debug_delay_loop(void) | 176 | static void debug_delay_loop(int count) |
142 | { | 177 | { |
143 | double start, end, delay; | 178 | double start, end, delay; |
144 | 179 | ||
145 | while (1) { | 180 | while (count--) { |
146 | for (delay = 0.5; delay > 0.01; delay -= 0.01) { | 181 | for (delay = 0.5; delay > 0.01; delay -= 0.01) { |
147 | start = wctime(); | 182 | start = wctime(); |
148 | loop_for(delay, 0); | 183 | loop_for(delay, 0); |
@@ -249,7 +284,7 @@ int main(int argc, char** argv) | |||
249 | lt_t hyperperiod; | 284 | lt_t hyperperiod; |
250 | lt_t budget; | 285 | lt_t budget; |
251 | double wcet_ms, period_ms, hyperperiod_ms, budget_ms; | 286 | double wcet_ms, period_ms, hyperperiod_ms, budget_ms; |
252 | unsigned int priority = LITMUS_LOWEST_PRIORITY; | 287 | unsigned int priority = LITMUS_NO_PRIORITY; |
253 | int migrate = 0; | 288 | int migrate = 0; |
254 | int cluster = 0; | 289 | int cluster = 0; |
255 | int opt; | 290 | int opt; |
@@ -266,7 +301,7 @@ int main(int argc, char** argv) | |||
266 | struct rt_task param; | 301 | struct rt_task param; |
267 | struct mc2_task mc2_param; | 302 | struct mc2_task mc2_param; |
268 | struct reservation_config config; | 303 | struct reservation_config config; |
269 | int res_type = SPORADIC_POLLING; | 304 | int res_type = PERIODIC_POLLING; |
270 | int n_str, num_int = 0; | 305 | int n_str, num_int = 0; |
271 | 306 | ||
272 | int verbose = 0; | 307 | int verbose = 0; |
@@ -284,7 +319,7 @@ int main(int argc, char** argv) | |||
284 | /* default for reservation */ | 319 | /* default for reservation */ |
285 | config.id = 0; | 320 | config.id = 0; |
286 | config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */ | 321 | config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */ |
287 | config.cpu = 0; | 322 | config.cpu = -1; |
288 | 323 | ||
289 | mc2_param.crit = CRIT_LEVEL_C; | 324 | mc2_param.crit = CRIT_LEVEL_C; |
290 | 325 | ||
@@ -346,14 +381,10 @@ int main(int argc, char** argv) | |||
346 | break; | 381 | break; |
347 | case 'm': | 382 | case 'm': |
348 | mc2_param.crit = atoi(optarg); | 383 | mc2_param.crit = atoi(optarg); |
349 | if (mc2_param.crit == CRIT_LEVEL_A) { | 384 | if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) { |
350 | res_type = TABLE_DRIVEN; | ||
351 | } | ||
352 | else if (mc2_param.crit == CRIT_LEVEL_B) { | ||
353 | res_type = PERIODIC_POLLING; | ||
354 | } | ||
355 | else | ||
356 | usage("Invalid criticality level."); | 385 | usage("Invalid criticality level."); |
386 | } | ||
387 | res_type = PERIODIC_POLLING; | ||
357 | break; | 388 | break; |
358 | case 'h': | 389 | case 'h': |
359 | hyperperiod_ms = atof(optarg); | 390 | hyperperiod_ms = atof(optarg); |
@@ -362,14 +393,7 @@ int main(int argc, char** argv) | |||
362 | budget_ms = atof(optarg); | 393 | budget_ms = atof(optarg); |
363 | break; | 394 | break; |
364 | case 'i': | 395 | case 'i': |
365 | n_str = strlen(optarg); | 396 | config.priority = atoi(optarg); |
366 | while(n_str--) { | ||
367 | if (optarg[n_str] == ',') | ||
368 | num_int++; | ||
369 | } | ||
370 | if (!num_int) | ||
371 | usage("Bad argument."); | ||
372 | config.table_driven_params.intervals = parse_td_intervals(num_int, optarg, &config.table_driven_params.num_intervals); | ||
373 | break; | 397 | break; |
374 | case ':': | 398 | case ':': |
375 | usage("Argument missing."); | 399 | usage("Argument missing."); |
@@ -382,10 +406,13 @@ int main(int argc, char** argv) | |||
382 | } | 406 | } |
383 | 407 | ||
384 | if (test_loop) { | 408 | if (test_loop) { |
385 | debug_delay_loop(); | 409 | debug_delay_loop(1); |
386 | return 0; | 410 | return 0; |
387 | } | 411 | } |
388 | 412 | ||
413 | if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY) | ||
414 | usage("Bad criticailty level or priority"); | ||
415 | |||
389 | srand(getpid()); | 416 | srand(getpid()); |
390 | 417 | ||
391 | if (file) { | 418 | if (file) { |
@@ -440,20 +467,15 @@ int main(int argc, char** argv) | |||
440 | config.id = gettid(); | 467 | config.id = gettid(); |
441 | 468 | ||
442 | if (hyperperiod%period != 0 ) { | 469 | if (hyperperiod%period != 0 ) { |
443 | bail_out("hyperperiod must be multiple of period"); | 470 | ;//bail_out("hyperperiod must be multiple of period"); |
444 | } | 471 | } |
445 | 472 | ||
446 | if (mc2_param.crit == CRIT_LEVEL_A) { | 473 | config.polling_params.budget = budget; |
447 | config.table_driven_params.major_cycle_length = period; | 474 | config.polling_params.period = period; |
448 | } | 475 | config.polling_params.offset = 0; |
449 | else if (mc2_param.crit == CRIT_LEVEL_B) { | 476 | config.polling_params.relative_deadline = 0; |
450 | config.polling_params.budget = budget; | 477 | if (config.polling_params.budget > config.polling_params.period) { |
451 | config.polling_params.period = period; | 478 | usage("The budget must not exceed the period."); |
452 | config.polling_params.offset = 0; | ||
453 | config.polling_params.relative_deadline = 0; | ||
454 | if (config.polling_params.budget > config.polling_params.period) { | ||
455 | usage("The budget must not exceed the period."); | ||
456 | } | ||
457 | } | 479 | } |
458 | 480 | ||
459 | /* create a reservation */ | 481 | /* create a reservation */ |
@@ -474,23 +496,33 @@ int main(int argc, char** argv) | |||
474 | param.cpu = gettid(); | 496 | param.cpu = gettid(); |
475 | } | 497 | } |
476 | ret = set_rt_task_param(gettid(), ¶m); | 498 | ret = set_rt_task_param(gettid(), ¶m); |
499 | //printf("SET_RT_TASK\n"); | ||
477 | if (ret < 0) | 500 | if (ret < 0) |
478 | bail_out("could not setup rt task params"); | 501 | bail_out("could not setup rt task params"); |
479 | 502 | ||
480 | mc2_param.pid = gettid(); | 503 | mc2_param.res_id = gettid(); |
481 | mc2_param.hyperperiod = hyperperiod; | ||
482 | ret = set_mc2_task_param(gettid(), &mc2_param); | 504 | ret = set_mc2_task_param(gettid(), &mc2_param); |
505 | //printf("SET_MC2_TASK\n"); | ||
483 | if (ret < 0) | 506 | if (ret < 0) |
484 | bail_out("could not setup mc2 task params"); | 507 | bail_out("could not setup mc2 task params"); |
508 | |||
509 | pages = (int*)malloc(sizeof(int)*NUM_ITEMS); | ||
510 | access_order = (unsigned long*)malloc(sizeof(unsigned long)*NUM_ITEMS); | ||
511 | sattolo(access_order, NUM_ITEMS); | ||
512 | |||
485 | init_litmus(); | 513 | init_litmus(); |
514 | printf("CALL\n"); | ||
515 | set_page_color(config.cpu); | ||
516 | printf("CALL\n"); | ||
486 | 517 | ||
518 | //printf("INIT_LITMUS\n"); | ||
487 | start = wctime(); | 519 | start = wctime(); |
488 | ret = task_mode(LITMUS_RT_TASK); | 520 | ret = task_mode(LITMUS_RT_TASK); |
521 | //printf("TASK_MODE\n"); | ||
489 | if (ret != 0) | 522 | if (ret != 0) |
490 | bail_out("could not become RT task"); | 523 | bail_out("could not become RT task"); |
491 | 524 | ||
492 | if (protocol >= 0) { | 525 | if (protocol >= 0) { |
493 | /* open reference to semaphore */ | ||
494 | lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster); | 526 | lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster); |
495 | if (lock_od < 0) { | 527 | if (lock_od < 0) { |
496 | perror("litmus_open_lock"); | 528 | perror("litmus_open_lock"); |
@@ -500,6 +532,7 @@ int main(int argc, char** argv) | |||
500 | 532 | ||
501 | 533 | ||
502 | if (wait) { | 534 | if (wait) { |
535 | //printf("BEFORE WAIT\n"); | ||
503 | ret = wait_for_ts_release(); | 536 | ret = wait_for_ts_release(); |
504 | if (ret != 0) | 537 | if (ret != 0) |
505 | bail_out("wait_for_ts_release()"); | 538 | bail_out("wait_for_ts_release()"); |
@@ -507,9 +540,7 @@ int main(int argc, char** argv) | |||
507 | } | 540 | } |
508 | 541 | ||
509 | if (file) { | 542 | if (file) { |
510 | /* use times read from the CSV file */ | ||
511 | for (cur_job = 0; cur_job < num_jobs; ++cur_job) { | 543 | for (cur_job = 0; cur_job < num_jobs; ++cur_job) { |
512 | /* convert job's length to seconds */ | ||
513 | job(exec_times[cur_job] * 0.001 * scale, | 544 | job(exec_times[cur_job] * 0.001 * scale, |
514 | start + duration, | 545 | start + duration, |
515 | lock_od, cs_length * 0.001); | 546 | lock_od, cs_length * 0.001); |
@@ -521,11 +552,10 @@ int main(int argc, char** argv) | |||
521 | printf("rtspin/%d:%u @ %.4fms\n", gettid(), | 552 | printf("rtspin/%d:%u @ %.4fms\n", gettid(), |
522 | job_no, (wctime() - start) * 1000); | 553 | job_no, (wctime() - start) * 1000); |
523 | } | 554 | } |
524 | /* convert to seconds and scale */ | ||
525 | } while (job(wcet_ms * 0.001 * scale, start + duration, | 555 | } while (job(wcet_ms * 0.001 * scale, start + duration, |
526 | lock_od, cs_length * 0.001)); | 556 | lock_od, cs_length * 0.001)); |
527 | } | 557 | } |
528 | 558 | printf("BEFORE BACK_TASK\n"); | |
529 | ret = task_mode(BACKGROUND_TASK); | 559 | ret = task_mode(BACKGROUND_TASK); |
530 | if (ret != 0) | 560 | if (ret != 0) |
531 | bail_out("could not become regular task (huh?)"); | 561 | bail_out("could not become regular task (huh?)"); |
@@ -534,8 +564,11 @@ int main(int argc, char** argv) | |||
534 | free(exec_times); | 564 | free(exec_times); |
535 | 565 | ||
536 | reservation_destroy(gettid(), config.cpu); | 566 | reservation_destroy(gettid(), config.cpu); |
537 | if (mc2_param.crit == CRIT_LEVEL_A) { | 567 | |
538 | free(config.table_driven_params.intervals); | 568 | printf("CALL\n"); |
539 | } | 569 | set_page_color(config.cpu); |
570 | printf("CALL\n"); | ||
571 | free(pages); | ||
572 | free(access_order); | ||
540 | return 0; | 573 | return 0; |
541 | } | 574 | } |
diff --git a/bin/mttest.c b/bin/mttest.c new file mode 100644 index 0000000..e2813e6 --- /dev/null +++ b/bin/mttest.c | |||
@@ -0,0 +1,256 @@ | |||
1 | /* based_mt_task.c -- A basic multi-threaded real-time task skeleton. | ||
2 | * | ||
3 | * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT | ||
4 | * real-time task. Familiarity with the single threaded example (base_task.c) | ||
5 | * is assumed. | ||
6 | * | ||
7 | * Currently, liblitmus still lacks automated support for real-time | ||
8 | * tasks, but internaly it is thread-safe, and thus can be used together | ||
9 | * with pthreads. | ||
10 | */ | ||
11 | |||
12 | #include <stdio.h> | ||
13 | #include <stdlib.h> | ||
14 | #include <string.h> | ||
15 | #include <limits.h> | ||
16 | #include <sys/mman.h> | ||
17 | #include <sys/stat.h> | ||
18 | #include <fcntl.h> | ||
19 | /* Include gettid() */ | ||
20 | #include <sys/types.h> | ||
21 | |||
22 | /* Include threading support. */ | ||
23 | #include <pthread.h> | ||
24 | |||
25 | /* Include the LITMUS^RT API.*/ | ||
26 | #include "litmus.h" | ||
27 | #include "color_shm.h" | ||
28 | |||
29 | #define PERIOD 100 | ||
30 | #define RELATIVE_DEADLINE 100 | ||
31 | #define EXEC_COST 10 | ||
32 | |||
33 | /* Let's create 10 threads in the example, | ||
34 | * for a total utilization of 1. | ||
35 | */ | ||
36 | #define NUM_THREADS 2 | ||
37 | |||
38 | /* The information passed to each thread. Could be anything. */ | ||
39 | struct thread_context { | ||
40 | int id; | ||
41 | int cpu; | ||
42 | int job_no; | ||
43 | char* shm; | ||
44 | }; | ||
45 | |||
46 | /* The real-time thread program. Doesn't have to be the same for | ||
47 | * all threads. Here, we only have one that will invoke job(). | ||
48 | */ | ||
49 | void* rt_thread(void *tcontext); | ||
50 | |||
51 | /* Declare the periodically invoked job. | ||
52 | * Returns 1 -> task should exit. | ||
53 | * 0 -> task should continue. | ||
54 | */ | ||
55 | int job(struct thread_context *tcx); | ||
56 | |||
57 | |||
58 | /* Catch errors. | ||
59 | */ | ||
60 | #define CALL( exp ) do { \ | ||
61 | int ret; \ | ||
62 | ret = exp; \ | ||
63 | if (ret != 0) \ | ||
64 | fprintf(stderr, "%s failed: %m\n", #exp);\ | ||
65 | else \ | ||
66 | fprintf(stderr, "%s ok.\n", #exp); \ | ||
67 | } while (0) | ||
68 | |||
69 | |||
70 | /* Basic setup is the same as in the single-threaded example. However, | ||
71 | * we do some thread initiliazation first before invoking the job. | ||
72 | */ | ||
73 | int main(int argc, char** argv) | ||
74 | { | ||
75 | int i, ret, fd; | ||
76 | struct thread_context ctx[NUM_THREADS]; | ||
77 | pthread_t task[NUM_THREADS]; | ||
78 | char *shm; | ||
79 | struct ioctl_cmd shm_info; | ||
80 | /* The task is in background mode upon startup. */ | ||
81 | |||
82 | |||
83 | /***** | ||
84 | * 1) Command line paramter parsing would be done here. | ||
85 | */ | ||
86 | |||
87 | |||
88 | |||
89 | /***** | ||
90 | * 2) Work environment (e.g., global data structures, file data, etc.) would | ||
91 | * be setup here. | ||
92 | */ | ||
93 | fd = open("/dev/litmus/color_shm", O_RDWR); | ||
94 | if (fd < 0) { | ||
95 | printf("Device open error.\n"); | ||
96 | return -1; | ||
97 | } | ||
98 | |||
99 | shm_info.color = 0x0000cccc; | ||
100 | shm_info.bank = 0x000000ac; | ||
101 | |||
102 | ret = ioctl(fd, SET_COLOR_SHM_CMD, &shm_info); | ||
103 | |||
104 | shm = mmap(NULL, 6000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | ||
105 | if (shm == MAP_FAILED) { | ||
106 | printf("mmap failed.\n"); | ||
107 | return -1; | ||
108 | } | ||
109 | |||
110 | mlockall(MCL_CURRENT | MCL_FUTURE); | ||
111 | /***** | ||
112 | * 3) Initialize LITMUS^RT. | ||
113 | * Task parameters will be specified per thread. | ||
114 | */ | ||
115 | init_litmus(); | ||
116 | |||
117 | |||
118 | /***** | ||
119 | * 4) Launch threads. | ||
120 | */ | ||
121 | for (i = 0; i < NUM_THREADS; i++) { | ||
122 | ctx[i].id = i; | ||
123 | ctx[i].cpu = 0; | ||
124 | ctx[i].job_no = 0; | ||
125 | ctx[i].shm = shm; | ||
126 | pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i)); | ||
127 | } | ||
128 | |||
129 | |||
130 | /***** | ||
131 | * 5) Wait for RT threads to terminate. | ||
132 | */ | ||
133 | for (i = 0; i < NUM_THREADS; i++) | ||
134 | pthread_join(task[i], NULL); | ||
135 | |||
136 | |||
137 | /***** | ||
138 | * 6) Clean up, maybe print results and stats, and exit. | ||
139 | */ | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | |||
144 | |||
145 | /* A real-time thread is very similar to the main function of a single-threaded | ||
146 | * real-time app. Notice, that init_rt_thread() is called to initialized per-thread | ||
147 | * data structures of the LITMUS^RT user space libary. | ||
148 | */ | ||
149 | void* rt_thread(void *tcontext) | ||
150 | { | ||
151 | int do_exit; | ||
152 | struct thread_context *ctx = (struct thread_context *) tcontext; | ||
153 | struct rt_task param; | ||
154 | int ret; | ||
155 | |||
156 | /* Set up task parameters */ | ||
157 | init_rt_task_param(¶m); | ||
158 | param.exec_cost = ms2ns(EXEC_COST); | ||
159 | param.period = ms2ns(PERIOD); | ||
160 | param.relative_deadline = ms2ns(RELATIVE_DEADLINE*(ctx->id+1)); | ||
161 | |||
162 | /* What to do in the case of budget overruns? */ | ||
163 | param.budget_policy = NO_ENFORCEMENT; | ||
164 | |||
165 | /* The task class parameter is ignored by most plugins. */ | ||
166 | param.cls = RT_CLASS_SOFT; | ||
167 | |||
168 | /* The priority parameter is only used by fixed-priority plugins. */ | ||
169 | param.priority = LITMUS_LOWEST_PRIORITY; | ||
170 | |||
171 | /* Make presence visible. */ | ||
172 | printf("RT Thread %d active.\n", ctx->id); | ||
173 | |||
174 | /***** | ||
175 | * 1) Initialize real-time settings. | ||
176 | */ | ||
177 | CALL( init_rt_thread() ); | ||
178 | |||
179 | /* To specify a partition, do | ||
180 | * | ||
181 | * param.cpu = CPU; | ||
182 | * be_migrate_to(CPU); | ||
183 | * | ||
184 | * where CPU ranges from 0 to "Number of CPUs" - 1 before calling | ||
185 | * set_rt_task_param(). | ||
186 | */ | ||
187 | param.cpu = ctx->cpu; | ||
188 | ret = be_migrate_to_cpu(ctx->cpu); | ||
189 | if (ret < 0) { | ||
190 | printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu); | ||
191 | return NULL; | ||
192 | } | ||
193 | CALL( set_rt_task_param(gettid(), ¶m) ); | ||
194 | |||
195 | /***** | ||
196 | * 2) Transition to real-time mode. | ||
197 | */ | ||
198 | CALL( task_mode(LITMUS_RT_TASK) ); | ||
199 | |||
200 | /* The task is now executing as a real-time task if the call didn't fail. | ||
201 | */ | ||
202 | |||
203 | |||
204 | |||
205 | /***** | ||
206 | * 3) Invoke real-time jobs. | ||
207 | */ | ||
208 | do { | ||
209 | /* Wait until the next job is released. */ | ||
210 | sleep_next_period(); | ||
211 | /* Invoke job. */ | ||
212 | do_exit = job(ctx); | ||
213 | } while (!do_exit); | ||
214 | |||
215 | |||
216 | |||
217 | /***** | ||
218 | * 4) Transition to background mode. | ||
219 | */ | ||
220 | CALL( task_mode(BACKGROUND_TASK) ); | ||
221 | |||
222 | |||
223 | return NULL; | ||
224 | } | ||
225 | |||
226 | |||
227 | |||
228 | int job(struct thread_context *tcx) | ||
229 | { | ||
230 | int i; | ||
231 | char* buf = tcx->shm; | ||
232 | /* Do real-time calculation. */ | ||
233 | printf("Task %d Job %d executinig\n", tcx->id, tcx->job_no); | ||
234 | |||
235 | if (tcx->id == 0) { | ||
236 | printf("WRITE\n"); | ||
237 | for (i=0; i<6000; i++) { | ||
238 | buf[i] = rand()%255; | ||
239 | printf("%x ",buf[i]); | ||
240 | } | ||
241 | printf("\n"); | ||
242 | } else if (tcx->id == 1) { | ||
243 | printf("READ\n"); | ||
244 | for (i=0; i<6000; i++) { | ||
245 | char t = buf[i]; | ||
246 | printf("%x ", t); | ||
247 | } | ||
248 | printf("\n"); | ||
249 | } | ||
250 | //test_call(0); | ||
251 | tcx->job_no++; | ||
252 | if (tcx->job_no == 1) | ||
253 | return 1; | ||
254 | /* Don't exit. */ | ||
255 | return 0; | ||
256 | } | ||
diff --git a/bin/rtspin.c b/bin/rtspin.c index ea7f192..fd57c45 100644 --- a/bin/rtspin.c +++ b/bin/rtspin.c | |||
@@ -6,7 +6,7 @@ | |||
6 | #include <time.h> | 6 | #include <time.h> |
7 | #include <string.h> | 7 | #include <string.h> |
8 | #include <assert.h> | 8 | #include <assert.h> |
9 | 9 | #include <limits.h> | |
10 | 10 | ||
11 | #include "litmus.h" | 11 | #include "litmus.h" |
12 | #include "common.h" | 12 | #include "common.h" |
@@ -191,7 +191,7 @@ int main(int argc, char** argv) | |||
191 | lt_t wcet; | 191 | lt_t wcet; |
192 | lt_t period; | 192 | lt_t period; |
193 | double wcet_ms, period_ms; | 193 | double wcet_ms, period_ms; |
194 | unsigned int priority = LITMUS_LOWEST_PRIORITY; | 194 | unsigned int priority = LITMUS_NO_PRIORITY; |
195 | int migrate = 0; | 195 | int migrate = 0; |
196 | int cluster = 0; | 196 | int cluster = 0; |
197 | int reservation = -1; | 197 | int reservation = -1; |
diff --git a/include/color_shm.h b/include/color_shm.h new file mode 100644 index 0000000..a95ffde --- /dev/null +++ b/include/color_shm.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <sys/ioctl.h> | ||
2 | #include <fcntl.h> | ||
3 | |||
4 | #define SHM_MAJOR 240 | ||
5 | |||
6 | struct ioctl_cmd { | ||
7 | unsigned int color; | ||
8 | unsigned int bank; | ||
9 | }; | ||
10 | |||
11 | #define SET_COLOR_SHM_CMD \ | ||
12 | _IOW(SHM_MAJOR, 0x1, struct ioctl_cmd) | ||
13 | |||
diff --git a/include/litmus.h b/include/litmus.h index b90a83d..e96a4a6 100644 --- a/include/litmus.h +++ b/include/litmus.h | |||
@@ -46,7 +46,7 @@ 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 6 | 49 | #define SCHED_LITMUS 7 |
50 | 50 | ||
51 | /** | 51 | /** |
52 | * Initialise a real-time task param struct | 52 | * Initialise a real-time task param struct |
@@ -424,6 +424,10 @@ int reservation_destroy(unsigned int reservation_id, int cpu); | |||
424 | 424 | ||
425 | int set_mc2_task_param(pid_t pid, struct mc2_task* param); | 425 | int set_mc2_task_param(pid_t pid, struct mc2_task* param); |
426 | 426 | ||
427 | int set_page_color(int cpu); | ||
428 | |||
429 | int test_call(unsigned int param); | ||
430 | |||
427 | #ifdef __cplusplus | 431 | #ifdef __cplusplus |
428 | } | 432 | } |
429 | #endif | 433 | #endif |
diff --git a/src/syscalls.c b/src/syscalls.c index b07d135..ab064ad 100644 --- a/src/syscalls.c +++ b/src/syscalls.c | |||
@@ -100,4 +100,14 @@ int reservation_destroy(unsigned int reservation_id, int cpu) | |||
100 | int set_mc2_task_param(pid_t pid, struct mc2_task *param) | 100 | int set_mc2_task_param(pid_t pid, struct mc2_task *param) |
101 | { | 101 | { |
102 | return syscall(__NR_set_mc2_task_param, pid, param); | 102 | return syscall(__NR_set_mc2_task_param, pid, param); |
103 | } \ No newline at end of file | 103 | } |
104 | |||
105 | int set_page_color(int cpu) | ||
106 | { | ||
107 | return syscall(__NR_set_page_color, cpu); | ||
108 | } | ||
109 | |||
110 | int test_call(unsigned int param) | ||
111 | { | ||
112 | return syscall(__NR_test_call, param); | ||
113 | } | ||