]> rtime.felk.cvut.cz Git - can-benchmark.git/blobdiff - latester/latester.c
Attempt to ignore ENOBUFS error
[can-benchmark.git] / latester / latester.c
index c94837c13f1cbc04428834b7c9b191b61dc93452..b3f20029becb8c67e55f9bf95183c7cd9491e8b7 100644 (file)
@@ -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 = {
@@ -87,14 +90,32 @@ struct msg_info msg_infos[MAX_INFOS];
 
 struct histogram histogram;
 
-int can_frame_sprintf(char *buf, struct can_frame *frame)
-{
-       char datastr[17];
-       int i;
-       for (i=0; i<8; i++)
-               sprintf(&datastr[i*2], "%02x", frame->data[i]);
-       sprintf(buf, "id=0x%x, len=%d, data=%s",
-               frame->can_id, frame->can_dlc, datastr);
+void sprint_canframe(char *buf , struct can_frame *cf, int sep) {
+       /* documentation see lib.h */
+
+       int i,offset;
+       int dlc = (cf->can_dlc > 8)? 8 : cf->can_dlc;
+
+       if (cf->can_id & CAN_ERR_FLAG) {
+               sprintf(buf, "%08X#", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
+               offset = 9;
+       } else if (cf->can_id & CAN_EFF_FLAG) {
+               sprintf(buf, "%08X#", cf->can_id & CAN_EFF_MASK);
+               offset = 9;
+       } else {
+               sprintf(buf, "%03X#", cf->can_id & CAN_SFF_MASK);
+               offset = 4;
+       }
+
+       if (cf->can_id & CAN_RTR_FLAG) /* there are no ERR frames with RTR */
+               sprintf(buf+offset, "R");
+       else
+               for (i = 0; i < dlc; i++) {
+                       sprintf(buf+offset, "%02X", cf->data[i]);
+                       offset += 2;
+                       if (sep && (i+1 < dlc))
+                               sprintf(buf+offset++, ".");
+               }
 }
 
 static inline struct msg_info *frame2info(struct can_frame *frame)
@@ -124,19 +145,19 @@ void msg_info_print(FILE *f, struct msg_info *mi)
        static long num = 0;
        char sent[64], received[64];
 
-       can_frame_sprintf(sent, &mi->sent);
-       can_frame_sprintf(received, &mi->received);
+       sprint_canframe(sent, &mi->sent, true);
+       sprint_canframe(received, &mi->received, true);
 
 #define S(ts) tstamp_str(local, &ts)
 #define DIFF(a, b) (timespec_subtract(&diff, &b, &a), S(diff))
 
        if (num_interfaces == 2)
-               fprintf(f, "%ld: %s [%s] -> %s (%s) [%s] = %s (%s)\n",
+               fprintf(f, "%ld: %s %s -> %s (%s) %s = %s (%s)\n",
                        num, S(mi->ts_sent), sent, S(mi->ts_rx_final_kern), S(mi->ts_rx_final), received,
                       DIFF(mi->ts_sent, mi->ts_rx_final_kern),
                       DIFF(mi->ts_sent, mi->ts_rx_final));
        else
-               fprintf(f, "%ld: %s [%s] -> %s (%s) -> %s (%s) [%s] = %s (%s), %s (%s)\n",
+               fprintf(f, "%ld: %s %s -> %s (%s) -> %s (%s) %s = %s (%s), %s (%s)\n",
                        num, S(mi->ts_sent), sent,
                        S(mi->ts_rx_onwire_kern), S(mi->ts_rx_onwire),
                        S(mi->ts_rx_final_kern), S(mi->ts_rx_final), received,
@@ -210,9 +231,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_kern, &mi->ts_rx_onwire_kern);
+               else
+                       timespec_subtract(&diff, &mi->ts_rx_final, &mi->ts_rx_onwire);
        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;
 }
 
@@ -250,7 +277,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)
@@ -264,7 +349,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;
@@ -286,13 +371,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)
@@ -448,13 +534,19 @@ void *measure_thread(void *arg)
 
        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++;                      \
+#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) { \
+                               /* 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) {
@@ -528,6 +620,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 }
 };
@@ -579,7 +672,7 @@ int main(int argc, const char *argv[])
 {
        pthread_t thread;
        sigset_t set;
-       int ret;
+       int ret, i;
 
        parse_options(argc, argv);
 
@@ -588,6 +681,9 @@ int main(int argc, const char *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);
        }
@@ -598,6 +694,8 @@ int main(int argc, const char *argv[])
        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);