diff options
author | Christopher Kenna <cjk@cs.unc.edu> | 2011-10-10 22:09:45 -0400 |
---|---|---|
committer | Christopher Kenna <cjk@cs.unc.edu> | 2011-10-10 22:09:45 -0400 |
commit | f3afa50681cde8a3b26a93b3e87db85a1230c21f (patch) | |
tree | 87835a51b9844c42ddb6e4415165068b1dced56a | |
parent | b6c2c3cb4e727a4dd7e4f2df3b5c7b634338c845 (diff) |
Add a new version of RTSpin
This version uses nanoseconds as its parameters and takes an extra
parameter that is the time to run for; i.e., RTSpin does not run for its
WCET, but something less than that.
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | bin/rtspin.ovh.c | 243 |
2 files changed, 247 insertions, 1 deletions
@@ -70,7 +70,7 @@ AR := ${CROSS_COMPILE}${AR} | |||
70 | # Targets | 70 | # Targets |
71 | 71 | ||
72 | all = lib ${rt-apps} | 72 | all = lib ${rt-apps} |
73 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ | 73 | rt-apps = cycles base_task rt_launch rtspin rtspin.ovh release_ts measure_syscall \ |
74 | base_mt_task runtests | 74 | base_mt_task runtests |
75 | 75 | ||
76 | .PHONY: all lib clean dump-config TAGS tags cscope help | 76 | .PHONY: all lib clean dump-config TAGS tags cscope help |
@@ -211,6 +211,9 @@ obj-rt_launch = rt_launch.o common.o | |||
211 | obj-rtspin = rtspin.o common.o | 211 | obj-rtspin = rtspin.o common.o |
212 | lib-rtspin = -lrt | 212 | lib-rtspin = -lrt |
213 | 213 | ||
214 | obj-rtspin.ovh = rtspin.ovh.o common.o | ||
215 | lib-rtspin.ovh = -lrt | ||
216 | |||
214 | obj-release_ts = release_ts.o | 217 | obj-release_ts = release_ts.o |
215 | 218 | ||
216 | obj-measure_syscall = null_call.o | 219 | obj-measure_syscall = null_call.o |
diff --git a/bin/rtspin.ovh.c b/bin/rtspin.ovh.c new file mode 100644 index 0000000..31a4458 --- /dev/null +++ b/bin/rtspin.ovh.c | |||
@@ -0,0 +1,243 @@ | |||
1 | #include <sys/time.h> | ||
2 | |||
3 | #include <stdio.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <unistd.h> | ||
6 | #include <time.h> | ||
7 | #include <assert.h> | ||
8 | #include <strings.h> | ||
9 | |||
10 | |||
11 | #include "litmus.h" | ||
12 | #include "common.h" | ||
13 | |||
14 | #include <litmus/sched_mc.h> | ||
15 | |||
16 | |||
17 | static void usage(char *error) { | ||
18 | fprintf(stderr, "Error: %s\n", error); | ||
19 | fprintf(stderr, | ||
20 | "Usage:\n" | ||
21 | " rt_spin [COMMON-OPTS] EXEC_TIME WCET PERIOD DURATION\n" | ||
22 | " rt_spin -l\n" | ||
23 | "\n" | ||
24 | "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n" | ||
25 | " [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n" | ||
26 | "\n" | ||
27 | "WCET and PERIOD are nanoseconds, DURATION is seconds.\n"); | ||
28 | exit(EXIT_FAILURE); | ||
29 | } | ||
30 | |||
31 | #define NUMS 4096 | ||
32 | static int num[NUMS]; | ||
33 | static char* progname; | ||
34 | |||
35 | static int loop_once(void) | ||
36 | { | ||
37 | int i, j = 0; | ||
38 | for (i = 0; i < NUMS; i++) | ||
39 | j += num[i]++; | ||
40 | return j; | ||
41 | } | ||
42 | |||
43 | static int loop_for(double exec_time, double emergency_exit) | ||
44 | { | ||
45 | double last_loop = 0, loop_start; | ||
46 | int tmp = 0; | ||
47 | |||
48 | double start = cputime(); | ||
49 | double now = cputime(); | ||
50 | |||
51 | while (now + last_loop < start + exec_time) { | ||
52 | loop_start = now; | ||
53 | tmp += loop_once(); | ||
54 | now = cputime(); | ||
55 | last_loop = now - loop_start; | ||
56 | if (emergency_exit && wctime() > emergency_exit) { | ||
57 | /* Oops --- this should only be possible if the execution time tracking | ||
58 | * is broken in the LITMUS^RT kernel. */ | ||
59 | fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid()); | ||
60 | fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n"); | ||
61 | break; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | return tmp; | ||
66 | } | ||
67 | |||
68 | |||
69 | static void debug_delay_loop(void) | ||
70 | { | ||
71 | double start, end, delay; | ||
72 | |||
73 | while (1) { | ||
74 | for (delay = 0.5; delay > 0.01; delay -= 0.01) { | ||
75 | start = wctime(); | ||
76 | loop_for(delay, 0); | ||
77 | end = wctime(); | ||
78 | printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n", | ||
79 | delay, | ||
80 | end - start, | ||
81 | end - start - delay, | ||
82 | 100 * (end - start - delay) / delay); | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | |||
87 | static int job(double exec_time, double program_end) | ||
88 | { | ||
89 | if (wctime() > program_end) | ||
90 | return 0; | ||
91 | else { | ||
92 | loop_for(exec_time, program_end + 1); | ||
93 | sleep_next_period(); | ||
94 | return 1; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | enum crit_level str2crit(const char* str) | ||
99 | { | ||
100 | if (0 == strncasecmp("a", str, 1)) | ||
101 | return CRIT_LEVEL_A; | ||
102 | else if (0 == strncasecmp("b", str, 1)) | ||
103 | return CRIT_LEVEL_B; | ||
104 | else if (0 == strncasecmp("c", str, 1)) | ||
105 | return CRIT_LEVEL_C; | ||
106 | /* failure */ | ||
107 | return NUM_CRIT_LEVELS; | ||
108 | } | ||
109 | |||
110 | #define OPTSTR "p:c:wlveo:f:s:r:i:" | ||
111 | |||
112 | int main(int argc, char** argv) | ||
113 | { | ||
114 | int ret; | ||
115 | lt_t exec_time; | ||
116 | lt_t wcet; | ||
117 | lt_t period; | ||
118 | int migrate = 0; | ||
119 | int cpu = 0; | ||
120 | int opt; | ||
121 | int wait = 0; | ||
122 | int test_loop = 0; | ||
123 | int column = 1; | ||
124 | int want_enforcement = 0; | ||
125 | double duration = 0, start; | ||
126 | double scale = 1.0; | ||
127 | task_class_t class = RT_CLASS_HARD; | ||
128 | struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 }; | ||
129 | |||
130 | progname = argv[0]; | ||
131 | |||
132 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | ||
133 | switch (opt) { | ||
134 | case 'w': | ||
135 | wait = 1; | ||
136 | break; | ||
137 | case 'p': | ||
138 | cpu = atoi(optarg); | ||
139 | migrate = 1; | ||
140 | break; | ||
141 | case 'c': | ||
142 | class = str2class(optarg); | ||
143 | if (class == -1) | ||
144 | usage("Unknown task class."); | ||
145 | break; | ||
146 | case 'e': | ||
147 | want_enforcement = 1; | ||
148 | break; | ||
149 | case 'l': | ||
150 | test_loop = 1; | ||
151 | break; | ||
152 | case 'o': | ||
153 | column = atoi(optarg); | ||
154 | break; | ||
155 | case 's': | ||
156 | scale = atof(optarg); | ||
157 | break; | ||
158 | case 'r': | ||
159 | mc_task.crit = str2crit(optarg); | ||
160 | if (NUM_CRIT_LEVELS == mc_task.crit) | ||
161 | usage("Bad crit level."); | ||
162 | break; | ||
163 | case 'i': | ||
164 | mc_task.lvl_a_id = atoi(optarg); | ||
165 | break; | ||
166 | case ':': | ||
167 | usage("Argument missing."); | ||
168 | break; | ||
169 | case '?': | ||
170 | default: | ||
171 | usage("Bad argument."); | ||
172 | break; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | if (test_loop) { | ||
177 | debug_delay_loop(); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | if (argc - optind < 4) | ||
182 | usage("Arguments missing."); | ||
183 | |||
184 | exec_time = atoi(argv[optind + 0]); | ||
185 | wcet = atoi(argv[optind + 1]); | ||
186 | period = atoi(argv[optind + 2]); | ||
187 | |||
188 | if (exec_time <= 0 || exec_time > period) | ||
189 | usage("bad execution time"); | ||
190 | if (wcet <= 0) | ||
191 | usage("The worst-case execution time must be a " | ||
192 | "positive number."); | ||
193 | if (period <= 0) | ||
194 | usage("The period must be a positive number."); | ||
195 | if (wcet > period) { | ||
196 | usage("The worst-case execution time must not " | ||
197 | "exceed the period."); | ||
198 | } | ||
199 | |||
200 | duration = atof(argv[optind + 3]); | ||
201 | |||
202 | if (migrate) { | ||
203 | ret = be_migrate_to(cpu); | ||
204 | if (ret < 0) | ||
205 | bail_out("could not migrate to target partition"); | ||
206 | } | ||
207 | |||
208 | ret = sporadic_task_ns(wcet, period, 0, cpu, class, | ||
209 | want_enforcement ? PRECISE_ENFORCEMENT | ||
210 | : NO_ENFORCEMENT, | ||
211 | migrate); | ||
212 | if (ret < 0) | ||
213 | bail_out("could not setup rt task params"); | ||
214 | |||
215 | if (NUM_CRIT_LEVELS != mc_task.crit) { | ||
216 | ret = set_rt_task_mc_param(gettid(), &mc_task); | ||
217 | if (ret < 0) | ||
218 | bail_out("could not setup rt mixed criticality params"); | ||
219 | } | ||
220 | |||
221 | init_litmus(); | ||
222 | |||
223 | ret = task_mode(LITMUS_RT_TASK); | ||
224 | if (ret != 0) | ||
225 | bail_out("could not become RT task"); | ||
226 | |||
227 | if (wait) { | ||
228 | ret = wait_for_ts_release(); | ||
229 | if (ret != 0) | ||
230 | bail_out("wait_for_ts_release()"); | ||
231 | } | ||
232 | |||
233 | start = wctime(); | ||
234 | |||
235 | /* conver to seconds and scale */ | ||
236 | while (job(exec_time * 0.000000001 * scale, start + duration)); | ||
237 | |||
238 | ret = task_mode(BACKGROUND_TASK); | ||
239 | if (ret != 0) | ||
240 | bail_out("could not become regular task (huh?)"); | ||
241 | |||
242 | return 0; | ||
243 | } | ||