aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2007-10-05 12:41:53 -0400
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2007-10-05 12:41:53 -0400
commit9de8f0850ce4b34a849384d119fc9e5a6f3f8d17 (patch)
tree236622c3b41231bb74507cd5e3b7f29d61170c43
parent7ddb0d79edf783b5cf45af8052195df198788b07 (diff)
Implement user space adaptive task launching interface.
-rw-r--r--Makefile4
-rw-r--r--include/adaptive.h23
-rw-r--r--include/litmus.h8
-rw-r--r--src/adaptive.c45
-rw-r--r--src/litmus.c60
-rw-r--r--src/rt_launch.c85
6 files changed, 191 insertions, 34 deletions
diff --git a/Makefile b/Makefile
index 10f57dd..24c7d2a 100644
--- a/Makefile
+++ b/Makefile
@@ -39,5 +39,5 @@ rt_launch: liblitmus.a litmus.h rt_launch.o
39edfhsb: liblitmus.a edf-hsb.o litmus.h edf-hsb.h hrt.o 39edfhsb: liblitmus.a edf-hsb.o litmus.h edf-hsb.h hrt.o
40 cc -o edfhsb hrt.o edf-hsb.o ${LIBS} 40 cc -o edfhsb hrt.o edf-hsb.o ${LIBS}
41 41
42liblitmus.a: litmus.o litmus.h edf-hsb.o edf-hsb.h 42liblitmus.a: litmus.o adaptive.o adaptive.h litmus.h edf-hsb.o edf-hsb.h
43 ${AR} rcs liblitmus.a litmus.o edf-hsb.o 43 ${AR} rcs liblitmus.a litmus.o adaptive.o edf-hsb.o
diff --git a/include/adaptive.h b/include/adaptive.h
new file mode 100644
index 0000000..a67c540
--- /dev/null
+++ b/include/adaptive.h
@@ -0,0 +1,23 @@
1#ifndef ADAPTIVE_H
2#define ADAPTIVE_H
3
4#define MAX_SERVICE_LEVELS 10
5
6typedef struct {
7 unsigned long exec_cost;
8 unsigned long period;
9 /* fixed point */
10 unsigned long utility;
11} service_level_t;
12
13int set_service_levels(pid_t pid,
14 unsigned int nr_levels,
15 service_level_t* levels);
16
17int get_cur_service_level(void);
18
19int create_adaptive_rt_task(rt_fn_t rt_prog, void *arg,
20 unsigned int no_levels, service_level_t* levels);
21
22
23#endif
diff --git a/include/litmus.h b/include/litmus.h
index 3595919..01503aa 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -8,6 +8,7 @@
8#define CLONE_REALTIME 0x10000000 8#define CLONE_REALTIME 0x10000000
9 9
10typedef int (*rt_fn_t)(void*); 10typedef int (*rt_fn_t)(void*);
11typedef int (*rt_setup_fn_t)(int pid, void* arg);
11 12
12/* Litmus scheduling policies */ 13/* Litmus scheduling policies */
13typedef enum { 14typedef enum {
@@ -99,6 +100,7 @@ void init_litmus(void);
99#define exit_litmus() {} 100#define exit_litmus() {}
100 101
101 102
103
102int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period); 104int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period);
103int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, 105int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
104 int period, task_class_t cls); 106 int period, task_class_t cls);
@@ -111,4 +113,10 @@ void exit_np(void);
111 113
112int litmus_task_active(); 114int litmus_task_active();
113 115
116
117/* low level operations, not intended for API use */
118int fork_rt(void);
119int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg,
120 rt_setup_fn_t setup, void* setup_arg);
121
114#endif 122#endif
diff --git a/src/adaptive.c b/src/adaptive.c
new file mode 100644
index 0000000..ebf662d
--- /dev/null
+++ b/src/adaptive.c
@@ -0,0 +1,45 @@
1#include <sys/types.h>
2#include <unistd.h>
3
4#include "litmus.h"
5#include "adaptive.h"
6
7#define __NR_set_service_levels 346
8#define __NR_get_cur_service_level 347
9
10
11
12int set_service_levels(pid_t pid,
13 unsigned int nr_levels,
14 service_level_t* levels)
15{
16 return syscall(__NR_set_service_levels, pid, nr_levels, levels);
17}
18
19
20int get_cur_service_level(void)
21{
22 return syscall(__NR_get_cur_service_level);
23}
24
25
26struct adaptive_param {
27 unsigned int no_levels;
28 service_level_t* levels;
29};
30
31int setup_adaptive(int pid, struct adaptive_param* arg)
32{
33 return set_service_levels(pid, arg->no_levels, arg->levels);
34}
35
36int create_adaptive_rt_task(rt_fn_t rt_prog, void *arg,
37 unsigned int no_levels, service_level_t* levels)
38{
39 struct adaptive_param p;
40 p.no_levels = no_levels;
41 p.levels = levels;
42 return __launch_rt_task(rt_prog, arg,
43 (rt_setup_fn_t) setup_adaptive, &p);
44}
45
diff --git a/src/litmus.c b/src/litmus.c
index 9a2ebea..b39da7f 100644
--- a/src/litmus.c
+++ b/src/litmus.c
@@ -63,6 +63,12 @@ type name(type1 arg1,type2 arg2) \
63 63
64_syscall2(int, raw_clone, unsigned long, flags, unsigned long, child_stack) 64_syscall2(int, raw_clone, unsigned long, flags, unsigned long, child_stack)
65 65
66int fork_rt(void)
67{
68 int rt_task = raw_clone(CLONE_LITMUS, 0);
69 return rt_task;
70}
71
66 72
67const char* get_scheduler_name(spolicy scheduler) 73const char* get_scheduler_name(spolicy scheduler)
68{ 74{
@@ -103,27 +109,20 @@ const char* get_scheduler_name(spolicy scheduler)
103 return name; 109 return name;
104} 110}
105 111
106int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) {
107 return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD);
108}
109 112
110int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period, 113/* common launch routine */
111 task_class_t class) 114int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup,
115 void* setup_arg)
112{ 116{
113 int ret; 117 int ret;
114 rt_param_t params; 118 int rt_task = fork_rt();
115 int rt_task = raw_clone(CLONE_LITMUS, 0);
116 119
117 if (rt_task < 0) 120 if (rt_task < 0)
118 return rt_task; 121 return rt_task;
119 122
120 if (rt_task > 0) { 123 if (rt_task > 0) {
121 /* we are the controller task */ 124 /* we are the controller task */
122 params.period = period; 125 ret = setup(rt_task, setup_arg);
123 params.exec_cost = wcet;
124 params.cpu = cpu;
125 params.cls = class;
126 ret = set_rt_task_param(rt_task, &params);
127 if (ret < 0) { 126 if (ret < 0) {
128 /* we have a problem: we created the task but 127 /* we have a problem: we created the task but
129 * for some stupid reason we cannot set the real-time 128 * for some stupid reason we cannot set the real-time
@@ -138,7 +137,7 @@ int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
138 ret = prepare_rt_task(rt_task); 137 ret = prepare_rt_task(rt_task);
139 if (ret < 0) { 138 if (ret < 0) {
140 /* same problem as above*/ 139 /* same problem as above*/
141 //kill(rt_task, SIGKILL); 140 kill(rt_task, SIGKILL);
142 rt_task = -1; 141 rt_task = -1;
143 } 142 }
144 return rt_task; 143 return rt_task;
@@ -148,10 +147,43 @@ int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
148 * launch task and die when it is done 147 * launch task and die when it is done
149 */ 148 */
150 149
151 exit(rt_prog(arg)); 150 exit(rt_prog(rt_arg));
152 } 151 }
153} 152}
154 153
154struct create_rt_param {
155 int cpu;
156 int wcet;
157 int period;
158 task_class_t class;
159};
160
161int setup_create_rt(int pid, struct create_rt_param* arg)
162{
163 rt_param_t params;
164 params.period = arg->period;
165 params.exec_cost = arg->wcet;
166 params.cpu = arg->cpu;
167 params.cls = arg->class;
168 return set_rt_task_param(pid, &params);
169}
170
171int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
172 task_class_t class)
173{
174 struct create_rt_param params;
175 params.cpu = cpu;
176 params.period = period;
177 params.wcet = wcet;
178 params.class = class;
179 return __launch_rt_task(rt_prog, arg,
180 (rt_setup_fn_t) setup_create_rt, &params);
181}
182
183int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) {
184 return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD);
185}
186
155 187
156void show_rt_param(rt_param_t* tp) 188void show_rt_param(rt_param_t* tp)
157{ 189{
diff --git a/src/rt_launch.c b/src/rt_launch.c
index a90bea8..cd98ad3 100644
--- a/src/rt_launch.c
+++ b/src/rt_launch.c
@@ -1,8 +1,11 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <stdlib.h> 2#include <stdlib.h>
3#include <string.h>
3#include <unistd.h> 4#include <unistd.h>
5#include <limits.h>
4 6
5#include "litmus.h" 7#include "litmus.h"
8#include "adaptive.h"
6 9
7typedef struct { 10typedef struct {
8 char * exec_path; 11 char * exec_path;
@@ -20,12 +23,38 @@ int launch(void *task_info_p) {
20 23
21void usage(char *error) { 24void usage(char *error) {
22 fprintf(stderr, "%s\nUsage: launch_rt [-c {hrt|srt|be}] [-p <cpu>]" 25 fprintf(stderr, "%s\nUsage: launch_rt [-c {hrt|srt|be}] [-p <cpu>]"
23 "<wcet> <period> program arg1 arg2 ...\n", 26 "{<wcet> <period>|{-a wcet/period/utility}+}"
27 " program arg1 arg2 ...\n",
24 error); 28 error);
25 exit(1); 29 exit(1);
26} 30}
27 31
28#define OPTSTR "p:c:" 32/* argument format should be wcet/period/utility */
33static int parse_service_level(service_level_t* level, char* str)
34{
35 char *wcet, *period, *utility;
36 double u;
37 wcet = strtok(str, "/");
38 period = strtok(NULL, "/");
39 utility = strtok(NULL, "/");
40 str = strtok(NULL, "/");
41
42 if (str || !utility || !period || !wcet)
43 return 0;
44
45 level->exec_cost = atol(wcet);
46 level->period = atol(period);
47 u = atof(utility);
48
49 if (level->exec_cost == 0 || level->period < level->exec_cost ||
50 u <= 0.0 || u > 1.0)
51 return 0;
52
53 level->utility = (unsigned long) ULONG_MAX * u;
54 return 1;
55}
56
57#define OPTSTR "p:c:a:"
29 58
30int main(int argc, char** argv) 59int main(int argc, char** argv)
31{ 60{
@@ -36,9 +65,20 @@ int main(int argc, char** argv)
36 int opt; 65 int opt;
37 startup_info_t info; 66 startup_info_t info;
38 task_class_t class = RT_CLASS_HARD; 67 task_class_t class = RT_CLASS_HARD;
68
69 int adaptive = 0;
70 unsigned int level = 0;
71 service_level_t slevel[MAX_SERVICE_LEVELS];
39 72
40 while ((opt = getopt(argc, argv, OPTSTR)) != -1) { 73 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
41 switch (opt) { 74 switch (opt) {
75 case 'a':
76 adaptive = 1;
77 if (level == MAX_SERVICE_LEVELS)
78 usage("Too many service levels.");
79 if (!parse_service_level(slevel + level++, optarg))
80 usage("Bad service level.");
81 break;
42 case 'p': 82 case 'p':
43 cpu = atoi(optarg); 83 cpu = atoi(optarg);
44 break; 84 break;
@@ -58,23 +98,32 @@ int main(int argc, char** argv)
58 } 98 }
59 } 99 }
60 100
61 if (argc - optind < 3) 101 if (!adaptive) {
62 { 102 if (argc - optind < 3)
63 printf("argc: %d optind: %d\n", argc, optind); 103 usage("Arguments missing.");
64 usage("Arguments missing."); 104 wcet = atoi(argv[optind + 0]);
65 } 105 period = atoi(argv[optind + 1]);
66 wcet = atoi(argv[optind + 0]); 106 if (wcet <= 0)
67 period = atoi(argv[optind + 1]); 107 usage("The worst-case execution time must be a "
68 if (wcet <= 0) 108 "positive number.");
69 usage("The worst-case execution time must be a positive number."); 109 if (period <= 0)
70 if (period <= 0) 110 usage("The period must be a positive number.");
71 usage("The period must be a positive number."); 111 if (wcet > period) {
72 if (wcet > period) { 112 usage("The worst-case execution time must not "
73 usage("The worst-case execution time must not exceed the period."); 113 "exceed the period.");
114 }
115 info.exec_path = argv[optind + 2];
116 info.argv = argv + optind + 2;
117 ret = __create_rt_task(launch, &info, cpu, wcet, period, class);
118 } else {
119 if (argc == optind)
120 usage("Arguments missing.");
121 info.exec_path = argv[optind];
122 info.argv = argv + optind;
123 ret = create_adaptive_rt_task(launch, &info, level, slevel);
74 } 124 }
75 info.exec_path = argv[optind + 2]; 125
76 info.argv = argv + optind + 2; 126
77 ret = __create_rt_task(launch, &info, cpu, wcet, period, class);
78 if (ret < 0) { 127 if (ret < 0) {
79 perror("Could not create rt child process"); 128 perror("Could not create rt child process");
80 return 2; 129 return 2;