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_ |
+ |