diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/rt-app.c | 140 | ||||
-rw-r--r-- | src/rt-app_args.h | 3 | ||||
-rw-r--r-- | src/rt-app_parse_config.c | 13 | ||||
-rw-r--r-- | src/rt-app_parse_config.h | 2 | ||||
-rw-r--r-- | src/rt-app_types.h | 18 | ||||
-rw-r--r-- | src/rt-app_utils.c | 27 | ||||
-rw-r--r-- | src/rt-app_utils.h | 6 |
7 files changed, 162 insertions, 47 deletions
diff --git a/src/rt-app.c b/src/rt-app.c index 5283ac7..a7a1eb4 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -35,10 +35,11 @@ static int nthreads; static volatile sig_atomic_t running_threads; static int p_load; rtapp_options_t opts; +static struct timespec t_zero; +static pthread_barrier_t threads_barrier; static ftrace_data_t ft_data = { .debugfs = "/sys/kernel/debug", - .trace_fd = -1, .marker_fd = -1, }; @@ -46,10 +47,11 @@ static ftrace_data_t ft_data = { * Function: to do some useless operation. * TODO: improve the waste loop with more heavy functions */ -void waste_cpu_cycles(int load_loops) +void waste_cpu_cycles(unsigned long long load_loops) { double param, result; - double n, i; + double n; + unsigned long long i; param = 0.95; n = 4; @@ -170,10 +172,27 @@ int calibrate_cpu_cycles(int clock) } -static inline loadwait(unsigned long exec) +static inline unsigned long loadwait(unsigned long exec) { unsigned long load_count; + unsigned long secs; + int i; + + /* + * If exec is still too big, let's run it in bursts + * so that we don't overflow load_count. + */ + secs = exec / 1000000; + for (i = 0; i < secs; i++) { + load_count = 1000000000/p_load; + waste_cpu_cycles(load_count); + exec -= 1000000; + } + + /* + * Run for the remainig exec (if any). + */ load_count = (exec * 1000)/p_load; waste_cpu_cycles(load_count); @@ -217,7 +236,8 @@ static void memload(unsigned long count, struct _rtapp_iomem_buf *iomem) } static int run_event(event_data_t *event, int dry_run, - unsigned long *perf, unsigned long *duration, rtapp_resource_t *resources) + unsigned long *perf, rtapp_resource_t *resources, + struct timespec *t_first, log_data_t *ldata) { rtapp_resource_t *rdata = &(resources[event->res]); rtapp_resource_t *ddata = &(resources[event->dep]); @@ -267,11 +287,12 @@ static int run_event(event_data_t *event, int dry_run, { struct timespec t_start, t_end; log_debug("run %d ", event->duration); + ldata->c_duration += event->duration; clock_gettime(CLOCK_MONOTONIC, &t_start); *perf += loadwait(event->duration); clock_gettime(CLOCK_MONOTONIC, &t_end); t_end = timespec_sub(&t_end, &t_start); - *duration += timespec_to_usec(&t_end); + ldata->duration += timespec_to_usec(&t_end); } break; case rtapp_runtime: @@ -280,6 +301,7 @@ static int run_event(event_data_t *event, int dry_run, int64_t diff_ns; log_debug("runtime %d ", event->duration); + ldata->c_duration += event->duration; clock_gettime(CLOCK_MONOTONIC, &t_start); do { @@ -291,27 +313,39 @@ static int run_event(event_data_t *event, int dry_run, } while ((diff_ns / 1000) < event->duration); t_end = timespec_sub(&t_end, &t_start); - *duration += timespec_to_usec(&t_end); + ldata->duration += timespec_to_usec(&t_end); } break; case rtapp_timer: { - struct timespec t_period, t_now; + struct timespec t_period, t_now, t_wu, t_slack; log_debug("timer %d ", event->duration); t_period = usec_to_timespec(event->duration); + ldata->c_period += event->duration; if (rdata->res.timer.init == 0) { rdata->res.timer.init = 1; - clock_gettime(CLOCK_MONOTONIC, &rdata->res.timer.t_next); + rdata->res.timer.t_next = *t_first; } rdata->res.timer.t_next = timespec_add(&rdata->res.timer.t_next, &t_period); clock_gettime(CLOCK_MONOTONIC, &t_now); - if (timespec_lower(&t_now, &rdata->res.timer.t_next)) - clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &rdata->res.timer.t_next, NULL); + t_slack = timespec_sub(&rdata->res.timer.t_next, &t_now); + if (opts.cumulative_slack) + ldata->slack += timespec_to_usec_long(&t_slack); else - clock_gettime(CLOCK_MONOTONIC, &rdata->res.timer.t_next); + ldata->slack = timespec_to_usec_long(&t_slack); + if (timespec_lower(&t_now, &rdata->res.timer.t_next)) { + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &rdata->res.timer.t_next, NULL); + clock_gettime(CLOCK_MONOTONIC, &t_now); + t_wu = timespec_sub(&t_now, &rdata->res.timer.t_next); + ldata->wu_latency += timespec_to_usec(&t_wu); + } else { + if (rdata->res.timer.relative) + clock_gettime(CLOCK_MONOTONIC, &rdata->res.timer.t_next); + ldata->wu_latency = 0UL; + } } break; case rtapp_suspend: @@ -347,8 +381,11 @@ static int run_event(event_data_t *event, int dry_run, return lock; } -int run(int ind, phase_data_t *pdata, unsigned long *duration, - rtapp_resource_t *resources) +int run(int ind, + phase_data_t *pdata, + rtapp_resource_t *resources, + struct timespec *t_first, + log_data_t *ldata) { event_data_t *events = pdata->events; int nbevents = pdata->nbevents; @@ -358,14 +395,15 @@ int run(int ind, phase_data_t *pdata, unsigned long *duration, for (i = 0; i < nbevents; i++) { if (!continue_running && !lock) - return; + return perf; log_debug("[%d] runs events %d type %d ", ind, i, events[i].type); if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] executing %d", ind, i); - lock += run_event(&events[i], !continue_running, &perf, duration, resources); + lock += run_event(&events[i], !continue_running, &perf, + resources, t_first, ldata); } return perf; @@ -396,10 +434,8 @@ shutdown(int sig) } if (opts.ftrace) { - log_notice("stopping ftrace"); log_ftrace(ft_data.marker_fd, "main ends\n"); - log_ftrace(ft_data.trace_fd, "0"); - close(ft_data.trace_fd); + log_notice("deconfiguring ftrace"); close(ft_data.marker_fd); } @@ -410,10 +446,11 @@ void *thread_body(void *arg) { thread_data_t *data = (thread_data_t*) arg; phase_data_t *pdata; + log_data_t ldata; struct sched_param param; - struct timespec t_start, t_end; + struct timespec t_start, t_end, t_first; unsigned long t_start_usec; - unsigned long perf, duration; + long slack; timing_point_t *curr_timing; timing_point_t *timings; timing_point_t tmp_timing; @@ -536,9 +573,27 @@ void *thread_body(void *arg) } } + if (data->ind == 0) { + /* + * Only first thread sets t_zero. Other threads sync with this + * timestamp. + */ + clock_gettime(CLOCK_MONOTONIC, &t_zero); + if (opts.ftrace) + log_ftrace(ft_data.marker_fd, + "[%d] sets zero time", + data->ind); + } + + pthread_barrier_wait(&threads_barrier); + t_first = t_zero; + log_notice("[%d] starting thread ...\n", data->ind); - fprintf(data->log_handler, "#idx\tperf\trun\tperiod\tstart\t\tend\t\trel_st\n"); + fprintf(data->log_handler, "%s %8s %8s %8s %15s %15s %15s %10s %10s %10s %10s\n", + "#idx", "perf", "run", "period", + "start", "end", "rel_st", "slack", + "c_duration", "c_period", "wu_lat"); if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] starts", data->ind); @@ -560,6 +615,16 @@ void *thread_body(void *arg) } } #endif + + if (data->delay > 0) { + struct timespec delay = usec_to_timespec(data->delay); + + log_debug("initial delay %d ", data->delay); + t_first = timespec_add(&t_first, &delay); + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t_first, + NULL); + } + i = j = loop = idx = 0; while (continue_running && (i != data->loop)) { @@ -569,9 +634,10 @@ void *thread_body(void *arg) log_ftrace(ft_data.marker_fd, "[%d] begins loop %d phase %d step %d", data->ind, i, j, loop); log_debug("[%d] begins loop %d phase %d step %d", data->ind, i, j, loop);; - duration = 0; + memset(&ldata, 0, sizeof(ldata)); clock_gettime(CLOCK_MONOTONIC, &t_start); - perf = run(data->ind, pdata, &duration, *(data->resources)); + ldata.perf = run(data->ind, pdata, *(data->resources), + &t_first, &ldata); clock_gettime(CLOCK_MONOTONIC, &t_end); if (timings) @@ -587,10 +653,14 @@ void *thread_body(void *arg) curr_timing->start_time = timespec_to_usec_ull(&t_start); curr_timing->end_time = timespec_to_usec_ull(&t_end); curr_timing->period = timespec_to_usec(&t_diff); - curr_timing->duration = duration; - curr_timing->perf = perf; - - if (opts.logsize && !timings) + curr_timing->duration = ldata.duration; + curr_timing->perf = ldata.perf; + curr_timing->wu_latency = ldata.wu_latency; + curr_timing->slack = ldata.slack; + curr_timing->c_period = ldata.c_period; + curr_timing->c_duration = ldata.c_duration; + + if (opts.logsize && !timings && continue_running) log_timing(data->log_handler, curr_timing); if (opts.ftrace) @@ -660,7 +730,7 @@ int main(int argc, char* argv[]) /* allocated threads */ nthreads = opts.nthreads; threads = malloc(nthreads * sizeof(pthread_t)); - running_threads = 0; + pthread_barrier_init(&threads_barrier, NULL, nthreads); /* install a signal handler for proper shutdown */ signal(SIGQUIT, shutdown); @@ -673,21 +743,14 @@ int main(int argc, char* argv[]) log_notice("configuring ftrace"); strcpy(tmp, ft_data.debugfs); strcat(tmp, "/tracing/tracing_on"); - ft_data.trace_fd = open(tmp, O_WRONLY); - if (ft_data.trace_fd < 0) { - log_error("Cannot open trace_fd file %s", tmp); - exit(EXIT_FAILURE); - } - strcpy(tmp, ft_data.debugfs); strcat(tmp, "/tracing/trace_marker"); ft_data.marker_fd = open(tmp, O_WRONLY); - if (ft_data.trace_fd < 0) { + if (ft_data.marker_fd < 0) { log_error("Cannot open trace_marker file %s", tmp); exit(EXIT_FAILURE); } - log_ftrace(ft_data.trace_fd, "1"); log_ftrace(ft_data.marker_fd, "main creates threads\n"); } @@ -877,10 +940,7 @@ int main(int argc, char* argv[]) } if (opts.ftrace) { - log_notice("stopping ftrace"); log_ftrace(ft_data.marker_fd, "main ends\n"); - log_ftrace(ft_data.trace_fd, "0"); - close(ft_data.trace_fd); close(ft_data.marker_fd); } exit(EXIT_SUCCESS); diff --git a/src/rt-app_args.h b/src/rt-app_args.h index 9bbde38..23ba50c 100644 --- a/src/rt-app_args.h +++ b/src/rt-app_args.h @@ -36,10 +36,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifdef DLSCHED #include "dl_syscalls.h" #endif - -#ifdef JSON #include "rt-app_parse_config.h" -#endif #define DEFAULT_THREAD_PRIORITY 10 #define PATH_LENGTH 256 diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index c59b562..2b27f64 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -181,6 +181,7 @@ static int init_timer_resource(rtapp_resource_t *data, const rtapp_options_t *op { log_info(PIN3 "Init: %s timer", data->name); data->res.timer.init = 0; + data->res.timer.relative = 1; } static int init_cond_resource(rtapp_resource_t *data, const rtapp_options_t *opts) @@ -489,6 +490,11 @@ parse_thread_event_data(char *name, struct json_object *obj, rdata = &(opts->resources[data->res]); ddata = &(opts->resources[data->dep]); + tmp = get_string_value_from(obj, "mode", TRUE, "relative"); + if (!strncmp(tmp, "absolute", strlen("absolute"))) + rdata->res.timer.relative = 0; + free(tmp); + log_info(PIN2 "type %d target %s [%d] period %d", data->type, rdata->name, rdata->index, data->duration); return; } @@ -689,6 +695,11 @@ parse_thread_data(char *name, struct json_object *obj, int index, } log_info(PIN "key: cpus %s", data->cpuset_str); + /* initial delay */ + data->delay = get_int_value_from(obj, "delay", TRUE, 0); + if (data->delay < 0) + data->delay = 0; + /* Get phases */ phases_obj = get_in_object(obj, "phases", TRUE); if (phases_obj) { @@ -773,6 +784,7 @@ parse_global(struct json_object *global, rtapp_options_t *opts) opts->pi_enabled = 0; opts->io_device = strdup("/dev/null"); opts->mem_buffer_size = DEFAULT_MEM_BUF_SIZE; + opts->cumulative_slack = 0; return; } @@ -861,6 +873,7 @@ parse_global(struct json_object *global, rtapp_options_t *opts) "/dev/null"); opts->mem_buffer_size = get_int_value_from(global, "mem_buffer_size", TRUE, DEFAULT_MEM_BUF_SIZE); + opts->cumulative_slack = get_bool_value_from(global, "cumulative_slack", TRUE, 0); } diff --git a/src/rt-app_parse_config.h b/src/rt-app_parse_config.h index 023cabd..9b0e5fa 100644 --- a/src/rt-app_parse_config.h +++ b/src/rt-app_parse_config.h @@ -45,5 +45,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. void parse_config(const char *filename, rtapp_options_t *opts); +void +parse_config_stdin(rtapp_options_t *opts); #endif // _RTAPP_PARSE_CONFIG_H diff --git a/src/rt-app_types.h b/src/rt-app_types.h index 57fb80d..1eb9467 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -87,6 +87,7 @@ struct _rtapp_signal { struct _rtapp_timer { struct timespec t_next; int init; + int relative; }; struct _rtapp_iomem_buf { @@ -149,6 +150,8 @@ typedef struct _thread_data_t { char sched_policy_descr[RTAPP_POLICY_DESCR_LENGTH]; int sched_prio; + unsigned long delay; + #ifdef DLSCHED struct sched_attr dl_params; #endif @@ -160,6 +163,15 @@ typedef struct _ftrace_data_t { int marker_fd; } ftrace_data_t; +typedef struct _log_data_t { + unsigned long perf; + unsigned long duration; + unsigned long wu_latency; + unsigned long c_duration; + unsigned long c_period; + long slack; +} log_data_t; + typedef struct _rtapp_options_t { int lock_pages; @@ -184,6 +196,8 @@ typedef struct _rtapp_options_t { int die_on_dmiss; int mem_buffer_size; char *io_device; + + int cumulative_slack; } rtapp_options_t; typedef struct _timing_point_t { @@ -191,6 +205,10 @@ typedef struct _timing_point_t { unsigned long perf; unsigned long duration; unsigned long period; + unsigned long c_duration; + unsigned long c_period; + unsigned long wu_latency; + long slack; __u64 start_time; __u64 end_time; __u64 rel_start_time; diff --git a/src/rt-app_utils.c b/src/rt-app_utils.c index c4840db..f12f48c 100644 --- a/src/rt-app_utils.c +++ b/src/rt-app_utils.c @@ -19,6 +19,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include <errno.h> +#include <string.h> #include "rt-app_utils.h" unsigned long @@ -33,6 +35,12 @@ timespec_to_usec_ull(struct timespec *ts) return llround((ts->tv_sec * 1E9 + ts->tv_nsec) / 1000.0); } +long +timespec_to_usec_long(struct timespec *ts) +{ + return round((ts->tv_sec * 1E9 + ts->tv_nsec) / 1000.0); +} + #ifdef DLSCHED __u64 timespec_to_nsec(struct timespec *ts) @@ -132,14 +140,18 @@ void log_timing(FILE *handler, timing_point_t *t) { fprintf(handler, - "%d\t%lu\t%lu\t%lu\t%llu\t%llu\t%llu", + "%4d %8lu %8lu %8lu %15llu %15llu %15llu %10ld %10lu %10lu %10lu", t->ind, t->perf, t->duration, t->period, t->start_time, t->end_time, - t->rel_start_time + t->rel_start_time, + t->slack, + t->c_duration, + t->c_period, + t->wu_latency ); fprintf(handler, "\n"); } @@ -253,7 +265,7 @@ resource_to_string(resource_t resource, char *resource_name) void ftrace_write(int mark_fd, const char *fmt, ...) { va_list ap; - int n, size = BUF_SIZE; + int n, size = BUF_SIZE, ret; char *tmp, *ntmp; if (mark_fd < 0) { @@ -274,8 +286,15 @@ void ftrace_write(int mark_fd, const char *fmt, ...) /* If it worked return success */ if (n > -1 && n < size) { - write(mark_fd, tmp, n); + ret = write(mark_fd, tmp, n); free(tmp); + if (ret < 0) { + log_error("Cannot write mark_fd: %s\n", + strerror(errno)); + exit(EXIT_FAILURE); + } else if (ret < n) { + log_debug("Cannot write all bytes at once into mark_fd\n"); + } return; } diff --git a/src/rt-app_utils.h b/src/rt-app_utils.h index 64f97f6..6a8d921 100644 --- a/src/rt-app_utils.h +++ b/src/rt-app_utils.h @@ -28,6 +28,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include <string.h> #include <stdarg.h> #include <stdlib.h> +#define _GNU_SOURCE +#include <unistd.h> +#include <sys/syscall.h> #include "rt-app_types.h" #ifndef LOG_PREFIX @@ -89,6 +92,9 @@ timespec_to_usec(struct timespec *ts); unsigned long long timespec_to_usec_ull(struct timespec *ts); +long +timespec_to_usec_long(struct timespec *ts); + struct timespec usec_to_timespec(unsigned long usec); |