From 2c34274eb9dca67c916fc8f5d3b6f20bb17202c4 Mon Sep 17 00:00:00 2001 From: Andrea Bastoni Date: Sat, 12 Jun 2010 12:14:16 -0400 Subject: [EDF-fm] Add support for sporadic edf-fm tasks and rtspin_edffm --- SConstruct | 1 + bin/rtspin_edffm.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/litmus.h | 5 + src/litmus.c | 38 +++++++- 4 files changed, 304 insertions(+), 3 deletions(-) create mode 100644 bin/rtspin_edffm.c diff --git a/SConstruct b/SConstruct index c41e41e..7ae2883 100644 --- a/SConstruct +++ b/SConstruct @@ -208,6 +208,7 @@ rt.Program('base_task', 'bin/base_task.c') mtrt.Program('base_mt_task', 'bin/base_mt_task.c') rt.Program('rt_launch', ['bin/rt_launch.c', 'bin/common.c']) rt.Program('rtspin', ['bin/rtspin.c', 'bin/common.c']) +rt.Program('rtspin_edffm', ['bin/rtspin_edffm.c', 'bin/common.c']) rt.Program('release_ts', 'bin/release_ts.c') rtm.Program('measure_syscall', 'bin/null_call.c') diff --git a/bin/rtspin_edffm.c b/bin/rtspin_edffm.c new file mode 100644 index 0000000..04dce0a --- /dev/null +++ b/bin/rtspin_edffm.c @@ -0,0 +1,263 @@ +#include + +#include +#include +#include +#include + + +#include "litmus.h" +#include "common.h" + + +static double cputime() +{ + struct timespec ts; + int err; + err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); + if (err != 0) + perror("clock_gettime"); + return (ts.tv_sec + 1E-9 * ts.tv_nsec); +} + +static double wctime() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec + 1E-6 * tv.tv_usec); +} + +void usage(char *error) { + fprintf(stderr, "Error: %s\n", error); + fprintf(stderr, + "Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION fracnum1 fracden2 fracnum2 fracden2 cpu1 cpu2\n" + " rt_spin -l\n"); + exit(1); +} + +#define NUMS 4096 +static int num[NUMS]; +static double loop_length = 1.0; +static char* progname; + +static int loop_once(void) +{ + int i, j = 0; + for (i = 0; i < NUMS; i++) + j += num[i]++; + return j; +} + +static int loop_for(double exec_time) +{ + double t = 0; + int tmp = 0; +/* while (t + loop_length < exec_time) { + tmp += loop_once(); + t += loop_length; + } +*/ + double start = cputime(); + double now = cputime(); + while (now + loop_length < start + exec_time) { + tmp += loop_once(); + t += loop_length; + now = cputime(); + } + + return tmp; +} + +static void fine_tune(double interval) +{ + double start, end, delta; + + start = wctime(); + loop_for(interval); + end = wctime(); + delta = (end - start - interval) / interval; + if (delta != 0) + loop_length = loop_length / (1 - delta); +} + +static void configure_loop(void) +{ + double start; + + /* prime cache */ + loop_once(); + loop_once(); + loop_once(); + + /* measure */ + start = wctime(); + loop_once(); /* hope we didn't get preempted */ + loop_length = wctime(); + loop_length -= start; + + /* fine tune */ + fine_tune(0.1); + fine_tune(0.1); + fine_tune(0.1); +} + +static void show_loop_length(void) +{ + printf("%s/%d: loop_length=%f (%ldus)\n", + progname, getpid(), loop_length, + (long) (loop_length * 1000000)); +} + +static void debug_delay_loop(void) +{ + double start, end, delay; + show_loop_length(); + while (1) { + for (delay = 0.5; delay > 0.01; delay -= 0.01) { + start = wctime(); + loop_for(delay); + end = wctime(); + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n", + delay, + end - start, + end - start - delay, + 100 * (end - start - delay) / delay); + } + } +} + +static int job(double exec_time) +{ + loop_for(exec_time); + sleep_next_period(); + return 0; +} + +#define OPTSTR "p:c:wld:v" + +int main(int argc, char** argv) +{ + int ret; + lt_t wcet; + lt_t period; + /* [num,den] */ + lt_t frac1[2], frac2[2]; + int cpu1, cpu2; + double wcet_ms, period_ms; + int migrate = 0; + int cpu = 0; + int opt; + int wait = 0; + int test_loop = 0; + int skip_config = 0; + int verbose = 0; + double duration, start; + task_class_t class = RT_CLASS_HARD; + + progname = argv[0]; + + while ((opt = getopt(argc, argv, OPTSTR)) != -1) { + switch (opt) { + case 'w': + wait = 1; + break; + case 'p': + cpu = atoi(optarg); + migrate = 1; + break; + case 'c': + class = str2class(optarg); + if (class == -1) + usage("Unknown task class."); + break; + case 'l': + test_loop = 1; + break; + case 'd': + /* manually configure delay per loop iteration + * unit: microseconds */ + loop_length = atof(optarg) / 1000000; + skip_config = 1; + break; + case 'v': + verbose = 1; + break; + case ':': + usage("Argument missing."); + break; + case '?': + default: + usage("Bad argument."); + break; + } + } + + + if (!skip_config) + configure_loop(); + + if (test_loop) { + debug_delay_loop(); + return 0; + } + + if (argc - optind < 3) + usage("Arguments missing."); + wcet_ms = atof(argv[optind + 0]); + period_ms = atof(argv[optind + 1]); + duration = atof(argv[optind + 2]); + /* frac num, den = 0 means fixed task */ + frac1[0] = atoi(argv[optind + 3]); + frac1[1] = atoi(argv[optind + 4]); + frac2[0] = atoi(argv[optind + 5]); + frac2[1] = atoi(argv[optind + 6]); + cpu1 = atoi(argv[optind + 7]); + cpu2 = atoi(argv[optind + 8]); + wcet = wcet_ms * __NS_PER_MS; + period = period_ms * __NS_PER_MS; + 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 (migrate) { + ret = be_migrate_to(cpu); + if (ret < 0) + bail_out("could not migrate to target partition"); + } + + ret = sporadic_task_ns_edffm(wcet, period, 0, cpu, + frac1, frac2, cpu1, cpu2, + class, NO_ENFORCEMENT, migrate); + + if (ret < 0) + bail_out("could not setup rt task params"); + + if (verbose) + show_loop_length(); + + init_litmus(); + + ret = task_mode(LITMUS_RT_TASK); + if (ret != 0) + bail_out("could not become RT task"); + + if (wait) { + ret = wait_for_ts_release(); + if (ret != 0) + bail_out("wait_for_ts_release()"); + } + + start = wctime(); + + while (start + duration > wctime()) { + job(wcet_ms * 0.0009); /* 90% wcet, in seconds */ + } + + return 0; +} diff --git a/include/litmus.h b/include/litmus.h index b798c92..e27b10d 100644 --- a/include/litmus.h +++ b/include/litmus.h @@ -40,6 +40,11 @@ int sporadic_task_ns( int cpu, task_class_t cls, budget_policy_t budget_policy, int set_cpu_set); +int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu, + lt_t *frac1, lt_t *frac2, int cpu1, int cpu2, + task_class_t cls, budget_policy_t budget_policy, + int set_cpu_set); + /* budget enforcement off by default in these macros */ #define sporadic_global(e, p) \ sporadic_task(e, p, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 0) diff --git a/src/litmus.c b/src/litmus.c index f71f337..d253368 100644 --- a/src/litmus.c +++ b/src/litmus.c @@ -10,14 +10,14 @@ #include "litmus.h" #include "internal.h" -void show_rt_param(struct rt_task* tp) +void show_rt_param(struct rt_task* tp) { printf("rt params:\n\t" "exec_cost:\t%llu\n\tperiod:\t\t%llu\n\tcpu:\t%d\n", tp->exec_cost, tp->period, tp->cpu); } -task_class_t str2class(const char* str) +task_class_t str2class(const char* str) { if (!strcmp(str, "hrt")) return RT_CLASS_HARD; @@ -62,7 +62,39 @@ int sporadic_task_ns(lt_t e, lt_t p, lt_t phase, param.phase = phase; param.budget_policy = budget_policy; - if (set_cpu_set) { + if (set_cpu_set) { + ret = be_migrate_to(cpu); + check("migrate to cpu"); + } + return set_rt_task_param(gettid(), ¶m); +} + +int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu, + lt_t *frac1, lt_t *frac2, int cpu1, int cpu2, + task_class_t cls, budget_policy_t budget_policy, + int set_cpu_set) +{ + struct rt_task param; + int ret; + param.exec_cost = e; + param.period = p; + param.cpu = cpu; + /* check on denominators */ + if (frac1[1] != 0 && frac2[1] != 0) { + /* edf-fm migrat task */ + param.nr_cpus = 1; + param.cpus[0] = cpu1; + param.cpus[1] = cpu2; + param.fraction[0][0] = frac1[0]; + param.fraction[1][0] = frac1[1]; + param.fraction[0][1] = frac2[0]; + param.fraction[1][1] = frac2[1]; + } + param.cls = cls; + param.phase = phase; + param.budget_policy = budget_policy; + + if (set_cpu_set) { ret = be_migrate_to(cpu); check("migrate to cpu"); } -- cgit v1.2.2