1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2010 the V8 project authors. All rights reserved. 2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Redistribution and use in source and binary forms, with or without 3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// modification, are permitted provided that the following conditions are 4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// met: 5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Redistributions of source code must retain the above copyright 7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// notice, this list of conditions and the following disclaimer. 8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Redistributions in binary form must reproduce the above 9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// copyright notice, this list of conditions and the following 10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// disclaimer in the documentation and/or other materials provided 11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// with the distribution. 12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Neither the name of Google Inc. nor the names of its 13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// contributors may be used to endorse or promote products derived 14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from this software without specific prior written permission. 15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This file is an internal atomic implementation, use atomicops.h instead. 29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. 31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifndef V8_ATOMICOPS_INTERNALS_ARM_GCC_H_ 33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define V8_ATOMICOPS_INTERNALS_ARM_GCC_H_ 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 { 36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal { 37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 0xffff0fc0 is the hard coded address of a function provided by 39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the kernel which implements an atomic compare-exchange. On older 40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// ARM architecture revisions (pre-v6) this may be implemented using 41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// a syscall. This address is stable, and in active use (hard coded) 42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// by at least glibc-2.7 and the Android C library. 43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochtypedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value, 44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 new_value, 45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch volatile Atomic32* ptr); 46b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochLinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) = 47b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (LinuxKernelCmpxchgFunc) 0xffff0fc0; 48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochtypedef void (*LinuxKernelMemoryBarrierFunc)(void); 50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochLinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = 51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; 52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, 55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 old_value, 56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 new_value) { 57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 prev_value = *ptr; 58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { 59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!pLinuxKernelCmpxchg(old_value, new_value, 60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const_cast<Atomic32*>(ptr))) { 61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return old_value; 62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prev_value = *ptr; 64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (prev_value == old_value); 65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return prev_value; 66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, 69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 new_value) { 70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 old_value; 71b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { 72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch old_value = *ptr; 73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (pLinuxKernelCmpxchg(old_value, new_value, 74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const_cast<Atomic32*>(ptr))); 75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return old_value; 76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, 79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 increment) { 80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Barrier_AtomicIncrement(ptr, increment); 81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, 84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 increment) { 85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (;;) { 86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Atomic exchange the old value with an incremented one. 87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 old_value = *ptr; 88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 new_value = old_value + increment; 89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (pLinuxKernelCmpxchg(old_value, new_value, 90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const_cast<Atomic32*>(ptr)) == 0) { 91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The exchange took place as expected. 92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new_value; 93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Otherwise, *ptr changed mid-loop and we need to retry. 95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, 99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 old_value, 100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 new_value) { 101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return NoBarrier_CompareAndSwap(ptr, old_value, new_value); 102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, 105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 old_value, 106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 new_value) { 107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return NoBarrier_CompareAndSwap(ptr, old_value, new_value); 108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { 111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *ptr = value; 112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void MemoryBarrier() { 115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pLinuxKernelMemoryBarrier(); 116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { 119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *ptr = value; 120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch MemoryBarrier(); 121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { 124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch MemoryBarrier(); 125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *ptr = value; 126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { 129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return *ptr; 130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { 133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Atomic32 value = *ptr; 134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch MemoryBarrier(); 135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return value; 136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline Atomic32 Release_Load(volatile const Atomic32* ptr) { 139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch MemoryBarrier(); 140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return *ptr; 141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} } // namespace v8::internal 144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif // V8_ATOMICOPS_INTERNALS_ARM_GCC_H_ 146