From 9c34fa02e79539b60be96bf3eae7b94561d6b4c5 Mon Sep 17 00:00:00 2001 From: Yavor Goulishev Date: Tue, 5 Nov 2024 10:44:10 -0800 Subject: [PATCH] Remove starboard/atomic.h (#4369) b/369181947 --- starboard/BUILD.gn | 1 - starboard/CHANGELOG.md | 1 + starboard/README.md | 8 +- starboard/android/shared/BUILD.gn | 1 - starboard/atomic.h | 259 ----------- starboard/common/atomic.h | 490 --------------------- starboard/linux/shared/BUILD.gn | 1 - starboard/nplb/atomic_base_test.cc | 523 ----------------------- starboard/nplb/atomic_test.cc | 473 -------------------- starboard/raspi/shared/BUILD.gn | 1 - starboard/shared/gcc/atomic_gcc_public.h | 205 --------- starboard/shared/stub/atomic_public.h | 168 -------- 12 files changed, 3 insertions(+), 2128 deletions(-) delete mode 100644 starboard/atomic.h delete mode 100644 starboard/common/atomic.h delete mode 100644 starboard/nplb/atomic_base_test.cc delete mode 100644 starboard/nplb/atomic_test.cc delete mode 100644 starboard/shared/gcc/atomic_gcc_public.h delete mode 100644 starboard/shared/stub/atomic_public.h diff --git a/starboard/BUILD.gn b/starboard/BUILD.gn index e00e717c5d5e7..397aa9a92b373 100644 --- a/starboard/BUILD.gn +++ b/starboard/BUILD.gn @@ -179,7 +179,6 @@ source_set("starboard_headers_only") { check_includes = false sources = [ - "atomic.h", "audio_sink.h", "configuration.h", "configuration_constants.h", diff --git a/starboard/CHANGELOG.md b/starboard/CHANGELOG.md index a1e0cefe555d2..dc0b83f475c21 100644 --- a/starboard/CHANGELOG.md +++ b/starboard/CHANGELOG.md @@ -13,6 +13,7 @@ Starboard 17 fully switches to POSIX APIs. ### Removed `starboard/accessibility.h` The functionality is migrated to a starboard extension. +### Removed `starboard/atomic.h` ### Removed `starboard/byte_swap.h` ### Removed `starboard/condition_variable.h` ### Removed `starboard/directory.h` diff --git a/starboard/README.md b/starboard/README.md index a9ea41f8c504a..bfdd80545b60f 100644 --- a/starboard/README.md +++ b/starboard/README.md @@ -90,7 +90,7 @@ With subdirectories: * `shared/` - For code shared between architectures within a product family. * `/` - For any code that is specific to a specific binary variant. Each one of these must at least have `BUILD.gn`, - `configuration_public.h`, `atomic_public.h`, + `configuration_public.h`, `platform_configuration/BUILD.gn`, `platform_configuration/configuration.gni`, and `toolchain/BUILD.gn` files. @@ -104,7 +104,6 @@ In the BobCo's BobBox example, we would see something like: * `configuration.gni` * `toolchain/` * `BUILD.gn` - * `atomic_public.h` * `BUILD.gn` * `configuration_public.h` * `armel/` @@ -113,7 +112,6 @@ In the BobCo's BobBox example, we would see something like: * `configuration.gni` * `toolchain/` * `BUILD.gn` - * `atomic_public.h` * `BUILD.gn` * `configuration_public.h` @@ -162,7 +160,7 @@ In order to use a new platform configuration in a build, you need to ensure that you have a `BUILD.gn`, `toolchain/BUILD.gn`, `platform_configuration/configuration.gni`, and `platform_configuration/BUILD.gn` in their own directory for each binary -variant, plus the header files `configuration_public.h` and `atomic_public.h`. +variant, plus the header files `configuration_public.h`. You must add your platform name to `starboard/build/platforms.py` along with the path to the port to be able to build it. @@ -196,8 +194,6 @@ the path to the port to be able to build it. as appropriate for your platform. 1. Update `BUILD.gn` to point at all the source files you want to build as part of your new Starboard implementation (as mentioned above). - 1. Update `atomic_public.h` as necessary to point - at the appropriate shared or custom implementations. If you want to use `cobalt/build/gn.py`, you'll also need a `third_party/starboard///args.gn` file. This diff --git a/starboard/android/shared/BUILD.gn b/starboard/android/shared/BUILD.gn index b76af0306250c..b3842346f3ba2 100644 --- a/starboard/android/shared/BUILD.gn +++ b/starboard/android/shared/BUILD.gn @@ -37,7 +37,6 @@ shared_library("starboard_jni_state") { static_library("starboard_platform") { sources = [ "//starboard/shared/egl/system_egl.cc", - "//starboard/shared/gcc/atomic_gcc_public.h", "//starboard/shared/gles/gl_call.h", "//starboard/shared/gles/system_gles2.cc", "//starboard/shared/internal_only.h", diff --git a/starboard/atomic.h b/starboard/atomic.h deleted file mode 100644 index 04c6c423319f0..0000000000000 --- a/starboard/atomic.h +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2015 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Module Overview: Starboard Atomic API -// -// Defines a set of atomic integer operations that can be used as lightweight -// synchronization or as building blocks for heavier synchronization primitives. -// Their use is very subtle and requires detailed understanding of the behavior -// of supported architectures, so their direct use is not recommended except -// when rigorously deemed absolutely necessary for performance reasons. - -#ifndef STARBOARD_ATOMIC_H_ -#define STARBOARD_ATOMIC_H_ - -#include "starboard/configuration.h" -#include "starboard/types.h" - -#ifndef __cplusplus -#error "This header should not be included in C source code" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef int8_t SbAtomic8; -typedef int32_t SbAtomic32; - -// Atomically execute: -// result = *ptr; -// if (*ptr == old_value) -// *ptr = new_value; -// return result; -// -// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". -// Always return the old value of "*ptr" -// -// This routine implies no memory barriers. -static SbAtomic32 SbAtomicNoBarrier_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value); - -// Atomically store new_value into *ptr, returning the previous value held in -// *ptr. This routine implies no memory barriers. -static SbAtomic32 SbAtomicNoBarrier_Exchange(volatile SbAtomic32* ptr, - SbAtomic32 new_value); - -// Atomically increment *ptr by "increment". Returns the new value of -// *ptr with the increment applied. This routine implies no memory barriers. -static SbAtomic32 SbAtomicNoBarrier_Increment(volatile SbAtomic32* ptr, - SbAtomic32 increment); - -// Same as SbAtomicNoBarrier_Increment, but with a memory barrier. -static SbAtomic32 SbAtomicBarrier_Increment(volatile SbAtomic32* ptr, - SbAtomic32 increment); - -// These following lower-level operations are typically useful only to people -// implementing higher-level synchronization operations like spinlocks, mutexes, -// and condition-variables. They combine CompareAndSwap(), a load, or a store -// with appropriate memory-ordering instructions. "Acquire" operations ensure -// that no later memory access can be reordered ahead of the operation. -// "Release" operations ensure that no previous memory access can be reordered -// after the operation. "Barrier" operations have both "Acquire" and "Release" -// semantics. A SbAtomicMemoryBarrier() has "Barrier" semantics, but does no -// memory access. -static SbAtomic32 SbAtomicAcquire_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value); -static SbAtomic32 SbAtomicRelease_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value); - -static void SbAtomicMemoryBarrier(); -static void SbAtomicNoBarrier_Store(volatile SbAtomic32* ptr, SbAtomic32 value); -static void SbAtomicAcquire_Store(volatile SbAtomic32* ptr, SbAtomic32 value); -static void SbAtomicRelease_Store(volatile SbAtomic32* ptr, SbAtomic32 value); - -static SbAtomic32 SbAtomicNoBarrier_Load(volatile const SbAtomic32* ptr); -static SbAtomic32 SbAtomicAcquire_Load(volatile const SbAtomic32* ptr); -static SbAtomic32 SbAtomicRelease_Load(volatile const SbAtomic32* ptr); - -// Overloaded functions for Atomic8. -static SbAtomic8 SbAtomicRelease_CompareAndSwap8(volatile SbAtomic8* ptr, - SbAtomic8 old_value, - SbAtomic8 new_value); -static void SbAtomicNoBarrier_Store8(volatile SbAtomic8* ptr, SbAtomic8 value); -static SbAtomic8 SbAtomicNoBarrier_Load8(volatile const SbAtomic8* ptr); - -// 64-bit atomic operations (only available on 64-bit processors). -#if SB_HAS(64_BIT_ATOMICS) -typedef int64_t SbAtomic64; - -static SbAtomic64 SbAtomicNoBarrier_CompareAndSwap64(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value); -static SbAtomic64 SbAtomicNoBarrier_Exchange64(volatile SbAtomic64* ptr, - SbAtomic64 new_value); -static SbAtomic64 SbAtomicNoBarrier_Increment64(volatile SbAtomic64* ptr, - SbAtomic64 increment); -static SbAtomic64 SbAtomicBarrier_Increment64(volatile SbAtomic64* ptr, - SbAtomic64 increment); -static SbAtomic64 SbAtomicAcquire_CompareAndSwap64(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value); -static SbAtomic64 SbAtomicRelease_CompareAndSwap64(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value); -static void SbAtomicNoBarrier_Store64(volatile SbAtomic64* ptr, - SbAtomic64 value); -static void SbAtomicAcquire_Store64(volatile SbAtomic64* ptr, SbAtomic64 value); -static void SbAtomicRelease_Store64(volatile SbAtomic64* ptr, SbAtomic64 value); -static SbAtomic64 SbAtomicNoBarrier_Load64(volatile const SbAtomic64* ptr); -static SbAtomic64 SbAtomicAcquire_Load64(volatile const SbAtomic64* ptr); -static SbAtomic64 SbAtomicRelease_Load64(volatile const SbAtomic64* ptr); -#endif // SB_HAS(64_BIT_ATOMICS) - -// Pointer-sized atomic operations. Forwards to either 32-bit or 64-bit -// functions as appropriate. -#if SB_SIZE_OF(POINTER) == 8 -typedef SbAtomic64 SbAtomicPtr; -#else -typedef SbAtomic32 SbAtomicPtr; -#endif - -static SB_C_FORCE_INLINE SbAtomicPtr -SbAtomicNoBarrier_CompareAndSwapPtr(volatile SbAtomicPtr* ptr, - SbAtomicPtr old_value, - SbAtomicPtr new_value) { -#if SB_SIZE_OF(POINTER) == 8 - return SbAtomicNoBarrier_CompareAndSwap64(ptr, old_value, new_value); -#else - return SbAtomicNoBarrier_CompareAndSwap(ptr, old_value, new_value); -#endif -} - -static SB_C_FORCE_INLINE SbAtomicPtr -SbAtomicNoBarrier_ExchangePtr(volatile SbAtomicPtr* ptr, - SbAtomicPtr new_value) { -#if SB_SIZE_OF(POINTER) == 8 - return SbAtomicNoBarrier_Exchange64(ptr, new_value); -#else - return SbAtomicNoBarrier_Exchange(ptr, new_value); -#endif -} - -static SB_C_FORCE_INLINE SbAtomicPtr -SbAtomicNoBarrier_IncrementPtr(volatile SbAtomicPtr* ptr, - SbAtomicPtr increment) { -#if SB_SIZE_OF(POINTER) == 8 - return SbAtomicNoBarrier_Increment64(ptr, increment); -#else - return SbAtomicNoBarrier_Increment(ptr, increment); -#endif -} - -static SB_C_FORCE_INLINE SbAtomicPtr -SbAtomicBarrier_IncrementPtr(volatile SbAtomicPtr* ptr, SbAtomicPtr increment) { -#if SB_SIZE_OF(POINTER) == 8 - return SbAtomicBarrier_Increment64(ptr, increment); -#else - return SbAtomicBarrier_Increment(ptr, increment); -#endif -} - -static SB_C_FORCE_INLINE SbAtomicPtr -SbAtomicAcquire_CompareAndSwapPtr(volatile SbAtomicPtr* ptr, - SbAtomicPtr old_value, - SbAtomicPtr new_value) { -#if SB_SIZE_OF(POINTER) == 8 - return SbAtomicAcquire_CompareAndSwap64(ptr, old_value, new_value); -#else - return SbAtomicAcquire_CompareAndSwap(ptr, old_value, new_value); -#endif -} - -static SB_C_FORCE_INLINE SbAtomicPtr -SbAtomicRelease_CompareAndSwapPtr(volatile SbAtomicPtr* ptr, - SbAtomicPtr old_value, - SbAtomicPtr new_value) { -#if SB_SIZE_OF(POINTER) == 8 - return SbAtomicRelease_CompareAndSwap64(ptr, old_value, new_value); -#else - return SbAtomicRelease_CompareAndSwap(ptr, old_value, new_value); -#endif -} - -static SB_C_FORCE_INLINE void SbAtomicNoBarrier_StorePtr( - volatile SbAtomicPtr* ptr, - SbAtomicPtr value) { -#if SB_SIZE_OF(POINTER) == 8 - SbAtomicNoBarrier_Store64(ptr, value); -#else - SbAtomicNoBarrier_Store(ptr, value); -#endif -} - -static SB_C_FORCE_INLINE void SbAtomicAcquire_StorePtr( - volatile SbAtomicPtr* ptr, - SbAtomicPtr value) { -#if SB_SIZE_OF(POINTER) == 8 - SbAtomicAcquire_Store64(ptr, value); -#else - SbAtomicAcquire_Store(ptr, value); -#endif -} - -static SB_C_FORCE_INLINE void SbAtomicRelease_StorePtr( - volatile SbAtomicPtr* ptr, - SbAtomicPtr value) { -#if SB_SIZE_OF(POINTER) == 8 - SbAtomicRelease_Store64(ptr, value); -#else - SbAtomicRelease_Store(ptr, value); -#endif -} - -static SB_C_FORCE_INLINE SbAtomicPtr -SbAtomicNoBarrier_LoadPtr(volatile const SbAtomicPtr* ptr) { -#if SB_SIZE_OF(POINTER) == 8 - return SbAtomicNoBarrier_Load64(ptr); -#else - return SbAtomicNoBarrier_Load(ptr); -#endif -} - -static SB_C_FORCE_INLINE SbAtomicPtr -SbAtomicAcquire_LoadPtr(volatile const SbAtomicPtr* ptr) { -#if SB_SIZE_OF(POINTER) == 8 - return SbAtomicAcquire_Load64(ptr); -#else - return SbAtomicAcquire_Load(ptr); -#endif -} - -static SB_C_FORCE_INLINE SbAtomicPtr -SbAtomicRelease_LoadPtr(volatile const SbAtomicPtr* ptr) { -#if SB_SIZE_OF(POINTER) == 8 - return SbAtomicRelease_Load64(ptr); -#else - return SbAtomicRelease_Load(ptr); -#endif -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // STARBOARD_ATOMIC_H_ diff --git a/starboard/common/atomic.h b/starboard/common/atomic.h deleted file mode 100644 index eb545e471f175..0000000000000 --- a/starboard/common/atomic.h +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright 2023 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_COMMON_ATOMIC_H_ -#define STARBOARD_COMMON_ATOMIC_H_ - -#include "starboard/atomic.h" -#include "starboard/common/mutex.h" - -// C++ Can choose the right function based on overloaded arguments. This -// provides overloaded versions that will choose the right function version -// based on type for C++ callers. - -namespace starboard { -namespace atomic { - -inline SbAtomic8 Release_CompareAndSwap(volatile SbAtomic8* ptr, - SbAtomic8 old_value, - SbAtomic8 new_value) { - return SbAtomicRelease_CompareAndSwap8(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile SbAtomic8* ptr, SbAtomic8 value) { - SbAtomicNoBarrier_Store8(ptr, value); -} - -inline SbAtomic8 NoBarrier_Load(volatile const SbAtomic8* ptr) { - return SbAtomicNoBarrier_Load8(ptr); -} - -inline SbAtomic32 NoBarrier_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value) { - return SbAtomicNoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline SbAtomic32 NoBarrier_Exchange(volatile SbAtomic32* ptr, - SbAtomic32 new_value) { - return SbAtomicNoBarrier_Exchange(ptr, new_value); -} - -inline SbAtomic32 NoBarrier_Increment(volatile SbAtomic32* ptr, - SbAtomic32 increment) { - return SbAtomicNoBarrier_Increment(ptr, increment); -} - -inline SbAtomic32 Barrier_Increment(volatile SbAtomic32* ptr, - SbAtomic32 increment) { - return SbAtomicBarrier_Increment(ptr, increment); -} - -inline SbAtomic32 Acquire_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value) { - return SbAtomicAcquire_CompareAndSwap(ptr, old_value, new_value); -} - -inline SbAtomic32 Release_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value) { - return SbAtomicRelease_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile SbAtomic32* ptr, SbAtomic32 value) { - SbAtomicNoBarrier_Store(ptr, value); -} - -inline void Acquire_Store(volatile SbAtomic32* ptr, SbAtomic32 value) { - SbAtomicAcquire_Store(ptr, value); -} - -inline void Release_Store(volatile SbAtomic32* ptr, SbAtomic32 value) { - SbAtomicRelease_Store(ptr, value); -} - -inline SbAtomic32 NoBarrier_Load(volatile const SbAtomic32* ptr) { - return SbAtomicNoBarrier_Load(ptr); -} - -inline SbAtomic32 Acquire_Load(volatile const SbAtomic32* ptr) { - return SbAtomicAcquire_Load(ptr); -} - -inline SbAtomic32 Release_Load(volatile const SbAtomic32* ptr) { - return SbAtomicRelease_Load(ptr); -} - -#if SB_HAS(64_BIT_ATOMICS) -inline SbAtomic64 NoBarrier_CompareAndSwap(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value) { - return SbAtomicNoBarrier_CompareAndSwap64(ptr, old_value, new_value); -} - -inline SbAtomic64 NoBarrier_Exchange(volatile SbAtomic64* ptr, - SbAtomic64 new_value) { - return SbAtomicNoBarrier_Exchange64(ptr, new_value); -} - -inline SbAtomic64 NoBarrier_Increment(volatile SbAtomic64* ptr, - SbAtomic64 increment) { - return SbAtomicNoBarrier_Increment64(ptr, increment); -} - -inline SbAtomic64 Barrier_Increment(volatile SbAtomic64* ptr, - SbAtomic64 increment) { - return SbAtomicBarrier_Increment64(ptr, increment); -} - -inline SbAtomic64 Acquire_CompareAndSwap(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value) { - return SbAtomicAcquire_CompareAndSwap64(ptr, old_value, new_value); -} - -inline SbAtomic64 Release_CompareAndSwap(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value) { - return SbAtomicRelease_CompareAndSwap64(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile SbAtomic64* ptr, SbAtomic64 value) { - SbAtomicNoBarrier_Store64(ptr, value); -} - -inline void Acquire_Store(volatile SbAtomic64* ptr, SbAtomic64 value) { - SbAtomicAcquire_Store64(ptr, value); -} - -inline void Release_Store(volatile SbAtomic64* ptr, SbAtomic64 value) { - SbAtomicRelease_Store64(ptr, value); -} - -inline SbAtomic64 NoBarrier_Load(volatile const SbAtomic64* ptr) { - return SbAtomicNoBarrier_Load64(ptr); -} - -inline SbAtomic64 Acquire_Load(volatile const SbAtomic64* ptr) { - return SbAtomicAcquire_Load64(ptr); -} - -inline SbAtomic64 Release_Load(volatile const SbAtomic64* ptr) { - return SbAtomicRelease_Load64(ptr); -} -#endif // SB_HAS(64_BIT_ATOMICS) - -} // namespace atomic - -// Provides atomic types like integer and float. Some types like atomic_int32_t -// are likely to be hardware accelerated for your platform. -// -// Never use the parent types like atomic_base, atomic_number or -// atomic_integral and instead use the fully qualified classes like -// atomic_int32_t, atomic_pointer, etc. -// -// Note on template instantiation, avoid using the parent type and instead -// use the fully qualified type. -// BAD: -// template -// void Foo(const atomic_base& value); -// GOOD: -// template -// void Foo(const atomic_t& value); - -// Atomic Pointer class. Instantiate as atomic_pointer -// for void* pointer types. -template -class atomic_pointer; - -// Atomic bool class. -class atomic_bool; - -// Atomic int32 class -class atomic_int32_t; - -// Atomic int64 class. -class atomic_int64_t; - -// Atomic float class. -class atomic_float; - -// Atomic double class. -class atomic_double; - -/////////////////////////////////////////////////////////////////////////////// -// Class hierarchy. -/////////////////////////////////////////////////////////////////////////////// - -// Base functionality for atomic types. Defines exchange(), load(), -// store(), compare_exchange_weak(), compare_exchange_strong() -template -class atomic_base; - -// Subtype of atomic_base for numbers likes float and integer types but not -// bool. Adds fetch_add() and fetch_sub(). -template -class atomic_number; - -// Subtype of atomic_number for integer types like int32 and int64. Adds -// increment and decrement. -template -class atomic_integral; - -/////////////////////////////////////////////////////////////////////////////// -// Implementation. -/////////////////////////////////////////////////////////////////////////////// - -// Similar to C++11 std::atomic. -// atomic_base may be instantiated with any TriviallyCopyable type T. -// atomic_base is neither copyable nor movable. -template -class atomic_base { - public: - typedef T ValueType; - - // C++11 forbids a copy constructor for std::atomic, it also forbids - // a move operation. - atomic_base() : value_() {} - explicit atomic_base(T v) : value_(v) {} - - // Checks whether the atomic operations on all objects of this type - // are lock-free. - // Returns true if the atomic operations on the objects of this type - // are lock-free, false otherwise. - // - // All atomic types may be implemented using mutexes or other locking - // operations, rather than using the lock-free atomic CPU instructions. - // atomic types are also allowed to be sometimes lock-free, e.g. if only - // aligned memory accesses are naturally atomic on a given architecture, - // misaligned objects of the same type have to use locks. - // - // See also std::atomic::is_lock_free(). - bool is_lock_free() const { return false; } - bool is_lock_free() const volatile { return false; } - - // Atomically replaces the value of the atomic object and returns the value - // held previously. - // See also std::atomic::exchange(). - T exchange(T new_val) { - T old_value; - { - starboard::ScopedLock lock(mutex_); - old_value = value_; - value_ = new_val; - } - return old_value; - } - - // Atomically obtains the value of the atomic object. - // See also std::atomic::load(). - T load() const { - starboard::ScopedLock lock(mutex_); - return value_; - } - - // Stores the value. See std::atomic::store(...) - void store(T val) { - starboard::ScopedLock lock(mutex_); - value_ = val; - } - - // compare_exchange_strong(...) sets the new value if and only if - // *expected_value matches what is stored internally. - // If this succeeds then true is returned and *expected_value == new_value. - // Otherwise If there is a mismatch then false is returned and - // *expected_value is set to the internal value. - // Inputs: - // new_value: Attempt to set the value to this new value. - // expected_value: A test condition for success. If the actual value - // matches the expected_value then the swap will succeed. - // - // See also std::atomic::compare_exchange_strong(...). - bool compare_exchange_strong(T* expected_value, T new_value) { - // Save original value so that its local. This hints to the compiler - // that test_val doesn't have aliasing issues and should result in - // more optimal code inside of the lock. - const T test_val = *expected_value; - starboard::ScopedLock lock(mutex_); - if (test_val == value_) { - value_ = new_value; - return true; - } else { - *expected_value = value_; - return false; - } - } - - // Weak version of this function is documented to be faster, but has allows - // weaker memory ordering and therefore will sometimes have a false negative: - // The value compared will actually be equal but the return value from this - // function indicates otherwise. - // By default, the function delegates to compare_exchange_strong(...). - // - // See also std::atomic::compare_exchange_weak(...). - bool compare_exchange_weak(T* expected_value, T new_value) { - return compare_exchange_strong(expected_value, new_value); - } - - protected: - T value_; - starboard::Mutex mutex_; -}; - -// A subclass of atomic_base that adds fetch_add(...) and fetch_sub(...). -template -class atomic_number : public atomic_base { - public: - typedef atomic_base Super; - typedef T ValueType; - - atomic_number() : Super() {} - explicit atomic_number(T v) : Super(v) {} - - // Returns the previous value before the input value was added. - // See also std::atomic::fetch_add(...). - T fetch_add(T val) { - T old_val; - { - starboard::ScopedLock lock(this->mutex_); - old_val = this->value_; - this->value_ += val; - } - return old_val; - } - - // Returns the value before the operation was applied. - // See also std::atomic::fetch_sub(...). - T fetch_sub(T val) { - T old_val; - { - starboard::ScopedLock lock(this->mutex_); - old_val = this->value_; - this->value_ -= val; - } - return old_val; - } -}; - -// A subclass to classify Atomic Integers. Adds increment and decrement -// functions. -template -class atomic_integral : public atomic_number { - public: - typedef atomic_number Super; - - atomic_integral() : Super() {} - explicit atomic_integral(T v) : Super(v) {} - - T increment() { return this->fetch_add(T(1)); } - T decrement() { return this->fetch_sub(T(1)); } -}; - -// atomic_pointer class. -template -class atomic_pointer : public atomic_base { - public: - typedef atomic_base Super; - atomic_pointer() : Super() {} - explicit atomic_pointer(T initial_val) : Super(initial_val) {} -}; - -// Simple atomic bool class. -class atomic_bool { - public: - typedef bool ValueType; - - // C++11 forbids a copy constructor for std::atomic, it also forbids - // a move operation. - atomic_bool() : value_(false) {} - explicit atomic_bool(bool v) : value_(v) {} - - bool is_lock_free() const { return true; } - bool is_lock_free() const volatile { return true; } - - bool exchange(bool new_val) { - return SbAtomicNoBarrier_Exchange(volatile_ptr(), new_val); - } - - bool load() const { return SbAtomicAcquire_Load(volatile_const_ptr()) != 0; } - - void store(bool val) { SbAtomicRelease_Store(volatile_ptr(), val); } - - private: - volatile int32_t* volatile_ptr() { return &value_; } - volatile const int32_t* volatile_const_ptr() const { return &value_; } - int32_t value_; -}; - -// Lockfree atomic int class. -class atomic_int32_t { - public: - typedef int32_t ValueType; - atomic_int32_t() : value_(0) {} - explicit atomic_int32_t(SbAtomic32 value) : value_(value) {} - - bool is_lock_free() const { return true; } - bool is_lock_free() const volatile { return true; } - - int32_t increment() { return fetch_add(1); } - int32_t decrement() { return fetch_add(-1); } - - int32_t fetch_add(int32_t val) { - // fetch_add is a post-increment operation, while SbAtomicBarrier_Increment - // is a pre-increment operation. Therefore subtract the value to match - // the expected interface. - return SbAtomicBarrier_Increment(volatile_ptr(), val) - val; - } - - int32_t fetch_sub(int32_t val) { return fetch_add(-val); } - - // Atomically replaces the value of the atomic object - // and returns the value held previously. - // See also std::atomic::exchange(). - int32_t exchange(int32_t new_val) { - return SbAtomicNoBarrier_Exchange(volatile_ptr(), new_val); - } - - // Atomically obtains the value of the atomic object. - // See also std::atomic::load(). - int32_t load() const { return SbAtomicAcquire_Load(volatile_const_ptr()); } - - // Stores the value. See std::atomic::store(...) - void store(int32_t val) { SbAtomicRelease_Store(volatile_ptr(), val); } - - bool compare_exchange_strong(int32_t* expected_value, int32_t new_value) { - int32_t prev_value = *expected_value; - SbAtomicMemoryBarrier(); - int32_t value_written = - SbAtomicRelease_CompareAndSwap(volatile_ptr(), prev_value, new_value); - const bool write_ok = (prev_value == value_written); - if (!write_ok) { - *expected_value = value_written; - } - return write_ok; - } - - // Weak version of this function is documented to be faster, but has allows - // weaker memory ordering and therefore will sometimes have a false negative: - // The value compared will actually be equal but the return value from this - // function indicates otherwise. - // By default, the function delegates to compare_exchange_strong(...). - // - // See also std::atomic::compare_exchange_weak(...). - bool compare_exchange_weak(int32_t* expected_value, int32_t new_value) { - return compare_exchange_strong(expected_value, new_value); - } - - private: - volatile int32_t* volatile_ptr() { return &value_; } - volatile const int32_t* volatile_const_ptr() const { return &value_; } - int32_t value_; -}; - -// Simple atomic int class. This could be optimized for speed using -// compiler intrinsics for concurrent integer modification. -class atomic_int64_t : public atomic_integral { - public: - typedef atomic_integral Super; - atomic_int64_t() : Super() {} - explicit atomic_int64_t(int64_t initial_val) : Super(initial_val) {} -}; - -class atomic_float : public atomic_number { - public: - typedef atomic_number Super; - atomic_float() : Super() {} - explicit atomic_float(float initial_val) : Super(initial_val) {} -}; - -class atomic_double : public atomic_number { - public: - typedef atomic_number Super; - atomic_double() : Super() {} - explicit atomic_double(double initial_val) : Super(initial_val) {} -}; - -} // namespace starboard - -#endif // STARBOARD_COMMON_ATOMIC_H_ diff --git a/starboard/linux/shared/BUILD.gn b/starboard/linux/shared/BUILD.gn index 526914314dce3..77b3522ab0e97 100644 --- a/starboard/linux/shared/BUILD.gn +++ b/starboard/linux/shared/BUILD.gn @@ -96,7 +96,6 @@ static_library("starboard_platform_sources") { "//starboard/shared/alsa/alsa_util.cc", "//starboard/shared/alsa/alsa_util.h", "//starboard/shared/egl/system_egl.cc", - "//starboard/shared/gcc/atomic_gcc_public.h", "//starboard/shared/gles/system_gles2.cc", "//starboard/shared/iso/memory_allocate_unchecked.cc", "//starboard/shared/iso/memory_free.cc", diff --git a/starboard/nplb/atomic_base_test.cc b/starboard/nplb/atomic_base_test.cc deleted file mode 100644 index 716376a027b2d..0000000000000 --- a/starboard/nplb/atomic_base_test.cc +++ /dev/null @@ -1,523 +0,0 @@ -// Copyright 2016 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include -#include -#include - -#include "starboard/common/atomic.h" -#include "starboard/common/mutex.h" -#include "starboard/configuration.h" -#include "testing/gtest/include/gtest/gtest.h" - -#define NUM_THREADS 4 - -namespace starboard { -namespace nplb { -namespace { - -// TestThread that is a bare bones class wrapper around Starboard -// thread. Subclasses must override Run(). -class TestThread { - public: - TestThread() : thread_(0) {} - virtual ~TestThread() {} - - // Subclasses should override the Run method. - virtual void Run() = 0; - - // Calls pthread_create() with default parameters. - void Start() { - pthread_create(&thread_, nullptr, ThreadEntryPoint, this); - - if (thread_ == 0) { - ADD_FAILURE_AT(__FILE__, __LINE__) << "Invalid thread."; - } - return; - } - - void Join() { - if (pthread_join(thread_, NULL) != 0) { - ADD_FAILURE_AT(__FILE__, __LINE__) << "Could not join thread."; - } - } - - private: - static void* ThreadEntryPoint(void* ptr) { - TestThread* this_ptr = static_cast(ptr); - this_ptr->Run(); - return NULL; - } - - pthread_t thread_; - - TestThread(const TestThread&) = delete; - void operator=(const TestThread&) = delete; -}; - -/////////////////////////////////////////////////////////////////////////////// -// Boilerplate for test setup. -/////////////////////////////////////////////////////////////////////////////// - -// Defines a typelist for all atomic types. -typedef ::testing::Types> - AllAtomicTypes; - -// Defines a typelist for just atomic number types. -typedef ::testing:: - Types - AtomicNumberTypes; - -// Defines a typelist for just atomic number types. -typedef ::testing::Types AtomicIntegralTypes; - -// Defines test type that will be instantiated using each type in -// AllAtomicTypes type list. -template -class AtomicBaseTest : public ::testing::Test {}; -TYPED_TEST_CASE(AtomicBaseTest, AllAtomicTypes); // Registration. - -// Defines test type that will be instantiated using each type in -// AtomicNumberTypes type list. -template -class AtomicNumberTest : public ::testing::Test {}; -TYPED_TEST_CASE(AtomicNumberTest, AtomicNumberTypes); // Registration. - -template -class AtomicIntegralTest : public ::testing::Test {}; -TYPED_TEST_CASE(AtomicIntegralTest, AtomicIntegralTypes); // Registration. - -/////////////////////////////////////////////////////////////////////////////// -// Singlethreaded tests. -/////////////////////////////////////////////////////////////////////////////// - -// Tests default constructor and single-argument constructor. -TYPED_TEST(AtomicBaseTest, Constructors) { - typedef TypeParam AtomicT; - typedef typename AtomicT::ValueType T; - - const T zero(0); - const T one = zero + 1; // Allows AtomicPointer. - - AtomicT atomic_default; - - // Tests that default value is zero. - ASSERT_EQ(atomic_default.load(), zero); - AtomicT atomic_val(one); - ASSERT_EQ(one, atomic_val.load()); -} - -// Tests load() and exchange(). -TYPED_TEST(AtomicBaseTest, Load_Exchange_SingleThread) { - typedef TypeParam AtomicT; - typedef typename AtomicT::ValueType T; - - const T zero(0); - const T one = zero + 1; // Allows AtomicPointer. - - AtomicT atomic; - ASSERT_EQ(atomic.load(), zero); // Default is 0. - ASSERT_EQ(zero, atomic.exchange(one)); // Old value was 0. - - // Tests that AtomicType has const get function. - const AtomicT& const_atomic = atomic; - ASSERT_EQ(one, const_atomic.load()); -} - -// Tests compare_exchange_strong(). -TYPED_TEST(AtomicNumberTest, CompareExchangeStrong_SingleThread) { - typedef TypeParam AtomicT; - typedef typename AtomicT::ValueType T; - - const T zero(0); - const T one = zero + 1; // Allows AtomicPointer. - - AtomicT atomic; - ASSERT_EQ(atomic.load(), zero); // Default is 0. - T expected_value = zero; - // Should succeed. - ASSERT_TRUE(atomic.compare_exchange_strong(&expected_value, - one)); // New value. - - ASSERT_EQ(zero, expected_value); - ASSERT_EQ(one, atomic.load()); // Expect that value was set. - - expected_value = zero; - // Asserts that when the expected and actual value is mismatched that the - // compare_exchange_strong() fails. - ASSERT_FALSE(atomic.compare_exchange_strong(&expected_value, // Mismatched. - zero)); // New value. - - // Failed and this means that expected_value should be set to what the - // internal value was. In this case, one. - ASSERT_EQ(expected_value, one); - ASSERT_EQ(one, atomic.load()); - - ASSERT_TRUE(atomic.compare_exchange_strong(&expected_value, // Matches. - zero)); - ASSERT_EQ(expected_value, one); -} - -// Tests atomic fetching and adding. -TYPED_TEST(AtomicNumberTest, FetchAdd_SingleThread) { - typedef TypeParam AtomicT; - typedef typename AtomicT::ValueType T; - - const T zero(0); - const T one = zero + 1; // Allows atomic_pointer. - const T two = zero + 2; - - AtomicT atomic; - ASSERT_EQ(atomic.load(), zero); // Default is 0. - ASSERT_EQ(zero, atomic.fetch_add(one)); // Prev value was 0. - ASSERT_EQ(one, atomic.load()); // Now value is this. - ASSERT_EQ(one, atomic.fetch_add(one)); // Prev value was 1. - ASSERT_EQ(two, atomic.exchange(one)); // Old value was 2. -} - -// Tests atomic fetching and subtracting. -TYPED_TEST(AtomicNumberTest, FetchSub_SingleThread) { - typedef TypeParam AtomicT; - typedef typename AtomicT::ValueType T; - - const T zero(0); - const T one = zero + 1; // Allows AtomicPointer. - const T two = zero + 2; - const T neg_two(zero - 2); - - AtomicT atomic; - ASSERT_EQ(atomic.load(), zero); // Default is 0. - atomic.exchange(two); - ASSERT_EQ(two, atomic.fetch_sub(one)); // Prev value was 2. - ASSERT_EQ(one, atomic.load()); // New value. - ASSERT_EQ(one, atomic.fetch_sub(one)); // Prev value was one. - ASSERT_EQ(zero, atomic.load()); // New 0. - ASSERT_EQ(zero, atomic.fetch_sub(two)); - ASSERT_EQ(neg_two, atomic.load()); // 0-2 = -2 -} - -TYPED_TEST(AtomicIntegralTest, IncrementAndDecrement_SingleThread) { - typedef TypeParam AtomicT; - typedef typename AtomicT::ValueType T; - - const T zero(0); - const T one = zero + 1; // Allows AtomicPointer. - - AtomicT atomic; - ASSERT_EQ(atomic.load(), zero); // Default is 0. - ASSERT_EQ(zero, atomic.increment()); // Tests for post-increment operation. - ASSERT_EQ(one, atomic.decrement()); // Tests for post-decrement operation. -} - -/////////////////////////////////////////////////////////////////////////////// -// Multithreaded tests. -/////////////////////////////////////////////////////////////////////////////// - -// A thread that will execute compare_exchange_strong() and write out a result -// to a shared output. -template -class CompareExchangeThread : public TestThread { - public: - typedef typename AtomicT::ValueType T; - CompareExchangeThread(int start_num, - int end_num, - AtomicT* atomic_value, - std::vector* output, - starboard::Mutex* output_mutex) - : start_num_(start_num), - end_num_(end_num), - atomic_value_(atomic_value), - output_(output), - output_mutex_(output_mutex) {} - - virtual void Run() { - std::vector output_buffer; - output_buffer.reserve(end_num_ - start_num_); - for (int i = start_num_; i < end_num_; ++i) { - T new_value = T(i); - while (true) { - if (std::rand() % 3 == 0) { - // 1 in 3 chance of yielding. - // Attempt to cause more contention by giving other threads a chance - // to run. - sched_yield(); - } - - const T prev_value = atomic_value_->load(); - T expected_value = prev_value; - const bool success = - atomic_value_->compare_exchange_strong(&expected_value, new_value); - if (success) { - output_buffer.push_back(prev_value); - break; - } - } - } - - // Lock the output to append this output buffer. - starboard::ScopedLock lock(*output_mutex_); - output_->insert(output_->end(), output_buffer.begin(), output_buffer.end()); - } - - private: - const int start_num_; - const int end_num_; - AtomicT* const atomic_value_; - std::vector* const output_; - starboard::Mutex* const output_mutex_; -}; - -// Tests Atomic::compare_exchange_strong(). Each thread has a unique -// sequential range [0,1,2,3 ... ), [5,6,8, ...) that it will generate. -// The numbers are sequentially written to the shared Atomic type and then -// exposed to other threads: -// -// Generates [0,1,2,...,n/2) -// +------+ Thread A <--------+ (Write Exchanged Value) -// | | -// | compare_exchange() +---> exchanged? ---+ -// +----> +------------+ +----+ v -// | AtomicType | Output vector -// +----> +------------+ +----+ ^ -// | compare_exchange() +---> exchanged? ---+ -// | | -// +------+ Thread B <--------+ -// Generates [n/2,n/2+1,...,n) -// -// By repeatedly calling atomic::compare_exchange_strong() by each of the -// threads, each will see the previous value of the shared variable when their -// exchange (atomic swap) operation is successful. If all of the swapped out -// values are recombined then it will form the original generated sequence from -// all threads. -// -// TEST PHASE -// sort( output vector ) AND TEST THAT -// output vector Contains [0,1,2,...,n) -// -// The test passes when the output array is tested that it contains every -// expected generated number from all threads. If compare_exchange_strong() is -// written incorrectly for an atomic type then the output array will have -// duplicates or otherwise not be equal to the expected natural number set. -TYPED_TEST(AtomicNumberTest, Test_CompareExchange_MultiThreaded) { - typedef TypeParam AtomicT; - typedef typename AtomicT::ValueType T; - - static const int kNumElements = 1000; - - AtomicT atomic_value(T(-1)); - std::vector threads; - std::vector output_values; - starboard::Mutex output_mutex; - - for (int i = 0; i < NUM_THREADS; ++i) { - const int start_num = (kNumElements * i) / NUM_THREADS; - const int end_num = (kNumElements * (i + 1)) / NUM_THREADS; - threads.push_back(new CompareExchangeThread( - start_num, // defines the number range to generate. - end_num, &atomic_value, &output_values, &output_mutex)); - } - - // These threads will generate unique numbers in their range and then - // write them to the output array. - for (int i = 0; i < NUM_THREADS; ++i) { - threads[i]->Start(); - } - - for (int i = 0; i < NUM_THREADS; ++i) { - threads[i]->Join(); - } - // Cleanup threads. - for (int i = 0; i < NUM_THREADS; ++i) { - delete threads[i]; - } - threads.clear(); - - // Final value needs to be written out. The last thread to join doesn't - // know it's the last and therefore the final value in the shared - // has not be pushed to the output array. - output_values.push_back(atomic_value.load()); - std::sort(output_values.begin(), output_values.end()); - - // We expect the -1 value because it was the explicit initial value of the - // shared atomic. - ASSERT_EQ(T(-1), output_values[0]); - ASSERT_EQ(T(0), output_values[1]); - output_values.erase(output_values.begin()); // Chop off the -1 at the front. - - // Finally, assert that the output array is equal to the natural numbers - // after it has been sorted. - ASSERT_EQ(output_values.size(), kNumElements); - // All of the elements should be equal too. - for (int i = 0; i < output_values.size(); ++i) { - ASSERT_EQ(output_values[i], T(i)); - } -} - -// A thread that will invoke increment() and decrement() and equal number -// of times to atomic_value. The value after this is done should be equal to -// 0. -template -class IncrementAndDecrementThread : public TestThread { - public: - typedef typename AtomicT::ValueType T; - IncrementAndDecrementThread(size_t half_number_of_operations, - AtomicT* atomic_value) - : atomic_value_(atomic_value) { - for (size_t i = 0; i < half_number_of_operations; ++i) { - operation_sequence_.push_back(true); - } - for (size_t i = 0; i < half_number_of_operations; ++i) { - operation_sequence_.push_back(false); - } - std::shuffle(operation_sequence_.begin(), operation_sequence_.end(), - std::default_random_engine()); - } - - virtual void Run() { - for (size_t i = 0; i < operation_sequence_.size(); ++i) { - if (std::rand() % 3 == 0) { - // 1 in 3 chance of yielding. - // Attempt to cause more contention by giving other threads a chance - // to run. - sched_yield(); - } - T prev_value = 0; - if (operation_sequence_[i]) { - prev_value = atomic_value_->increment(); - } else { - prev_value = atomic_value_->decrement(); - } - } - } - - private: - // Used purely for true/false values. Note that we don't - // use std::vector because some platforms won't support - // swapping elements of std::vector, which is required for - // std::random_shuffle(). - std::vector operation_sequence_; - AtomicT* const atomic_value_; -}; - -TYPED_TEST(AtomicIntegralTest, Test_IncrementAndDecrement_MultiThreaded) { - typedef TypeParam AtomicT; - typedef typename AtomicT::ValueType T; - - static const int kNumOperations = 10000; - - AtomicT atomic_value(T(0)); - std::vector threads; - - for (int i = 0; i < NUM_THREADS; ++i) { - threads.push_back(new IncrementAndDecrementThread(kNumOperations, - &atomic_value)); - } - - for (int i = 0; i < NUM_THREADS; ++i) { - threads[i]->Start(); - } - - for (int i = 0; i < NUM_THREADS; ++i) { - threads[i]->Join(); - } - // Cleanup threads. - for (int i = 0; i < NUM_THREADS; ++i) { - delete threads[i]; - } - threads.clear(); - - // After an equal number of decrements and increments, the final value should - // be 0. - ASSERT_EQ(0, atomic_value.load()); -} - -template -class FetchAddSubThread : public TestThread { - public: - typedef typename AtomicT::ValueType T; - FetchAddSubThread(const int32_t start_value, - const int32_t end_value, - AtomicT* atomic_value) - : start_value_(start_value), - end_value_(end_value), - atomic_value_(atomic_value) {} - - virtual void Run() { - for (int32_t i = start_value_; i < end_value_; ++i) { - if (std::rand() % 3 == 0) { - // 1 in 3 chance of yielding. - // Attempt to cause more contention by giving other threads a chance - // to run.s - sched_yield(); - } - - if (std::rand() % 2 == 0) { - atomic_value_->fetch_add(i); - } else { - atomic_value_->fetch_sub(-i); - } - } - } - - private: - int32_t start_value_; - int32_t end_value_; - AtomicT* const atomic_value_; -}; - -TYPED_TEST(AtomicIntegralTest, Test_FetchAdd_MultiThreaded) { - typedef TypeParam AtomicT; - typedef typename AtomicT::ValueType T; - - static const int kNumOperations = 10000; - - AtomicT atomic_value(T(0)); - std::vector threads; - - // First value is inclusive, second is exclusive. - threads.push_back( - new FetchAddSubThread(-kNumOperations, 0, &atomic_value)); - - threads.push_back( - new FetchAddSubThread(1, kNumOperations + 1, &atomic_value)); - - for (int i = 0; i < threads.size(); ++i) { - threads[i]->Start(); - } - - for (int i = 0; i < threads.size(); ++i) { - threads[i]->Join(); - } - // Cleanup threads. - for (int i = 0; i < threads.size(); ++i) { - delete threads[i]; - } - threads.clear(); - - // After an equal number of decrements and increments, the final value should - // be 0. - ASSERT_EQ(0, atomic_value.load()); -} - -} // namespace -} // namespace nplb -} // namespace starboard diff --git a/starboard/nplb/atomic_test.cc b/starboard/nplb/atomic_test.cc deleted file mode 100644 index d8ea8db439e36..0000000000000 --- a/starboard/nplb/atomic_test.cc +++ /dev/null @@ -1,473 +0,0 @@ -// Copyright 2016 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Adapted from base's atomicops_unittest. - -#include -#include - -#include "starboard/common/atomic.h" -#include "starboard/thread.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace starboard { -namespace nplb { -namespace { - -// Sets up an empty test fixture, required for typed tests. -// BasicSbAtomicTest contains test cases all enabled atomic types should pass. -template -class BasicSbAtomicTest : public testing::Test { - public: - BasicSbAtomicTest() {} - virtual ~BasicSbAtomicTest() {} -}; - -// AdvancedSbAtomicTest provides test coverage for all atomic functions. -// Atomic8 is right now the only atomic type not required to pass -// AdvancedSbAtomicTest, as it does not support implementations for the full -// set of atomic functions like the other types do. -template -class AdvancedSbAtomicTest : public BasicSbAtomicTest { - public: - AdvancedSbAtomicTest() {} - virtual ~AdvancedSbAtomicTest() {} -}; - -typedef testing::Types - BasicSbAtomicTestTypes; -typedef testing::Types - AdvancedSbAtomicTestTypes; - -TYPED_TEST_CASE(BasicSbAtomicTest, BasicSbAtomicTestTypes); - -TYPED_TEST_CASE(AdvancedSbAtomicTest, AdvancedSbAtomicTestTypes); - -// Return an SbAtomicType with the value 0xa5a5a5... -template -SbAtomicType TestFillValue() { - SbAtomicType val = 0; - memset(&val, 0xa5, sizeof(SbAtomicType)); - return val; -} - -// Returns the number of bits in a type. -template -T Bits() { - return (sizeof(T) * 8); -} - -// Returns a value with the high bit |bits| from the most significant bit set. -template -SbAtomicType GetHighBitAt(int bits) { - return (SbAtomicType(1) << (Bits() - (bits + 1))); -} - -// Produces a test value that has non-zero bits in both halves, for testing -// 64-bit implementation on 32-bit platforms. -template -SbAtomicType GetTestValue() { - return GetHighBitAt(1) + 11; -} - -TYPED_TEST(BasicSbAtomicTest, ReleaseCompareAndSwapSingleThread) { - TypeParam value = 0; - TypeParam prev = atomic::Release_CompareAndSwap(&value, 0, 1); - EXPECT_EQ(1, value); - EXPECT_EQ(0, prev); - - const TypeParam kTestValue = GetTestValue(); - value = kTestValue; - prev = atomic::Release_CompareAndSwap(&value, 0, 5); - EXPECT_EQ(kTestValue, value); - EXPECT_EQ(kTestValue, prev); - - value = kTestValue; - prev = atomic::Release_CompareAndSwap(&value, kTestValue, 5); - EXPECT_EQ(5, value); - EXPECT_EQ(kTestValue, prev); -} - -TYPED_TEST(BasicSbAtomicTest, NoBarrierStoreSingleThread) { - const TypeParam kVal1 = TestFillValue(); - const TypeParam kVal2 = static_cast(-1); - - TypeParam value; - - atomic::NoBarrier_Store(&value, kVal1); - EXPECT_EQ(kVal1, value); - atomic::NoBarrier_Store(&value, kVal2); - EXPECT_EQ(kVal2, value); -} - -TYPED_TEST(BasicSbAtomicTest, NoBarrierLoadSingleThread) { - const TypeParam kVal1 = TestFillValue(); - const TypeParam kVal2 = static_cast(-1); - - TypeParam value; - - value = kVal1; - EXPECT_EQ(kVal1, atomic::NoBarrier_Load(&value)); - value = kVal2; - EXPECT_EQ(kVal2, atomic::NoBarrier_Load(&value)); -} - -TYPED_TEST(AdvancedSbAtomicTest, IncrementSingleThread) { - // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go - // outside the expected address bounds. This is in particular to - // test that some future change to the asm code doesn't cause the - // 32-bit NoBarrier_AtomicIncrement doesn't do the wrong thing on 64-bit - // machines. - struct { - TypeParam prev_word; - TypeParam count; - TypeParam next_word; - } s; - - TypeParam prev_word_value, next_word_value; - memset(&prev_word_value, 0xFF, sizeof(TypeParam)); - memset(&next_word_value, 0xEE, sizeof(TypeParam)); - - s.prev_word = prev_word_value; - s.count = 0; - s.next_word = next_word_value; - - EXPECT_EQ(atomic::NoBarrier_Increment(&s.count, 1), 1); - EXPECT_EQ(s.count, 1); - EXPECT_EQ(s.prev_word, prev_word_value); - EXPECT_EQ(s.next_word, next_word_value); - - EXPECT_EQ(atomic::NoBarrier_Increment(&s.count, 2), 3); - EXPECT_EQ(s.count, 3); - EXPECT_EQ(s.prev_word, prev_word_value); - EXPECT_EQ(s.next_word, next_word_value); - - EXPECT_EQ(atomic::NoBarrier_Increment(&s.count, 3), 6); - EXPECT_EQ(s.count, 6); - EXPECT_EQ(s.prev_word, prev_word_value); - EXPECT_EQ(s.next_word, next_word_value); - - EXPECT_EQ(atomic::NoBarrier_Increment(&s.count, -3), 3); - EXPECT_EQ(s.count, 3); - EXPECT_EQ(s.prev_word, prev_word_value); - EXPECT_EQ(s.next_word, next_word_value); - - EXPECT_EQ(atomic::NoBarrier_Increment(&s.count, -2), 1); - EXPECT_EQ(s.count, 1); - EXPECT_EQ(s.prev_word, prev_word_value); - EXPECT_EQ(s.next_word, next_word_value); - - EXPECT_EQ(atomic::NoBarrier_Increment(&s.count, -1), 0); - EXPECT_EQ(s.count, 0); - EXPECT_EQ(s.prev_word, prev_word_value); - EXPECT_EQ(s.next_word, next_word_value); - - EXPECT_EQ(atomic::NoBarrier_Increment(&s.count, -1), -1); - EXPECT_EQ(s.count, -1); - EXPECT_EQ(s.prev_word, prev_word_value); - EXPECT_EQ(s.next_word, next_word_value); - - EXPECT_EQ(atomic::NoBarrier_Increment(&s.count, -4), -5); - EXPECT_EQ(s.count, -5); - EXPECT_EQ(s.prev_word, prev_word_value); - EXPECT_EQ(s.next_word, next_word_value); - - EXPECT_EQ(atomic::NoBarrier_Increment(&s.count, 5), 0); - EXPECT_EQ(s.count, 0); - EXPECT_EQ(s.prev_word, prev_word_value); - EXPECT_EQ(s.next_word, next_word_value); -} - -TYPED_TEST(AdvancedSbAtomicTest, NoBarrierCompareAndSwapSingleThread) { - TypeParam value = 0; - TypeParam prev = atomic::NoBarrier_CompareAndSwap(&value, 0, 1); - EXPECT_EQ(1, value); - EXPECT_EQ(0, prev); - - const TypeParam kTestValue = GetTestValue(); - value = kTestValue; - prev = atomic::NoBarrier_CompareAndSwap(&value, 0, 5); - EXPECT_EQ(kTestValue, value); - EXPECT_EQ(kTestValue, prev); - - value = kTestValue; - prev = atomic::NoBarrier_CompareAndSwap(&value, kTestValue, 5); - EXPECT_EQ(5, value); - EXPECT_EQ(kTestValue, prev); -} - -TYPED_TEST(AdvancedSbAtomicTest, ExchangeSingleThread) { - TypeParam value = 0; - TypeParam new_value = atomic::NoBarrier_Exchange(&value, 1); - EXPECT_EQ(1, value); - EXPECT_EQ(0, new_value); - - const TypeParam kTestValue = GetTestValue(); - value = kTestValue; - new_value = atomic::NoBarrier_Exchange(&value, kTestValue); - EXPECT_EQ(kTestValue, value); - EXPECT_EQ(kTestValue, new_value); - - value = kTestValue; - new_value = atomic::NoBarrier_Exchange(&value, 5); - EXPECT_EQ(5, value); - EXPECT_EQ(kTestValue, new_value); -} - -TYPED_TEST(AdvancedSbAtomicTest, IncrementBoundsSingleThread) { - // Test at rollover boundary between int_max and int_min - TypeParam test_val = GetHighBitAt(0); - TypeParam value = -1 ^ test_val; - TypeParam new_value = atomic::NoBarrier_Increment(&value, 1); - EXPECT_EQ(test_val, value); - EXPECT_EQ(value, new_value); - - atomic::NoBarrier_Increment(&value, -1); - EXPECT_EQ(-1 ^ test_val, value); - - // Test at 32-bit boundary for 64-bit atomic type. - test_val = SB_UINT64_C(1) << (Bits() / 2); - value = test_val - 1; - new_value = atomic::NoBarrier_Increment(&value, 1); - EXPECT_EQ(test_val, value); - EXPECT_EQ(value, new_value); - - atomic::NoBarrier_Increment(&value, -1); - EXPECT_EQ(test_val - 1, value); -} - -TYPED_TEST(AdvancedSbAtomicTest, BarrierStoreSingleThread) { - const TypeParam kVal1 = TestFillValue(); - const TypeParam kVal2 = static_cast(-1); - - TypeParam value; - - atomic::Acquire_Store(&value, kVal1); - EXPECT_EQ(kVal1, value); - atomic::Acquire_Store(&value, kVal2); - EXPECT_EQ(kVal2, value); - - atomic::Release_Store(&value, kVal1); - EXPECT_EQ(kVal1, value); - atomic::Release_Store(&value, kVal2); - EXPECT_EQ(kVal2, value); -} - -TYPED_TEST(AdvancedSbAtomicTest, BarrierLoadSingleThread) { - const TypeParam kVal1 = TestFillValue(); - const TypeParam kVal2 = static_cast(-1); - - TypeParam value; - - value = kVal1; - EXPECT_EQ(kVal1, atomic::Acquire_Load(&value)); - value = kVal2; - EXPECT_EQ(kVal2, atomic::Acquire_Load(&value)); - - value = kVal1; - EXPECT_EQ(kVal1, atomic::Release_Load(&value)); - value = kVal2; - EXPECT_EQ(kVal2, atomic::Release_Load(&value)); -} - -// Uses |state| to control initialization of |out_data| to |data| from multiple -// threads. This function was adapted from base/lazy_instance, to ensure I got -// the barrier operations correct. -template -void SetData(SbAtomicType* state, - char* out_data, - const char* data, - int data_size) { - const SbAtomicType kUninitialized = 0; - const SbAtomicType kInitializing = 1; - const SbAtomicType kInitialized = 2; - - // Try to grab the initialization. If we're the first, will go from - // kUninitialized to kInitializing, otherwise we've been beaten. The memory - // access has no memory ordering as kUninitialized and kInitializing have no - // associated data (memory barriers are all about ordering of memory accesses - // to *associated* data). - if (atomic::NoBarrier_CompareAndSwap(state, kUninitialized, kInitializing) == - kUninitialized) { - // We've locked the state, now we will initialize the data. - memcpy(out_data, data, data_size); - // Signal the initialization has completed. - atomic::Release_Store(state, kInitialized); - return; - } - - // It's either in the process of initializing, or already initialized. Spin. - // The load has acquire memory ordering as a thread which sees state_ == - // kInitialized needs to acquire visibility over the associated data - // (out_data). The paired Release_Store is above in the initialization - // clause. - while (atomic::Acquire_Load(state) == kInitializing) { - sched_yield(); - } -} - -// A struct to pass through all the thread parameters. -template -struct TestOnceContext { - const char* data; - char* out_data; - SbAtomicType* state; - int size; -}; - -// The entry point for all the threads spawned during TestOnce(). -template -void* TestOnceEntryPoint(void* raw_context) { - pthread_setname_np(pthread_self(), "TestOnceThread"); - // Force every thread to sleep immediately so the first thread doesn't always - // just win. - usleep(1000); - TestOnceContext* context = - reinterpret_cast*>(raw_context); - SetData(context->state, context->out_data, context->data, context->size); - return NULL; -} - -// Tests a "once"-like functionality implemented with Atomics. This should -// effectively test multi-threaded CompareAndSwap, Release_Store and -// Acquire_Load. -TYPED_TEST(AdvancedSbAtomicTest, OnceMultipleThreads) { - const int kNumTrials = 25; - const int kNumThreads = 12; - // Ensure each thread has slightly different data by offsetting it a bit as - // the 256-value pattern repeats. - const int kDataPerThread = 65534; - const int kTotalData = kDataPerThread * kNumThreads; - - for (int trial = 0; trial < kNumTrials; ++trial) { - // The control variable to use atomics to synchronize on. - TypeParam state = 0; - - // The target buffer to store the data. - char* target_data = new char[kDataPerThread]; - memset(target_data, 0, kDataPerThread); - - // Each thread has a different set of data that it will try to set. - char* data = new char[kTotalData]; - for (int i = 0; i < kTotalData; ++i) { - data[i] = static_cast(i & 0xFF); - } - - // Start up kNumThreads to fight over initializing |target_data|. - TestOnceContext contexts[kNumThreads] = {0}; - pthread_t threads[kNumThreads] = {0}; - for (int i = 0; i < kNumThreads; ++i) { - contexts[i].data = data + i * kDataPerThread; - contexts[i].out_data = target_data; - contexts[i].state = &state; - contexts[i].size = kDataPerThread; - pthread_create(&threads[i], nullptr, TestOnceEntryPoint, - &(contexts[i])); - EXPECT_TRUE(threads[i] != 0); - } - - // Wait for all threads to complete, and clean up their resources. - for (int i = 0; i < kNumThreads; ++i) { - EXPECT_EQ(pthread_join(threads[i], NULL), 0); - } - - // Ensure that exactly one thread initialized the data. - bool match = false; - for (int i = 0; i < kNumThreads; ++i) { - if (memcmp(target_data, data + i * kDataPerThread, kDataPerThread) == 0) { - match = true; - break; - } - } - - EXPECT_TRUE(match) << "trial " << trial; - delete[] data; - delete[] target_data; - } -} - -const int kNumIncrements = 4000; - -template -void* IncrementEntryPoint(void* raw_context) { - pthread_setname_np(pthread_self(), "TestIncrementThread"); - SbAtomicType* target = reinterpret_cast(raw_context); - for (int i = 0; i < kNumIncrements; ++i) { - atomic::NoBarrier_Increment(target, 1); - } - return NULL; -} - -template -void* DecrementEntryPoint(void* raw_context) { - pthread_setname_np(pthread_self(), "TestDecrementThread"); - SbAtomicType* target = reinterpret_cast(raw_context); - for (int i = 0; i < kNumIncrements; ++i) { - atomic::NoBarrier_Increment(target, -1); - } - return NULL; -} - -TYPED_TEST(AdvancedSbAtomicTest, IncrementDecrementMultipleThreads) { - const int kNumTrials = 15; - const int kNumThreads = 12; - SB_COMPILE_ASSERT(kNumThreads % 2 == 0, kNumThreads_is_even); - - const TypeParam kTestValue = GetTestValue(); - for (int trial = 0; trial < kNumTrials; ++trial) { - // The control variable to increment and decrement. - TypeParam value = kTestValue; - - // Start up kNumThreads to fight. - pthread_t threads[kNumThreads] = {0}; - - // First half are incrementers. - for (int i = 0; i < kNumThreads / 2; ++i) { - pthread_create(&threads[i], nullptr, IncrementEntryPoint, - &value); - EXPECT_TRUE(threads[i] != 0); - } - - // Second half are decrementers. - for (int i = kNumThreads / 2; i < kNumThreads; ++i) { - pthread_create(&threads[i], nullptr, DecrementEntryPoint, - &value); - EXPECT_TRUE(threads[i] != 0); - } - - // Wait for all threads to complete, and clean up their resources. - for (int i = 0; i < kNumThreads; ++i) { - EXPECT_EQ(pthread_join(threads[i], NULL), 0); - } - - // |value| should be back to its original value. If the increment/decrement - // isn't atomic, then the value should drift as the load + increment + store - // operations collide in funny ways. - EXPECT_EQ(kTestValue, value) << "trial " << trial; - } -} - -} // namespace -} // namespace nplb -} // namespace starboard diff --git a/starboard/raspi/shared/BUILD.gn b/starboard/raspi/shared/BUILD.gn index 99a78548cdb53..d9239cef22e16 100644 --- a/starboard/raspi/shared/BUILD.gn +++ b/starboard/raspi/shared/BUILD.gn @@ -77,7 +77,6 @@ static_library("starboard_platform_sources") { "//starboard/shared/alsa/alsa_util.cc", "//starboard/shared/alsa/alsa_util.h", "//starboard/shared/egl/system_egl.cc", - "//starboard/shared/gcc/atomic_gcc_public.h", "//starboard/shared/iso/memory_allocate_unchecked.cc", "//starboard/shared/iso/memory_free.cc", "//starboard/shared/iso/memory_reallocate_unchecked.cc", diff --git a/starboard/shared/gcc/atomic_gcc_public.h b/starboard/shared/gcc/atomic_gcc_public.h deleted file mode 100644 index a6c520e20c487..0000000000000 --- a/starboard/shared/gcc/atomic_gcc_public.h +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2015 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_SHARED_GCC_ATOMIC_GCC_PUBLIC_H_ -#define STARBOARD_SHARED_GCC_ATOMIC_GCC_PUBLIC_H_ - -#include "starboard/atomic.h" - -#ifdef __cplusplus -extern "C" { -#endif - -static SB_C_FORCE_INLINE SbAtomic32 -SbAtomicNoBarrier_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); - return old_value; -} - -static SB_C_FORCE_INLINE SbAtomic32 -SbAtomicNoBarrier_Exchange(volatile SbAtomic32* ptr, SbAtomic32 new_value) { - return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED); -} - -static SB_C_FORCE_INLINE SbAtomic32 -SbAtomicNoBarrier_Increment(volatile SbAtomic32* ptr, SbAtomic32 increment) { - return increment + __atomic_fetch_add(ptr, increment, __ATOMIC_RELAXED); -} - -static SB_C_FORCE_INLINE SbAtomic32 -SbAtomicBarrier_Increment(volatile SbAtomic32* ptr, SbAtomic32 increment) { - return increment + __atomic_fetch_add(ptr, increment, __ATOMIC_SEQ_CST); -} - -static SB_C_FORCE_INLINE SbAtomic32 -SbAtomicAcquire_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); - return old_value; -} - -static SB_C_FORCE_INLINE SbAtomic32 -SbAtomicRelease_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_RELEASE, __ATOMIC_RELAXED); - return old_value; -} - -static SB_C_FORCE_INLINE void SbAtomicMemoryBarrier() { - __atomic_thread_fence(__ATOMIC_SEQ_CST); -} - -static SB_C_FORCE_INLINE void SbAtomicNoBarrier_Store(volatile SbAtomic32* ptr, - SbAtomic32 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELAXED); -} - -static SB_C_FORCE_INLINE void SbAtomicAcquire_Store(volatile SbAtomic32* ptr, - SbAtomic32 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELAXED); - SbAtomicMemoryBarrier(); -} - -static SB_C_FORCE_INLINE void SbAtomicRelease_Store(volatile SbAtomic32* ptr, - SbAtomic32 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELEASE); -} - -static SB_C_FORCE_INLINE SbAtomic32 -SbAtomicNoBarrier_Load(volatile const SbAtomic32* ptr) { - return __atomic_load_n(ptr, __ATOMIC_RELAXED); -} - -static SB_C_FORCE_INLINE SbAtomic32 -SbAtomicAcquire_Load(volatile const SbAtomic32* ptr) { - return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); -} - -static SB_C_FORCE_INLINE SbAtomic32 -SbAtomicRelease_Load(volatile const SbAtomic32* ptr) { - SbAtomicMemoryBarrier(); - return __atomic_load_n(ptr, __ATOMIC_RELAXED); -} - -// 8-bit atomic operations. -static SB_C_FORCE_INLINE SbAtomic8 -SbAtomicRelease_CompareAndSwap8(volatile SbAtomic8* ptr, - SbAtomic8 old_value, - SbAtomic8 new_value) { - bool result = __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_RELEASE, __ATOMIC_RELAXED); - SB_UNREFERENCED_PARAMETER(result); // Make gcc compiler happy. - return old_value; -} - -static SB_C_FORCE_INLINE void SbAtomicNoBarrier_Store8(volatile SbAtomic8* ptr, - SbAtomic8 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELAXED); -} - -static SB_C_FORCE_INLINE SbAtomic8 -SbAtomicNoBarrier_Load8(volatile const SbAtomic8* ptr) { - return __atomic_load_n(ptr, __ATOMIC_RELAXED); -} - -// 64-bit atomic operations (only available on 64-bit processors). -#if SB_HAS(64_BIT_ATOMICS) -static SB_C_FORCE_INLINE SbAtomic64 -SbAtomicNoBarrier_CompareAndSwap64(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); - return old_value; -} - -static SB_C_FORCE_INLINE SbAtomic64 -SbAtomicNoBarrier_Exchange64(volatile SbAtomic64* ptr, SbAtomic64 new_value) { - return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED); -} - -static SB_C_FORCE_INLINE SbAtomic64 -SbAtomicNoBarrier_Increment64(volatile SbAtomic64* ptr, SbAtomic64 increment) { - return increment + __atomic_fetch_add(ptr, increment, __ATOMIC_RELAXED); -} - -static SB_C_FORCE_INLINE SbAtomic64 -SbAtomicBarrier_Increment64(volatile SbAtomic64* ptr, SbAtomic64 increment) { - return increment + __atomic_fetch_add(ptr, increment, __ATOMIC_SEQ_CST); -} - -static SB_C_FORCE_INLINE SbAtomic64 -SbAtomicAcquire_CompareAndSwap64(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); - return old_value; -} - -static SB_C_FORCE_INLINE SbAtomic64 -SbAtomicRelease_CompareAndSwap64(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_RELEASE, __ATOMIC_RELAXED); - return old_value; -} - -static SB_C_FORCE_INLINE void SbAtomicNoBarrier_Store64( - volatile SbAtomic64* ptr, - SbAtomic64 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELAXED); -} - -static SB_C_FORCE_INLINE void SbAtomicAcquire_Store64(volatile SbAtomic64* ptr, - SbAtomic64 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELAXED); - SbAtomicMemoryBarrier(); -} - -static SB_C_FORCE_INLINE void SbAtomicRelease_Store64(volatile SbAtomic64* ptr, - SbAtomic64 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELEASE); -} - -static SB_C_FORCE_INLINE SbAtomic64 -SbAtomicNoBarrier_Load64(volatile const SbAtomic64* ptr) { - return __atomic_load_n(ptr, __ATOMIC_RELAXED); -} - -static SB_C_FORCE_INLINE SbAtomic64 -SbAtomicAcquire_Load64(volatile const SbAtomic64* ptr) { - return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); -} - -static SB_C_FORCE_INLINE SbAtomic64 -SbAtomicRelease_Load64(volatile const SbAtomic64* ptr) { - SbAtomicMemoryBarrier(); - return __atomic_load_n(ptr, __ATOMIC_RELAXED); -} -#endif // SB_HAS(64_BIT_ATOMICS) - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // STARBOARD_SHARED_GCC_ATOMIC_GCC_PUBLIC_H_ diff --git a/starboard/shared/stub/atomic_public.h b/starboard/shared/stub/atomic_public.h deleted file mode 100644 index 1b7a2a5619516..0000000000000 --- a/starboard/shared/stub/atomic_public.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2016 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_SHARED_STUB_ATOMIC_PUBLIC_H_ -#define STARBOARD_SHARED_STUB_ATOMIC_PUBLIC_H_ - -#include "starboard/atomic.h" - -#ifdef __cplusplus -extern "C" { -#endif - -SB_C_FORCE_INLINE SbAtomic32 -SbAtomicNoBarrier_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic32 -SbAtomicNoBarrier_Exchange(volatile SbAtomic32* ptr, SbAtomic32 new_value) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic32 -SbAtomicNoBarrier_Increment(volatile SbAtomic32* ptr, SbAtomic32 increment) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic32 SbAtomicBarrier_Increment(volatile SbAtomic32* ptr, - SbAtomic32 increment) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic32 -SbAtomicAcquire_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic32 -SbAtomicRelease_CompareAndSwap(volatile SbAtomic32* ptr, - SbAtomic32 old_value, - SbAtomic32 new_value) { - return 0; -} - -SB_C_FORCE_INLINE void SbAtomicMemoryBarrier() {} - -SB_C_FORCE_INLINE void SbAtomicNoBarrier_Store(volatile SbAtomic32* ptr, - SbAtomic32 value) {} - -SB_C_FORCE_INLINE void SbAtomicAcquire_Store(volatile SbAtomic32* ptr, - SbAtomic32 value) {} - -SB_C_FORCE_INLINE void SbAtomicRelease_Store(volatile SbAtomic32* ptr, - SbAtomic32 value) {} - -SB_C_FORCE_INLINE SbAtomic32 -SbAtomicNoBarrier_Load(volatile const SbAtomic32* ptr) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic32 -SbAtomicAcquire_Load(volatile const SbAtomic32* ptr) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic32 -SbAtomicRelease_Load(volatile const SbAtomic32* ptr) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic8 -SbAtomicRelease_CompareAndSwap8(volatile SbAtomic8* ptr, - SbAtomic8 old_value, - SbAtomic8 new_value) { - return 0; -} - -SB_C_FORCE_INLINE void SbAtomicNoBarrier_Store8(volatile SbAtomic8* ptr, - SbAtomic8 value) {} - -SB_C_FORCE_INLINE SbAtomic8 -SbAtomicNoBarrier_Load8(volatile const SbAtomic8* ptr) { - return 0; -} - -// 64-bit atomic operations (only available on 64-bit processors). -#if SB_HAS(64_BIT_ATOMICS) -SB_C_FORCE_INLINE SbAtomic64 -SbAtomicNoBarrier_CompareAndSwap64(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic64 -SbAtomicNoBarrier_Exchange64(volatile SbAtomic64* ptr, SbAtomic64 new_value) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic64 -SbAtomicNoBarrier_Increment64(volatile SbAtomic64* ptr, SbAtomic64 increment) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic64 -SbAtomicBarrier_Increment64(volatile SbAtomic64* ptr, SbAtomic64 increment) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic64 -SbAtomicAcquire_CompareAndSwap64(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic64 -SbAtomicRelease_CompareAndSwap64(volatile SbAtomic64* ptr, - SbAtomic64 old_value, - SbAtomic64 new_value) { - return 0; -} - -SB_C_FORCE_INLINE void SbAtomicNoBarrier_Store64(volatile SbAtomic64* ptr, - SbAtomic64 value) {} - -SB_C_FORCE_INLINE void SbAtomicAcquire_Store64(volatile SbAtomic64* ptr, - SbAtomic64 value) {} - -SB_C_FORCE_INLINE void SbAtomicRelease_Store64(volatile SbAtomic64* ptr, - SbAtomic64 value) {} - -SB_C_FORCE_INLINE SbAtomic64 -SbAtomicNoBarrier_Load64(volatile const SbAtomic64* ptr) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic64 -SbAtomicAcquire_Load64(volatile const SbAtomic64* ptr) { - return 0; -} - -SB_C_FORCE_INLINE SbAtomic64 -SbAtomicRelease_Load64(volatile const SbAtomic64* ptr) { - return 0; -} -#endif // SB_HAS(64_BIT_ATOMICS) - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // STARBOARD_SHARED_STUB_ATOMIC_PUBLIC_H_