aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--SConstruct11
-rw-r--r--bin/npsf_add_server.c108
-rw-r--r--bin/rt_launch_edffm.c133
-rw-r--r--bin/rt_launch_npsf.c110
-rw-r--r--bin/rtspin_edffm.c263
-rw-r--r--bin/rtspin_npsf.c252
-rw-r--r--include/litmus.h38
-rw-r--r--src/litmus.c59
-rw-r--r--src/syscalls.c5
-rw-r--r--src/task.c48
10 files changed, 1018 insertions, 9 deletions
diff --git a/SConstruct b/SConstruct
index 6a726c2..4e6b4c6 100644
--- a/SConstruct
+++ b/SConstruct
@@ -208,11 +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('rtspin_edfwm', ['bin/rtspin_edfwm.c', 'bin/common.c'])
212rt.Program('rt_launch_edfwm', ['bin/rt_launch_edfwm.c', 'bin/common.c'])
213rt.Program('release_ts', 'bin/release_ts.c') 211rt.Program('release_ts', 'bin/release_ts.c')
214rtm.Program('measure_syscall', 'bin/null_call.c') 212rtm.Program('measure_syscall', 'bin/null_call.c')
215 213
214rt.Program('rtspin_edffm', ['bin/rtspin_edffm.c', 'bin/common.c'])
215rt.Program('rt_launch_edffm', ['bin/rt_launch_edffm.c', 'bin/common.c'])
216
217rt.Program('rtspin_npsf', ['bin/rtspin_npsf.c', 'bin/common.c'])
218rt.Program('npsf_add_server', ['bin/npsf_add_server.c', 'bin/common.c'])
219rt.Program('rt_launch_npsf', ['bin/rt_launch_npsf.c', 'bin/common.c'])
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'])
216 223
217# ##################################################################### 224# #####################################################################
218# Test suite. 225# Test suite.
diff --git a/bin/npsf_add_server.c b/bin/npsf_add_server.c
new file mode 100644
index 0000000..9f3f92c
--- /dev/null
+++ b/bin/npsf_add_server.c
@@ -0,0 +1,108 @@
1/* wrapper for sys_add_server
2 *
3 * Input: a file with on each line:
4 * npsf_id cpu budget(us)
5 */
6#include <stdio.h>
7#include <stdlib.h>
8#include <unistd.h>
9
10#include "litmus.h"
11#include "common.h"
12
13void usage(char *error) {
14 fprintf(stderr, "Error: %s\n", error);
15 fprintf(stderr,
16 "Usage: npsf_add_server SERVERS-FILE MAX-SPLITS-PER-NPSFID\n");
17 exit(1);
18}
19
20int main(int argc, char** argv)
21{
22 int ret;
23 FILE *file;
24 int i,j;
25 int npsf_id, curr_id = -1;
26 int cpu, max_splits_server;
27 int budget_us;
28 struct npsf_budgets *budgets;
29
30 if (argc < 3)
31 usage("Arguments missing.");
32
33 max_splits_server = atoi(argv[2]);
34
35 if ((file = fopen(argv[1], "r")) == NULL) {
36 fprintf(stderr, "Cannot open %s\n", argv[1]);
37 return -1;
38 }
39
40 /* format: npsf_id cpu budget-us */
41 i = 0;
42 while (fscanf(file, "%d %d %d\n", &npsf_id, &cpu, &budget_us) != EOF) {
43
44 printf("Read: %d %d %d\n", npsf_id, cpu, budget_us);
45
46 if (curr_id == -1) {
47 curr_id = npsf_id;
48 budgets = malloc(max_splits_server *
49 sizeof(struct npsf_budgets));
50 for(j = 0; j < max_splits_server; j++) {
51 budgets[j].cpu = -1;
52 budgets[j].budget = 0;
53 }
54 }
55
56 if (npsf_id == curr_id) {
57 /* same notional processor, different cpu and budget */
58 budgets[i].cpu = cpu;
59 budgets[i].budget = (lt_t) (budget_us * 1000);
60 i++;
61 } else {
62 /* different notional processor */
63 /* add server */
64 printf("Adding npsf_id = %d\n", curr_id);
65 ret = add_server(&curr_id, budgets, 0);
66
67 if (ret < 0) {
68 fclose(file);
69 free(budgets);
70 printf("Cannot add Notional Processor %d\n",
71 curr_id);
72 return ret;
73 }
74
75 /* reinit new */
76 i = 0;
77 budgets = malloc(max_splits_server *
78 sizeof(struct npsf_budgets));
79 for(j = 0; j < max_splits_server; j++) {
80 budgets[j].cpu = -1;
81 budgets[j].budget = 0;
82 }
83 curr_id = npsf_id;
84 budgets[i].cpu = cpu;
85 budgets[i].budget = (lt_t) (budget_us * 1000);
86 i++;
87 }
88 }
89
90 if (ferror(file)) {
91 fprintf(stderr, "Error while reading\n");
92 fclose(file);
93 return -1;
94 }
95
96 /* save the last entry */
97 ret = add_server(&curr_id, budgets, 1);
98 printf("Adding npsf_id = %d\n", curr_id);
99 if (ret < 0) {
100 fclose(file);
101 free(budgets);
102 bail_out("Cannot add Notional Processor: ");
103 }
104
105 fclose(file);
106
107 return 0;
108}
diff --git a/bin/rt_launch_edffm.c b/bin/rt_launch_edffm.c
new file mode 100644
index 0000000..ddde7dd
--- /dev/null
+++ b/bin/rt_launch_edffm.c
@@ -0,0 +1,133 @@
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 frac1[2], frac2[2];
54 int cpu1, cpu2;
55 int migrate = 0;
56 int cpu = 0;
57 int opt;
58 int verbose = 0;
59 int wait = 0;
60 startup_info_t info;
61 task_class_t class = RT_CLASS_HARD;
62
63 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
64 switch (opt) {
65 case 'w':
66 wait = 1;
67 break;
68 case 'v':
69 verbose = 1;
70 break;
71 case 'p':
72 cpu = atoi(optarg);
73 migrate = 1;
74 break;
75 case 'c':
76 class = str2class(optarg);
77 if (class == -1)
78 usage("Unknown task class.");
79 break;
80
81 case ':':
82 usage("Argument missing.");
83 break;
84 case '?':
85 default:
86 usage("Bad argument.");
87 break;
88 }
89 }
90
91 signal(SIGUSR1, SIG_IGN);
92
93 if (argc - optind < 8)
94 usage("Arguments missing.");
95 wcet = ms2lt(atoi(argv[optind + 0]));
96 period = ms2lt(atoi(argv[optind + 1]));
97 /* frac num, den = 0 means fixed task */
98 frac1[0] = atoi(argv[optind + 2]);
99 frac1[1] = atoi(argv[optind + 3]);
100 cpu1 = atoi(argv[optind + 4]);
101 frac2[0] = atoi(argv[optind + 5]);
102 frac2[1] = atoi(argv[optind + 6]);
103 cpu2 = atoi(argv[optind + 7]);
104 if (wcet <= 0)
105 usage("The worst-case execution time must be a "
106 "positive number.");
107 if (period <= 0)
108 usage("The period must be a positive number.");
109 if (wcet > period) {
110 usage("The worst-case execution time must not "
111 "exceed the period.");
112 }
113 info.exec_path = argv[optind + 8];
114 info.argv = argv + optind + 8;
115 info.wait = wait;
116 if (migrate) {
117 ret = be_migrate_to(cpu);
118 if (ret < 0)
119 bail_out("could not migrate to target partition");
120 }
121 /* create in src/task.c a new wrapper for the __launch_rt_task
122 * which takes the fraction and the cpus */
123 ret = __create_rt_task_edffm(launch, &info, cpu, wcet, period, frac1,
124 frac2, cpu1, cpu2, class);
125
126
127 if (ret < 0)
128 bail_out("could not create rt child process");
129 else if (verbose)
130 printf("%d\n", ret);
131
132 return 0;
133}
diff --git a/bin/rt_launch_npsf.c b/bin/rt_launch_npsf.c
new file mode 100644
index 0000000..97ad361
--- /dev/null
+++ b/bin/rt_launch_npsf.c
@@ -0,0 +1,110 @@
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] wcet period cpu npsf-id program [arg1 arg2 ...]\n"
33 "\t-w\tSynchronous release\n"
34 "\t-v\tVerbose\n"
35 "\twcet, period in ms\n"
36 "\tprogram to be launched\n",
37 error);
38 exit(1);
39}
40
41
42#define OPTSTR "vw"
43
44int main(int argc, char** argv)
45{
46 int ret;
47 lt_t wcet;
48 lt_t period;
49 int migrate = 0;
50 int cpu = 0;
51 int npsf_id;
52 int opt;
53 int verbose = 0;
54 int wait = 0;
55 startup_info_t info;
56
57 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
58 switch (opt) {
59 case 'w':
60 wait = 1;
61 break;
62 case 'v':
63 verbose = 1;
64 break;
65 case ':':
66 usage("Argument missing.");
67 break;
68 case '?':
69 default:
70 usage("Bad argument.");
71 break;
72 }
73 }
74
75 signal(SIGUSR1, SIG_IGN);
76
77 if (argc - optind < 5)
78 usage("Arguments missing.");
79 wcet = ms2lt(atoi(argv[optind + 0]));
80 period = ms2lt(atoi(argv[optind + 1]));
81 cpu = atoi(argv[optind + 2]);
82 migrate = 1;
83 npsf_id = atoi(argv[optind + 3]);
84 if (wcet <= 0)
85 usage("The worst-case execution time must be a "
86 "positive number.");
87 if (period <= 0)
88 usage("The period must be a positive number.");
89 if (wcet > period) {
90 usage("The worst-case execution time must not "
91 "exceed the period.");
92 }
93 info.exec_path = argv[optind + 4];
94 info.argv = argv + optind + 4;
95 info.wait = wait;
96 if (migrate) {
97 ret = be_migrate_to(cpu);
98 if (ret < 0)
99 bail_out("could not migrate to target partition");
100 }
101 ret = __create_rt_task_npsf(launch, &info, cpu, wcet, period, npsf_id, RT_CLASS_HARD);
102
103
104 if (ret < 0)
105 bail_out("could not create rt child process");
106 else if (verbose)
107 printf("%d\n", ret);
108
109 return 0;
110}
diff --git a/bin/rtspin_edffm.c b/bin/rtspin_edffm.c
new file mode 100644
index 0000000..5271c10
--- /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 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 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 < 9)
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 cpu1 = atoi(argv[optind + 5]);
213 frac2[0] = atoi(argv[optind + 6]);
214 frac2[1] = 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/bin/rtspin_npsf.c b/bin/rtspin_npsf.c
new file mode 100644
index 0000000..d5dff3d
--- /dev/null
+++ b/bin/rtspin_npsf.c
@@ -0,0 +1,252 @@
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] WCET PERIOD DURATION CPU NPSF-ID\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 "c:wld:v"
137
138int main(int argc, char** argv)
139{
140 int ret;
141 lt_t wcet;
142 lt_t period;
143 double wcet_ms, period_ms;
144 int migrate = 0;
145 int cpu = 0;
146 int npsf_id = 0;
147 int opt;
148 int wait = 0;
149 int test_loop = 0;
150 int skip_config = 0;
151 int verbose = 0;
152 double duration, start;
153 task_class_t class = RT_CLASS_HARD;
154
155 progname = argv[0];
156
157 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
158 switch (opt) {
159 case 'w':
160 wait = 1;
161 break;
162 case 'c':
163 class = str2class(optarg);
164 if (class == -1)
165 usage("Unknown task class.");
166 break;
167 case 'l':
168 test_loop = 1;
169 break;
170 case 'd':
171 /* manually configure delay per loop iteration
172 * unit: microseconds */
173 loop_length = atof(optarg) / 1000000;
174 skip_config = 1;
175 break;
176 case 'v':
177 verbose = 1;
178 break;
179 case ':':
180 usage("Argument missing.");
181 break;
182 case '?':
183 default:
184 usage("Bad argument.");
185 break;
186 }
187 }
188
189
190 if (!skip_config)
191 configure_loop();
192
193 if (test_loop) {
194 debug_delay_loop();
195 return 0;
196 }
197
198 if (argc - optind < 5)
199 usage("Arguments missing.");
200 wcet_ms = atof(argv[optind + 0]);
201 period_ms = atof(argv[optind + 1]);
202 duration = atof(argv[optind + 2]);
203 cpu = atoi(argv[optind + 3]);
204 migrate = 1;
205 npsf_id = atoi(argv[optind + 4]);
206 wcet = wcet_ms * __NS_PER_MS;
207 period = period_ms * __NS_PER_MS;
208 if (wcet <= 0)
209 usage("The worst-case execution time must be a "
210 "positive number.");
211 if (period <= 0)
212 usage("The period must be a positive number.");
213 if (wcet > period) {
214 usage("The worst-case execution time must not "
215 "exceed the period.");
216 }
217
218 if (migrate) {
219 ret = be_migrate_to(cpu);
220 if (ret < 0)
221 bail_out("could not migrate to target partition");
222 }
223
224 ret = sporadic_task_ns_npsf(wcet, period, 0, cpu, class, npsf_id,
225 NO_ENFORCEMENT, migrate);
226
227 if (ret < 0)
228 bail_out("could not setup rt task params");
229
230 if (verbose)
231 show_loop_length();
232
233 init_litmus();
234
235 ret = task_mode(LITMUS_RT_TASK);
236 if (ret != 0)
237 bail_out("could not become RT task");
238
239 if (wait) {
240 ret = wait_for_ts_release();
241 if (ret != 0)
242 bail_out("wait_for_ts_release()");
243 }
244
245 start = wctime();
246
247 while (start + duration > wctime()) {
248 job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
249 }
250
251 return 0;
252}
diff --git a/include/litmus.h b/include/litmus.h
index 2b499da..6c3483c 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -41,7 +41,17 @@ int sporadic_task_ns(
41 int cpu, task_class_t cls, 41 int cpu, task_class_t cls,
42 budget_policy_t budget_policy, int set_cpu_set); 42 budget_policy_t budget_policy, int set_cpu_set);
43 43
44/* times are in ns, specific helper for semi-partitioned algos */ 44/* Semi-partitioned schedulers --- sporadic task helpers (ns) */
45int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu,
46 lt_t *frac1, lt_t *frac2, int cpu1, int cpu2,
47 task_class_t cls, budget_policy_t budget_policy,
48 int set_cpu_set);
49
50int sporadic_task_ns_npsf(
51 lt_t e, lt_t p, lt_t phase,
52 int cpu, task_class_t cls, int npsf_id,
53 budget_policy_t budget_policy, int set_cpu_set);
54
45int sporadic_task_ns_semi(struct rt_task *rt); 55int sporadic_task_ns_semi(struct rt_task *rt);
46 56
47/* budget enforcement off by default in these macros */ 57/* budget enforcement off by default in these macros */
@@ -89,10 +99,13 @@ typedef int (*rt_fn_t)(void*);
89int 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);
90int __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,
91 int period, task_class_t cls); 101 int period, task_class_t cls);
92/* wrapper to mask __launch_rt_task() for semi-partitioned algorithms 102
93 * (it can be extended to cover all algorithms that directly submit 103/* Semi-partitioned schedulers helper to wrap __launch_rt_task() */
94 * an rt_task structure instead of a set of values). 104int __create_rt_task_edffm(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
95 */ 105 int period, lt_t *frac1, lt_t *frac2,
106 int cpu1, int cpu2, task_class_t class);
107int __create_rt_task_npsf(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
108 int period, int npsf_id, task_class_t class);
96int create_rt_task_semi(rt_fn_t rt_prog, void *arg, struct rt_task *params); 109int create_rt_task_semi(rt_fn_t rt_prog, void *arg, struct rt_task *params);
97 110
98/* per-task modes */ 111/* per-task modes */
@@ -143,6 +156,21 @@ int null_call(cycles_t *timestamp);
143 */ 156 */
144struct control_page* get_ctrl_page(void); 157struct control_page* get_ctrl_page(void);
145 158
159/* NPS-F syscall to add a notional processor (a server) to a cpu.
160 * A notional processor may span across multiple cpu.
161 *
162 * @npsf_id: a "unique" identifier for the notional processor.
163 * @budgets: array of (cpu, budget-ns) that describes this np.
164 * on possibly more than one cpu.
165 * @last: marks the end of servers initialization and trigger
166 * the switching of servers in the plugin.
167 * Should be set to 1 only once at the end of the sequence
168 * of add_server() calls
169 *
170 * Currently implemented on x86_64 only.
171 */
172int add_server(int *npsf_id, struct npsf_budgets *budgets, int last);
173
146#ifdef __cplusplus 174#ifdef __cplusplus
147} 175}
148#endif 176#endif
diff --git a/src/litmus.c b/src/litmus.c
index 6a7e6e9..33e1a6d 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;
@@ -68,6 +68,61 @@ int sporadic_task_ns(lt_t e, lt_t p, lt_t phase,
68} 68}
69 69
70/* Sporadic task helper function for Semi-Partitioned algorithms. */ 70/* Sporadic task helper function for Semi-Partitioned algorithms. */
71int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu,
72 lt_t *frac1, lt_t *frac2, int cpu1, int cpu2,
73 task_class_t cls, budget_policy_t budget_policy,
74 int set_cpu_set)
75{
76 struct rt_task param;
77 struct edffm_params fm;
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 fm.nr_cpus = 1;
86 fm.cpus[0] = cpu1;
87 fm.cpus[1] = cpu2;
88 fm.fraction[0][0] = frac1[0];
89 fm.fraction[1][0] = frac1[1];
90 fm.fraction[0][1] = frac2[0];
91 fm.fraction[1][1] = frac2[1];
92 }
93 param.semi_part.fm = fm;
94 param.cls = cls;
95 param.phase = phase;
96 param.budget_policy = budget_policy;
97
98 if (set_cpu_set) {
99 ret = be_migrate_to(cpu);
100 check("migrate to cpu");
101 }
102 return set_rt_task_param(gettid(), &param);
103}
104
105int sporadic_task_ns_npsf(lt_t e, lt_t p, lt_t phase,
106 int cpu, task_class_t cls, int npsf_id,
107 budget_policy_t budget_policy, int set_cpu_set)
108{
109 struct rt_task param;
110 int ret;
111 param.exec_cost = e;
112 param.period = p;
113 param.cpu = cpu;
114 param.cls = cls;
115 param.phase = phase;
116 param.budget_policy = budget_policy;
117 param.semi_part.npsf_id = (int) npsf_id;
118
119 if (set_cpu_set) {
120 ret = be_migrate_to(cpu);
121 check("migrate to cpu");
122 }
123 return set_rt_task_param(gettid(), &param);
124}
125
71int sporadic_task_ns_semi(struct rt_task *param) 126int sporadic_task_ns_semi(struct rt_task *param)
72{ 127{
73 int ret; 128 int ret;
diff --git a/src/syscalls.c b/src/syscalls.c
index 77a6277..7ac488a 100644
--- a/src/syscalls.c
+++ b/src/syscalls.c
@@ -95,3 +95,8 @@ int null_call(cycles_t *timestamp)
95{ 95{
96 return syscall(__NR_null_call, timestamp); 96 return syscall(__NR_null_call, timestamp);
97} 97}
98
99int add_server(int *npsf_id, struct npsf_budgets *budgets, int last)
100{
101 return syscall(__NR_add_server, npsf_id, budgets, last);
102}
diff --git a/src/task.c b/src/task.c
index 2f825ee..daf95ca 100644
--- a/src/task.c
+++ b/src/task.c
@@ -40,6 +40,54 @@ int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup,
40 return rt_task; 40 return rt_task;
41} 41}
42 42
43int __create_rt_task_edffm(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
44 int period, lt_t *frac1, lt_t *frac2,
45 int cpu1, int cpu2, task_class_t class)
46{
47 struct rt_task params;
48 struct edffm_params fm;
49 params.cpu = cpu;
50 params.period = period;
51 params.exec_cost = wcet;
52 params.cls = class;
53 params.phase = 0;
54 /* enforce budget for tasks that might not use sleep_next_period() */
55 params.budget_policy = QUANTUM_ENFORCEMENT;
56
57 /* edf-fm check on denominators for migratory tasks */
58 if (frac1[1] != 0 && frac2[1] != 0) {
59 /* edf-fm migrat task */
60 fm.nr_cpus = 1;
61 fm.cpus[0] = cpu1;
62 fm.cpus[1] = cpu2;
63 fm.fraction[0][0] = frac1[0];
64 fm.fraction[1][0] = frac1[1];
65 fm.fraction[0][1] = frac2[0];
66 fm.fraction[1][1] = frac2[1];
67 }
68 params.semi_part.fm = fm;
69
70 return __launch_rt_task(rt_prog, arg,
71 (rt_setup_fn_t) set_rt_task_param, &params);
72}
73
74int __create_rt_task_npsf(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
75 int period, int npsf_id, task_class_t class)
76{
77 struct rt_task params;
78 params.cpu = cpu;
79 params.period = period;
80 params.exec_cost = wcet;
81 params.cls = class;
82 params.phase = 0;
83 /* enforce budget for tasks that might not use sleep_next_period() */
84 params.budget_policy = QUANTUM_ENFORCEMENT;
85 params.semi_part.npsf_id = (int) npsf_id;
86
87 return __launch_rt_task(rt_prog, arg,
88 (rt_setup_fn_t) set_rt_task_param, &params);
89}
90
43int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period, 91int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
44 task_class_t class) 92 task_class_t class)
45{ 93{