Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2006-2008 The Chromium 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 base/atomicops.h instead.
      6 
      7 #ifndef BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
      8 #define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
      9 #pragma once
     10 
     11 #include <windows.h>
     12 
     13 namespace base {
     14 namespace subtle {
     15 
     16 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
     17                                          Atomic32 old_value,
     18                                          Atomic32 new_value) {
     19   LONG result = InterlockedCompareExchange(
     20       reinterpret_cast<volatile LONG*>(ptr),
     21       static_cast<LONG>(new_value),
     22       static_cast<LONG>(old_value));
     23   return static_cast<Atomic32>(result);
     24 }
     25 
     26 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
     27                                          Atomic32 new_value) {
     28   LONG result = InterlockedExchange(
     29       reinterpret_cast<volatile LONG*>(ptr),
     30       static_cast<LONG>(new_value));
     31   return static_cast<Atomic32>(result);
     32 }
     33 
     34 inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
     35                                         Atomic32 increment) {
     36   return InterlockedExchangeAdd(
     37       reinterpret_cast<volatile LONG*>(ptr),
     38       static_cast<LONG>(increment)) + increment;
     39 }
     40 
     41 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
     42                                           Atomic32 increment) {
     43   return Barrier_AtomicIncrement(ptr, increment);
     44 }
     45 
     46 #if !(defined(_MSC_VER) && _MSC_VER >= 1400)
     47 #error "We require at least vs2005 for MemoryBarrier"
     48 #endif
     49 inline void MemoryBarrier() {
     50   // We use MemoryBarrier from WinNT.h
     51   ::MemoryBarrier();
     52 }
     53 
     54 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
     55                                        Atomic32 old_value,
     56                                        Atomic32 new_value) {
     57   return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
     58 }
     59 
     60 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
     61                                        Atomic32 old_value,
     62                                        Atomic32 new_value) {
     63   return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
     64 }
     65 
     66 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
     67   *ptr = value;
     68 }
     69 
     70 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
     71   NoBarrier_AtomicExchange(ptr, value);
     72               // acts as a barrier in this implementation
     73 }
     74 
     75 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
     76   *ptr = value; // works w/o barrier for current Intel chips as of June 2005
     77   // See comments in Atomic64 version of Release_Store() below.
     78 }
     79 
     80 inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
     81   return *ptr;
     82 }
     83 
     84 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
     85   Atomic32 value = *ptr;
     86   return value;
     87 }
     88 
     89 inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
     90   MemoryBarrier();
     91   return *ptr;
     92 }
     93 
     94 #if defined(_WIN64)
     95 
     96 // 64-bit low-level operations on 64-bit platform.
     97 
     98 COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic);
     99 
    100 inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
    101                                          Atomic64 old_value,
    102                                          Atomic64 new_value) {
    103   PVOID result = InterlockedCompareExchangePointer(
    104     reinterpret_cast<volatile PVOID*>(ptr),
    105     reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
    106   return reinterpret_cast<Atomic64>(result);
    107 }
    108 
    109 inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
    110                                          Atomic64 new_value) {
    111   PVOID result = InterlockedExchangePointer(
    112     reinterpret_cast<volatile PVOID*>(ptr),
    113     reinterpret_cast<PVOID>(new_value));
    114   return reinterpret_cast<Atomic64>(result);
    115 }
    116 
    117 inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
    118                                         Atomic64 increment) {
    119   return InterlockedExchangeAdd64(
    120       reinterpret_cast<volatile LONGLONG*>(ptr),
    121       static_cast<LONGLONG>(increment)) + increment;
    122 }
    123 
    124 inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
    125                                           Atomic64 increment) {
    126   return Barrier_AtomicIncrement(ptr, increment);
    127 }
    128 
    129 inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
    130   *ptr = value;
    131 }
    132 
    133 inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
    134   NoBarrier_AtomicExchange(ptr, value);
    135               // acts as a barrier in this implementation
    136 }
    137 
    138 inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
    139   *ptr = value; // works w/o barrier for current Intel chips as of June 2005
    140 
    141   // When new chips come out, check:
    142   //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
    143   //  System Programming Guide, Chatper 7: Multiple-processor management,
    144   //  Section 7.2, Memory Ordering.
    145   // Last seen at:
    146   //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
    147 }
    148 
    149 inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
    150   return *ptr;
    151 }
    152 
    153 inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
    154   Atomic64 value = *ptr;
    155   return value;
    156 }
    157 
    158 inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
    159   MemoryBarrier();
    160   return *ptr;
    161 }
    162 
    163 inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
    164                                        Atomic64 old_value,
    165                                        Atomic64 new_value) {
    166   return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
    167 }
    168 
    169 inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
    170                                        Atomic64 old_value,
    171                                        Atomic64 new_value) {
    172   return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
    173 }
    174 
    175 
    176 #endif  // defined(_WIN64)
    177 
    178 }  // namespace base::subtle
    179 }  // namespace base
    180 
    181 #endif  // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
    182