aboutsummaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rw-r--r--bin/common.c119
-rw-r--r--bin/rt_launch_edfwm.c98
-rw-r--r--bin/rtspin_edfwm.c233
3 files changed, 450 insertions, 0 deletions
diff --git a/bin/common.c b/bin/common.c
index 452b882..4fd24e1 100644
--- a/bin/common.c
+++ b/bin/common.c
@@ -1,6 +1,7 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <stdlib.h> 2#include <stdlib.h>
3#include <errno.h> 3#include <errno.h>
4#include <string.h>
4 5
5#include "common.h" 6#include "common.h"
6 7
@@ -9,3 +10,121 @@ void bail_out(const char* msg)
9 perror(msg); 10 perror(msg);
10 exit(-1 * errno); 11 exit(-1 * errno);
11} 12}
13
14/* EDF-WM helper functions to parse a custom text file format to "easily"
15 * launch tests with rtspin and rt_launch:
16 *
17 * Format for task:
18 *
19 * <task_id execution_cost period phase cpu slices_number> .
20 *
21 * If the task is split on multiple slices, slices_number is non 0
22 * and we scan a list of slice parameters up to slices_number:
23 *
24 * Format for slices:
25 *
26 * <task_id cpu deadline(from job release) budget offset> .
27 *
28 * The offset is the start time for the slice relative to the job release.
29 *
30 * Example:
31 * 14 2.26245771754 10 0 5 2
32 * 14 5 5.000000 1.497306 0.000000
33 * 14 7 10.000000 0.765152 5.000000
34 */
35
36#define fms_to_ns(x) (lt_t)(((x) * __NS_PER_MS))
37/*
38 * <task_id, cpu, deadline (from job release), budget, offset> .
39 */
40int parse_edfwm_slice(FILE *ts, int slices_no, int task_id,
41 struct rt_task *rt)
42{
43 int i, tid;
44 unsigned int cpu;
45 double deadline, budget, offset;
46
47 lt_t total_budget = 0;
48
49 struct edf_wm_params* wm = (struct edf_wm_params*) &rt->semi_part;
50
51 for (i = 0; i < slices_no; i++) {
52
53 if (fscanf(ts, "%d %u %lf %lf %lf\n", &tid, &cpu,
54 &deadline, &budget, &offset) != EOF) {
55
56 if (task_id != tid) {
57 fprintf(stderr, "task_id %d != tid %d\n",
58 task_id, tid);
59 return -1;
60 }
61
62 wm->slices[i].deadline = fms_to_ns(deadline);
63 wm->slices[i].budget = fms_to_ns(budget);
64 wm->slices[i].offset = fms_to_ns(offset);
65 wm->slices[i].cpu = cpu;
66
67 printf("slice(tid, cpu, d, e, ph) = (%d, %u, %llu, %llu, %llu)\n",
68 tid, cpu, wm->slices[i].deadline,
69 wm->slices[i].budget, wm->slices[i].offset);
70
71 if (wm->slices[i].budget < MIN_EDF_WM_SLICE_SIZE) {
72
73 fprintf(stderr, "Slice %llu is too small\n",
74 wm->slices[i].budget);
75 return -1;
76 }
77
78 total_budget += wm->slices[i].budget;
79 }
80
81 if (ferror(ts)) {
82 fprintf(stderr, "Cannot read file\n");
83 return -1;
84 }
85 }
86 wm->count = slices_no;
87 rt->exec_cost = total_budget;
88 printf("--- total %u slices ---\n", wm->count);
89 return 0;
90}
91
92/*
93 * <task_id, execution_cost, period, phase, cpu, slices_number> .
94 */
95int parse_edfwm_ts_file(FILE *ts, struct rt_task *rt)
96{
97 int task_id, ret = 1;
98 unsigned int cpu, sliceno;
99 double fwcet, fperiod, fphase;
100
101 ret = fscanf(ts, "%d %lf %lf %lf %d %d\n",
102 &task_id, &fwcet, &fperiod, &fphase, &cpu, &sliceno);
103
104 if (ferror(ts))
105 goto err;
106
107 rt->exec_cost = fms_to_ns(fwcet);
108 rt->period = fms_to_ns(fperiod);
109 rt->phase = fms_to_ns(fphase);
110 rt->cpu = cpu;
111 rt->cls = RT_CLASS_HARD;
112 rt->budget_policy = PRECISE_ENFORCEMENT;
113
114 printf("(tid, wcet, period, ph, cpu, slices) = "
115 "(%d, %llu, %llu, %llu, %u, %u)\n",
116 task_id, rt->exec_cost, rt->period, rt->phase, cpu, sliceno);
117 if (sliceno > 0) {
118 memset(&rt->semi_part, 0, sizeof(struct edf_wm_params));
119 ret = parse_edfwm_slice(ts, sliceno, task_id, rt);
120 if (ret < 0)
121 goto err;
122 }
123
124 return 0;
125
126err:
127 fprintf(stderr, "Error parsing file\n");
128 return -1;
129}
130
diff --git a/bin/rt_launch_edfwm.c b/bin/rt_launch_edfwm.c
new file mode 100644
index 0000000..9e8a322
--- /dev/null
+++ b/bin/rt_launch_edfwm.c
@@ -0,0 +1,98 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <limits.h>
6#include <signal.h>
7
8#include "litmus.h"
9#include "common.h"
10
11typedef struct {
12 int wait;
13 char * exec_path;
14 char ** argv;
15} startup_info_t;
16
17
18int launch(void *task_info_p) {
19 startup_info_t *info = (startup_info_t*) task_info_p;
20 int ret;
21 if (info->wait) {
22 ret = wait_for_ts_release();
23 if (ret != 0)
24 perror("wait_for_ts_release()");
25 }
26 ret = execvp(info->exec_path, info->argv);
27 perror("execv failed");
28 return ret;
29}
30
31void usage(char *error) {
32 fprintf(stderr, "%s\nUsage: rt_launch [-w] task_parameters_file "
33 "program [arg1 arg2 ...]\n"
34 "\t-w\tSynchronous release\n"
35 "\tprogram to be launched\n",
36 error);
37 exit(1);
38}
39
40#define OPTSTR "w"
41
42int main(int argc, char** argv)
43{
44 int ret;
45 int wait = 0;
46 int opt;
47 startup_info_t info;
48
49 struct rt_task rt;
50 FILE *file;
51
52 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
53 switch (opt) {
54 case 'w':
55 wait = 1;
56 break;
57 case ':':
58 usage("Argument missing.");
59 break;
60 case '?':
61 default:
62 usage("Bad argument.");
63 break;
64 }
65 }
66
67 signal(SIGUSR1, SIG_IGN);
68
69 if (argc - optind < 2)
70 usage("Arguments missing.");
71
72 if ((file = fopen(argv[optind + 0], "r")) == NULL) {
73 fprintf(stderr, "Cannot open %s\n", argv[1]);
74 return -1;
75 }
76
77 memset(&rt, 0, sizeof(struct rt_task));
78
79 if (parse_edfwm_ts_file(file, &rt) < 0)
80 bail_out("Could not parse file\n");
81
82 if (sporadic_task_ns_semi(&rt) < 0)
83 bail_out("could not setup rt task params");
84
85 fclose(file);
86
87 info.exec_path = argv[optind + 1];
88 info.argv = argv + optind + 1;
89 info.wait = wait;
90
91 ret = create_rt_task_semi(launch, &info, &rt);
92
93 if (ret < 0)
94 bail_out("could not create rt child process");
95
96 return 0;
97}
98
diff --git a/bin/rtspin_edfwm.c b/bin/rtspin_edfwm.c
new file mode 100644
index 0000000..21a5f3b
--- /dev/null
+++ b/bin/rtspin_edfwm.c
@@ -0,0 +1,233 @@
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 OPTSTR "wld:v"
137
138int main(int argc, char** argv)
139{
140 int ret;
141
142 int opt;
143 int wait = 0;
144 int test_loop = 0;
145 int skip_config = 0;
146 int verbose = 0;
147 double wcet_ms;
148 double duration, start;
149
150 struct rt_task rt;
151 FILE *file;
152
153 progname = argv[0];
154
155 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
156 switch (opt) {
157 case 'w':
158 wait = 1;
159 break;
160 case 'l':
161 test_loop = 1;
162 break;
163 case 'd':
164 /* manually configure delay per loop iteration
165 * unit: microseconds */
166 loop_length = atof(optarg) / 1000000;
167 skip_config = 1;
168 break;
169 case 'v':
170 verbose = 1;
171 break;
172 case ':':
173 usage("Argument missing.");
174 break;
175 case '?':
176 default:
177 usage("Bad argument.");
178 break;
179 }
180 }
181
182
183 if (!skip_config)
184 configure_loop();
185
186 if (test_loop) {
187 debug_delay_loop();
188 return 0;
189 }
190
191 if (argc - optind < 2)
192 usage("Arguments missing.");
193
194 if ((file = fopen(argv[optind + 0], "r")) == NULL) {
195 fprintf(stderr, "Cannot open %s\n", argv[1]);
196 return -1;
197 }
198 duration = atof(argv[optind + 1]);
199
200 memset(&rt, 0, sizeof(struct rt_task));
201
202 if (parse_edfwm_ts_file(file, &rt) < 0)
203 bail_out("Could not parse file\n");
204
205 if (sporadic_task_ns_semi(&rt) < 0)
206 bail_out("could not setup rt task params");
207
208 fclose(file);
209
210 if (verbose)
211 show_loop_length();
212
213 init_litmus();
214
215 ret = task_mode(LITMUS_RT_TASK);
216 if (ret != 0)
217 bail_out("could not become RT task");
218
219 if (wait) {
220 ret = wait_for_ts_release();
221 if (ret != 0)
222 bail_out("wait_for_ts_release()");
223 }
224
225 wcet_ms = ((double) rt.exec_cost ) / __NS_PER_MS;
226 start = wctime();
227
228 while (start + duration > wctime()) {
229 job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
230 }
231
232 return 0;
233}