aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/rt_launch.c172
-rw-r--r--include/internal.h5
-rw-r--r--include/litmus.h29
-rw-r--r--src/task.c58
4 files changed, 112 insertions, 152 deletions
diff --git a/bin/rt_launch.c b/bin/rt_launch.c
index 5e29893..c468b68 100644
--- a/bin/rt_launch.c
+++ b/bin/rt_launch.c
@@ -8,64 +8,63 @@
8#include "litmus.h" 8#include "litmus.h"
9#include "common.h" 9#include "common.h"
10 10
11typedef struct { 11const char *usage_msg =
12 int wait; 12 "Usage: rt_launch OPTIONS wcet period program [arg1 arg2 ...]\n"
13 char * exec_path; 13 " -w wait for synchronous release\n"
14 char ** argv; 14 " -v verbose (prints PID)\n"
15} startup_info_t; 15 " -p CPU physical partition or cluster to assign to\n"
16 16 " -r VCPU virtual CPU to attach to (irrelevant to most plugins)\n"
17 17 " -d DEADLINE relative deadline, implicit by default (in ms)\n"
18int launch(void *task_info_p) { 18 " -o OFFSET offset (also known as phase), zero by default (in ms)\n"
19 startup_info_t *info = (startup_info_t*) task_info_p; 19 " -q PRIORITY priority to use (ignored by EDF plugins, highest=1, lowest=511)\n"
20 int ret; 20 " -c be|srt|hrt task class (best-effort, soft real-time, hard real-time)\n"
21 if (info->wait) { 21 " -e turn off budget enforcement (DANGEROUS: can result in lockup)\n"
22 ret = wait_for_ts_release(); 22 " wcet, period reservation parameters (in ms)\n"
23 if (ret != 0) 23 " program path to the binary to be launched\n"
24 perror("wait_for_ts_release()"); 24 "\n";
25 }
26 ret = execvp(info->exec_path, info->argv);
27 perror("execv failed");
28 return ret;
29}
30 25
31void usage(char *error) { 26void usage(char *error) {
32 fprintf(stderr, "%s\nUsage: rt_launch [-w][-v][-p partition/cluster [-z cluster size]][-q prio][-c hrt | srt | be] wcet period program [arg1 arg2 ...]\n" 27 fprintf(stderr, "%s\n%s", error, usage_msg);
33 "\t-w\tSynchronous release\n"
34 "\t-v\tVerbose\n"
35 "\t-p\tpartition or cluster\n"
36 "\t-z\tsize of cluster (default = 1 for partitioned)\n"
37 "\t-c\tClass\n"
38 "\twcet, period in ms\n"
39 "\tprogram to be launched\n",
40 error);
41 exit(1); 28 exit(1);
42} 29}
43 30
31#define OPTSTR "wp:q:c:er:b:o:d:vh"
44 32
45#define OPTSTR "p:c:vwq:" 33int main(int argc, char** argv)
46
47int main(int argc, char** argv)
48{ 34{
49 int ret; 35 int ret, opt;
50 lt_t wcet; 36 lt_t wcet;
51 lt_t period; 37 lt_t period;
52 int migrate = 0; 38 lt_t offset;
53 int cluster = 0; 39 lt_t deadline;
54 int opt; 40 double wcet_ms, period_ms, offset_ms, deadline_ms;
55 int verbose = 0; 41 unsigned int priority;
56 int wait = 0; 42 int migrate;
57 startup_info_t info; 43 int cluster;
58 task_class_t class = RT_CLASS_HARD; 44 int reservation;
59 unsigned int priority = LITMUS_LOWEST_PRIORITY; 45 int wait;
46 int want_enforcement;
47 int verbose;
48 task_class_t class;
49 struct rt_task param;
50
51 /* Reasonable defaults */
52 verbose = 0;
53 offset_ms = 0;
54 deadline_ms = 0;
55 priority = LITMUS_LOWEST_PRIORITY;
56 want_enforcement = 1; /* safety: default to enforcement */
57 wait = 0; /* don't wait for task system release */
58 class = RT_CLASS_SOFT; /* ignored by most plugins */
59 migrate = 0; /* assume global unless -p is specified */
60 cluster = -1; /* where to migrate to, invalid by default */
61 reservation = -1; /* set if task should attach to virtual CPU */
60 62
61 while ((opt = getopt(argc, argv, OPTSTR)) != -1) { 63 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
62 switch (opt) { 64 switch (opt) {
63 case 'w': 65 case 'w':
64 wait = 1; 66 wait = 1;
65 break; 67 break;
66 case 'v':
67 verbose = 1;
68 break;
69 case 'p': 68 case 'p':
70 cluster = atoi(optarg); 69 cluster = atoi(optarg);
71 migrate = 1; 70 migrate = 1;
@@ -80,7 +79,28 @@ int main(int argc, char** argv)
80 if (class == -1) 79 if (class == -1)
81 usage("Unknown task class."); 80 usage("Unknown task class.");
82 break; 81 break;
83 82 case 'e':
83 want_enforcement = 0;
84 break;
85 case 'r':
86 reservation = atoi(optarg);
87 break;
88 case 'o':
89 offset_ms = atof(optarg);
90 break;
91 case 'd':
92 deadline_ms = atof(optarg);
93 if (!deadline_ms || deadline_ms < 0) {
94 usage("The relative deadline must be a positive"
95 " number.");
96 }
97 break;
98 case 'v':
99 verbose = 1;
100 break;
101 case 'h':
102 usage("");
103 break;
84 case ':': 104 case ':':
85 usage("Argument missing."); 105 usage("Argument missing.");
86 break; 106 break;
@@ -95,33 +115,65 @@ int main(int argc, char** argv)
95 115
96 if (argc - optind < 3) 116 if (argc - optind < 3)
97 usage("Arguments missing."); 117 usage("Arguments missing.");
98 wcet = ms2ns(atoi(argv[optind + 0])); 118
99 period = ms2ns(atoi(argv[optind + 1])); 119 wcet_ms = atof(argv[optind + 0]);
120 period_ms = atof(argv[optind + 1]);
121
122 wcet = ms2ns(wcet_ms);
123 period = ms2ns(period_ms);
124 offset = ms2ns(offset_ms);
125 deadline = ms2ns(deadline_ms);
100 if (wcet <= 0) 126 if (wcet <= 0)
101 usage("The worst-case execution time must be a " 127 usage("The worst-case execution time must be a "
102 "positive number."); 128 "positive number.");
103 if (period <= 0) 129 if (period <= 0)
104 usage("The period must be a positive number."); 130 usage("The period must be a positive number.");
105 if (wcet > period) { 131 if (wcet > period) {
106 usage("The worst-case execution time must not " 132 usage("The worst-case execution time must not "
107 "exceed the period."); 133 "exceed the period.");
108 } 134 }
109 info.exec_path = argv[optind + 2]; 135
110 info.argv = argv + optind + 2;
111 info.wait = wait;
112 if (migrate) { 136 if (migrate) {
113 ret = be_migrate_to_domain(cluster); 137 ret = be_migrate_to_domain(cluster);
114 if (ret < 0) 138 if (ret < 0)
115 bail_out("could not migrate to target partition or cluster"); 139 bail_out("could not migrate to target partition or cluster.");
116 } 140 }
117 ret = __create_rt_task(launch, &info, cluster, wcet, period,
118 priority, class);
119
120 141
142 init_rt_task_param(&param);
143 param.exec_cost = wcet;
144 param.period = period;
145 param.phase = offset;
146 param.relative_deadline = deadline;
147 param.priority = priority;
148 param.cls = class;
149 param.budget_policy = (want_enforcement) ?
150 PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
151 if (migrate) {
152 if (reservation >= 0)
153 param.cpu = reservation;
154 else
155 param.cpu = domain_to_first_cpu(cluster);
156 }
157 ret = set_rt_task_param(gettid(), &param);
121 if (ret < 0) 158 if (ret < 0)
122 bail_out("could not create rt child process"); 159 bail_out("could not setup rt task params");
123 else if (verbose)
124 printf("%d\n", ret);
125 160
126 return 0; 161 init_litmus();
162
163 ret = task_mode(LITMUS_RT_TASK);
164 if (ret != 0)
165 bail_out("could not become RT task");
166
167 if (verbose)
168 printf("%d\n", gettid());
169
170 if (wait) {
171 ret = wait_for_ts_release();
172 if (ret != 0)
173 bail_out("wait_for_ts_release()");
174 }
175
176 execvp(argv[optind + 2], argv + optind + 2);
177 perror("execv failed");
178 return 1;
127} 179}
diff --git a/include/internal.h b/include/internal.h
index 035440b..354f7dc 100644
--- a/include/internal.h
+++ b/include/internal.h
@@ -3,11 +3,6 @@
3 3
4/* low level operations, not intended for API use */ 4/* low level operations, not intended for API use */
5 5
6/* prepare a real-time task */
7typedef int (*rt_setup_fn_t)(int pid, void* arg);
8int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg,
9 rt_setup_fn_t setup, void* setup_arg);
10
11#define check(str) \ 6#define check(str) \
12 if (ret == -1) { \ 7 if (ret == -1) { \
13 perror(str); \ 8 perror(str); \
diff --git a/include/litmus.h b/include/litmus.h
index 8c54fdc..f99ccec 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -251,35 +251,6 @@ int init_rt_thread(void);
251 */ 251 */
252void exit_litmus(void); 252void exit_litmus(void);
253 253
254/* A real-time program. */
255typedef int (*rt_fn_t)(void*);
256
257/**
258 * Create a real-time task that enforces exectution budgets
259 * @param rt_prog Function pointer to real-time task body
260 * @param arg Pointer to arguments to pass to the pointer in rt_prog
261 * @param cluster Cluster to schedule this task on. For partitioned scheduling,
262 * set to the desired partition. For global scheduling, set to 0
263 * @param wcet Worst-Case execution time for this task
264 * @param period Period at which this task should be launched
265 * @param prio Priority for this task
266 */
267int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster,
268 lt_t wcet, lt_t period, unsigned int prio);
269/**
270 * Create a real-time task
271 * @param rt_prog Function pointer to real-time task body
272 * @param arg Pointer to arguments to pass to the pointer in rt_prog
273 * @param cluster Cluster to schedule this task on. For partitioned scheduling,
274 * set to the desired partition. For global scheduling, set to 0
275 * @param wcet Worst-Case execution time for this task
276 * @param period Period at which this task should be launched
277 * @param prio Priority for this task
278 * @param cls Task class (unused)
279 */
280int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster,
281 lt_t wcet, lt_t period, unsigned int prio, task_class_t cls);
282
283/* per-task modes */ 254/* per-task modes */
284enum rt_task_mode_t { 255enum rt_task_mode_t {
285 BACKGROUND_TASK = 0, 256 BACKGROUND_TASK = 0,
diff --git a/src/task.c b/src/task.c
index cd78aa9..3e3950c 100644
--- a/src/task.c
+++ b/src/task.c
@@ -8,64 +8,6 @@
8#include "litmus.h" 8#include "litmus.h"
9#include "internal.h" 9#include "internal.h"
10 10
11static void tperrorx(char* msg)
12{
13 fprintf(stderr,
14 "Task %d: %s: %m",
15 gettid(), msg);
16 exit(-1);
17}
18
19/* common launch routine */
20int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup,
21 void* setup_arg)
22{
23 int ret;
24 int rt_task = fork();
25
26 if (rt_task == 0) {
27 /* we are the real-time task
28 * launch task and die when it is done
29 */
30 rt_task = gettid();
31 ret = setup(rt_task, setup_arg);
32 if (ret < 0)
33 tperrorx("could not setup task parameters");
34 ret = task_mode(LITMUS_RT_TASK);
35 if (ret < 0)
36 tperrorx("could not become real-time task");
37 exit(rt_prog(rt_arg));
38 }
39
40 return rt_task;
41}
42
43int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster,
44 lt_t wcet, lt_t period, unsigned int priority, task_class_t class)
45{
46 struct rt_task params;
47 init_rt_task_param(&params);
48 params.cpu = domain_to_first_cpu(cluster);
49 params.period = period;
50 params.exec_cost = wcet;
51 params.cls = class;
52 params.phase = 0;
53 params.priority = priority;
54 /* enforce budget for tasks that might not use sleep_next_period() */
55 params.budget_policy = QUANTUM_ENFORCEMENT;
56
57 return __launch_rt_task(rt_prog, arg,
58 (rt_setup_fn_t) set_rt_task_param, &params);
59}
60
61int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster,
62 lt_t wcet, lt_t period, unsigned int prio)
63{
64 return __create_rt_task(rt_prog, arg, cluster, wcet, period,
65 prio, RT_CLASS_HARD);
66}
67
68
69#define SCHED_NORMAL 0 11#define SCHED_NORMAL 0
70 12
71int task_mode(int mode) 13int task_mode(int mode)