aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-06-12 12:14:16 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-06-12 12:14:16 -0400
commit2c34274eb9dca67c916fc8f5d3b6f20bb17202c4 (patch)
tree7c781642e4d15fc603c9cdfde04fdb426863ca31
parente9c900fae35e4e4730469e189ff17bf30518346a (diff)
[EDF-fm] Add support for sporadic edf-fm tasks and rtspin_edffm
-rw-r--r--SConstruct1
-rw-r--r--bin/rtspin_edffm.c263
-rw-r--r--include/litmus.h5
-rw-r--r--src/litmus.c38
4 files changed, 304 insertions, 3 deletions
diff --git a/SConstruct b/SConstruct
index c41e41e..7ae2883 100644
--- a/SConstruct
+++ b/SConstruct
@@ -208,6 +208,7 @@ rt.Program('base_task', 'bin/base_task.c')
208mtrt.Program('base_mt_task', 'bin/base_mt_task.c') 208mtrt.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('release_ts', 'bin/release_ts.c') 212rt.Program('release_ts', 'bin/release_ts.c')
212rtm.Program('measure_syscall', 'bin/null_call.c') 213rtm.Program('measure_syscall', 'bin/null_call.c')
213 214
diff --git a/bin/rtspin_edffm.c b/bin/rtspin_edffm.c
new file mode 100644
index 0000000..04dce0a
--- /dev/null
+++ b/bin/rtspin_edffm.c
@@ -0,0 +1,263 @@
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 fracden2 fracnum2 fracden2 cpu1 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 frac1[2], frac2[2];
145 int cpu1, cpu2;
146 double wcet_ms, period_ms;
147 int migrate = 0;
148 int cpu = 0;
149 int opt;
150 int wait = 0;
151 int test_loop = 0;
152 int skip_config = 0;
153 int verbose = 0;
154 double duration, start;
155 task_class_t class = RT_CLASS_HARD;
156
157 progname = argv[0];
158
159 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
160 switch (opt) {
161 case 'w':
162 wait = 1;
163 break;
164 case 'p':
165 cpu = atoi(optarg);
166 migrate = 1;
167 break;
168 case 'c':
169 class = str2class(optarg);
170 if (class == -1)
171 usage("Unknown task class.");
172 break;
173 case 'l':
174 test_loop = 1;
175 break;
176 case 'd':
177 /* manually configure delay per loop iteration
178 * unit: microseconds */
179 loop_length = atof(optarg) / 1000000;
180 skip_config = 1;
181 break;
182 case 'v':
183 verbose = 1;
184 break;
185 case ':':
186 usage("Argument missing.");
187 break;
188 case '?':
189 default:
190 usage("Bad argument.");
191 break;
192 }
193 }
194
195
196 if (!skip_config)
197 configure_loop();
198
199 if (test_loop) {
200 debug_delay_loop();
201 return 0;
202 }
203
204 if (argc - optind < 3)
205 usage("Arguments missing.");
206 wcet_ms = atof(argv[optind + 0]);
207 period_ms = atof(argv[optind + 1]);
208 duration = atof(argv[optind + 2]);
209 /* frac num, den = 0 means fixed task */
210 frac1[0] = atoi(argv[optind + 3]);
211 frac1[1] = atoi(argv[optind + 4]);
212 frac2[0] = atoi(argv[optind + 5]);
213 frac2[1] = atoi(argv[optind + 6]);
214 cpu1 = atoi(argv[optind + 7]);
215 cpu2 = atoi(argv[optind + 8]);
216 wcet = wcet_ms * __NS_PER_MS;
217 period = period_ms * __NS_PER_MS;
218 if (wcet <= 0)
219 usage("The worst-case execution time must be a "
220 "positive number.");
221 if (period <= 0)
222 usage("The period must be a positive number.");
223 if (wcet > period) {
224 usage("The worst-case execution time must not "
225 "exceed the period.");
226 }
227
228 if (migrate) {
229 ret = be_migrate_to(cpu);
230 if (ret < 0)
231 bail_out("could not migrate to target partition");
232 }
233
234 ret = sporadic_task_ns_edffm(wcet, period, 0, cpu,
235 frac1, frac2, cpu1, cpu2,
236 class, NO_ENFORCEMENT, migrate);
237
238 if (ret < 0)
239 bail_out("could not setup rt task params");
240
241 if (verbose)
242 show_loop_length();
243
244 init_litmus();
245
246 ret = task_mode(LITMUS_RT_TASK);
247 if (ret != 0)
248 bail_out("could not become RT task");
249
250 if (wait) {
251 ret = wait_for_ts_release();
252 if (ret != 0)
253 bail_out("wait_for_ts_release()");
254 }
255
256 start = wctime();
257
258 while (start + duration > wctime()) {
259 job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
260 }
261
262 return 0;
263}
diff --git a/include/litmus.h b/include/litmus.h
index b798c92..e27b10d 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -40,6 +40,11 @@ int sporadic_task_ns(
40 int cpu, task_class_t cls, 40 int cpu, task_class_t cls,
41 budget_policy_t budget_policy, int set_cpu_set); 41 budget_policy_t budget_policy, int set_cpu_set);
42 42
43int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu,
44 lt_t *frac1, lt_t *frac2, int cpu1, int cpu2,
45 task_class_t cls, budget_policy_t budget_policy,
46 int set_cpu_set);
47
43/* budget enforcement off by default in these macros */ 48/* budget enforcement off by default in these macros */
44#define sporadic_global(e, p) \ 49#define sporadic_global(e, p) \
45 sporadic_task(e, p, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 0) 50 sporadic_task(e, p, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 0)
diff --git a/src/litmus.c b/src/litmus.c
index f71f337..d253368 100644
--- a/src/litmus.c
+++ b/src/litmus.c
@@ -10,14 +10,14 @@
10#include "litmus.h" 10#include "litmus.h"
11#include "internal.h" 11#include "internal.h"
12 12
13void show_rt_param(struct rt_task* tp) 13void show_rt_param(struct rt_task* tp)
14{ 14{
15 printf("rt params:\n\t" 15 printf("rt params:\n\t"
16 "exec_cost:\t%llu\n\tperiod:\t\t%llu\n\tcpu:\t%d\n", 16 "exec_cost:\t%llu\n\tperiod:\t\t%llu\n\tcpu:\t%d\n",
17 tp->exec_cost, tp->period, tp->cpu); 17 tp->exec_cost, tp->period, tp->cpu);
18} 18}
19 19
20task_class_t str2class(const char* str) 20task_class_t str2class(const char* str)
21{ 21{
22 if (!strcmp(str, "hrt")) 22 if (!strcmp(str, "hrt"))
23 return RT_CLASS_HARD; 23 return RT_CLASS_HARD;
@@ -62,7 +62,39 @@ int sporadic_task_ns(lt_t e, lt_t p, lt_t phase,
62 param.phase = phase; 62 param.phase = phase;
63 param.budget_policy = budget_policy; 63 param.budget_policy = budget_policy;
64 64
65 if (set_cpu_set) { 65 if (set_cpu_set) {
66 ret = be_migrate_to(cpu);
67 check("migrate to cpu");
68 }
69 return set_rt_task_param(gettid(), &param);
70}
71
72int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu,
73 lt_t *frac1, lt_t *frac2, int cpu1, int cpu2,
74 task_class_t cls, budget_policy_t budget_policy,
75 int set_cpu_set)
76{
77 struct rt_task param;
78 int ret;
79 param.exec_cost = e;
80 param.period = p;
81 param.cpu = cpu;
82 /* check on denominators */
83 if (frac1[1] != 0 && frac2[1] != 0) {
84 /* edf-fm migrat task */
85 param.nr_cpus = 1;
86 param.cpus[0] = cpu1;
87 param.cpus[1] = cpu2;
88 param.fraction[0][0] = frac1[0];
89 param.fraction[1][0] = frac1[1];
90 param.fraction[0][1] = frac2[0];
91 param.fraction[1][1] = frac2[1];
92 }
93 param.cls = cls;
94 param.phase = phase;
95 param.budget_policy = budget_policy;
96
97 if (set_cpu_set) {
66 ret = be_migrate_to(cpu); 98 ret = be_migrate_to(cpu);
67 check("migrate to cpu"); 99 check("migrate to cpu");
68 } 100 }