This is to do with TSan instrumentation, see http://llvm.org/bugs/show_bug.cgi?id=22836
Details
Diff Detail
Event Timeline
OK, two questions:
- Are there means to evolve the ABI?
- There are always people who build their world from scratch. Is there a way to enable such a change conditionally?
__sync_add_and_fetch is lowered to atomicrmw add with seq_cst ordering, just like std::atomic<>::operator++. Same with __sync_add_and_fetch and std::atomic<>::operator-- and __sync_bool_compare_and_swap and std::atomic<>:: compare_exchange_strong
What is the functional difference here?
Every load of the counter is now atomic and that is both correct and pleasing to TSan.
Eg, as per the aforementioned bug report:
99 __shared_weak_count* 100 __shared_weak_count::lock() _NOEXCEPT 101 { 102 long object_owners = __shared_owners_; 103 while (object_owners != -1) 104 { 105 if (__sync_bool_compare_and_swap(&__shared_owners_, 106 object_owners, 107 object_owners+1)) 108 return this; 109 object_owners = __shared_owners_; 110 } 111 return 0; 112 }
Ah, so it is our crummy attempt at a relaxed load. Would the implementation be correct if we kept everything the same but used __atomic_load to do the loads of _shared_owners_?
Unfortunately I don't know whether that is going to be picked up by TSan. Could you ask in the bug please? (so that we avoid playing the broken telephone game).
P.S. I have anecdotal evidence that TSan is pacified with the full std::atomic annotations, but that is quite a different thing.
- Are there means to evolve the ABI?
I started a discussion about this a month or so ago, but it petered out w/o a conclusion.
There are users of libc++ for whom *any* ABI change is unacceptable.
There are also users of libc++ who (as you say), "build the world from scratch" regularly, for whom ABI change is a non-issue.
We need a scheme that satisfies the first group w/o limiting the second.
As for this change, would "fixing" the load on line #102 fix the observed problem?
I was recently corrected. The change for long to std::atomic<long> doesn't break the ABI because they are layout compatible and there is no constructor code.
However
- <atomic> only compiles with clang in c++11 mode and with some GCC versions. This restriction is somewhat artificial.
- This is a pessimization when the program is single threaded. Not much we can do about that at this point though.
Neither of these things should block the patch but we should be aware.
@mclow.lists This looks like a good reason to lift the restrictions on atomic.
I think a much safer change would be to use the __atomic_foo builtins. It means we wouldn't have to change the type stored in __shared_count and __shared_weak_count and we wouldn't depend on the <atomic> header.
Is there a reason this approach was not taken?
Yep, This patch was superseded by D10406 which has been committed. I'm going to go ahead and resign from this revision but it should be closed.