150ffd9921e6dc82cae8ef143e8cecfd8bcf900fbmtklein/* 250ffd9921e6dc82cae8ef143e8cecfd8bcf900fbmtklein * Copyright 2015 Google Inc. 350ffd9921e6dc82cae8ef143e8cecfd8bcf900fbmtklein * 450ffd9921e6dc82cae8ef143e8cecfd8bcf900fbmtklein * Use of this source code is governed by a BSD-style license that can be 550ffd9921e6dc82cae8ef143e8cecfd8bcf900fbmtklein * found in the LICENSE file. 650ffd9921e6dc82cae8ef143e8cecfd8bcf900fbmtklein */ 750ffd9921e6dc82cae8ef143e8cecfd8bcf900fbmtklein 8a64c48f4f929775f9c203aae809f440ac01d2c64mtklein#ifndef SkAtomics_DEFINED 9a64c48f4f929775f9c203aae809f440ac01d2c64mtklein#define SkAtomics_DEFINED 10a64c48f4f929775f9c203aae809f440ac01d2c64mtklein 11a64c48f4f929775f9c203aae809f440ac01d2c64mtklein// This file is not part of the public Skia API. 12a64c48f4f929775f9c203aae809f440ac01d2c64mtklein#include "SkTypes.h" 13a64c48f4f929775f9c203aae809f440ac01d2c64mtklein 14a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleinenum sk_memory_order { 15a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein sk_memory_order_relaxed, 16a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein sk_memory_order_consume, 17a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein sk_memory_order_acquire, 18a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein sk_memory_order_release, 19a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein sk_memory_order_acq_rel, 20a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein sk_memory_order_seq_cst, 21a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein}; 22a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 23a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleintemplate <typename T> 24a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleinT sk_atomic_load(const T*, sk_memory_order = sk_memory_order_seq_cst); 25a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 26a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleintemplate <typename T> 27a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleinvoid sk_atomic_store(T*, T, sk_memory_order = sk_memory_order_seq_cst); 28a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 29a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleintemplate <typename T> 30a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleinT sk_atomic_fetch_add(T*, T, sk_memory_order = sk_memory_order_seq_cst); 31a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 32a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleintemplate <typename T> 33a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleinbool sk_atomic_compare_exchange(T*, T* expected, T desired, 34a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein sk_memory_order success = sk_memory_order_seq_cst, 35a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein sk_memory_order failure = sk_memory_order_seq_cst); 3686821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein 3750ffd9921e6dc82cae8ef143e8cecfd8bcf900fbmtkleintemplate <typename T> 3850ffd9921e6dc82cae8ef143e8cecfd8bcf900fbmtkleinT sk_atomic_exchange(T*, T, sk_memory_order = sk_memory_order_seq_cst); 3950ffd9921e6dc82cae8ef143e8cecfd8bcf900fbmtklein 4086821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein// A little wrapper class for small T (think, builtins: int, float, void*) to 4186821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein// ensure they're always used atomically. This is our stand-in for std::atomic<T>. 4286821b56704ebc0a1a6d1e5d1e329369ac797c98mtkleintemplate <typename T> 4386821b56704ebc0a1a6d1e5d1e329369ac797c98mtkleinclass SkAtomic : SkNoncopyable { 4486821b56704ebc0a1a6d1e5d1e329369ac797c98mtkleinpublic: 4586821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein SkAtomic() {} 4686821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein 4786821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein // It is essential we return by value rather than by const&. fVal may change at any time. 4886821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein T load(sk_memory_order mo = sk_memory_order_seq_cst) const { 4986821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein return sk_atomic_load(&fVal, mo); 5086821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein } 5186821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein 5286821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein void store(const T& val, sk_memory_order mo = sk_memory_order_seq_cst) { 5386821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein sk_atomic_store(&fVal, val, mo); 5486821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein } 5559c9203321cf4afb48597f39e4bdd4ae91da12a0mtklein 5659c9203321cf4afb48597f39e4bdd4ae91da12a0mtklein bool compare_exchange(T* expected, const T& desired, 5759c9203321cf4afb48597f39e4bdd4ae91da12a0mtklein sk_memory_order success = sk_memory_order_seq_cst, 5859c9203321cf4afb48597f39e4bdd4ae91da12a0mtklein sk_memory_order failure = sk_memory_order_seq_cst) { 5959c9203321cf4afb48597f39e4bdd4ae91da12a0mtklein return sk_atomic_compare_exchange(&fVal, expected, desired, success, failure); 6059c9203321cf4afb48597f39e4bdd4ae91da12a0mtklein } 6186821b56704ebc0a1a6d1e5d1e329369ac797c98mtkleinprivate: 6286821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein T fVal; 6386821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein}; 6486821b56704ebc0a1a6d1e5d1e329369ac797c98mtklein 65a64c48f4f929775f9c203aae809f440ac01d2c64mtklein#if defined(_MSC_VER) 66a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein #include "../ports/SkAtomics_std.h" 67a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein#elif !defined(SK_BUILD_FOR_IOS) && defined(__ATOMIC_RELAXED) 68a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein #include "../ports/SkAtomics_atomic.h" 69a64c48f4f929775f9c203aae809f440ac01d2c64mtklein#else 70a64c48f4f929775f9c203aae809f440ac01d2c64mtklein #include "../ports/SkAtomics_sync.h" 71a64c48f4f929775f9c203aae809f440ac01d2c64mtklein#endif 72a64c48f4f929775f9c203aae809f440ac01d2c64mtklein 73a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein// From here down we have shims for our old atomics API, to be weaned off of. 74a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein// We use the default sequentially-consistent memory order to make things simple 75a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein// and to match the practical reality of our old _sync and _win implementations. 76a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 77a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleininline int32_t sk_atomic_inc(int32_t* ptr) { return sk_atomic_fetch_add(ptr, +1); } 78a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleininline int32_t sk_atomic_dec(int32_t* ptr) { return sk_atomic_fetch_add(ptr, -1); } 79a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleininline int32_t sk_atomic_add(int32_t* ptr, int32_t v) { return sk_atomic_fetch_add(ptr, v); } 80a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 81a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleininline int64_t sk_atomic_inc(int64_t* ptr) { return sk_atomic_fetch_add<int64_t>(ptr, +1); } 82a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 83a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleininline bool sk_atomic_cas(int32_t* ptr, int32_t expected, int32_t desired) { 84a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein return sk_atomic_compare_exchange(ptr, &expected, desired); 85a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein} 86a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 87a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleininline void* sk_atomic_cas(void** ptr, void* expected, void* desired) { 88a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein (void)sk_atomic_compare_exchange(ptr, &expected, desired); 89a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein return expected; 90a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein} 91a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 92a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleininline int32_t sk_atomic_conditional_inc(int32_t* ptr) { 93a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein int32_t prev = sk_atomic_load(ptr); 94a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein do { 95a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein if (0 == prev) { 96a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein break; 97a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein } 98a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein } while(!sk_atomic_compare_exchange(ptr, &prev, prev+1)); 99a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein return prev; 100a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein} 101a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 102a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleintemplate <typename T> 103a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleinT sk_acquire_load(T* ptr) { return sk_atomic_load(ptr, sk_memory_order_acquire); } 104a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 105a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleintemplate <typename T> 106a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleinvoid sk_release_store(T* ptr, T val) { sk_atomic_store(ptr, val, sk_memory_order_release); } 107a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 108a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleininline void sk_membar_acquire__after_atomic_dec() {} 109a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtkleininline void sk_membar_acquire__after_atomic_conditional_inc() {} 110a669bc7a7ae7580c5cd92067aeb95d09e64ea720mtklein 111a64c48f4f929775f9c203aae809f440ac01d2c64mtklein#endif//SkAtomics_DEFINED 112