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