security/sandbox/chromium/base/atomicops_internals_x86_gcc.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/sandbox/chromium/base/atomicops_internals_x86_gcc.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,269 @@
     1.4 +// Copyright (c) 2011 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 +#ifndef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
    1.11 +#define BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
    1.12 +
    1.13 +#include "base/base_export.h"
    1.14 +
    1.15 +// This struct is not part of the public API of this module; clients may not
    1.16 +// use it.  (However, it's exported via BASE_EXPORT because clients implicitly
    1.17 +// do use it at link time by inlining these functions.)
    1.18 +// Features of this x86.  Values may not be correct before main() is run,
    1.19 +// but are set conservatively.
    1.20 +struct AtomicOps_x86CPUFeatureStruct {
    1.21 +  bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
    1.22 +                            // after acquire compare-and-swap.
    1.23 +  bool has_sse2;            // Processor has SSE2.
    1.24 +};
    1.25 +BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct
    1.26 +    AtomicOps_Internalx86CPUFeatures;
    1.27 +
    1.28 +#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
    1.29 +
    1.30 +namespace base {
    1.31 +namespace subtle {
    1.32 +
    1.33 +// 32-bit low-level operations on any platform.
    1.34 +
    1.35 +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
    1.36 +                                         Atomic32 old_value,
    1.37 +                                         Atomic32 new_value) {
    1.38 +  Atomic32 prev;
    1.39 +  __asm__ __volatile__("lock; cmpxchgl %1,%2"
    1.40 +                       : "=a" (prev)
    1.41 +                       : "q" (new_value), "m" (*ptr), "0" (old_value)
    1.42 +                       : "memory");
    1.43 +  return prev;
    1.44 +}
    1.45 +
    1.46 +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
    1.47 +                                         Atomic32 new_value) {
    1.48 +  __asm__ __volatile__("xchgl %1,%0"  // The lock prefix is implicit for xchg.
    1.49 +                       : "=r" (new_value)
    1.50 +                       : "m" (*ptr), "0" (new_value)
    1.51 +                       : "memory");
    1.52 +  return new_value;  // Now it's the previous value.
    1.53 +}
    1.54 +
    1.55 +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
    1.56 +                                          Atomic32 increment) {
    1.57 +  Atomic32 temp = increment;
    1.58 +  __asm__ __volatile__("lock; xaddl %0,%1"
    1.59 +                       : "+r" (temp), "+m" (*ptr)
    1.60 +                       : : "memory");
    1.61 +  // temp now holds the old value of *ptr
    1.62 +  return temp + increment;
    1.63 +}
    1.64 +
    1.65 +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
    1.66 +                                        Atomic32 increment) {
    1.67 +  Atomic32 temp = increment;
    1.68 +  __asm__ __volatile__("lock; xaddl %0,%1"
    1.69 +                       : "+r" (temp), "+m" (*ptr)
    1.70 +                       : : "memory");
    1.71 +  // temp now holds the old value of *ptr
    1.72 +  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
    1.73 +    __asm__ __volatile__("lfence" : : : "memory");
    1.74 +  }
    1.75 +  return temp + increment;
    1.76 +}
    1.77 +
    1.78 +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
    1.79 +                                       Atomic32 old_value,
    1.80 +                                       Atomic32 new_value) {
    1.81 +  Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
    1.82 +  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
    1.83 +    __asm__ __volatile__("lfence" : : : "memory");
    1.84 +  }
    1.85 +  return x;
    1.86 +}
    1.87 +
    1.88 +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
    1.89 +                                       Atomic32 old_value,
    1.90 +                                       Atomic32 new_value) {
    1.91 +  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
    1.92 +}
    1.93 +
    1.94 +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
    1.95 +  *ptr = value;
    1.96 +}
    1.97 +
    1.98 +#if defined(__x86_64__)
    1.99 +
   1.100 +// 64-bit implementations of memory barrier can be simpler, because it
   1.101 +// "mfence" is guaranteed to exist.
   1.102 +inline void MemoryBarrier() {
   1.103 +  __asm__ __volatile__("mfence" : : : "memory");
   1.104 +}
   1.105 +
   1.106 +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
   1.107 +  *ptr = value;
   1.108 +  MemoryBarrier();
   1.109 +}
   1.110 +
   1.111 +#else
   1.112 +
   1.113 +inline void MemoryBarrier() {
   1.114 +  if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
   1.115 +    __asm__ __volatile__("mfence" : : : "memory");
   1.116 +  } else { // mfence is faster but not present on PIII
   1.117 +    Atomic32 x = 0;
   1.118 +    NoBarrier_AtomicExchange(&x, 0);  // acts as a barrier on PIII
   1.119 +  }
   1.120 +}
   1.121 +
   1.122 +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
   1.123 +  if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
   1.124 +    *ptr = value;
   1.125 +    __asm__ __volatile__("mfence" : : : "memory");
   1.126 +  } else {
   1.127 +    NoBarrier_AtomicExchange(ptr, value);
   1.128 +                          // acts as a barrier on PIII
   1.129 +  }
   1.130 +}
   1.131 +#endif
   1.132 +
   1.133 +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
   1.134 +  ATOMICOPS_COMPILER_BARRIER();
   1.135 +  *ptr = value; // An x86 store acts as a release barrier.
   1.136 +  // See comments in Atomic64 version of Release_Store(), below.
   1.137 +}
   1.138 +
   1.139 +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
   1.140 +  return *ptr;
   1.141 +}
   1.142 +
   1.143 +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
   1.144 +  Atomic32 value = *ptr; // An x86 load acts as a acquire barrier.
   1.145 +  // See comments in Atomic64 version of Release_Store(), below.
   1.146 +  ATOMICOPS_COMPILER_BARRIER();
   1.147 +  return value;
   1.148 +}
   1.149 +
   1.150 +inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
   1.151 +  MemoryBarrier();
   1.152 +  return *ptr;
   1.153 +}
   1.154 +
   1.155 +#if defined(__x86_64__)
   1.156 +
   1.157 +// 64-bit low-level operations on 64-bit platform.
   1.158 +
   1.159 +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
   1.160 +                                         Atomic64 old_value,
   1.161 +                                         Atomic64 new_value) {
   1.162 +  Atomic64 prev;
   1.163 +  __asm__ __volatile__("lock; cmpxchgq %1,%2"
   1.164 +                       : "=a" (prev)
   1.165 +                       : "q" (new_value), "m" (*ptr), "0" (old_value)
   1.166 +                       : "memory");
   1.167 +  return prev;
   1.168 +}
   1.169 +
   1.170 +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
   1.171 +                                         Atomic64 new_value) {
   1.172 +  __asm__ __volatile__("xchgq %1,%0"  // The lock prefix is implicit for xchg.
   1.173 +                       : "=r" (new_value)
   1.174 +                       : "m" (*ptr), "0" (new_value)
   1.175 +                       : "memory");
   1.176 +  return new_value;  // Now it's the previous value.
   1.177 +}
   1.178 +
   1.179 +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
   1.180 +                                          Atomic64 increment) {
   1.181 +  Atomic64 temp = increment;
   1.182 +  __asm__ __volatile__("lock; xaddq %0,%1"
   1.183 +                       : "+r" (temp), "+m" (*ptr)
   1.184 +                       : : "memory");
   1.185 +  // temp now contains the previous value of *ptr
   1.186 +  return temp + increment;
   1.187 +}
   1.188 +
   1.189 +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
   1.190 +                                        Atomic64 increment) {
   1.191 +  Atomic64 temp = increment;
   1.192 +  __asm__ __volatile__("lock; xaddq %0,%1"
   1.193 +                       : "+r" (temp), "+m" (*ptr)
   1.194 +                       : : "memory");
   1.195 +  // temp now contains the previous value of *ptr
   1.196 +  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
   1.197 +    __asm__ __volatile__("lfence" : : : "memory");
   1.198 +  }
   1.199 +  return temp + increment;
   1.200 +}
   1.201 +
   1.202 +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
   1.203 +  *ptr = value;
   1.204 +}
   1.205 +
   1.206 +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
   1.207 +  *ptr = value;
   1.208 +  MemoryBarrier();
   1.209 +}
   1.210 +
   1.211 +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
   1.212 +  ATOMICOPS_COMPILER_BARRIER();
   1.213 +
   1.214 +  *ptr = value; // An x86 store acts as a release barrier
   1.215 +                // for current AMD/Intel chips as of Jan 2008.
   1.216 +                // See also Acquire_Load(), below.
   1.217 +
   1.218 +  // When new chips come out, check:
   1.219 +  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
   1.220 +  //  System Programming Guide, Chatper 7: Multiple-processor management,
   1.221 +  //  Section 7.2, Memory Ordering.
   1.222 +  // Last seen at:
   1.223 +  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
   1.224 +  //
   1.225 +  // x86 stores/loads fail to act as barriers for a few instructions (clflush
   1.226 +  // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
   1.227 +  // not generated by the compiler, and are rare.  Users of these instructions
   1.228 +  // need to know about cache behaviour in any case since all of these involve
   1.229 +  // either flushing cache lines or non-temporal cache hints.
   1.230 +}
   1.231 +
   1.232 +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
   1.233 +  return *ptr;
   1.234 +}
   1.235 +
   1.236 +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
   1.237 +  Atomic64 value = *ptr; // An x86 load acts as a acquire barrier,
   1.238 +                         // for current AMD/Intel chips as of Jan 2008.
   1.239 +                         // See also Release_Store(), above.
   1.240 +  ATOMICOPS_COMPILER_BARRIER();
   1.241 +  return value;
   1.242 +}
   1.243 +
   1.244 +inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
   1.245 +  MemoryBarrier();
   1.246 +  return *ptr;
   1.247 +}
   1.248 +
   1.249 +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
   1.250 +                                       Atomic64 old_value,
   1.251 +                                       Atomic64 new_value) {
   1.252 +  Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
   1.253 +  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
   1.254 +    __asm__ __volatile__("lfence" : : : "memory");
   1.255 +  }
   1.256 +  return x;
   1.257 +}
   1.258 +
   1.259 +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
   1.260 +                                       Atomic64 old_value,
   1.261 +                                       Atomic64 new_value) {
   1.262 +  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
   1.263 +}
   1.264 +
   1.265 +#endif  // defined(__x86_64__)
   1.266 +
   1.267 +} // namespace base::subtle
   1.268 +} // namespace base
   1.269 +
   1.270 +#undef ATOMICOPS_COMPILER_BARRIER
   1.271 +
   1.272 +#endif  // BASE_ATOMICOPS_INTERNALS_X86_GCC_H_

mercurial