aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-09-22 12:06:26 -0400
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2011-01-26 18:20:24 -0500
commit289b53f7b55a30c054e4a2fb7b19fa2cbcf27703 (patch)
tree4173b7deb87ef73e66828ca404aa63ff01026343
parent03b0ba375a39a632988e4ec5ec2b887bc24b92aa (diff)
Add rtspin_edffm launcher function
It reads the parameter for a task from a text file. The format is: - <task-id, wcet, period, phase, firstcpu, number of slices> (for task parameters). - <task-id, cpu, deadline, wcet, phase> (for slices). Example: 15 2.96343109764 10 0 3 7 15 3 1.428571 1.175260 0.000000 15 7 2.857143 0.700065 1.428571 15 2 4.285714 0.504732 2.857143 15 0 5.714286 0.279637 4.285714 15 1 7.142857 0.185294 5.714286 15 4 8.571429 0.065379 7.142857 15 6 10.000000 0.053062 8.571429
-rw-r--r--SConstruct1
-rw-r--r--bin/rtspin_edfwm.c319
2 files changed, 320 insertions, 0 deletions
diff --git a/SConstruct b/SConstruct
index 657a92f..1f4770a 100644
--- a/SConstruct
+++ b/SConstruct
@@ -213,6 +213,7 @@ rt.Program('rt_launch_edffm', ['bin/rt_launch_edffm.c', 'bin/common.c'])
213rt.Program('rtspin_npsf', ['bin/rtspin_npsf.c', 'bin/common.c']) 213rt.Program('rtspin_npsf', ['bin/rtspin_npsf.c', 'bin/common.c'])
214rt.Program('npsf_add_server', ['bin/npsf_add_server.c', 'bin/common.c']) 214rt.Program('npsf_add_server', ['bin/npsf_add_server.c', 'bin/common.c'])
215rt.Program('rt_launch_npsf', ['bin/rt_launch_npsf.c', 'bin/common.c']) 215rt.Program('rt_launch_npsf', ['bin/rt_launch_npsf.c', 'bin/common.c'])
216rt.Program('rtspin_edfwm', ['bin/rtspin_edfwm.c', 'bin/common.c'])
216rt.Program('release_ts', 'bin/release_ts.c') 217rt.Program('release_ts', 'bin/release_ts.c')
217rtm.Program('measure_syscall', 'bin/null_call.c') 218rtm.Program('measure_syscall', 'bin/null_call.c')
218 219
diff --git a/bin/rtspin_edfwm.c b/bin/rtspin_edfwm.c
new file mode 100644
index 0000000..9a78aa3
--- /dev/null
+++ b/bin/rtspin_edfwm.c
@@ -0,0 +1,319 @@
1#include <sys/time.h>
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <time.h>
7#include <string.h>
8
9#include "litmus.h"
10#include "common.h"
11
12
13static double cputime()
14{
15 struct timespec ts;
16 int err;
17 err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
18 if (err != 0)
19 perror("clock_gettime");
20 return (ts.tv_sec + 1E-9 * ts.tv_nsec);
21}
22
23static double wctime()
24{
25 struct timeval tv;
26 gettimeofday(&tv, NULL);
27 return (tv.tv_sec + 1E-6 * tv.tv_usec);
28}
29
30void usage(char *error) {
31 fprintf(stderr, "Error: %s\n", error);
32 fprintf(stderr,
33 "Usage: rt_spin [-w] task_parameters_file duration\n"
34 " rt_spin -l\n");
35 exit(1);
36}
37
38#define NUMS 4096
39static int num[NUMS];
40static double loop_length = 1.0;
41static char* progname;
42
43static int loop_once(void)
44{
45 int i, j = 0;
46 for (i = 0; i < NUMS; i++)
47 j += num[i]++;
48 return j;
49}
50
51static int loop_for(double exec_time)
52{
53 double t = 0;
54 int tmp = 0;
55/* while (t + loop_length < exec_time) {
56 tmp += loop_once();
57 t += loop_length;
58 }
59*/
60 double start = cputime();
61 double now = cputime();
62 while (now + loop_length < start + exec_time) {
63 tmp += loop_once();
64 t += loop_length;
65 now = cputime();
66 }
67
68 return tmp;
69}
70
71static void fine_tune(double interval)
72{
73 double start, end, delta;
74
75 start = wctime();
76 loop_for(interval);
77 end = wctime();
78 delta = (end - start - interval) / interval;
79 if (delta != 0)
80 loop_length = loop_length / (1 - delta);
81}
82
83static void configure_loop(void)
84{
85 double start;
86
87 /* prime cache */
88 loop_once();
89 loop_once();
90 loop_once();
91
92 /* measure */
93 start = wctime();
94 loop_once(); /* hope we didn't get preempted */
95 loop_length = wctime();
96 loop_length -= start;
97
98 /* fine tune */
99 fine_tune(0.1);
100 fine_tune(0.1);
101 fine_tune(0.1);
102}
103
104static void show_loop_length(void)
105{
106 printf("%s/%d: loop_length=%f (%ldus)\n",
107 progname, getpid(), loop_length,
108 (long) (loop_length * 1000000));
109}
110
111static void debug_delay_loop(void)
112{
113 double start, end, delay;
114 show_loop_length();
115 while (1) {
116 for (delay = 0.5; delay > 0.01; delay -= 0.01) {
117 start = wctime();
118 loop_for(delay);
119 end = wctime();
120 printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
121 delay,
122 end - start,
123 end - start - delay,
124 100 * (end - start - delay) / delay);
125 }
126 }
127}
128
129static int job(double exec_time)
130{
131 loop_for(exec_time);
132 sleep_next_period();
133 return 0;
134}
135
136#define fms_to_ns(x) (lt_t)(((x) * __NS_PER_MS))
137/*
138 * <task_id, cpu, deadline (from job release), budget, offset> .
139 */
140int parse_edfwm_slice(FILE *ts, int slices_no, int task_id,
141 struct edf_wm_params *wm)
142{
143 int i, tid;
144 unsigned int cpu;
145 double deadline, budget, offset;
146
147 for (i = 0; i < slices_no; i++) {
148
149 if (fscanf(ts, "%d %u %lf %lf %lf\n", &tid, &cpu,
150 &deadline, &budget, &offset) != EOF) {
151
152 printf("slice(tid, cpu, d, e, ph) = (%d, %u, %lf, %lf, %lf)\n",
153 tid, cpu, deadline, budget, offset);
154
155 if (task_id != tid) {
156 fprintf(stderr, "task_id %d != tid %d\n",
157 task_id, tid);
158 return -1;
159 }
160
161 wm->slices[i].deadline = fms_to_ns(deadline);
162 wm->slices[i].budget = fms_to_ns(budget);
163 wm->slices[i].offset = fms_to_ns(offset);
164 }
165 if (ferror(ts)) {
166 fprintf(stderr, "Cannot read file\n");
167 return -1;
168 }
169 }
170 return 1;
171}
172
173/* Custom format to read parameters for tasks from a plain text file:
174 * <task_id, execution_cost, period, phase, cpu, slices_number> .
175 * If the task is split on multiple slices, slices_number is non 0
176 * and we scan a list of slice parameters up to slices_number:
177 * <task_id, cpu, deadline (from job release), budget, offset> .
178 * The offset is the start time for the slice relative to the job release.
179 *
180 * FIXME: this function should go in a separate file where all the parsing
181 * funtions for the semi-part plugins are. It will help in later testing with
182 * "tasks" programs.
183 */
184int parse_edfwm_ts_file(FILE *ts, struct rt_task *rt)
185{
186 int task_id, ret = 1;
187 unsigned int cpu, sliceno;
188 double fwcet, fperiod, fphase;
189
190 ret = fscanf(ts, "%d %lf %lf %lf %d %d\n",
191 &task_id, &fwcet, &fperiod, &fphase, &cpu, &sliceno);
192
193 if (ret != EOF) {
194
195 printf("(tid, wcet, period, ph, cpu, slices) = "
196 "(%d, %.2f, %.2f, %.2f, %u, %u)\n",
197 task_id, fwcet, fperiod, fphase, cpu, sliceno);
198
199 rt->exec_cost = fms_to_ns(fwcet);
200 rt->period = fms_to_ns(fperiod);
201 rt->phase = fms_to_ns(fphase);
202 rt->cpu = cpu;
203 rt->cls = RT_CLASS_HARD;
204 rt->budget_policy = PRECISE_ENFORCEMENT;
205 if (sliceno > 0) {
206 ret = parse_edfwm_slice(ts, sliceno, task_id,
207 (struct edf_wm_params*) &rt->semi_part);
208 if (ret < 0)
209 goto err;
210 }
211 }
212 if (ferror(ts))
213 goto err;
214
215 return EOF;
216
217err:
218 fprintf(stderr, "Error parsing file\n");
219 return -1;
220}
221
222#define OPTSTR "wld:v"
223
224int main(int argc, char** argv)
225{
226 int ret;
227
228 int opt;
229 int wait = 0;
230 int test_loop = 0;
231 int skip_config = 0;
232 int verbose = 0;
233 double wcet_ms;
234 double duration, start;
235
236 struct rt_task rt;
237 FILE *file;
238
239 progname = argv[0];
240
241 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
242 switch (opt) {
243 case 'w':
244 wait = 1;
245 break;
246 case 'l':
247 test_loop = 1;
248 break;
249 case 'd':
250 /* manually configure delay per loop iteration
251 * unit: microseconds */
252 loop_length = atof(optarg) / 1000000;
253 skip_config = 1;
254 break;
255 case 'v':
256 verbose = 1;
257 break;
258 case ':':
259 usage("Argument missing.");
260 break;
261 case '?':
262 default:
263 usage("Bad argument.");
264 break;
265 }
266 }
267
268
269 if (!skip_config)
270 configure_loop();
271
272 if (test_loop) {
273 debug_delay_loop();
274 return 0;
275 }
276
277 if (argc - optind < 2)
278 usage("Arguments missing.");
279
280 if ((file = fopen(argv[optind + 0], "r")) == NULL) {
281 fprintf(stderr, "Cannot open %s\n", argv[1]);
282 return -1;
283 }
284 duration = atof(argv[optind + 1]);
285
286 memset(&rt, 0, sizeof(struct rt_task));
287
288 while (parse_edfwm_ts_file(file, &rt) != EOF) {
289
290 if (sporadic_task_ns_semi(&rt) < 0)
291 bail_out("could not setup rt task params");
292 }
293
294 fclose(file);
295
296 if (verbose)
297 show_loop_length();
298
299 init_litmus();
300
301 ret = task_mode(LITMUS_RT_TASK);
302 if (ret != 0)
303 bail_out("could not become RT task");
304
305 if (wait) {
306 ret = wait_for_ts_release();
307 if (ret != 0)
308 bail_out("wait_for_ts_release()");
309 }
310
311 wcet_ms = ((double) rt.exec_cost ) / __NS_PER_MS;
312 start = wctime();
313
314 while (start + duration > wctime()) {
315 job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
316 }
317
318 return 0;
319}