diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | include/adaptive.h | 24 | ||||
-rw-r--r-- | src/adaptive.c | 16 | ||||
-rw-r--r-- | src/rt_launch.c | 82 |
4 files changed, 97 insertions, 27 deletions
@@ -1,4 +1,4 @@ | |||
1 | CFLAGS=-Wall -g -Iinclude/ | 1 | CFLAGS=-Wall -g -Iinclude/ -D_XOPEN_SOURCE=600 |
2 | CPPFLAGS=-Wall -g | 2 | CPPFLAGS=-Wall -g |
3 | 3 | ||
4 | LIBS= ./liblitmus.a | 4 | LIBS= ./liblitmus.a |
diff --git a/include/adaptive.h b/include/adaptive.h index a67c540..21e1dfd 100644 --- a/include/adaptive.h +++ b/include/adaptive.h | |||
@@ -1,23 +1,35 @@ | |||
1 | #ifndef ADAPTIVE_H | 1 | #ifndef ADAPTIVE_H |
2 | #define ADAPTIVE_H | 2 | #define ADAPTIVE_H |
3 | 3 | ||
4 | #define MAX_SERVICE_LEVELS 10 | 4 | #define FP_SHIFT 16 |
5 | typedef struct | ||
6 | { | ||
7 | long long val; | ||
8 | } fp_t; | ||
9 | |||
10 | static inline fp_t f2fp(double f) | ||
11 | { | ||
12 | return (fp_t) {f * (1 << FP_SHIFT)}; | ||
13 | } | ||
5 | 14 | ||
15 | #define MAX_SERVICE_LEVELS 10 | ||
6 | typedef struct { | 16 | typedef struct { |
7 | unsigned long exec_cost; | 17 | fp_t weight; |
8 | unsigned long period; | 18 | unsigned long period; |
9 | /* fixed point */ | 19 | fp_t value; |
10 | unsigned long utility; | ||
11 | } service_level_t; | 20 | } service_level_t; |
12 | 21 | ||
13 | int set_service_levels(pid_t pid, | 22 | int set_service_levels(pid_t pid, |
14 | unsigned int nr_levels, | 23 | unsigned int nr_levels, |
15 | service_level_t* levels); | 24 | service_level_t* levels, |
25 | fp_t *wt_y, | ||
26 | fp_t *wt_slope); | ||
16 | 27 | ||
17 | int get_cur_service_level(void); | 28 | int get_cur_service_level(void); |
18 | 29 | ||
19 | int create_adaptive_rt_task(rt_fn_t rt_prog, void *arg, | 30 | int create_adaptive_rt_task(rt_fn_t rt_prog, void *arg, |
20 | unsigned int no_levels, service_level_t* levels); | 31 | unsigned int no_levels, service_level_t* levels, |
32 | fp_t wt_y, fp_t wt_slope); | ||
21 | 33 | ||
22 | 34 | ||
23 | #endif | 35 | #endif |
diff --git a/src/adaptive.c b/src/adaptive.c index ebf662d..8dfb27b 100644 --- a/src/adaptive.c +++ b/src/adaptive.c | |||
@@ -11,9 +11,11 @@ | |||
11 | 11 | ||
12 | int set_service_levels(pid_t pid, | 12 | int set_service_levels(pid_t pid, |
13 | unsigned int nr_levels, | 13 | unsigned int nr_levels, |
14 | service_level_t* levels) | 14 | service_level_t* levels, |
15 | fp_t *wt_y, | ||
16 | fp_t *wt_slope) | ||
15 | { | 17 | { |
16 | return syscall(__NR_set_service_levels, pid, nr_levels, levels); | 18 | return syscall(__NR_set_service_levels, pid, nr_levels, levels, wt_y, wt_slope); |
17 | } | 19 | } |
18 | 20 | ||
19 | 21 | ||
@@ -26,19 +28,25 @@ int get_cur_service_level(void) | |||
26 | struct adaptive_param { | 28 | struct adaptive_param { |
27 | unsigned int no_levels; | 29 | unsigned int no_levels; |
28 | service_level_t* levels; | 30 | service_level_t* levels; |
31 | fp_t wt_y; | ||
32 | fp_t wt_slope; | ||
29 | }; | 33 | }; |
30 | 34 | ||
31 | int setup_adaptive(int pid, struct adaptive_param* arg) | 35 | int setup_adaptive(int pid, struct adaptive_param* arg) |
32 | { | 36 | { |
33 | return set_service_levels(pid, arg->no_levels, arg->levels); | 37 | return set_service_levels(pid, arg->no_levels, arg->levels, |
38 | &arg->wt_y, &arg->wt_slope); | ||
34 | } | 39 | } |
35 | 40 | ||
36 | int create_adaptive_rt_task(rt_fn_t rt_prog, void *arg, | 41 | int create_adaptive_rt_task(rt_fn_t rt_prog, void *arg, |
37 | unsigned int no_levels, service_level_t* levels) | 42 | unsigned int no_levels, service_level_t* levels, |
43 | fp_t wt_y, fp_t wt_slope) | ||
38 | { | 44 | { |
39 | struct adaptive_param p; | 45 | struct adaptive_param p; |
40 | p.no_levels = no_levels; | 46 | p.no_levels = no_levels; |
41 | p.levels = levels; | 47 | p.levels = levels; |
48 | p.wt_y = wt_y; | ||
49 | p.wt_slope = wt_slope; | ||
42 | return __launch_rt_task(rt_prog, arg, | 50 | return __launch_rt_task(rt_prog, arg, |
43 | (rt_setup_fn_t) setup_adaptive, &p); | 51 | (rt_setup_fn_t) setup_adaptive, &p); |
44 | } | 52 | } |
diff --git a/src/rt_launch.c b/src/rt_launch.c index cd98ad3..b76cb8c 100644 --- a/src/rt_launch.c +++ b/src/rt_launch.c | |||
@@ -22,39 +22,78 @@ int launch(void *task_info_p) { | |||
22 | } | 22 | } |
23 | 23 | ||
24 | void usage(char *error) { | 24 | void usage(char *error) { |
25 | fprintf(stderr, "%s\nUsage: launch_rt [-c {hrt|srt|be}] [-p <cpu>]" | 25 | fprintf(stderr, "%s\nUsage: \nlaunch_rt supports one of two modes:\n" |
26 | "{<wcet> <period>|{-a wcet/period/utility}+}" | 26 | "\n\tlaunch_rt <SPORADIC OPTIONS> program arg1 arg2 ...\n" |
27 | " program arg1 arg2 ...\n", | 27 | "\n\tlaunch_rt <ADAPTIVE OPTIONS> program arg1 arg2 ...\n" |
28 | "\nwhere:" | ||
29 | "\n\t <SPORADIC OPTIONS> = " | ||
30 | "[-c {hrt|srt|be}] [-p <cpu>] <wcet> <period>\n" | ||
31 | "\n\t <ADAPTIVE OPTIONS> = " | ||
32 | "(-a weight/period/utility)+ [-w <y intercept>+<slope>v]\n" | ||
33 | "\nExamples:" | ||
34 | "\n\trt_launch -p 2 10 100 cpu_job" | ||
35 | "\n\t => Launch cpu_job a hard real-time task with period 100 and weight 0.1" | ||
36 | "\n\t on CPU 2.\n" | ||
37 | "\n\trt_launch -a 0.1/100/0.4 -a 0.2/75/0.5 -w 0.2+0.3v adaptive_job" | ||
38 | "\n\t => Launch adaptive_job with two service levels and a custom " | ||
39 | "\n\t weight-transfer function." | ||
40 | "\n\n", | ||
28 | error); | 41 | error); |
29 | exit(1); | 42 | exit(1); |
30 | } | 43 | } |
31 | 44 | ||
32 | /* argument format should be wcet/period/utility */ | 45 | /* argument format should be weight/period/utility */ |
33 | static int parse_service_level(service_level_t* level, char* str) | 46 | static int parse_service_level(service_level_t* level, char* str) |
34 | { | 47 | { |
35 | char *wcet, *period, *utility; | 48 | char *weight, *period, *utility; |
36 | double u; | 49 | double u, w; |
37 | wcet = strtok(str, "/"); | 50 | weight = strtok(str, "/"); |
38 | period = strtok(NULL, "/"); | 51 | period = strtok(NULL, "/"); |
39 | utility = strtok(NULL, "/"); | 52 | utility = strtok(NULL, "/"); |
40 | str = strtok(NULL, "/"); | 53 | str = strtok(NULL, "/"); |
41 | 54 | ||
42 | if (str || !utility || !period || !wcet) | 55 | if (str || !utility || !period || !weight) |
43 | return 0; | 56 | return 0; |
44 | 57 | ||
45 | level->exec_cost = atol(wcet); | 58 | w = atof(weight); |
46 | level->period = atol(period); | ||
47 | u = atof(utility); | 59 | u = atof(utility); |
60 | level->weight = f2fp(w); | ||
61 | level->period = atol(period); | ||
62 | level->value = f2fp(u); | ||
63 | |||
64 | if (level->period == 0 || | ||
65 | u <= 0.0 || u > 1.0 || w <= 0.0 || w > 1.0) | ||
66 | return 0; | ||
67 | return 1; | ||
68 | } | ||
48 | 69 | ||
49 | if (level->exec_cost == 0 || level->period < level->exec_cost || | 70 | /* argument format should be <y intercept>+<slope>v */ |
50 | u <= 0.0 || u > 1.0) | 71 | static int parse_wt(fp_t *_y, fp_t *_slope, char* str) |
72 | { | ||
73 | char *y, *slope; | ||
74 | double yf, sf; | ||
75 | y = strtok(str, "+"); | ||
76 | slope = strtok(NULL, "v"); | ||
77 | str = strtok(NULL, "/"); /* If we find anyting at all then the | ||
78 | * string is malformed. | ||
79 | */ | ||
80 | if (str || !y || !slope) | ||
51 | return 0; | 81 | return 0; |
52 | 82 | ||
53 | level->utility = (unsigned long) ULONG_MAX * u; | 83 | yf = strtof(y, &y); |
84 | sf = strtof(slope, &slope); | ||
85 | |||
86 | if (*y || *slope || | ||
87 | yf < 0.0 || sf <= 0.0) | ||
88 | return 0; | ||
89 | |||
90 | *_y = f2fp(yf); | ||
91 | *_slope = f2fp(sf); | ||
54 | return 1; | 92 | return 1; |
55 | } | 93 | } |
56 | 94 | ||
57 | #define OPTSTR "p:c:a:" | 95 | |
96 | #define OPTSTR "p:c:a:w:" | ||
58 | 97 | ||
59 | int main(int argc, char** argv) | 98 | int main(int argc, char** argv) |
60 | { | 99 | { |
@@ -69,7 +108,13 @@ int main(int argc, char** argv) | |||
69 | int adaptive = 0; | 108 | int adaptive = 0; |
70 | unsigned int level = 0; | 109 | unsigned int level = 0; |
71 | service_level_t slevel[MAX_SERVICE_LEVELS]; | 110 | service_level_t slevel[MAX_SERVICE_LEVELS]; |
111 | fp_t wt_y; /* weight-transfer y intercept */ | ||
112 | fp_t wt_slope; /* weight-transfer slope */ | ||
72 | 113 | ||
114 | |||
115 | wt_y = f2fp(0.0); | ||
116 | wt_slope = f2fp(1.0); | ||
117 | |||
73 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | 118 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { |
74 | switch (opt) { | 119 | switch (opt) { |
75 | case 'a': | 120 | case 'a': |
@@ -79,6 +124,10 @@ int main(int argc, char** argv) | |||
79 | if (!parse_service_level(slevel + level++, optarg)) | 124 | if (!parse_service_level(slevel + level++, optarg)) |
80 | usage("Bad service level."); | 125 | usage("Bad service level."); |
81 | break; | 126 | break; |
127 | case 'w': | ||
128 | if (!parse_wt(&wt_y, &wt_slope, optarg)) | ||
129 | usage("Bad weight transfer function."); | ||
130 | break; | ||
82 | case 'p': | 131 | case 'p': |
83 | cpu = atoi(optarg); | 132 | cpu = atoi(optarg); |
84 | break; | 133 | break; |
@@ -93,7 +142,7 @@ int main(int argc, char** argv) | |||
93 | break; | 142 | break; |
94 | case '?': | 143 | case '?': |
95 | default: | 144 | default: |
96 | usage("Unknown flag."); | 145 | usage("Bad argument."); |
97 | break; | 146 | break; |
98 | } | 147 | } |
99 | } | 148 | } |
@@ -120,7 +169,8 @@ int main(int argc, char** argv) | |||
120 | usage("Arguments missing."); | 169 | usage("Arguments missing."); |
121 | info.exec_path = argv[optind]; | 170 | info.exec_path = argv[optind]; |
122 | info.argv = argv + optind; | 171 | info.argv = argv + optind; |
123 | ret = create_adaptive_rt_task(launch, &info, level, slevel); | 172 | ret = create_adaptive_rt_task(launch, &info, level, slevel, |
173 | wt_y, wt_slope); | ||
124 | } | 174 | } |
125 | 175 | ||
126 | 176 | ||