1// Copyright 2010 the V8 project 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 atomicops.h instead.
6
7#ifndef V8_BASE_ATOMICOPS_INTERNALS_MAC_H_
8#define V8_BASE_ATOMICOPS_INTERNALS_MAC_H_
9
10#include <libkern/OSAtomic.h>
11
12namespace v8 {
13namespace base {
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 Atomic8* ptr, Atomic8 value) {
74  *ptr = value;
75}
76
77inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
78  *ptr = value;
79}
80
81inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
82  *ptr = value;
83  MemoryBarrier();
84}
85
86inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
87  MemoryBarrier();
88  *ptr = value;
89}
90
91inline Atomic8 NoBarrier_Load(volatile const Atomic8* ptr) {
92  return *ptr;
93}
94
95inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
96  return *ptr;
97}
98
99inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
100  Atomic32 value = *ptr;
101  MemoryBarrier();
102  return value;
103}
104
105inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
106  MemoryBarrier();
107  return *ptr;
108}
109
110#ifdef __LP64__
111
112// 64-bit implementation on 64-bit platform
113
114inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
115                                         Atomic64 old_value,
116                                         Atomic64 new_value) {
117  Atomic64 prev_value;
118  do {
119    if (OSAtomicCompareAndSwap64(old_value, new_value,
120                                 reinterpret_cast<volatile int64_t*>(ptr))) {
121      return old_value;
122    }
123    prev_value = *ptr;
124  } while (prev_value == old_value);
125  return prev_value;
126}
127
128inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
129                                         Atomic64 new_value) {
130  Atomic64 old_value;
131  do {
132    old_value = *ptr;
133  } while (!OSAtomicCompareAndSwap64(old_value, new_value,
134                                     reinterpret_cast<volatile int64_t*>(ptr)));
135  return old_value;
136}
137
138inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
139                                          Atomic64 increment) {
140  return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr));
141}
142
143inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
144                                        Atomic64 increment) {
145  return OSAtomicAdd64Barrier(increment,
146                              reinterpret_cast<volatile int64_t*>(ptr));
147}
148
149inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
150                                       Atomic64 old_value,
151                                       Atomic64 new_value) {
152  Atomic64 prev_value;
153  do {
154    if (OSAtomicCompareAndSwap64Barrier(
155        old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) {
156      return old_value;
157    }
158    prev_value = *ptr;
159  } while (prev_value == old_value);
160  return prev_value;
161}
162
163inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
164                                       Atomic64 old_value,
165                                       Atomic64 new_value) {
166  // The lib kern interface does not distinguish between
167  // Acquire and Release memory barriers; they are equivalent.
168  return Acquire_CompareAndSwap(ptr, old_value, new_value);
169}
170
171inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
172  *ptr = value;
173}
174
175inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
176  *ptr = value;
177  MemoryBarrier();
178}
179
180inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
181  MemoryBarrier();
182  *ptr = value;
183}
184
185inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
186  return *ptr;
187}
188
189inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
190  Atomic64 value = *ptr;
191  MemoryBarrier();
192  return value;
193}
194
195inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
196  MemoryBarrier();
197  return *ptr;
198}
199
200#endif  // defined(__LP64__)
201
202} }  // namespace v8::base
203
204#endif  // V8_BASE_ATOMICOPS_INTERNALS_MAC_H_
205