diff options
-rw-r--r-- | Makefile | 13 | ||||
-rw-r--r-- | bin/color.c | 2 | ||||
-rw-r--r-- | bin/colorbench.c | 37 | ||||
-rw-r--r-- | bin/colorspin.c | 99 | ||||
-rw-r--r-- | bin/colortest.c | 1 | ||||
-rw-r--r-- | bin/perfcounters.c | 27 | ||||
-rw-r--r-- | bin/rtspin.c | 222 | ||||
-rw-r--r-- | bin/singlepage.c | 158 | ||||
-rw-r--r-- | include/perfcounters.h | 10 | ||||
-rw-r--r-- | include/spin_common.h | 42 | ||||
-rw-r--r-- | src/spin_common.c | 235 |
11 files changed, 614 insertions, 232 deletions
@@ -12,7 +12,7 @@ host-arch := $(shell uname -m | \ | |||
12 | ARCH ?= ${host-arch} | 12 | ARCH ?= ${host-arch} |
13 | 13 | ||
14 | # LITMUS_KERNEL -- where to find the litmus kernel? | 14 | # LITMUS_KERNEL -- where to find the litmus kernel? |
15 | LITMUS_KERNEL ?= ../backup-litmus-rt | 15 | LITMUS_KERNEL ?= ../litmus-rt |
16 | 16 | ||
17 | 17 | ||
18 | # ############################################################################## | 18 | # ############################################################################## |
@@ -72,7 +72,8 @@ AR := ${CROSS_COMPILE}${AR} | |||
72 | 72 | ||
73 | all = lib ${rt-apps} | 73 | all = lib ${rt-apps} |
74 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ | 74 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ |
75 | base_mt_task runtests colortest colorbench testcounters bespin | 75 | base_mt_task runtests colortest colorbench testcounters \ |
76 | colorspin singlepage | ||
76 | 77 | ||
77 | .PHONY: all lib clean dump-config TAGS tags cscope help | 78 | .PHONY: all lib clean dump-config TAGS tags cscope help |
78 | 79 | ||
@@ -213,6 +214,9 @@ lib-rt_launch = -lgsl -lgslcblas | |||
213 | obj-rtspin = rtspin.o common.o | 214 | obj-rtspin = rtspin.o common.o |
214 | lib-rtspin = -lrt -lgsl -lgslcblas | 215 | lib-rtspin = -lrt -lgsl -lgslcblas |
215 | 216 | ||
217 | obj-colorspin = colorspin.o common.o | ||
218 | lib-colorspin = -lrt -lgsl -lgslcblas | ||
219 | |||
216 | obj-rtspin.ovh = rtspin.ovh.o common.o | 220 | obj-rtspin.ovh = rtspin.ovh.o common.o |
217 | lib-rtspin.ovh = -lrt -lgsl -lgslcblas | 221 | lib-rtspin.ovh = -lrt -lgsl -lgslcblas |
218 | 222 | ||
@@ -236,6 +240,9 @@ lib-colortest = -static | |||
236 | obj-colorbench = colorbench.o color.o perfcounters.o common.o | 240 | obj-colorbench = colorbench.o color.o perfcounters.o common.o |
237 | lib-colorbench = -lpthread -lrt -lgsl -lgslcblas | 241 | lib-colorbench = -lpthread -lrt -lgsl -lgslcblas |
238 | 242 | ||
243 | obj-singlepage = singlepage.o color.o perfcounters.o common.o | ||
244 | lib-singlepage = -lgsl -lgslcblas | ||
245 | |||
239 | obj-testcounters = testcounters.o | 246 | obj-testcounters = testcounters.o |
240 | lib-testcounters = | 247 | lib-testcounters = |
241 | 248 | ||
@@ -244,7 +251,7 @@ lib-testcounters = | |||
244 | 251 | ||
245 | .SECONDEXPANSION: | 252 | .SECONDEXPANSION: |
246 | ${rt-apps}: $${obj-$$@} liblitmus.a | 253 | ${rt-apps}: $${obj-$$@} liblitmus.a |
247 | $(CC) -o $@ $(LDFLAGS) ${ldf-$@} $(filter-out liblitmus.a,$+) $(LOADLIBS) $(LDLIBS) ${liblitmus-flags} ${lib-$@} | 254 | $(CC) -o $@ $(LDFLAGS) ${ldf-$@} $(filter-out liblitmus.a,$+) $(LOADLIBS) $(LDLIBS) ${lib-$@} ${liblitmus-flags} |
248 | 255 | ||
249 | # ############################################################################## | 256 | # ############################################################################## |
250 | # Dependency resolution. | 257 | # Dependency resolution. |
diff --git a/bin/color.c b/bin/color.c index 2ec97a4..c1753a4 100644 --- a/bin/color.c +++ b/bin/color.c | |||
@@ -21,7 +21,7 @@ static int map_file(const char* filename, void **addr, size_t size) | |||
21 | if (fd >= 0) { | 21 | if (fd >= 0) { |
22 | *addr = mmap(NULL, size, | 22 | *addr = mmap(NULL, size, |
23 | PROT_READ | PROT_WRITE, | 23 | PROT_READ | PROT_WRITE, |
24 | MAP_PRIVATE, | 24 | MAP_SHARED, |
25 | fd, 0); | 25 | fd, 0); |
26 | if (*addr == MAP_FAILED) | 26 | if (*addr == MAP_FAILED) |
27 | error = -1; | 27 | error = -1; |
diff --git a/bin/colorbench.c b/bin/colorbench.c index c91b731..ac0c01a 100644 --- a/bin/colorbench.c +++ b/bin/colorbench.c | |||
@@ -18,17 +18,25 @@ | |||
18 | #define DEBUG 1 | 18 | #define DEBUG 1 |
19 | #define NR_LOOPS 10 | 19 | #define NR_LOOPS 10 |
20 | 20 | ||
21 | #if 0 | ||
21 | /* Pound */ | 22 | /* Pound */ |
22 | #define NR_CPUS 4 | 23 | #define NR_CPUS 4 |
23 | #define CACHE_SIZE_MB 8 | 24 | #define CACHE_SIZE_MB 8 |
24 | #define ASSOC 16 | 25 | #define ASSOC 16 |
25 | #define LINE_SIZE 64 | 26 | #define LINE_SIZE 64 |
27 | #endif | ||
28 | |||
29 | /* Flare */ | ||
30 | #define NR_CPUS 1 | ||
31 | #define CACHE_SIZE_MB 3 | ||
32 | #define ASSOC 12 | ||
33 | #define LINE_SIZE 64 | ||
26 | 34 | ||
27 | #define CACHE_SIZE (CACHE_SIZE_MB * 1024 * 1024) | 35 | #define CACHE_SIZE (CACHE_SIZE_MB * 1024 * 1024) |
28 | #define TOTAL_COLORS (CACHE_SIZE / ASSOC / PAGE_SIZE) | 36 | #define TOTAL_COLORS (CACHE_SIZE / ASSOC / PAGE_SIZE) |
29 | 37 | ||
30 | /* number of colors we actually use */ | 38 | /* number of colors we actually use (cannot be zero) */ |
31 | #define USE_COLORS (TOTAL_COLORS >> color_shift) | 39 | #define USE_COLORS ({int v = TOTAL_COLORS >> color_shift; (v) ? v : 1; }) |
32 | 40 | ||
33 | /* how many adjacent pages of the same color we need to allocate */ | 41 | /* how many adjacent pages of the same color we need to allocate */ |
34 | #define CONTIG_COLORS (ARENA_PAGES / USE_COLORS) | 42 | #define CONTIG_COLORS (ARENA_PAGES / USE_COLORS) |
@@ -76,7 +84,7 @@ static pthread_barrier_t barrier; | |||
76 | static int nr_threads; | 84 | static int nr_threads; |
77 | static int arena_size; | 85 | static int arena_size; |
78 | static int color_shift; | 86 | static int color_shift; |
79 | //static int *page_line_order; | 87 | static int *page_line_order; |
80 | static int *arena_line_order; | 88 | static int *arena_line_order; |
81 | static struct perf_counter perf_counters[NR_CPUS * NR_PERF_COUNTERS]; | 89 | static struct perf_counter perf_counters[NR_CPUS * NR_PERF_COUNTERS]; |
82 | 90 | ||
@@ -138,7 +146,6 @@ void sattolo(int *items, const int len) | |||
138 | * Starting at position 0 in the page_line_order means the cycle ends with 0. | 146 | * Starting at position 0 in the page_line_order means the cycle ends with 0. |
139 | * We use 0 in the arena to signify that we are done reading. | 147 | * We use 0 in the arena to signify that we are done reading. |
140 | */ | 148 | */ |
141 | #if 0 | ||
142 | static void init_arena_page_line_order(int *arena) | 149 | static void init_arena_page_line_order(int *arena) |
143 | { | 150 | { |
144 | int cur_page; | 151 | int cur_page; |
@@ -168,7 +175,8 @@ static void init_arena_page_line_order(int *arena) | |||
168 | } | 175 | } |
169 | } | 176 | } |
170 | } | 177 | } |
171 | #endif | 178 | |
179 | #if 0 | ||
172 | static void init_arena_line_order(int *arena) | 180 | static void init_arena_line_order(int *arena) |
173 | { | 181 | { |
174 | int cur_line; | 182 | int cur_line; |
@@ -184,6 +192,7 @@ static void init_arena_line_order(int *arena) | |||
184 | arena[idx] = next_idx; | 192 | arena[idx] = next_idx; |
185 | } | 193 | } |
186 | } | 194 | } |
195 | #endif | ||
187 | 196 | ||
188 | static void setup_colors(struct pthread_state *state) | 197 | static void setup_colors(struct pthread_state *state) |
189 | { | 198 | { |
@@ -262,8 +271,8 @@ int thread_init(struct pthread_state *state) | |||
262 | goto out; | 271 | goto out; |
263 | } | 272 | } |
264 | 273 | ||
265 | //init_arena_page_line_order(state->arena); | 274 | init_arena_page_line_order(state->arena); |
266 | init_arena_line_order(state->arena); | 275 | //init_arena_line_order(state->arena); |
267 | 276 | ||
268 | err = mlockall(MCL_CURRENT|MCL_FUTURE); | 277 | err = mlockall(MCL_CURRENT|MCL_FUTURE); |
269 | if (err) | 278 | if (err) |
@@ -405,7 +414,7 @@ int main(int argc, char **argv) | |||
405 | } | 414 | } |
406 | 415 | ||
407 | pthread_state = malloc(nr_threads * sizeof(*pthread_state)); | 416 | pthread_state = malloc(nr_threads * sizeof(*pthread_state)); |
408 | //page_line_order = malloc(PAGE_LINES * sizeof(*page_line_order)); | 417 | page_line_order = malloc(PAGE_LINES * sizeof(*page_line_order)); |
409 | arena_line_order = malloc(ARENA_LINES * sizeof(*arena_line_order)); | 418 | arena_line_order = malloc(ARENA_LINES * sizeof(*arena_line_order)); |
410 | //if (!pthread_state || !page_line_order) { | 419 | //if (!pthread_state || !page_line_order) { |
411 | if (!pthread_state || !arena_line_order) { | 420 | if (!pthread_state || !arena_line_order) { |
@@ -420,9 +429,10 @@ int main(int argc, char **argv) | |||
420 | CHECK(pthread_attr_setdetachstate, &attr, PTHREAD_CREATE_JOINABLE); | 429 | CHECK(pthread_attr_setdetachstate, &attr, PTHREAD_CREATE_JOINABLE); |
421 | CHECK(pthread_barrier_init, &barrier, NULL, nr_threads); | 430 | CHECK(pthread_barrier_init, &barrier, NULL, nr_threads); |
422 | 431 | ||
423 | //sattolo(page_line_order, PAGE_LINES); | 432 | sattolo(page_line_order, PAGE_LINES); |
424 | sattolo(arena_line_order, ARENA_LINES); | 433 | //sattolo(arena_line_order, ARENA_LINES); |
425 | //sequential(page_line_order, PAGE_LINES); | 434 | //sequential(page_line_order, PAGE_LINES); |
435 | //sequential(arena_line_order, PAGE_LINES); | ||
426 | 436 | ||
427 | for (i = 0; i < nr_threads; i++) { | 437 | for (i = 0; i < nr_threads; i++) { |
428 | pthread_state[i].tid = i; | 438 | pthread_state[i].tid = i; |
@@ -447,12 +457,15 @@ int main(int argc, char **argv) | |||
447 | CHECK(pthread_barrier_destroy, &barrier); | 457 | CHECK(pthread_barrier_destroy, &barrier); |
448 | CHECK(pthread_attr_destroy, &attr); | 458 | CHECK(pthread_attr_destroy, &attr); |
449 | 459 | ||
460 | printf("page size: %d\n", PAGE_SIZE); | ||
461 | printf("cache size: %d\n", CACHE_SIZE); | ||
462 | printf("total colors: %d\n", TOTAL_COLORS); | ||
463 | printf("use colors: %d\n", USE_COLORS); | ||
464 | printf("contiguous colors: %d\n", CONTIG_COLORS); | ||
450 | printf("arena size: %d\n", arena_size); | 465 | printf("arena size: %d\n", arena_size); |
451 | printf("color shift: %d\n", color_shift); | 466 | printf("color shift: %d\n", color_shift); |
452 | printf("arena pages: %d\n", ARENA_PAGES); | 467 | printf("arena pages: %d\n", ARENA_PAGES); |
453 | printf("arena lines: %d\n", ARENA_LINES); | 468 | printf("arena lines: %d\n", ARENA_LINES); |
454 | printf("use colors: %d\n", USE_COLORS); | ||
455 | printf("contiguous colors: %d\n", CONTIG_COLORS); | ||
456 | //print_perf_counters(); | 469 | //print_perf_counters(); |
457 | 470 | ||
458 | out: | 471 | out: |
diff --git a/bin/colorspin.c b/bin/colorspin.c new file mode 100644 index 0000000..83a7390 --- /dev/null +++ b/bin/colorspin.c | |||
@@ -0,0 +1,99 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <unistd.h> | ||
3 | #include <assert.h> | ||
4 | #include "spin_common.h" | ||
5 | #include "common.h" | ||
6 | |||
7 | static void usage(char *error) { | ||
8 | fprintf(stderr, "Error: %s\n", error); | ||
9 | fprintf(stderr, | ||
10 | "Usage:\n" | ||
11 | " color_spin [COMMON-OPTS] WCET PERIOD DURATION\n" | ||
12 | " color_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n" | ||
13 | "\n" | ||
14 | "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n" | ||
15 | " [-x COLOR-FILE]\n" | ||
16 | "\n" | ||
17 | "WCET and PERIOD are milliseconds, DURATION is seconds.\n"); | ||
18 | exit(EXIT_FAILURE); | ||
19 | } | ||
20 | |||
21 | static void get_page_colors(const char *file, int *num_colors, | ||
22 | int **colors, int **pages) | ||
23 | { | ||
24 | FILE *fstream; | ||
25 | int ch, line; | ||
26 | *num_colors = 0; | ||
27 | |||
28 | fstream = fopen(file, "r"); | ||
29 | if (!fstream) | ||
30 | bail_out("could not open page color file\n"); | ||
31 | |||
32 | do { | ||
33 | skip_comments(fstream); | ||
34 | ch = skip_to_next_line(fstream); | ||
35 | if (ch != EOF) | ||
36 | ++(*num_colors); | ||
37 | } while (ch != EOF); | ||
38 | |||
39 | if (-1 == fseek(fstream, 0L, SEEK_SET)) | ||
40 | bail_out("rewinding file failed"); | ||
41 | |||
42 | *colors = calloc(*num_colors, sizeof(*colors)); | ||
43 | *pages = calloc(*num_colors, sizeof(*pages)); | ||
44 | if (!*pages || !*colors) | ||
45 | bail_out("couldn't allocate memory"); | ||
46 | |||
47 | for (line = 0; line < *num_colors && !feof(fstream); ++line) { | ||
48 | |||
49 | skip_comments(fstream); | ||
50 | |||
51 | if (2 != fscanf(fstream, "%d,%d", | ||
52 | &(*colors)[line], &(*pages)[line])) { | ||
53 | fprintf(stderr, "invalid color pages near line %d\n", | ||
54 | line); | ||
55 | exit(EXIT_FAILURE); | ||
56 | } | ||
57 | |||
58 | skip_to_next_line(fstream); | ||
59 | } | ||
60 | |||
61 | assert(line == *num_colors); | ||
62 | fclose(fstream); | ||
63 | } | ||
64 | |||
65 | #define OPTSTR SPIN_OPTS "x:" | ||
66 | |||
67 | int main(int argc, char** argv) | ||
68 | { | ||
69 | const char* file = NULL; | ||
70 | int *pages, *colors, num_colors, opt, i; | ||
71 | struct spin_opts sopts; | ||
72 | |||
73 | init_spin_opts(&sopts, usage, NULL); | ||
74 | |||
75 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | ||
76 | switch (opt) { | ||
77 | case 'x': | ||
78 | file = optarg; | ||
79 | break; | ||
80 | case ':': | ||
81 | usage("Argument missing."); | ||
82 | break; | ||
83 | case '?': | ||
84 | default: | ||
85 | if (!do_spin_opt(&sopts, opt, optarg)) | ||
86 | usage("Bad argument."); | ||
87 | break; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | if (file) { | ||
92 | get_page_colors(file, &num_colors, &colors, &pages); | ||
93 | for (i = 0; i < num_colors; i++) | ||
94 | printf("color %d has %d pages\n", colors[i], pages[i]); | ||
95 | } | ||
96 | |||
97 | /* setup_spin(&sopts, optind, argc, argv); */ | ||
98 | return 0; | ||
99 | } | ||
diff --git a/bin/colortest.c b/bin/colortest.c index 02a9169..bc66522 100644 --- a/bin/colortest.c +++ b/bin/colortest.c | |||
@@ -1,7 +1,6 @@ | |||
1 | #include <stdlib.h> | 1 | #include <stdlib.h> |
2 | #include <stdio.h> | 2 | #include <stdio.h> |
3 | #include <stdint.h> | 3 | #include <stdint.h> |
4 | |||
5 | #include <litmus/rt_param.h> | 4 | #include <litmus/rt_param.h> |
6 | 5 | ||
7 | #include "color.h" | 6 | #include "color.h" |
diff --git a/bin/perfcounters.c b/bin/perfcounters.c index 6302164..975ee5b 100644 --- a/bin/perfcounters.c +++ b/bin/perfcounters.c | |||
@@ -39,7 +39,7 @@ struct perf_counter_setup { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | #if 0 | 41 | #if 0 |
42 | /* these events are always zero */ | 42 | /* on Pound, these events are always zero */ |
43 | static struct perf_fd perf_fds[] = { | 43 | static struct perf_fd perf_fds[] = { |
44 | { | 44 | { |
45 | .fd = -1, | 45 | .fd = -1, |
@@ -61,6 +61,8 @@ static struct perf_fd perf_fds[] = { | |||
61 | }; | 61 | }; |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | #if 0 | ||
65 | /* these are for Pound */ | ||
64 | static struct perf_counter_setup perf_setup[NR_PERF_COUNTERS] = { | 66 | static struct perf_counter_setup perf_setup[NR_PERF_COUNTERS] = { |
65 | #if 0 | 67 | #if 0 |
66 | { | 68 | { |
@@ -108,7 +110,30 @@ static struct perf_counter_setup perf_setup[NR_PERF_COUNTERS] = { | |||
108 | #endif | 110 | #endif |
109 | }, | 111 | }, |
110 | }; | 112 | }; |
113 | #endif | ||
111 | 114 | ||
115 | static struct perf_counter_setup perf_setup[NR_PERF_COUNTERS] = { | ||
116 | { | ||
117 | .name = "Linux LL Cache Read Miss", | ||
118 | .type = PERF_TYPE_HW_CACHE, | ||
119 | .config = ATTR_CONFIG_CACHE(LL, OP_READ, RESULT_MISS), | ||
120 | #if 0 | ||
121 | /* read misses */ | ||
122 | .config = ATTR_CONFIG_CACHE(LL, OP_READ, RESULT_MISS), | ||
123 | /* write misses */ | ||
124 | .config = ATTR_CONFIG_CACHE(LL, OP_WRITE, RESULT_MISS), | ||
125 | /* prefetch misses */ | ||
126 | .config = ATTR_CONFIG_CACHE(LL, OP_PREFETCH, RESULT_MISS), | ||
127 | #endif | ||
128 | }, | ||
129 | #if (2 == NR_PERF_COUNTERS) | ||
130 | { | ||
131 | .name = "Cycles", | ||
132 | .type = PERF_TYPE_HARDWARE, | ||
133 | .config = PERF_COUNT_HW_CPU_CYCLES, | ||
134 | }, | ||
135 | #endif | ||
136 | }; | ||
112 | 137 | ||
113 | /* from kernel tools/perf/perf.h */ | 138 | /* from kernel tools/perf/perf.h */ |
114 | int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid, | 139 | int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid, |
diff --git a/bin/rtspin.c b/bin/rtspin.c index a19637c..d823edc 100644 --- a/bin/rtspin.c +++ b/bin/rtspin.c | |||
@@ -1,15 +1,7 @@ | |||
1 | #include <sys/time.h> | ||
2 | |||
3 | #include <stdio.h> | ||
4 | #include <stdlib.h> | 1 | #include <stdlib.h> |
5 | #include <unistd.h> | 2 | #include <unistd.h> |
6 | #include <time.h> | ||
7 | #include <assert.h> | ||
8 | #include <strings.h> | ||
9 | #include <string.h> | ||
10 | 3 | ||
11 | #include "litmus.h" | 4 | #include "spin_common.h" |
12 | #include "common.h" | ||
13 | 5 | ||
14 | static void usage(char *error) { | 6 | static void usage(char *error) { |
15 | fprintf(stderr, "Error: %s\n", error); | 7 | fprintf(stderr, "Error: %s\n", error); |
@@ -20,80 +12,11 @@ static void usage(char *error) { | |||
20 | " rt_spin -l\n" | 12 | " rt_spin -l\n" |
21 | "\n" | 13 | "\n" |
22 | "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n" | 14 | "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n" |
23 | " [-h NUM-COLORS,AVG-WAYS]\n" | ||
24 | "\n" | 15 | "\n" |
25 | "WCET and PERIOD are milliseconds, DURATION is seconds.\n"); | 16 | "WCET and PERIOD are milliseconds, DURATION is seconds.\n"); |
26 | exit(EXIT_FAILURE); | 17 | exit(EXIT_FAILURE); |
27 | } | 18 | } |
28 | 19 | ||
29 | /* | ||
30 | * returns the character that made processing stop, newline or EOF | ||
31 | */ | ||
32 | static int skip_to_next_line(FILE *fstream) | ||
33 | { | ||
34 | int ch; | ||
35 | for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream)); | ||
36 | return ch; | ||
37 | } | ||
38 | |||
39 | static void skip_comments(FILE *fstream) | ||
40 | { | ||
41 | int ch; | ||
42 | for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream)) | ||
43 | skip_to_next_line(fstream); | ||
44 | ungetc(ch, fstream); | ||
45 | } | ||
46 | |||
47 | static void get_exec_times(const char *file, const int column, | ||
48 | int *num_jobs, double **exec_times) | ||
49 | { | ||
50 | FILE *fstream; | ||
51 | int cur_job, cur_col, ch; | ||
52 | *num_jobs = 0; | ||
53 | |||
54 | fstream = fopen(file, "r"); | ||
55 | if (!fstream) | ||
56 | bail_out("could not open execution time file"); | ||
57 | |||
58 | /* figure out the number of jobs */ | ||
59 | do { | ||
60 | skip_comments(fstream); | ||
61 | ch = skip_to_next_line(fstream); | ||
62 | if (ch != EOF) | ||
63 | ++(*num_jobs); | ||
64 | } while (ch != EOF); | ||
65 | |||
66 | if (-1 == fseek(fstream, 0L, SEEK_SET)) | ||
67 | bail_out("rewinding file failed"); | ||
68 | |||
69 | /* allocate space for exec times */ | ||
70 | *exec_times = calloc(*num_jobs, sizeof(*exec_times)); | ||
71 | if (!*exec_times) | ||
72 | bail_out("couldn't allocate memory"); | ||
73 | |||
74 | for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) { | ||
75 | |||
76 | skip_comments(fstream); | ||
77 | |||
78 | for (cur_col = 1; cur_col < column; ++cur_col) { | ||
79 | /* discard input until we get to the column we want */ | ||
80 | fscanf(fstream, "%*s,"); | ||
81 | } | ||
82 | |||
83 | /* get the desired exec. time */ | ||
84 | if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) { | ||
85 | fprintf(stderr, "invalid execution time near line %d\n", | ||
86 | cur_job); | ||
87 | exit(EXIT_FAILURE); | ||
88 | } | ||
89 | |||
90 | skip_to_next_line(fstream); | ||
91 | } | ||
92 | |||
93 | assert(cur_job == *num_jobs); | ||
94 | fclose(fstream); | ||
95 | } | ||
96 | |||
97 | #define NUMS 4096 | 20 | #define NUMS 4096 |
98 | static int num[NUMS]; | 21 | static int num[NUMS]; |
99 | static char* progname; | 22 | static char* progname; |
@@ -161,70 +84,27 @@ static int job(double exec_time, double program_end) | |||
161 | } | 84 | } |
162 | } | 85 | } |
163 | 86 | ||
164 | #define OPTSTR "p:c:wlveo:f:s:h:" | 87 | #define OPTSTR SPIN_OPTS "l" |
165 | 88 | ||
166 | int main(int argc, char** argv) | 89 | int main(int argc, char** argv) |
167 | { | 90 | { |
168 | int ret; | 91 | int opt, test_loop = 0; |
169 | lt_t wcet; | 92 | struct spin_opts sopts; |
170 | lt_t period; | ||
171 | double wcet_ms, period_ms; | ||
172 | int migrate = 0; | ||
173 | int cpu = 0; | ||
174 | int opt; | ||
175 | int wait = 0; | ||
176 | int test_loop = 0; | ||
177 | int column = 1; | ||
178 | const char *file = NULL; | ||
179 | int want_enforcement = 0; | ||
180 | double duration = 0, start; | ||
181 | double *exec_times = NULL; | ||
182 | double scale = 1.0; | ||
183 | task_class_t class = RT_CLASS_HARD; | ||
184 | int cur_job, num_jobs; | ||
185 | int task_colors = 0; | ||
186 | int avg_ways = 0; | ||
187 | 93 | ||
188 | progname = argv[0]; | 94 | init_spin_opts(&sopts, usage, job); |
189 | 95 | ||
190 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | 96 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { |
191 | switch (opt) { | 97 | switch (opt) { |
192 | case 'w': | ||
193 | wait = 1; | ||
194 | break; | ||
195 | case 'p': | ||
196 | cpu = atoi(optarg); | ||
197 | migrate = 1; | ||
198 | break; | ||
199 | case 'c': | ||
200 | class = str2class(optarg); | ||
201 | if (class == -1) | ||
202 | usage("Unknown task class."); | ||
203 | break; | ||
204 | case 'e': | ||
205 | want_enforcement = 1; | ||
206 | break; | ||
207 | case 'l': | 98 | case 'l': |
208 | test_loop = 1; | 99 | test_loop = 1; |
209 | break; | 100 | break; |
210 | case 'o': | ||
211 | column = atoi(optarg); | ||
212 | break; | ||
213 | case 'f': | ||
214 | file = optarg; | ||
215 | break; | ||
216 | case 's': | ||
217 | scale = atof(optarg); | ||
218 | break; | ||
219 | case 'h': | ||
220 | sscanf(optarg, "%d,%d", &task_colors, &avg_ways); | ||
221 | break; | ||
222 | case ':': | 101 | case ':': |
223 | usage("Argument missing."); | 102 | usage("Argument missing."); |
224 | break; | 103 | break; |
225 | case '?': | 104 | case '?': |
226 | default: | 105 | default: |
227 | usage("Bad argument."); | 106 | if (!do_spin_opt(&sopts, opt, optarg)) |
107 | usage("Bad argument."); | ||
228 | break; | 108 | break; |
229 | } | 109 | } |
230 | } | 110 | } |
@@ -234,92 +114,8 @@ int main(int argc, char** argv) | |||
234 | return 0; | 114 | return 0; |
235 | } | 115 | } |
236 | 116 | ||
237 | if (file) { | 117 | setup_spin(&sopts, optind, argc, argv); |
238 | get_exec_times(file, column, &num_jobs, &exec_times); | 118 | run_spin(&sopts); |
239 | |||
240 | if (argc - optind < 2) | ||
241 | usage("Arguments missing."); | ||
242 | |||
243 | for (cur_job = 0; cur_job < num_jobs; ++cur_job) { | ||
244 | /* convert the execution time to seconds */ | ||
245 | duration += exec_times[cur_job] * 0.001; | ||
246 | } | ||
247 | } else { | ||
248 | /* | ||
249 | * if we're not reading from the CSV file, then we need | ||
250 | * three parameters | ||
251 | */ | ||
252 | if (argc - optind < 3) | ||
253 | usage("Arguments missing."); | ||
254 | } | ||
255 | |||
256 | wcet_ms = atof(argv[optind + 0]); | ||
257 | period_ms = atof(argv[optind + 1]); | ||
258 | |||
259 | wcet = wcet_ms * __NS_PER_MS; | ||
260 | period = period_ms * __NS_PER_MS; | ||
261 | if (wcet <= 0) | ||
262 | usage("The worst-case execution time must be a " | ||
263 | "positive number."); | ||
264 | if (period <= 0) | ||
265 | usage("The period must be a positive number."); | ||
266 | if (!file && wcet > period) { | ||
267 | usage("The worst-case execution time must not " | ||
268 | "exceed the period."); | ||
269 | } | ||
270 | |||
271 | if (!file) | ||
272 | duration = atof(argv[optind + 2]); | ||
273 | else if (file && num_jobs > 1) | ||
274 | duration += period_ms * 0.001 * (num_jobs - 1); | ||
275 | |||
276 | if (migrate) { | ||
277 | ret = be_migrate_to(cpu); | ||
278 | if (ret < 0) | ||
279 | bail_out("could not migrate to target partition"); | ||
280 | } | ||
281 | |||
282 | ret = sporadic_task_ns(wcet, period, 0, cpu, class, | ||
283 | want_enforcement ? PRECISE_ENFORCEMENT | ||
284 | : NO_ENFORCEMENT, | ||
285 | migrate); | ||
286 | if (ret < 0) | ||
287 | bail_out("could not setup rt task params"); | ||
288 | |||
289 | init_litmus(); | ||
290 | |||
291 | request_resources(task_colors, avg_ways); | ||
292 | |||
293 | ret = task_mode(LITMUS_RT_TASK); | ||
294 | if (ret != 0) | ||
295 | bail_out("could not become RT task"); | ||
296 | |||
297 | if (wait) { | ||
298 | ret = wait_for_ts_release(); | ||
299 | if (ret != 0) | ||
300 | bail_out("wait_for_ts_release()"); | ||
301 | } | ||
302 | |||
303 | start = wctime(); | ||
304 | |||
305 | if (file) { | ||
306 | /* use times read from the CSV file */ | ||
307 | for (cur_job = 0; cur_job < num_jobs; ++cur_job) { | ||
308 | /* convert job's length to seconds */ | ||
309 | job(exec_times[cur_job] * 0.001 * scale, | ||
310 | start + duration); | ||
311 | } | ||
312 | } else { | ||
313 | /* conver to seconds and scale */ | ||
314 | while (job(wcet_ms * 0.001 * scale, start + duration)); | ||
315 | } | ||
316 | |||
317 | ret = task_mode(BACKGROUND_TASK); | ||
318 | if (ret != 0) | ||
319 | bail_out("could not become regular task (huh?)"); | ||
320 | |||
321 | if (file) | ||
322 | free(exec_times); | ||
323 | 119 | ||
324 | return 0; | 120 | return 0; |
325 | } | 121 | } |
diff --git a/bin/singlepage.c b/bin/singlepage.c new file mode 100644 index 0000000..376f55d --- /dev/null +++ b/bin/singlepage.c | |||
@@ -0,0 +1,158 @@ | |||
1 | #include <stdint.h> | ||
2 | #include <stdio.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <sys/ioctl.h> | ||
5 | |||
6 | #include <litmus/rt_param.h> | ||
7 | |||
8 | #include "perfcounters.h" | ||
9 | #include "color.h" | ||
10 | #include "litmus.h" | ||
11 | |||
12 | #define CPU 0 | ||
13 | #define NR_PAGES 10 | ||
14 | #define NR_LOOPS 10 | ||
15 | |||
16 | struct page { | ||
17 | struct page *ptr; | ||
18 | char _unused[PAGE_SIZE - sizeof(struct page*)]; | ||
19 | }; | ||
20 | |||
21 | /* | ||
22 | * Get a random number in [0, max). Not really a good way to do this. | ||
23 | */ | ||
24 | static int randrange(const int max) | ||
25 | { | ||
26 | return (rand() / (RAND_MAX / max + 1)); | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * Sattolo's algorithm makes a random cycle that includes all the elements | ||
31 | * in the items array. | ||
32 | */ | ||
33 | static void sattolo(int *items, const int len) | ||
34 | { | ||
35 | int i; | ||
36 | /* first set up 0, 1, ..., n - 1 */ | ||
37 | for (i = 0; i < len; i++) | ||
38 | items[i] = i; | ||
39 | /* note: i is now n */ | ||
40 | while (1 < i--) { | ||
41 | /* 0 <= j < i */ | ||
42 | int t, j = randrange(i); | ||
43 | t = items[i]; | ||
44 | items[i] = items[j]; | ||
45 | items[j] = t; | ||
46 | } | ||
47 | } | ||
48 | static struct page * do_read(struct page* page) | ||
49 | { | ||
50 | struct page *old; | ||
51 | do { | ||
52 | old = page; | ||
53 | page = page->ptr; | ||
54 | } while (page); | ||
55 | return old; | ||
56 | } | ||
57 | |||
58 | static inline void get_counters(const struct perf_counter *pc, uint64_t *vals) | ||
59 | { | ||
60 | read_perf_counter(&pc[0], &vals[0]); | ||
61 | #if (2 == NR_PERF_COUNTERS) | ||
62 | read_perf_counter(&pc[1], &vals[1]); | ||
63 | #endif | ||
64 | } | ||
65 | |||
66 | static void print_counters(uint64_t *vals, double div) | ||
67 | { | ||
68 | int i; | ||
69 | for (i = 0; i < NR_PERF_COUNTERS; i++) { | ||
70 | printf("counter %d: %12lu div: %8.3f\n", i, vals[i], vals[i] / div); | ||
71 | } | ||
72 | printf("\n"); | ||
73 | } | ||
74 | |||
75 | #define quit_on_err(err, msg) do { \ | ||
76 | if (err) { \ | ||
77 | fprintf(stderr, "error: " msg); \ | ||
78 | goto out; \ | ||
79 | } \ | ||
80 | } while (0) | ||
81 | |||
82 | int main(int argc, char **argv) | ||
83 | { | ||
84 | static struct perf_counter perf_counters[NR_PERF_COUNTERS]; | ||
85 | struct color_ctrl_page *color_ctrl; | ||
86 | struct page *pages[NR_PAGES]; | ||
87 | struct page *page_ptr; | ||
88 | int read_order[NR_PAGES]; | ||
89 | uint64_t counter_vals[NR_PERF_COUNTERS]; | ||
90 | int i, err = 0; | ||
91 | |||
92 | err = be_migrate_to(CPU); | ||
93 | quit_on_err(err, "migrate to cpu\n"); | ||
94 | |||
95 | err = setup_cpu_perf(CPU, -1, perf_counters); | ||
96 | quit_on_err(err, "setup perf\n"); | ||
97 | |||
98 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_DISABLE); | ||
99 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_RESET); | ||
100 | |||
101 | |||
102 | err = map_color_ctrl((void**)&color_ctrl); | ||
103 | quit_on_err(err, "map color ctrl\n"); | ||
104 | |||
105 | color_ctrl->colors[0] = 0; | ||
106 | |||
107 | for (i = 0; i < NR_PAGES; i++) { | ||
108 | pages[i] = color_malloc(sizeof(*pages[i])); | ||
109 | if (!pages[i]) { | ||
110 | fprintf(stderr, "could not color malloc\n"); | ||
111 | err = -1; | ||
112 | goto out; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | sattolo(read_order, NR_PAGES); | ||
117 | |||
118 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_ENABLE); | ||
119 | |||
120 | for (i = 0; i < NR_PAGES; i++) { | ||
121 | if (0 != read_order[i]) { | ||
122 | /* not the last element */ | ||
123 | pages[i]->ptr = pages[read_order[i]]; | ||
124 | } else { | ||
125 | /* last element should be NULL (terminate the cycle) */ | ||
126 | pages[i]->ptr = NULL; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | get_counters(perf_counters, counter_vals); | ||
131 | print_counters(counter_vals, NR_PAGES); | ||
132 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_RESET); | ||
133 | |||
134 | page_ptr = do_read(pages[0]); | ||
135 | get_counters(perf_counters, counter_vals); | ||
136 | print_counters(counter_vals, NR_PAGES); | ||
137 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_RESET); | ||
138 | |||
139 | page_ptr = do_read(pages[0]); | ||
140 | get_counters(perf_counters, counter_vals); | ||
141 | print_counters(counter_vals, NR_PAGES); | ||
142 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_RESET); | ||
143 | |||
144 | page_ptr = do_read(pages[0]); | ||
145 | get_counters(perf_counters, counter_vals); | ||
146 | print_counters(counter_vals, NR_PAGES); | ||
147 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_RESET); | ||
148 | |||
149 | for (i = 0; i < NR_LOOPS; i++) { | ||
150 | page_ptr = do_read(pages[0]); | ||
151 | } | ||
152 | get_counters(perf_counters, counter_vals); | ||
153 | print_counters(counter_vals, NR_PAGES * NR_LOOPS); | ||
154 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_DISABLE); | ||
155 | |||
156 | out: | ||
157 | return err; | ||
158 | } | ||
diff --git a/include/perfcounters.h b/include/perfcounters.h index 03f94fb..0329921 100644 --- a/include/perfcounters.h +++ b/include/perfcounters.h | |||
@@ -5,7 +5,15 @@ | |||
5 | 5 | ||
6 | #include "../../litmus-rt/include/linux/perf_event.h" | 6 | #include "../../litmus-rt/include/linux/perf_event.h" |
7 | 7 | ||
8 | #define NR_PERF_COUNTERS 4 | 8 | /* on Pound */ |
9 | //#define NR_PERF_COUNTERS 4 | ||
10 | |||
11 | /* | ||
12 | * Flare: 1 gets you the L2 read misses and 2 gets you that plus the | ||
13 | * CPU clock counter. However, accessing the CPU clock will add misses | ||
14 | * when you go to read the performance counters, so I don't use it. | ||
15 | */ | ||
16 | #define NR_PERF_COUNTERS 1 | ||
9 | 17 | ||
10 | /* | 18 | /* |
11 | * Retain this information with a performance counter file descriptor. | 19 | * Retain this information with a performance counter file descriptor. |
diff --git a/include/spin_common.h b/include/spin_common.h new file mode 100644 index 0000000..977c201 --- /dev/null +++ b/include/spin_common.h | |||
@@ -0,0 +1,42 @@ | |||
1 | #ifndef SPIN_COMMON_H_ | ||
2 | #define SPIN_COMMON_H_ | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include "litmus.h" | ||
6 | |||
7 | #define SPIN_OPTS "p:c:weo:f:s:" | ||
8 | |||
9 | typedef void (*usage_t)(char *error); | ||
10 | typedef int (*job_t)(double exec, double end); | ||
11 | |||
12 | struct spin_opts { | ||
13 | usage_t usage; | ||
14 | job_t job; | ||
15 | |||
16 | int wait; | ||
17 | int cpu; | ||
18 | int migrate; | ||
19 | int column; | ||
20 | int want_enforcement; | ||
21 | double scale; | ||
22 | task_class_t class; | ||
23 | const char* file; | ||
24 | |||
25 | int num_jobs; | ||
26 | double duration; | ||
27 | double *exec_times; | ||
28 | double wcet; | ||
29 | double period; | ||
30 | }; | ||
31 | |||
32 | void init_spin_opts(struct spin_opts *sopts, usage_t usage, job_t job); | ||
33 | |||
34 | int skip_to_next_line(FILE *fstream); | ||
35 | void skip_comments(FILE *fstream); | ||
36 | |||
37 | int do_spin_opt(struct spin_opts *sopts, int opt, const char *optarg); | ||
38 | |||
39 | void setup_spin(struct spin_opts *sopts, int last, int argc, char** argv); | ||
40 | void run_spin(struct spin_opts *sopts); | ||
41 | |||
42 | #endif | ||
diff --git a/src/spin_common.c b/src/spin_common.c new file mode 100644 index 0000000..157a9bb --- /dev/null +++ b/src/spin_common.c | |||
@@ -0,0 +1,235 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <assert.h> | ||
3 | |||
4 | #include "spin_common.h" | ||
5 | #include "common.h" | ||
6 | |||
7 | /* | ||
8 | * returns the character that made processing stop, newline or EOF | ||
9 | */ | ||
10 | int skip_to_next_line(FILE *fstream) | ||
11 | { | ||
12 | int ch; | ||
13 | for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream)); | ||
14 | return ch; | ||
15 | } | ||
16 | |||
17 | void skip_comments(FILE *fstream) | ||
18 | { | ||
19 | int ch; | ||
20 | for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream)) | ||
21 | skip_to_next_line(fstream); | ||
22 | ungetc(ch, fstream); | ||
23 | } | ||
24 | |||
25 | static void get_exec_times(const char *file, const int column, | ||
26 | int *num_jobs, double **exec_times) | ||
27 | { | ||
28 | FILE *fstream; | ||
29 | int curr_job, cur_col, ch; | ||
30 | *num_jobs = 0; | ||
31 | |||
32 | fstream = fopen(file, "r"); | ||
33 | if (!fstream) | ||
34 | bail_out("could not open execution time file"); | ||
35 | |||
36 | /* figure out the number of jobs */ | ||
37 | do { | ||
38 | skip_comments(fstream); | ||
39 | ch = skip_to_next_line(fstream); | ||
40 | if (ch != EOF) | ||
41 | ++(*num_jobs); | ||
42 | } while (ch != EOF); | ||
43 | |||
44 | if (-1 == fseek(fstream, 0L, SEEK_SET)) | ||
45 | bail_out("rewinding file failed"); | ||
46 | |||
47 | /* allocate space for exec times */ | ||
48 | *exec_times = calloc(*num_jobs, sizeof(*exec_times)); | ||
49 | if (!*exec_times) | ||
50 | bail_out("couldn't allocate memory"); | ||
51 | |||
52 | for (curr_job = 0; curr_job < *num_jobs && !feof(fstream); ++curr_job) { | ||
53 | |||
54 | skip_comments(fstream); | ||
55 | |||
56 | for (cur_col = 1; cur_col < column; ++cur_col) { | ||
57 | /* discard input until we get to the column we want */ | ||
58 | fscanf(fstream, "%*s,"); | ||
59 | } | ||
60 | |||
61 | /* get the desired exec. time */ | ||
62 | if (1 != fscanf(fstream, "%lf", (*exec_times)+curr_job)) { | ||
63 | fprintf(stderr, "invalid execution time near line %d\n", | ||
64 | curr_job); | ||
65 | exit(EXIT_FAILURE); | ||
66 | } | ||
67 | |||
68 | skip_to_next_line(fstream); | ||
69 | } | ||
70 | |||
71 | assert(curr_job == *num_jobs); | ||
72 | fclose(fstream); | ||
73 | } | ||
74 | |||
75 | |||
76 | |||
77 | int do_spin_opt(struct spin_opts *sopts, int opt, const char *optarg) | ||
78 | { | ||
79 | int ret = 1; | ||
80 | |||
81 | switch (opt) { | ||
82 | case 'w': | ||
83 | sopts->wait = 1; | ||
84 | break; | ||
85 | case 'p': | ||
86 | sopts->cpu = atoi(optarg); | ||
87 | sopts->migrate = 1; | ||
88 | break; | ||
89 | case 'c': | ||
90 | sopts->class = str2class(optarg); | ||
91 | if (sopts->class == -1) | ||
92 | sopts->usage("Unknown task class."); | ||
93 | break; | ||
94 | case 'e': | ||
95 | sopts->want_enforcement = 1; | ||
96 | break; | ||
97 | case 'o': | ||
98 | sopts->column = atoi(optarg); | ||
99 | break; | ||
100 | case 'f': | ||
101 | sopts->file = optarg; | ||
102 | break; | ||
103 | case 's': | ||
104 | sopts->scale = atof(optarg); | ||
105 | break; | ||
106 | default: | ||
107 | ret = 0; | ||
108 | } | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | void init_spin_opts(struct spin_opts *sopts, usage_t usage, job_t job) | ||
114 | { | ||
115 | sopts->usage = usage; | ||
116 | sopts->job = job; | ||
117 | |||
118 | sopts->wait = 0; | ||
119 | sopts->cpu = 0; | ||
120 | sopts->migrate = 0; | ||
121 | sopts->column = 1; | ||
122 | sopts->want_enforcement = 0; | ||
123 | sopts->scale = 1.0; | ||
124 | sopts->class = RT_CLASS_HARD; | ||
125 | sopts->file = NULL; | ||
126 | |||
127 | sopts->num_jobs = 0; | ||
128 | sopts->duration = 0; | ||
129 | sopts->exec_times = NULL; | ||
130 | |||
131 | sopts->wcet = 0; | ||
132 | sopts->period = 0; | ||
133 | } | ||
134 | |||
135 | |||
136 | void setup_spin(struct spin_opts *sopts, int last, int argc, char** argv) | ||
137 | { | ||
138 | int ret; | ||
139 | double wcet_ns, period_ns; | ||
140 | int curr_job; | ||
141 | |||
142 | if (sopts->file) { | ||
143 | get_exec_times(sopts->file, sopts->column, | ||
144 | &sopts->num_jobs, &sopts->exec_times); | ||
145 | |||
146 | if (argc - last < 2) | ||
147 | sopts->usage("Arguments missing."); | ||
148 | |||
149 | for (curr_job = 0; curr_job < sopts->num_jobs; ++curr_job) { | ||
150 | /* convert the execution time to seconds */ | ||
151 | sopts->duration += sopts->exec_times[curr_job] * 0.001; | ||
152 | } | ||
153 | } else { | ||
154 | /* | ||
155 | * if we're not reading from the CSV file, then we need | ||
156 | * three parameters | ||
157 | */ | ||
158 | if (argc - last < 3) | ||
159 | sopts->usage("Arguments missing."); | ||
160 | } | ||
161 | |||
162 | sopts->wcet = atof(argv[last + 0]); | ||
163 | sopts->period = atof(argv[last + 1]); | ||
164 | |||
165 | wcet_ns = sopts->wcet * __NS_PER_MS; | ||
166 | period_ns = sopts->period * __NS_PER_MS; | ||
167 | if (wcet_ns <= 0) | ||
168 | sopts->usage("The worst-case execution time must be a " | ||
169 | "positive number."); | ||
170 | if (period_ns <= 0) | ||
171 | sopts->usage("The period must be a positive number."); | ||
172 | if (!sopts->file && wcet_ns > period_ns) { | ||
173 | sopts->usage("The worst-case execution time must not " | ||
174 | "exceed the period."); | ||
175 | } | ||
176 | |||
177 | if (!sopts->file) | ||
178 | sopts->duration = atof(argv[last + 2]); | ||
179 | else if (sopts->file && sopts->num_jobs > 1) | ||
180 | sopts->duration += period_ns * 0.001 * (sopts->num_jobs - 1); | ||
181 | |||
182 | if (sopts->migrate) { | ||
183 | ret = be_migrate_to(sopts->cpu); | ||
184 | if (ret < 0) | ||
185 | bail_out("could not migrate to target partition"); | ||
186 | } | ||
187 | |||
188 | ret = sporadic_task_ns(wcet_ns, period_ns, 0, | ||
189 | sopts->cpu, sopts->class, | ||
190 | sopts->want_enforcement ? PRECISE_ENFORCEMENT | ||
191 | : NO_ENFORCEMENT, | ||
192 | sopts->migrate); | ||
193 | |||
194 | if (ret < 0) | ||
195 | bail_out("could not setup rt task params"); | ||
196 | } | ||
197 | |||
198 | void run_spin(struct spin_opts *sopts) | ||
199 | { | ||
200 | double end, scale; | ||
201 | int ret, curr_job; | ||
202 | |||
203 | init_litmus(); | ||
204 | |||
205 | ret = task_mode(LITMUS_RT_TASK); | ||
206 | if (ret != 0) | ||
207 | bail_out("could not become RT task"); | ||
208 | |||
209 | if (sopts->wait) { | ||
210 | ret = wait_for_ts_release(); | ||
211 | if (ret != 0) | ||
212 | bail_out("wait_for_ts_release()"); | ||
213 | } | ||
214 | |||
215 | scale = .001 * sopts->scale; | ||
216 | end = wctime() + sopts->duration; | ||
217 | |||
218 | if (sopts->file) { | ||
219 | /* use times read from the CSV file */ | ||
220 | for (curr_job = 0; curr_job < sopts->num_jobs; ++curr_job) { | ||
221 | /* convert job's length to seconds */ | ||
222 | sopts->job(sopts->exec_times[curr_job] * scale, end); | ||
223 | } | ||
224 | } else { | ||
225 | /* conver to seconds and scale */ | ||
226 | while (sopts->job(sopts->wcet * scale, end)); | ||
227 | } | ||
228 | |||
229 | ret = task_mode(BACKGROUND_TASK); | ||
230 | if (ret != 0) | ||
231 | bail_out("could not become regular task (huh?)"); | ||
232 | |||
233 | if (sopts->file) | ||
234 | free(sopts->exec_times); | ||
235 | } | ||