Package: iperf
Version: 2.0.4-4

000-Iperf_Fix-CPU-Usage.diff contains a bug can cause iperf deadlock while
it acting as server with multiple clients.
For example, in the code below, Condition_Wait is incorrectly used without a
Condition_Lock.
@@ -396,11 +390,8 @@
 void EndReport( ReportHeader *agent ) {
     if ( agent != NULL ) {
         int index = agent->reporterindex;
-       if (threadSleeping)
-           Condition_Signal( &ReportCond );
-
         while ( index != -1 ) {
-            thread_rest();
+            Condition_Wait( &ReportDoneCond );
             index = agent->reporterindex;
         }
         agent->agentindex = -1;


I Have a patch to fix it: 007-iperf-reporter-deadlock.patch
===========
# add a Condition_Wait_Event for ReporterDoneCond
diff -r -u --show-c-function iperf-2.0.4/include/Condition.h
iperf-2.0.4.orig/include/Condition.h
--- iperf-2.0.4.orig/include/Condition.h        2007-08-30
06:06:19.000000000 +0800
+++ iperf-2.0.4/include/Condition.h     2009-06-19 01:29:28.000000000 +0800
@@ -115,6 +115,11 @@ typedef struct Condition {
     // sleep this thread, waiting for condition signal
 #if   defined( HAVE_POSIX_THREAD )
     #define Condition_Wait( Cond ) pthread_cond_wait( &(Cond)->mCondition,
&(Cond)->mMutex )
+    #define Condition_Wait_Event( Cond ) do { \
+        Mutex_Lock( &(Cond)->mMutex ); \
+        pthread_cond_wait( &(Cond)->mCondition, &(Cond)->mMutex ); \
+        Mutex_Unlock( &(Cond)->mMutex ); \
+    } while( 0 )
 #elif defined( HAVE_WIN32_THREAD )
     // atomically release mutex and wait on condition,

     // then re-acquire the mutex
@@ -122,6 +127,10 @@ typedef struct Condition {
         SignalObjectAndWait( (Cond)->mMutex, (Cond)->mCondition, INFINITE,
false ); \
         Mutex_Lock( &(Cond)->mMutex );                          \
     } while ( 0 )
+    #define Condition_Wait_Event( Cond ) do { \
+        Mutex_Lock( &(Cond)->mMutex );                          \
+        SignalObjectAndWait( (Cond)->mMutex, (Cond)->mCondition, INFINITE,
false ); \
+    } while ( 0 )
 #else
     #define Condition_Wait( Cond )
 #endif
diff -r -u --show-c-function iperf-2.0.4/src/Reporter.c
iperf-2.0.4.orig/src/Reporter.c
--- iperf-2.0.4/src/Reporter.c  2009-06-19 01:30:32.000000000 +0800
+++ iperf-2.0.4.orig/src/Reporter.c     2009-06-19 01:23:53.000000000 +0800
@@ -339,7 +339,7 @@ void ReportPacket( ReportHeader* agent, 
             // item
             while ( index == 0 ) {
                 Condition_Signal( &ReportCond );
-                Condition_Wait( &ReportDoneCond );
+                Condition_Wait_Event( &ReportDoneCond );
                 index = agent->reporterindex;
             }
             agent->agentindex = 0;
@@ -347,7 +347,7 @@ void ReportPacket( ReportHeader* agent, 
         // Need to make sure that reporter is not about to be "lapped"
         while ( index - 1 == agent->agentindex ) {
             Condition_Signal( &ReportCond );
-            Condition_Wait( &ReportDoneCond );
+            Condition_Wait_Event( &ReportDoneCond );
             index = agent->reporterindex;
         }
 
@@ -391,7 +391,7 @@ void EndReport( ReportHeader *agent ) {
     if ( agent != NULL ) {
         int index = agent->reporterindex;
         while ( index != -1 ) {
-            Condition_Wait( &ReportDoneCond );
+            Condition_Wait_Event( &ReportDoneCond );
             index = agent->reporterindex;
         }
         agent->agentindex = -1;
@@ -412,7 +412,7 @@ void EndReport( ReportHeader *agent ) {
 Transfer_Info *GetReport( ReportHeader *agent ) {
     int index = agent->reporterindex;
     while ( index != -1 ) {
-        Condition_Wait( &ReportDoneCond );
+        Condition_Wait_Event( &ReportDoneCond );
         index = agent->reporterindex;
     }
     return &agent->report.info;
===========

The second problem.
And with the 004-svn-r43.patch iperf can not reach a high package rate. As
below:

[...@91.31 ~]# ./iperf -u -c 10.11.91.32 -b 750M -l 600 -d -t 5
[  4] local 10.11.91.31 port 52747 connected with 10.11.91.32 port 5001
[  3] local 10.11.91.31 port 5001 connected with 10.11.91.32 port 52411
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0- 5.0 sec    394 MBytes    662 Mbits/sec
[  4] Sent 689346 datagrams
[  3]  0.0- 5.0 sec    281 MBytes    471 Mbits/sec  0.006 ms 171032/661467
(26%)
[  3]  0.0- 5.0 sec  1 datagrams received out-of-order
[  4] Server Report:
[  4]  0.0- 5.0 sec    343 MBytes    576 Mbits/sec  0.129 ms 89705/689345
(13%)
[  4]  0.0- 5.0 sec  1 datagrams received out-of-order

I have dropped 004-svn-r43.patch, and use my 2 small simple patches instead.
So everythings goes right:

[...@91.31 ~]# iperf -u -c 10.11.91.32 -b 750M -l 600 -d -t 5 
 [  4] local 10.11.91.31 port 52755 connected with 10.11.91.32 port 5001
[  3] local 10.11.91.31 port 5001 connected with 10.11.91.32 port 52419
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0- 5.0 sec    458 MBytes    769 Mbits/sec
[  4] Sent 801077 datagrams
[ ID] Interval       Transfer     Bandwidth       Jitter   Lost/Total
Datagrams
[  3]  0.0- 5.0 sec    432 MBytes    725 Mbits/sec  0.008 ms 13720/768973
(1.8%)
[  3]  0.0- 5.0 sec  1 datagrams received out-of-order
[  4] Server Report:
[ ID] Interval       Transfer     Bandwidth       Jitter   Lost/Total
Datagrams
[  4]  0.0- 5.0 sec    447 MBytes    750 Mbits/sec  0.006 ms 19946/801076
(2.5%)
[  4]  0.0- 5.0 sec  1 datagrams received out-of-order 


iperf-2.0.4-numofreport.patch 
==========
# increase the queue length to avoid thread racing
diff -r -u --show-c-function iperf-2.0.4.ori/include/Reporter.h
iperf-2.0.4/include/Reporter.h
--- iperf-2.0.4.ori/include/Reporter.h  2008-04-08 10:37:54.000000000 +0800
+++ iperf-2.0.4/include/Reporter.h      2009-06-16 23:34:03.000000000 +0800
@@ -61,7 +61,7 @@ struct server_hdr;
 
 #include "Settings.hpp"
 
-#define NUM_REPORT_STRUCTS 700
+#define NUM_REPORT_STRUCTS 5700
 #define NUM_MULTI_SLOTS    5
 
 #ifdef __cplusplus
==========

iperf-2.0.4-delayloop.patch
==========
# using sched_yield to schedule other threads, so multiple iperf can run
simultaneously
# using usleep with delay-loop between 2 package is long than 1.25ms.
diff -r -u --show-c-function iperf-2.0.4.ori/compat/delay.cpp
iperf-2.0.4/compat/delay.cpp
--- iperf-2.0.4.ori/compat/delay.cpp    2007-08-30 06:06:19.000000000 +0800
+++ iperf-2.0.4/compat/delay.cpp        2009-06-16 23:54:35.000000000 +0800
@@ -69,6 +69,13 @@ void delay_loop( unsigned long usec ) {
 
     Timestamp now;
     while ( now.before( end ) ) {
+       long diff = end.subUsec(now);
+       if (diff >= 1250) {
+               usleep(0);
+       }
+       if (diff >= 2) {
+               sched_yield();
+       }
         now.setnow();
     }
 }
==========






-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to