ipc/chromium/src/base/atomicops_internals_arm_gcc.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/chromium/src/base/atomicops_internals_arm_gcc.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,124 @@
     1.4 +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +// This file is an internal atomic implementation, use base/atomicops.h instead.
     1.9 +//
    1.10 +// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
    1.11 +
    1.12 +#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
    1.13 +#define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
    1.14 +
    1.15 +namespace base {
    1.16 +namespace subtle {
    1.17 +
    1.18 +// 0xffff0fc0 is the hard coded address of a function provided by
    1.19 +// the kernel which implements an atomic compare-exchange. On older
    1.20 +// ARM architecture revisions (pre-v6) this may be implemented using
    1.21 +// a syscall. This address is stable, and in active use (hard coded)
    1.22 +// by at least glibc-2.7 and the Android C library.
    1.23 +typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value,
    1.24 +                                           Atomic32 new_value,
    1.25 +                                           volatile Atomic32* ptr);
    1.26 +LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) =
    1.27 +    (LinuxKernelCmpxchgFunc) 0xffff0fc0;
    1.28 +
    1.29 +typedef void (*LinuxKernelMemoryBarrierFunc)(void);
    1.30 +LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) =
    1.31 +    (LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
    1.32 +
    1.33 +
    1.34 +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
    1.35 +                                         Atomic32 old_value,
    1.36 +                                         Atomic32 new_value) {
    1.37 +  Atomic32 prev_value = *ptr;
    1.38 +  do {
    1.39 +    if (!pLinuxKernelCmpxchg(old_value, new_value,
    1.40 +                             const_cast<Atomic32*>(ptr))) {
    1.41 +      return old_value;
    1.42 +    }
    1.43 +    prev_value = *ptr;
    1.44 +  } while (prev_value == old_value);
    1.45 +  return prev_value;
    1.46 +}
    1.47 +
    1.48 +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
    1.49 +                                         Atomic32 new_value) {
    1.50 +  Atomic32 old_value;
    1.51 +  do {
    1.52 +    old_value = *ptr;
    1.53 +  } while (pLinuxKernelCmpxchg(old_value, new_value,
    1.54 +                               const_cast<Atomic32*>(ptr)));
    1.55 +  return old_value;
    1.56 +}
    1.57 +
    1.58 +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
    1.59 +                                          Atomic32 increment) {
    1.60 +  return Barrier_AtomicIncrement(ptr, increment);
    1.61 +}
    1.62 +
    1.63 +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
    1.64 +                                        Atomic32 increment) {
    1.65 +  for (;;) {
    1.66 +    // Atomic exchange the old value with an incremented one.
    1.67 +    Atomic32 old_value = *ptr;
    1.68 +    Atomic32 new_value = old_value + increment;
    1.69 +    if (pLinuxKernelCmpxchg(old_value, new_value,
    1.70 +                            const_cast<Atomic32*>(ptr)) == 0) {
    1.71 +      // The exchange took place as expected.
    1.72 +      return new_value;
    1.73 +    }
    1.74 +    // Otherwise, *ptr changed mid-loop and we need to retry.
    1.75 +  }
    1.76 +
    1.77 +}
    1.78 +
    1.79 +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
    1.80 +                                       Atomic32 old_value,
    1.81 +                                       Atomic32 new_value) {
    1.82 +  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
    1.83 +}
    1.84 +
    1.85 +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
    1.86 +                                       Atomic32 old_value,
    1.87 +                                       Atomic32 new_value) {
    1.88 +  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
    1.89 +}
    1.90 +
    1.91 +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
    1.92 +  *ptr = value;
    1.93 +}
    1.94 +
    1.95 +inline void MemoryBarrier() {
    1.96 +  pLinuxKernelMemoryBarrier();
    1.97 +}
    1.98 +
    1.99 +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
   1.100 +  *ptr = value;
   1.101 +  MemoryBarrier();
   1.102 +}
   1.103 +
   1.104 +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
   1.105 +  MemoryBarrier();
   1.106 +  *ptr = value;
   1.107 +}
   1.108 +
   1.109 +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
   1.110 +  return *ptr;
   1.111 +}
   1.112 +
   1.113 +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
   1.114 +  Atomic32 value = *ptr;
   1.115 +  MemoryBarrier();
   1.116 +  return value;
   1.117 +}
   1.118 +
   1.119 +inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
   1.120 +  MemoryBarrier();
   1.121 +  return *ptr;
   1.122 +}
   1.123 +
   1.124 +} // namespace base::subtle
   1.125 +} // namespace base
   1.126 +
   1.127 +#endif  // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_

mercurial