15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is an internal atomic implementation, use base/atomicops.h instead. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_ 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_ 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <intrin.h> 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/macros.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ARCH_CPU_64_BITS) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// windows.h #defines this (only on x64). This causes problems because the 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// public API also uses MemoryBarrier at the public name for this fence. So, on 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// X64, undef it, and call its documented 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// implementation directly. 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#undef MemoryBarrier 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace subtle { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic32 old_value, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic32 new_value) { 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LONG result = _InterlockedCompareExchange( 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<volatile LONG*>(ptr), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<LONG>(new_value), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<LONG>(old_value)); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<Atomic32>(result); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic32 new_value) { 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LONG result = _InterlockedExchange( 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<volatile LONG*>(ptr), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<LONG>(new_value)); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<Atomic32>(result); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic32 increment) { 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return _InterlockedExchangeAdd( 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<volatile LONG*>(ptr), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<LONG>(increment)) + increment; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic32 increment) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Barrier_AtomicIncrement(ptr, increment); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !(defined(_MSC_VER) && _MSC_VER >= 1400) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error "We require at least vs2005 for MemoryBarrier" 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void MemoryBarrier() { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ARCH_CPU_64_BITS) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See #undef and note at the top of this file. 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) __faststorefence(); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We use MemoryBarrier from WinNT.h 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::MemoryBarrier(); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic32 old_value, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic32 new_value) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NoBarrier_CompareAndSwap(ptr, old_value, new_value); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic32 old_value, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic32 new_value) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NoBarrier_CompareAndSwap(ptr, old_value, new_value); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = value; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NoBarrier_AtomicExchange(ptr, value); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // acts as a barrier in this implementation 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = value; // works w/o barrier for current Intel chips as of June 2005 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See comments in Atomic64 version of Release_Store() below. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *ptr; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic32 value = *ptr; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic32 Release_Load(volatile const Atomic32* ptr) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryBarrier(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *ptr; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_WIN64) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 64-bit low-level operations on 64-bit platform. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic64 old_value, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic64 new_value) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PVOID result = InterlockedCompareExchangePointer( 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<volatile PVOID*>(ptr), 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value)); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<Atomic64>(result); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic64 new_value) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PVOID result = InterlockedExchangePointer( 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<volatile PVOID*>(ptr), 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<PVOID>(new_value)); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<Atomic64>(result); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic64 increment) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InterlockedExchangeAdd64( 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<volatile LONGLONG*>(ptr), 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<LONGLONG>(increment)) + increment; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic64 increment) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Barrier_AtomicIncrement(ptr, increment); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = value; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NoBarrier_AtomicExchange(ptr, value); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // acts as a barrier in this implementation 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = value; // works w/o barrier for current Intel chips as of June 2005 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When new chips come out, check: 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IA-32 Intel Architecture Software Developer's Manual, Volume 3: 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // System Programming Guide, Chatper 7: Multiple-processor management, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Section 7.2, Memory Ordering. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Last seen at: 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://developer.intel.com/design/pentium4/manuals/index_new.htm 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *ptr; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic64 value = *ptr; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Release_Load(volatile const Atomic64* ptr) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryBarrier(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *ptr; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic64 old_value, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic64 new_value) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NoBarrier_CompareAndSwap(ptr, old_value, new_value); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic64 old_value, 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atomic64 new_value) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NoBarrier_CompareAndSwap(ptr, old_value, new_value); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(_WIN64) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base::subtle 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_ 199