![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright 2005-2010 Intel Corporation. All Rights Reserved. 00003 00004 This file is part of Threading Building Blocks. 00005 00006 Threading Building Blocks is free software; you can redistribute it 00007 and/or modify it under the terms of the GNU General Public License 00008 version 2 as published by the Free Software Foundation. 00009 00010 Threading Building Blocks is distributed in the hope that it will be 00011 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00012 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Threading Building Blocks; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 As a special exception, you may use this file as part of a free software 00020 library without restriction. Specifically, if other files instantiate 00021 templates or use macros or inline functions from this file, or you compile 00022 this file and link it with other files to produce an executable, this 00023 file does not by itself cause the resulting executable to be covered by 00024 the GNU General Public License. This exception does not however 00025 invalidate any other reasons why the executable file might be covered by 00026 the GNU General Public License. 00027 */ 00028 00029 #ifndef __TBB_machine_H 00030 #error Do not include this file directly; include tbb_machine.h instead 00031 #endif 00032 00033 #if !__MINGW32__ 00034 #include "linux_common.h" 00035 #endif 00036 00037 #define __TBB_WORDSIZE 4 00038 #define __TBB_BIG_ENDIAN 0 00039 00040 #define __TBB_release_consistency_helper() __asm__ __volatile__("": : :"memory") 00041 00042 inline void __TBB_rel_acq_fence() { __asm__ __volatile__("mfence": : :"memory"); } 00043 00044 #if __TBB_ICC_ASM_VOLATILE_BROKEN 00045 #define __TBB_VOLATILE 00046 #else 00047 #define __TBB_VOLATILE volatile 00048 #endif 00049 00050 #define __MACHINE_DECL_ATOMICS(S,T,X) \ 00051 static inline T __TBB_machine_cmpswp##S (volatile void *ptr, T value, T comparand ) \ 00052 { \ 00053 T result; \ 00054 \ 00055 __asm__ __volatile__("lock\ncmpxchg" X " %2,%1" \ 00056 : "=a"(result), "=m"(*(__TBB_VOLATILE T*)ptr) \ 00057 : "q"(value), "0"(comparand), "m"(*(__TBB_VOLATILE T*)ptr) \ 00058 : "memory"); \ 00059 return result; \ 00060 } \ 00061 \ 00062 static inline T __TBB_machine_fetchadd##S(volatile void *ptr, T addend) \ 00063 { \ 00064 T result; \ 00065 __asm__ __volatile__("lock\nxadd" X " %0,%1" \ 00066 : "=r"(result), "=m"(*(__TBB_VOLATILE T*)ptr) \ 00067 : "0"(addend), "m"(*(__TBB_VOLATILE T*)ptr) \ 00068 : "memory"); \ 00069 return result; \ 00070 } \ 00071 \ 00072 static inline T __TBB_machine_fetchstore##S(volatile void *ptr, T value) \ 00073 { \ 00074 T result; \ 00075 __asm__ __volatile__("lock\nxchg" X " %0,%1" \ 00076 : "=r"(result), "=m"(*(__TBB_VOLATILE T*)ptr) \ 00077 : "0"(value), "m"(*(__TBB_VOLATILE T*)ptr) \ 00078 : "memory"); \ 00079 return result; \ 00080 } \ 00081 00082 __MACHINE_DECL_ATOMICS(1,int8_t,"") 00083 __MACHINE_DECL_ATOMICS(2,int16_t,"") 00084 __MACHINE_DECL_ATOMICS(4,int32_t,"l") 00085 00086 static inline int64_t __TBB_machine_cmpswp8 (volatile void *ptr, int64_t value, int64_t comparand ) 00087 { 00088 int64_t result; 00089 #if __PIC__ 00090 /* compiling position-independent code */ 00091 // EBX register preserved for compliance with position-independent code rules on IA32 00092 __asm__ __volatile__ ( 00093 "pushl %%ebx\n\t" 00094 "movl (%%ecx),%%ebx\n\t" 00095 "movl 4(%%ecx),%%ecx\n\t" 00096 "lock\n\t cmpxchg8b %1\n\t" 00097 "popl %%ebx" 00098 : "=A"(result), "=m"(*(int64_t *)ptr) 00099 : "m"(*(int64_t *)ptr) 00100 , "0"(comparand) 00101 , "c"(&value) 00102 : "memory", "esp" 00103 #if __INTEL_COMPILER 00104 ,"ebx" 00105 #endif 00106 ); 00107 #else /* !__PIC__ */ 00108 union { 00109 int64_t i64; 00110 int32_t i32[2]; 00111 }; 00112 i64 = value; 00113 __asm__ __volatile__ ( 00114 "lock\n\t cmpxchg8b %1\n\t" 00115 : "=A"(result), "=m"(*(__TBB_VOLATILE int64_t *)ptr) 00116 : "m"(*(__TBB_VOLATILE int64_t *)ptr) 00117 , "0"(comparand) 00118 , "b"(i32[0]), "c"(i32[1]) 00119 : "memory" 00120 ); 00121 #endif /* __PIC__ */ 00122 return result; 00123 } 00124 00125 static inline int32_t __TBB_machine_lg( uint32_t x ) { 00126 int32_t j; 00127 __asm__ ("bsr %1,%0" : "=r"(j) : "r"(x)); 00128 return j; 00129 } 00130 00131 static inline void __TBB_machine_or( volatile void *ptr, uint32_t addend ) { 00132 __asm__ __volatile__("lock\norl %1,%0" : "=m"(*(__TBB_VOLATILE uint32_t *)ptr) : "r"(addend), "m"(*(__TBB_VOLATILE uint32_t *)ptr) : "memory"); 00133 } 00134 00135 static inline void __TBB_machine_and( volatile void *ptr, uint32_t addend ) { 00136 __asm__ __volatile__("lock\nandl %1,%0" : "=m"(*(__TBB_VOLATILE uint32_t *)ptr) : "r"(addend), "m"(*(__TBB_VOLATILE uint32_t *)ptr) : "memory"); 00137 } 00138 00139 static inline void __TBB_machine_pause( int32_t delay ) { 00140 for (int32_t i = 0; i < delay; i++) { 00141 __asm__ __volatile__("pause;"); 00142 } 00143 return; 00144 } 00145 00146 static inline int64_t __TBB_machine_load8 (const volatile void *ptr) { 00147 int64_t result; 00148 if( ((uint32_t)ptr&7u)==0 ) { 00149 // Aligned load 00150 __asm__ __volatile__ ( "fildq %1\n\t" 00151 "fistpq %0" : "=m"(result) : "m"(*(const __TBB_VOLATILE uint64_t*)ptr) : "memory" ); 00152 } else { 00153 // Unaligned load 00154 result = __TBB_machine_cmpswp8(const_cast<void*>(ptr),0,0); 00155 } 00156 return result; 00157 } 00158 00160 00161 extern "C" void __TBB_machine_store8_slow( volatile void *ptr, int64_t value ); 00162 extern "C" void __TBB_machine_store8_slow_perf_warning( volatile void *ptr ); 00163 00164 static inline void __TBB_machine_store8(volatile void *ptr, int64_t value) { 00165 if( ((uint32_t)ptr&7u)==0 ) { 00166 // Aligned store 00167 __asm__ __volatile__ ( "fildq %1\n\t" 00168 "fistpq %0" : "=m"(*(__TBB_VOLATILE int64_t*)ptr) : "m"(value) : "memory" ); 00169 } else { 00170 // Unaligned store 00171 #if TBB_USE_PERFORMANCE_WARNINGS 00172 __TBB_machine_store8_slow_perf_warning(ptr); 00173 #endif /* TBB_USE_PERFORMANCE_WARNINGS */ 00174 __TBB_machine_store8_slow(ptr,value); 00175 } 00176 } 00177 00178 template <typename T, size_t S> 00179 struct __TBB_machine_load_store { 00180 static inline T load_with_acquire(const volatile T& location) { 00181 T to_return = location; 00182 __asm__ __volatile__("" : : : "memory" ); // Compiler fence to keep operations from migrating upwards 00183 return to_return; 00184 } 00185 00186 static inline void store_with_release(volatile T &location, T value) { 00187 __asm__ __volatile__("" : : : "memory" ); // Compiler fence to keep operations from migrating upwards 00188 location = value; 00189 } 00190 }; 00191 00192 template <typename T> 00193 struct __TBB_machine_load_store<T,8> { 00194 static inline T load_with_acquire(const volatile T& location) { 00195 T to_return = __TBB_machine_load8((const volatile void *)&location); 00196 __asm__ __volatile__("" : : : "memory" ); // Compiler fence to keep operations from migrating upwards 00197 return to_return; 00198 } 00199 00200 static inline void store_with_release(volatile T &location, T value) { 00201 __asm__ __volatile__("" : : : "memory" ); // Compiler fence to keep operations from migrating downwards 00202 __TBB_machine_store8((volatile void *)&location,(int64_t)value); 00203 } 00204 }; 00205 00206 #undef __TBB_VOLATILE 00207 00208 template<typename T> 00209 inline T __TBB_machine_load_with_acquire(const volatile T &location) { 00210 return __TBB_machine_load_store<T,sizeof(T)>::load_with_acquire(location); 00211 } 00212 00213 template<typename T, typename V> 00214 inline void __TBB_machine_store_with_release(volatile T &location, V value) { 00215 __TBB_machine_load_store<T,sizeof(T)>::store_with_release(location,value); 00216 } 00217 00218 #define __TBB_load_with_acquire(L) __TBB_machine_load_with_acquire((L)) 00219 #define __TBB_store_with_release(L,V) __TBB_machine_store_with_release((L),(V)) 00220 00221 // Machine specific atomic operations 00222 00223 #define __TBB_CompareAndSwap1(P,V,C) __TBB_machine_cmpswp1(P,V,C) 00224 #define __TBB_CompareAndSwap2(P,V,C) __TBB_machine_cmpswp2(P,V,C) 00225 #define __TBB_CompareAndSwap4(P,V,C) __TBB_machine_cmpswp4(P,V,C) 00226 #define __TBB_CompareAndSwap8(P,V,C) __TBB_machine_cmpswp8(P,V,C) 00227 #define __TBB_CompareAndSwapW(P,V,C) __TBB_machine_cmpswp4(P,V,C) 00228 00229 #define __TBB_FetchAndAdd1(P,V) __TBB_machine_fetchadd1(P,V) 00230 #define __TBB_FetchAndAdd2(P,V) __TBB_machine_fetchadd2(P,V) 00231 #define __TBB_FetchAndAdd4(P,V) __TBB_machine_fetchadd4(P,V) 00232 #define __TBB_FetchAndAddW(P,V) __TBB_machine_fetchadd4(P,V) 00233 00234 #define __TBB_FetchAndStore1(P,V) __TBB_machine_fetchstore1(P,V) 00235 #define __TBB_FetchAndStore2(P,V) __TBB_machine_fetchstore2(P,V) 00236 #define __TBB_FetchAndStore4(P,V) __TBB_machine_fetchstore4(P,V) 00237 #define __TBB_FetchAndStoreW(P,V) __TBB_machine_fetchstore4(P,V) 00238 00239 #define __TBB_Store8(P,V) __TBB_machine_store8(P,V) 00240 #define __TBB_Load8(P) __TBB_machine_load8(P) 00241 00242 #define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) 00243 #define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V) 00244 00245 00246 // Those we chose not to implement (they will be implemented generically using CMPSWP8) 00247 #undef __TBB_FetchAndAdd8 00248 #undef __TBB_FetchAndStore8 00249 00250 // Definition of other functions 00251 #define __TBB_Pause(V) __TBB_machine_pause(V) 00252 #define __TBB_Log2(V) __TBB_machine_lg(V) 00253 00254 // Special atomic functions 00255 #define __TBB_FetchAndAddWrelease(P,V) __TBB_FetchAndAddW(P,V) 00256 #define __TBB_FetchAndIncrementWacquire(P) __TBB_FetchAndAddW(P,1) 00257 #define __TBB_FetchAndDecrementWrelease(P) __TBB_FetchAndAddW(P,-1) 00258 00259 // Use generic definitions from tbb_machine.h 00260 #undef __TBB_TryLockByte 00261 #undef __TBB_LockByte
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.