atomicops_internals_x86_macosx.h revision c7f5f8508d98d5952d42ed7648c2a8f30a4da156
1// Copyright (c) 2006-2008 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.
4
5// This file is an internal atomic implementation, use base/atomicops.h instead.
6
7#ifndef BASE_ATOMICOPS_INTERNALS_X86_MACOSX_H_
8#define BASE_ATOMICOPS_INTERNALS_X86_MACOSX_H_
9
10#include <libkern/OSAtomic.h>
11
12namespace base {
13namespace subtle {
14
15inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
16                                         Atomic32 old_value,
17                                         Atomic32 new_value) {
18  Atomic32 prev_value;
19  do {
20    if (OSAtomicCompareAndSwap32(old_value, new_value,
21                                 const_cast<Atomic32*>(ptr))) {
22      return old_value;
23    }
24    prev_value = *ptr;
25  } while (prev_value == old_value);
26  return prev_value;
27}
28
29inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
30                                         Atomic32 new_value) {
31  Atomic32 old_value;
32  do {
33    old_value = *ptr;
34  } while (!OSAtomicCompareAndSwap32(old_value, new_value,
35                                     const_cast<Atomic32*>(ptr)));
36  return old_value;
37}
38
39inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
40                                          Atomic32 increment) {
41  return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
42}
43
44inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
45                                          Atomic32 increment) {
46  return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
47}
48
49inline void MemoryBarrier() {
50  OSMemoryBarrier();
51}
52
53inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
54                                       Atomic32 old_value,
55                                       Atomic32 new_value) {
56  Atomic32 prev_value;
57  do {
58    if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
59                                        const_cast<Atomic32*>(ptr))) {
60      return old_value;
61    }
62    prev_value = *ptr;
63  } while (prev_value == old_value);
64  return prev_value;
65}
66
67inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
68                                       Atomic32 old_value,
69                                       Atomic32 new_value) {
70  return Acquire_CompareAndSwap(ptr, old_value, new_value);
71}
72
73inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
74  *ptr = value;
75}
76
77inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
78  *ptr = value;
79  MemoryBarrier();
80}
81
82inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
83  MemoryBarrier();
84  *ptr = value;
85}
86
87inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
88  return *ptr;
89}
90
91inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
92  Atomic32 value = *ptr;
93  MemoryBarrier();
94  return value;
95}
96
97inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
98  MemoryBarrier();
99  return *ptr;
100}
101
102#ifdef __LP64__
103
104// 64-bit implementation on 64-bit platform
105
106inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
107                                         Atomic64 old_value,
108                                         Atomic64 new_value) {
109  Atomic64 prev_value;
110  do {
111    if (OSAtomicCompareAndSwap64(old_value, new_value,
112                                 const_cast<Atomic64*>(ptr))) {
113      return old_value;
114    }
115    prev_value = *ptr;
116  } while (prev_value == old_value);
117  return prev_value;
118}
119
120inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr,
121                                         Atomic64 new_value) {
122  Atomic64 old_value;
123  do {
124    old_value = *ptr;
125  } while (!OSAtomicCompareAndSwap64(old_value, new_value,
126                                     const_cast<Atomic64*>(ptr)));
127  return old_value;
128}
129
130inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
131                                          Atomic64 increment) {
132  return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
133}
134
135inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
136                                        Atomic64 increment) {
137  return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
138}
139
140inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
141                                       Atomic64 old_value,
142                                       Atomic64 new_value) {
143  Atomic64 prev_value;
144  do {
145    if (OSAtomicCompareAndSwap64Barrier(old_value, new_value,
146                                        const_cast<Atomic64*>(ptr))) {
147      return old_value;
148    }
149    prev_value = *ptr;
150  } while (prev_value == old_value);
151  return prev_value;
152}
153
154inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr,
155                                       Atomic64 old_value,
156                                       Atomic64 new_value) {
157  // The lib kern interface does not distinguish between
158  // Acquire and Release memory barriers; they are equivalent.
159  return Acquire_CompareAndSwap(ptr, old_value, new_value);
160}
161
162inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
163  *ptr = value;
164}
165
166inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
167  *ptr = value;
168  MemoryBarrier();
169}
170
171inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
172  MemoryBarrier();
173  *ptr = value;
174}
175
176inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
177  return *ptr;
178}
179
180inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
181  Atomic64 value = *ptr;
182  MemoryBarrier();
183  return value;
184}
185
186inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
187  MemoryBarrier();
188  return *ptr;
189}
190
191#endif  // defined(__LP64__)
192
193// MacOS uses long for intptr_t, AtomicWord and Atomic32 are always different
194// on the Mac, even when they are the same size.  We need to explicitly cast
195// from AtomicWord to Atomic32/64 to implement the AtomicWord interface.
196#ifdef __LP64__
197#define AtomicWordCastType Atomic64
198#else
199#define AtomicWordCastType Atomic32
200#endif
201
202inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
203                                           AtomicWord old_value,
204                                           AtomicWord new_value) {
205  return NoBarrier_CompareAndSwap(
206      reinterpret_cast<volatile AtomicWordCastType*>(ptr),
207      old_value, new_value);
208}
209
210inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr,
211                                           AtomicWord new_value) {
212  return NoBarrier_AtomicExchange(
213      reinterpret_cast<volatile AtomicWordCastType*>(ptr), new_value);
214}
215
216inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
217                                            AtomicWord increment) {
218  return NoBarrier_AtomicIncrement(
219      reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
220}
221
222inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
223                                          AtomicWord increment) {
224  return Barrier_AtomicIncrement(
225      reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
226}
227
228inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
229                                         AtomicWord old_value,
230                                         AtomicWord new_value) {
231  return base::subtle::Acquire_CompareAndSwap(
232      reinterpret_cast<volatile AtomicWordCastType*>(ptr),
233      old_value, new_value);
234}
235
236inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
237                                         AtomicWord old_value,
238                                         AtomicWord new_value) {
239  return base::subtle::Release_CompareAndSwap(
240      reinterpret_cast<volatile AtomicWordCastType*>(ptr),
241      old_value, new_value);
242}
243
244inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) {
245  NoBarrier_Store(
246      reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
247}
248
249inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
250  return base::subtle::Acquire_Store(
251      reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
252}
253
254inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
255  return base::subtle::Release_Store(
256      reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
257}
258
259inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) {
260  return NoBarrier_Load(
261      reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
262}
263
264inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
265  return base::subtle::Acquire_Load(
266      reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
267}
268
269inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
270  return base::subtle::Release_Load(
271      reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
272}
273
274#undef AtomicWordCastType
275
276}   // namespace base::subtle
277}   // namespace base
278
279#endif  // BASE_ATOMICOPS_INTERNALS_X86_MACOSX_H_
280