| Index: include/core/SkLazyPtr.h | 
| diff --git a/include/core/SkLazyPtr.h b/include/core/SkLazyPtr.h | 
| index 896dfbf88d762570545a9e5a7715aeeb795313e9..fb2e43e874681c1e993992ae891bae40561930a4 100644 | 
| --- a/include/core/SkLazyPtr.h | 
| +++ b/include/core/SkLazyPtr.h | 
| @@ -60,9 +60,7 @@ | 
|  | 
| // Everything below here is private implementation details.  Don't touch, don't even look. | 
|  | 
| -#include "SkDynamicAnnotations.h" | 
| -#include "SkThread.h" | 
| -#include "SkThreadPriv.h" | 
| +#include "SkAtomics.h" | 
|  | 
| // See FIXME below. | 
| class SkFontConfigInterfaceDirect; | 
| @@ -70,18 +68,21 @@ class SkFontConfigInterfaceDirect; | 
| namespace Private { | 
|  | 
| // Set *dst to ptr if *dst is NULL.  Returns value of *dst, destroying ptr if not swapped in. | 
| -// Issues the same memory barriers as sk_atomic_cas: acquire on failure, release on success. | 
| +// Issues acquire memory barrier on failure, release on success. | 
| template <typename P, void (*Destroy)(P)> | 
| -static P try_cas(void** dst, P ptr) { | 
| -    P prev = (P)sk_atomic_cas(dst, NULL, ptr); | 
| - | 
| -    if (prev) { | 
| -        // We need an acquire barrier before returning prev, which sk_atomic_cas provided. | 
| +static P try_cas(P* dst, P ptr) { | 
| +    P prev = NULL; | 
| +    if (sk_atomic_compare_exchange(dst, &prev, ptr, | 
| +                                   sk_memory_order_release/*on success*/, | 
| +                                   sk_memory_order_acquire/*on failure*/)) { | 
| +        // We need a release barrier before returning ptr.  The compare_exchange provides it. | 
| +        SkASSERT(!prev); | 
| +        return ptr; | 
| +    } else { | 
| Destroy(ptr); | 
| +        // We need an acquire barrier before returning prev.  The compare_exchange provided it. | 
| +        SkASSERT(prev); | 
| return prev; | 
| -    } else { | 
| -        // We need a release barrier before returning ptr, which sk_atomic_cas provided. | 
| -        return ptr; | 
| } | 
| } | 
|  | 
| @@ -97,8 +98,20 @@ template <typename T> void sk_delete(T* ptr) { SkDELETE(ptr); } | 
| // reader-consumes memory pairing rather than the more general write-releases / | 
| // reader-acquires convention. | 
| // | 
| -// This is nice, because a sk_consume_load is free on all our platforms: x86, | 
| -// ARM, MIPS.  In contrast, sk_acquire_load issues a memory barrier on non-x86. | 
| +// This is nice, because a consume load is free on all our platforms: x86, | 
| +// ARM, MIPS.  In contrast, an acquire load issues a memory barrier on non-x86. | 
| + | 
| +template <typename T> | 
| +T consume_load(T* ptr) { | 
| +#if DYNAMIC_ANNOTATIONS_ENABLED | 
| +    // TSAN gets anxious if we don't tell it what we're actually doing, a consume load. | 
| +    return sk_atomic_load(ptr, sk_memory_order_consume); | 
| +#else | 
| +    // All current compilers blindly upgrade consume memory order to acquire memory order. | 
| +    // For our purposes, though, no memory barrier is required, so we lie and use relaxed. | 
| +    return sk_atomic_load(ptr, sk_memory_order_relaxed); | 
| +#endif | 
| +} | 
|  | 
| // This has no constructor and must be zero-initalized (the macro above does this). | 
| template <typename T, T* (*Create)() = sk_new<T>, void (*Destroy)(T*) = sk_delete<T> > | 
| @@ -107,12 +120,12 @@ public: | 
| T* get() { | 
| // If fPtr has already been filled, we need a consume barrier when loading it. | 
| // If not, we need a release barrier when setting it.  try_cas will do that. | 
| -        T* ptr = (T*)sk_consume_load(&fPtr); | 
| +        T* ptr = consume_load(&fPtr); | 
| return ptr ? ptr : try_cas<T*, Destroy>(&fPtr, Create()); | 
| } | 
|  | 
| private: | 
| -    void* fPtr; | 
| +    T* fPtr; | 
| }; | 
|  | 
| template <typename T> T* sk_new_arg(int i) { return SkNEW_ARGS(T, (i)); } | 
| @@ -125,12 +138,12 @@ public: | 
| SkASSERT(i >= 0 && i < N); | 
| // If fPtr has already been filled, we need an consume barrier when loading it. | 
| // If not, we need a release barrier when setting it.  try_cas will do that. | 
| -        T* ptr = (T*)sk_consume_load(&fArray[i]); | 
| +        T* ptr = consume_load(&fArray[i]); | 
| return ptr ? ptr : try_cas<T*, Destroy>(&fArray[i], Create(i)); | 
| } | 
|  | 
| private: | 
| -    void* fArray[N]; | 
| +    T* fArray[N]; | 
| }; | 
|  | 
| }  // namespace Private | 
| @@ -148,18 +161,18 @@ public: | 
| ~SkLazyPtr() { if (fPtr) { Destroy((T*)fPtr); } } | 
|  | 
| T* get() const { | 
| -        T* ptr = (T*)sk_consume_load(&fPtr); | 
| +        T* ptr = Private::consume_load(&fPtr); | 
| return ptr ? ptr : Private::try_cas<T*, Destroy>(&fPtr, SkNEW(T)); | 
| } | 
|  | 
| template <typename Create> | 
| T* get(const Create& create) const { | 
| -        T* ptr = (T*)sk_consume_load(&fPtr); | 
| +        T* ptr = Private::consume_load(&fPtr); | 
| return ptr ? ptr : Private::try_cas<T*, Destroy>(&fPtr, create()); | 
| } | 
|  | 
| private: | 
| -    mutable void* fPtr; | 
| +    mutable T* fPtr; | 
| }; | 
|  | 
|  | 
|  |