Прирост приложения :: поток зависает при блокировке мьютекса при компиляции для ARM, работающего на BeagleBone Black

В настоящее время я работаю над приложением C ++, которое отлично работает на моем ПК, и я хочу, чтобы оно работало на BeagleBone Black, на котором я уже установил Debian Wheezy.

Я кросс-компилирую с помощью ELDK v5.3 и qmake с моего компьютера (Intel Celeron, Debian Wheezy, boost v1.49.0-3.2) на BeagleBone Black (ARM Cortex A8, Debian Wheezy, boost v1.49.0-3.2).

Все работает, как должно, но время от времени мое приложение зависает (зависает на __pthread_mutex_lock), когда создается boost :: thread или приложение ожидает boost :: thread :: join (). Я просто хочу понять, что происходит.

Если у вас есть несколько советов, которые помогут мне обеспечить безопасность этих вызовов для boost :: thread (try / catch, check error check …), пожалуйста, поделитесь ими 🙂

Спасибо !!

Вот небольшой исходный код, который замораживается аналогичным образом при выполнении на BeagleBone Black, за которым следует обратная трассировка, напечатанная при зависании приложения (GDB), и файл .pro, используемый при выполнении команды qmake:

#include <stdio.h>
#include <boost/thread.hpp>

#define NB_THREADS              20
#define THREAD_LIFE_DURATION    5

int g_nb_thread = 0;

boost::thread * subRegisterThread(boost::thread * pthread)
{
printf("Register thread #%d  %p created\n",
g_nb_thread++, pthread);

return pthread;
}

/////////////////// Sub dummy class

class sub_dummy_class
{
public:
boost::thread *mThread;

sub_dummy_class();
~sub_dummy_class();
void loop();
void start();
};sub_dummy_class::sub_dummy_class()
{
mThread = NULL;
}

sub_dummy_class::~sub_dummy_class()
{
if(mThread)
{
mThread->join();
}
}

void sub_dummy_class::start()
{
mThread = subRegisterThread(new boost::thread(boost::bind(&sub_dummy_class::loop, this)));
}

void sub_dummy_class::loop()
{
int life_duration = THREAD_LIFE_DURATION;
while(life_duration > 0)
{
life_duration--;
printf("Got %d seconds to live !\n", life_duration);
usleep(1000000);
}
return;
}////////////////////////// Dummy class

class dummy_class
{
public:

sub_dummy_class dummies[NB_THREADS];

dummy_class();
~dummy_class();
void start();};

dummy_class::dummy_class()
{

}

dummy_class::~dummy_class()
{

}

void dummy_class::start()
{
for(int i = 0 ; i < NB_THREADS ; i++)
{
dummies[i].start();
}
}int main(int argc, char* argv[])
{
printf("Starting program\n");

printf("Creating dummy class\n");
dummy_class *DC = new dummy_class();

printf("Starting dummy class\n");
DC->start();

printf("Deleting dummy class\n");
delete DC;

return 0;
}

Трассировки стека :

(gdb) bt
#0  __libc_do_syscall () at ../ports/sysdeps/unix/sysv/linux/arm/eabi/libc-do-syscall.S:44
#1  0xb6756f92 in __lll_lock_wait (futex=0x1881c, private=0) at ../ports/sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.c:47
#2  0xb675357a in __pthread_mutex_lock (mutex=0x1881c) at pthread_mutex_lock.c:61
#3  0xb68029dc in pthread_mutex_lock (mutex=<optimized out>) at forward.c:182
#4  0xb6991710 in lock (this=0xb69a2c68) at ./boost/smart_ptr/detail/spinlock_pt.hpp:41
#5  scoped_lock (pv=0x1f714, this=<synthetic pointer>) at ./boost/smart_ptr/detail/spinlock_pool.hpp:65
#6  atomic_increment (pw=0x1f714) at ./boost/smart_ptr/detail/sp_counted_base_spin.hpp:41
#7  add_ref_copy (this=0x1f710) at ./boost/smart_ptr/detail/sp_counted_base_spin.hpp:90
#8  shared_count (r=..., this=<optimized out>) at ./boost/smart_ptr/detail/shared_count.hpp:316
#9  shared_ptr (this=<optimized out>) at ./boost/smart_ptr/shared_ptr.hpp:164
#10 operator= (r=..., this=0x1f604) at ./boost/smart_ptr/shared_ptr.hpp:311
#11 boost::thread::start_thread (this=0x1f5e8) at libs/thread/src/pthread/thread.cpp:185
#12 0x0000cf7c in boost::thread::thread<boost::_bi::bind_t<void, boost::_mfi::mf0<void, sub_dummy_class>, boost::_bi::list1<boost::_bi::value<sub_dummy_class*> > > > (this=0x1f5e8, f=...)
at /opt/eldk-5.3/armv7a-hf/sysroots/armv7ahf-vfp-neon-linux-gnueabi/usr/include/boost/thread/detail/thread.hpp:205
#13 0x0000aa44 in sub_dummy_class::start (this=0x1cfdc) at main.cpp:51
#14 0x0000abc4 in dummy_class::start (this=0x1cf90) at main.cpp:96
#15 0x0000ac44 in main (argc=1, argv=0xbefff834) at main.cpp:109

РЕДАКТИРОВАТЬ: Вот файл .pro, который я использую для команды qmake (qmake -spec linux-armv7a-hf-g ++):

# .pro for test_boost
TEMPLATE = app
CONFIG =

QT -= qt webkit

TARGET = test_boost_ARM
QMAKE_LFLAGS += -Wl,-rpath ./
QMAKE_LFLAGS_RPATH =

HEADERS =
SOURCES = main.cpp

OTHER_FILES =

DESTDIR = .

# external libs
LIBS += -lboost_thread

Я немного протестировал эти два параметра. Когда NB_THREADS = 15, кажется, что он каждый раз работает нормально, но когда он равен 16, он часто зависает. THREAD_LIFE_DURATION, похоже, не влияет на поведение программы. Я надеюсь, что это поможет кому-то понять, что происходит.

3

Решение

Похоже, что обновление boost до версии 1.54 устраняет проблему. Потребовалось некоторое время, чтобы получить нужные пакеты, потому что стабильная версия Debian Wheezy — 1.49, поэтому мне пришлось вручную обновить платформу кросс-компиляции.

Теперь приложение может без проблем запускать до 380 потоков, для меня этого более чем достаточно.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector