00001 /* Copyright (c) 2006, Google Inc. 00002 * All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions are 00006 * met: 00007 * 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above 00011 * copyright notice, this list of conditions and the following disclaimer 00012 * in the documentation and/or other materials provided with the 00013 * distribution. 00014 * * Neither the name of Google Inc. nor the names of its 00015 * contributors may be used to endorse or promote products derived from 00016 * this software without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00021 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00022 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00023 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00024 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00025 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00026 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00028 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 * 00030 * --- 00031 * Author: Sanjay Ghemawat 00032 */ 00033 00034 // Some fast atomic operations -- typically with machine-dependent 00035 // implementations. This file may need editing as Google code is 00036 // ported to different architectures. 00037 00038 #ifndef THREAD_ATOMICOPS_H__ 00039 #define THREAD_ATOMICOPS_H__ 00040 00041 #include "config.h" 00042 #include <stdint.h> 00043 00044 // ------------------------------------------------------------------------ 00045 // Include the platform specific implementations of the types 00046 // and operations listed below. 00047 // TODO(csilvers): figure out ARCH_PIII/ARCH_K8 (perhaps via ./configure?) 00048 // ------------------------------------------------------------------------ 00049 00050 // macosx.h should work correctly for Darwin/x86 as well, but the 00051 // x86.h version works fine as well, so we'll go with that. 00052 // TODO(csilvers): match piii, not just __i386. Also, match k8 00053 #if defined(__MACH__) && defined(__APPLE__) && defined(__ppc__) 00054 #include "base/atomicops-internals-macosx.h" 00055 #elif defined(__GNUC__) && (defined(__i386) || defined(ARCH_K8)) 00056 #include "base/atomicops-internals-x86.h" 00057 #elif defined(__i386) && defined(MSVC) 00058 #include "base/atomicops-internals-x86-msvc.h" 00059 #else 00060 // Assume x86 for now. If you need to support a new architecture and 00061 // don't know how to implement atomic ops, you can probably get away 00062 // with using pthreads, since atomicops is only used by spinlock.h/cc 00063 //#error You need to implement atomic operations for this architecture 00064 #include "base/atomicops-internals-x86.h" 00065 #endif 00066 00067 // ------------------------------------------------------------------------ 00068 // Commented out type definitions and method declarations for documentation 00069 // of the interface provided by this module. 00070 // ------------------------------------------------------------------------ 00071 00072 #if 0 00073 00074 // Signed type that can hold a pointer and supports the atomic ops below, as 00075 // well as atomic loads and stores. Instances must be naturally-aligned. 00076 typedef intptr_t AtomicWord; 00077 00078 // Signed 32-bit type that supports the atomic ops below, as well as atomic 00079 // loads and stores. Instances must be naturally aligned. This type differs 00080 // from AtomicWord in 64-bit binaries where AtomicWord is 64-bits. 00081 typedef int32_t Atomic32; 00082 00083 // Atomically execute: 00084 // result = *ptr; 00085 // if (*ptr == old_value) 00086 // *ptr = new_value; 00087 // return result; 00088 // 00089 // I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". 00090 // Always return the old value of "*ptr" 00091 // 00092 // This routine implies no memory barriers. 00093 AtomicWord CompareAndSwap(volatile AtomicWord* ptr, 00094 AtomicWord old_value, 00095 AtomicWord new_value); 00096 00097 // Atomically store new_value into *ptr, returning the previous value held in 00098 // *ptr. This routine implies no memory barriers. 00099 AtomicWord AtomicExchange(volatile AtomicWord* ptr, AtomicWord new_value); 00100 00101 // Atomically increment *ptr by "increment". Returns the new value of 00102 // *ptr with the increment applied. This routine implies no memory 00103 // barriers. 00104 AtomicWord AtomicIncrement(volatile AtomicWord* ptr, AtomicWord increment); 00105 00106 // ------------------------------------------------------------------------ 00107 // These following lower-level operations are typically useful only to people 00108 // implementing higher-level synchronization operations like spinlocks, 00109 // mutexes, and condition-variables. They combine CompareAndSwap(), a load, or 00110 // a store with appropriate memory-ordering instructions. "Acquire" operations 00111 // ensure that no later memory access can be reordered ahead of the operation. 00112 // "Release" operations ensure that no previous memory access can be reordered 00113 // after the operation. 00114 // ------------------------------------------------------------------------ 00115 AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, 00116 AtomicWord old_value, 00117 AtomicWord new_value); 00118 AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, 00119 AtomicWord old_value, 00120 AtomicWord new_value); 00121 void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value); 00122 void Release_Store(volatile AtomicWord* ptr, AtomicWord value); 00123 AtomicWord Acquire_Load(volatile const AtomicWord* ptr); 00124 AtomicWord Release_Load(volatile const AtomicWord* ptr); 00125 00126 // Corresponding operations on Atomic32 00127 Atomic32 CompareAndSwap(volatile Atomic32* ptr, 00128 Atomic32 old_value, 00129 Atomic32 new_value); 00130 Atomic32 AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); 00131 Atomic32 AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); 00132 Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, 00133 Atomic32 old_value, 00134 Atomic32 new_value); 00135 Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, 00136 Atomic32 old_value, 00137 Atomic32 new_value); 00138 void Acquire_Store(volatile Atomic32* ptr, Atomic32 value); 00139 void Release_Store(volatile Atomic32* ptr, Atomic32 value); 00140 Atomic32 Acquire_Load(volatile const Atomic32* ptr); 00141 Atomic32 Release_Load(volatile const Atomic32* ptr); 00142 00143 void MemoryBarrier(); 00144 00145 #endif 00146 00147 #endif // THREAD_ATOMICOPS_H__