aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Erickson <jerickso@cs.unc.edu>2013-05-02 21:54:37 -0400
committerJeremy Erickson <jerickso@cs.unc.edu>2013-05-02 21:54:37 -0400
commitf9436915a157da898b4015637b66a559dc71223b (patch)
tree441fea93b6a74a5da292b061ad47e8b4f9b11941
parentece0c6e7b111f2761066b66ea1b34cb2854b3752 (diff)
Add EDF-os versions of rtspin and rt_launch
-rw-r--r--SConstruct2
-rw-r--r--bin/rt_launch_edfos.c138
-rw-r--r--bin/rtspin_edfos.c268
3 files changed, 408 insertions, 0 deletions
diff --git a/SConstruct b/SConstruct
index 3b7aa6c..617948d 100644
--- a/SConstruct
+++ b/SConstruct
@@ -209,7 +209,9 @@ mtrt.Program('base_mt_task', 'bin/base_mt_task.c')
209rt.Program('rt_launch', ['bin/rt_launch.c', 'bin/common.c']) 209rt.Program('rt_launch', ['bin/rt_launch.c', 'bin/common.c'])
210rt.Program('rtspin', ['bin/rtspin.c', 'bin/common.c']) 210rt.Program('rtspin', ['bin/rtspin.c', 'bin/common.c'])
211rt.Program('rtspin_edffm', ['bin/rtspin_edffm.c', 'bin/common.c']) 211rt.Program('rtspin_edffm', ['bin/rtspin_edffm.c', 'bin/common.c'])
212rt.Program('rtspin_edfos', ['bin/rtspin_edfos.c', 'bin/common.c'])
212rt.Program('rt_launch_edffm', ['bin/rt_launch_edffm.c', 'bin/common.c']) 213rt.Program('rt_launch_edffm', ['bin/rt_launch_edffm.c', 'bin/common.c'])
214rt.Program('rt_launch_edfos', ['bin/rt_launch_edfos.c', 'bin/common.c'])
213rt.Program('rtspin_npsf', ['bin/rtspin_npsf.c', 'bin/common.c']) 215rt.Program('rtspin_npsf', ['bin/rtspin_npsf.c', 'bin/common.c'])
214rt.Program('npsf_add_server', ['bin/npsf_add_server.c', 'bin/common.c']) 216rt.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']) 217rt.Program('rt_launch_npsf', ['bin/rt_launch_npsf.c', 'bin/common.c'])
diff --git a/bin/rt_launch_edfos.c b/bin/rt_launch_edfos.c
new file mode 100644
index 0000000..43ebee5
--- /dev/null
+++ b/bin/rt_launch_edfos.c
@@ -0,0 +1,138 @@
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][-v][-p cpu][-c hrt | srt | be] wcet period"
33 " fracnum1 fracden1 cpu1 fracnum2 fracden2 cpu2 program [arg1 arg2 ...]\n"
34 "\t-w\tSynchronous release\n"
35 "\t-v\tVerbose\n"
36 "\t-p\tcpu (or initial cpu)\n"
37 "\t-c\tClass\n"
38 "\twcet, period in ms\n"
39 "\tprogram to be launched\n",
40 error);
41 exit(1);
42}
43
44
45#define OPTSTR "p:c:vw"
46
47int main(int argc, char** argv)
48{
49 int ret;
50 lt_t wcet;
51 lt_t period;
52 /* [num,den] */
53 lt_t fracs[NR_CPUS][2];
54 int migrate = 0;
55 int cpu = 0;
56 int opt;
57 int verbose = 0;
58 int wait = 0;
59 int i;
60 startup_info_t info;
61 task_class_t class = RT_CLASS_HARD;
62
63 for (i = 0; i < NR_CPUS; i++) {
64 fracs[i][0] = 0;
65 fracs[i][1] = 0;
66 }
67
68 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
69 switch (opt) {
70 case 'w':
71 wait = 1;
72 break;
73 case 'v':
74 verbose = 1;
75 break;
76 case 'p':
77 cpu = atoi(optarg);
78 fracs[cpu][0] = 1;
79 fracs[cpu][1] = 1;
80 migrate = 1;
81 break;
82 case 'c':
83 class = str2class(optarg);
84 if (class == -1)
85 usage("Unknown task class.");
86 break;
87 case ':':
88 usage("Argument missing.");
89 break;
90 case '?':
91 default:
92 usage("Bad argument.");
93 break;
94 }
95 }
96
97 signal(SIGUSR1, SIG_IGN);
98
99 if ((argc - (optind + 2)) % 3 != 0)
100 usage("Arguments missing.");
101 wcet = ms2lt(atoi(argv[optind + 0]));
102 period = ms2lt(atoi(argv[optind + 1]));
103
104 for (i = optind + 1; i < argc; i+= 3) {
105 cpu = atoi(argv[i+2]);
106 fracs[cpu][0] = atoi(argv[i]);
107 fracs[cpu][1] = atoi(argv[i+1]);
108 }
109 if (wcet <= 0)
110 usage("The worst-case execution time must be a "
111 "positive number.");
112 if (period <= 0)
113 usage("The period must be a positive number.");
114 if (wcet > period) {
115 usage("The worst-case execution time must not "
116 "exceed the period.");
117 }
118 info.exec_path = argv[optind + 8];
119 info.argv = argv + optind + 8;
120 info.wait = wait;
121 if (migrate) {
122 ret = be_migrate_to(cpu);
123 if (ret < 0)
124 bail_out("could not migrate to target partition");
125 }
126 /* create in src/task.c a new wrapper for the __launch_rt_task
127 * which takes the fraction and the cpus */
128 ret = __create_rt_task_edfos(launch, &info, wcet, period, fracs,
129 class);
130
131
132 if (ret < 0)
133 bail_out("could not create rt child process");
134 else if (verbose)
135 printf("%d\n", ret);
136
137 return 0;
138}
diff --git a/bin/rtspin_edfos.c b/bin/rtspin_edfos.c
new file mode 100644
index 0000000..e39a8c0
--- /dev/null
+++ b/bin/rtspin_edfos.c
@@ -0,0 +1,268 @@
1#include <sys/time.h>
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <time.h>
7
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] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION fracnum1 fracden1 cpu1 fracnum2 fracden2 cpu2\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 "p:c:wld:v"
137
138int main(int argc, char** argv)
139{
140 int ret;
141 lt_t wcet;
142 lt_t period;
143 /* [num,den] */
144 lt_t fracs[NR_CPUS][2];
145 double wcet_ms, period_ms;
146 int migrate = 0;
147 int cpu = 0;
148 int opt;
149 int wait = 0;
150 int test_loop = 0;
151 int skip_config = 0;
152 int verbose = 0;
153 int i;
154 double duration, start;
155 task_class_t class = RT_CLASS_HARD;
156
157 progname = argv[0];
158
159 for (i = 0; i < NR_CPUS; i++) {
160 fracs[i][0] = 0;
161 fracs[i][1] = 1;
162 }
163
164 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
165 switch (opt) {
166 case 'w':
167 wait = 1;
168 break;
169 case 'p':
170 cpu = atoi(optarg);
171 fracs[cpu][0] = 1;
172 fracs[cpu][1] = 1;
173 migrate = 1;
174 break;
175 case 'c':
176 class = str2class(optarg);
177 if (class == -1)
178 usage("Unknown task class.");
179 break;
180 case 'l':
181 test_loop = 1;
182 break;
183 case 'd':
184 /* manually configure delay per loop iteration
185 * unit: microseconds */
186 loop_length = atof(optarg) / 1000000;
187 skip_config = 1;
188 break;
189 case 'v':
190 verbose = 1;
191 break;
192 case ':':
193 usage("Argument missing.");
194 break;
195 case '?':
196 default:
197 usage("Bad argument.");
198 break;
199 }
200 }
201
202
203 if (!skip_config)
204 configure_loop();
205
206 if (test_loop) {
207 debug_delay_loop();
208 return 0;
209 }
210
211 if ((argc - (optind + 3)) % 3 != 0)
212 usage("Arguments missing.");
213 wcet_ms = atof(argv[optind + 0]);
214 period_ms = atof(argv[optind + 1]);
215 duration = atof(argv[optind + 2]);
216 /* frac num, den = 0 means fixed task */
217 for (i = optind + 3; i < argc; i += 3) {
218 cpu = atof(argv[i]);
219 fracs[cpu][0] = argv[i+1];
220 fracs[cpu][1] = argv[i+2];
221 }
222 wcet = wcet_ms * __NS_PER_MS;
223 period = period_ms * __NS_PER_MS;
224 if (wcet <= 0)
225 usage("The worst-case execution time must be a "
226 "positive number.");
227 if (period <= 0)
228 usage("The period must be a positive number.");
229 if (wcet > period) {
230 usage("The worst-case execution time must not "
231 "exceed the period.");
232 }
233
234 if (migrate) {
235 ret = be_migrate_to(cpu);
236 if (ret < 0)
237 bail_out("could not migrate to target partition");
238 }
239
240 ret = sporadic_task_ns_edfos(wcet, period, 0, fracs, class,
241 NO_ENFORCEMENT);
242
243 if (ret < 0)
244 bail_out("could not setup rt task params");
245
246 if (verbose)
247 show_loop_length();
248
249 init_litmus();
250
251 ret = task_mode(LITMUS_RT_TASK);
252 if (ret != 0)
253 bail_out("could not become RT task");
254
255 if (wait) {
256 ret = wait_for_ts_release();
257 if (ret != 0)
258 bail_out("wait_for_ts_release()");
259 }
260
261 start = wctime();
262
263 while (start + duration > wctime()) {
264 job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
265 }
266
267 return 0;
268}