Chromium Code Reviews| Index: base/atomicops_internals_nacl.h |
| =================================================================== |
| --- base/atomicops_internals_nacl.h (revision 0) |
| +++ base/atomicops_internals_nacl.h (revision 0) |
| @@ -0,0 +1,108 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// 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. |
| + |
| +#ifndef BASE_ATOMICOPS_INTERNALS_NACL_H_ |
| +#define BASE_ATOMICOPS_INTERNALS_NACL_H_ |
| + |
| +// For Native Client, use GCC atomic op intrinsics. |
|
bbudge
2012/08/16 20:44:17
This file is a copy of base/atomicops_internals_ar
jar (doing other things)
2012/08/16 22:47:21
You should at a minimum put this comment in the co
Mark Seaborn
2012/08/17 00:08:24
Is there any reason you can't modify the existing
bbudge
2012/08/21 02:02:07
Done. I added conditional expressions to switch be
bbudge
2012/08/21 02:02:07
Since I have no idea what the strange Linux code t
|
| + |
| +namespace base { |
| +namespace subtle { |
| + |
| +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, |
| + Atomic32 old_value, |
| + Atomic32 new_value) { |
| + Atomic32 prev_value = *ptr; |
| + do { |
| + if (!__sync_val_compare_and_swap(const_cast<Atomic32*>(ptr), |
| + old_value, new_value)) { |
| + return old_value; |
| + } |
| + prev_value = *ptr; |
| + } while (prev_value == old_value); |
| + return prev_value; |
| +} |
| + |
| +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, |
| + Atomic32 new_value) { |
| + Atomic32 old_value; |
| + do { |
| + old_value = *ptr; |
| + } while (__sync_val_compare_and_swap(const_cast<Atomic32*>(ptr), |
| + old_value, new_value)); |
| + return old_value; |
| +} |
| + |
| +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, |
| + Atomic32 increment) { |
| + return Barrier_AtomicIncrement(ptr, increment); |
| +} |
| + |
| +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, |
| + Atomic32 increment) { |
| + for (;;) { |
| + // Atomic exchange the old value with an incremented one. |
| + Atomic32 old_value = *ptr; |
| + Atomic32 new_value = old_value + increment; |
| + if (__sync_val_compare_and_swap(const_cast<Atomic32*>(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, |
| + Atomic32 old_value, |
| + Atomic32 new_value) { |
| + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); |
|
jar (doing other things)
2012/08/16 22:47:21
This was confusing, since Acquire semantics requir
bbudge
2012/08/21 21:49:02
This code is indeed confusing. I succeeded in merg
|
| +} |
| + |
| +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, |
| + Atomic32 old_value, |
| + Atomic32 new_value) { |
| + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); |
| +} |
| + |
| +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { |
| + *ptr = value; |
| +} |
| + |
| +inline void MemoryBarrier() { |
| + __sync_synchronize(); |
| +} |
| + |
| +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { |
| + *ptr = value; |
| + MemoryBarrier(); |
| +} |
| + |
| +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { |
| + MemoryBarrier(); |
| + *ptr = value; |
| +} |
| + |
| +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { |
| + return *ptr; |
| +} |
| + |
| +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { |
| + Atomic32 value = *ptr; |
| + MemoryBarrier(); |
| + return value; |
| +} |
| + |
| +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { |
| + MemoryBarrier(); |
| + return *ptr; |
| +} |
| + |
| +} // namespace base::subtle |
| +} // namespace base |
| + |
| +#endif // BASE_ATOMICOPS_INTERNALS_NACL_H_ |