#include "histogram.h"
+//#define FTRACE
+
#ifndef DEBUG
#define dbg(level, fmt, arg...) do {} while (0)
#else
FILE *file;
FILE *histogram;
int length;
+ int userhist;
};
struct options opt = {
.length = 2,
};
+struct {
+ unsigned enobufs;
+} stats;
+
int num_interfaces = 0;
int count = 0; /* Number of sent messages */
int completion_pipe[2];
{
struct timespec diff;
if (num_interfaces == 3)
- timespec_subtract(&diff, &mi->ts_rx_final_kern, &mi->ts_rx_onwire_kern);
+ if (opt.userhist)
+ timespec_subtract(&diff, &mi->ts_rx_final, &mi->ts_rx_onwire);
+ else
+ timespec_subtract(&diff, &mi->ts_rx_final_kern, &mi->ts_rx_onwire_kern);
else
- timespec_subtract(&diff, &mi->ts_rx_final_kern, &mi->ts_sent);
+ if (opt.userhist)
+ timespec_subtract(&diff, &mi->ts_rx_final, &mi->ts_sent);
+ else
+ timespec_subtract(&diff, &mi->ts_rx_final_kern, &mi->ts_sent);
return diff.tv_sec * 1000000 + diff.tv_nsec/1000;
}
static inline get_tstamp(struct timespec *ts)
{
- clock_gettime(CLOCK_MONOTONIC, ts);
+ clock_gettime(CLOCK_REALTIME, ts);
+}
+
+
+int trace_fd = -1;
+int marker_fd = -1;
+
+int init_ftrace()
+{
+#ifdef FTRACE
+ char *debugfs;
+ char path[256];
+ FILE *f;
+
+ debugfs = "/sys/kernel/debug";
+ if (debugfs) {
+ strcpy(path, debugfs);
+ strcat(path,"/tracing/tracing_on");
+ trace_fd = open(path, O_WRONLY);
+ if (trace_fd >= 0)
+ write(trace_fd, "1", 1);
+
+ strcpy(path, debugfs);
+ strcat(path,"/tracing/trace_marker");
+ marker_fd = open(path, O_WRONLY);
+
+ strcpy(path, debugfs);
+ strcat(path,"/tracing/set_ftrace_pid");
+ f = fopen(path, "w");
+ fprintf(f, "%d\n", getpid());
+ fclose(f);
+ system("echo function_graph > /sys/kernel/debug/tracing/current_tracer");
+ system("echo can_send > /sys/kernel/debug/tracing/set_graph_function");
+ system("echo > /sys/kernel/debug/tracing/trace");
+ system("echo 1 > /sys/kernel/debug/tracing/tracing_enabled");
+ }
+#endif /* FTRACE */
+}
+
+static inline void trace_on()
+{
+ if (trace_fd >= 0)
+ write(trace_fd, "1", 1);
+}
+
+static inline void trace_off(int ret)
+{
+ if (marker_fd >= 0) {
+ char marker[100];
+ sprintf(marker, "write returned %d\n", ret);
+ write(marker_fd, marker, strlen(marker));
+ }
+ if (trace_fd >= 0)
+ write(trace_fd, "0", 1);
+}
+
+void msg_info_free(struct msg_info *mi)
+{
+ mi->id = -1;
}
int send_frame(int socket)
MEMSET_ZERO(frame);
i = curr_msg+1;
- while (msg_infos[i].id != 0 && i != curr_msg) {
+ while (msg_infos[i].id != -1 && i != curr_msg) {
i++;
if (i >= MAX_INFOS)
i = 0;
mi->length = frame.can_dlc;
get_tstamp(&mi->ts_sent);
mi->sent = frame;
+
+ trace_on();
ret = write(socket, &frame, sizeof(frame));
- return ret;
-}
+ trace_off(ret);
-void msg_info_free(struct msg_info *mi)
-{
- mi->id = 0;
+ if (ret == -1)
+ msg_info_free(mi);
+ return ret;
}
static inline void get_next_timeout(struct timespec *timeout)
pfd[i].events = POLLIN;
}
- set_sched_policy_and_prio(SCHED_FIFO, 99);
-
-#define SEND() \
- do { \
- ret = send_frame(pfd[0].fd); \
- if (ret != sizeof(struct can_frame)) \
- error(1, errno, "send_frame (line %d)", __LINE__); \
- count++; \
- msg_in_progress++; \
+ set_sched_policy_and_prio(SCHED_FIFO, 40);
+
+#define SEND() \
+ do { \
+ ret = send_frame(pfd[0].fd); \
+ if (ret != sizeof(struct can_frame)) { \
+ if (ret == -1 && errno == ENOBUFS && opt.period_us == 0 && !opt.oneattime) { \
+ stats.enobufs++; \
+ /* Ignore this error - pfifo_fast qeuue is full */ \
+ } else \
+ error(1, errno, "send_frame (line %d)", __LINE__); \
+ } \
+ else { \
+ count++; \
+ msg_in_progress++; \
+ } \
} while (0)
if (opt.oneattime) {
{ "file", 'f', POPT_ARG_STRING, NULL, 'f', "File where to store results", "filename"},
{ "histogram", 'h', POPT_ARG_STRING, NULL, 'h', "Store histogram in file", "filename"},
{ "length", 'l', POPT_ARG_INT|POPT_ARGFLAG_SHOW_DEFAULT, &opt.length, 0, "The length of generated messages", "bytes"},
+ { "userhist", 'u', POPT_ARG_NONE, &opt.userhist, 0, "Generate histogram from userspace timestamps"},
POPT_AUTOHELP
{ NULL, 0, 0, NULL, 0 }
};
{
pthread_t thread;
sigset_t set;
- int ret;
+ int ret, i;
parse_options(argc, argv);
signal(SIGINT, term_handler);
signal(SIGTERM, term_handler);
+ for (i=0; i<MAX_INFOS; i++)
+ msg_infos[i].id = -1;
+
if (opt.histogram) {
histogram_init(&histogram, 5000000, 1);
}
ret = fcntl(completion_pipe[1], F_SETFL, O_NONBLOCK);
if (ret == -1)
error(1, errno, "pipe fcntl");
+
+ init_ftrace();
pthread_create(&thread, 0, measure_thread, NULL);