Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

concurrent_vector push_back segfault


I'm working on parallelizing some open source code (SystemC) that is using std::vector
After replacing it with tbb::concurrent_vector, segfault occurs (deterministically, not a race condition).

Details follow.

System info (output of 'make info' of tbb):
OS: linux

I could not copy my Makefile here, simply because SystemC is a rather big project, using automake, etc. but I've already build it with some tbb constructs succesfully.

::tbb::concurrent_vector m_delta_events;

According to the eclipse call hierarchy command & gdb, the first time the member is accessed is in the following code:
sc_simcontext::add_delta_event( sc_event* e )
m_delta_events.push_back( e );
return ( m_delta_events.size() - 1 );

e is not null, however *e is not initialized.

The backtrace:
#0 0xb7796bdd in __TBB_machine_load_store::load_with_acquire (location=@0x6c) at ../../include/tbb/machine/linux_ia32.h:181
#1 0xb7796c05 in __TBB_machine_load_with_acquire (location=@0x6c) at ../../include/tbb/machine/linux_ia32.h:210
#2 0xb7797558 in tbb::internal::concurrent_vector_base_v3::helper::acquire_segment (v=@0x809e098, index=27, element_size=4, owner=false) at ../../src/tbb/concurrent_vector.cpp:117
#3 0xb77960a7 in tbb::internal::concurrent_vector_base_v3::internal_push_back (this=0x809e098, element_size=4, index=@0xbfcdabe0) at ../../src/tbb/concurrent_vector.cpp:422
#4 0x0804bdeb in tbb::concurrent_vector<:SC_EVENT> >::push_back (this=0x809e094, item=@0xbfcdac24) at /tmp/sdaniele/local/tbb30_20100310oss/include/tbb/concurrent_vector.h:660
#5 0x0804beb4 in sc_core::sc_simcontext::add_delta_event (this=0x809e058, e=0xbfcdad60) at /tmp/sdaniele/trunk/code/current/systemc-2.2.0/include/sysc/kernel/sc_simcontext.h:509
#6 0x08066e8f in sc_core::sc_event::notify_internal (this=0xbfcdad60, t=@0xbfcdad44) at ../../../../src/sysc/kernel/sc_event.h:244
#7 0x0806c87b in sc_clock (this=0xbfcdace8, name_=0x80839b3 "Clock_1", period_v_=1, period_tu_=sc_core::SC_MS, duty_cycle_=0.5) at ../../../../src/sysc/communication/sc_clock.cpp:152
#8 0x0804a6f1 in sc_main (argc=6, argv=0xbfcdaf84) at main.cpp:51
#9 0x0805362e in sc_elab_and_sim (argc=6, argv=0xbfcdaf84) at ../../../../src/sysc/kernel/sc_main_main.cpp:99
#10 0x08052e38 in main (argc=6, argv=0xbfcdaf84) at ../../../../src/sysc/kernel/sc_main.cpp:70

Thanks in advance,

Daniel Krikun
0 Kudos
1 Reply
Hi, it is hard to say why segfault happens without at least top-level scheme of how/where/when concurrent_vector is used, created, and destroyed. I guess some serial (not-thread-safe) method is used simultaneously with concurrent push_back(). It can be clear()/destruction, swap(), assign, and etc.

I also noticed another problem in your code:
m_delta_events.push_back( e );
return ( m_delta_events.size() - 1 );
It is not guaranteed that size() will return index of previously executed push_back(). 1) They are not synchronized. 2) size()-1 can return an index less than an index of the most recent inserted element (see why).
If you need an index of the element inserted by this push_back(), please use iterator returned by the call. E.g. index=my.push_back()-my.begin();
And if index would be used to access the element later, you might want to optimize out unnecessary address calculation in operator [] by using that iterator (or pointer) directly.