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. --- Makefile | 4 +-- include/adaptive.h | 23 +++++++++++++++ include/litmus.h | 8 +++++ src/adaptive.c | 45 +++++++++++++++++++++++++++++ src/litmus.c | 60 +++++++++++++++++++++++++++++--------- src/rt_launch.c | 85 ++++++++++++++++++++++++++++++++++++++++++------------ 6 files changed, 191 insertions(+), 34 deletions(-) create mode 100644 include/adaptive.h create mode 100644 src/adaptive.c 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 edfhsb: liblitmus.a edf-hsb.o litmus.h edf-hsb.h hrt.o cc -o edfhsb hrt.o edf-hsb.o ${LIBS} -liblitmus.a: litmus.o litmus.h edf-hsb.o edf-hsb.h - ${AR} rcs liblitmus.a litmus.o edf-hsb.o +liblitmus.a: litmus.o adaptive.o adaptive.h litmus.h edf-hsb.o edf-hsb.h + ${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 @@ +#ifndef ADAPTIVE_H +#define ADAPTIVE_H + +#define MAX_SERVICE_LEVELS 10 + +typedef struct { + unsigned long exec_cost; + unsigned long period; + /* fixed point */ + unsigned long utility; +} service_level_t; + +int set_service_levels(pid_t pid, + unsigned int nr_levels, + service_level_t* levels); + +int get_cur_service_level(void); + +int create_adaptive_rt_task(rt_fn_t rt_prog, void *arg, + unsigned int no_levels, service_level_t* levels); + + +#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 @@ #define CLONE_REALTIME 0x10000000 typedef int (*rt_fn_t)(void*); +typedef int (*rt_setup_fn_t)(int pid, void* arg); /* Litmus scheduling policies */ typedef enum { @@ -99,6 +100,7 @@ void init_litmus(void); #define exit_litmus() {} + int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period); int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period, task_class_t cls); @@ -111,4 +113,10 @@ void exit_np(void); int litmus_task_active(); + +/* low level operations, not intended for API use */ +int fork_rt(void); +int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, + rt_setup_fn_t setup, void* setup_arg); + #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 @@ +#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