1// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// This file is an internal atomic implementation, include base/atomicops.h 6// instead. This file is for platforms that use GCC intrinsics rather than 7// platform-specific assembly code for atomic operations. 8 9#ifndef BASE_ATOMICOPS_INTERNALS_GCC_H_ 10#define BASE_ATOMICOPS_INTERNALS_GCC_H_ 11 12namespace base { 13namespace subtle { 14 15inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, 16 Atomic32 old_value, 17 Atomic32 new_value) { 18 Atomic32 prev_value; 19 do { 20 if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) 21 return old_value; 22 prev_value = *ptr; 23 } while (prev_value == old_value); 24 return prev_value; 25} 26 27inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, 28 Atomic32 new_value) { 29 Atomic32 old_value; 30 do { 31 old_value = *ptr; 32 } while (!__sync_bool_compare_and_swap(ptr, old_value, new_value)); 33 return old_value; 34} 35 36inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, 37 Atomic32 increment) { 38 return Barrier_AtomicIncrement(ptr, increment); 39} 40 41inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, 42 Atomic32 increment) { 43 for (;;) { 44 // Atomic exchange the old value with an incremented one. 45 Atomic32 old_value = *ptr; 46 Atomic32 new_value = old_value + increment; 47 if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) { 48 // The exchange took place as expected. 49 return new_value; 50 } 51 // Otherwise, *ptr changed mid-loop and we need to retry. 52 } 53} 54 55inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, 56 Atomic32 old_value, 57 Atomic32 new_value) { 58 // Since NoBarrier_CompareAndSwap uses __sync_bool_compare_and_swap, which 59 // is a full memory barrier, none is needed here or below in Release. 60 return NoBarrier_CompareAndSwap(ptr, old_value, new_value); 61} 62 63inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, 64 Atomic32 old_value, 65 Atomic32 new_value) { 66 return NoBarrier_CompareAndSwap(ptr, old_value, new_value); 67} 68 69inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { 70 *ptr = value; 71} 72 73inline void MemoryBarrier() { 74 __sync_synchronize(); 75} 76 77inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { 78 *ptr = value; 79 MemoryBarrier(); 80} 81 82inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { 83 MemoryBarrier(); 84 *ptr = value; 85} 86 87inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { 88 return *ptr; 89} 90 91inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { 92 Atomic32 value = *ptr; 93 MemoryBarrier(); 94 return value; 95} 96 97inline Atomic32 Release_Load(volatile const Atomic32* ptr) { 98 MemoryBarrier(); 99 return *ptr; 100} 101 102} // namespace base::subtle 103} // namespace base 104 105#endif // BASE_ATOMICOPS_INTERNALS_GCC_H_ 106 107