| enumerable_thread_specific.h | | enumerable_thread_specific.h | |
| | | | |
| skipping to change at line 35 | | skipping to change at line 35 | |
| invalidate any other reasons why the executable file might be covered b
y | | invalidate any other reasons why the executable file might be covered b
y | |
| the GNU General Public License. | | the GNU General Public License. | |
| */ | | */ | |
| | | | |
| #ifndef __TBB_enumerable_thread_specific_H | | #ifndef __TBB_enumerable_thread_specific_H | |
| #define __TBB_enumerable_thread_specific_H | | #define __TBB_enumerable_thread_specific_H | |
| | | | |
| #include "concurrent_vector.h" | | #include "concurrent_vector.h" | |
| #include "tbb_thread.h" | | #include "tbb_thread.h" | |
| #include "tbb_allocator.h" | | #include "tbb_allocator.h" | |
|
| | | #include "tbb_profiling.h" | |
| #include "cache_aligned_allocator.h" | | #include "cache_aligned_allocator.h" | |
| #include "aligned_space.h" | | #include "aligned_space.h" | |
| #include <string.h> // for memcpy | | #include <string.h> // for memcpy | |
| | | | |
| #if _WIN32||_WIN64 | | #if _WIN32||_WIN64 | |
| #include "machine/windows_api.h" | | #include "machine/windows_api.h" | |
| #else | | #else | |
| #include <pthread.h> | | #include <pthread.h> | |
| #endif | | #endif | |
| | | | |
| namespace tbb { | | namespace tbb { | |
| | | | |
| //! enum for selecting between single key and key-per-instance versions | | //! enum for selecting between single key and key-per-instance versions | |
| enum ets_key_usage_type { ets_key_per_instance, ets_no_key }; | | enum ets_key_usage_type { ets_key_per_instance, ets_no_key }; | |
| | | | |
| namespace interface6 { | | namespace interface6 { | |
| | | | |
| //! @cond | | //! @cond | |
| namespace internal { | | namespace internal { | |
| | | | |
|
| | | using namespace tbb::internal; | |
| | | | |
| template<ets_key_usage_type ETS_key_type> | | template<ets_key_usage_type ETS_key_type> | |
| class ets_base: tbb::internal::no_copy { | | class ets_base: tbb::internal::no_copy { | |
| protected: | | protected: | |
| #if _WIN32||_WIN64 | | #if _WIN32||_WIN64 | |
| typedef DWORD key_type; | | typedef DWORD key_type; | |
| #else | | #else | |
| typedef pthread_t key_type; | | typedef pthread_t key_type; | |
| #endif | | #endif | |
| #if __TBB_PROTECTED_NESTED_CLASS_BROKEN | | #if __TBB_PROTECTED_NESTED_CLASS_BROKEN | |
| public: | | public: | |
| | | | |
| skipping to change at line 130 | | skipping to change at line 133 | |
| static size_t hash( key_type k ) { | | static size_t hash( key_type k ) { | |
| // Multiplicative hashing. Client should use *upper* bits. | | // Multiplicative hashing. Client should use *upper* bits. | |
| // casts required for Mac gcc4.* compiler | | // casts required for Mac gcc4.* compiler | |
| return uintptr_t(k)*tbb::internal::select_size_t_constant<0
x9E3779B9,0x9E3779B97F4A7C15ULL>::value; | | return uintptr_t(k)*tbb::internal::select_size_t_constant<0
x9E3779B9,0x9E3779B97F4A7C15ULL>::value; | |
| } | | } | |
| | | | |
| ets_base() {my_root=NULL; my_count=0;} | | ets_base() {my_root=NULL; my_count=0;} | |
| virtual ~ets_base(); // g++ complains if this is not virtual..
. | | virtual ~ets_base(); // g++ complains if this is not virtual..
. | |
| void* table_lookup( bool& exists ); | | void* table_lookup( bool& exists ); | |
| void table_clear(); | | void table_clear(); | |
|
| | | // table_find is used in copying ETS, so is not used in concurr | |
| | | ent context. So | |
| | | // we don't need itt annotations for it. | |
| slot& table_find( key_type k ) { | | slot& table_find( key_type k ) { | |
| size_t h = hash(k); | | size_t h = hash(k); | |
| array* r = my_root; | | array* r = my_root; | |
| size_t mask = r->mask(); | | size_t mask = r->mask(); | |
| for(size_t i = r->start(h);;i=(i+1)&mask) { | | for(size_t i = r->start(h);;i=(i+1)&mask) { | |
| slot& s = r->at(i); | | slot& s = r->at(i); | |
| if( s.empty() || s.match(k) ) | | if( s.empty() || s.match(k) ) | |
| return s; | | return s; | |
| } | | } | |
| } | | } | |
| | | | |
| skipping to change at line 174 | | skipping to change at line 179 | |
| } | | } | |
| | | | |
| template<ets_key_usage_type ETS_key_type> | | template<ets_key_usage_type ETS_key_type> | |
| void* ets_base<ETS_key_type>::table_lookup( bool& exists ) { | | void* ets_base<ETS_key_type>::table_lookup( bool& exists ) { | |
| const key_type k = key_of_current_thread(); | | const key_type k = key_of_current_thread(); | |
| | | | |
| __TBB_ASSERT(k!=0,NULL); | | __TBB_ASSERT(k!=0,NULL); | |
| void* found; | | void* found; | |
| size_t h = hash(k); | | size_t h = hash(k); | |
| for( array* r=my_root; r; r=r->next ) { | | for( array* r=my_root; r; r=r->next ) { | |
|
| | | call_itt_notify(acquired,r); | |
| size_t mask=r->mask(); | | size_t mask=r->mask(); | |
| for(size_t i = r->start(h); ;i=(i+1)&mask) { | | for(size_t i = r->start(h); ;i=(i+1)&mask) { | |
| slot& s = r->at(i); | | slot& s = r->at(i); | |
| if( s.empty() ) break; | | if( s.empty() ) break; | |
| if( s.match(k) ) { | | if( s.match(k) ) { | |
| if( r==my_root ) { | | if( r==my_root ) { | |
| // Success at top level | | // Success at top level | |
| exists = true; | | exists = true; | |
| return s.ptr; | | return s.ptr; | |
| } else { | | } else { | |
| // Success at some other level. Need to insert
at top level. | | // Success at some other level. Need to insert
at top level. | |
| exists = true; | | exists = true; | |
| found = s.ptr; | | found = s.ptr; | |
| goto insert; | | goto insert; | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
|
| // Key does not yet exist | | // Key does not yet exist. The density of slots in the table d | |
| | | oes not exceed 0.5, | |
| | | // for if this will occur a new table is allocated with double | |
| | | the current table | |
| | | // size, which is swapped in as the new root table. So an empt | |
| | | y slot is guaranteed. | |
| exists = false; | | exists = false; | |
| found = create_local(); | | found = create_local(); | |
| { | | { | |
| size_t c = ++my_count; | | size_t c = ++my_count; | |
| array* r = my_root; | | array* r = my_root; | |
|
| | | call_itt_notify(acquired,r); | |
| if( !r || c>r->size()/2 ) { | | if( !r || c>r->size()/2 ) { | |
| size_t s = r ? r->lg_size : 2; | | size_t s = r ? r->lg_size : 2; | |
| while( c>size_t(1)<<(s-1) ) ++s; | | while( c>size_t(1)<<(s-1) ) ++s; | |
| array* a = allocate(s); | | array* a = allocate(s); | |
| for(;;) { | | for(;;) { | |
|
| a->next = my_root; | | a->next = r; | |
| | | call_itt_notify(releasing,a); | |
| array* new_r = my_root.compare_and_swap(a,r); | | array* new_r = my_root.compare_and_swap(a,r); | |
| if( new_r==r ) break; | | if( new_r==r ) break; | |
|
| | | call_itt_notify(acquired, new_r); | |
| if( new_r->lg_size>=s ) { | | if( new_r->lg_size>=s ) { | |
| // Another thread inserted an equal or bigger
array, so our array is superfluous. | | // Another thread inserted an equal or bigger
array, so our array is superfluous. | |
| free(a); | | free(a); | |
| break; | | break; | |
| } | | } | |
| r = new_r; | | r = new_r; | |
| } | | } | |
| } | | } | |
| } | | } | |
| insert: | | insert: | |
|
| // Guaranteed to be room for it, and it is not present, so sear | | // Whether a slot has been found in an older table, or if it has be | |
| ch for empty slot and grab it. | | en inserted at this level, | |
| | | // it has already been accounted for in the total. Guaranteed to b | |
| | | e room for it, and it is | |
| | | // not present, so search for empty slot and use it. | |
| array* ir = my_root; | | array* ir = my_root; | |
|
| | | call_itt_notify(acquired, ir); | |
| size_t mask = ir->mask(); | | size_t mask = ir->mask(); | |
| for(size_t i = ir->start(h);;i=(i+1)&mask) { | | for(size_t i = ir->start(h);;i=(i+1)&mask) { | |
| slot& s = ir->at(i); | | slot& s = ir->at(i); | |
| if( s.empty() ) { | | if( s.empty() ) { | |
| if( s.claim(k) ) { | | if( s.claim(k) ) { | |
| s.ptr = found; | | s.ptr = found; | |
| return found; | | return found; | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
End of changes. 10 change blocks. |
| 4 lines changed or deleted | | 23 lines changed or added | |
|
| gcc_armv7.h | | gcc_armv7.h | |
| | | | |
| skipping to change at line 62 | | skipping to change at line 62 | |
| #if __BIG_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_B
IG_ENDIAN__) | | #if __BIG_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_B
IG_ENDIAN__) | |
| #define __TBB_ENDIANNESS __TBB_ENDIAN_BIG | | #define __TBB_ENDIANNESS __TBB_ENDIAN_BIG | |
| #elif __LITTLE_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__==__OR
DER_LITTLE_ENDIAN__) | | #elif __LITTLE_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__==__OR
DER_LITTLE_ENDIAN__) | |
| #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | | #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | |
| #elif defined(__BYTE_ORDER__) | | #elif defined(__BYTE_ORDER__) | |
| #define __TBB_ENDIANNESS __TBB_ENDIAN_UNSUPPORTED | | #define __TBB_ENDIANNESS __TBB_ENDIAN_UNSUPPORTED | |
| #else | | #else | |
| #define __TBB_ENDIANNESS __TBB_ENDIAN_DETECT | | #define __TBB_ENDIANNESS __TBB_ENDIAN_DETECT | |
| #endif | | #endif | |
| | | | |
|
| #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | | #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | |
| | | #define __TBB_full_memory_fence() __asm__ __volatile__("dmb ish": : :"memor | |
| | | y") | |
| #define __TBB_control_consistency_helper() __TBB_compiler_fence() | | #define __TBB_control_consistency_helper() __TBB_compiler_fence() | |
|
| | | #define __TBB_acquire_consistency_helper() __TBB_full_memory_fence() | |
| #define __TBB_armv7_inner_shareable_barrier() __asm__ __volatile__("dmb ish | | #define __TBB_release_consistency_helper() __TBB_full_memory_fence() | |
| ": : :"memory") | | | |
| #define __TBB_acquire_consistency_helper() __TBB_armv7_inner_shareable_barr | | | |
| ier() | | | |
| #define __TBB_release_consistency_helper() __TBB_armv7_inner_shareable_barr | | | |
| ier() | | | |
| #define __TBB_full_memory_fence() __TBB_armv7_inner_shareable_barrier() | | | |
| | | | |
| //-------------------------------------------------- | | //-------------------------------------------------- | |
| // Compare and swap | | // Compare and swap | |
| //-------------------------------------------------- | | //-------------------------------------------------- | |
| | | | |
| /** | | /** | |
| * Atomic CAS for 32 bit values, if *ptr==comparand, then *ptr=value, retur
ns *ptr | | * Atomic CAS for 32 bit values, if *ptr==comparand, then *ptr=value, retur
ns *ptr | |
| * @param ptr pointer to value in memory to be swapped with value if *ptr==
comparand | | * @param ptr pointer to value in memory to be swapped with value if *ptr==
comparand | |
| * @param value value to assign *ptr to if *ptr==comparand | | * @param value value to assign *ptr to if *ptr==comparand | |
| * @param comparand value to compare with *ptr | | * @param comparand value to compare with *ptr | |
| | | | |
| skipping to change at line 199 | | skipping to change at line 197 | |
| namespace internal { | | namespace internal { | |
| template <typename T, size_t S> | | template <typename T, size_t S> | |
| struct machine_load_store_relaxed { | | struct machine_load_store_relaxed { | |
| static inline T load ( const volatile T& location ) { | | static inline T load ( const volatile T& location ) { | |
| const T value = location; | | const T value = location; | |
| | | | |
| /* | | /* | |
| * An extra memory barrier is required for errata #761319 | | * An extra memory barrier is required for errata #761319 | |
| * Please see http://infocenter.arm.com/help/topic/com.arm.doc.u
an0004a | | * Please see http://infocenter.arm.com/help/topic/com.arm.doc.u
an0004a | |
| */ | | */ | |
|
| __TBB_armv7_inner_shareable_barrier(); | | __TBB_acquire_consistency_helper(); | |
| return value; | | return value; | |
| } | | } | |
| | | | |
| static inline void store ( volatile T& location, T value ) { | | static inline void store ( volatile T& location, T value ) { | |
| location = value; | | location = value; | |
| } | | } | |
| }; | | }; | |
| }} // namespaces internal, tbb | | }} // namespaces internal, tbb | |
| | | | |
| // Machine specific atomic operations | | // Machine specific atomic operations | |
| | | | |
| #define __TBB_CompareAndSwap4(P,V,C) __TBB_machine_cmpswp4(P,V,C) | | #define __TBB_CompareAndSwap4(P,V,C) __TBB_machine_cmpswp4(P,V,C) | |
| #define __TBB_CompareAndSwap8(P,V,C) __TBB_machine_cmpswp8(P,V,C) | | #define __TBB_CompareAndSwap8(P,V,C) __TBB_machine_cmpswp8(P,V,C) | |
|
| #define __TBB_CompareAndSwapW(P,V,C) __TBB_machine_cmpswp4(P,V,C) | | | |
| #define __TBB_Pause(V) __TBB_machine_pause(V) | | #define __TBB_Pause(V) __TBB_machine_pause(V) | |
| | | | |
| // Use generics for some things | | // Use generics for some things | |
| #define __TBB_USE_GENERIC_PART_WORD_CAS 1 | | #define __TBB_USE_GENERIC_PART_WORD_CAS 1 | |
| #define __TBB_USE_GENERIC_PART_WORD_FETCH_ADD 1 | | #define __TBB_USE_GENERIC_PART_WORD_FETCH_ADD 1 | |
| #define __TBB_USE_GENERIC_PART_WORD_FETCH_STORE 1 | | #define __TBB_USE_GENERIC_PART_WORD_FETCH_STORE 1 | |
| #define __TBB_USE_GENERIC_FETCH_STORE 1 | | #define __TBB_USE_GENERIC_FETCH_STORE 1 | |
| #define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 | | #define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 | |
| #define __TBB_USE_GENERIC_DWORD_LOAD_STORE 1 | | #define __TBB_USE_GENERIC_DWORD_LOAD_STORE 1 | |
| #define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 | | #define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 | |
| | | | |
End of changes. 4 change blocks. |
| 11 lines changed or deleted | | 6 lines changed or added | |
|
| msvc_armv7.h | | msvc_armv7.h | |
| | | | |
| skipping to change at line 42 | | skipping to change at line 42 | |
| | | | |
| #define __TBB_msvc_armv7_H | | #define __TBB_msvc_armv7_H | |
| | | | |
| #include <intrin.h> | | #include <intrin.h> | |
| #include <float.h> | | #include <float.h> | |
| | | | |
| #define __TBB_WORDSIZE 4 | | #define __TBB_WORDSIZE 4 | |
| | | | |
| #define __TBB_ENDIANNESS __TBB_ENDIAN_UNSUPPORTED | | #define __TBB_ENDIANNESS __TBB_ENDIAN_UNSUPPORTED | |
| | | | |
|
| #define __TBB_compiler_fence() __dmb(_ARM_BARRIER_SY) | | #if defined(TBB_WIN32_USE_CL_BUILTINS) | |
| | | // We can test this on _M_IX86 | |
| | | #pragma intrinsic(_ReadWriteBarrier) | |
| | | #pragma intrinsic(_mm_mfence) | |
| | | #define __TBB_compiler_fence() _ReadWriteBarrier() | |
| | | #define __TBB_full_memory_fence() _mm_mfence() | |
| #define __TBB_control_consistency_helper() __TBB_compiler_fence() | | #define __TBB_control_consistency_helper() __TBB_compiler_fence() | |
|
| | | #define __TBB_acquire_consistency_helper() __TBB_compiler_fence() | |
| #define __TBB_armv7_inner_shareable_barrier() __dmb(_ARM_BARRIER_ISH) | | #define __TBB_release_consistency_helper() __TBB_compiler_fence() | |
| #define __TBB_acquire_consistency_helper() __TBB_armv7_inner_shareable_barr | | #else | |
| ier() | | //Now __dmb(_ARM_BARRIER_SY) is used for both compiler and memory fences | |
| #define __TBB_release_consistency_helper() __TBB_armv7_inner_shareable_barr | | //This might be changed later after testing | |
| ier() | | #define __TBB_compiler_fence() __dmb(_ARM_BARRIER_SY) | |
| #define __TBB_full_memory_fence() __TBB_armv7_inner_shareable_barrier() | | #define __TBB_full_memory_fence() __dmb(_ARM_BARRIER_SY) | |
| | | #define __TBB_control_consistency_helper() __TBB_compiler_fence() | |
| | | #define __TBB_acquire_consistency_helper() __TBB_full_memory_fence() | |
| | | #define __TBB_release_consistency_helper() __TBB_full_memory_fence() | |
| | | #endif | |
| | | | |
| //-------------------------------------------------- | | //-------------------------------------------------- | |
| // Compare and swap | | // Compare and swap | |
| //-------------------------------------------------- | | //-------------------------------------------------- | |
| | | | |
| /** | | /** | |
| * Atomic CAS for 32 bit values, if *ptr==comparand, then *ptr=value, retur
ns *ptr | | * Atomic CAS for 32 bit values, if *ptr==comparand, then *ptr=value, retur
ns *ptr | |
| * @param ptr pointer to value in memory to be swapped with value if *ptr==
comparand | | * @param ptr pointer to value in memory to be swapped with value if *ptr==
comparand | |
| * @param value value to assign *ptr to if *ptr==comparand | | * @param value value to assign *ptr to if *ptr==comparand | |
| * @param comparand value to compare with *ptr | | * @param comparand value to compare with *ptr | |
| * @return value originally in memory at ptr, regardless of success | | * @return value originally in memory at ptr, regardless of success | |
| */ | | */ | |
| | | | |
| #define __TBB_MACHINE_DEFINE_ATOMICS_CMPSWP(S,T,F)
\ | | #define __TBB_MACHINE_DEFINE_ATOMICS_CMPSWP(S,T,F)
\ | |
| inline T __TBB_machine_cmpswp##S( volatile void *ptr, T value, T comparand
) { \ | | inline T __TBB_machine_cmpswp##S( volatile void *ptr, T value, T comparand
) { \ | |
|
| return _InterlockedCompareExchange##F(reinterpret_cast<volatile T *>
(ptr),comparand,value); \ | | return _InterlockedCompareExchange##F(reinterpret_cast<volatile T *>(pt
r),value,comparand); \ | |
| }
\ | | }
\ | |
| | | | |
| #define __TBB_MACHINE_DEFINE_ATOMICS_FETCHADD(S,T,F)
\ | | #define __TBB_MACHINE_DEFINE_ATOMICS_FETCHADD(S,T,F)
\ | |
| inline T __TBB_machine_fetchadd##S( volatile void *ptr, T value ) {
\ | | inline T __TBB_machine_fetchadd##S( volatile void *ptr, T value ) {
\ | |
|
| return _InterlockedAdd##F(reinterpret_cast<volatile T *>(ptr),value)
; \ | | return _InterlockedExchangeAdd##F(reinterpret_cast<volatile T *>(ptr),v
alue); \ | |
| }
\ | | }
\ | |
| | | | |
| __TBB_MACHINE_DEFINE_ATOMICS_CMPSWP(1,char,8) | | __TBB_MACHINE_DEFINE_ATOMICS_CMPSWP(1,char,8) | |
| __TBB_MACHINE_DEFINE_ATOMICS_CMPSWP(2,short,16) | | __TBB_MACHINE_DEFINE_ATOMICS_CMPSWP(2,short,16) | |
| __TBB_MACHINE_DEFINE_ATOMICS_CMPSWP(4,long,) | | __TBB_MACHINE_DEFINE_ATOMICS_CMPSWP(4,long,) | |
| __TBB_MACHINE_DEFINE_ATOMICS_CMPSWP(8,__int64,64) | | __TBB_MACHINE_DEFINE_ATOMICS_CMPSWP(8,__int64,64) | |
| __TBB_MACHINE_DEFINE_ATOMICS_FETCHADD(4,long,) | | __TBB_MACHINE_DEFINE_ATOMICS_FETCHADD(4,long,) | |
|
| | | #if defined(TBB_WIN32_USE_CL_BUILTINS) | |
| | | // No _InterlockedExchangeAdd64 intrinsic on _M_IX86 | |
| | | #define __TBB_64BIT_ATOMICS 0 | |
| | | #else | |
| __TBB_MACHINE_DEFINE_ATOMICS_FETCHADD(8,__int64,64) | | __TBB_MACHINE_DEFINE_ATOMICS_FETCHADD(8,__int64,64) | |
|
| | | #endif | |
| | | | |
| inline void __TBB_machine_pause (int32_t delay ) | | inline void __TBB_machine_pause (int32_t delay ) | |
| { | | { | |
| while(delay>0) | | while(delay>0) | |
| { | | { | |
|
| __TBB_compiler_fence(); | | __TBB_compiler_fence(); | |
| delay--; | | delay--; | |
| } | | } | |
| } | | } | |
| | | | |
| namespace tbb { | | namespace tbb { | |
|
| namespace internal { | | namespace internal { | |
| template <typename T, size_t S> | | template <typename T, size_t S> | |
| struct machine_load_store_relaxed { | | struct machine_load_store_relaxed { | |
| static inline T load ( const volatile T& location ) { | | static inline T load ( const volatile T& location ) { | |
| const T value = location; | | const T value = location; | |
| | | | |
| /* | | /* | |
| * An extra memory barrier is required for errata #761319 | | * An extra memory barrier is required for errata #761319 | |
| * Please see http://infocenter.arm.com/help/topic/com.arm.doc.u | | * Please see http://infocenter.arm.com/help/topic/com.arm.d | |
| an0004a | | oc.uan0004a | |
| */ | | */ | |
| __TBB_armv7_inner_shareable_barrier(); | | __TBB_acquire_consistency_helper(); | |
| return value; | | return value; | |
| } | | } | |
| | | | |
| static inline void store ( volatile T& location, T value ) { | | static inline void store ( volatile T& location, T value ) { | |
| location = value; | | location = value; | |
| } | | } | |
| }; | | }; | |
| }} // namespaces internal, tbb | | }} // namespaces internal, tbb | |
| | | | |
| // Machine specific atomic operations | | // Machine specific atomic operations | |
|
| | | | |
| #define __TBB_CompareAndSwap4(P,V,C) __TBB_machine_cmpswp4(P,V,C) | | #define __TBB_CompareAndSwap4(P,V,C) __TBB_machine_cmpswp4(P,V,C) | |
| #define __TBB_CompareAndSwap8(P,V,C) __TBB_machine_cmpswp8(P,V,C) | | #define __TBB_CompareAndSwap8(P,V,C) __TBB_machine_cmpswp8(P,V,C) | |
| #define __TBB_Pause(V) __TBB_machine_pause(V) | | #define __TBB_Pause(V) __TBB_machine_pause(V) | |
| | | | |
| // Use generics for some things | | // Use generics for some things | |
|
| | | #define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1 | |
| | | #define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 | |
| #define __TBB_USE_GENERIC_PART_WORD_FETCH_ADD 1 | | #define __TBB_USE_GENERIC_PART_WORD_FETCH_ADD 1 | |
| #define __TBB_USE_GENERIC_PART_WORD_FETCH_STORE 1 | | #define __TBB_USE_GENERIC_PART_WORD_FETCH_STORE 1 | |
| #define __TBB_USE_GENERIC_FETCH_STORE 1 | | #define __TBB_USE_GENERIC_FETCH_STORE 1 | |
|
| #define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 | | | |
| #define __TBB_USE_GENERIC_DWORD_LOAD_STORE 1 | | #define __TBB_USE_GENERIC_DWORD_LOAD_STORE 1 | |
| #define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 | | #define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 | |
| | | | |
|
| | | #if defined(TBB_WIN32_USE_CL_BUILTINS) | |
| | | #if !__TBB_WIN8UI_SUPPORT | |
| | | extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void ); | |
| | | #define __TBB_Yield() SwitchToThread() | |
| | | #else | |
| | | #include<thread> | |
| | | #define __TBB_Yield() std::this_thread::yield() | |
| | | #endif | |
| | | #else | |
| #define __TBB_Yield() __yield() | | #define __TBB_Yield() __yield() | |
|
| | | #endif | |
| | | | |
|
| // API to retrieve/update FPU control setting not implemented | | // API to retrieve/update FPU control setting | |
| #define __TBB_CPU_CTL_ENV_PRESENT 1 | | #define __TBB_CPU_CTL_ENV_PRESENT 1 | |
| | | | |
| typedef unsigned int __TBB_cpu_ctl_env_t; | | typedef unsigned int __TBB_cpu_ctl_env_t; | |
| | | | |
| inline void __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* ctl ) { | | inline void __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* ctl ) { | |
| *ctl = _control87(0, 0); | | *ctl = _control87(0, 0); | |
| } | | } | |
| inline void __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* ctl ) { | | inline void __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* ctl ) { | |
| _control87( *ctl, ~0U ); | | _control87( *ctl, ~0U ); | |
| } | | } | |
| | | | |
End of changes. 14 change blocks. |
| 34 lines changed or deleted | | 58 lines changed or added | |
|
| tbb_exception.h | | tbb_exception.h | |
| | | | |
| skipping to change at line 164 | | skipping to change at line 164 | |
| TBB provides two implementations of this interface: tbb::captured_excep
tion and | | TBB provides two implementations of this interface: tbb::captured_excep
tion and | |
| template class tbb::movable_exception. See their declarations for more
info. **/ | | template class tbb::movable_exception. See their declarations for more
info. **/ | |
| class tbb_exception : public std::exception | | class tbb_exception : public std::exception | |
| { | | { | |
| /** No operator new is provided because the TBB usage model assumes dyn
amic | | /** No operator new is provided because the TBB usage model assumes dyn
amic | |
| creation of the TBB exception objects only by means of applying mov
e() | | creation of the TBB exception objects only by means of applying mov
e() | |
| operation on an exception thrown out of TBB scheduler. **/ | | operation on an exception thrown out of TBB scheduler. **/ | |
| void* operator new ( size_t ); | | void* operator new ( size_t ); | |
| | | | |
| public: | | public: | |
|
| | | #if __clang__ | |
| | | // At -O3 or even -O2 optimization level, Clang may fully throw away an | |
| | | empty destructor | |
| | | // of tbb_exception from destructors of derived classes. As a result, i | |
| | | t does not create | |
| | | // vtable for tbb_exception, which is a required part of TBB binary int | |
| | | erface. | |
| | | // Making the destructor non-empty (with just a semicolon) prevents tha | |
| | | t optimization. | |
| | | ~tbb_exception() throw() { /* keep the semicolon! */ ; } | |
| | | #endif | |
| | | | |
| //! Creates and returns pointer to the deep copy of this exception obje
ct. | | //! Creates and returns pointer to the deep copy of this exception obje
ct. | |
| /** Move semantics is allowed. **/ | | /** Move semantics is allowed. **/ | |
| virtual tbb_exception* move () throw() = 0; | | virtual tbb_exception* move () throw() = 0; | |
| | | | |
| //! Destroys objects created by the move() method. | | //! Destroys objects created by the move() method. | |
| /** Frees memory and calls destructor for this exception object. | | /** Frees memory and calls destructor for this exception object. | |
| Can and must be used only on objects created by the move method. **
/ | | Can and must be used only on objects created by the move method. **
/ | |
| virtual void destroy () throw() = 0; | | virtual void destroy () throw() = 0; | |
| | | | |
| //! Throws this exception object. | | //! Throws this exception object. | |
| | | | |
End of changes. 1 change blocks. |
| 0 lines changed or deleted | | 12 lines changed or added | |
|
| tbb_machine.h | | tbb_machine.h | |
| | | | |
| skipping to change at line 217 | | skipping to change at line 217 | |
| #define __TBB_Yield() SwitchToThread() | | #define __TBB_Yield() SwitchToThread() | |
| #if (TBB_USE_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT) | | #if (TBB_USE_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT) | |
| #include "machine/gcc_generic.h" | | #include "machine/gcc_generic.h" | |
| #elif __MINGW64__ | | #elif __MINGW64__ | |
| #include "machine/linux_intel64.h" | | #include "machine/linux_intel64.h" | |
| #elif __MINGW32__ | | #elif __MINGW32__ | |
| #include "machine/linux_ia32.h" | | #include "machine/linux_ia32.h" | |
| #endif | | #endif | |
| #elif (TBB_USE_ICC_BUILTINS && __TBB_ICC_BUILTIN_ATOMICS_PRESENT) | | #elif (TBB_USE_ICC_BUILTINS && __TBB_ICC_BUILTIN_ATOMICS_PRESENT) | |
| #include "machine/icc_generic.h" | | #include "machine/icc_generic.h" | |
|
| #elif defined(_M_IX86) | | #elif defined(_M_IX86) && !defined(__TBB_WIN32_USE_CL_BUILTINS) | |
| #include "machine/windows_ia32.h" | | #include "machine/windows_ia32.h" | |
| #elif defined(_M_X64) | | #elif defined(_M_X64) | |
| #include "machine/windows_intel64.h" | | #include "machine/windows_intel64.h" | |
|
| #elif _XBOX | | #elif defined(_XBOX) | |
| #include "machine/xbox360_ppc.h" | | #include "machine/xbox360_ppc.h" | |
|
| #elif _M_ARM | | #elif defined(_M_ARM) || defined(__TBB_WIN32_USE_CL_BUILTINS) | |
| #include "machine/msvc_armv7.h" | | #include "machine/msvc_armv7.h" | |
| #endif | | #endif | |
| | | | |
| #ifdef _MANAGED | | #ifdef _MANAGED | |
| #pragma managed(pop) | | #pragma managed(pop) | |
| #endif | | #endif | |
| | | | |
| #elif __TBB_DEFINE_MIC | | #elif __TBB_DEFINE_MIC | |
| | | | |
| #include "machine/mic_common.h" | | #include "machine/mic_common.h" | |
| | | | |
| skipping to change at line 851 | | skipping to change at line 851 | |
| | | | |
| // Mapping historically used names to the ones expected by atomic_load_stor
e_traits | | // Mapping historically used names to the ones expected by atomic_load_stor
e_traits | |
| #define __TBB_load_acquire __TBB_load_with_acquire | | #define __TBB_load_acquire __TBB_load_with_acquire | |
| #define __TBB_store_release __TBB_store_with_release | | #define __TBB_store_release __TBB_store_with_release | |
| | | | |
| #ifndef __TBB_Log2 | | #ifndef __TBB_Log2 | |
| inline intptr_t __TBB_Log2( uintptr_t x ) { | | inline intptr_t __TBB_Log2( uintptr_t x ) { | |
| if( x==0 ) return -1; | | if( x==0 ) return -1; | |
| intptr_t result = 0; | | intptr_t result = 0; | |
| | | | |
|
| #ifndef _M_ARM | | #if !defined(_M_ARM) | |
| uintptr_t tmp; | | uintptr_t tmp; | |
|
| if( sizeof(x)>4 && (tmp = ((uint64_t)x)>>32) ) { x=tmp; result += 32
; } | | if( sizeof(x)>4 && (tmp = ((uint64_t)x)>>32) ) { x=tmp; result += 32; } | |
| #endif | | #endif | |
| if( uintptr_t tmp = x>>16 ) { x=tmp; result += 16; } | | if( uintptr_t tmp = x>>16 ) { x=tmp; result += 16; } | |
| if( uintptr_t tmp = x>>8 ) { x=tmp; result += 8; } | | if( uintptr_t tmp = x>>8 ) { x=tmp; result += 8; } | |
| if( uintptr_t tmp = x>>4 ) { x=tmp; result += 4; } | | if( uintptr_t tmp = x>>4 ) { x=tmp; result += 4; } | |
| if( uintptr_t tmp = x>>2 ) { x=tmp; result += 2; } | | if( uintptr_t tmp = x>>2 ) { x=tmp; result += 2; } | |
| | | | |
| return (x&2)? result+1: result; | | return (x&2)? result+1: result; | |
| } | | } | |
| #endif | | #endif | |
| | | | |
| | | | |
End of changes. 5 change blocks. |
| 5 lines changed or deleted | | 5 lines changed or added | |
|
| tbb_stddef.h | | tbb_stddef.h | |
| | | | |
| skipping to change at line 390 | | skipping to change at line 390 | |
| //! A function to determine if "arg is a multiplication of a number and a p
ower of 2". | | //! A function to determine if "arg is a multiplication of a number and a p
ower of 2". | |
| // i.e. for strictly positive i and j, with j a power of 2, | | // i.e. for strictly positive i and j, with j a power of 2, | |
| // determines whether i==j<<k for some nonnegative k (so i==j yields true). | | // determines whether i==j<<k for some nonnegative k (so i==j yields true). | |
| template<typename argument_integer_type, typename divisor_integer_type> | | template<typename argument_integer_type, typename divisor_integer_type> | |
| inline bool is_power_of_two_factor(argument_integer_type arg, divisor_integ
er_type divisor) { | | inline bool is_power_of_two_factor(argument_integer_type arg, divisor_integ
er_type divisor) { | |
| // Divisor is assumed to be a power of two (which is valid for current
uses). | | // Divisor is assumed to be a power of two (which is valid for current
uses). | |
| __TBB_ASSERT( is_power_of_two(divisor), "Divisor should be a power of t
wo" ); | | __TBB_ASSERT( is_power_of_two(divisor), "Divisor should be a power of t
wo" ); | |
| return 0 == (arg & (arg - divisor)); | | return 0 == (arg & (arg - divisor)); | |
| } | | } | |
| | | | |
|
| | | //! Utility template function to prevent "unused" warnings by various compi | |
| | | lers. | |
| | | template<typename T> | |
| | | void suppress_unused_warning( const T& ) {} | |
| | | | |
| // Struct to be used as a version tag for inline functions. | | // Struct to be used as a version tag for inline functions. | |
| /** Version tag can be necessary to prevent loader on Linux from using the
wrong | | /** Version tag can be necessary to prevent loader on Linux from using the
wrong | |
| symbol in debug builds (when inline functions are compiled as out-of-li
ne). **/ | | symbol in debug builds (when inline functions are compiled as out-of-li
ne). **/ | |
| struct version_tag_v3 {}; | | struct version_tag_v3 {}; | |
| | | | |
| typedef version_tag_v3 version_tag; | | typedef version_tag_v3 version_tag; | |
| | | | |
| } // internal | | } // internal | |
| //! @endcond | | //! @endcond | |
| | | | |
| | | | |
End of changes. 1 change blocks. |
| 0 lines changed or deleted | | 5 lines changed or added | |
|
| tick_count.h | | tick_count.h | |
| | | | |
| skipping to change at line 82 | | skipping to change at line 82 | |
| //! Subtract two intervals. | | //! Subtract two intervals. | |
| friend interval_t operator-( const interval_t& i, const interval_t&
j ) { | | friend interval_t operator-( const interval_t& i, const interval_t&
j ) { | |
| return interval_t(i.value-j.value); | | return interval_t(i.value-j.value); | |
| } | | } | |
| | | | |
| //! Accumulation operator | | //! Accumulation operator | |
| interval_t& operator+=( const interval_t& i ) {value += i.value; re
turn *this;} | | interval_t& operator+=( const interval_t& i ) {value += i.value; re
turn *this;} | |
| | | | |
| //! Subtraction operator | | //! Subtraction operator | |
| interval_t& operator-=( const interval_t& i ) {value -= i.value; re
turn *this;} | | interval_t& operator-=( const interval_t& i ) {value -= i.value; re
turn *this;} | |
|
| | | private: | |
| | | static long long ticks_per_second(){ | |
| | | #if _WIN32||_WIN64 | |
| | | LARGE_INTEGER qpfreq; | |
| | | int rval = QueryPerformanceFrequency(&qpfreq); | |
| | | __TBB_ASSERT_EX(rval, "QueryPerformanceFrequency returned zero" | |
| | | ); | |
| | | return static_cast<long long>(qpfreq.QuadPart); | |
| | | #elif __linux__ | |
| | | return static_cast<long long>(1E9); | |
| | | #else /* generic Unix */ | |
| | | return static_cast<long long>(1E6); | |
| | | #endif /* (choice of OS) */ | |
| | | } | |
| }; | | }; | |
| | | | |
| //! Construct an absolute timestamp initialized to zero. | | //! Construct an absolute timestamp initialized to zero. | |
| tick_count() : my_count(0) {}; | | tick_count() : my_count(0) {}; | |
| | | | |
| //! Return current time. | | //! Return current time. | |
| static tick_count now(); | | static tick_count now(); | |
| | | | |
| //! Subtract two timestamps to get the time interval between | | //! Subtract two timestamps to get the time interval between | |
| friend interval_t operator-( const tick_count& t1, const tick_count& t0
); | | friend interval_t operator-( const tick_count& t1, const tick_count& t0
); | |
| | | | |
|
| | | //! Return the resolution of the clock in seconds per tick. | |
| | | static double resolution() { return 1.0 / interval_t::ticks_per_second( | |
| | | ); } | |
| | | | |
| private: | | private: | |
| long long my_count; | | long long my_count; | |
| }; | | }; | |
| | | | |
| inline tick_count tick_count::now() { | | inline tick_count tick_count::now() { | |
| tick_count result; | | tick_count result; | |
| #if _WIN32||_WIN64 | | #if _WIN32||_WIN64 | |
| LARGE_INTEGER qpcnt; | | LARGE_INTEGER qpcnt; | |
|
| QueryPerformanceCounter(&qpcnt); | | int rval = QueryPerformanceCounter(&qpcnt); | |
| | | __TBB_ASSERT_EX(rval, "QueryPerformanceCounter failed"); | |
| result.my_count = qpcnt.QuadPart; | | result.my_count = qpcnt.QuadPart; | |
| #elif __linux__ | | #elif __linux__ | |
| struct timespec ts; | | struct timespec ts; | |
|
| #if TBB_USE_ASSERT | | int status = clock_gettime( CLOCK_REALTIME, &ts ); | |
| int status = | | __TBB_ASSERT_EX( status==0, "CLOCK_REALTIME not supported" ); | |
| #endif /* TBB_USE_ASSERT */ | | | |
| clock_gettime( CLOCK_REALTIME, &ts ); | | | |
| __TBB_ASSERT( status==0, "CLOCK_REALTIME not supported" ); | | | |
| result.my_count = static_cast<long long>(1000000000UL)*static_cast<long
long>(ts.tv_sec) + static_cast<long long>(ts.tv_nsec); | | result.my_count = static_cast<long long>(1000000000UL)*static_cast<long
long>(ts.tv_sec) + static_cast<long long>(ts.tv_nsec); | |
| #else /* generic Unix */ | | #else /* generic Unix */ | |
| struct timeval tv; | | struct timeval tv; | |
|
| #if TBB_USE_ASSERT | | int status = gettimeofday(&tv, NULL); | |
| int status = | | __TBB_ASSERT_EX( status==0, "gettimeofday failed" ); | |
| #endif /* TBB_USE_ASSERT */ | | | |
| gettimeofday(&tv, NULL); | | | |
| __TBB_ASSERT( status==0, "gettimeofday failed" ); | | | |
| result.my_count = static_cast<long long>(1000000)*static_cast<long long
>(tv.tv_sec) + static_cast<long long>(tv.tv_usec); | | result.my_count = static_cast<long long>(1000000)*static_cast<long long
>(tv.tv_sec) + static_cast<long long>(tv.tv_usec); | |
| #endif /*(choice of OS) */ | | #endif /*(choice of OS) */ | |
| return result; | | return result; | |
| } | | } | |
| | | | |
|
| inline tick_count::interval_t::interval_t( double sec ) | | inline tick_count::interval_t::interval_t( double sec ) { | |
| { | | value = static_cast<long long>(sec*interval_t::ticks_per_second()); | |
| #if _WIN32||_WIN64 | | | |
| LARGE_INTEGER qpfreq; | | | |
| QueryPerformanceFrequency(&qpfreq); | | | |
| value = static_cast<long long>(sec*qpfreq.QuadPart); | | | |
| #elif __linux__ | | | |
| value = static_cast<long long>(sec*1E9); | | | |
| #else /* generic Unix */ | | | |
| value = static_cast<long long>(sec*1E6); | | | |
| #endif /* (choice of OS) */ | | | |
| } | | } | |
| | | | |
| inline tick_count::interval_t operator-( const tick_count& t1, const tick_c
ount& t0 ) { | | inline tick_count::interval_t operator-( const tick_count& t1, const tick_c
ount& t0 ) { | |
| return tick_count::interval_t( t1.my_count-t0.my_count ); | | return tick_count::interval_t( t1.my_count-t0.my_count ); | |
| } | | } | |
| | | | |
| inline double tick_count::interval_t::seconds() const { | | inline double tick_count::interval_t::seconds() const { | |
|
| #if _WIN32||_WIN64 | | return value*tick_count::resolution(); | |
| LARGE_INTEGER qpfreq; | | | |
| QueryPerformanceFrequency(&qpfreq); | | | |
| return value/(double)qpfreq.QuadPart; | | | |
| #elif __linux__ | | | |
| return value*1E-9; | | | |
| #else /* generic Unix */ | | | |
| return value*1E-6; | | | |
| #endif /* (choice of OS) */ | | | |
| } | | } | |
| | | | |
| } // namespace tbb | | } // namespace tbb | |
| | | | |
| #endif /* __TBB_tick_count_H */ | | #endif /* __TBB_tick_count_H */ | |
| | | | |
End of changes. 7 change blocks. |
| 31 lines changed or deleted | | 27 lines changed or added | |
|