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