summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rt-app.c140
-rw-r--r--src/rt-app_args.h3
-rw-r--r--src/rt-app_parse_config.c13
-rw-r--r--src/rt-app_parse_config.h2
-rw-r--r--src/rt-app_types.h18
-rw-r--r--src/rt-app_utils.c27
-rw-r--r--src/rt-app_utils.h6
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);