From 1bdee77d67b26cb8137d750b755c77195b7cbac1 Mon Sep 17 00:00:00 2001 From: khizmax Date: Thu, 21 May 2015 08:58:10 +0300 Subject: [PATCH] Removed TSan annotations, tuned memory ordering --- cds/container/details/skip_list_base.h | 6 -- cds/details/allocator.h | 67 +------------------ cds/gc/impl/dhp_decl.h | 12 ++-- cds/gc/impl/hp_decl.h | 12 ++-- cds/intrusive/details/split_list_base.h | 2 - cds/intrusive/impl/michael_list.h | 15 ++--- cds/intrusive/lazy_list_rcu.h | 41 ++++++++---- cds/intrusive/split_list_rcu.h | 9 --- cds/memory/michael/allocator.h | 10 --- cds/urcu/details/base.h | 10 +-- cds/urcu/details/gpb.h | 4 -- cds/urcu/details/gpi.h | 9 ++- cds/urcu/details/gpt.h | 2 - cds/urcu/details/sig_buffered.h | 4 -- cds/urcu/details/sig_threaded.h | 2 - cds/urcu/dispose_thread.h | 2 - tests/cppunit/thread.cpp | 4 -- tests/unit/ellen_bintree_update_desc_pool.h | 2 - .../queue/intrusive_queue_reader_writer.cpp | 2 - tests/unit/stack/stack_intrusive_pushpop.cpp | 2 - tools/tsan-suppression | 4 ++ 21 files changed, 61 insertions(+), 160 deletions(-) create mode 100644 tools/tsan-suppression diff --git a/cds/container/details/skip_list_base.h b/cds/container/details/skip_list_base.h index ed309c52..e11ec367 100644 --- a/cds/container/details/skip_list_base.h +++ b/cds/container/details/skip_list_base.h @@ -171,23 +171,19 @@ namespace cds { namespace container { template node_type * New( unsigned int nHeight, Q const& v ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; unsigned char * pMem = alloc_space( nHeight ); node_type * p = new( pMem ) node_type( nHeight, nHeight > 1 ? reinterpret_cast(pMem + c_nNodeSize) : nullptr, v ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; return p; } template node_type * New( unsigned int nHeight, Args&&... args ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; unsigned char * pMem = alloc_space( nHeight ); node_type * p = new( pMem ) node_type( nHeight, nHeight > 1 ? reinterpret_cast(pMem + c_nNodeSize) : nullptr, std::forward(args)... ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; return p; } @@ -197,9 +193,7 @@ namespace cds { namespace container { unsigned int nHeight = p->height(); node_allocator_type().destroy( p ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; free_space( reinterpret_cast(p), nHeight ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; } }; diff --git a/cds/details/allocator.h b/cds/details/allocator.h index cbc634c0..0b8b36f5 100644 --- a/cds/details/allocator.h +++ b/cds/details/allocator.h @@ -42,52 +42,20 @@ namespace cds { template value_type * New( S const&... src ) { -# if CDS_THREAD_SANITIZER_ENABLED - if ( c_bStdAllocator ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; - } - value_type * pv = Construct( allocator_type::allocate(1), src... ); - if ( c_bStdAllocator ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; - } - return pv; -# else return Construct( allocator_type::allocate(1), src... ); -# endif } /// Analogue of operator new T( std::forward(args)... ) (move semantics) template value_type * MoveNew( Args&&... args ) { -# if CDS_THREAD_SANITIZER_ENABLED - if ( c_bStdAllocator ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; - } - value_type * pv = MoveConstruct( allocator_type::allocate(1), std::forward(args)... ); - if ( c_bStdAllocator ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; - } - return pv; -# else return MoveConstruct( allocator_type::allocate(1), std::forward(args)... ); -# endif } /// Analogue of operator new T[\p nCount ] value_type * NewArray( size_t nCount ) { -# if CDS_THREAD_SANITIZER_ENABLED - if ( c_bStdAllocator ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; - } -# endif value_type * p = allocator_type::allocate( nCount ); -# if CDS_THREAD_SANITIZER_ENABLED - if ( c_bStdAllocator ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; - } -# endif for ( size_t i = 0; i < nCount; ++i ) Construct( p + i ); return p; @@ -100,17 +68,7 @@ namespace cds { template value_type * NewArray( size_t nCount, S const& src ) { -# if CDS_THREAD_SANITIZER_ENABLED - if ( c_bStdAllocator ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; - } -# endif value_type * p = allocator_type::allocate( nCount ); -# if CDS_THREAD_SANITIZER_ENABLED - if ( c_bStdAllocator ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; - } -# endif for ( size_t i = 0; i < nCount; ++i ) Construct( p + i, src ); return p; @@ -140,22 +98,16 @@ namespace cds { /// Analogue of operator delete void Delete( value_type * p ) { - // TSan false positive possible - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; allocator_type::destroy( p ); allocator_type::deallocate( p, 1 ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; } /// Analogue of operator delete [] void Delete( value_type * p, size_t nCount ) { - // TSan false positive possible - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; for ( size_t i = 0; i < nCount; ++i ) allocator_type::destroy( p + i ); allocator_type::deallocate( p, nCount ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; } # if CDS_COMPILER == CDS_COMPILER_INTEL @@ -170,10 +122,7 @@ namespace cds { template value_type * Construct( void * p, S const&... src ) { - // TSan false positive possible - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; value_type * pv = new( p ) value_type( src... ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; return pv; } @@ -181,10 +130,7 @@ namespace cds { template value_type * MoveConstruct( void * p, Args&&... args ) { - // TSan false positive possible - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; value_type * pv = new( p ) value_type( std::forward(args)... ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; return pv; } @@ -202,18 +148,7 @@ namespace cds { size_t const nPtrSize = ( nByteSize + sizeof(void *) - 1 ) / sizeof(void *); typedef typename allocator_type::template rebind< void * >::other void_allocator; -# if CDS_THREAD_SANITIZER_ENABLED - if ( c_bStdAllocator ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; - } -# endif - void * p = void_allocator().allocate( nPtrSize ); -# if CDS_THREAD_SANITIZER_ENABLED - if ( c_bStdAllocator ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; - } -# endif - return p; + return void_allocator().allocate( nPtrSize ); } //@endcond }; diff --git a/cds/gc/impl/dhp_decl.h b/cds/gc/impl/dhp_decl.h index 4b88ace1..b0bde8f0 100644 --- a/cds/gc/impl/dhp_decl.h +++ b/cds/gc/impl/dhp_decl.h @@ -140,7 +140,7 @@ namespace cds { namespace gc { template T protect( atomics::atomic const& toGuard ) { - T pCur = toGuard.load(atomics::memory_order_relaxed); + T pCur = toGuard.load(atomics::memory_order_acquire); T pRet; do { pRet = assign( pCur ); @@ -169,7 +169,7 @@ namespace cds { namespace gc { template T protect( atomics::atomic const& toGuard, Func f ) { - T pCur = toGuard.load(atomics::memory_order_relaxed); + T pCur = toGuard.load(atomics::memory_order_acquire); T pRet; do { pRet = pCur; @@ -282,8 +282,8 @@ namespace cds { namespace gc { { T pRet; do { - pRet = assign( nIndex, toGuard.load(atomics::memory_order_relaxed) ); - } while ( pRet != toGuard.load(atomics::memory_order_acquire)); + pRet = assign( nIndex, toGuard.load(atomics::memory_order_acquire) ); + } while ( pRet != toGuard.load(atomics::memory_order_relaxed)); return pRet; } @@ -310,8 +310,8 @@ namespace cds { namespace gc { { T pRet; do { - assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_relaxed) )); - } while ( pRet != toGuard.load(atomics::memory_order_acquire)); + assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_acquire) )); + } while ( pRet != toGuard.load(atomics::memory_order_relaxed)); return pRet; } diff --git a/cds/gc/impl/hp_decl.h b/cds/gc/impl/hp_decl.h index 043006cf..302829cf 100644 --- a/cds/gc/impl/hp_decl.h +++ b/cds/gc/impl/hp_decl.h @@ -136,7 +136,7 @@ namespace cds { namespace gc { template T protect( atomics::atomic const& toGuard ) { - T pCur = toGuard.load(atomics::memory_order_relaxed); + T pCur = toGuard.load(atomics::memory_order_acquire); T pRet; do { pRet = assign( pCur ); @@ -165,7 +165,7 @@ namespace cds { namespace gc { template T protect( atomics::atomic const& toGuard, Func f ) { - T pCur = toGuard.load(atomics::memory_order_relaxed); + T pCur = toGuard.load(atomics::memory_order_acquire); T pRet; do { pRet = pCur; @@ -276,8 +276,8 @@ namespace cds { namespace gc { { T pRet; do { - pRet = assign( nIndex, toGuard.load(atomics::memory_order_relaxed) ); - } while ( pRet != toGuard.load(atomics::memory_order_acquire)); + pRet = assign( nIndex, toGuard.load(atomics::memory_order_acquire) ); + } while ( pRet != toGuard.load(atomics::memory_order_relaxed)); return pRet; } @@ -304,8 +304,8 @@ namespace cds { namespace gc { { T pRet; do { - assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_relaxed) )); - } while ( pRet != toGuard.load(atomics::memory_order_acquire)); + assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_acquire) )); + } while ( pRet != toGuard.load(atomics::memory_order_relaxed)); return pRet; } diff --git a/cds/intrusive/details/split_list_base.h b/cds/intrusive/details/split_list_base.h index 494ea363..94e11ca3 100644 --- a/cds/intrusive/details/split_list_base.h +++ b/cds/intrusive/details/split_list_base.h @@ -712,11 +712,9 @@ namespace cds { namespace intrusive { { splitlist_node_type * p = static_cast( node_traits::to_node_ptr( v )); if ( p->is_dummy() ) { - CDS_TSAN_ANNOTATE_HAPPENS_BEFORE( p ); dummy_node_disposer()( p ); } else { - CDS_TSAN_ANNOTATE_HAPPENS_BEFORE( v ); native_disposer()( v ); } } diff --git a/cds/intrusive/impl/michael_list.h b/cds/intrusive/impl/michael_list.h index b49bb64b..97023f6d 100644 --- a/cds/intrusive/impl/michael_list.h +++ b/cds/intrusive/impl/michael_list.h @@ -223,10 +223,8 @@ namespace cds { namespace intrusive { struct clean_disposer { void operator()( value_type * p ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; michael_list::node_cleaner()( node_traits::to_node_ptr( p ) ); disposer()( p ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; } }; //@endcond @@ -256,7 +254,7 @@ namespace cds { namespace intrusive { // Mark the node (logical deleting) marked_node_ptr next(pos.pNext, 0); - if ( pos.pCur->m_pNext.compare_exchange_strong( next, marked_node_ptr(pos.pNext, 1), memory_model::memory_order_release, atomics::memory_order_relaxed )) { + if ( pos.pCur->m_pNext.compare_exchange_strong( next, marked_node_ptr(pos.pNext, 1), memory_model::memory_order_acq_rel, atomics::memory_order_relaxed )) { // physical deletion may be performed by search function if it detects that a node is logically deleted (marked) // CAS may be successful here or in other thread that searching something marked_node_ptr cur(pos.pCur); @@ -1071,9 +1069,9 @@ try_again: pPrev = &refHead; pNext = nullptr; - pCur = pPrev->load(memory_model::memory_order_relaxed); + pCur = pPrev->load(memory_model::memory_order_acquire); pos.guards.assign( position::guard_current_item, node_traits::to_value_ptr( pCur.ptr() ) ); - if ( pPrev->load(memory_model::memory_order_acquire) != pCur.ptr() ) + if ( pPrev->load(memory_model::memory_order_relaxed) != pCur.ptr() ) goto try_again; while ( true ) { @@ -1084,15 +1082,14 @@ try_again: return false; } - pNext = pCur->m_pNext.load(memory_model::memory_order_relaxed); - CDS_TSAN_ANNOTATE_HAPPENS_AFTER( pNext.ptr() ); + pNext = pCur->m_pNext.load(memory_model::memory_order_acquire); pos.guards.assign( position::guard_next_item, node_traits::to_value_ptr( pNext.ptr() )); - if ( pCur->m_pNext.load(memory_model::memory_order_acquire).all() != pNext.all() ) { + if ( pCur->m_pNext.load(memory_model::memory_order_relaxed).all() != pNext.all() ) { bkoff(); goto try_again; } - if ( pPrev->load(memory_model::memory_order_acquire).all() != pCur.ptr() ) { + if ( pPrev->load(memory_model::memory_order_relaxed).all() != pCur.ptr() ) { bkoff(); goto try_again; } diff --git a/cds/intrusive/lazy_list_rcu.h b/cds/intrusive/lazy_list_rcu.h index a62cf157..bd76c694 100644 --- a/cds/intrusive/lazy_list_rcu.h +++ b/cds/intrusive/lazy_list_rcu.h @@ -846,13 +846,21 @@ namespace cds { namespace intrusive { return insert_at( pHead, *node_traits::to_value_ptr( pNode ) ); } - bool insert_at( node_type * pHead, value_type& val, bool bLock = true ) + bool insert_at( node_type * pHead, value_type& val ) { + rcu_lock l; + return insert_at_locked( pHead, val ); + } + + bool insert_at_locked( node_type * pHead, value_type& val ) + { + // RCU lock should be locked!!! + assert( gc::is_locked() ); + link_checker::is_empty( node_traits::to_node_ptr( val ) ); position pos; key_comparator cmp; - rcu_lock l( bLock ); while ( true ) { search( pHead, val, pos ); { @@ -900,22 +908,31 @@ namespace cds { namespace intrusive { } } - iterator insert_at_( node_type * pHead, value_type& val, bool bLock = true ) + iterator insert_at_( node_type * pHead, value_type& val ) { - rcu_lock l( bLock ); - if ( insert_at( pHead, val, false )) + rcu_lock l; + if ( insert_at_locked( pHead, val )) return iterator( node_traits::to_node_ptr( val )); return end(); } template - std::pair ensure_at_( node_type * pHead, value_type& val, Func func, bool bLock = true ) + std::pair ensure_at_( node_type * pHead, value_type& val, Func func ) + { + rcu_lock l; + return ensure_at_locked( pHead, val, func ); + } + + template + std::pair ensure_at_locked( node_type * pHead, value_type& val, Func func ) { + // RCU lock should be locked!!! + assert( gc::is_locked() ); + position pos; key_comparator cmp; - rcu_lock l( bLock ); while ( true ) { search( pHead, val, pos ); { @@ -942,10 +959,10 @@ namespace cds { namespace intrusive { } template - std::pair ensure_at( node_type * pHead, value_type& val, Func func, bool bLock = true ) + std::pair ensure_at( node_type * pHead, value_type& val, Func func ) { - rcu_lock l( bLock ); - std::pair ret = ensure_at_( pHead, val, func, false ); + rcu_lock l; + std::pair ret = ensure_at_locked( pHead, val, func ); return std::make_pair( ret.first != end(), ret.second ); } @@ -1072,11 +1089,11 @@ namespace cds { namespace intrusive { } template - bool find_at( node_type * pHead, Q& val, Compare cmp, Func f, bool bLock = true ) const + bool find_at( node_type * pHead, Q& val, Compare cmp, Func f ) const { position pos; - rcu_lock l( bLock ); + rcu_lock l; search( pHead, val, pos, cmp ); if ( pos.pCur != &m_Tail ) { std::unique_lock< typename node_type::lock_type> al( pos.pCur->m_Lock ); diff --git a/cds/intrusive/split_list_rcu.h b/cds/intrusive/split_list_rcu.h index 7c8618f7..3ba40492 100644 --- a/cds/intrusive/split_list_rcu.h +++ b/cds/intrusive/split_list_rcu.h @@ -519,10 +519,7 @@ namespace cds { namespace intrusive { dummy_node_type * pHead = get_bucket( nHash ); assert( pHead != nullptr ); - // TSan false positive: hash is read-only, will be ordered when we insert a node - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; node_traits::to_node_ptr( val )->m_nHash = split_list::regular_hash( nHash ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; if ( m_List.insert_at( pHead, val )) { inc_item_count(); @@ -561,10 +558,7 @@ namespace cds { namespace intrusive { dummy_node_type * pHead = get_bucket( nHash ); assert( pHead != nullptr ); - // TSan false positive: hash is read-only, will be ordered when we insert a node - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; node_traits::to_node_ptr( val )->m_nHash = split_list::regular_hash( nHash ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; if ( m_List.insert_at( pHead, val, f )) { inc_item_count(); @@ -609,10 +603,7 @@ namespace cds { namespace intrusive { dummy_node_type * pHead = get_bucket( nHash ); assert( pHead != nullptr ); - // TSan false positive: hash is read-only, will be ordered when we insert a node - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; node_traits::to_node_ptr( val )->m_nHash = split_list::regular_hash( nHash ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; std::pair bRet = m_List.ensure_at( pHead, val, func ); if ( bRet.first && bRet.second ) { diff --git a/cds/memory/michael/allocator.h b/cds/memory/michael/allocator.h index c4336d7a..0366e55a 100644 --- a/cds/memory/michael/allocator.h +++ b/cds/memory/michael/allocator.h @@ -60,17 +60,13 @@ namespace michael { /// Allocates memory block of \p nSize bytes (\p malloc wrapper) static void * alloc( size_t nSize ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; void * p = ::malloc( nSize ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; return p; } /// Returning memory block to the system (\p free wrapper) static void free( void * p ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; ::free( p ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; } }; @@ -1226,10 +1222,8 @@ namespace michael { newAnchor = oldAnchor = pDesc->anchor.load(atomics::memory_order_acquire); assert( oldAnchor.avail < pDesc->nCapacity ); - CDS_TSAN_ANNOTATE_IGNORE_READS_BEGIN; pAddr = pDesc->pSB + oldAnchor.avail * (unsigned long long) pDesc->nBlockSize; newAnchor.avail = reinterpret_cast( pAddr )->nNextFree; - CDS_TSAN_ANNOTATE_IGNORE_READS_END; newAnchor.tag += 1; if ( oldActive.credits() == 0 ) { @@ -1310,10 +1304,8 @@ namespace michael { newAnchor = oldAnchor = pDesc->anchor.load(atomics::memory_order_acquire); assert( oldAnchor.avail < pDesc->nCapacity ); - CDS_TSAN_ANNOTATE_IGNORE_READS_BEGIN; pAddr = pDesc->pSB + oldAnchor.avail * pDesc->nBlockSize; newAnchor.avail = reinterpret_cast( pAddr )->nNextFree; - CDS_TSAN_ANNOTATE_IGNORE_READS_END; ++newAnchor.tag; } while ( !pDesc->anchor.compare_exchange_strong(oldAnchor, newAnchor, atomics::memory_order_release, atomics::memory_order_relaxed) ); @@ -1350,13 +1342,11 @@ namespace michael { byte * pEnd = pDesc->pSB + pDesc->nCapacity * pDesc->nBlockSize; unsigned int nNext = 0; const unsigned int nBlockSize = pDesc->nBlockSize; - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; for ( byte * p = pDesc->pSB; p < pEnd; p += nBlockSize ) { reinterpret_cast( p )->set( pDesc, 0 ); reinterpret_cast( p )->nNextFree = ++nNext; } reinterpret_cast( pEnd - nBlockSize )->nNextFree = 0; - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; active_tag newActive; newActive.set( pDesc, ( (pDesc->nCapacity - 1 < active_tag::c_nMaxCredits) ? pDesc->nCapacity - 1 : active_tag::c_nMaxCredits ) - 1 ); diff --git a/cds/urcu/details/base.h b/cds/urcu/details/base.h index 37864bd7..76420833 100644 --- a/cds/urcu/details/base.h +++ b/cds/urcu/details/base.h @@ -407,19 +407,15 @@ namespace cds { typedef ThreadGC thread_gc; typedef typename thread_gc::rcu_tag rcu_tag; - bool m_bLocked; public: - scoped_lock(bool bLock = true) - : m_bLocked( bLock ) + scoped_lock() { - if ( bLock ) - thread_gc::access_lock(); + thread_gc::access_lock(); } ~scoped_lock() { - if ( m_bLocked ) - thread_gc::access_unlock(); + thread_gc::access_unlock(); } }; //@endcond diff --git a/cds/urcu/details/gpb.h b/cds/urcu/details/gpb.h index 023c2638..229aded8 100644 --- a/cds/urcu/details/gpb.h +++ b/cds/urcu/details/gpb.h @@ -108,9 +108,7 @@ namespace cds { namespace urcu { epoch_retired_ptr p; while ( m_Buffer.pop( p )) { if ( p.m_nEpoch <= nEpoch ) { - CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN; p.free(); - CDS_TSAN_ANNOTATE_IGNORE_RW_END; } else { push_buffer( p ); @@ -126,9 +124,7 @@ namespace cds { namespace urcu { if ( !bPushed || m_Buffer.size() >= capacity() ) { synchronize(); if ( !bPushed ) { - CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN; ep.free(); - CDS_TSAN_ANNOTATE_IGNORE_RW_END; } return true; } diff --git a/cds/urcu/details/gpi.h b/cds/urcu/details/gpi.h index 783a3064..1e5426ba 100644 --- a/cds/urcu/details/gpi.h +++ b/cds/urcu/details/gpi.h @@ -112,9 +112,9 @@ namespace cds { namespace urcu { { synchronize(); if ( p.m_p ) { - CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN; + // TSan ignores atomic_thread_fence in synchronize() + //CDS_TSAN_ANNOTATE_HAPPENS_BEFORE( p.m_p ); p.free(); - CDS_TSAN_ANNOTATE_IGNORE_RW_END; } } @@ -127,8 +127,11 @@ namespace cds { namespace urcu { while ( itFirst != itLast ) { retired_ptr p( *itFirst ); ++itFirst; - if ( p.m_p ) + if ( p.m_p ) { + // TSan ignores atomic_thread_fence in synchronize() + //CDS_TSAN_ANNOTATE_HAPPENS_BEFORE( p.m_p ); p.free(); + } } } } diff --git a/cds/urcu/details/gpt.h b/cds/urcu/details/gpt.h index 84d2c1a8..30bb1ebb 100644 --- a/cds/urcu/details/gpt.h +++ b/cds/urcu/details/gpt.h @@ -114,9 +114,7 @@ namespace cds { namespace urcu { if ( !bPushed || m_Buffer.size() >= capacity() ) { synchronize(); if ( !bPushed ) { - CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN; p.free(); - CDS_TSAN_ANNOTATE_IGNORE_RW_END; } return true; } diff --git a/cds/urcu/details/sig_buffered.h b/cds/urcu/details/sig_buffered.h index bb0e0c5d..874092ea 100644 --- a/cds/urcu/details/sig_buffered.h +++ b/cds/urcu/details/sig_buffered.h @@ -105,9 +105,7 @@ namespace cds { namespace urcu { epoch_retired_ptr p; while ( m_Buffer.pop( p )) { if ( p.m_nEpoch <= nEpoch ) { - CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN; p.free(); - CDS_TSAN_ANNOTATE_IGNORE_RW_END; } else { push_buffer( p ); @@ -122,9 +120,7 @@ namespace cds { namespace urcu { if ( !bPushed || m_Buffer.size() >= capacity() ) { synchronize(); if ( !bPushed ) { - CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN; ep.free(); - CDS_TSAN_ANNOTATE_IGNORE_RW_END; } return true; } diff --git a/cds/urcu/details/sig_threaded.h b/cds/urcu/details/sig_threaded.h index 17d01525..ffc8b490 100644 --- a/cds/urcu/details/sig_threaded.h +++ b/cds/urcu/details/sig_threaded.h @@ -111,9 +111,7 @@ namespace cds { namespace urcu { if ( !bPushed || m_Buffer.size() >= capacity() ) { synchronize(); if ( !bPushed ) { - CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN; p.free(); - CDS_TSAN_ANNOTATE_IGNORE_RW_END; } return true; } diff --git a/cds/urcu/dispose_thread.h b/cds/urcu/dispose_thread.h index 46baa8fa..553a4d6b 100644 --- a/cds/urcu/dispose_thread.h +++ b/cds/urcu/dispose_thread.h @@ -103,9 +103,7 @@ namespace cds { namespace urcu { epoch_retired_ptr p; while ( pBuf->pop( p ) ) { if ( p.m_nEpoch <= nCurEpoch ) { - CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN; p.free(); - CDS_TSAN_ANNOTATE_IGNORE_RW_END; } else { pBuf->push( p ); diff --git a/tests/cppunit/thread.cpp b/tests/cppunit/thread.cpp index bac98015..69f8e862 100644 --- a/tests/cppunit/thread.cpp +++ b/tests/cppunit/thread.cpp @@ -43,16 +43,12 @@ namespace CppUnitMini { ThreadPool::~ThreadPool() { - CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN; - delete m_pBarrierStart; delete m_pBarrierDone; for ( size_t i = 0; i < m_arrThreads.size(); ++i ) delete m_arrThreads[i]; m_arrThreads.resize( 0 ); - - CDS_TSAN_ANNOTATE_IGNORE_RW_END; } void ThreadPool::add( TestThread * pThread, size_t nCount ) diff --git a/tests/unit/ellen_bintree_update_desc_pool.h b/tests/unit/ellen_bintree_update_desc_pool.h index e8158e9f..f5fec302 100644 --- a/tests/unit/ellen_bintree_update_desc_pool.h +++ b/tests/unit/ellen_bintree_update_desc_pool.h @@ -87,9 +87,7 @@ namespace ellen_bintree_pool { T * allocate( size_t n, void const * pHint = nullptr ) { internal_node_counter::onAlloc(); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; T * p = base_class::allocate( n, pHint ); - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; return p; } diff --git a/tests/unit/queue/intrusive_queue_reader_writer.cpp b/tests/unit/queue/intrusive_queue_reader_writer.cpp index a4f0e734..b5ad38c4 100644 --- a/tests/unit/queue/intrusive_queue_reader_writer.cpp +++ b/tests/unit/queue/intrusive_queue_reader_writer.cpp @@ -168,14 +168,12 @@ namespace queue { while ( true ) { typename Queue::value_type * p = m_Queue.pop(); if ( p ) { - CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN; p->nConsumer = m_nThreadNo; ++m_nPopped; if ( p->nWriterNo < nTotalWriters ) m_WriterData[ p->nWriterNo ].push_back( p->nNo ); else ++m_nBadWriter; - CDS_TSAN_ANNOTATE_IGNORE_RW_END; } else { ++m_nPopEmpty; diff --git a/tests/unit/stack/stack_intrusive_pushpop.cpp b/tests/unit/stack/stack_intrusive_pushpop.cpp index 2ed56cd9..4369bf1c 100644 --- a/tests/unit/stack/stack_intrusive_pushpop.cpp +++ b/tests/unit/stack/stack_intrusive_pushpop.cpp @@ -149,14 +149,12 @@ namespace istack { while ( !(getTest().m_nWorkingProducers.load(atomics::memory_order_acquire) == 0 && m_Stack.empty()) ) { typename Stack::value_type * p = m_Stack.pop(); if ( p ) { - CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN; p->nConsumer = m_nThreadNo; ++m_nPopCount; if ( p->nNo < sizeof(m_arrPop)/sizeof(m_arrPop[0]) ) ++m_arrPop[p->nNo]; else ++m_nDirtyPop; - CDS_TSAN_ANNOTATE_IGNORE_WRITES_END; } else ++m_nPopEmpty; diff --git a/tools/tsan-suppression b/tools/tsan-suppression new file mode 100644 index 00000000..ba02f0cd --- /dev/null +++ b/tools/tsan-suppression @@ -0,0 +1,4 @@ + + +# Boost race [?] in test framework. Do not affect to libcds +race:CppUnitMini::ThreadPool::~ThreadPool -- 2.34.1