Hi all,
I'm using a ts7800, and discover (what i think is) a bug when using
the OABI cross-toolchain . The bug only shows when a thread run with
the SCHED_FIFO policy.
If i use the EABI toolchain, the bug never show.
If i build natively the test program on the ts7800, the bug shows.
Attached is an example program that will show the bug.
In short, it seems there's a race condition in the libstdc++,
actually, there is at least one in std::iostream (showed with the
attach program), and another one in std::string (i was not able to
reproduce that one with a simple program, but i notice that threads
was blocked in std::string::_Rep::_M_refcopy and/or
std::string::_Rep::_M_dispose).
When 2 threads are busy writing on std::cout, the program will ends
with a screwed-up output, where each thread is slowly writing one
character at a time, one thread after each other. The normal behavior
would be to "quickly" write a block of characters one after each other.
Does anyone on this mailing list had encourted this kind of problem in
the past?
Would Technologic system's people consider investigating this? And
possibly come with a fix?
With best regards,
Chris
PS1: Here is a sample output from the test program:
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF200132 abcdefghijklmnopqrstuvwxyz
GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
[...]
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW1X9Y9Z7A1B6C
DaEbFcGdHeIfJgKhLiMjNkOlPmQnRoSpTqUrVsWtXuYvZwAxByCzD
E7F2G0H0I3J5K LaMbNcOdPeQfRgShTiUjVkWlXmYnZoApBqCrDsEtFuGvHwIxJyKzL
M7N4O0P3Q0R8S TaUbVcWdXeYfZg
hijklAmBnCoDpEqFrGsHtIuJvKwLxMyNzO
P7Q1R0S0T1U3V WaXbYcZdAeBfCgDhEiFjGkHlImJnKoLpMqNrOsPtQuRvSwTxUyVzW
X7Y0Z0A0B1C0D EaFbGcHdIeJfKgLhMiNjOkPlQmRnSoTpUqVrWsXtYuZvAwBxCyDzE
F7G0H9I9J9K5L MaNbOcPdQeRfSgThUiVjWkXlYmZnAoBpCqDrEsFtGuHvIwJxKyLzM
N7O2P0Q0R0S5T UaVbWcXdYeZf
ghijAkBlCmDnEoFpGqHrIsJtKuLvMwNxOyPzQ
R7S0T9U9V3W7X YaZbAcBdCeDfEgFhGiHjIkJlKmLnMoNpOqPrQsRtSuTvUwVxWyXzY
Z7A0B0C0D2E8F GaHbIcJdKeLfMgNhOiPjQkRlSmTnUoVpWqXrYsZtAuBvCwDxEyFzG
H7I2J9K9L8M7N OaPbQcRdSeTfUgVhWiXjYkZlAmBnCoDpEqFrGsHtIuJvKwLxMyNzO
[...]
PS2: The following backtrace for both threads show that there are
fighting for a mutex in the stdlib.
----
#0 0x40026d80 in __pthread_sigsuspend () from /lib/libpthread.so.0
#1 0x40025a7c in __pthread_wait_for_restart_signal () from
/lib/libpthread.so.0
#2 0x40028b54 in __pthread_alt_lock () from /lib/libpthread.so.0
#3 0x400255a0 in pthread_mutex_lock () from /lib/libpthread.so.0
#4 0x400d66e0 in std::locale::locale () from /usr/lib/libstdc++.so.5
#5 0x400be1c0 in std::basic_filebuf<char, std::char_traits<char>
>::_M_convert_to_external ()
from /usr/lib/libstdc++.so.5
#6 0x400be088 in std::basic_filebuf<char, std::char_traits<char>
>::_M_really_overflow ()
from /usr/lib/libstdc++.so.5
#7 0x400bdf88 in std::basic_filebuf<char, std::char_traits<char>
>::overflow ()
from /usr/lib/libstdc++.so.5
#8 0x40123030 in std::basic_streambuf<char, std::char_traits<char>
>::xsputn ()
from /usr/lib/libstdc++.so.5
#9 0x4010efec in std::operator<< <char, std::char_traits<char>,
std::allocator<char> > ()
from /usr/lib/libstdc++.so.5
#10 0x000092e4 in routine_2 (arg=0x0) at test.cc:66
#11 0x40023fb0 in pthread_start_thread () from /lib/libpthread.so.0
----
#0 0x4002b6dc in nanosleep () from /lib/libpthread.so.0
#1 0x40028a90 in __pthread_acquire () from /lib/libpthread.so.0
#2 0x40028c60 in __pthread_alt_unlock () from /lib/libpthread.so.0
#3 0x4002519c in pthread_mutex_unlock () from /lib/libpthread.so.0
#4 0x400d6708 in std::locale::locale () from /usr/lib/libstdc++.so.5
#5 0x400be1c0 in std::basic_filebuf<char, std::char_traits<char>
>::_M_convert_to_external ()
from /usr/lib/libstdc++.so.5
#6 0x400be088 in std::basic_filebuf<char, std::char_traits<char>
>::_M_really_overflow ()
from /usr/lib/libstdc++.so.5
#7 0x400bdf88 in std::basic_filebuf<char, std::char_traits<char>
>::overflow ()
from /usr/lib/libstdc++.so.5
#8 0x40123030 in std::basic_streambuf<char, std::char_traits<char>
>::xsputn ()
from /usr/lib/libstdc++.so.5
#9 0x4010efec in std::operator<< <char, std::char_traits<char>,
std::allocator<char> > ()
from /usr/lib/libstdc++.so.5
#10 0x00009090 in routine_1 (arg=0x0) at test.cc:48
#11 0x40023fb0 in pthread_start_thread () from /lib/libpthread.so.0
----
------------------------------------
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/ts-7000/
<*> Your email settings:
Individual Email | Traditional
<*> To change settings online go to:
http://groups.yahoo.com/group/ts-7000/join
(Yahoo! ID required)
<*> To change settings via email:
<*> To unsubscribe from this group, send an email to:
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
/*
** @file test.cc
** @author Christian Gagneraud <>
** @date Fri Jan 23 11:03:20 2009
**
** @brief
**
** With oabi, the programm will bug, not with the eabi toolchain:
** arm-linux-g++ -DSHOW_BUG=1 -Wall -g -O2 test.cc -static -lpthread -o test
**
** Programs run OK with both oabi and eabi toochain:
** arm-linux-g++ -DSHOW_BUG=0 -Wall -g -O2 test.cc -static -lpthread -o test
*/
#include <iostream>
#include <iomanip>
#include <string>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <assert.h>
#define ASSERT(cmd) do { int rc = cmd; assert (rc == 0); } while (0)
pthread_attr_t attr_1;
pthread_t thread_1;
void* routine_1 (void* arg)
{
struct itimerval timer;
sigset_t timersigset;
int timersig = SIGALRM;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 200000; // 200 ms
timer.it_value = timer.it_interval;
ASSERT( sigemptyset(&timersigset) );
ASSERT( sigaddset(&timersigset, timersig) );
ASSERT( setitimer(ITIMER_REAL, &timer, NULL) );
struct timeval before, now;
ASSERT( gettimeofday (&before, NULL) );
while (true)
{
ASSERT( sigwait(&timersigset, &timersig) );
assert (timersig == SIGALRM);
ASSERT( gettimeofday (&now, NULL) );
std::cout << std::setw(6)
<< ((now.tv_usec > before.tv_usec) ? (now.tv_usec -
before.tv_usec) : (1000000L + now.tv_usec - before.tv_usec))
<< " abcdefghijklmnopqrstuvwxyz" << std::endl;
before = now;
}
return NULL;
}
pthread_attr_t attr_2;
pthread_t thread_2;
void* routine_2 (void* arg)
{
while (true)
{
std::string str;
// The more we have to print on the screen, the more likely the
// bug will show
for (int i=0; i<5; ++i)
str += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::cout << str << std::endl;
#ifdef SLEEP_MS
// nanosleep () has the advantage of not affecting any signals
// Here we sleep for between 1 and SLEEP_MS ms
// The less we sleep here the sooner the bug will show...
struct timespec tm;
tm.tv_sec = 0;
tm.tv_nsec = 1000*1000*(1 + (int) (SLEEP_MS * 1.0 * (rand() / (RAND_MAX +
1.0))));
int rc = nanosleep (&tm, NULL);
if (rc != 0 && errno != EINTR)
std::cout << "ERROR: " << rc << " " << errno
<< " " << tm.tv_sec << "." << tm.tv_nsec << std::endl;
#endif
}
}
void create_thread (pthread_t * p_thread, pthread_attr_t *p_attr,
void* (*routine)(void*),
int sched_policy = SCHED_OTHER,
int sched_priority = sched_get_priority_min(SCHED_OTHER))
{
ASSERT( pthread_attr_init(p_attr) );
ASSERT( pthread_attr_setschedpolicy(p_attr, sched_policy) );
struct sched_param sparam;
sparam.sched_priority = sched_priority;
ASSERT( pthread_attr_setschedparam(p_attr, &sparam) );
ASSERT( pthread_create (p_thread, p_attr, routine, NULL) );
}
int main (int argc, char **argv)
{
// Threads will inherit our sigmask
sigset_t mask, oldmask;
sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
ASSERT( pthread_sigmask(SIG_BLOCK, &mask, &oldmask) );
#if SHOW_BUG
// Running with SCHED_FIFO will show the bug
create_thread(&thread_1, &attr_1, routine_1, SCHED_FIFO,
sched_get_priority_max(SCHED_FIFO)-2);
#else
create_thread(&thread_1, &attr_1, routine_1);
#endif
create_thread(&thread_2, &attr_2, routine_2);
// We'll be blocked forever here...
pthread_join (thread_1, NULL);
}
|