15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Copyright (c) 2006, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation of atomic operations for Mac OS X.  This file should not
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be included directly.  Clients should instead include
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "base/atomicops.h".
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_ATOMICOPS_INTERNALS_MACOSX_H_
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_ATOMICOPS_INTERNALS_MACOSX_H_
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef int32_t Atomic32;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MacOS uses long for intptr_t, AtomicWord and Atomic32 are always different
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on the Mac, even when they are the same size.  Similarly, on __ppc64__,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AtomicWord and Atomic64 are always different.  Thus, we need explicit
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// casting.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __LP64__
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define AtomicWordCastType base::subtle::Atomic64
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define AtomicWordCastType Atomic32
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__LP64__) || defined(__i386__)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_HAS_ATOMIC64 1  // Use only in tests and base/atomic*
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libkern/OSAtomic.h>
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace subtle {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(__LP64__) && defined(__ppc__)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The Mac 64-bit OSAtomic implementations are not available for 32-bit PowerPC,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// while the underlying assembly instructions are available only some
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implementations of PowerPC.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following inline functions will fail with the error message at compile
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// time ONLY IF they are called.  So it is safe to use this header if user
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// code only calls AtomicWord and Atomic32 operations.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE(vchen): Implementation notes to implement the atomic ops below may
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be found in "PowerPC Virtual Environment Architecture, Book II,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Version 2.02", January 28, 2005, Appendix B, page 46.  Unfortunately,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// extra care must be taken to ensure data are properly 8-byte aligned, and
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that data are returned correctly according to Mac OS X ABI specs.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline int64_t OSAtomicCompareAndSwap64(
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64_t oldValue, int64_t newValue, int64_t *theValue) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __asm__ __volatile__(
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "_OSAtomicCompareAndSwap64_not_supported_for_32_bit_ppc\n\t");
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline int64_t OSAtomicAdd64(int64_t theAmount, int64_t *theValue) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __asm__ __volatile__(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "_OSAtomicAdd64_not_supported_for_32_bit_ppc\n\t");
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline int64_t OSAtomicCompareAndSwap64Barrier(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64_t oldValue, int64_t newValue, int64_t *theValue) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64_t prev = OSAtomicCompareAndSwap64(oldValue, newValue, theValue);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSMemoryBarrier();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return prev;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline int64_t OSAtomicAdd64Barrier(
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64_t theAmount, int64_t *theValue) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64_t new_val = OSAtomicAdd64(theAmount, theValue);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSMemoryBarrier();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new_val;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef int64_t Atomic64;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void MemoryBarrier() {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSMemoryBarrier();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 32-bit Versions.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Atomic32 old_value,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Atomic32 new_value) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic32 prev_value;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (OSAtomicCompareAndSwap32(old_value, new_value,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const_cast<Atomic32*>(ptr))) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return old_value;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_value = *ptr;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (prev_value == old_value);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return prev_value;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Atomic32 new_value) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic32 old_value;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_value = *ptr;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (!OSAtomicCompareAndSwap32(old_value, new_value,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const_cast<Atomic32*>(ptr)));
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return old_value;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          Atomic32 increment) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          Atomic32 increment) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic32 old_value,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic32 new_value) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic32 prev_value;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const_cast<Atomic32*>(ptr))) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return old_value;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_value = *ptr;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (prev_value == old_value);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return prev_value;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic32 old_value,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic32 new_value) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Acquire_CompareAndSwap(ptr, old_value, new_value);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = value;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = value;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = value;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *ptr;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic32 value = *ptr;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *ptr;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 64-bit version
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Atomic64 old_value,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Atomic64 new_value) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic64 prev_value;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (OSAtomicCompareAndSwap64(old_value, new_value,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const_cast<Atomic64*>(ptr))) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return old_value;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_value = *ptr;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (prev_value == old_value);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return prev_value;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Atomic64 new_value) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic64 old_value;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_value = *ptr;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (!OSAtomicCompareAndSwap64(old_value, new_value,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const_cast<Atomic64*>(ptr)));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return old_value;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          Atomic64 increment) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        Atomic64 increment) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic64 old_value,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic64 new_value) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic64 prev_value;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (OSAtomicCompareAndSwap64Barrier(old_value, new_value,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const_cast<Atomic64*>(ptr))) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return old_value;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_value = *ptr;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (prev_value == old_value);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return prev_value;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic64 old_value,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Atomic64 new_value) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The lib kern interface does not distinguish between
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Acquire and Release memory barriers; they are equivalent.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Acquire_CompareAndSwap(ptr, old_value, new_value);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __LP64__
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 64-bit implementation on 64-bit platform
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = value;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = value;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = value;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *ptr;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic64 value = *ptr;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *ptr;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 64-bit implementation on 32-bit platform
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__ppc__)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   __asm__ __volatile__(
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       "_NoBarrier_Store_not_supported_for_32_bit_ppc\n\t");
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   __asm__ __volatile__(
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       "_NoBarrier_Load_not_supported_for_32_bit_ppc\n\t");
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return 0;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__i386__)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __asm__ __volatile__("movq %1, %%mm0\n\t"    // Use mmx reg for 64-bit atomic
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       "movq %%mm0, %0\n\t"  // moves (ptr could be read-only)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       "emms\n\t"              // Reset FP registers
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       : "=m" (*ptr)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       : "m" (value)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       : // mark the FP stack and mmx registers as clobbered
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "st", "st(1)", "st(2)", "st(3)", "st(4)",
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "st(5)", "st(6)", "st(7)", "mm0", "mm1",
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic64 value;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __asm__ __volatile__("movq %1, %%mm0\n\t"  // Use mmx reg for 64-bit atomic
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       "movq %%mm0, %0\n\t"  // moves (ptr could be read-only)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       "emms\n\t"            // Reset FP registers
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       : "=m" (value)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       : "m" (*ptr)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       : // mark the FP stack and mmx registers as clobbered
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "st", "st(1)", "st(2)", "st(3)", "st(4)",
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "st(5)", "st(6)", "st(7)", "mm0", "mm1",
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NoBarrier_Store(ptr, value);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NoBarrier_Store(ptr, value);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Atomic64 value = NoBarrier_Load(ptr);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryBarrier();
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NoBarrier_Load(ptr);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // __LP64__
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}   // namespace base::subtle
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}   // namespace base
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_ATOMICOPS_INTERNALS_MACOSX_H_
360