2

I'm building the code below using Visual Studio 2015 Preview (but I've had a similar issue with Visual Studio 2013, so it's not specific to 2015), and then running the program under Intel Inspector XE 2013 Update 9 (build 328075). Intel Inspector reports several data races in code, around the access to shared_ptr and its atomic contents. Intel Inspector is known to report false positive races, I just want to confirm that is the case indeed, and understand whether this is an issue in the Inspector or in the Microsoft STL implementation...

Here is the code, there are 2 threads, which concurrently and atomically modify a shared_ptr pointing to an atomic int, and one of the thread also prints dots (so you can observe the activity printed on console):

#include <memory>
#include <atomic>
#include <thread>
#include <iostream>

using namespace std;

int main()
{
    shared_ptr<atomic<int>> a;
    atomic_store(&a, make_shared<atomic<int>>(42));

    thread t1([&]
    {
        for (int i = 0; i < 1000000; i++)
        {
            auto ptr_copy = atomic_load(&a);
            if (*ptr_copy == 42)
                *ptr_copy = 0;
        }
    });

    thread t2([&]
    {
        for (int i = 0; i < 1000000; i++)
        {
            auto ptr_copy = atomic_load(&a);
            if (*ptr_copy == 0)
            {
                atomic_store(&a, make_shared<atomic<int>>(42));
                cout << ".";
            }
        }
    });

    t1.join();
    t2.join();
}

This is one of the data races reported, excerpt:

P1: Error: Data race
  Error X22: Write: Function operator()
  Code snippet:
   28              if (*ptr_copy == 0)
   29              {
  >30                  atomic_store(&a, make_shared<atomic<int>>(42));
   31                  cout << ".";
   32              }

  Error X23: Read: Function atomic_load_explicit<struct std::atomic<int> >
  Code snippet:
   1919      {    // load *_Ptr atomically
   1920      _Shared_ptr_spin_lock _Lock;
  >1921      shared_ptr<_Ty> _Result = *_Ptr;
   1922      return (_Result);
   1923      }

  Stack (1 of 1 instance(s))
  >AtomicSharedPtrRace1.exe!atomic_load_explicit<struct std::atomic<int> > - c:\program files (x86)\microsoft visual studio 14.0\vc\include\memory:1921
   AtomicSharedPtrRace1.exe!atomic_load<struct std::atomic<int> > - c:\program files (x86)\microsoft visual studio 14.0\vc\include\memory:1928
   AtomicSharedPtrRace1.exe!operator() - atomicsharedptrrace1.cpp:17

I suppose Intel Inspector does not recognize the shared_ptr internal spinlock as a synchronization mechanism...

Questions:

  1. Is the sample code above data-race-free according to the standard?
  2. If so, is the MS STL implementation of atomic_store/atomic_load standard-compliant? It ignores the memory order argument completely and seems to use a global spin lock, does it mean that it always enforces sequential consistency for memory operations and work as compiler barrier (even if I pass memory_order relaxed)?

    template <class _Ty> inline
        shared_ptr<_Ty> atomic_load_explicit(const shared_ptr<_Ty> *_Ptr,
            memory_order)
        {   // load *_Ptr atomically
        _Shared_ptr_spin_lock _Lock;
        shared_ptr<_Ty> _Result = *_Ptr;
        return (_Result);
        }
    
  3. Is this a problem with Microsoft's implementation, that the spinlock is not recognized by Intel Inspector, or is it a problem with Intel Inspector? I would like to find some workaround, I suspect that many other data races reported by Inspector in our code could be false positives as they are around the place where we use atomic_load and atomic_store. I know that atomic_load and atomic_store will likely be deprecated in future, but I'd like to sort out those false positives somehow until then...

Community
  • 1
  • 1
Massimiliano
  • 16,770
  • 10
  • 69
  • 112
  • 1. Yes, the code is conforming and data-race-free. 2. A compliant implementation can in general ignore memory ordering parameters in every case if it enforces sequentially consistent semantics, since `seq_cst` is strictly stronger than all other memory orderings. Doing so may affect performance, but not correctness. 3. I haven't examined `_Shared_ptr_spin_lock`, but I strongly suspect that the implementation is correct and that Inspector is reporting a false positive. – Casey Dec 09 '14 at 19:38

0 Answers0