diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2009-03-25 21:48:12 -0400 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2009-03-25 21:48:12 -0400 |
commit | 7b709ceb7d2191fc552ab70bc1365b47120c634c (patch) | |
tree | 4cd9b9efa3ac6af5211a47460dce2bb1c52c2f2b | |
parent | 8ce85aaacafa0a46827f7799d051a20fac639ee9 (diff) |
auto-configure spin loop in rtspin
Don't just blindly overrun the budget.
Instead, try to measure a spin loop and hope that we get good results.
-rw-r--r-- | bin/rtspin.c | 123 |
1 files changed, 110 insertions, 13 deletions
diff --git a/bin/rtspin.c b/bin/rtspin.c index 435e496..56f5549 100644 --- a/bin/rtspin.c +++ b/bin/rtspin.c | |||
@@ -9,11 +9,6 @@ | |||
9 | #include "litmus.h" | 9 | #include "litmus.h" |
10 | #include "common.h" | 10 | #include "common.h" |
11 | 11 | ||
12 | void usage(char *error) { | ||
13 | fprintf(stderr, "Error: %s\n", error); | ||
14 | fprintf(stderr, "Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION\n"); | ||
15 | exit(1); | ||
16 | } | ||
17 | 12 | ||
18 | static double wctime() | 13 | static double wctime() |
19 | { | 14 | { |
@@ -22,11 +17,99 @@ static double wctime() | |||
22 | return (tv.tv_sec + 1E-6 * tv.tv_usec); | 17 | return (tv.tv_sec + 1E-6 * tv.tv_usec); |
23 | } | 18 | } |
24 | 19 | ||
25 | #define OPTSTR "p:c:w" | 20 | void usage(char *error) { |
21 | fprintf(stderr, "Error: %s\n", error); | ||
22 | fprintf(stderr, | ||
23 | "Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION\n" | ||
24 | " rt_spin -l\n"); | ||
25 | exit(1); | ||
26 | } | ||
27 | |||
28 | #define NUMS 4096 | ||
29 | static int num[NUMS]; | ||
30 | static double loop_length = 1.0; | ||
31 | |||
32 | static int loop_once(void) | ||
33 | { | ||
34 | int i, j = 0; | ||
35 | for (i = 0; i < NUMS; i++) | ||
36 | j += num[i]++; | ||
37 | return j; | ||
38 | } | ||
39 | |||
40 | static int loop_for(double exec_time) | ||
41 | { | ||
42 | double t = 0; | ||
43 | int tmp = 0; | ||
44 | while (t + loop_length < exec_time) { | ||
45 | tmp += loop_once(); | ||
46 | t += loop_length; | ||
47 | } | ||
48 | return tmp; | ||
49 | } | ||
50 | |||
51 | static void fine_tune(double interval) | ||
52 | { | ||
53 | double start, end, delta; | ||
54 | |||
55 | start = wctime(); | ||
56 | loop_for(interval); | ||
57 | end = wctime(); | ||
58 | delta = (end - start - interval) / interval; | ||
59 | if (delta != 0) | ||
60 | loop_length = loop_length / (1 - delta); | ||
61 | } | ||
62 | |||
63 | static void configure_loop(void) | ||
64 | { | ||
65 | double start; | ||
66 | |||
67 | /* prime cache */ | ||
68 | loop_once(); | ||
69 | loop_once(); | ||
70 | loop_once(); | ||
71 | |||
72 | /* measure */ | ||
73 | start = wctime(); | ||
74 | loop_once(); /* hope we didn't get preempted */ | ||
75 | loop_length = wctime(); | ||
76 | loop_length -= start; | ||
77 | |||
78 | /* fine tune */ | ||
79 | fine_tune(0.1); | ||
80 | fine_tune(0.1); | ||
81 | fine_tune(0.1); | ||
82 | } | ||
83 | |||
84 | static void debug_delay_loop(void) | ||
85 | { | ||
86 | double start, end, delay; | ||
87 | printf("loop_length=%f\n", loop_length); | ||
88 | while (1) { | ||
89 | for (delay = 0.5; delay > 0.01; delay -= 0.01) { | ||
90 | start = wctime(); | ||
91 | loop_for(delay); | ||
92 | end = wctime(); | ||
93 | printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n", | ||
94 | delay, | ||
95 | end - start, | ||
96 | end - start - delay, | ||
97 | 100 * (end - start - delay) / delay); | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | |||
102 | static int job(double exec_time) | ||
103 | { | ||
104 | loop_for(exec_time); | ||
105 | sleep_next_period(); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | #define OPTSTR "p:c:wl" | ||
26 | 110 | ||
27 | int main(int argc, char** argv) | 111 | int main(int argc, char** argv) |
28 | { | 112 | { |
29 | int i; | ||
30 | int ret; | 113 | int ret; |
31 | lt_t wcet; | 114 | lt_t wcet; |
32 | lt_t period; | 115 | lt_t period; |
@@ -34,6 +117,7 @@ int main(int argc, char** argv) | |||
34 | int cpu = 0; | 117 | int cpu = 0; |
35 | int opt; | 118 | int opt; |
36 | int wait = 0; | 119 | int wait = 0; |
120 | int test_loop = 0; | ||
37 | double duration, start; | 121 | double duration, start; |
38 | task_class_t class = RT_CLASS_HARD; | 122 | task_class_t class = RT_CLASS_HARD; |
39 | 123 | ||
@@ -51,6 +135,9 @@ int main(int argc, char** argv) | |||
51 | if (class == -1) | 135 | if (class == -1) |
52 | usage("Unknown task class."); | 136 | usage("Unknown task class."); |
53 | break; | 137 | break; |
138 | case 'l': | ||
139 | test_loop = 1; | ||
140 | break; | ||
54 | case ':': | 141 | case ':': |
55 | usage("Argument missing."); | 142 | usage("Argument missing."); |
56 | break; | 143 | break; |
@@ -61,6 +148,14 @@ int main(int argc, char** argv) | |||
61 | } | 148 | } |
62 | } | 149 | } |
63 | 150 | ||
151 | |||
152 | configure_loop(); | ||
153 | |||
154 | if (test_loop) { | ||
155 | debug_delay_loop(); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
64 | if (argc - optind < 3) | 159 | if (argc - optind < 3) |
65 | usage("Arguments missing."); | 160 | usage("Arguments missing."); |
66 | wcet = atoi(argv[optind + 0]); | 161 | wcet = atoi(argv[optind + 0]); |
@@ -75,21 +170,21 @@ int main(int argc, char** argv) | |||
75 | usage("The worst-case execution time must not " | 170 | usage("The worst-case execution time must not " |
76 | "exceed the period."); | 171 | "exceed the period."); |
77 | } | 172 | } |
173 | |||
78 | if (migrate) { | 174 | if (migrate) { |
79 | ret = be_migrate_to(cpu); | 175 | ret = be_migrate_to(cpu); |
80 | if (ret < 0) | 176 | if (ret < 0) |
81 | bail_out("could not migrate to target partition"); | 177 | bail_out("could not migrate to target partition"); |
82 | } | 178 | } |
83 | 179 | ||
84 | // printf("wcet: %llu\nperiod: %llu\n", wcet, period); | ||
85 | ret = sporadic_task(wcet, period, 0, cpu, class, migrate); | 180 | ret = sporadic_task(wcet, period, 0, cpu, class, migrate); |
86 | 181 | ||
87 | if (ret < 0) | 182 | if (ret < 0) |
88 | bail_out("could not become rt tasks."); | 183 | bail_out("could not become rt tasks."); |
89 | 184 | ||
90 | // ret = init_litmus(); | 185 | ret = init_litmus(); |
91 | // if (ret < 0) | 186 | if (ret < 0) |
92 | // perror("init_litmus()"); | 187 | perror("init_litmus()"); |
93 | 188 | ||
94 | ret = task_mode(LITMUS_RT_TASK); | 189 | ret = task_mode(LITMUS_RT_TASK); |
95 | if (ret != 0) | 190 | if (ret != 0) |
@@ -100,10 +195,12 @@ int main(int argc, char** argv) | |||
100 | if (ret != 0) | 195 | if (ret != 0) |
101 | bail_out("wait_for_ts_release()"); | 196 | bail_out("wait_for_ts_release()"); |
102 | } | 197 | } |
198 | |||
199 | |||
103 | start = wctime(); | 200 | start = wctime(); |
104 | 201 | ||
105 | while (start + duration > wctime()) { | 202 | while (start + duration > wctime()) { |
106 | for (i = 0; i < 500000; i++); | 203 | job(wcet * 0.0009); /* 90% wcet, in seconds */ |
107 | } | 204 | } |
108 | 205 | ||
109 | return 0; | 206 | return 0; |