X-Git-Url: http://rtime.felk.cvut.cz/gitweb/can-benchmark.git/blobdiff_plain/5748270012688e3342a7667000ee48eecd192a15..3ea7fae8477eb1f8a65e07a2e5f8c139110a2a81:/latester/latester.c diff --git a/latester/latester.c b/latester/latester.c index f3ba4c6..61b2b43 100644 --- a/latester/latester.c +++ b/latester/latester.c @@ -59,10 +59,15 @@ struct options { unsigned timeout_ms; unsigned count; unsigned oneattime; - FILE *file; - FILE *histogram; + char *name; int length; int userhist; + int quiet; + + /* Temporary variables */ + FILE *f_msgs; + FILE *f_hist; + FILE *f_stat; }; struct options opt = { @@ -76,6 +81,9 @@ struct { unsigned enobufs; unsigned overrun; unsigned lost; + struct timespec tic, tac; + unsigned timeouts; + unsigned invalid_frame; } stats; int num_interfaces = 0; @@ -125,7 +133,7 @@ void sprint_canframe(char *buf , struct can_frame *cf, int sep) { } } -static inline struct msg_info *frame2info(struct can_frame *frame) +static inline uint16_t frame_index(struct can_frame *frame) { uint16_t idx; if (frame->can_dlc >= 2) { @@ -136,7 +144,12 @@ static inline struct msg_info *frame2info(struct can_frame *frame) error(1, 0, "%s error", __FUNCTION__); } - return &msg_infos[idx]; + return idx; +} + +static inline struct msg_info *frame2info(struct can_frame *frame) +{ + return &msg_infos[frame_index(frame)]; } static inline char *tstamp_str(const void *ctx, struct timespec *tstamp) @@ -158,12 +171,14 @@ void msg_info_print(FILE *f, struct msg_info *mi) #define S(ts) tstamp_str(local, &ts) #define DIFF(a, b) (timespec_subtract(&diff, &b, &a), S(diff)) - if (num_interfaces == 2) + switch (num_interfaces) { + case 2: 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 + break; + case 3: 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), @@ -172,35 +187,14 @@ void msg_info_print(FILE *f, struct msg_info *mi) DIFF(mi->ts_sent, mi->ts_rx_onwire), DIFF(mi->ts_rx_onwire_kern, mi->ts_rx_final_kern), DIFF(mi->ts_rx_onwire, mi->ts_rx_final)); + break; + } #undef S #undef DIFF num++; talloc_free (local); } -int msg_info_store(FILE *f, struct msg_info *mi) -{ - struct timespec diff; - void *local = talloc_new (NULL); - static long num = 0; - -#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 %d %d %s\n", - num, mi->id, mi->length, - DIFF(mi->ts_sent, mi->ts_rx_final_kern)); - else - fprintf(f, "%ld %d %d %s\n", - num, mi->id, mi->length, - DIFF(mi->ts_rx_onwire_kern, mi->ts_rx_final_kern)); -#undef S -#undef DIFF - talloc_free (local); -} - - /* Subtract the `struct timespec' values X and Y, storing the result in RESULT. Return 1 if the difference is negative, otherwise 0. */ @@ -237,16 +231,22 @@ void dbg_print_timespec(char *msg, struct timespec *tv) static inline unsigned get_msg_latency_us(struct msg_info *mi) { struct timespec diff; - if (num_interfaces == 3) + switch (num_interfaces) { + case 3: 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 + break; + case 2: 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); + break; + default: + return 0; + } return diff.tv_sec * 1000000 + diff.tv_nsec/1000; } @@ -340,11 +340,16 @@ static inline void trace_off(int ret) write(trace_fd, "0", 1); } -void msg_info_free(struct msg_info *mi) +static inline void msg_info_free(struct msg_info *mi) { mi->id = -1; } +static inline bool msg_info_used(struct msg_info *mi) +{ + return mi->id != -1; +} + int send_frame(int socket) { struct can_frame frame; @@ -356,7 +361,7 @@ int send_frame(int socket) MEMSET_ZERO(frame); i = curr_msg+1; - while (msg_infos[i].id != -1 && i != curr_msg) { + while (msg_info_used(&msg_infos[i]) && i != curr_msg) { i++; if (i >= MAX_INFOS) i = 0; @@ -383,7 +388,7 @@ int send_frame(int socket) ret = write(socket, &frame, sizeof(frame)); trace_off(ret); - if (ret == -1) + if (ret == -1 || num_interfaces == 1) msg_info_free(mi); return ret; } @@ -485,8 +490,11 @@ void process_on_wire_rx(int s) struct msg_info *mi; receive(s, &frame, &ts_kern, &ts_user); mi = frame2info(&frame); - mi->ts_rx_onwire_kern = ts_kern; - mi->ts_rx_onwire = ts_user; + if (msg_info_used(mi)) { + mi->ts_rx_onwire_kern = ts_kern; + mi->ts_rx_onwire = ts_user; + } else + stats.invalid_frame++; } @@ -503,8 +511,7 @@ void process_final_rx(int s) mi->ts_rx_final = ts_user; mi->received = frame; - if (opt.histogram) - histogram_add(&histogram, get_msg_latency_us(mi)); + histogram_add(&histogram, get_msg_latency_us(mi)); ret = write(completion_pipe[1], &mi, sizeof(mi)); if (ret == -1) @@ -518,6 +525,7 @@ void *measure_thread(void *arg) struct timespec timeout; struct sockaddr_can addr; sigset_t set; + int consecutive_timeouts = 0; MEMSET_ZERO(pfd); @@ -564,6 +572,8 @@ void *measure_thread(void *arg) if (opt.oneattime) SEND(); + get_tstamp(&stats.tic); + while (!finish_flag && (opt.count == 0 || count < opt.count || msg_in_progress != 0)) { @@ -582,7 +592,13 @@ void *measure_thread(void *arg) SEND(); } } else { - error(1, 0, "poll timeout"); + /* Lost message - send a new one */ + stats.timeouts++; + consecutive_timeouts++; + if (consecutive_timeouts < 10) + SEND(); + else /* Something is really broken */ + finish_flag = 1; } break; default: // Event @@ -595,13 +611,16 @@ void *measure_thread(void *arg) } pfd[0].revents = 0; - if (num_interfaces == 3 && pfd[1].revents != 0) { + if (num_interfaces == 3 && pfd[1].revents & POLLIN) { process_on_wire_rx(pfd[1].fd); pfd[1].revents = 0; } + if (num_interfaces == 3 && pfd[1].revents & ~POLLIN) + error(1, 0, "Unexpected pfd[1].revents: 0x%04x\n", pfd[1].revents); i = (num_interfaces == 2) ? 1 : 2; - if (pfd[i].revents != 0) { + if (pfd[i].revents & POLLIN) { + consecutive_timeouts = 0; process_final_rx(pfd[i].fd); msg_in_progress--; pfd[i].revents = 0; @@ -610,9 +629,13 @@ void *measure_thread(void *arg) SEND(); } } + if (pfd[i].revents & ~POLLIN) + error(1, 0, "Unexpected pfd[%d].revents: 0x%04x\n", pfd[i].revents); } } + get_tstamp(&stats.tac); + for (i=0; i"); @@ -649,16 +673,6 @@ int parse_options(int argc, const char *argv[]) case 'd': num_interfaces++; break; - case 'f': - opt.file = fopen(poptGetOptArg(optCon), "w"); - if (!opt.file) - error(1, errno, "fopen: %s", poptGetOptArg(optCon)); - break; - case 'h': - opt.histogram = fopen(poptGetOptArg(optCon), "w"); - if (!opt.histogram) - error(1, errno, "fopen: %s", poptGetOptArg(optCon)); - break; } } if (c < -1) @@ -666,21 +680,47 @@ int parse_options(int argc, const char *argv[]) poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(c)); - if (num_interfaces < 2 || num_interfaces > 3) - error(1, 0, "-d option must be given exactly 2 or 3 times"); + if (num_interfaces < 1 || num_interfaces > 3) + error(1, 0, "-d option must only be given one, two or three times"); if (opt.oneattime && opt.period_us) error(1, 0, "oneattime and period cannot be specified at the same time"); - poptFreeContext(optCon); + if (opt.name) { + char *f = talloc_asprintf(local, "%s-msgs.txt", opt.name); + opt.f_msgs = fopen(f, "w"); + if (!opt.f_msgs) + error(1, errno, "fopen: %s", f); + } + + if (opt.name) { + char *f = talloc_asprintf(local, "%s-hist.txt", opt.name); + opt.f_hist = fopen(f, "w"); + if (!opt.f_hist) + error(1, errno, "fopen: %s", f); + } + if (opt.name) { + char *f = talloc_asprintf(local, "%s-stat.txt", opt.name); + opt.f_stat = fopen(f, "w"); + if (!opt.f_stat) + error(1, errno, "fopen: %s", f); + } + + poptFreeContext(optCon); + talloc_free(local); return 0; } void print_progress() { - printf("\rSent %5d, in progress %5d", count, msg_in_progress); - fflush(stdout); + if (! opt.quiet) { + if (num_interfaces > 1) + printf("\rSent %5d, in progress %5d", count, msg_in_progress); + else + printf("\rSent %5d", count); + fflush(stdout); + } } int main(int argc, const char *argv[]) @@ -699,9 +739,7 @@ int main(int argc, const char *argv[]) for (i=0; i= opt.count) { if (allsent.tv_sec == 0) allsent = now; - if (now.tv_sec - allsent.tv_sec >= 2) + timespec_subtract(&diff, &now, &allsent); + if (diff.tv_sec >= 1) finish_flag = 1; } } print_progress(); - printf("\n"); + if (!opt.quiet) + printf("\n"); stats.lost = msg_in_progress; @@ -762,19 +801,37 @@ int main(int argc, const char *argv[]) close(completion_pipe[0]); close(completion_pipe[1]); - if (opt.histogram) { - histogram_fprint(&histogram, opt.histogram); - fclose(opt.histogram); - } - if (opt.file) - fclose(opt.file); + histogram_fprint(&histogram, opt.f_hist); + fclose(opt.f_hist); + fclose(opt.f_msgs); + + + fprintf(opt.f_stat, "cmdline='"); + for (i=0; i