ipc/chromium/src/base/atomicops_internals_arm_gcc.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 // This file is an internal atomic implementation, use base/atomicops.h instead.
     6 //
     7 // LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
     9 #ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
    10 #define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
    12 namespace base {
    13 namespace subtle {
    15 // 0xffff0fc0 is the hard coded address of a function provided by
    16 // the kernel which implements an atomic compare-exchange. On older
    17 // ARM architecture revisions (pre-v6) this may be implemented using
    18 // a syscall. This address is stable, and in active use (hard coded)
    19 // by at least glibc-2.7 and the Android C library.
    20 typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value,
    21                                            Atomic32 new_value,
    22                                            volatile Atomic32* ptr);
    23 LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) =
    24     (LinuxKernelCmpxchgFunc) 0xffff0fc0;
    26 typedef void (*LinuxKernelMemoryBarrierFunc)(void);
    27 LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) =
    28     (LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
    31 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
    32                                          Atomic32 old_value,
    33                                          Atomic32 new_value) {
    34   Atomic32 prev_value = *ptr;
    35   do {
    36     if (!pLinuxKernelCmpxchg(old_value, new_value,
    37                              const_cast<Atomic32*>(ptr))) {
    38       return old_value;
    39     }
    40     prev_value = *ptr;
    41   } while (prev_value == old_value);
    42   return prev_value;
    43 }
    45 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
    46                                          Atomic32 new_value) {
    47   Atomic32 old_value;
    48   do {
    49     old_value = *ptr;
    50   } while (pLinuxKernelCmpxchg(old_value, new_value,
    51                                const_cast<Atomic32*>(ptr)));
    52   return old_value;
    53 }
    55 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
    56                                           Atomic32 increment) {
    57   return Barrier_AtomicIncrement(ptr, increment);
    58 }
    60 inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
    61                                         Atomic32 increment) {
    62   for (;;) {
    63     // Atomic exchange the old value with an incremented one.
    64     Atomic32 old_value = *ptr;
    65     Atomic32 new_value = old_value + increment;
    66     if (pLinuxKernelCmpxchg(old_value, new_value,
    67                             const_cast<Atomic32*>(ptr)) == 0) {
    68       // The exchange took place as expected.
    69       return new_value;
    70     }
    71     // Otherwise, *ptr changed mid-loop and we need to retry.
    72   }
    74 }
    76 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
    77                                        Atomic32 old_value,
    78                                        Atomic32 new_value) {
    79   return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
    80 }
    82 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
    83                                        Atomic32 old_value,
    84                                        Atomic32 new_value) {
    85   return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
    86 }
    88 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
    89   *ptr = value;
    90 }
    92 inline void MemoryBarrier() {
    93   pLinuxKernelMemoryBarrier();
    94 }
    96 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
    97   *ptr = value;
    98   MemoryBarrier();
    99 }
   101 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
   102   MemoryBarrier();
   103   *ptr = value;
   104 }
   106 inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
   107   return *ptr;
   108 }
   110 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
   111   Atomic32 value = *ptr;
   112   MemoryBarrier();
   113   return value;
   114 }
   116 inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
   117   MemoryBarrier();
   118   return *ptr;
   119 }
   121 } // namespace base::subtle
   122 } // namespace base
   124 #endif  // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_

mercurial