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 12 namespace base { 13 namespace subtle { 14 15 inline 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 27 inline 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 36 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, 37 Atomic32 increment) { 38 return Barrier_AtomicIncrement(ptr, increment); 39 } 40 41 inline 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 55 inline 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 63 inline 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 69 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { 70 *ptr = value; 71 } 72 73 inline void MemoryBarrier() { 74 __sync_synchronize(); 75 } 76 77 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { 78 *ptr = value; 79 MemoryBarrier(); 80 } 81 82 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { 83 MemoryBarrier(); 84 *ptr = value; 85 } 86 87 inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { 88 return *ptr; 89 } 90 91 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { 92 Atomic32 value = *ptr; 93 MemoryBarrier(); 94 return value; 95 } 96 97 inline 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