aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2011-10-10 22:09:45 -0400
committerChristopher Kenna <cjk@cs.unc.edu>2011-10-10 22:09:45 -0400
commitf3afa50681cde8a3b26a93b3e87db85a1230c21f (patch)
tree87835a51b9844c42ddb6e4415165068b1dced56a
parentb6c2c3cb4e727a4dd7e4f2df3b5c7b634338c845 (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--Makefile5
-rw-r--r--bin/rtspin.ovh.c243
2 files changed, 247 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index ae06ce5..36d395b 100644
--- a/Makefile
+++ b/Makefile
@@ -70,7 +70,7 @@ 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 release_ts measure_syscall \ 73rt-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
211obj-rtspin = rtspin.o common.o 211obj-rtspin = rtspin.o common.o
212lib-rtspin = -lrt 212lib-rtspin = -lrt
213 213
214obj-rtspin.ovh = rtspin.ovh.o common.o
215lib-rtspin.ovh = -lrt
216
214obj-release_ts = release_ts.o 217obj-release_ts = release_ts.o
215 218
216obj-measure_syscall = null_call.o 219obj-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
17static 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
32static int num[NUMS];
33static char* progname;
34
35static 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
43static 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
69static 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
87static 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
98enum 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
112int 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}