From cde81d76400a5eaed1e7986fc5df62b420122aeb Mon Sep 17 00:00:00 2001 From: Ben Fox-Moore Date: Wed, 16 May 2018 23:49:45 +0200 Subject: [PATCH] Add initial portable time abstraction --- configure | 69 ++++++++++++++++++ configure.ac | 4 ++ src/Makefile.am | 2 + src/Makefile.in | 38 ++++++++-- src/iperf.h | 11 +-- src/iperf_api.c | 80 ++++++++++++--------- src/iperf_api.h | 3 +- src/iperf_client_api.c | 23 +++--- src/iperf_config.h.in | 3 + src/iperf_server_api.c | 23 +++--- src/iperf_time.c | 156 +++++++++++++++++++++++++++++++++++++++++ src/iperf_time.h | 49 +++++++++++++ src/iperf_udp.c | 27 +++---- src/iperf_util.c | 13 ++-- src/t_timer.c | 9 +-- src/timer.c | 68 +++++++----------- src/timer.h | 17 ++--- 17 files changed, 455 insertions(+), 140 deletions(-) create mode 100644 src/iperf_time.c create mode 100644 src/iperf_time.h diff --git a/configure b/configure index 1250a4240..591446692 100755 --- a/configure +++ b/configure @@ -13090,6 +13090,75 @@ $as_echo "#define HAVE_SO_MAX_PACING_RATE 1" >>confdefs.h fi +# Check if we need -lrt for clock_gettime +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt posix4; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_clock_gettime=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_clock_gettime+:} false; then : + break +fi +done +if ${ac_cv_search_clock_gettime+:} false; then : + +else + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +# Check for clock_gettime support +for ac_func in clock_gettime +do : + ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" +if test "x$ac_cv_func_clock_gettime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CLOCK_GETTIME 1 +_ACEOF + +fi +done + ac_config_files="$ac_config_files Makefile src/Makefile src/version.h examples/Makefile iperf3.spec" diff --git a/configure.ac b/configure.ac index 800b6a60c..428ed30d0 100644 --- a/configure.ac +++ b/configure.ac @@ -182,5 +182,9 @@ if test "x$iperf3_cv_header_so_max_pacing_rate" = "xyes"; then AC_DEFINE([HAVE_SO_MAX_PACING_RATE], [1], [Have SO_MAX_PACING_RATE sockopt.]) fi +# Check if we need -lrt for clock_gettime +AC_SEARCH_LIBS(clock_gettime, [rt posix4]) +# Check for clock_gettime support +AC_CHECK_FUNCS([clock_gettime]) AC_OUTPUT([Makefile src/Makefile src/version.h examples/Makefile iperf3.spec]) diff --git a/src/Makefile.am b/src/Makefile.am index 9184e84a5..32a7b435d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,6 +27,8 @@ libiperf_la_SOURCES = \ iperf_sctp.h \ iperf_util.c \ iperf_util.h \ + iperf_time.c \ + iperf_time.h \ dscp.c \ net.c \ net.h \ diff --git a/src/Makefile.in b/src/Makefile.in index 13e9d3d60..a26b94e78 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -142,7 +142,8 @@ libiperf_la_LIBADD = am_libiperf_la_OBJECTS = cjson.lo iperf_api.lo iperf_error.lo \ iperf_auth.lo iperf_client_api.lo iperf_locale.lo \ iperf_server_api.lo iperf_tcp.lo iperf_udp.lo iperf_sctp.lo \ - iperf_util.lo dscp.lo net.lo tcp_info.lo timer.lo units.lo + iperf_util.lo iperf_time.lo dscp.lo net.lo tcp_info.lo \ + timer.lo units.lo libiperf_la_OBJECTS = $(am_libiperf_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -165,6 +166,7 @@ am__objects_1 = iperf3_profile-cjson.$(OBJEXT) \ iperf3_profile-iperf_udp.$(OBJEXT) \ iperf3_profile-iperf_sctp.$(OBJEXT) \ iperf3_profile-iperf_util.$(OBJEXT) \ + iperf3_profile-iperf_time.$(OBJEXT) \ iperf3_profile-dscp.$(OBJEXT) iperf3_profile-net.$(OBJEXT) \ iperf3_profile-tcp_info.$(OBJEXT) \ iperf3_profile-timer.$(OBJEXT) iperf3_profile-units.$(OBJEXT) @@ -220,6 +222,7 @@ am__depfiles_remade = ./$(DEPDIR)/cjson.Plo ./$(DEPDIR)/dscp.Plo \ ./$(DEPDIR)/iperf3_profile-iperf_sctp.Po \ ./$(DEPDIR)/iperf3_profile-iperf_server_api.Po \ ./$(DEPDIR)/iperf3_profile-iperf_tcp.Po \ + ./$(DEPDIR)/iperf3_profile-iperf_time.Po \ ./$(DEPDIR)/iperf3_profile-iperf_udp.Po \ ./$(DEPDIR)/iperf3_profile-iperf_util.Po \ ./$(DEPDIR)/iperf3_profile-main.Po \ @@ -230,11 +233,12 @@ am__depfiles_remade = ./$(DEPDIR)/cjson.Plo ./$(DEPDIR)/dscp.Plo \ ./$(DEPDIR)/iperf_auth.Plo ./$(DEPDIR)/iperf_client_api.Plo \ ./$(DEPDIR)/iperf_error.Plo ./$(DEPDIR)/iperf_locale.Plo \ ./$(DEPDIR)/iperf_sctp.Plo ./$(DEPDIR)/iperf_server_api.Plo \ - ./$(DEPDIR)/iperf_tcp.Plo ./$(DEPDIR)/iperf_udp.Plo \ - ./$(DEPDIR)/iperf_util.Plo ./$(DEPDIR)/net.Plo \ - ./$(DEPDIR)/t_timer-t_timer.Po ./$(DEPDIR)/t_units-t_units.Po \ - ./$(DEPDIR)/t_uuid-t_uuid.Po ./$(DEPDIR)/tcp_info.Plo \ - ./$(DEPDIR)/timer.Plo ./$(DEPDIR)/units.Plo + ./$(DEPDIR)/iperf_tcp.Plo ./$(DEPDIR)/iperf_time.Plo \ + ./$(DEPDIR)/iperf_udp.Plo ./$(DEPDIR)/iperf_util.Plo \ + ./$(DEPDIR)/net.Plo ./$(DEPDIR)/t_timer-t_timer.Po \ + ./$(DEPDIR)/t_units-t_units.Po ./$(DEPDIR)/t_uuid-t_uuid.Po \ + ./$(DEPDIR)/tcp_info.Plo ./$(DEPDIR)/timer.Plo \ + ./$(DEPDIR)/units.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -619,6 +623,8 @@ libiperf_la_SOURCES = \ iperf_sctp.h \ iperf_util.c \ iperf_util.h \ + iperf_time.c \ + iperf_time.h \ dscp.c \ net.c \ net.h \ @@ -848,6 +854,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_sctp.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_server_api.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_tcp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_time.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_udp.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_util.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-main.Po@am__quote@ # am--include-marker @@ -863,6 +870,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_sctp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_server_api.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_tcp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_time.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_udp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_util.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Plo@am__quote@ # am--include-marker @@ -1082,6 +1090,20 @@ iperf3_profile-iperf_util.obj: iperf_util.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_util.obj `if test -f 'iperf_util.c'; then $(CYGPATH_W) 'iperf_util.c'; else $(CYGPATH_W) '$(srcdir)/iperf_util.c'; fi` +iperf3_profile-iperf_time.o: iperf_time.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_time.o -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_time.Tpo -c -o iperf3_profile-iperf_time.o `test -f 'iperf_time.c' || echo '$(srcdir)/'`iperf_time.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_time.Tpo $(DEPDIR)/iperf3_profile-iperf_time.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iperf_time.c' object='iperf3_profile-iperf_time.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_time.o `test -f 'iperf_time.c' || echo '$(srcdir)/'`iperf_time.c + +iperf3_profile-iperf_time.obj: iperf_time.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_time.obj -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_time.Tpo -c -o iperf3_profile-iperf_time.obj `if test -f 'iperf_time.c'; then $(CYGPATH_W) 'iperf_time.c'; else $(CYGPATH_W) '$(srcdir)/iperf_time.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_time.Tpo $(DEPDIR)/iperf3_profile-iperf_time.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iperf_time.c' object='iperf3_profile-iperf_time.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_time.obj `if test -f 'iperf_time.c'; then $(CYGPATH_W) 'iperf_time.c'; else $(CYGPATH_W) '$(srcdir)/iperf_time.c'; fi` + iperf3_profile-dscp.o: dscp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-dscp.o -MD -MP -MF $(DEPDIR)/iperf3_profile-dscp.Tpo -c -o iperf3_profile-dscp.o `test -f 'dscp.c' || echo '$(srcdir)/'`dscp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-dscp.Tpo $(DEPDIR)/iperf3_profile-dscp.Po @@ -1632,6 +1654,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/iperf3_profile-iperf_sctp.Po -rm -f ./$(DEPDIR)/iperf3_profile-iperf_server_api.Po -rm -f ./$(DEPDIR)/iperf3_profile-iperf_tcp.Po + -rm -f ./$(DEPDIR)/iperf3_profile-iperf_time.Po -rm -f ./$(DEPDIR)/iperf3_profile-iperf_udp.Po -rm -f ./$(DEPDIR)/iperf3_profile-iperf_util.Po -rm -f ./$(DEPDIR)/iperf3_profile-main.Po @@ -1647,6 +1670,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/iperf_sctp.Plo -rm -f ./$(DEPDIR)/iperf_server_api.Plo -rm -f ./$(DEPDIR)/iperf_tcp.Plo + -rm -f ./$(DEPDIR)/iperf_time.Plo -rm -f ./$(DEPDIR)/iperf_udp.Plo -rm -f ./$(DEPDIR)/iperf_util.Plo -rm -f ./$(DEPDIR)/net.Plo @@ -1714,6 +1738,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/iperf3_profile-iperf_sctp.Po -rm -f ./$(DEPDIR)/iperf3_profile-iperf_server_api.Po -rm -f ./$(DEPDIR)/iperf3_profile-iperf_tcp.Po + -rm -f ./$(DEPDIR)/iperf3_profile-iperf_time.Po -rm -f ./$(DEPDIR)/iperf3_profile-iperf_udp.Po -rm -f ./$(DEPDIR)/iperf3_profile-iperf_util.Po -rm -f ./$(DEPDIR)/iperf3_profile-main.Po @@ -1729,6 +1754,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/iperf_sctp.Plo -rm -f ./$(DEPDIR)/iperf_server_api.Plo -rm -f ./$(DEPDIR)/iperf_tcp.Plo + -rm -f ./$(DEPDIR)/iperf_time.Plo -rm -f ./$(DEPDIR)/iperf_udp.Plo -rm -f ./$(DEPDIR)/iperf_util.Plo -rm -f ./$(DEPDIR)/net.Plo diff --git a/src/iperf.h b/src/iperf.h index 5c361235d..26e4f4f5f 100755 --- a/src/iperf.h +++ b/src/iperf.h @@ -61,6 +61,7 @@ #include "timer.h" #include "queue.h" #include "cjson.h" +#include "iperf_time.h" #if defined(HAVE_SSL) #include @@ -72,8 +73,8 @@ typedef uint64_t iperf_size_t; struct iperf_interval_results { iperf_size_t bytes_transferred; /* bytes transfered in this interval */ - struct timeval interval_start_time; - struct timeval interval_end_time; + struct iperf_time interval_start_time; + struct iperf_time interval_end_time; float interval_duration; /* for UDP */ @@ -119,9 +120,9 @@ struct iperf_stream_result int stream_sum_rtt; int stream_count_rtt; int stream_max_snd_cwnd; - struct timeval start_time; - struct timeval end_time; - struct timeval start_time_fixed; + struct iperf_time start_time; + struct iperf_time end_time; + struct iperf_time start_time_fixed; double sender_time; double receiver_time; TAILQ_HEAD(irlisthead, iperf_interval_results) interval_results; diff --git a/src/iperf_api.c b/src/iperf_api.c index 9af71c379..1046526ab 100755 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -1246,14 +1246,16 @@ iperf_set_send_state(struct iperf_test *test, signed char state) } void -iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP) +iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP) { + struct iperf_time temp_time; double seconds; uint64_t bits_per_second; if (sp->test->done) return; - seconds = timeval_diff(&sp->result->start_time_fixed, nowP); + iperf_time_diff(&sp->result->start_time_fixed, nowP, &temp_time); + seconds = iperf_time_in_secs(&temp_time); bits_per_second = sp->result->bytes_sent * 8 / seconds; if (bits_per_second < sp->test->settings->rate) { sp->green_light = 1; @@ -1269,7 +1271,7 @@ iperf_send(struct iperf_test *test, fd_set *write_setP) { register int multisend, r, streams_active; register struct iperf_stream *sp; - struct timeval now; + struct iperf_time now; /* Can we do multisend mode? */ if (test->settings->burst != 0) @@ -1281,7 +1283,7 @@ iperf_send(struct iperf_test *test, fd_set *write_setP) for (; multisend > 0; --multisend) { if (test->settings->rate != 0 && test->settings->burst == 0) - gettimeofday(&now, NULL); + iperf_time_now(&now); streams_active = 0; SLIST_FOREACH(sp, &test->streams, streams) { if ((sp->green_light && @@ -1307,7 +1309,7 @@ iperf_send(struct iperf_test *test, fd_set *write_setP) break; } if (test->settings->burst != 0) { - gettimeofday(&now, NULL); + iperf_time_now(&now); SLIST_FOREACH(sp, &test->streams, streams) iperf_check_throttle(sp, &now); } @@ -1343,7 +1345,7 @@ iperf_recv(struct iperf_test *test, fd_set *read_setP) int iperf_init_test(struct iperf_test *test) { - struct timeval now; + struct iperf_time now; struct iperf_stream *sp; if (test->protocol->init) { @@ -1352,7 +1354,7 @@ iperf_init_test(struct iperf_test *test) } /* Init each stream. */ - if (gettimeofday(&now, NULL) < 0) { + if (iperf_time_now(&now) < 0) { i_errno = IEINITTEST; return -1; } @@ -1367,7 +1369,7 @@ iperf_init_test(struct iperf_test *test) } static void -send_timer_proc(TimerClientData client_data, struct timeval *nowP) +send_timer_proc(TimerClientData client_data, struct iperf_time *nowP) { struct iperf_stream *sp = client_data.p; @@ -1381,11 +1383,11 @@ send_timer_proc(TimerClientData client_data, struct timeval *nowP) int iperf_create_send_timers(struct iperf_test * test) { - struct timeval now; + struct iperf_time now; struct iperf_stream *sp; TimerClientData cd; - if (gettimeofday(&now, NULL) < 0) { + if (iperf_time_now(&now) < 0) { i_errno = IEINITTEST; return -1; } @@ -1393,7 +1395,7 @@ iperf_create_send_timers(struct iperf_test * test) sp->green_light = 1; if (test->settings->rate != 0) { cd.p = sp; - sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, test->settings->pacing_timer, 1); + sp->send_timer = tmr_create(NULL, send_timer_proc, cd, test->settings->pacing_timer, 1); if (sp->send_timer == NULL) { i_errno = IEINITTEST; return -1; @@ -1689,6 +1691,7 @@ send_results(struct iperf_test *test) int sender_has_retransmits; iperf_size_t bytes_transferred; int retransmits; + struct iperf_time temp_time; double start_time, end_time; j = cJSON_CreateObject(); @@ -1758,8 +1761,10 @@ send_results(struct iperf_test *test) cJSON_AddNumberToObject(j_stream, "errors", sp->cnt_error); cJSON_AddNumberToObject(j_stream, "packets", sp->packet_count); - start_time = timeval_diff(&sp->result->start_time, &sp->result->start_time); - end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time); + iperf_time_diff(&sp->result->start_time, &sp->result->start_time, &temp_time); + start_time = iperf_time_in_secs(&temp_time); + iperf_time_diff(&sp->result->start_time, &sp->result->end_time, &temp_time); + end_time = iperf_time_in_secs(&temp_time); cJSON_AddNumberToObject(j_stream, "start_time", start_time); cJSON_AddNumberToObject(j_stream, "end_time", end_time); @@ -2430,13 +2435,13 @@ iperf_reset_test(struct iperf_test *test) void iperf_reset_stats(struct iperf_test *test) { - struct timeval now; + struct iperf_time now; struct iperf_stream *sp; struct iperf_stream_result *rp; test->bytes_sent = 0; test->blocks_sent = 0; - gettimeofday(&now, NULL); + iperf_time_now(&now); SLIST_FOREACH(sp, &test->streams, streams) { sp->omitted_packet_count = sp->packet_count; sp->omitted_cnt_error = sp->cnt_error; @@ -2469,6 +2474,7 @@ iperf_stats_callback(struct iperf_test *test) struct iperf_stream *sp; struct iperf_stream_result *rp = NULL; struct iperf_interval_results *irp, temp; + struct iperf_time temp_time; temp.omitted = test->omitting; SLIST_FOREACH(sp, &test->streams, streams) { @@ -2479,14 +2485,14 @@ iperf_stats_callback(struct iperf_test *test) irp = TAILQ_LAST(&rp->interval_results, irlisthead); /* result->end_time contains timestamp of previous interval */ if ( irp != NULL ) /* not the 1st interval */ - memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct timeval)); + memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct iperf_time)); else /* or use timestamp from beginning */ - memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct timeval)); + memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct iperf_time)); /* now save time of end of this interval */ - gettimeofday(&rp->end_time, NULL); - memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct timeval)); - temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); - //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); + iperf_time_now(&rp->end_time); + memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct iperf_time)); + iperf_time_diff(&temp.interval_start_time, &temp.interval_end_time, &temp_time); + temp.interval_duration = iperf_time_in_secs(&temp_time); if (test->protocol->id == Ptcp) { if ( has_tcpinfo()) { save_tcpinfo(sp, &temp); @@ -2553,6 +2559,7 @@ iperf_print_intermediate(struct iperf_test *test) double bandwidth; int retransmits = 0; double start_time, end_time; + struct iperf_time temp_time; cJSON *json_interval; cJSON *json_interval_streams; int total_packets = 0, lost_packets = 0; @@ -2575,8 +2582,8 @@ iperf_print_intermediate(struct iperf_test *test) SLIST_FOREACH(sp, &test->streams, streams) { irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); if (irp) { - double interval_len = timeval_diff(&irp->interval_start_time, - &irp->interval_end_time); + iperf_time_diff(&irp->interval_start_time, &irp->interval_end_time, &temp_time); + double interval_len = iperf_time_in_secs(&temp_time); if (test->debug) { printf("interval_len %f bytes_transferred %" PRIu64 "\n", interval_len, irp->bytes_transferred); } @@ -2641,14 +2648,16 @@ iperf_print_intermediate(struct iperf_test *test) sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */ /* Only do this of course if there was a first stream */ if (sp) { - irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* use 1st stream for timing info */ + irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* use 1st stream for timing info */ - unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A'); - bandwidth = (double) bytes / (double) irp->interval_duration; - unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); + unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A'); + bandwidth = (double) bytes / (double) irp->interval_duration; + unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); - start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time); - end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time); + iperf_time_diff(&sp->result->start_time,&irp->interval_start_time, &temp_time); + start_time = iperf_time_in_secs(&temp_time); + iperf_time_diff(&sp->result->start_time,&irp->interval_end_time, &temp_time); + end_time = iperf_time_in_secs(&temp_time); if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { if (test->sender && test->sender_has_retransmits) { /* Interval sum, TCP with retransmits. */ @@ -2710,6 +2719,7 @@ iperf_print_results(struct iperf_test *test) iperf_size_t bytes_received, total_received = 0; double start_time, end_time = 0.0, avg_jitter = 0.0, lost_percent = 0.0; double sender_time = 0.0, receiver_time = 0.0; + struct iperf_time temp_time; double bandwidth; /* print final summary for all intervals */ @@ -2747,7 +2757,8 @@ iperf_print_results(struct iperf_test *test) * basically emulating what iperf 3.1 did. */ if (sp) { - end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time); + iperf_time_diff(&sp->result->start_time, &sp->result->end_time, &temp_time); + end_time = iperf_time_in_secs(&temp_time); if (test->sender) { sp->result->sender_time = end_time; if (sp->result->receiver_time == 0.0) { @@ -3142,6 +3153,7 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON * char nbuf[UNIT_LEN]; char cbuf[UNIT_LEN]; double st = 0., et = 0.; + struct iperf_time temp_time; struct iperf_interval_results *irp = NULL; double bandwidth, lost_percent; @@ -3157,7 +3169,7 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON * ** else if there's more than one stream, print the separator; ** else nothing. */ - if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) { + if (iperf_time_compare(&sp->result->start_time, &irp->interval_start_time) == 0) { if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { if (test->sender && test->sender_has_retransmits) iperf_printf(test, "%s", report_bw_retrans_cwnd_header); @@ -3183,8 +3195,10 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON * } unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); - st = timeval_diff(&sp->result->start_time, &irp->interval_start_time); - et = timeval_diff(&sp->result->start_time, &irp->interval_end_time); + iperf_time_diff(&sp->result->start_time, &irp->interval_start_time, &temp_time); + st = iperf_time_in_secs(&temp_time); + iperf_time_diff(&sp->result->start_time, &irp->interval_end_time, &temp_time); + et = iperf_time_in_secs(&temp_time); if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { if (test->sender && test->sender_has_retransmits) { diff --git a/src/iperf_api.h b/src/iperf_api.h index 53012c062..f0818bda1 100755 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -42,6 +42,7 @@ struct iperf_test; struct iperf_stream_result; struct iperf_interval_results; struct iperf_stream; +struct iperf_time; /* default settings */ #define Ptcp SOCK_STREAM @@ -240,7 +241,7 @@ void print_tcpinfo(struct iperf_test *test); void build_tcpinfo_message(struct iperf_interval_results *r, char *message); int iperf_set_send_state(struct iperf_test *test, signed char state); -void iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP); +void iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP); int iperf_send(struct iperf_test *, fd_set *) /* __attribute__((hot)) */; int iperf_recv(struct iperf_test *, fd_set *); void iperf_catch_sigend(void (*handler)(int)); diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c index c823c5a10..30fa2ac79 100644 --- a/src/iperf_client_api.c +++ b/src/iperf_client_api.c @@ -41,6 +41,7 @@ #include "iperf_api.h" #include "iperf_util.h" #include "iperf_locale.h" +#include "iperf_time.h" #include "net.h" #include "timer.h" @@ -116,7 +117,7 @@ iperf_create_streams(struct iperf_test *test) } static void -test_timer_proc(TimerClientData client_data, struct timeval *nowP) +test_timer_proc(TimerClientData client_data, struct iperf_time *nowP) { struct iperf_test *test = client_data.p; @@ -125,7 +126,7 @@ test_timer_proc(TimerClientData client_data, struct timeval *nowP) } static void -client_stats_timer_proc(TimerClientData client_data, struct timeval *nowP) +client_stats_timer_proc(TimerClientData client_data, struct iperf_time *nowP) { struct iperf_test *test = client_data.p; @@ -136,7 +137,7 @@ client_stats_timer_proc(TimerClientData client_data, struct timeval *nowP) } static void -client_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP) +client_reporter_timer_proc(TimerClientData client_data, struct iperf_time *nowP) { struct iperf_test *test = client_data.p; @@ -149,10 +150,10 @@ client_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP) static int create_client_timers(struct iperf_test * test) { - struct timeval now; + struct iperf_time now; TimerClientData cd; - if (gettimeofday(&now, NULL) < 0) { + if (iperf_time_now(&now) < 0) { i_errno = IEINITTEST; return -1; } @@ -184,7 +185,7 @@ create_client_timers(struct iperf_test * test) } static void -client_omit_timer_proc(TimerClientData client_data, struct timeval *nowP) +client_omit_timer_proc(TimerClientData client_data, struct iperf_time *nowP) { struct iperf_test *test = client_data.p; @@ -204,14 +205,14 @@ client_omit_timer_proc(TimerClientData client_data, struct timeval *nowP) static int create_client_omit_timer(struct iperf_test * test) { - struct timeval now; + struct iperf_time now; TimerClientData cd; if (test->omit == 0) { test->omit_timer = NULL; test->omitting = 0; } else { - if (gettimeofday(&now, NULL) < 0) { + if (iperf_time_now(&now) < 0) { i_errno = IEINITTEST; return -1; } @@ -442,7 +443,7 @@ iperf_run_client(struct iperf_test * test) int startup; int result = 0; fd_set read_set, write_set; - struct timeval now; + struct iperf_time now; struct timeval* timeout = NULL; struct iperf_stream *sp; @@ -475,7 +476,7 @@ iperf_run_client(struct iperf_test * test) while (test->state != IPERF_DONE) { memcpy(&read_set, &test->read_set, sizeof(fd_set)); memcpy(&write_set, &test->write_set, sizeof(fd_set)); - (void) gettimeofday(&now, NULL); + iperf_time_now(&now); timeout = tmr_timeout(&now); result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout); if (result < 0 && errno != EINTR) { @@ -516,7 +517,7 @@ iperf_run_client(struct iperf_test * test) } /* Run the timers. */ - (void) gettimeofday(&now, NULL); + iperf_time_now(&now); tmr_run(&now); /* Is the test done yet? */ diff --git a/src/iperf_config.h.in b/src/iperf_config.h.in index 2d13f9846..e543cbd59 100644 --- a/src/iperf_config.h.in +++ b/src/iperf_config.h.in @@ -1,5 +1,8 @@ /* src/iperf_config.h.in. Generated from configure.ac by autoheader. */ +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + /* Define to 1 if you have the `cpuset_setaffinity' function. */ #undef HAVE_CPUSET_SETAFFINITY diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c index 5fa1dd744..272db82b2 100644 --- a/src/iperf_server_api.c +++ b/src/iperf_server_api.c @@ -54,6 +54,7 @@ #include "iperf_tcp.h" #include "iperf_util.h" #include "timer.h" +#include "iperf_time.h" #include "net.h" #include "units.h" #include "iperf_util.h" @@ -223,7 +224,7 @@ iperf_handle_message_server(struct iperf_test *test) } static void -server_timer_proc(TimerClientData client_data, struct timeval *nowP) +server_timer_proc(TimerClientData client_data, struct iperf_time *nowP) { struct iperf_test *test = client_data.p; struct iperf_stream *sp; @@ -243,7 +244,7 @@ server_timer_proc(TimerClientData client_data, struct timeval *nowP) } static void -server_stats_timer_proc(TimerClientData client_data, struct timeval *nowP) +server_stats_timer_proc(TimerClientData client_data, struct iperf_time *nowP) { struct iperf_test *test = client_data.p; @@ -254,7 +255,7 @@ server_stats_timer_proc(TimerClientData client_data, struct timeval *nowP) } static void -server_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP) +server_reporter_timer_proc(TimerClientData client_data, struct iperf_time *nowP) { struct iperf_test *test = client_data.p; @@ -267,10 +268,10 @@ server_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP) static int create_server_timers(struct iperf_test * test) { - struct timeval now; + struct iperf_time now; TimerClientData cd; - if (gettimeofday(&now, NULL) < 0) { + if (iperf_time_now(&now) < 0) { i_errno = IEINITTEST; return -1; } @@ -304,7 +305,7 @@ create_server_timers(struct iperf_test * test) } static void -server_omit_timer_proc(TimerClientData client_data, struct timeval *nowP) +server_omit_timer_proc(TimerClientData client_data, struct iperf_time *nowP) { struct iperf_test *test = client_data.p; @@ -324,14 +325,14 @@ server_omit_timer_proc(TimerClientData client_data, struct timeval *nowP) static int create_server_omit_timer(struct iperf_test * test) { - struct timeval now; + struct iperf_time now; TimerClientData cd; if (test->omit == 0) { test->omit_timer = NULL; test->omitting = 0; } else { - if (gettimeofday(&now, NULL) < 0) { + if (iperf_time_now(&now) < 0) { i_errno = IEINITTEST; return -1; } @@ -391,7 +392,7 @@ iperf_run_server(struct iperf_test *test) #endif /* HAVE_TCP_CONGESTION */ fd_set read_set, write_set; struct iperf_stream *sp; - struct timeval now; + struct iperf_time now; struct timeval* timeout; if (test->affinity != -1) @@ -428,7 +429,7 @@ iperf_run_server(struct iperf_test *test) memcpy(&read_set, &test->read_set, sizeof(fd_set)); memcpy(&write_set, &test->write_set, sizeof(fd_set)); - (void) gettimeofday(&now, NULL); + iperf_time_now(&now); timeout = tmr_timeout(&now); result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout); if (result < 0 && errno != EINTR) { @@ -606,7 +607,7 @@ iperf_run_server(struct iperf_test *test) if (result == 0 || (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)) { /* Run the timers. */ - (void) gettimeofday(&now, NULL); + iperf_time_now(&now); tmr_run(&now); } } diff --git a/src/iperf_time.c b/src/iperf_time.c new file mode 100644 index 000000000..0ca3790e3 --- /dev/null +++ b/src/iperf_time.c @@ -0,0 +1,156 @@ +/* + * iperf, Copyright (c) 2014-2018, The Regents of the University of + * California, through Lawrence Berkeley National Laboratory (subject + * to receipt of any required approvals from the U.S. Dept. of + * Energy). All rights reserved. + * + * If you have questions about your rights to use or distribute this + * software, please contact Berkeley Lab's Technology Transfer + * Department at TTD@lbl.gov. + * + * NOTICE. This software is owned by the U.S. Department of Energy. + * As such, the U.S. Government has been granted for itself and others + * acting on its behalf a paid-up, nonexclusive, irrevocable, + * worldwide license in the Software to reproduce, prepare derivative + * works, and perform publicly and display publicly. Beginning five + * (5) years after the date permission to assert copyright is obtained + * from the U.S. Department of Energy, and subject to any subsequent + * five (5) year renewals, the U.S. Government is granted for itself + * and others acting on its behalf a paid-up, nonexclusive, + * irrevocable, worldwide license in the Software to reproduce, + * prepare derivative works, distribute copies to the public, perform + * publicly and display publicly, and to permit others to do so. + * + * This code is distributed under a BSD style license, see the LICENSE + * file for complete information. + */ + + +#include + +#include "iperf_config.h" +#include "iperf_time.h" + +#ifdef HAVE_CLOCK_GETTIME + +#include + +int +iperf_time_now(struct iperf_time *time1) +{ + struct timespec ts; + int result; + result = clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + if (result == 0) { + time1->secs = (uint32_t) ts.tv_sec; + time1->usecs = (uint32_t) ts.tv_nsec / 1000; + } + return result; +} + +#else + +#include + +int +iperf_time_now(struct iperf_time *time1) +{ + struct timeval tv; + int result; + result = gettimeofday(&tv, NULL); + time1->secs = tv.tv_sec; + time1->usecs = tv.tv_usec; + return result; +} + +#endif + +/* iperf_time_add_usecs + * + * Add a number of microseconds to a iperf_time. + */ +void +iperf_time_add_usecs(struct iperf_time *time1, uint64_t usecs) +{ + time1->secs += usecs / 1000000L; + time1->usecs += usecs % 1000000L; + if ( time1->usecs >= 1000000L ) { + time1->secs += time1->usecs / 1000000L; + time1->usecs %= 1000000L; + } +} + +uint64_t +iperf_time_in_usecs(struct iperf_time *time) +{ + return time->secs * 1000000LL + time->usecs; +} + +double +iperf_time_in_secs(struct iperf_time *time) +{ + return time->secs + time->usecs / 1000000.0; +} + +/* iperf_time_compare + * + * Compare two timestamps + * + * Returns -1 if time1 is earlier, 1 if time1 is later, + * or 0 if the timestamps are equal. + */ +int +iperf_time_compare(struct iperf_time *time1, struct iperf_time *time2) +{ + if (time1->secs < time2->secs) + return -1; + if (time1->secs > time2->secs) + return 1; + if (time1->usecs < time2->usecs) + return -1; + if (time1->usecs > time2->usecs) + return 1; + return 0; +} + +/* iperf_time_diff + * + * Calculates the time from time2 to time1, assuming time1 is later than time2. + * The diff will always be positive, so the return value should be checked + * to determine if time1 was earlier than time2. + * + * Returns 1 if the time1 is less than or equal to time2, otherwise 0. + */ +int +iperf_time_diff(struct iperf_time *time1, struct iperf_time *time2, struct iperf_time *diff) +{ + int past = 0; + int cmp = 0; + + cmp = iperf_time_compare(time1, time2); + if (cmp == 0) { + diff->secs = 0; + diff->usecs = 0; + past = 1; + } + else if (cmp == 1) { + diff->secs = time1->secs - time2->secs; + diff->usecs = time1->usecs; + if (diff->usecs < time2->usecs) { + diff->secs -= 1; + diff->usecs += 1000000; + } + diff->usecs = diff->usecs - time2->usecs; + } else { + diff->secs = time2->secs - time1->secs; + diff->usecs = time2->usecs; + if (diff->usecs < time1->usecs) { + diff->secs -= 1; + diff->usecs += 1000000; + } + diff->usecs = diff->usecs - time1->usecs; + past = 1; + } + + return past; +} diff --git a/src/iperf_time.h b/src/iperf_time.h new file mode 100644 index 000000000..588ee2624 --- /dev/null +++ b/src/iperf_time.h @@ -0,0 +1,49 @@ +/* + * iperf, Copyright (c) 2014-2018, The Regents of the University of + * California, through Lawrence Berkeley National Laboratory (subject + * to receipt of any required approvals from the U.S. Dept. of + * Energy). All rights reserved. + * + * If you have questions about your rights to use or distribute this + * software, please contact Berkeley Lab's Technology Transfer + * Department at TTD@lbl.gov. + * + * NOTICE. This software is owned by the U.S. Department of Energy. + * As such, the U.S. Government has been granted for itself and others + * acting on its behalf a paid-up, nonexclusive, irrevocable, + * worldwide license in the Software to reproduce, prepare derivative + * works, and perform publicly and display publicly. Beginning five + * (5) years after the date permission to assert copyright is obtained + * from the U.S. Department of Energy, and subject to any subsequent + * five (5) year renewals, the U.S. Government is granted for itself + * and others acting on its behalf a paid-up, nonexclusive, + * irrevocable, worldwide license in the Software to reproduce, + * prepare derivative works, distribute copies to the public, perform + * publicly and display publicly, and to permit others to do so. + * + * This code is distributed under a BSD style license, see the LICENSE + * file for complete information. + */ +#ifndef __IPERF_TIME_H +#define __IPERF_TIME_H + +#include + +struct iperf_time { + uint32_t secs; + uint32_t usecs; +}; + +int iperf_time_now(struct iperf_time *time1); + +void iperf_time_add_usecs(struct iperf_time *time1, uint64_t usecs); + +int iperf_time_compare(struct iperf_time *time1, struct iperf_time *time2); + +int iperf_time_diff(struct iperf_time *time1, struct iperf_time *time2, struct iperf_time *diff); + +uint64_t iperf_time_in_usecs(struct iperf_time *time); + +double iperf_time_in_secs(struct iperf_time *time); + +#endif diff --git a/src/iperf_udp.c b/src/iperf_udp.c index 33f367fdb..3d37dab67 100644 --- a/src/iperf_udp.c +++ b/src/iperf_udp.c @@ -66,7 +66,7 @@ iperf_udp_recv(struct iperf_stream *sp) int r; int size = sp->settings->blksize; double transit = 0, d = 0; - struct timeval sent_time, arrival_time; + struct iperf_time sent_time, arrival_time, temp_time; r = Nread(sp->socket, sp->buffer, size, Pudp); @@ -90,8 +90,8 @@ iperf_udp_recv(struct iperf_stream *sp) sec = ntohl(sec); usec = ntohl(usec); pcount = be64toh(pcount); - sent_time.tv_sec = sec; - sent_time.tv_usec = usec; + sent_time.secs = sec; + sent_time.usecs = usec; } else { uint32_t pc; @@ -101,8 +101,8 @@ iperf_udp_recv(struct iperf_stream *sp) sec = ntohl(sec); usec = ntohl(usec); pcount = ntohl(pc); - sent_time.tv_sec = sec; - sent_time.tv_usec = usec; + sent_time.secs = sec; + sent_time.usecs = usec; } if (sp->test->debug) @@ -163,9 +163,10 @@ iperf_udp_recv(struct iperf_stream *sp) * computation does not require knowing the round-trip * time. */ - gettimeofday(&arrival_time, NULL); + iperf_time_now(&arrival_time); - transit = timeval_diff(&sent_time, &arrival_time); + iperf_time_diff(&arrival_time, &sent_time, &temp_time); + transit = iperf_time_in_secs(&temp_time); d = transit - sp->prev_transit; if (d < 0) d = -d; @@ -190,9 +191,9 @@ iperf_udp_send(struct iperf_stream *sp) { int r; int size = sp->settings->blksize; - struct timeval before; + struct iperf_time before; - gettimeofday(&before, 0); + iperf_time_now(&before); ++sp->packet_count; @@ -201,8 +202,8 @@ iperf_udp_send(struct iperf_stream *sp) uint32_t sec, usec; uint64_t pcount; - sec = htonl(before.tv_sec); - usec = htonl(before.tv_usec); + sec = htonl(before.secs); + usec = htonl(before.usecs); pcount = htobe64(sp->packet_count); memcpy(sp->buffer, &sec, sizeof(sec)); @@ -214,8 +215,8 @@ iperf_udp_send(struct iperf_stream *sp) uint32_t sec, usec, pcount; - sec = htonl(before.tv_sec); - usec = htonl(before.tv_usec); + sec = htonl(before.secs); + usec = htonl(before.usecs); pcount = htonl(sp->packet_count); memcpy(sp->buffer, &sec, sizeof(sec)); diff --git a/src/iperf_util.c b/src/iperf_util.c index 3922def14..c5af476be 100644 --- a/src/iperf_util.c +++ b/src/iperf_util.c @@ -189,10 +189,10 @@ timeval_diff(struct timeval * tv0, struct timeval * tv1) void cpu_util(double pcpu[3]) { - static struct timeval last; + static struct iperf_time last; static clock_t clast; static struct rusage rlast; - struct timeval temp; + struct iperf_time now, temp_time; clock_t ctemp; struct rusage rtemp; double timediff; @@ -200,18 +200,19 @@ cpu_util(double pcpu[3]) double systemdiff; if (pcpu == NULL) { - gettimeofday(&last, NULL); + iperf_time_now(&last); clast = clock(); getrusage(RUSAGE_SELF, &rlast); return; } - gettimeofday(&temp, NULL); + iperf_time_now(&now); ctemp = clock(); getrusage(RUSAGE_SELF, &rtemp); - timediff = ((temp.tv_sec * 1000000.0 + temp.tv_usec) - - (last.tv_sec * 1000000.0 + last.tv_usec)); + iperf_time_diff(&now, &last, &temp_time); + timediff = iperf_time_in_secs(&temp_time); + userdiff = ((rtemp.ru_utime.tv_sec * 1000000.0 + rtemp.ru_utime.tv_usec) - (rlast.ru_utime.tv_sec * 1000000.0 + rlast.ru_utime.tv_usec)); systemdiff = ((rtemp.ru_stime.tv_sec * 1000000.0 + rtemp.ru_stime.tv_usec) - diff --git a/src/t_timer.c b/src/t_timer.c index ed74672d4..959859472 100644 --- a/src/t_timer.c +++ b/src/t_timer.c @@ -35,13 +35,14 @@ #include #include "timer.h" +#include "iperf_time.h" static int flag; static void -timer_proc( TimerClientData client_data, struct timeval* nowP ) +timer_proc( TimerClientData client_data, struct iperf_time* nowP ) { flag = 1; } @@ -53,7 +54,7 @@ main(int argc, char **argv) Timer *tp; flag = 0; - tp = tmr_create((struct timeval*) 0, timer_proc, JunkClientData, 3000000, 0); + tp = tmr_create(NULL, timer_proc, JunkClientData, 3000000, 0); if (!tp) { printf("failed to create timer\n"); @@ -62,7 +63,7 @@ main(int argc, char **argv) sleep(2); - tmr_run((struct timeval*) 0); + tmr_run(NULL); if (flag) { printf("timer should not have expired\n"); @@ -70,7 +71,7 @@ main(int argc, char **argv) } sleep(1); - tmr_run((struct timeval*) 0); + tmr_run(NULL); if (!flag) { printf("timer should have expired\n"); diff --git a/src/timer.c b/src/timer.c index bfc52e48f..33923c79c 100644 --- a/src/timer.c +++ b/src/timer.c @@ -31,7 +31,7 @@ #include #include "timer.h" - +#include "iperf_time.h" static Timer* timers = NULL; static Timer* free_timers = NULL; @@ -41,19 +41,19 @@ TimerClientData JunkClientData; /* This is an efficiency tweak. All the routines that need to know the -** current time get passed a pointer to a struct timeval. If it's non-NULL -** it gets used, otherwise we do our own gettimeofday() to fill it in. -** This lets the caller avoid extraneous gettimeofday()s when efficiency +** current time get passed a pointer to a struct iperf_time. If it's non-NULL +** it gets used, otherwise we do our own iperf_time_now() to fill it in. +** This lets the caller avoid extraneous iperf_time_now()s when efficiency ** is needed, and not bother with the extra code when efficiency doesn't ** matter too much. */ static void -getnow( struct timeval* nowP, struct timeval* nowP2 ) +getnow( struct iperf_time* nowP, struct iperf_time* nowP2 ) { if ( nowP != NULL ) *nowP2 = *nowP; else - (void) gettimeofday( nowP2, NULL ); + iperf_time_now(nowP2); } @@ -68,9 +68,7 @@ list_add( Timer* t ) timers = t; t->prev = t->next = NULL; } else { - if ( t->time.tv_sec < timers->time.tv_sec || - ( t->time.tv_sec == timers->time.tv_sec && - t->time.tv_usec < timers->time.tv_usec ) ) { + if (iperf_time_compare(&t->time, &timers->time) < 0) { /* The new timer goes at the head of the list. */ t->prev = NULL; t->next = timers; @@ -80,9 +78,7 @@ list_add( Timer* t ) /* Walk the list to find the insertion point. */ for ( t2prev = timers, t2 = timers->next; t2 != NULL; t2prev = t2, t2 = t2->next ) { - if ( t->time.tv_sec < t2->time.tv_sec || - ( t->time.tv_sec == t2->time.tv_sec && - t->time.tv_usec < t2->time.tv_usec ) ) { + if (iperf_time_compare(&t->time, &t2->time) < 0) { /* Found it. */ t2prev->next = t; t->prev = t2prev; @@ -122,24 +118,12 @@ list_resort( Timer* t ) } -static void -add_usecs( struct timeval* t, int64_t usecs ) -{ - t->tv_sec += usecs / 1000000L; - t->tv_usec += usecs % 1000000L; - if ( t->tv_usec >= 1000000L ) { - t->tv_sec += t->tv_usec / 1000000L; - t->tv_usec %= 1000000L; - } -} - - Timer* tmr_create( - struct timeval* nowP, TimerProc* timer_proc, TimerClientData client_data, + struct iperf_time* nowP, TimerProc* timer_proc, TimerClientData client_data, int64_t usecs, int periodic ) { - struct timeval now; + struct iperf_time now; Timer* t; getnow( nowP, &now ); @@ -158,7 +142,7 @@ tmr_create( t->usecs = usecs; t->periodic = periodic; t->time = now; - add_usecs( &t->time, usecs ); + iperf_time_add_usecs(&t->time, usecs); /* Add the new timer to the active list. */ list_add( t ); @@ -167,20 +151,22 @@ tmr_create( struct timeval* -tmr_timeout( struct timeval* nowP ) +tmr_timeout( struct iperf_time* nowP ) { - struct timeval now; + struct iperf_time now, diff; int64_t usecs; + int past; static struct timeval timeout; getnow( nowP, &now ); /* Since the list is sorted, we only need to look at the first timer. */ if ( timers == NULL ) return NULL; - usecs = ( timers->time.tv_sec - now.tv_sec ) * 1000000LL + - ( timers->time.tv_usec - now.tv_usec ); - if ( usecs <= 0 ) - usecs = 0; + past = iperf_time_diff(&timers->time, &now, &diff); + if (past) + usecs = 0; + else + usecs = iperf_time_in_usecs(&diff); timeout.tv_sec = usecs / 1000000LL; timeout.tv_usec = usecs % 1000000LL; return &timeout; @@ -188,9 +174,9 @@ tmr_timeout( struct timeval* nowP ) void -tmr_run( struct timeval* nowP ) +tmr_run( struct iperf_time* nowP ) { - struct timeval now; + struct iperf_time now; Timer* t; Timer* next; @@ -200,14 +186,12 @@ tmr_run( struct timeval* nowP ) /* Since the list is sorted, as soon as we find a timer ** that isn't ready yet, we are done. */ - if ( t->time.tv_sec > now.tv_sec || - ( t->time.tv_sec == now.tv_sec && - t->time.tv_usec > now.tv_usec ) ) + if (iperf_time_compare(&t->time, &now) > 0) break; (t->timer_proc)( t->client_data, &now ); if ( t->periodic ) { /* Reschedule. */ - add_usecs( &t->time, t->usecs ); + iperf_time_add_usecs(&t->time, t->usecs); list_resort( t ); } else tmr_cancel( t ); @@ -216,13 +200,13 @@ tmr_run( struct timeval* nowP ) void -tmr_reset( struct timeval* nowP, Timer* t ) +tmr_reset( struct iperf_time* nowP, Timer* t ) { - struct timeval now; + struct iperf_time now; getnow( nowP, &now ); t->time = now; - add_usecs( &t->time, t->usecs ); + iperf_time_add_usecs( &t->time, t->usecs ); list_resort( t ); } diff --git a/src/timer.h b/src/timer.h index 0f9c5ebcb..301cdf34e 100644 --- a/src/timer.h +++ b/src/timer.h @@ -30,7 +30,8 @@ #ifndef __TIMER_H #define __TIMER_H -#include +#include +#include "iperf_time.h" /* TimerClientData is an opaque value that tags along with a timer. The ** client can use it for whatever, and it gets passed to the callback when @@ -46,10 +47,10 @@ typedef union extern TimerClientData JunkClientData; /* for use when you don't care */ /* The TimerProc gets called when the timer expires. It gets passed -** the TimerClientData associated with the timer, and a timeval in case +** the TimerClientData associated with the timer, and a iperf_time in case ** it wants to schedule another timer. */ -typedef void TimerProc( TimerClientData client_data, struct timeval* nowP ); +typedef void TimerProc( TimerClientData client_data, struct iperf_time* nowP ); /* The Timer struct. */ typedef struct TimerStruct @@ -58,7 +59,7 @@ typedef struct TimerStruct TimerClientData client_data; int64_t usecs; int periodic; - struct timeval time; + struct iperf_time time; struct TimerStruct* prev; struct TimerStruct* next; int hash; @@ -66,22 +67,22 @@ typedef struct TimerStruct /* Set up a timer, either periodic or one-shot. Returns (Timer*) 0 on errors. */ extern Timer* tmr_create( - struct timeval* nowP, TimerProc* timer_proc, TimerClientData client_data, + struct iperf_time* nowP, TimerProc* timer_proc, TimerClientData client_data, int64_t usecs, int periodic ); /* Returns a timeout indicating how long until the next timer triggers. You ** can just put the call to this routine right in your select(). Returns ** (struct timeval*) 0 if no timers are pending. */ -extern struct timeval* tmr_timeout( struct timeval* nowP ) /* __attribute__((hot)) */; +extern struct timeval* tmr_timeout( struct iperf_time* nowP ) /* __attribute__((hot)) */; /* Run the list of timers. Your main program needs to call this every so often, ** or as indicated by tmr_timeout(). */ -extern void tmr_run( struct timeval* nowP ) /* __attribute__((hot)) */; +extern void tmr_run( struct iperf_time* nowP ) /* __attribute__((hot)) */; /* Reset the clock on a timer, to current time plus the original timeout. */ -extern void tmr_reset( struct timeval* nowP, Timer* timer ); +extern void tmr_reset( struct iperf_time* nowP, Timer* timer ); /* Deschedule a timer. Note that non-periodic timers are automatically ** descheduled when they run, so you don't have to call this on them.