X-Git-Url: http://rtime.felk.cvut.cz/gitweb/can-benchmark.git/blobdiff_plain/3406f77a4d776d415515ad718c7b44482db075b3..cf9bd660b3c10cff6e81af6fb4e42d3569229514:/latester/latester.c diff --git a/latester/latester.c b/latester/latester.c index 85288f7..c980f24 100644 --- a/latester/latester.c +++ b/latester/latester.c @@ -35,6 +35,8 @@ #include "histogram.h" +//#define FTRACE + #ifndef DEBUG #define dbg(level, fmt, arg...) do {} while (0) #else @@ -60,6 +62,7 @@ struct options { FILE *file; FILE *histogram; int length; + int userhist; }; struct options opt = { @@ -69,6 +72,11 @@ struct options opt = { .length = 2, }; +struct { + unsigned enobufs; + unsigned overrun; +} stats; + int num_interfaces = 0; int count = 0; /* Number of sent messages */ int completion_pipe[2]; @@ -228,9 +236,15 @@ static inline unsigned get_msg_latency_us(struct msg_info *mi) { 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; } @@ -268,7 +282,65 @@ static inline int sock_get_if_index(int s, const char *if_name) 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) @@ -282,7 +354,7 @@ 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; @@ -304,13 +376,14 @@ int send_frame(int socket) 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) @@ -329,7 +402,10 @@ static inline void get_next_timeout(struct timespec *timeout) last.tv_nsec -= 1000000000; last.tv_sec++; } - timespec_subtract(timeout, &last, &now); + if (timespec_subtract(timeout, &last, &now) /* is negative */) { + stats.overrun++; + memset(timeout, 0, sizeof(*timeout)); + } } else if (opt.timeout_ms != 0) { timeout->tv_sec = opt.timeout_ms/1000; timeout->tv_nsec = (opt.timeout_ms%1000)*1000000; @@ -464,15 +540,22 @@ void *measure_thread(void *arg) 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) { @@ -546,6 +629,7 @@ struct poptOption optionsTable[] = { { "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 } }; @@ -597,7 +681,7 @@ int main(int argc, const char *argv[]) { pthread_t thread; sigset_t set; - int ret; + int ret, i; parse_options(argc, argv); @@ -606,6 +690,9 @@ int main(int argc, const char *argv[]) signal(SIGINT, term_handler); signal(SIGTERM, term_handler); + for (i=0; i