1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2010 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This file is an internal atomic implementation, use atomicops.h instead.
6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochnamespace v8 {
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace base {
12257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This struct is not part of the public API of this module; clients may not
14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// use it.
15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Features of this x86.  Values may not be correct before main() is run,
16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// but are set conservatively.
17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstruct AtomicOps_x86CPUFeatureStruct {
18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool has_amd_lock_mb_bug;  // Processor has AMD memory-barrier bug; do lfence
19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             // after acquire compare-and-swap.
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if !defined(__SSE2__)
21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool has_sse2;             // Processor has SSE2.
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochextern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures;
25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 32-bit low-level operations on any platform.
29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         Atomic32 old_value,
32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         Atomic32 new_value) {
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Atomic32 prev;
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __asm__ __volatile__("lock; cmpxchgl %1,%2"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "=a" (prev)
36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "q" (new_value), "m" (*ptr), "0" (old_value)
37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "memory");
38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return prev;
39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         Atomic32 new_value) {
43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __asm__ __volatile__("xchgl %1,%0"  // The lock prefix is implicit for xchg.
44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "=r" (new_value)
45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "m" (*ptr), "0" (new_value)
46b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "memory");
47b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new_value;  // Now it's the previous value.
48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          Atomic32 increment) {
52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Atomic32 temp = increment;
53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __asm__ __volatile__("lock; xaddl %0,%1"
54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "+r" (temp), "+m" (*ptr)
55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : : "memory");
56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // temp now holds the old value of *ptr
57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return temp + increment;
58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                        Atomic32 increment) {
62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Atomic32 temp = increment;
63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __asm__ __volatile__("lock; xaddl %0,%1"
64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "+r" (temp), "+m" (*ptr)
65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : : "memory");
66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // temp now holds the old value of *ptr
67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __asm__ __volatile__("lfence" : : : "memory");
69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return temp + increment;
71b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       Atomic32 old_value,
75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       Atomic32 new_value) {
76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __asm__ __volatile__("lfence" : : : "memory");
79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return x;
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       Atomic32 old_value,
85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       Atomic32 new_value) {
86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline void NoBarrier_Store(volatile Atomic8* ptr, Atomic8 value) {
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *ptr = value;
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *ptr = value;
95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__x86_64__) || defined(__SSE2__)
98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 64-bit implementations of memory barrier can be simpler, because it
100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "mfence" is guaranteed to exist.
101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void MemoryBarrier() {
102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __asm__ __volatile__("mfence" : : : "memory");
103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *ptr = value;
107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MemoryBarrier();
108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#else
111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void MemoryBarrier() {
113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __asm__ __volatile__("mfence" : : : "memory");
115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {  // mfence is faster but not present on PIII
116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Atomic32 x = 0;
117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    NoBarrier_AtomicExchange(&x, 0);  // acts as a barrier on PIII
118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    *ptr = value;
124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __asm__ __volatile__("mfence" : : : "memory");
125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    NoBarrier_AtomicExchange(ptr, value);
127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          // acts as a barrier on PIII
128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ATOMICOPS_COMPILER_BARRIER();
134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *ptr = value;  // An x86 store acts as a release barrier.
135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // See comments in Atomic64 version of Release_Store(), below.
136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic8 NoBarrier_Load(volatile const Atomic8* ptr) {
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return *ptr;
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return *ptr;
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Atomic32 value = *ptr;  // An x86 load acts as a acquire barrier.
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // See comments in Atomic64 version of Release_Store(), below.
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ATOMICOPS_COMPILER_BARRIER();
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return value;
151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 Release_Load(volatile const Atomic32* ptr) {
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MemoryBarrier();
155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return *ptr;
156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__x86_64__) && defined(V8_HOST_ARCH_64_BIT)
159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 64-bit low-level operations on 64-bit platform.
161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         Atomic64 old_value,
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         Atomic64 new_value) {
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Atomic64 prev;
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __asm__ __volatile__("lock; cmpxchgq %1,%2"
167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "=a" (prev)
168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "q" (new_value), "m" (*ptr), "0" (old_value)
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "memory");
170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return prev;
171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         Atomic64 new_value) {
175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __asm__ __volatile__("xchgq %1,%0"  // The lock prefix is implicit for xchg.
176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "=r" (new_value)
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "m" (*ptr), "0" (new_value)
178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "memory");
179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new_value;  // Now it's the previous value.
180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          Atomic64 increment) {
184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Atomic64 temp = increment;
185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __asm__ __volatile__("lock; xaddq %0,%1"
186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "+r" (temp), "+m" (*ptr)
187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : : "memory");
188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // temp now contains the previous value of *ptr
189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return temp + increment;
190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                        Atomic64 increment) {
194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Atomic64 temp = increment;
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __asm__ __volatile__("lock; xaddq %0,%1"
196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : "+r" (temp), "+m" (*ptr)
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       : : "memory");
198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // temp now contains the previous value of *ptr
199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __asm__ __volatile__("lfence" : : : "memory");
201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return temp + increment;
203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *ptr = value;
207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *ptr = value;
211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MemoryBarrier();
212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ATOMICOPS_COMPILER_BARRIER();
216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *ptr = value;  // An x86 store acts as a release barrier
218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 // for current AMD/Intel chips as of Jan 2008.
219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 // See also Acquire_Load(), below.
220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // When new chips come out, check:
222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  System Programming Guide, Chatper 7: Multiple-processor management,
224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  Section 7.2, Memory Ordering.
225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Last seen at:
226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //
228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // x86 stores/loads fail to act as barriers for a few instructions (clflush
229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // not generated by the compiler, and are rare.  Users of these instructions
231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // need to know about cache behaviour in any case since all of these involve
232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // either flushing cache lines or non-temporal cache hints.
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return *ptr;
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Atomic64 value = *ptr;  // An x86 load acts as a acquire barrier,
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          // for current AMD/Intel chips as of Jan 2008.
242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          // See also Release_Store(), above.
243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ATOMICOPS_COMPILER_BARRIER();
244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return value;
245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic64 Release_Load(volatile const Atomic64* ptr) {
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MemoryBarrier();
249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return *ptr;
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       Atomic64 old_value,
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       Atomic64 new_value) {
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __asm__ __volatile__("lfence" : : : "memory");
258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return x;
260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       Atomic64 old_value,
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       Atomic64 new_value) {
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif  // defined(__x86_64__)
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} }  // namespace v8::base
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef ATOMICOPS_COMPILER_BARRIER
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
275