aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-09-22 17:15:33 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-09-22 17:15:33 -0400
commit2a98375fc5483a4ab7690464e3a1f961bde0126a (patch)
tree095e3f9a4043a1685e6c2f057d525d15439de7a7
parent74f2569ef754b076e26c7d1eed572715daaf8dfc (diff)
parent626f116df35e97e523aca3b2304b91770883826c (diff)
Merge branch 'wip-edf-wm' into wip-semi-part
Merging library branches for EDF-fm, EDF-WM, and NPS-F scheduling algorithms. This version of the library will compile against litmus2010 with all plugins merged (wip-semi-part). Conflicts: SConstruct include/litmus.h src/litmus.c
-rw-r--r--SConstruct8
-rw-r--r--bin/common.c119
-rw-r--r--bin/rt_launch_edfwm.c98
-rw-r--r--bin/rtspin_edfwm.c233
-rw-r--r--include/common.h4
-rw-r--r--include/litmus.h7
-rw-r--r--src/litmus.c15
-rw-r--r--src/task.c5
8 files changed, 484 insertions, 5 deletions
diff --git a/SConstruct b/SConstruct
index 657a92f..4e6b4c6 100644
--- a/SConstruct
+++ b/SConstruct
@@ -208,14 +208,18 @@ 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('release_ts', 'bin/release_ts.c')
212rtm.Program('measure_syscall', 'bin/null_call.c')
213
211rt.Program('rtspin_edffm', ['bin/rtspin_edffm.c', 'bin/common.c']) 214rt.Program('rtspin_edffm', ['bin/rtspin_edffm.c', 'bin/common.c'])
212rt.Program('rt_launch_edffm', ['bin/rt_launch_edffm.c', 'bin/common.c']) 215rt.Program('rt_launch_edffm', ['bin/rt_launch_edffm.c', 'bin/common.c'])
216
213rt.Program('rtspin_npsf', ['bin/rtspin_npsf.c', 'bin/common.c']) 217rt.Program('rtspin_npsf', ['bin/rtspin_npsf.c', 'bin/common.c'])
214rt.Program('npsf_add_server', ['bin/npsf_add_server.c', 'bin/common.c']) 218rt.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']) 219rt.Program('rt_launch_npsf', ['bin/rt_launch_npsf.c', 'bin/common.c'])
216rt.Program('release_ts', 'bin/release_ts.c')
217rtm.Program('measure_syscall', 'bin/null_call.c')
218 220
221rt.Program('rtspin_edfwm', ['bin/rtspin_edfwm.c', 'bin/common.c'])
222rt.Program('rt_launch_edfwm', ['bin/rt_launch_edfwm.c', 'bin/common.c'])
219 223
220# ##################################################################### 224# #####################################################################
221# Test suite. 225# Test suite.
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}
diff --git a/include/common.h b/include/common.h
index d1234ba..dbcfd34 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1,7 +1,11 @@
1#ifndef COMMON_H 1#ifndef COMMON_H
2#define COMMON_H 2#define COMMON_H
3 3
4#include "litmus.h"
4 5
5void bail_out(const char* msg); 6void bail_out(const char* msg);
6 7
8/* EDF-WM helper functions to parse task parameters from file */
9int parse_edfwm_ts_file(FILE *ts, struct rt_task *rt);
10
7#endif 11#endif
diff --git a/include/litmus.h b/include/litmus.h
index 7382936..6c3483c 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -9,6 +9,7 @@ extern "C" {
9 * This is required for the rt_param 9 * This is required for the rt_param
10 * and control_page structures. 10 * and control_page structures.
11 */ 11 */
12#include <linux/threads.h>
12#include <litmus/rt_param.h> 13#include <litmus/rt_param.h>
13 14
14#include <sys/types.h> 15#include <sys/types.h>
@@ -40,6 +41,7 @@ int sporadic_task_ns(
40 int cpu, task_class_t cls, 41 int cpu, task_class_t cls,
41 budget_policy_t budget_policy, int set_cpu_set); 42 budget_policy_t budget_policy, int set_cpu_set);
42 43
44/* Semi-partitioned schedulers --- sporadic task helpers (ns) */
43int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu, 45int 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, 46 lt_t *frac1, lt_t *frac2, int cpu1, int cpu2,
45 task_class_t cls, budget_policy_t budget_policy, 47 task_class_t cls, budget_policy_t budget_policy,
@@ -50,6 +52,8 @@ int sporadic_task_ns_npsf(
50 int cpu, task_class_t cls, int npsf_id, 52 int cpu, task_class_t cls, int npsf_id,
51 budget_policy_t budget_policy, int set_cpu_set); 53 budget_policy_t budget_policy, int set_cpu_set);
52 54
55int sporadic_task_ns_semi(struct rt_task *rt);
56
53/* budget enforcement off by default in these macros */ 57/* budget enforcement off by default in these macros */
54#define sporadic_global(e, p) \ 58#define sporadic_global(e, p) \
55 sporadic_task(e, p, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 0) 59 sporadic_task(e, p, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 0)
@@ -95,11 +99,14 @@ typedef int (*rt_fn_t)(void*);
95int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period); 99int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period);
96int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, 100int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
97 int period, task_class_t cls); 101 int period, task_class_t cls);
102
103/* Semi-partitioned schedulers helper to wrap __launch_rt_task() */
98int __create_rt_task_edffm(rt_fn_t rt_prog, void *arg, int cpu, int wcet, 104int __create_rt_task_edffm(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
99 int period, lt_t *frac1, lt_t *frac2, 105 int period, lt_t *frac1, lt_t *frac2,
100 int cpu1, int cpu2, task_class_t class); 106 int cpu1, int cpu2, task_class_t class);
101int __create_rt_task_npsf(rt_fn_t rt_prog, void *arg, int cpu, int wcet, 107int __create_rt_task_npsf(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
102 int period, int npsf_id, task_class_t class); 108 int period, int npsf_id, task_class_t class);
109int create_rt_task_semi(rt_fn_t rt_prog, void *arg, struct rt_task *params);
103 110
104/* per-task modes */ 111/* per-task modes */
105enum rt_task_mode_t { 112enum rt_task_mode_t {
diff --git a/src/litmus.c b/src/litmus.c
index b339e62..33e1a6d 100644
--- a/src/litmus.c
+++ b/src/litmus.c
@@ -29,8 +29,6 @@ task_class_t str2class(const char* str)
29 return -1; 29 return -1;
30} 30}
31 31
32#define NS_PER_MS 1000000
33
34/* only for best-effort execution: migrate to target_cpu */ 32/* only for best-effort execution: migrate to target_cpu */
35int be_migrate_to(int target_cpu) 33int be_migrate_to(int target_cpu)
36{ 34{
@@ -45,7 +43,7 @@ int sporadic_task(lt_t e, lt_t p, lt_t phase,
45 int cpu, task_class_t cls, 43 int cpu, task_class_t cls,
46 budget_policy_t budget_policy, int set_cpu_set) 44 budget_policy_t budget_policy, int set_cpu_set)
47{ 45{
48 return sporadic_task_ns(e * NS_PER_MS, p * NS_PER_MS, phase * NS_PER_MS, 46 return sporadic_task_ns(e * __NS_PER_MS, p * __NS_PER_MS, phase * __NS_PER_MS,
49 cpu, cls, budget_policy, set_cpu_set); 47 cpu, cls, budget_policy, set_cpu_set);
50} 48}
51 49
@@ -69,6 +67,7 @@ int sporadic_task_ns(lt_t e, lt_t p, lt_t phase,
69 return set_rt_task_param(gettid(), &param); 67 return set_rt_task_param(gettid(), &param);
70} 68}
71 69
70/* Sporadic task helper function for Semi-Partitioned algorithms. */
72int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu, 71int 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, 72 lt_t *frac1, lt_t *frac2, int cpu1, int cpu2,
74 task_class_t cls, budget_policy_t budget_policy, 73 task_class_t cls, budget_policy_t budget_policy,
@@ -124,6 +123,16 @@ int sporadic_task_ns_npsf(lt_t e, lt_t p, lt_t phase,
124 return set_rt_task_param(gettid(), &param); 123 return set_rt_task_param(gettid(), &param);
125} 124}
126 125
126int sporadic_task_ns_semi(struct rt_task *param)
127{
128 int ret;
129
130 ret = be_migrate_to(param->cpu);
131 check("migrate to cpu");
132
133 return set_rt_task_param(gettid(), param);
134}
135
127int init_kernel_iface(void); 136int init_kernel_iface(void);
128 137
129int init_litmus(void) 138int init_litmus(void)
diff --git a/src/task.c b/src/task.c
index 2db9c98..daf95ca 100644
--- a/src/task.c
+++ b/src/task.c
@@ -108,6 +108,11 @@ int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) {
108 return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD); 108 return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD);
109} 109}
110 110
111int create_rt_task_semi(rt_fn_t rt_prog, void *arg, struct rt_task *params)
112{
113 return __launch_rt_task(rt_prog, arg,
114 (rt_setup_fn_t) set_rt_task_param, params);
115}
111 116
112#define SCHED_NORMAL 0 117#define SCHED_NORMAL 0
113#define SCHED_LITMUS 6 118#define SCHED_LITMUS 6