Chromium Code Reviews| Index: base/atomicops_internals_gcc.h |
| =================================================================== |
| --- base/atomicops_internals_gcc.h (revision 152192) |
| +++ base/atomicops_internals_gcc.h (working copy) |
| @@ -2,39 +2,34 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -// This file is an internal atomic implementation, use base/atomicops.h instead. |
| -// |
| -// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. |
| +// This file is an internal atomic implementation, include base/atomicops.h |
| +// instead. This file is for platforms that use GCC intrinsics rather than |
| +// platform-specific assembly code for atomic operations. |
| -#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ |
| -#define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ |
| +#ifndef BASE_ATOMICOPS_INTERNALS_GCC_H_ |
| +#define BASE_ATOMICOPS_INTERNALS_GCC_H_ |
| namespace base { |
| namespace subtle { |
| -// 0xffff0fc0 is the hard coded address of a function provided by |
| -// the kernel which implements an atomic compare-exchange. On older |
| -// ARM architecture revisions (pre-v6) this may be implemented using |
| -// a syscall. This address is stable, and in active use (hard coded) |
| -// by at least glibc-2.7 and the Android C library. |
| -typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value, |
| - Atomic32 new_value, |
| - volatile Atomic32* ptr); |
| -LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) = |
| - (LinuxKernelCmpxchgFunc) 0xffff0fc0; |
| +namespace { |
| -typedef void (*LinuxKernelMemoryBarrierFunc)(void); |
| -LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = |
| - (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; |
| +bool Barrier_CompareAndSwap(volatile Atomic32* ptr, |
| + Atomic32 old_value, |
| + Atomic32 new_value) { |
| + // The GCC intrinsic for compare-and-swap is a full memory barrier. |
| + return __sync_bool_compare_and_swap(const_cast<Atomic32*>(ptr), |
|
Roland McGrath
2012/08/21 21:52:59
What's this cast for?
bbudge
2012/08/21 22:06:12
It's a vestige of the old file. As you point out,
|
| + old_value, new_value); |
| +} |
| +} // namespace |
| inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, |
| Atomic32 old_value, |
| Atomic32 new_value) { |
| Atomic32 prev_value = *ptr; |
| do { |
| - if (!pLinuxKernelCmpxchg(old_value, new_value, |
| - const_cast<Atomic32*>(ptr))) { |
| + if (Barrier_CompareAndSwap(ptr, old_value, new_value)) { |
| return old_value; |
| } |
| prev_value = *ptr; |
| @@ -47,8 +42,7 @@ |
| Atomic32 old_value; |
| do { |
| old_value = *ptr; |
| - } while (pLinuxKernelCmpxchg(old_value, new_value, |
| - const_cast<Atomic32*>(ptr))); |
| + } while (!Barrier_CompareAndSwap(ptr, old_value, new_value)); |
| return old_value; |
| } |
| @@ -63,14 +57,12 @@ |
| // Atomic exchange the old value with an incremented one. |
| Atomic32 old_value = *ptr; |
| Atomic32 new_value = old_value + increment; |
| - if (pLinuxKernelCmpxchg(old_value, new_value, |
| - const_cast<Atomic32*>(ptr)) == 0) { |
| + if (!Barrier_CompareAndSwap(ptr, old_value, new_value) == 0) { |
| // The exchange took place as expected. |
| return new_value; |
| } |
| // Otherwise, *ptr changed mid-loop and we need to retry. |
| } |
| - |
| } |
| inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, |
| @@ -90,7 +82,7 @@ |
| } |
| inline void MemoryBarrier() { |
| - pLinuxKernelMemoryBarrier(); |
| + __sync_synchronize(); |
| } |
| inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { |
| @@ -118,7 +110,8 @@ |
| return *ptr; |
| } |
| -} // namespace base::subtle |
| -} // namespace base |
| +} // namespace base::subtle |
| +} // namespace base |
| -#endif // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ |
| +#endif // BASE_ATOMICOPS_INTERNALS_GCC_H_ |
| + |