diff options
author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2017-09-14 17:58:28 -0400 |
---|---|---|
committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2017-09-14 17:58:28 -0400 |
commit | a430c7b5cacae4219a185decb863f6fb9e5cbcb9 (patch) | |
tree | 8a1302ddb89504f856ff89ec2d17deaac1172cb6 | |
parent | e9d67470da50e5428ab4d359f2beedf54a28f9aa (diff) | |
parent | 31352298446e1fc1ba4dc391197aef3fd57bf080 (diff) |
Merge remote-tracking branch 'github/master'
Conflicts:
bin/rtspin.c
Resolve option clash by moving the calibration loop to -a0.
-rw-r--r-- | bin/rtspin.c | 136 | ||||
-rw-r--r-- | include/common.h | 6 |
2 files changed, 112 insertions, 30 deletions
diff --git a/bin/rtspin.c b/bin/rtspin.c index 68f721d..fb7f13f 100644 --- a/bin/rtspin.c +++ b/bin/rtspin.c | |||
@@ -19,8 +19,9 @@ const char *usage_msg = | |||
19 | "Usage: (1) rtspin OPTIONS WCET PERIOD DURATION\n" | 19 | "Usage: (1) rtspin OPTIONS WCET PERIOD DURATION\n" |
20 | " (2) rtspin -S [INPUT] WCET PERIOD DURATION\n" | 20 | " (2) rtspin -S [INPUT] WCET PERIOD DURATION\n" |
21 | " (3) rtspin OPTIONS -C FILE:COLUMN WCET PERIOD [DURATION]\n" | 21 | " (3) rtspin OPTIONS -C FILE:COLUMN WCET PERIOD [DURATION]\n" |
22 | " (4) rtspin -l\n" | 22 | " (4) rtspin -l [-a CYCLES]\n" |
23 | " (5) rtspin -B -m FOOTPRINT\n" | 23 | " (5) rtspin -B -m FOOTPRINT\n" |
24 | " (6) rtspin -a 0\n" | ||
24 | "\n" | 25 | "\n" |
25 | "Modes: (1) run as periodic task with given WCET and PERIOD\n" | 26 | "Modes: (1) run as periodic task with given WCET and PERIOD\n" |
26 | " (2) run as sporadic task with given WCET and PERIOD,\n" | 27 | " (2) run as sporadic task with given WCET and PERIOD,\n" |
@@ -31,12 +32,15 @@ const char *usage_msg = | |||
31 | " (4) Run calibration loop (how accurately are target\n" | 32 | " (4) Run calibration loop (how accurately are target\n" |
32 | " runtimes met?)\n" | 33 | " runtimes met?)\n" |
33 | " (5) Run background, non-real-time cache-thrashing loop.\n" | 34 | " (5) Run background, non-real-time cache-thrashing loop.\n" |
35 | " (6) Run 1 ms workload calibration (estimate cycles for 1ms, 10ms, 100ms workload)\n" | ||
34 | "\n" | 36 | "\n" |
35 | "Required arguments:\n" | 37 | "Required arguments:\n" |
36 | " WCET, PERIOD reservation parameters (in ms)\n" | 38 | " WCET, PERIOD reservation parameters (in ms)\n" |
37 | " DURATION terminate the task after DURATION seconds\n" | 39 | " DURATION terminate the task after DURATION seconds\n" |
38 | "\n" | 40 | "\n" |
39 | "Options:\n" | 41 | "Options:\n" |
42 | " -a CYCLES number of cycles for 1ms of workload loop chosen after calibration;\n " | ||
43 | " pass '0' to run the calibration loop\n" | ||
40 | " -B run non-real-time background loop\n" | 44 | " -B run non-real-time background loop\n" |
41 | " -c be|srt|hrt task class (best-effort, soft real-time, hard real-time)\n" | 45 | " -c be|srt|hrt task class (best-effort, soft real-time, hard real-time)\n" |
42 | " -d DEADLINE relative deadline, equal to the period by default (in ms)\n" | 46 | " -d DEADLINE relative deadline, equal to the period by default (in ms)\n" |
@@ -106,18 +110,23 @@ static int nr_of_pages = 0; | |||
106 | static int page_size; | 110 | static int page_size; |
107 | static void *base = NULL; | 111 | static void *base = NULL; |
108 | 112 | ||
109 | static int loop_once(void) | 113 | static int cycles_ms = 0; |
114 | |||
115 | static noinline int loop(int count) | ||
110 | { | 116 | { |
111 | int i, j = 0; | 117 | int i, j = 0; |
112 | /* touch some numbers and do some math */ | 118 | /* touch some numbers and do some math */ |
113 | for (i = 0; i < NUMS; i++) { | 119 | for (i = 0; i < count; i++) { |
114 | j += num[i]++; | 120 | int index = i % NUMS; |
115 | if (j > num[i]) | 121 | j += num[index]++; |
116 | num[i] = (j / 2) + 1; | 122 | if (j > num[index]) |
123 | num[index] = (j / 2) + 1; | ||
117 | } | 124 | } |
118 | return j; | 125 | return j; |
119 | } | 126 | } |
120 | 127 | ||
128 | #define loop_once() loop(NUMS) | ||
129 | |||
121 | static int loop_once_with_mem(void) | 130 | static int loop_once_with_mem(void) |
122 | { | 131 | { |
123 | int i, j = 0; | 132 | int i, j = 0; |
@@ -143,30 +152,35 @@ static int loop_once_with_mem(void) | |||
143 | 152 | ||
144 | static int loop_for(double exec_time, double emergency_exit) | 153 | static int loop_for(double exec_time, double emergency_exit) |
145 | { | 154 | { |
146 | double last_loop = 0, loop_start; | ||
147 | int tmp = 0; | 155 | int tmp = 0; |
148 | 156 | ||
149 | double start = cputime(); | 157 | if (cycles_ms) { |
150 | double now = cputime(); | 158 | double count = cycles_ms * exec_time * 1000; |
159 | tmp += loop(count); | ||
160 | } else { | ||
161 | double last_loop = 0, loop_start; | ||
162 | double start = cputime(); | ||
163 | double now = cputime(); | ||
151 | 164 | ||
152 | while (now + last_loop < start + exec_time) { | 165 | while (now + last_loop < start + exec_time) { |
153 | loop_start = now; | 166 | loop_start = now; |
154 | if (nr_of_pages) | 167 | if (nr_of_pages) |
155 | tmp += loop_once_with_mem(); | 168 | tmp += loop_once_with_mem(); |
156 | else | 169 | else |
157 | tmp += loop_once(); | 170 | tmp += loop_once(); |
158 | now = cputime(); | 171 | now = cputime(); |
159 | last_loop = now - loop_start; | 172 | last_loop = now - loop_start; |
160 | if (emergency_exit && wctime() > emergency_exit) { | 173 | if (emergency_exit && wctime() > emergency_exit) { |
161 | /* Oops --- this should only be possible if the | 174 | /* Oops --- this should only be possible if the |
162 | * execution time tracking is broken in the LITMUS^RT | 175 | * execution time tracking is broken in the LITMUS^RT |
163 | * kernel or the user specified infeasible parameters. | 176 | * kernel or the user specified infeasible parameters. |
164 | */ | 177 | */ |
165 | fprintf(stderr, "!!! rtspin/%d emergency exit!\n", | 178 | fprintf(stderr, "!!! rtspin/%d emergency exit!\n", |
166 | getpid()); | 179 | getpid()); |
167 | fprintf(stderr, "Reached experiment timeout while " | 180 | fprintf(stderr, "Reached experiment timeout while " |
168 | "spinning.\n"); | 181 | "spinning.\n"); |
169 | break; | 182 | break; |
183 | } | ||
170 | } | 184 | } |
171 | } | 185 | } |
172 | 186 | ||
@@ -180,9 +194,9 @@ static void debug_delay_loop(void) | |||
180 | 194 | ||
181 | while (1) { | 195 | while (1) { |
182 | for (delay = 0.5; delay > 0.01; delay -= 0.01) { | 196 | for (delay = 0.5; delay > 0.01; delay -= 0.01) { |
183 | start = wctime(); | 197 | start = cputime(); |
184 | loop_for(delay, 0); | 198 | loop_for(delay, 0); |
185 | end = wctime(); | 199 | end = cputime(); |
186 | printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n", | 200 | printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n", |
187 | delay, | 201 | delay, |
188 | end - start, | 202 | end - start, |
@@ -194,6 +208,51 @@ static void debug_delay_loop(void) | |||
194 | 208 | ||
195 | static char input_buf[4096] = "<no input>"; | 209 | static char input_buf[4096] = "<no input>"; |
196 | 210 | ||
211 | static int calibrate_ms(int ms) | ||
212 | { | ||
213 | int right = NUMS; | ||
214 | int left = 0; | ||
215 | int middle; | ||
216 | |||
217 | double start; | ||
218 | double now; | ||
219 | double dms = 0.001 * ms; | ||
220 | |||
221 | /*look for initial loop count values for binary search*/ | ||
222 | for (;;) | ||
223 | { | ||
224 | printf("Probe %d loops for %d ms:\n", right, ms); | ||
225 | start = wctime(); | ||
226 | loop(right); | ||
227 | now = wctime(); | ||
228 | if ((now - start) >= dms) | ||
229 | break; | ||
230 | left = right; | ||
231 | right += right; | ||
232 | } | ||
233 | |||
234 | middle = (left + right) / 2; | ||
235 | |||
236 | /*binary search for a loop count value for expected calibration time*/ | ||
237 | while (left < middle) | ||
238 | { | ||
239 | start = wctime(); | ||
240 | loop(middle); | ||
241 | now = wctime(); | ||
242 | |||
243 | printf("%d loops elapsed in %4.20f s\n", middle, now - start); | ||
244 | |||
245 | if ((now - start) < dms) | ||
246 | left = middle; | ||
247 | else if ((now - start) == dms) | ||
248 | return middle; | ||
249 | else | ||
250 | right = middle; | ||
251 | middle = (left + right) / 2; | ||
252 | } | ||
253 | return middle; | ||
254 | } | ||
255 | |||
197 | static int wait_for_input(int event_fd) | 256 | static int wait_for_input(int event_fd) |
198 | { | 257 | { |
199 | /* We do a blocking read, accepting up to 4KiB of data. | 258 | /* We do a blocking read, accepting up to 4KiB of data. |
@@ -277,7 +336,7 @@ static lt_t choose_inter_arrival_time_ns( | |||
277 | return ms2ns(iat_ms); | 336 | return ms2ns(iat_ms); |
278 | } | 337 | } |
279 | 338 | ||
280 | #define OPTSTR "p:c:wlveo:s:m:q:r:X:L:Q:iRu:U:Bhd:C:S::O::TD:E:A:" | 339 | #define OPTSTR "p:c:wlveo:s:m:q:r:X:L:Q:iRu:U:Bhd:C:S::O::TD:E:A:a:" |
281 | 340 | ||
282 | int main(int argc, char** argv) | 341 | int main(int argc, char** argv) |
283 | { | 342 | { |
@@ -298,6 +357,7 @@ int main(int argc, char** argv) | |||
298 | int opt; | 357 | int opt; |
299 | int wait = 0; | 358 | int wait = 0; |
300 | int test_loop = 0; | 359 | int test_loop = 0; |
360 | int caliber_ms = 0; | ||
301 | int background_loop = 0; | 361 | int background_loop = 0; |
302 | 362 | ||
303 | int cost_column = 1; | 363 | int cost_column = 1; |
@@ -480,6 +540,11 @@ int main(int argc, char** argv) | |||
480 | verbose = 1; | 540 | verbose = 1; |
481 | report_interrupts = 1; | 541 | report_interrupts = 1; |
482 | break; | 542 | break; |
543 | case 'a': | ||
544 | cycles_ms = want_non_negative_int(optarg, "-a"); | ||
545 | if (!cycles_ms) | ||
546 | caliber_ms = 1; | ||
547 | break; | ||
483 | case ':': | 548 | case ':': |
484 | usage("Argument missing."); | 549 | usage("Argument missing."); |
485 | break; | 550 | break; |
@@ -513,10 +578,21 @@ int main(int argc, char** argv) | |||
513 | srand(getpid()); | 578 | srand(getpid()); |
514 | 579 | ||
515 | if (test_loop) { | 580 | if (test_loop) { |
581 | if (cycles_ms > 0) | ||
582 | printf("Evaluating loop with %d cycles:\n", cycles_ms); | ||
583 | |||
516 | debug_delay_loop(); | 584 | debug_delay_loop(); |
517 | return 0; | 585 | return 0; |
518 | } | 586 | } |
519 | 587 | ||
588 | if (caliber_ms) { | ||
589 | printf("In 1 ms %d loops.\n", calibrate_ms(1)); | ||
590 | printf("In 10 ms %d loops.\n", calibrate_ms(10)); | ||
591 | printf("In 100 ms %d loops.\n", calibrate_ms(100)); | ||
592 | printf("In 1 s %d loops.\n", calibrate_ms(1000)); | ||
593 | return 0; | ||
594 | } | ||
595 | |||
520 | if (background_loop) { | 596 | if (background_loop) { |
521 | while (1) { | 597 | while (1) { |
522 | if (nr_of_pages) | 598 | if (nr_of_pages) |
diff --git a/include/common.h b/include/common.h index b77ae67..7c33c94 100644 --- a/include/common.h +++ b/include/common.h | |||
@@ -6,6 +6,12 @@ | |||
6 | #ifndef COMMON_H | 6 | #ifndef COMMON_H |
7 | #define COMMON_H | 7 | #define COMMON_H |
8 | 8 | ||
9 | #if defined(__GNUC__) | ||
10 | #define noinline __attribute__((__noinline__)) | ||
11 | #else | ||
12 | #define noinline | ||
13 | #endif | ||
14 | |||
9 | /** | 15 | /** |
10 | * End the current task with a message | 16 | * End the current task with a message |
11 | * @param msg Message to output before bailing | 17 | * @param msg Message to output before bailing |