@@ -1639,10 +1639,12 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
1639
1639
test -> use_pkcs1_padding = 1 ;
1640
1640
break ;
1641
1641
#endif /* HAVE_SSL */
1642
+ #if !defined(HAVE_CLOCK_NANOSLEEP ) && !defined(HAVE_NANOSLEEP )
1642
1643
case OPT_PACING_TIMER :
1643
1644
test -> settings -> pacing_timer = unit_atoi (optarg );
1644
1645
client_flag = 1 ;
1645
1646
break ;
1647
+ #endif /* !HAVE_CLOCK_NANOSLEEP && !HAVE_NANOSLEEP */
1646
1648
case OPT_CONNECT_TIMEOUT :
1647
1649
test -> settings -> connect_timeout = unit_atoi (optarg );
1648
1650
client_flag = 1 ;
@@ -1881,17 +1883,73 @@ iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP)
1881
1883
struct iperf_time temp_time ;
1882
1884
double seconds ;
1883
1885
uint64_t bits_per_second ;
1886
+ int64_t missing_rate ;
1887
+ uint64_t bits_sent ;
1888
+
1889
+ #if defined(HAVE_CLOCK_NANOSLEEP ) || defined(HAVE_NANOSLEEP )
1890
+ struct timespec nanosleep_time ;
1891
+ int64_t time_to_green_ligh , delta_bits ;
1892
+ int ret ;
1893
+ #endif /* HAVE_CLOCK_NANOSLEEP || HAVE_NANOSLEEP) */
1894
+ #if defined(HAVE_CLOCK_NANOSLEEP )
1895
+ int64_t ns ;
1896
+ #endif /* HAVE_CLOCK_NANOSLEEP */
1884
1897
1885
1898
if (sp -> test -> done || sp -> test -> settings -> rate == 0 )
1886
1899
return ;
1887
1900
iperf_time_diff (& sp -> result -> start_time_fixed , nowP , & temp_time );
1888
1901
seconds = iperf_time_in_secs (& temp_time );
1889
- bits_per_second = sp -> result -> bytes_sent * 8 / seconds ;
1890
- if (bits_per_second < sp -> test -> settings -> rate ) {
1902
+ bits_sent = sp -> result -> bytes_sent * 8 ;
1903
+ bits_per_second = bits_sent / seconds ;
1904
+ missing_rate = sp -> test -> settings -> rate - bits_per_second ;
1905
+
1906
+ if (missing_rate > 0 ) {
1891
1907
sp -> green_light = 1 ;
1892
1908
} else {
1893
1909
sp -> green_light = 0 ;
1894
1910
}
1911
+
1912
+ #if defined(HAVE_CLOCK_NANOSLEEP ) || defined(HAVE_NANOSLEEP )
1913
+ // If estimated time to next send is large enough, sleep instead of just CPU looping until green light is set
1914
+ if (missing_rate < 0 ) {
1915
+ delta_bits = bits_sent - (seconds * sp -> test -> settings -> rate );
1916
+ // Calclate time until next data send is required
1917
+ time_to_green_ligh = (SEC_TO_NS * delta_bits / sp -> test -> settings -> rate );
1918
+ // Whether shouuld wait before next send
1919
+ if (time_to_green_ligh >= 0 ) {
1920
+ #if defined(HAVE_CLOCK_NANOSLEEP )
1921
+ if (clock_gettime (CLOCK_MONOTONIC , & nanosleep_time ) == 0 ) {
1922
+ // Calculate absolute end of sleep time
1923
+ ns = nanosleep_time .tv_nsec + time_to_green_ligh ;
1924
+ if (ns < SEC_TO_NS ) {
1925
+ nanosleep_time .tv_nsec = ns ;
1926
+ } else {
1927
+ nanosleep_time .tv_sec += ns / SEC_TO_NS ;
1928
+ nanosleep_time .tv_nsec = ns % SEC_TO_NS ;
1929
+ }
1930
+ // Sleep until average baud rate reaches the target value
1931
+ while ((ret = clock_nanosleep (CLOCK_MONOTONIC , TIMER_ABSTIME , & nanosleep_time , NULL )) == EINTR );
1932
+ if (ret == 0 ) {
1933
+ sp -> green_light = 1 ;
1934
+ }
1935
+ }
1936
+
1937
+ #else /* HAVE_NANOSLEEP */
1938
+ nanosleep_time .tv_sec = 0 ;
1939
+ // Sleep until average baud rate reaches the target value or intrupt / error
1940
+ do {
1941
+ // nansleep() time should be less than 1 sec
1942
+ nanosleep_time .tv_nsec = (time_to_green_ligh >= SEC_TO_NS ) ? SEC_TO_NS - 1 : time_to_green_ligh ;
1943
+ time_to_green_ligh -= nanosleep_time .tv_nsec ;
1944
+ ret = nanosleep (& nanosleep_time , NULL );
1945
+ } while (ret == 0 && time_to_green_ligh > 0 );
1946
+ if (ret == 0 ) {
1947
+ sp -> green_light = 1 ;
1948
+ }
1949
+ #endif /* HAVE_CLOCK_NANOSLEEP else HAVE_NANOSLEEP */
1950
+ }
1951
+ }
1952
+ #endif /* HAVE_CLOCK_NANOSLEEP || HAVE_NANOSLEEP */
1895
1953
}
1896
1954
1897
1955
/* Verify that average traffic is not greater than the specified limit */
@@ -1982,7 +2040,11 @@ iperf_send_mt(struct iperf_stream *sp)
1982
2040
if (!streams_active )
1983
2041
break ;
1984
2042
}
2043
+ #if defined(HAVE_CLOCK_NANOSLEEP ) || defined(HAVE_NANOSLEEP )
2044
+ if (!sp -> green_light ) { /* Should check if green ligh can be set, as pacing timer is not supported in this case */
2045
+ #else /* !HAVE_CLOCK_NANOSLEEP && !HAVE_NANOSLEEP */
1985
2046
if (!no_throttle_check ) { /* Throttle check if was not checked for each send */
2047
+ #endif /* HAVE_CLOCK_NANOSLEEP, HAVE_NANOSLEEP */
1986
2048
iperf_time_now (& now );
1987
2049
if (sp -> sender )
1988
2050
iperf_check_throttle (sp , & now );
@@ -2032,6 +2094,7 @@ iperf_init_test(struct iperf_test *test)
2032
2094
return 0 ;
2033
2095
}
2034
2096
2097
+ #if !defined(HAVE_CLOCK_NANOSLEEP ) && !defined(HAVE_NANOSLEEP )
2035
2098
static void
2036
2099
send_timer_proc (TimerClientData client_data , struct iperf_time * nowP )
2037
2100
{
@@ -2043,20 +2106,25 @@ send_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
2043
2106
*/
2044
2107
iperf_check_throttle (sp , nowP );
2045
2108
}
2109
+ #endif /* !HAVE_CLOCK_NANOSLEEP && !HAVE_NANOSLEEP) */
2046
2110
2047
2111
int
2048
2112
iperf_create_send_timers (struct iperf_test * test )
2049
2113
{
2050
- struct iperf_time now ;
2051
2114
struct iperf_stream * sp ;
2115
+ #if !defined(HAVE_CLOCK_NANOSLEEP ) && !defined(HAVE_NANOSLEEP )
2052
2116
TimerClientData cd ;
2117
+ struct iperf_time now ;
2053
2118
2054
2119
if (iperf_time_now (& now ) < 0 ) {
2055
2120
i_errno = IEINITTEST ;
2056
2121
return -1 ;
2057
2122
}
2123
+ #endif /* !HAVE_CLOCK_NANOSLEEP && !HAVE_NANOSLEEP) */
2124
+
2058
2125
SLIST_FOREACH (sp , & test -> streams , streams ) {
2059
2126
sp -> green_light = 1 ;
2127
+ #if !defined(HAVE_CLOCK_NANOSLEEP ) && !defined(HAVE_NANOSLEEP )
2060
2128
if (test -> settings -> rate != 0 && sp -> sender ) {
2061
2129
cd .p = sp ;
2062
2130
sp -> send_timer = tmr_create (NULL , send_timer_proc , cd , test -> settings -> pacing_timer , 1 );
@@ -2065,6 +2133,7 @@ iperf_create_send_timers(struct iperf_test * test)
2065
2133
return -1 ;
2066
2134
}
2067
2135
}
2136
+ #endif /* !HAVE_CLOCK_NANOSLEEP && !HAVE_NANOSLEEP) */
2068
2137
}
2069
2138
return 0 ;
2070
2139
}
0 commit comments