Shadowrun: Awakened 29 September 2011 - Build 871
linux_ia32.h
Go to the documentation of this file.
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.

GNU Lesser General Public License 3 Sourceforge.net