Thread library bug for kernel >= 2.6.21
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
iperf (Debian) |
Fix Released
|
Unknown
|
|||
iperf (Ubuntu) |
Fix Released
|
Medium
|
Daniel Hahler |
Bug Description
Binary package hint: iperf
Taken from http://
The latest version of Linux kernel aggravates a pre-existing iperf thread
library bug. The iperf thread library assumes that calling usleep(0) will
cause
the thread to yield so that other threads will run. This has never been a
documented
behavior of Linux/Unix. The new high resolution timer option in the kernel
causes
usleep(0) to be a nop so the thread keeps running (until it's quanta is
exhausted).
Without this fix, iperf will get poor performance because the monitoring
thread
may hog the cpu, keeping the sender/receiver threads from running.
The fix to iperf is easy, just use sched_yield() instead. The manual page
for sched_yield
says to test for POSIX_PRIORITY_
--- compat/
+++ compat/Thread.c 2007-06-04 10:41:11.000000000 -0700
@@ -405,9 +405,13 @@
void thread_rest ( void ) {
#if defined( HAVE_THREAD )
#if defined( HAVE_POSIX_THREAD )
- // TODO add checks for sched_yield or pthread_yield and call that
- // if available
+
+#if defined( _POSIX_
+ sched_yield();
+#else
usleep( 0 );
+#endif
+
#else // Win32
SwitchToTh
#endif
Changed in iperf: | |
status: | Unknown → New |
Changed in iperf: | |
status: | New → Fix Released |
Same problem for me... kerneltrap. org/Linux/ Finding_ Bugs_With_ CFS
Solved with patch of Ingo Molnar from:
http://
---
compat/Thread.c | 3 ---
src/Reporter.c | 13 +++++++++----
src/main.cpp | 2 ++
3 files changed, 11 insertions(+), 7 deletions(-)
Index: iperf-2. 0.2/compat/ Thread. c ======= ======= ======= ======= ======= ======= ======= ======= ==== 0.2.orig/ compat/ Thread. c 0.2/compat/ Thread. c numuserthreads( void ) { read( ); 0.2/src/ Reporter. c ======= ======= ======= ======= ======= ======= ======= ======= ==== 0.2.orig/ src/Reporter. c 0.2/src/ Reporter. c reports[ kRepo process_ report ( ReportHeader *report ); handle_ packet( ReportHeader *report );
Condition_ Signal( &ReportCond );
index = agent-> reporterindex;
agent- >agentindex = 0;
Condition _Signal( &ReportCond ); reporterindex;
=======
--- iperf-2.
+++ iperf-2.
@@ -405,9 +405,6 @@ int thread_
void thread_rest ( void ) {
#if defined( HAVE_THREAD )
#if defined( HAVE_POSIX_THREAD )
- // TODO add checks for sched_yield or pthread_yield and call that
- // if available
- usleep( 0 );
#else // Win32
SwitchToTh
#endif
Index: iperf-2.
=======
--- iperf-2.
+++ iperf-2.
@@ -111,6 +111,7 @@ report_statistics multiple_
char buffer[64]; // Buffer for printing
ReportHeader *ReportRoot = NULL;
extern Condition ReportCond;
+extern Condition ReportDoneCond;
int reporter_
void process_report ( ReportHeader *report );
int reporter_
@@ -338,7 +339,7 @@ void ReportPacket( ReportHeader* agent,
// item
while ( index == 0 ) {
- thread_rest();
+ Condition_Wait( &ReportDoneCond );
}
@@ -346,7 +347,7 @@ void ReportPacket( ReportHeader* agent,
// Need to make sure that reporter is not about to be "lapped"
while ( index - 1 == agent->agentindex ) {
- thread_rest();
+ Condition_Wait( &ReportDoneCond );
index = agent->
}
@@ -553,6 +554,7 @@ void reporter_spawn( thread_Settings *th
Condition_ Unlock ( ReportCond );
}
+again:
ReportHea der *temp = ReportRoot;
/ /Condition_ Unlock ( ReportCond );
free( temp );
Condition_ Unlock ( ReportCond );
/ /Condition_ Unlock ( ReportCond ); 0.2/src/ main.cpp ======= ======= ======= ======= ======= ======= ======= ======= ==== 0.2.orig/ src/main. cpp 0.2/src/ main.cpp
if ( ReportRoot != NULL ) {
@@ -575,9 +577,12 @@ void reporter_spawn( thread_Settings *th
// finished with report so free it
+ Condition_Signal( &ReportDoneCond );
+ if (ReportRoot)
+ goto again;
}
- // yield control of CPU is another thread is waiting
- thread_rest();
+ Condition_Signal( &ReportDoneCond );
+ usleep(10000);
} else {
}
Index: iperf-2.
=======
--- iperf-2.
+++ iperf-2.
@@ -96,6 +96,7 @@ extern "C" {
// records being accessed in a report and also to
// serialize modification of the report list
Condition ReportCond;
+ Condition ReportDoneCond;
}
// global variables only accessed within this file
@@...