Home | History | Annotate | Download | only in src
      1 // Copyright 2010 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 // This file is an internal atomic implementation, use atomicops.h instead.
     29 
     30 #ifndef V8_ATOMICOPS_INTERNALS_X86_MACOSX_H_
     31 #define V8_ATOMICOPS_INTERNALS_X86_MACOSX_H_
     32 
     33 #include <libkern/OSAtomic.h>
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
     39                                          Atomic32 old_value,
     40                                          Atomic32 new_value) {
     41   Atomic32 prev_value;
     42   do {
     43     if (OSAtomicCompareAndSwap32(old_value, new_value,
     44                                  const_cast<Atomic32*>(ptr))) {
     45       return old_value;
     46     }
     47     prev_value = *ptr;
     48   } while (prev_value == old_value);
     49   return prev_value;
     50 }
     51 
     52 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
     53                                          Atomic32 new_value) {
     54   Atomic32 old_value;
     55   do {
     56     old_value = *ptr;
     57   } while (!OSAtomicCompareAndSwap32(old_value, new_value,
     58                                      const_cast<Atomic32*>(ptr)));
     59   return old_value;
     60 }
     61 
     62 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
     63                                           Atomic32 increment) {
     64   return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
     65 }
     66 
     67 inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
     68                                           Atomic32 increment) {
     69   return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
     70 }
     71 
     72 inline void MemoryBarrier() {
     73   OSMemoryBarrier();
     74 }
     75 
     76 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
     77                                        Atomic32 old_value,
     78                                        Atomic32 new_value) {
     79   Atomic32 prev_value;
     80   do {
     81     if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
     82                                         const_cast<Atomic32*>(ptr))) {
     83       return old_value;
     84     }
     85     prev_value = *ptr;
     86   } while (prev_value == old_value);
     87   return prev_value;
     88 }
     89 
     90 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
     91                                        Atomic32 old_value,
     92                                        Atomic32 new_value) {
     93   return Acquire_CompareAndSwap(ptr, old_value, new_value);
     94 }
     95 
     96 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
     97   *ptr = value;
     98 }
     99 
    100 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
    101   *ptr = value;
    102   MemoryBarrier();
    103 }
    104 
    105 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
    106   MemoryBarrier();
    107   *ptr = value;
    108 }
    109 
    110 inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
    111   return *ptr;
    112 }
    113 
    114 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
    115   Atomic32 value = *ptr;
    116   MemoryBarrier();
    117   return value;
    118 }
    119 
    120 inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
    121   MemoryBarrier();
    122   return *ptr;
    123 }
    124 
    125 #ifdef __LP64__
    126 
    127 // 64-bit implementation on 64-bit platform
    128 
    129 inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
    130                                          Atomic64 old_value,
    131                                          Atomic64 new_value) {
    132   Atomic64 prev_value;
    133   do {
    134     if (OSAtomicCompareAndSwap64(old_value, new_value,
    135                                  const_cast<Atomic64*>(ptr))) {
    136       return old_value;
    137     }
    138     prev_value = *ptr;
    139   } while (prev_value == old_value);
    140   return prev_value;
    141 }
    142 
    143 inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
    144                                          Atomic64 new_value) {
    145   Atomic64 old_value;
    146   do {
    147     old_value = *ptr;
    148   } while (!OSAtomicCompareAndSwap64(old_value, new_value,
    149                                      const_cast<Atomic64*>(ptr)));
    150   return old_value;
    151 }
    152 
    153 inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
    154                                           Atomic64 increment) {
    155   return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
    156 }
    157 
    158 inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
    159                                         Atomic64 increment) {
    160   return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
    161 }
    162 
    163 inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
    164                                        Atomic64 old_value,
    165                                        Atomic64 new_value) {
    166   Atomic64 prev_value;
    167   do {
    168     if (OSAtomicCompareAndSwap64Barrier(old_value, new_value,
    169                                         const_cast<Atomic64*>(ptr))) {
    170       return old_value;
    171     }
    172     prev_value = *ptr;
    173   } while (prev_value == old_value);
    174   return prev_value;
    175 }
    176 
    177 inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
    178                                        Atomic64 old_value,
    179                                        Atomic64 new_value) {
    180   // The lib kern interface does not distinguish between
    181   // Acquire and Release memory barriers; they are equivalent.
    182   return Acquire_CompareAndSwap(ptr, old_value, new_value);
    183 }
    184 
    185 inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
    186   *ptr = value;
    187 }
    188 
    189 inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
    190   *ptr = value;
    191   MemoryBarrier();
    192 }
    193 
    194 inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
    195   MemoryBarrier();
    196   *ptr = value;
    197 }
    198 
    199 inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
    200   return *ptr;
    201 }
    202 
    203 inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
    204   Atomic64 value = *ptr;
    205   MemoryBarrier();
    206   return value;
    207 }
    208 
    209 inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
    210   MemoryBarrier();
    211   return *ptr;
    212 }
    213 
    214 #endif  // defined(__LP64__)
    215 
    216 // MacOS uses long for intptr_t, AtomicWord and Atomic32 are always different
    217 // on the Mac, even when they are the same size.  We need to explicitly cast
    218 // from AtomicWord to Atomic32/64 to implement the AtomicWord interface.
    219 #ifdef __LP64__
    220 #define AtomicWordCastType Atomic64
    221 #else
    222 #define AtomicWordCastType Atomic32
    223 #endif
    224 
    225 inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
    226                                            AtomicWord old_value,
    227                                            AtomicWord new_value) {
    228   return NoBarrier_CompareAndSwap(
    229       reinterpret_cast<volatile AtomicWordCastType*>(ptr),
    230       old_value, new_value);
    231 }
    232 
    233 inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr,
    234                                            AtomicWord new_value) {
    235   return NoBarrier_AtomicExchange(
    236       reinterpret_cast<volatile AtomicWordCastType*>(ptr), new_value);
    237 }
    238 
    239 inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
    240                                             AtomicWord increment) {
    241   return NoBarrier_AtomicIncrement(
    242       reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
    243 }
    244 
    245 inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
    246                                           AtomicWord increment) {
    247   return Barrier_AtomicIncrement(
    248       reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
    249 }
    250 
    251 inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
    252                                          AtomicWord old_value,
    253                                          AtomicWord new_value) {
    254   return v8::internal::Acquire_CompareAndSwap(
    255       reinterpret_cast<volatile AtomicWordCastType*>(ptr),
    256       old_value, new_value);
    257 }
    258 
    259 inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
    260                                          AtomicWord old_value,
    261                                          AtomicWord new_value) {
    262   return v8::internal::Release_CompareAndSwap(
    263       reinterpret_cast<volatile AtomicWordCastType*>(ptr),
    264       old_value, new_value);
    265 }
    266 
    267 inline void NoBarrier_Store(volatile AtomicWord* ptr, AtomicWord value) {
    268   NoBarrier_Store(
    269       reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
    270 }
    271 
    272 inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
    273   return v8::internal::Acquire_Store(
    274       reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
    275 }
    276 
    277 inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
    278   return v8::internal::Release_Store(
    279       reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
    280 }
    281 
    282 inline AtomicWord NoBarrier_Load(volatile const AtomicWord* ptr) {
    283   return NoBarrier_Load(
    284       reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
    285 }
    286 
    287 inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
    288   return v8::internal::Acquire_Load(
    289       reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
    290 }
    291 
    292 inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
    293   return v8::internal::Release_Load(
    294       reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
    295 }
    296 
    297 #undef AtomicWordCastType
    298 
    299 } }  // namespace v8::internal
    300 
    301 #endif  // V8_ATOMICOPS_INTERNALS_X86_MACOSX_H_
    302