Eneboo - Documentación para desarrolladores
|
00001 #include <stdio.h> 00002 /* -*- C++ -*- */ 00003 00004 /* 00005 00006 Heap Layers: An Extensible Memory Allocation Infrastructure 00007 00008 Copyright (C) 2000-2006 by Emery Berger 00009 http://www.cs.umass.edu/~emery 00010 emery@cs.umass.edu 00011 00012 This program is free software; you can redistribute it and/or modify 00013 it under the terms of the GNU General Public License as published by 00014 the Free Software Foundation; either version 2 of the License, or 00015 (at your option) any later version. 00016 00017 This program is distributed in the hope that it will be useful, 00018 but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 GNU General Public License for more details. 00021 00022 You should have received a copy of the GNU General Public License 00023 along with this program; if not, write to the Free Software 00024 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00025 00026 */ 00027 00028 #ifndef _SPINLOCK_H_ 00029 #define _SPINLOCK_H_ 00030 00031 #if defined(unix) 00032 #include <sched.h> 00033 #endif 00034 00035 #if defined(__SVR4) 00036 #include <thread.h> 00037 #endif 00038 00039 #if defined(__sgi) 00040 #include <mutex.h> 00041 #endif 00042 00043 #if defined(__APPLE__) 00044 #include <libkern/OSAtomic.h> 00045 #endif 00046 00047 #include "hldefines.h" 00048 #include "cpuinfo.h" 00049 00050 #if defined(_MSC_VER) 00051 00052 #if !defined(NO_INLINE) 00053 #pragma inline_depth(255) 00054 #define NO_INLINE __declspec(noinline) 00055 #define INLINE __forceinline 00056 #define inline __forceinline 00057 #endif // !defined(NO_INLINE) 00058 00059 #else 00060 00061 #endif // defined(_MSC_VER) 00062 00063 00064 #if defined(__SUNPRO_CC) 00065 // x86-interchange.il, x86_64-interchange.il contributed by Markus Bernhardt. 00066 extern "C" unsigned long MyInterlockedExchange (unsigned long * oldval, 00067 unsigned long newval); 00068 #endif 00069 00070 #undef _WIN32 00071 #if defined(_WIN32) && !defined(_WIN64) 00072 #define _WIN32_WINNT 0x0500 00073 00074 // NOTE: Below is the new "pause" instruction, which is inocuous for 00075 // previous architectures, but crucial for Intel chips with 00076 // hyperthreading. See 00077 // http://www.usenix.org/events/wiess02/tech/full_papers/nakajima/nakajima.pdf 00078 // for discussion. 00079 00080 #define _MM_PAUSE {__asm{_emit 0xf3};__asm {_emit 0x90}} 00081 #include <windows.h> 00082 #else 00083 #define _MM_PAUSE 00084 #endif // defined(_WIN32) && !defined(_WIN64) 00085 00086 extern volatile int anyThreadCreated; 00087 00088 namespace HL { 00089 00090 class SpinLockType { 00091 private: 00092 00093 enum { UNLOCKED = 0, LOCKED = 1 }; 00094 00095 public: 00096 00097 SpinLockType (void) 00098 #if defined(__APPLE__) 00099 : mutex (OS_SPINLOCK_INIT) 00100 #else 00101 : mutex (UNLOCKED) 00102 #endif 00103 {} 00104 00105 ~SpinLockType (void) 00106 {} 00107 00108 inline void lock (void) { 00109 if (anyThreadCreated) { 00110 if (MyInterlockedExchange (const_cast<unsigned long *>(&mutex), LOCKED) 00111 != UNLOCKED) { 00112 contendedLock(); 00113 } 00114 } else { 00115 mutex = LOCKED; 00116 } 00117 } 00118 00119 00120 inline void unlock (void) { 00121 if (anyThreadCreated) { 00122 #if defined(_WIN32) && !defined(_WIN64) 00123 __asm {} 00124 #elif defined(__GNUC__) 00125 asm volatile ("" : : : "memory"); 00126 #endif 00127 } 00128 mutex = UNLOCKED; 00129 } 00130 00131 00132 #if !defined(__SUNPRO_CC) 00133 inline static volatile unsigned long MyInterlockedExchange (unsigned long *,unsigned long); 00134 #endif 00135 00136 private: 00137 00138 #if 0 // defined(__APPLE__) 00139 OSSpinLock mutex; 00140 00141 #else 00142 00143 NO_INLINE 00144 void contendedLock (void) { 00145 while (1) { 00146 if (MyInterlockedExchange (const_cast<unsigned long *>(&mutex), LOCKED) 00147 == UNLOCKED) { 00148 return; 00149 } 00150 while (mutex == LOCKED) { 00151 _MM_PAUSE; 00152 yieldProcessor(); 00153 } 00154 } 00155 } 00156 00157 // Is this system a multiprocessor? 00158 inline bool onMultiprocessor (void) { 00159 static CPUInfo cpuInfo; 00160 return (cpuInfo.getNumProcessors() > 1); 00161 } 00162 00163 inline void yieldProcessor (void) { 00164 #if defined(_WIN32) 00165 Sleep(0); 00166 #elif defined(__SVR4) 00167 thr_yield(); 00168 #else 00169 sched_yield(); 00170 #endif 00171 } 00172 00173 enum { MAX_SPIN_LIMIT = 1024 }; 00174 00175 union { 00176 volatile unsigned long mutex; 00177 }; 00178 #endif 00179 00180 }; 00181 00182 } 00183 00184 // Atomically: 00185 // retval = *oldval; 00186 // *oldval = newval; 00187 // return retval; 00188 00189 #if !defined(__SUNPRO_CC) // && !defined(__APPLE__) 00190 inline volatile unsigned long 00191 HL::SpinLockType::MyInterlockedExchange (unsigned long * oldval, 00192 unsigned long newval) 00193 { 00194 #if defined(_WIN32) && defined(_MSC_VER) 00195 return InterlockedExchange ((volatile LONG *) oldval, newval); 00196 00197 //#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 00198 // return __sync_val_compare_and_swap(oldval, *oldval, newval); 00199 00200 #elif defined(__sparc) 00201 asm volatile ("swap [%1],%0" 00202 :"=r" (newval) 00203 :"r" (oldval), "0" (newval) 00204 : "memory"); 00205 00206 #elif defined(__i386__) 00207 asm volatile ("lock; xchgl %0, %1" 00208 : "=r" (newval) 00209 : "m" (*oldval), "0" (newval) 00210 : "memory"); 00211 00212 #elif defined(__sgi) 00213 newval = test_and_set (oldval, newval); 00214 00215 #elif defined(__x86_64__) 00216 // Contributed by Kurt Roeckx. 00217 asm volatile ("lock; xchgq %0, %1" 00218 : "=r" (newval) 00219 : "m" (*oldval), "0" (newval) 00220 : "memory"); 00221 00222 #elif defined(__ppc) || defined(__powerpc__) || defined(PPC) 00223 // PPC assembly contributed by Maged Michael. 00224 int ret; 00225 asm volatile ( 00226 "La..%=0: lwarx %0,0,%1 ;" 00227 " cmpw %0,%2;" 00228 " beq La..%=1;" 00229 " stwcx. %2,0,%1;" 00230 " bne- La..%=0;" 00231 "La..%=1: isync;" 00232 : "=&r"(ret) 00233 : "r"(oldval), "r"(newval) 00234 : "cr0", "memory"); 00235 return ret; 00236 00237 #elif defined(__arm__) 00238 // Contributed by Bo Granlund. 00239 long result; 00240 asm volatile ( 00241 "\n\t" 00242 "swp %0,%2,[%1] \n\t" 00243 "" 00244 : "=&r"(result) 00245 : "r"(oldval), "r"(newval) 00246 : "memory"); 00247 return (result); 00248 #elif defined(__APPLE__) 00249 unsigned long oldValue = *oldval; 00250 bool swapped = OSAtomicCompareAndSwapLongBarrier (oldValue, newval, oldval); 00251 if (swapped) { 00252 return newval; 00253 } else { 00254 return oldValue; 00255 } 00256 #else 00257 #error "No spin lock implementation is available for this platform." 00258 #endif 00259 return newval; 00260 } 00261 00262 00263 #endif 00264 00265 #endif // _SPINLOCK_H_