diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2010-11-29 11:44:11 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2010-11-29 11:44:11 -0500 |
commit | 9a68dbea3ce813ead95b3b4b3ceb2542bc5ca670 (patch) | |
tree | a9a25a9bfa27cf6899fb651b8c78e20b4c37f5aa | |
parent | e83917699a930e63a34a8b112258b1d5e4031048 (diff) |
Feature: Allow rtspin to change its execution time dynamically
New controls added to rtspin that allow the user to specify different
execution time behaviors for rtspin. Behaviors are characterized by
waveforms. For example, execution time may follow a sine-wave pattern
over time. Supported waveforms are: flat, sin, triangle, box, sawtooth,
and reverse sawtooth.
-rw-r--r-- | SConstruct | 2 | ||||
-rw-r--r-- | bin/rtspin.c | 220 |
2 files changed, 214 insertions, 8 deletions
@@ -177,7 +177,7 @@ if not (env.GetOption('clean') or env.GetOption('help')): | |||
177 | 177 | ||
178 | # link with liblitmus | 178 | # link with liblitmus |
179 | rt = env.Clone( | 179 | rt = env.Clone( |
180 | LIBS = Split('litmus rt'), | 180 | LIBS = Split('litmus rt m'), |
181 | LIBPATH = '.' | 181 | LIBPATH = '.' |
182 | ) | 182 | ) |
183 | rt.Append(LINKFLAGS = '-static') | 183 | rt.Append(LINKFLAGS = '-static') |
diff --git a/bin/rtspin.c b/bin/rtspin.c index 650fcb3..939d507 100644 --- a/bin/rtspin.c +++ b/bin/rtspin.c | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <stdlib.h> | 4 | #include <stdlib.h> |
5 | #include <unistd.h> | 5 | #include <unistd.h> |
6 | #include <time.h> | 6 | #include <time.h> |
7 | 7 | #include <math.h> | |
8 | 8 | ||
9 | #include "litmus.h" | 9 | #include "litmus.h" |
10 | #include "common.h" | 10 | #include "common.h" |
@@ -30,8 +30,14 @@ static double wctime() | |||
30 | void usage(char *error) { | 30 | void usage(char *error) { |
31 | fprintf(stderr, "Error: %s\n", error); | 31 | fprintf(stderr, "Error: %s\n", error); |
32 | fprintf(stderr, | 32 | fprintf(stderr, |
33 | "Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION\n" | 33 | "Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] [-A fp# -B fp# -W wave# -M max_wcet -P #jobs [-D #jobs]] WCET PERIOD DURATION\n" |
34 | " rt_spin -l\n"); | 34 | " rt_spin -l\n" |
35 | " -A: Feedback control 'A' parameter\n" | ||
36 | " -B: Feedback control 'B' parameter\n" | ||
37 | " -W: 0 = flat; 1 = sine; 2 = triangle; 3 = box; 4 = sawtooth; 5 = reverse sawtooth\n" | ||
38 | " -M: max wcet (WCET is assumed min wcet)\n" | ||
39 | " -P: period of execution behavior wave\n" | ||
40 | " -D: Number of jobs wave should hold at extrema points (default = 0)\n"); | ||
35 | exit(1); | 41 | exit(1); |
36 | } | 42 | } |
37 | 43 | ||
@@ -133,7 +139,107 @@ static int job(double exec_time) | |||
133 | return 0; | 139 | return 0; |
134 | } | 140 | } |
135 | 141 | ||
136 | #define OPTSTR "p:c:wld:ve" | 142 | fp_t float_to_frac(double f) |
143 | { | ||
144 | fpbuf_t num; | ||
145 | fpbuf_t denom = 1000; /* express in 1000ths */ | ||
146 | |||
147 | num = (fpbuf_t)f * denom; | ||
148 | if(f != floor(f)) | ||
149 | { | ||
150 | num += (fpbuf_t)(f - floor(f)) * denom; | ||
151 | } | ||
152 | |||
153 | return(_frac(num, denom)); | ||
154 | } | ||
155 | |||
156 | #define OPTSTR "p:c:wld:veA:B:W:M:P:D:" | ||
157 | |||
158 | struct wave_data; | ||
159 | typedef double(*wave_func)(int, struct wave_data*); | ||
160 | |||
161 | struct wave_data | ||
162 | { | ||
163 | double min_wcet_ms; | ||
164 | double max_wcet_ms; | ||
165 | double amplitude; | ||
166 | int period; | ||
167 | int extrema_delay; | ||
168 | int min_point; | ||
169 | int max_point; | ||
170 | wave_func f; | ||
171 | }; | ||
172 | |||
173 | double flat_wave(int count, struct wave_data* w) | ||
174 | { | ||
175 | return(w->min_wcet_ms); | ||
176 | } | ||
177 | |||
178 | double sin_wave(int count, struct wave_data* w) | ||
179 | { | ||
180 | double step = count % w->period; | ||
181 | double exe = w->min_wcet_ms + w->amplitude * sin(M_PI*step/w->period); | ||
182 | return(exe); | ||
183 | } | ||
184 | |||
185 | double tri_wave(int count, struct wave_data* w) | ||
186 | { | ||
187 | double step = count % w->period; | ||
188 | double v = 2.0 * (step/w->period - floor(step/w->period + 0.5)); | ||
189 | double exe = w->min_wcet_ms + w->amplitude * abs(v); | ||
190 | return(exe); | ||
191 | } | ||
192 | |||
193 | double box_wave(int count, struct wave_data* w) | ||
194 | { | ||
195 | double step = count % w->period; | ||
196 | double exe = w->min_wcet_ms + w->amplitude *((step/w->period < 0.5) ? 0 : 1); | ||
197 | return(exe); | ||
198 | } | ||
199 | |||
200 | double saw_wave(int count, struct wave_data* w) | ||
201 | { | ||
202 | double step = (count % w->period)/2.0; | ||
203 | double v = 2.0 * (step/w->period - floor(step/w->period + 0.5)); | ||
204 | double exe; | ||
205 | if(v < 0) v += 1.0; | ||
206 | exe = w->min_wcet_ms + w->amplitude * v; | ||
207 | return(exe); | ||
208 | } | ||
209 | |||
210 | double rsaw_wave(int count, struct wave_data* w) | ||
211 | { | ||
212 | double step = (count % w->period)/2.0; | ||
213 | double v = 2.0 * (step/w->period - floor(step/w->period + 0.5)); | ||
214 | double exe; | ||
215 | if(v < 0) v += 1.0; | ||
216 | exe = w->max_wcet_ms - w->amplitude * v; | ||
217 | return(exe); | ||
218 | } | ||
219 | |||
220 | double get_execution_time(int count, struct wave_data* w) | ||
221 | { | ||
222 | static int skips = 0; | ||
223 | static int delay_count = 0; | ||
224 | |||
225 | if(w->extrema_delay) | ||
226 | { | ||
227 | int at_max = (((count - skips) % w->period) == w->max_point); | ||
228 | int at_min = (((count - skips) % w->period) == w->min_point); | ||
229 | |||
230 | if((at_max || at_min) && delay_count++ < w->extrema_delay) | ||
231 | { | ||
232 | ++skips; | ||
233 | return((at_max) ? w->max_wcet_ms : w->min_wcet_ms); | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | delay_count = 0; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | return(w->f(count - skips, w)); | ||
242 | } | ||
137 | 243 | ||
138 | int main(int argc, char** argv) | 244 | int main(int argc, char** argv) |
139 | { | 245 | { |
@@ -152,6 +258,18 @@ int main(int argc, char** argv) | |||
152 | double duration, start; | 258 | double duration, start; |
153 | task_class_t class = RT_CLASS_HARD; | 259 | task_class_t class = RT_CLASS_HARD; |
154 | 260 | ||
261 | fp_t A = LITMUS_FP_ZERO, B = LITMUS_FP_ZERO; | ||
262 | struct wave_data wave = { | ||
263 | .min_wcet_ms = 0.0, | ||
264 | .max_wcet_ms = 0.0, | ||
265 | .amplitude = 0.0, | ||
266 | .period = 0, | ||
267 | .extrema_delay = 0, | ||
268 | .max_point = 0, | ||
269 | .min_point = 0, | ||
270 | .f = NULL | ||
271 | }; | ||
272 | |||
155 | progname = argv[0]; | 273 | progname = argv[0]; |
156 | 274 | ||
157 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | 275 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { |
@@ -183,6 +301,49 @@ int main(int argc, char** argv) | |||
183 | case 'v': | 301 | case 'v': |
184 | verbose = 1; | 302 | verbose = 1; |
185 | break; | 303 | break; |
304 | case 'A': | ||
305 | A = float_to_frac(atof(optarg)); | ||
306 | break; | ||
307 | case 'B': | ||
308 | B = float_to_frac(atof(optarg)); | ||
309 | break; | ||
310 | case 'W': | ||
311 | switch(atoi(optarg)) | ||
312 | { | ||
313 | case 0: | ||
314 | wave.f = flat_wave; | ||
315 | break; | ||
316 | case 1: | ||
317 | wave.f = sin_wave; | ||
318 | break; | ||
319 | case 2: | ||
320 | wave.f = tri_wave; | ||
321 | break; | ||
322 | case 3: | ||
323 | wave.f = box_wave; | ||
324 | break; | ||
325 | case 4: | ||
326 | wave.f = saw_wave; | ||
327 | break; | ||
328 | case 5: | ||
329 | wave.f = rsaw_wave; | ||
330 | break; | ||
331 | default: | ||
332 | usage("Bad wave identifier."); | ||
333 | break; | ||
334 | } | ||
335 | break; | ||
336 | case 'M': | ||
337 | wave.max_wcet_ms = atof(optarg); | ||
338 | break; | ||
339 | case 'P': | ||
340 | wave.period = atoi(optarg); | ||
341 | if(wave.period <= 0) | ||
342 | usage("Execution behavior period must be a positive number."); | ||
343 | break; | ||
344 | case 'D': | ||
345 | wave.extrema_delay = atoi(optarg); | ||
346 | break; | ||
186 | case ':': | 347 | case ':': |
187 | usage("Argument missing."); | 348 | usage("Argument missing."); |
188 | break; | 349 | break; |
@@ -219,6 +380,42 @@ int main(int argc, char** argv) | |||
219 | "exceed the period."); | 380 | "exceed the period."); |
220 | } | 381 | } |
221 | 382 | ||
383 | if(wave.f != NULL) | ||
384 | { | ||
385 | wave.min_wcet_ms = wcet_ms; | ||
386 | wave.amplitude = wave.max_wcet_ms - wave.min_wcet_ms; | ||
387 | if(wave.amplitude < 0.0) | ||
388 | { | ||
389 | usage("The max wcet must be greater than min wcet."); | ||
390 | } | ||
391 | |||
392 | if(wave.f == flat_wave) | ||
393 | { | ||
394 | wave.max_point = 0; | ||
395 | wave.min_point = 0; | ||
396 | } | ||
397 | else if((wave.f == sin_wave) || (wave.f == tri_wave) || (wave.f == box_wave)) | ||
398 | { | ||
399 | wave.max_point = wave.period/2; | ||
400 | wave.min_point = 0; | ||
401 | } | ||
402 | else if(wave.f == saw_wave) | ||
403 | { | ||
404 | wave.max_point = wave.period-1; | ||
405 | wave.min_point = 0; | ||
406 | } | ||
407 | else if(wave.f == rsaw_wave) | ||
408 | { | ||
409 | wave.max_point = 0; | ||
410 | wave.min_point = wave.period-1; | ||
411 | } | ||
412 | |||
413 | if((wave.f == flat_wave) || (wave.f == box_wave)) | ||
414 | { | ||
415 | wave.extrema_delay = 0; | ||
416 | } | ||
417 | } | ||
418 | |||
222 | if (migrate) { | 419 | if (migrate) { |
223 | ret = be_migrate_to(cpu); | 420 | ret = be_migrate_to(cpu); |
224 | if (ret < 0) | 421 | if (ret < 0) |
@@ -226,7 +423,7 @@ int main(int argc, char** argv) | |||
226 | } | 423 | } |
227 | 424 | ||
228 | ret = sporadic_task_ns(wcet, period, 0, | 425 | ret = sporadic_task_ns(wcet, period, 0, |
229 | LITMUS_FP_ZERO, LITMUS_FP_ZERO, | 426 | A, B, |
230 | cpu, class, | 427 | cpu, class, |
231 | want_enforcement ? PRECISE_ENFORCEMENT | 428 | want_enforcement ? PRECISE_ENFORCEMENT |
232 | : NO_ENFORCEMENT, | 429 | : NO_ENFORCEMENT, |
@@ -252,8 +449,17 @@ int main(int argc, char** argv) | |||
252 | 449 | ||
253 | start = wctime(); | 450 | start = wctime(); |
254 | 451 | ||
255 | while (start + duration > wctime()) { | 452 | int count = 0; |
256 | job(wcet_ms * 0.0009); /* 90% wcet, in seconds */ | 453 | while (start + duration > wctime()) |
454 | { | ||
455 | if(wave.f == NULL) | ||
456 | { | ||
457 | job(wcet_ms * 0.0009); /* 90% wcet, in seconds */ | ||
458 | } | ||
459 | else | ||
460 | { | ||
461 | job(get_execution_time(count++, &wave) * 0.0009); | ||
462 | } | ||
257 | } | 463 | } |
258 | 464 | ||
259 | return 0; | 465 | return 0; |