From 2b8cb650ccd2f3a93846ab4829fdca030bd3272c Mon Sep 17 00:00:00 2001
From: khizmax <libcds.dev@gmail.com>
Date: Wed, 29 Apr 2015 00:12:17 +0300
Subject: [PATCH] Fixed TSan warnings in SplitList

---
 cds/compiler/feature_tsan.h             |  4 ++--
 cds/container/split_list_set_rcu.h      | 12 ++++++++++--
 cds/intrusive/details/split_list_base.h |  8 ++++++--
 cds/intrusive/impl/michael_list.h       |  7 +++++--
 cds/intrusive/split_list_rcu.h          |  7 ++++++-
 5 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/cds/compiler/feature_tsan.h b/cds/compiler/feature_tsan.h
index 926876ad..cecbadc5 100644
--- a/cds/compiler/feature_tsan.h
+++ b/cds/compiler/feature_tsan.h
@@ -7,8 +7,8 @@
 // From https://groups.google.com/d/msg/thread-sanitizer/SsrHB7FTnTk/mNTGNLQj-9cJ
 
 #ifdef CDS_THREAD_SANITIZER_ENABLED
-#   define CDS_TSAN_ANNOTATE_HAPPENS_BEFORE(addr)   AnnotateHappensBefore(__FILE__, __LINE__, (void*)(addr))
-#   define CDS_TSAN_ANNOTATE_HAPPENS_AFTER(addr)    AnnotateHappensAfter(__FILE__, __LINE__, (void*)(addr))
+#   define CDS_TSAN_ANNOTATE_HAPPENS_BEFORE(addr)   AnnotateHappensBefore(__FILE__, __LINE__, reinterpret_cast<void*>(addr))
+#   define CDS_TSAN_ANNOTATE_HAPPENS_AFTER(addr)    AnnotateHappensAfter(__FILE__, __LINE__, reinterpret_cast<void*>(addr))
 
 #   define CDS_TSAN_ANNOTATE_IGNORE_READS_BEGIN     AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
 #   define CDS_TSAN_ANNOTATE_IGNORE_READS_END       AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
diff --git a/cds/container/split_list_set_rcu.h b/cds/container/split_list_set_rcu.h
index f6caeb73..7ad24be8 100644
--- a/cds/container/split_list_set_rcu.h
+++ b/cds/container/split_list_set_rcu.h
@@ -226,18 +226,26 @@ namespace cds { namespace container {
         template <typename Q>
         static node_type * alloc_node( Q const& v )
         {
-            return cxx_node_allocator().New( v );
+            CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
+            node_type * p = cxx_node_allocator().New( v );
+            CDS_TSAN_ANNOTATE_IGNORE_WRITES_END;
+            return p;
         }
 
         template <typename... Args>
         static node_type * alloc_node( Args&&... args )
         {
-            return cxx_node_allocator().MoveNew( std::forward<Args>(args)...);
+            CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
+            node_type * p = cxx_node_allocator().MoveNew( std::forward<Args>(args)...);
+            CDS_TSAN_ANNOTATE_IGNORE_WRITES_END;
+            return p;
         }
 
         static void free_node( node_type * pNode )
         {
+            CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
             cxx_node_allocator().Delete( pNode );
+            CDS_TSAN_ANNOTATE_IGNORE_WRITES_END;
         }
 
         struct node_disposer {
diff --git a/cds/intrusive/details/split_list_base.h b/cds/intrusive/details/split_list_base.h
index cddfb628..494ea363 100644
--- a/cds/intrusive/details/split_list_base.h
+++ b/cds/intrusive/details/split_list_base.h
@@ -711,10 +711,14 @@ namespace cds { namespace intrusive {
                     void operator()( value_type * v )
                     {
                         splitlist_node_type * p = static_cast<splitlist_node_type *>( node_traits::to_node_ptr( v ));
-                        if ( p->is_dummy() )
+                        if ( p->is_dummy() ) {
+                            CDS_TSAN_ANNOTATE_HAPPENS_BEFORE( p );
                             dummy_node_disposer<gc, typename traits::allocator>()( p );
-                        else
+                        }
+                        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 bbe9b134..b49bb64b 100644
--- a/cds/intrusive/impl/michael_list.h
+++ b/cds/intrusive/impl/michael_list.h
@@ -223,8 +223,10 @@ namespace cds { namespace intrusive {
         struct clean_disposer {
             void operator()( value_type * p )
             {
+                CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
                 michael_list::node_cleaner<gc, node_type, memory_model>()( node_traits::to_node_ptr( p ) );
                 disposer()( p );
+                CDS_TSAN_ANNOTATE_IGNORE_WRITES_END;
             }
         };
         //@endcond
@@ -1082,9 +1084,10 @@ try_again:
                     return false;
                 }
 
-                pNext = pCur->m_pNext.load(memory_model::memory_order_acquire);
+                pNext = pCur->m_pNext.load(memory_model::memory_order_relaxed);
+                CDS_TSAN_ANNOTATE_HAPPENS_AFTER( pNext.ptr() );
                 pos.guards.assign( position::guard_next_item, node_traits::to_value_ptr( pNext.ptr() ));
-                if ( pCur->m_pNext.load(memory_model::memory_order_relaxed).all() != pNext.all() ) {
+                if ( pCur->m_pNext.load(memory_model::memory_order_acquire).all() != pNext.all() ) {
                     bkoff();
                     goto try_again;
                 }
diff --git a/cds/intrusive/split_list_rcu.h b/cds/intrusive/split_list_rcu.h
index 3ba40492..0ef8a765 100644
--- a/cds/intrusive/split_list_rcu.h
+++ b/cds/intrusive/split_list_rcu.h
@@ -255,11 +255,16 @@ namespace cds { namespace intrusive {
         dummy_node_type * alloc_dummy_node( size_t nHash )
         {
             m_Stat.onHeadNodeAllocated();
-            return dummy_node_allocator().New( nHash );
+            CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
+            dummy_node_type * p = dummy_node_allocator().New( nHash );
+            CDS_TSAN_ANNOTATE_IGNORE_WRITES_END;
+            return p;
         }
         void free_dummy_node( dummy_node_type * p )
         {
+            CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
             dummy_node_allocator().Delete( p );
+            CDS_TSAN_ANNOTATE_IGNORE_WRITES_END;
             m_Stat.onHeadNodeFreed();
         }
 
-- 
2.34.1