From 9de8f0850ce4b34a849384d119fc9e5a6f3f8d17 Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Fri, 5 Oct 2007 12:41:53 -0400 Subject: Implement user space adaptive task launching interface. --- src/adaptive.c | 45 ++++++++++++++++++++++++++++++ src/litmus.c | 60 ++++++++++++++++++++++++++++++---------- src/rt_launch.c | 85 +++++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 158 insertions(+), 32 deletions(-) create mode 100644 src/adaptive.c (limited to 'src') 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 @@ +#include +#include + +#include "litmus.h" +#include "adaptive.h" + +#define __NR_set_service_levels 346 +#define __NR_get_cur_service_level 347 + + + +int set_service_levels(pid_t pid, + unsigned int nr_levels, + service_level_t* levels) +{ + return syscall(__NR_set_service_levels, pid, nr_levels, levels); +} + + +int get_cur_service_level(void) +{ + return syscall(__NR_get_cur_service_level); +} + + +struct adaptive_param { + unsigned int no_levels; + service_level_t* levels; +}; + +int setup_adaptive(int pid, struct adaptive_param* arg) +{ + return set_service_levels(pid, arg->no_levels, arg->levels); +} + +int create_adaptive_rt_task(rt_fn_t rt_prog, void *arg, + unsigned int no_levels, service_level_t* levels) +{ + struct adaptive_param p; + p.no_levels = no_levels; + p.levels = levels; + return __launch_rt_task(rt_prog, arg, + (rt_setup_fn_t) setup_adaptive, &p); +} + 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) \ _syscall2(int, raw_clone, unsigned long, flags, unsigned long, child_stack) +int fork_rt(void) +{ + int rt_task = raw_clone(CLONE_LITMUS, 0); + return rt_task; +} + const char* get_scheduler_name(spolicy scheduler) { @@ -103,27 +109,20 @@ const char* get_scheduler_name(spolicy scheduler) return name; } -int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) { - return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD); -} -int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period, - task_class_t class) +/* common launch routine */ +int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup, + void* setup_arg) { int ret; - rt_param_t params; - int rt_task = raw_clone(CLONE_LITMUS, 0); + int rt_task = fork_rt(); if (rt_task < 0) return rt_task; if (rt_task > 0) { /* we are the controller task */ - params.period = period; - params.exec_cost = wcet; - params.cpu = cpu; - params.cls = class; - ret = set_rt_task_param(rt_task, ¶ms); + ret = setup(rt_task, setup_arg); if (ret < 0) { /* we have a problem: we created the task but * 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, ret = prepare_rt_task(rt_task); if (ret < 0) { /* same problem as above*/ - //kill(rt_task, SIGKILL); + kill(rt_task, SIGKILL); rt_task = -1; } return rt_task; @@ -148,10 +147,43 @@ int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period, * launch task and die when it is done */ - exit(rt_prog(arg)); + exit(rt_prog(rt_arg)); } } +struct create_rt_param { + int cpu; + int wcet; + int period; + task_class_t class; +}; + +int setup_create_rt(int pid, struct create_rt_param* arg) +{ + rt_param_t params; + params.period = arg->period; + params.exec_cost = arg->wcet; + params.cpu = arg->cpu; + params.cls = arg->class; + return set_rt_task_param(pid, ¶ms); +} + +int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period, + task_class_t class) +{ + struct create_rt_param params; + params.cpu = cpu; + params.period = period; + params.wcet = wcet; + params.class = class; + return __launch_rt_task(rt_prog, arg, + (rt_setup_fn_t) setup_create_rt, ¶ms); +} + +int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) { + return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD); +} + void show_rt_param(rt_param_t* tp) { 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 @@ #include #include +#include #include +#include #include "litmus.h" +#include "adaptive.h" typedef struct { char * exec_path; @@ -20,12 +23,38 @@ int launch(void *task_info_p) { void usage(char *error) { fprintf(stderr, "%s\nUsage: launch_rt [-c {hrt|srt|be}] [-p ]" - " program arg1 arg2 ...\n", + "{ |{-a wcet/period/utility}+}" + " program arg1 arg2 ...\n", error); exit(1); } -#define OPTSTR "p:c:" +/* argument format should be wcet/period/utility */ +static int parse_service_level(service_level_t* level, char* str) +{ + char *wcet, *period, *utility; + double u; + wcet = strtok(str, "/"); + period = strtok(NULL, "/"); + utility = strtok(NULL, "/"); + str = strtok(NULL, "/"); + + if (str || !utility || !period || !wcet) + return 0; + + level->exec_cost = atol(wcet); + level->period = atol(period); + u = atof(utility); + + if (level->exec_cost == 0 || level->period < level->exec_cost || + u <= 0.0 || u > 1.0) + return 0; + + level->utility = (unsigned long) ULONG_MAX * u; + return 1; +} + +#define OPTSTR "p:c:a:" int main(int argc, char** argv) { @@ -36,9 +65,20 @@ int main(int argc, char** argv) int opt; startup_info_t info; task_class_t class = RT_CLASS_HARD; + + int adaptive = 0; + unsigned int level = 0; + service_level_t slevel[MAX_SERVICE_LEVELS]; while ((opt = getopt(argc, argv, OPTSTR)) != -1) { switch (opt) { + case 'a': + adaptive = 1; + if (level == MAX_SERVICE_LEVELS) + usage("Too many service levels."); + if (!parse_service_level(slevel + level++, optarg)) + usage("Bad service level."); + break; case 'p': cpu = atoi(optarg); break; @@ -58,23 +98,32 @@ int main(int argc, char** argv) } } - if (argc - optind < 3) - { - printf("argc: %d optind: %d\n", argc, optind); - usage("Arguments missing."); - } - wcet = atoi(argv[optind + 0]); - period = atoi(argv[optind + 1]); - if (wcet <= 0) - usage("The worst-case execution time must be a positive number."); - if (period <= 0) - usage("The period must be a positive number."); - if (wcet > period) { - usage("The worst-case execution time must not exceed the period."); + if (!adaptive) { + if (argc - optind < 3) + usage("Arguments missing."); + wcet = atoi(argv[optind + 0]); + period = atoi(argv[optind + 1]); + if (wcet <= 0) + usage("The worst-case execution time must be a " + "positive number."); + if (period <= 0) + usage("The period must be a positive number."); + if (wcet > period) { + usage("The worst-case execution time must not " + "exceed the period."); + } + info.exec_path = argv[optind + 2]; + info.argv = argv + optind + 2; + ret = __create_rt_task(launch, &info, cpu, wcet, period, class); + } else { + if (argc == optind) + usage("Arguments missing."); + info.exec_path = argv[optind]; + info.argv = argv + optind; + ret = create_adaptive_rt_task(launch, &info, level, slevel); } - info.exec_path = argv[optind + 2]; - info.argv = argv + optind + 2; - ret = __create_rt_task(launch, &info, cpu, wcet, period, class); + + if (ret < 0) { perror("Could not create rt child process"); return 2; -- cgit v1.2.2