From c176d77f446a9f218e0bd413bfad949b286e8326 Mon Sep 17 00:00:00 2001 From: Andrea Bastoni Date: Thu, 24 Jun 2010 19:50:19 -0400 Subject: [NPS-F] Add rtspin and utility to add notional processors - add syscall to add notional processors (servers) - add rtspin_npsf program to run on specified (npsf_id, cpu) - add npsf_add_server as wrapper on the syscall --- bin/npsf_add_server.c | 45 +++++++++ bin/rtspin_npsf.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 297 insertions(+) create mode 100644 bin/npsf_add_server.c create mode 100644 bin/rtspin_npsf.c (limited to 'bin') diff --git a/bin/npsf_add_server.c b/bin/npsf_add_server.c new file mode 100644 index 0000000..3983e77 --- /dev/null +++ b/bin/npsf_add_server.c @@ -0,0 +1,45 @@ +/* wrapper for sys_add_server */ +#include +#include +#include + +#include "litmus.h" +#include "common.h" + +void usage(char *error) { + fprintf(stderr, "Error: %s\n", error); + fprintf(stderr, + "Usage: npsf_add_server NPSF-ID UTIL SLOT-SIZE(ms) CPU \n"); + exit(1); +} + +int main(int argc, char** argv) +{ + int ret; + int cpu = 0; + int npsf_id = 0; + double util = 0; + int slot_ms = 0; + lt_t budget_ns = 0; + + if (argc < 5) + usage("Arguments missing."); + npsf_id = atoi(argv[1]); + util = atof(argv[2]); + slot_ms = atoi(argv[3]); + cpu = atoi(argv[4]); + + if (util > 1) + usage("Utilization > 1"); + + budget_ns = (lt_t)((__NS_PER_MS * util) * slot_ms); + + printf("Trying to add NP(%d): budget = %f\n", npsf_id, (double)(budget_ns) / __NS_PER_MS); + + ret = add_server(&npsf_id, &budget_ns, &cpu); + + if (ret < 0) + bail_out("Cannot add Notional Processor: "); + + return 0; +} diff --git a/bin/rtspin_npsf.c b/bin/rtspin_npsf.c new file mode 100644 index 0000000..87eb52f --- /dev/null +++ b/bin/rtspin_npsf.c @@ -0,0 +1,252 @@ +#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] WCET PERIOD DURATION CPU NPSF-ID\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 "c:wld:v" + +int main(int argc, char** argv) +{ + int ret; + lt_t wcet; + lt_t period; + double wcet_ms, period_ms; + int migrate = 0; + int cpu = 0; + int npsf_id = 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 '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]); + cpu = atoi(argv[optind + 3]); + migrate = 1; + npsf_id = atoi(argv[optind + 4]); + 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_npsf(wcet, period, 0, cpu, class, npsf_id, + 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; +} -- cgit v1.2.2