15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2009 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is an internal atomic implementation, include base/atomicops.h
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instead. This file is for platforms that use GCC intrinsics rather than
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// platform-specific assembly code for atomic operations.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_ATOMICOPS_INTERNALS_GCC_H_
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_ATOMICOPS_INTERNALS_GCC_H_
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace subtle {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Atomic32 old_value,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Atomic32 new_value) {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic32 prev_value;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (__sync_bool_compare_and_swap(ptr, old_value, new_value))
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return old_value;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_value = *ptr;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (prev_value == old_value);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return prev_value;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Atomic32 new_value) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic32 old_value;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_value = *ptr;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (!__sync_bool_compare_and_swap(ptr, old_value, new_value));
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return old_value;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          Atomic32 increment) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Barrier_AtomicIncrement(ptr, increment);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        Atomic32 increment) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Atomic exchange the old value with an incremented one.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Atomic32 old_value = *ptr;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Atomic32 new_value = old_value + increment;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The exchange took place as expected.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return new_value;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Otherwise, *ptr changed mid-loop and we need to retry.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic32 old_value,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic32 new_value) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since NoBarrier_CompareAndSwap uses __sync_bool_compare_and_swap, which
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is a full memory barrier, none is needed here or below in Release.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic32 old_value,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic32 new_value) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = value;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void MemoryBarrier() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __sync_synchronize();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = value;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = value;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *ptr;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic32 value = *ptr;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *ptr;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base::subtle
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_ATOMICOPS_INTERNALS_GCC_H_
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
107