_concurrent_unordered_impl.h | _concurrent_unordered_impl.h | |||
---|---|---|---|---|
skipping to change at line 48 | skipping to change at line 48 | |||
#include "../tbb_stddef.h" | #include "../tbb_stddef.h" | |||
#if !TBB_USE_EXCEPTIONS && _MSC_VER | #if !TBB_USE_EXCEPTIONS && _MSC_VER | |||
// Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers | // Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers | |||
#pragma warning (push) | #pragma warning (push) | |||
#pragma warning (disable: 4530) | #pragma warning (disable: 4530) | |||
#endif | #endif | |||
#include <iterator> | #include <iterator> | |||
#include <utility> // Need std::pair | #include <utility> // Need std::pair | |||
#include <functional> | #include <functional> // Need std::equal_to (in ../concurrent_unordered_* .h) | |||
#include <string> // For tbb_hasher | #include <string> // For tbb_hasher | |||
#include <cstring> // Need std::memset | #include <cstring> // Need std::memset | |||
#if !TBB_USE_EXCEPTIONS && _MSC_VER | #if !TBB_USE_EXCEPTIONS && _MSC_VER | |||
#pragma warning (pop) | #pragma warning (pop) | |||
#endif | #endif | |||
#include "../atomic.h" | #include "../atomic.h" | |||
#include "../tbb_exception.h" | #include "../tbb_exception.h" | |||
#include "../tbb_allocator.h" | #include "../tbb_allocator.h" | |||
#include "tbb/atomic.h" | ||||
namespace tbb { | namespace tbb { | |||
namespace interface5 { | namespace interface5 { | |||
//! @cond INTERNAL | //! @cond INTERNAL | |||
namespace internal { | namespace internal { | |||
template <typename T, typename Allocator> | template <typename T, typename Allocator> | |||
class split_ordered_list; | class split_ordered_list; | |||
template <typename Traits> | template <typename Traits> | |||
class concurrent_unordered_base; | class concurrent_unordered_base; | |||
skipping to change at line 233 | skipping to change at line 234 | |||
// Return the order key (needed for hashing) | // Return the order key (needed for hashing) | |||
sokey_t get_order_key() const { // TODO: remove | sokey_t get_order_key() const { // TODO: remove | |||
return my_order_key; | return my_order_key; | |||
} | } | |||
// Inserts the new element in the list in an atomic fashion | // Inserts the new element in the list in an atomic fashion | |||
nodeptr_t atomic_set_next(nodeptr_t new_node, nodeptr_t current_nod e) | nodeptr_t atomic_set_next(nodeptr_t new_node, nodeptr_t current_nod e) | |||
{ | { | |||
// Try to change the next pointer on the current element to a n ew element, only if it still points to the cached next | // Try to change the next pointer on the current element to a n ew element, only if it still points to the cached next | |||
nodeptr_t exchange_node = (nodeptr_t) __TBB_CompareAndSwapW((vo id *) &my_next, (uintptr_t)new_node, (uintptr_t)current_node); | nodeptr_t exchange_node = tbb::internal::as_atomic(my_next).com pare_and_swap(new_node, current_node); | |||
if (exchange_node == current_node) // TODO: why this branch? | if (exchange_node == current_node) // TODO: why this branch? | |||
{ | { | |||
// Operation succeeded, return the new node | // Operation succeeded, return the new node | |||
return new_node; | return new_node; | |||
} | } | |||
else | else | |||
{ | { | |||
// Operation failed, return the "interfering" node | // Operation failed, return the "interfering" node | |||
return exchange_node; | return exchange_node; | |||
skipping to change at line 1293 | skipping to change at line 1294 | |||
// Create a dummy first node in this bucket | // Create a dummy first node in this bucket | |||
raw_iterator dummy_node = my_solist.insert_dummy(parent, split_orde r_key_dummy(bucket)); | raw_iterator dummy_node = my_solist.insert_dummy(parent, split_orde r_key_dummy(bucket)); | |||
set_bucket(bucket, dummy_node); | set_bucket(bucket, dummy_node); | |||
} | } | |||
void adjust_table_size(size_type total_elements, size_type current_size ) | void adjust_table_size(size_type total_elements, size_type current_size ) | |||
{ | { | |||
// Grow the table by a factor of 2 if possible and needed | // Grow the table by a factor of 2 if possible and needed | |||
if ( ((float) total_elements / (float) current_size) > my_maximum_b ucket_size ) | if ( ((float) total_elements / (float) current_size) > my_maximum_b ucket_size ) | |||
{ | { | |||
// Double the size of the hash only if size has not changed inb | // Double the size of the hash only if size has not changed in | |||
etween loads | between loads | |||
__TBB_CompareAndSwapW((uintptr_t*)&my_number_of_buckets, uintpt | my_number_of_buckets.compare_and_swap(2u*current_size, current_ | |||
r_t(2u*current_size), uintptr_t(current_size) ); | size); | |||
//Simple "my_number_of_buckets.compare_and_swap( current_size<< 1, current_size );" does not work for VC8 | //Simple "my_number_of_buckets.compare_and_swap( current_size<< 1, current_size );" does not work for VC8 | |||
//due to overzealous compiler warnings in /Wp64 mode | //due to overzealous compiler warnings in /Wp64 mode | |||
} | } | |||
} | } | |||
size_type get_parent(size_type bucket) const | size_type get_parent(size_type bucket) const | |||
{ | { | |||
// Unsets bucket's most significant turned-on bit | // Unsets bucket's most significant turned-on bit | |||
size_type msb = __TBB_Log2((uintptr_t)bucket); | size_type msb = __TBB_Log2((uintptr_t)bucket); | |||
return bucket & ~(size_type(1) << msb); | return bucket & ~(size_type(1) << msb); | |||
skipping to change at line 1339 | skipping to change at line 1340 | |||
void set_bucket(size_type bucket, raw_iterator dummy_head) { | void set_bucket(size_type bucket, raw_iterator dummy_head) { | |||
size_type segment = segment_index_of(bucket); | size_type segment = segment_index_of(bucket); | |||
bucket -= segment_base(segment); | bucket -= segment_base(segment); | |||
if (my_buckets[segment] == NULL) { | if (my_buckets[segment] == NULL) { | |||
size_type sz = segment_size(segment); | size_type sz = segment_size(segment); | |||
raw_iterator * new_segment = my_allocator.allocate(sz); | raw_iterator * new_segment = my_allocator.allocate(sz); | |||
std::memset(new_segment, 0, sz*sizeof(raw_iterator)); | std::memset(new_segment, 0, sz*sizeof(raw_iterator)); | |||
if (__TBB_CompareAndSwapW((void *) &my_buckets[segment], (uintp tr_t)new_segment, 0) != 0) | if (my_buckets[segment].compare_and_swap( new_segment, NULL) != NULL) | |||
my_allocator.deallocate(new_segment, sz); | my_allocator.deallocate(new_segment, sz); | |||
} | } | |||
my_buckets[segment][bucket] = dummy_head; | my_buckets[segment][bucket] = dummy_head; | |||
} | } | |||
bool is_initialized(size_type bucket) const { | bool is_initialized(size_type bucket) const { | |||
size_type segment = segment_index_of(bucket); | size_type segment = segment_index_of(bucket); | |||
bucket -= segment_base(segment); | bucket -= segment_base(segment); | |||
End of changes. 5 change blocks. | ||||
7 lines changed or deleted | 8 lines changed or added | |||
atomic.h | atomic.h | |||
---|---|---|---|---|
skipping to change at line 32 | skipping to change at line 32 | |||
this file and link it with other files to produce an executable, this | this file and link it with other files to produce an executable, this | |||
file does not by itself cause the resulting executable to be covered by | file does not by itself cause the resulting executable to be covered by | |||
the GNU General Public License. This exception does not however | the GNU General Public License. This exception does not however | |||
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_atomic_H | #ifndef __TBB_atomic_H | |||
#define __TBB_atomic_H | #define __TBB_atomic_H | |||
#include "tbb_stddef.h" | ||||
#include <cstddef> | #include <cstddef> | |||
#if _MSC_VER | #if _MSC_VER | |||
#define __TBB_LONG_LONG __int64 | #define __TBB_LONG_LONG __int64 | |||
#else | #else | |||
#define __TBB_LONG_LONG long long | #define __TBB_LONG_LONG long long | |||
#endif /* _MSC_VER */ | #endif /* _MSC_VER */ | |||
#include "tbb_machine.h" | #include "tbb_machine.h" | |||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) | #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) | |||
// Workaround for overzealous compiler warnings | // Workaround for overzealous compiler warnings | |||
#pragma warning (push) | #pragma warning (push) | |||
#pragma warning (disable: 4244 4267) | #pragma warning (disable: 4244 4267 4512) | |||
#endif | #endif | |||
namespace tbb { | namespace tbb { | |||
//! Specifies memory semantics. | //! Specifies memory semantics. | |||
enum memory_semantics { | enum memory_semantics { | |||
//! Sequential consistency | //! Sequential consistency | |||
full_fence, | full_fence, | |||
//! Acquire | //! Acquire | |||
acquire, | acquire, | |||
skipping to change at line 243 | skipping to change at line 242 | |||
template<typename value_type> | template<typename value_type> | |||
union converter { | union converter { | |||
typedef typename atomic_rep<sizeof(value_type)>::word bits_type; | typedef typename atomic_rep<sizeof(value_type)>::word bits_type; | |||
converter(){} | converter(){} | |||
converter(value_type a_value) : value(a_value) {} | converter(value_type a_value) : value(a_value) {} | |||
value_type value; | value_type value; | |||
bits_type bits; | bits_type bits; | |||
}; | }; | |||
template<typename value_t> | template<typename value_t> | |||
union ptr_converter; //Primary template declared, but never | ||||
defined. | ||||
template<typename value_t> | ||||
union ptr_converter<value_t *> { | ||||
typedef typename atomic_rep<sizeof(value_t)>::word * bits_ptr_type; | ||||
ptr_converter(){} | ||||
ptr_converter(value_t* a_value) : value(a_value) {} | ||||
value_t* value; | ||||
bits_ptr_type bits; | ||||
}; | ||||
template<typename value_t> | ||||
static typename converter<value_t>::bits_type to_bits(value_t value){ | static typename converter<value_t>::bits_type to_bits(value_t value){ | |||
return converter<value_t>(value).bits; | return converter<value_t>(value).bits; | |||
} | } | |||
template<typename value_t> | template<typename value_t> | |||
static value_t to_value(typename converter<value_t>::bits_type bits){ | static value_t to_value(typename converter<value_t>::bits_type bits){ | |||
converter<value_t> u; | converter<value_t> u; | |||
u.bits = bits; | u.bits = bits; | |||
return u.value; | return u.value; | |||
} | } | |||
//separate function is needed as it is impossible to distinguish (and t | ||||
hus overload to_bits) | ||||
//whether the pointer passed in is a pointer to atomic location or a va | ||||
lue of that location | ||||
template<typename value_t> | template<typename value_t> | |||
static typename ptr_converter<value_t*>::bits_ptr_type to_bits_ptr(valu | union ptr_converter; //Primary template declared, but never | |||
e_t* value){ | defined. | |||
//TODO: try to use cast to void* and second cast to required pointe | ||||
r type; | template<typename value_t> | |||
//Once (and if) union converter goes away - check if strict aliasin | union ptr_converter<value_t *> { | |||
g warning | ptr_converter(){} | |||
//suppression is still needed once. | ptr_converter(value_t* a_value) : value(a_value) {} | |||
value_t* value; | ||||
uintptr_t bits; | ||||
}; | ||||
//TODO: check if making to_bits accepting reference (thus unifying it w | ||||
ith to_bits_ref) | ||||
//does not hurt performance | ||||
template<typename value_t> | ||||
static typename converter<value_t>::bits_type & to_bits_ref(value_t& va | ||||
lue){ | ||||
//TODO: this #ifdef is temporary workaround, as union conversion se ems to fail | //TODO: this #ifdef is temporary workaround, as union conversion se ems to fail | |||
//on suncc for 64 bit types for 32 bit target | //on suncc for 64 bit types for 32 bit target | |||
#if !__SUNPRO_CC | #if !__SUNPRO_CC | |||
return ptr_converter<value_t*>(value).bits; | return *(typename converter<value_t>::bits_type*)ptr_converter< value_t*>(&value).bits; | |||
#else | #else | |||
return typename ptr_converter<value_t*>::bits_ptr_type (value); | return *(typename converter<value_t>::bits_type*)(&value); | |||
#endif | #endif | |||
} | } | |||
public: | public: | |||
typedef T value_type; | typedef T value_type; | |||
#if __TBB_ATOMIC_CTORS | #if __TBB_ATOMIC_CTORS | |||
atomic_impl() = default ; | atomic_impl() = default ; | |||
constexpr atomic_impl(value_type value):my_storage(value){} | constexpr atomic_impl(value_type value):my_storage(value){} | |||
#endif | #endif | |||
template<memory_semantics M> | template<memory_semantics M> | |||
value_type fetch_and_store( value_type value ) { | value_type fetch_and_store( value_type value ) { | |||
return to_value<value_type>(internal::atomic_traits<sizeof(value_ | return to_value<value_type>( | |||
type),M>::fetch_and_store(&my_storage.my_value,to_bits(value))); | internal::atomic_traits<sizeof(value_type),M>::fetch_and_ | |||
store( &my_storage.my_value, to_bits(value) ) | ||||
); | ||||
} | } | |||
value_type fetch_and_store( value_type value ) { | value_type fetch_and_store( value_type value ) { | |||
return fetch_and_store<full_fence>(value); | return fetch_and_store<full_fence>(value); | |||
} | } | |||
template<memory_semantics M> | template<memory_semantics M> | |||
value_type compare_and_swap( value_type value, value_type comparand ) { | value_type compare_and_swap( value_type value, value_type comparand ) { | |||
return to_value<value_type>(internal::atomic_traits<sizeof(value_ty | return to_value<value_type>( | |||
pe),M>::compare_and_swap(&my_storage.my_value,to_bits(value),to_bits(compar | internal::atomic_traits<sizeof(value_type),M>::compare_and_ | |||
and))); | swap( &my_storage.my_value, to_bits(value), to_bits(comparand) ) | |||
); | ||||
} | } | |||
value_type compare_and_swap( value_type value, value_type comparand ) { | value_type compare_and_swap( value_type value, value_type comparand ) { | |||
return compare_and_swap<full_fence>(value,comparand); | return compare_and_swap<full_fence>(value,comparand); | |||
} | } | |||
operator value_type() const volatile { // volatile quali fier here for backwards compatibility | operator value_type() const volatile { // volatile quali fier here for backwards compatibility | |||
return to_value<value_type>(__TBB_load_with_acquire(*to_bits_ptr(& | return to_value<value_type>( | |||
my_storage.my_value))); | __TBB_load_with_acquire( to_bits_ref(my_storage.my_value) ) | |||
); | ||||
} | } | |||
template<memory_semantics M> | template<memory_semantics M> | |||
value_type load () const { | value_type load () const { | |||
return to_value<value_type>(internal::atomic_load_store_traits<M>:: | return to_value<value_type>( | |||
load(*to_bits_ptr(&my_storage.my_value))); | internal::atomic_load_store_traits<M>::load( to_bits_ref(my | |||
_storage.my_value) ) | ||||
); | ||||
} | } | |||
value_type load () const { | value_type load () const { | |||
return load<acquire>(); | return load<acquire>(); | |||
} | } | |||
template<memory_semantics M> | template<memory_semantics M> | |||
void store ( value_type value ) { | void store ( value_type value ) { | |||
internal::atomic_load_store_traits<M>::store( *to_bits_ptr(&my_stor age.my_value), to_bits(value)); | internal::atomic_load_store_traits<M>::store( to_bits_ref(my_storag e.my_value), to_bits(value)); | |||
} | } | |||
void store ( value_type value ) { | void store ( value_type value ) { | |||
store<release>( value ); | store<release>( value ); | |||
} | } | |||
protected: | protected: | |||
value_type store_with_release( value_type rhs ) { | value_type store_with_release( value_type rhs ) { | |||
__TBB_store_with_release(*to_bits_ptr(&my_storage.my_value),to_bits | //TODO: unify with store<release> | |||
(rhs)); | __TBB_store_with_release( to_bits_ref(my_storage.my_value), to_bits | |||
(rhs) ); | ||||
return rhs; | return rhs; | |||
} | } | |||
}; | }; | |||
//! Base class that provides basic functionality for atomic<T> with fetch_a nd_add. | //! Base class that provides basic functionality for atomic<T> with fetch_a nd_add. | |||
/** I is the underlying type. | /** I is the underlying type. | |||
D is the difference type. | D is the difference type. | |||
StepType should be char if I is an integral type, and T if I is a T*. * / | StepType should be char if I is an integral type, and T if I is a T*. * / | |||
template<typename I, typename D, typename StepType> | template<typename I, typename D, typename StepType> | |||
struct atomic_impl_with_arithmetic: atomic_impl<I> { | struct atomic_impl_with_arithmetic: atomic_impl<I> { | |||
skipping to change at line 424 | skipping to change at line 427 | |||
T operator=( T rhs ) { | T operator=( T rhs ) { | |||
// "this" required here in strict ISO C++ because store_with_releas e is a dependent name | // "this" required here in strict ISO C++ because store_with_releas e is a dependent name | |||
return this->store_with_release(rhs); | return this->store_with_release(rhs); | |||
} | } | |||
atomic<T>& operator=( const atomic<T>& rhs ) {this->store_with_release( rhs); return *this;} | atomic<T>& operator=( const atomic<T>& rhs ) {this->store_with_release( rhs); return *this;} | |||
}; | }; | |||
#if __TBB_ATOMIC_CTORS | #if __TBB_ATOMIC_CTORS | |||
#define __TBB_DECL_ATOMIC(T) \ | #define __TBB_DECL_ATOMIC(T) \ | |||
template<> struct atomic<T>: internal::atomic_impl_with_arithmetic< T,T,char> { \ | template<> struct atomic<T>: internal::atomic_impl_with_arithmetic< T,T,char> { \ | |||
atomic() = default; \ | atomic() = default; \ | |||
constexpr atomic(T arg): internal::atomic_impl_with_arithmetic< T,T,char>(arg) {} \ | constexpr atomic(T arg): internal::atomic_impl_with_arithmetic< T,T,char>(arg) {} \ | |||
\ | \ | |||
T operator=( T rhs ) {return store_with_release(rhs);} \ | T operator=( T rhs ) {return store_with_release(rhs);} \ | |||
atomic<T>& operator=( const atomic<T>& rhs ) {store_with_releas e(rhs); return *this;} \ | atomic<T>& operator=( const atomic<T>& rhs ) {store_with_releas e(rhs); return *this;} \ | |||
}; | }; | |||
#else | #else | |||
#define __TBB_DECL_ATOMIC(T) \ | #define __TBB_DECL_ATOMIC(T) \ | |||
template<> struct atomic<T>: internal::atomic_impl_with_arithmetic< T,T,char> { \ | template<> struct atomic<T>: internal::atomic_impl_with_arithmetic< T,T,char> { \ | |||
T operator=( T rhs ) {return store_with_release(rhs);} \ | T operator=( T rhs ) {return store_with_release(rhs);} \ | |||
atomic<T>& operator=( const atomic<T>& rhs ) {store_with_releas e(rhs); return *this;} \ | atomic<T>& operator=( const atomic<T>& rhs ) {store_with_releas e(rhs); return *this;} \ | |||
skipping to change at line 457 | skipping to change at line 460 | |||
#if _MSC_VER && !_WIN64 | #if _MSC_VER && !_WIN64 | |||
#if __TBB_ATOMIC_CTORS | #if __TBB_ATOMIC_CTORS | |||
/* Special version of __TBB_DECL_ATOMIC that avoids gratuitous warnings fro m cl /Wp64 option. | /* Special version of __TBB_DECL_ATOMIC that avoids gratuitous warnings fro m cl /Wp64 option. | |||
It is identical to __TBB_DECL_ATOMIC(unsigned) except that it replaces o perator=(T) | It is identical to __TBB_DECL_ATOMIC(unsigned) except that it replaces o perator=(T) | |||
with an operator=(U) that explicitly converts the U to a T. Types T and U should be | with an operator=(U) that explicitly converts the U to a T. Types T and U should be | |||
type synonyms on the platform. Type U should be the wider variant of T from the | type synonyms on the platform. Type U should be the wider variant of T from the | |||
perspective of /Wp64. */ | perspective of /Wp64. */ | |||
#define __TBB_DECL_ATOMIC_ALT(T,U) \ | #define __TBB_DECL_ATOMIC_ALT(T,U) \ | |||
template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T, char> { \ | template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T, char> { \ | |||
atomic() = default ; \ | atomic() = default ; \ | |||
constexpr atomic(T arg): internal::atomic_impl_with_arithmetic<T,T, char>(arg) {} \ | constexpr atomic(T arg): internal::atomic_impl_with_arithmetic<T,T, char>(arg) {} \ | |||
T operator=( U rhs ) {return store_with_release(T(rhs));} \ | T operator=( U rhs ) {return store_with_release(T(rhs));} \ | |||
atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rh s); return *this;} \ | atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rh s); return *this;} \ | |||
}; | }; | |||
#else | #else | |||
#define __TBB_DECL_ATOMIC_ALT(T,U) \ | #define __TBB_DECL_ATOMIC_ALT(T,U) \ | |||
template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T, char> { \ | template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T, char> { \ | |||
T operator=( U rhs ) {return store_with_release(T(rhs));} \ | T operator=( U rhs ) {return store_with_release(T(rhs));} \ | |||
atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rh s); return *this;} \ | atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rh s); return *this;} \ | |||
}; | }; | |||
End of changes. 15 change blocks. | ||||
42 lines changed or deleted | 40 lines changed or added | |||
concurrent_hash_map.h | concurrent_hash_map.h | |||
---|---|---|---|---|
skipping to change at line 79 | skipping to change at line 79 | |||
static bool equal( const Key& a, const Key& b ) { return a == b; } | static bool equal( const Key& a, const Key& b ) { return a == b; } | |||
}; | }; | |||
namespace interface5 { | namespace interface5 { | |||
template<typename Key, typename T, typename HashCompare = tbb_hash_comp are<Key>, typename A = tbb_allocator<std::pair<Key, T> > > | template<typename Key, typename T, typename HashCompare = tbb_hash_comp are<Key>, typename A = tbb_allocator<std::pair<Key, T> > > | |||
class concurrent_hash_map; | class concurrent_hash_map; | |||
//! @cond INTERNAL | //! @cond INTERNAL | |||
namespace internal { | namespace internal { | |||
using namespace tbb::internal; | ||||
//! Type of a hash code. | //! Type of a hash code. | |||
typedef size_t hashcode_t; | typedef size_t hashcode_t; | |||
//! Node base type | //! Node base type | |||
struct hash_map_node_base : tbb::internal::no_copy { | struct hash_map_node_base : tbb::internal::no_copy { | |||
//! Mutex type | //! Mutex type | |||
typedef spin_rw_mutex mutex_t; | typedef spin_rw_mutex mutex_t; | |||
//! Scoped lock type for mutex | //! Scoped lock type for mutex | |||
typedef mutex_t::scoped_lock scoped_t; | typedef mutex_t::scoped_lock scoped_t; | |||
//! Next node in chain | //! Next node in chain | |||
skipping to change at line 287 | skipping to change at line 288 | |||
} | } | |||
//! Insert a node and check for load factor. @return segment index to enable. | //! Insert a node and check for load factor. @return segment index to enable. | |||
segment_index_t insert_new_node( bucket *b, node_base *n, hashcode_ t mask ) { | segment_index_t insert_new_node( bucket *b, node_base *n, hashcode_ t mask ) { | |||
size_type sz = ++my_size; // prefix form is to enforce allocati on after the first item inserted | size_type sz = ++my_size; // prefix form is to enforce allocati on after the first item inserted | |||
add_to_bucket( b, n ); | add_to_bucket( b, n ); | |||
// check load factor | // check load factor | |||
if( sz >= mask ) { // TODO: add custom load_factor | if( sz >= mask ) { // TODO: add custom load_factor | |||
segment_index_t new_seg = __TBB_Log2( mask+1 ); //optimized segment_index_of | segment_index_t new_seg = __TBB_Log2( mask+1 ); //optimized segment_index_of | |||
__TBB_ASSERT( is_valid(my_table[new_seg-1]), "new allocatio ns must not publish new mask until segment has allocated"); | __TBB_ASSERT( is_valid(my_table[new_seg-1]), "new allocatio ns must not publish new mask until segment has allocated"); | |||
static const segment_ptr_t is_allocating = (segment_ptr_t)2 ; | ||||
if( !itt_hide_load_word(my_table[new_seg]) | if( !itt_hide_load_word(my_table[new_seg]) | |||
&& __TBB_CompareAndSwapW(&my_table[new_seg], 2, 0) == 0 ) | && as_atomic(my_table[new_seg]).compare_and_swap(is_alloc ating, NULL) == NULL ) | |||
return new_seg; // The value must be processed | return new_seg; // The value must be processed | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
//! Prepare enough segments for number of buckets | //! Prepare enough segments for number of buckets | |||
void reserve(size_type buckets) { | void reserve(size_type buckets) { | |||
if( !buckets-- ) return; | if( !buckets-- ) return; | |||
bool is_initial = !my_size; | bool is_initial = !my_size; | |||
for( size_type m = my_mask; buckets > m; m = my_mask ) | for( size_type m = my_mask; buckets > m; m = my_mask ) | |||
End of changes. 3 change blocks. | ||||
1 lines changed or deleted | 3 lines changed or added | |||
gcc_armv7.h | gcc_armv7.h | |||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
library without restriction. Specifically, if other files instantiate | library without restriction. Specifically, if other files instantiate | |||
templates or use macros or inline functions from this file, or you comp ile | templates or use macros or inline functions from this file, or you comp ile | |||
this file and link it with other files to produce an executable, this | this file and link it with other files to produce an executable, this | |||
file does not by itself cause the resulting executable to be covered by | file does not by itself cause the resulting executable to be covered by | |||
the GNU General Public License. This exception does not however | the GNU General Public License. This exception does not however | |||
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. | |||
*/ | */ | |||
/* | /* | |||
This is the TBB implementation for the ARMv7-a architecture. | Platform isolation layer for the ARMv7-a architecture. | |||
*/ | */ | |||
#ifndef __TBB_machine_H | #ifndef __TBB_machine_H | |||
#error Do not include this file directly; include tbb_machine.h instead | #error Do not include this file directly; include tbb_machine.h instead | |||
#endif | #endif | |||
//TODO: is ARMv7 is the only version ever to support? | //TODO: is ARMv7 is the only version ever to support? | |||
#if !(__ARM_ARCH_7A__) | #if !(__ARM_ARCH_7A__) | |||
#error compilation requires an ARMv7-a architecture. | #error compilation requires an ARMv7-a architecture. | |||
#endif | #endif | |||
#include <sys/param.h> | #include <sys/param.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#define __TBB_WORDSIZE 4 | #define __TBB_WORDSIZE 4 | |||
#ifndef __BYTE_ORDER__ | // Traditionally ARM is little-endian. | |||
// Hopefully endianness can be validly determined at runtime. | // Note that, since only the layout of aligned 32-bit words is of interest, | |||
// This may silently fail in some embedded systems with page-specific e | // any apparent PDP-endianness of 32-bit words at half-word alignment or | |||
ndianness. | // any little-endian ordering of big-endian 32-bit words in 64-bit quantiti | |||
#elif __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ | es | |||
#define __TBB_BIG_ENDIAN 1 | // may be disregarded for this setting. | |||
#elif __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ | #if __BIG_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_B | |||
#define __TBB_BIG_ENDIAN 0 | IG_ENDIAN__) | |||
#define __TBB_ENDIANNESS __TBB_ENDIAN_BIG | ||||
#elif __LITTLE_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__==__OR | ||||
DER_LITTLE_ENDIAN__) | ||||
#define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | ||||
#elif defined(__BYTE_ORDER__) | ||||
#define __TBB_ENDIANNESS __TBB_ENDIAN_UNSUPPORTED | ||||
#else | #else | |||
#define __TBB_BIG_ENDIAN -1 // not currently supported | #define __TBB_ENDIANNESS __TBB_ENDIAN_DETECT | |||
#endif | #endif | |||
#define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | |||
#define __TBB_control_consistency_helper() __TBB_compiler_fence() | #define __TBB_control_consistency_helper() __TBB_compiler_fence() | |||
#define __TBB_armv7_inner_shareable_barrier() __asm__ __volatile__("dmb ish ": : :"memory") | #define __TBB_armv7_inner_shareable_barrier() __asm__ __volatile__("dmb ish ": : :"memory") | |||
#define __TBB_acquire_consistency_helper() __TBB_armv7_inner_shareable_barr ier() | #define __TBB_acquire_consistency_helper() __TBB_armv7_inner_shareable_barr ier() | |||
#define __TBB_release_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() | #define __TBB_full_memory_fence() __TBB_armv7_inner_shareable_barrier() | |||
End of changes. 3 change blocks. | ||||
10 lines changed or deleted | 16 lines changed or added | |||
gcc_generic.h | gcc_generic.h | |||
---|---|---|---|---|
skipping to change at line 49 | skipping to change at line 49 | |||
#if __TBB_GCC_64BIT_ATOMIC_BUILTINS_BROKEN | #if __TBB_GCC_64BIT_ATOMIC_BUILTINS_BROKEN | |||
#define __TBB_64BIT_ATOMICS 0 | #define __TBB_64BIT_ATOMICS 0 | |||
#endif | #endif | |||
/** FPU control setting not available for non-Intel architectures on Androi d **/ | /** FPU control setting not available for non-Intel architectures on Androi d **/ | |||
#if __ANDROID__ && __TBB_generic_arch | #if __ANDROID__ && __TBB_generic_arch | |||
#define __TBB_CPU_CTL_ENV_PRESENT 0 | #define __TBB_CPU_CTL_ENV_PRESENT 0 | |||
#endif | #endif | |||
#ifdef __BYTE_ORDER__ | // __BYTE_ORDER__ is used in accordance with http://gcc.gnu.org/onlinedocs/ | |||
#if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ | cpp/Common-Predefined-Macros.html, | |||
#define __TBB_BIG_ENDIAN 1 | // but __BIG_ENDIAN__ or __LITTLE_ENDIAN__ may be more commonly found inste | |||
#elif __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ | ad. | |||
#define __TBB_BIG_ENDIAN 0 | #if __BIG_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_B | |||
#elif __BYTE_ORDER__==__ORDER_PDP_ENDIAN__ | IG_ENDIAN__) | |||
#define __TBB_BIG_ENDIAN -1 // not currently supported | #define __TBB_ENDIANNESS __TBB_ENDIAN_BIG | |||
#endif | #elif __LITTLE_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__==__OR | |||
DER_LITTLE_ENDIAN__) | ||||
#define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | ||||
#elif defined(__BYTE_ORDER__) | ||||
#define __TBB_ENDIANNESS __TBB_ENDIAN_UNSUPPORTED | ||||
#else | ||||
#define __TBB_ENDIANNESS __TBB_ENDIAN_DETECT | ||||
#endif | #endif | |||
/** As this generic implementation has absolutely no information about unde rlying | /** As this generic implementation has absolutely no information about unde rlying | |||
hardware, its performance most likely will be sub-optimal because of fu ll memory | hardware, its performance most likely will be sub-optimal because of fu ll memory | |||
fence usages where a more lightweight synchronization means (or none at all) | fence usages where a more lightweight synchronization means (or none at all) | |||
could suffice. Thus if you use this header to enable TBB on a new platf orm, | could suffice. Thus if you use this header to enable TBB on a new platf orm, | |||
consider forking it and relaxing below helpers as appropriate. **/ | consider forking it and relaxing below helpers as appropriate. **/ | |||
#define __TBB_acquire_consistency_helper() __sync_synchronize() | #define __TBB_acquire_consistency_helper() __sync_synchronize() | |||
#define __TBB_release_consistency_helper() __sync_synchronize() | #define __TBB_release_consistency_helper() __sync_synchronize() | |||
#define __TBB_full_memory_fence() __sync_synchronize() | #define __TBB_full_memory_fence() __sync_synchronize() | |||
skipping to change at line 111 | skipping to change at line 113 | |||
} | } | |||
typedef unsigned char __TBB_Flag; | typedef unsigned char __TBB_Flag; | |||
typedef __TBB_atomic __TBB_Flag __TBB_atomic_flag; | typedef __TBB_atomic __TBB_Flag __TBB_atomic_flag; | |||
inline bool __TBB_machine_try_lock_byte( __TBB_atomic_flag &flag ) { | inline bool __TBB_machine_try_lock_byte( __TBB_atomic_flag &flag ) { | |||
return __sync_lock_test_and_set(&flag,1)==0; | return __sync_lock_test_and_set(&flag,1)==0; | |||
} | } | |||
inline void __TBB_machine_unlock_byte( __TBB_atomic_flag &flag , __TBB_Flag ) { | inline void __TBB_machine_unlock_byte( __TBB_atomic_flag &flag ) { | |||
__sync_lock_release(&flag); | __sync_lock_release(&flag); | |||
} | } | |||
// Machine specific atomic operations | // Machine specific atomic operations | |||
#define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) | #define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) | |||
#define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V) | #define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V) | |||
#define __TBB_TryLockByte __TBB_machine_try_lock_byte | #define __TBB_TryLockByte __TBB_machine_try_lock_byte | |||
#define __TBB_UnlockByte __TBB_machine_unlock_byte | #define __TBB_UnlockByte __TBB_machine_unlock_byte | |||
End of changes. 2 change blocks. | ||||
9 lines changed or deleted | 15 lines changed or added | |||
ibm_aix51.h | ibm_aix51.h | |||
---|---|---|---|---|
skipping to change at line 38 | skipping to change at line 38 | |||
// TODO: revise by comparing with mac_ppc.h | // TODO: revise by comparing with mac_ppc.h | |||
#if !defined(__TBB_machine_H) || defined(__TBB_machine_ibm_aix51_H) | #if !defined(__TBB_machine_H) || defined(__TBB_machine_ibm_aix51_H) | |||
#error Do not #include this internal file directly; use public TBB headers instead. | #error Do not #include this internal file directly; use public TBB headers instead. | |||
#endif | #endif | |||
#define __TBB_machine_ibm_aix51_H | #define __TBB_machine_ibm_aix51_H | |||
#define __TBB_WORDSIZE 8 | #define __TBB_WORDSIZE 8 | |||
#define __TBB_BIG_ENDIAN 1 // assumption based on operating system | #define __TBB_ENDIANNESS __TBB_ENDIAN_BIG // assumption based on operating system | |||
#include <stdint.h> | #include <stdint.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#include <sched.h> | #include <sched.h> | |||
extern "C" { | extern "C" { | |||
int32_t __TBB_machine_cas_32 (volatile void* ptr, int32_t value, int32_t co mparand); | int32_t __TBB_machine_cas_32 (volatile void* ptr, int32_t value, int32_t co mparand); | |||
int64_t __TBB_machine_cas_64 (volatile void* ptr, int64_t value, int64_t co mparand); | int64_t __TBB_machine_cas_64 (volatile void* ptr, int64_t value, int64_t co mparand); | |||
void __TBB_machine_flush (); | void __TBB_machine_flush (); | |||
void __TBB_machine_lwsync (); | void __TBB_machine_lwsync (); | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
icc_generic.h | icc_generic.h | |||
---|---|---|---|---|
skipping to change at line 54 | skipping to change at line 54 | |||
#endif | #endif | |||
//TODO: Make __TBB_WORDSIZE macro optional for ICC intrinsics port. | //TODO: Make __TBB_WORDSIZE macro optional for ICC intrinsics port. | |||
//As compiler intrinsics are used for all the operations it is possible to do. | //As compiler intrinsics are used for all the operations it is possible to do. | |||
#if __TBB_x86_32 | #if __TBB_x86_32 | |||
#define __TBB_WORDSIZE 4 | #define __TBB_WORDSIZE 4 | |||
#else | #else | |||
#define __TBB_WORDSIZE 8 | #define __TBB_WORDSIZE 8 | |||
#endif | #endif | |||
#define __TBB_BIG_ENDIAN 0 | #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | |||
//__TBB_compiler_fence() defined just in case, as it seems not to be used o n its own anywhere else | //__TBB_compiler_fence() defined just in case, as it seems not to be used o n its own anywhere else | |||
#if _MSC_VER | #if _MSC_VER | |||
//TODO: any way to use same intrinsics on windows and linux? | //TODO: any way to use same intrinsics on windows and linux? | |||
#pragma intrinsic(_ReadWriteBarrier) | #pragma intrinsic(_ReadWriteBarrier) | |||
#pragma intrinsic(_mm_mfence) | #pragma intrinsic(_mm_mfence) | |||
#define __TBB_compiler_fence() _ReadWriteBarrier() | #define __TBB_compiler_fence() _ReadWriteBarrier() | |||
#define __TBB_full_memory_fence() _mm_mfence() | #define __TBB_full_memory_fence() _mm_mfence() | |||
#else | #else | |||
#define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
linux_ia32.h | linux_ia32.h | |||
---|---|---|---|---|
skipping to change at line 39 | skipping to change at line 39 | |||
#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia32_H) | #if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia32_H) | |||
#error Do not #include this internal file directly; use public TBB headers instead. | #error Do not #include this internal file directly; use public TBB headers instead. | |||
#endif | #endif | |||
#define __TBB_machine_linux_ia32_H | #define __TBB_machine_linux_ia32_H | |||
#include <stdint.h> | #include <stdint.h> | |||
#include "gcc_ia32_common.h" | #include "gcc_ia32_common.h" | |||
#define __TBB_WORDSIZE 4 | #define __TBB_WORDSIZE 4 | |||
#define __TBB_BIG_ENDIAN 0 | #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | |||
#define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | |||
#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_acquire_consistency_helper() __TBB_compiler_fence() | |||
#define __TBB_release_consistency_helper() __TBB_compiler_fence() | #define __TBB_release_consistency_helper() __TBB_compiler_fence() | |||
#define __TBB_full_memory_fence() __asm__ __volatile__("mfence": : :"memory") | #define __TBB_full_memory_fence() __asm__ __volatile__("mfence": : :"memory") | |||
#if __TBB_ICC_ASM_VOLATILE_BROKEN | #if __TBB_ICC_ASM_VOLATILE_BROKEN | |||
#define __TBB_VOLATILE | #define __TBB_VOLATILE | |||
#else | #else | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
linux_ia64.h | linux_ia64.h | |||
---|---|---|---|---|
skipping to change at line 39 | skipping to change at line 39 | |||
#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia64_H) | #if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia64_H) | |||
#error Do not #include this internal file directly; use public TBB headers instead. | #error Do not #include this internal file directly; use public TBB headers instead. | |||
#endif | #endif | |||
#define __TBB_machine_linux_ia64_H | #define __TBB_machine_linux_ia64_H | |||
#include <stdint.h> | #include <stdint.h> | |||
#include <ia64intrin.h> | #include <ia64intrin.h> | |||
#define __TBB_WORDSIZE 8 | #define __TBB_WORDSIZE 8 | |||
#define __TBB_BIG_ENDIAN 0 | #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | |||
#if __INTEL_COMPILER | #if __INTEL_COMPILER | |||
#define __TBB_compiler_fence() | #define __TBB_compiler_fence() | |||
#define __TBB_control_consistency_helper() __TBB_compiler_fence() | #define __TBB_control_consistency_helper() __TBB_compiler_fence() | |||
#define __TBB_acquire_consistency_helper() | #define __TBB_acquire_consistency_helper() | |||
#define __TBB_release_consistency_helper() | #define __TBB_release_consistency_helper() | |||
#define __TBB_full_memory_fence() __mf() | #define __TBB_full_memory_fence() __mf() | |||
#else | #else | |||
#define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | |||
#define __TBB_control_consistency_helper() __TBB_compiler_fence() | #define __TBB_control_consistency_helper() __TBB_compiler_fence() | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
linux_intel64.h | linux_intel64.h | |||
---|---|---|---|---|
skipping to change at line 39 | skipping to change at line 39 | |||
#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_intel64_H) | #if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_intel64_H) | |||
#error Do not #include this internal file directly; use public TBB headers instead. | #error Do not #include this internal file directly; use public TBB headers instead. | |||
#endif | #endif | |||
#define __TBB_machine_linux_intel64_H | #define __TBB_machine_linux_intel64_H | |||
#include <stdint.h> | #include <stdint.h> | |||
#include "gcc_ia32_common.h" | #include "gcc_ia32_common.h" | |||
#define __TBB_WORDSIZE 8 | #define __TBB_WORDSIZE 8 | |||
#define __TBB_BIG_ENDIAN 0 | #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | |||
#define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") | |||
#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_acquire_consistency_helper() __TBB_compiler_fence() | |||
#define __TBB_release_consistency_helper() __TBB_compiler_fence() | #define __TBB_release_consistency_helper() __TBB_compiler_fence() | |||
#ifndef __TBB_full_memory_fence | #ifndef __TBB_full_memory_fence | |||
#define __TBB_full_memory_fence() __asm__ __volatile__("mfence": : :"memory ") | #define __TBB_full_memory_fence() __asm__ __volatile__("mfence": : :"memory ") | |||
#endif | #endif | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
mac_ppc.h | mac_ppc.h | |||
---|---|---|---|---|
skipping to change at line 50 | skipping to change at line 50 | |||
// Note that XL V9.0 (sometimes?) has trouble dealing with empty input and/ or clobber lists, so they should be avoided. | // Note that XL V9.0 (sometimes?) has trouble dealing with empty input and/ or clobber lists, so they should be avoided. | |||
#if __powerpc64__ || __ppc64__ | #if __powerpc64__ || __ppc64__ | |||
// IBM XL documents __powerpc64__ (and __PPC64__). | // IBM XL documents __powerpc64__ (and __PPC64__). | |||
// Apple documents __ppc64__ (with __ppc__ only on 32-bit). | // Apple documents __ppc64__ (with __ppc__ only on 32-bit). | |||
#define __TBB_WORDSIZE 8 | #define __TBB_WORDSIZE 8 | |||
#else | #else | |||
#define __TBB_WORDSIZE 4 | #define __TBB_WORDSIZE 4 | |||
#endif | #endif | |||
#ifndef __BYTE_ORDER__ | // Traditionally Power Architecture is big-endian. | |||
// Hopefully endianness can be validly determined at runtime. | // Little-endian could be just an address manipulation (compatibility with | |||
// This may silently fail in some embedded systems with page-specific e | TBB not verified), | |||
ndianness. | // or normal little-endian (on more recent systems). Embedded PowerPC syste | |||
#elif __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ | ms may support | |||
#define __TBB_BIG_ENDIAN 1 | // page-specific endianness, but then one endianness must be hidden from TB | |||
#elif __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ | B so that it still sees only one. | |||
#define __TBB_BIG_ENDIAN 0 | #if __BIG_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_B | |||
IG_ENDIAN__) | ||||
#define __TBB_ENDIANNESS __TBB_ENDIAN_BIG | ||||
#elif __LITTLE_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__==__OR | ||||
DER_LITTLE_ENDIAN__) | ||||
#define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | ||||
#elif defined(__BYTE_ORDER__) | ||||
#define __TBB_ENDIANNESS __TBB_ENDIAN_UNSUPPORTED | ||||
#else | #else | |||
#define __TBB_BIG_ENDIAN -1 // not currently supported | #define __TBB_ENDIANNESS __TBB_ENDIAN_DETECT | |||
#endif | #endif | |||
// On Power Architecture, (lock-free) 64-bit atomics require 64-bit hardwar e: | // On Power Architecture, (lock-free) 64-bit atomics require 64-bit hardwar e: | |||
#if __TBB_WORDSIZE==8 | #if __TBB_WORDSIZE==8 | |||
// Do not change the following definition, because TBB itself will use 64-bit atomics in 64-bit builds. | // Do not change the following definition, because TBB itself will use 64-bit atomics in 64-bit builds. | |||
#define __TBB_64BIT_ATOMICS 1 | #define __TBB_64BIT_ATOMICS 1 | |||
#elif __bgp__ | #elif __bgp__ | |||
// Do not change the following definition, because this is known 32-bit hardware. | // Do not change the following definition, because this is known 32-bit hardware. | |||
#define __TBB_64BIT_ATOMICS 0 | #define __TBB_64BIT_ATOMICS 0 | |||
#else | #else | |||
End of changes. 2 change blocks. | ||||
9 lines changed or deleted | 16 lines changed or added | |||
macos_common.h | macos_common.h | |||
---|---|---|---|---|
skipping to change at line 88 | skipping to change at line 88 | |||
#define __TBB_machine_cmpswp8 __TBB_machine_cmpswp8_OsX | #define __TBB_machine_cmpswp8 __TBB_machine_cmpswp8_OsX | |||
#endif /* __TBB_UnknownArchitecture */ | #endif /* __TBB_UnknownArchitecture */ | |||
#if __TBB_UnknownArchitecture | #if __TBB_UnknownArchitecture | |||
#ifndef __TBB_WORDSIZE | #ifndef __TBB_WORDSIZE | |||
#define __TBB_WORDSIZE 4 | #define __TBB_WORDSIZE 4 | |||
#endif | #endif | |||
#ifdef __TBB_BIG_ENDIAN | #ifdef __TBB_ENDIANNESS | |||
// Already determined based on hardware architecture. | // Already determined based on hardware architecture. | |||
#elif __BIG_ENDIAN__ | #elif __BIG_ENDIAN__ | |||
#define __TBB_BIG_ENDIAN 1 | #define __TBB_ENDIANNESS __TBB_ENDIAN_BIG | |||
#elif __LITTLE_ENDIAN__ | #elif __LITTLE_ENDIAN__ | |||
#define __TBB_BIG_ENDIAN 0 | #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | |||
#else | #else | |||
#define __TBB_BIG_ENDIAN -1 // not currently supported | #define __TBB_ENDIANNESS __TBB_ENDIAN_UNSUPPORTED | |||
#endif | #endif | |||
/** As this generic implementation has absolutely no information about unde rlying | /** As this generic implementation has absolutely no information about unde rlying | |||
hardware, its performance most likely will be sub-optimal because of fu ll memory | hardware, its performance most likely will be sub-optimal because of fu ll memory | |||
fence usages where a more lightweight synchronization means (or none at all) | fence usages where a more lightweight synchronization means (or none at all) | |||
could suffice. Thus if you use this header to enable TBB on a new platf orm, | could suffice. Thus if you use this header to enable TBB on a new platf orm, | |||
consider forking it and relaxing below helpers as appropriate. **/ | consider forking it and relaxing below helpers as appropriate. **/ | |||
#define __TBB_control_consistency_helper() OSMemoryBarrier() | #define __TBB_control_consistency_helper() OSMemoryBarrier() | |||
#define __TBB_acquire_consistency_helper() OSMemoryBarrier() | #define __TBB_acquire_consistency_helper() OSMemoryBarrier() | |||
#define __TBB_release_consistency_helper() OSMemoryBarrier() | #define __TBB_release_consistency_helper() OSMemoryBarrier() | |||
End of changes. 4 change blocks. | ||||
4 lines changed or deleted | 4 lines changed or added | |||
memory_pool.h | memory_pool.h | |||
---|---|---|---|---|
skipping to change at line 40 | skipping to change at line 40 | |||
#define __TBB_memory_pool_H | #define __TBB_memory_pool_H | |||
#if !TBB_PREVIEW_MEMORY_POOL | #if !TBB_PREVIEW_MEMORY_POOL | |||
#error Set TBB_PREVIEW_MEMORY_POOL to include memory_pool.h | #error Set TBB_PREVIEW_MEMORY_POOL to include memory_pool.h | |||
#endif | #endif | |||
/** @file */ | /** @file */ | |||
#include "scalable_allocator.h" | #include "scalable_allocator.h" | |||
#include "tbb_stddef.h" | #include "tbb_stddef.h" | |||
#include "tbb_machine.h" // TODO: avoid linkage with libtbb on IA-64 | #include "tbb_machine.h" // TODO: avoid linkage with libtbb on IA-64 | |||
#include "tbb/atomic.h" // for as_atomic | ||||
#include <new> // std::bad_alloc | #include <new> // std::bad_alloc | |||
#if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN | #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN | |||
#include <utility> // std::forward | #include <utility> // std::forward | |||
#endif | #endif | |||
#if __TBB_EXTRA_DEBUG | #if __TBB_EXTRA_DEBUG | |||
#define __TBBMALLOC_ASSERT ASSERT | #define __TBBMALLOC_ASSERT ASSERT | |||
#else | #else | |||
#define __TBBMALLOC_ASSERT(a,b) ((void)0) | #define __TBBMALLOC_ASSERT(a,b) ((void)0) | |||
#endif | #endif | |||
skipping to change at line 265 | skipping to change at line 266 | |||
#if _MSC_VER==1700 && !defined(__INTEL_COMPILER) | #if _MSC_VER==1700 && !defined(__INTEL_COMPILER) | |||
#pragma warning (pop) | #pragma warning (pop) | |||
#endif | #endif | |||
inline fixed_pool::fixed_pool(void *buf, size_t size) : my_buffer(buf), my_ size(size) { | inline fixed_pool::fixed_pool(void *buf, size_t size) : my_buffer(buf), my_ size(size) { | |||
rml::MemPoolPolicy args(allocate_request, 0, size, /*fixedPool=*/true); | rml::MemPoolPolicy args(allocate_request, 0, size, /*fixedPool=*/true); | |||
rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_ pool); | rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_ pool); | |||
if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc()); | if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc()); | |||
} | } | |||
inline void *fixed_pool::allocate_request(intptr_t pool_id, size_t & bytes) { | inline void *fixed_pool::allocate_request(intptr_t pool_id, size_t & bytes) { | |||
fixed_pool &self = *reinterpret_cast<fixed_pool*>(pool_id); | fixed_pool &self = *reinterpret_cast<fixed_pool*>(pool_id); | |||
if( !__TBB_CompareAndSwapW(&self.my_size, 0, (bytes=self.my_size)) ) | if( !tbb::internal::as_atomic(self.my_size).compare_and_swap(0, (bytes= self.my_size)) ) | |||
return 0; // all the memory was given already | return 0; // all the memory was given already | |||
return self.my_buffer; | return self.my_buffer; | |||
} | } | |||
} //namespace interface6 | } //namespace interface6 | |||
using interface6::memory_pool_allocator; | using interface6::memory_pool_allocator; | |||
using interface6::memory_pool; | using interface6::memory_pool; | |||
using interface6::fixed_pool; | using interface6::fixed_pool; | |||
} //namespace tbb | } //namespace tbb | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 2 lines changed or added | |||
msvc_armv7.h | msvc_armv7.h | |||
---|---|---|---|---|
skipping to change at line 40 | skipping to change at line 40 | |||
#error Do not #include this internal file directly; use public TBB headers instead. | #error Do not #include this internal file directly; use public TBB headers instead. | |||
#endif | #endif | |||
#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_BIG_ENDIAN -1 // not currently supported | #define __TBB_ENDIANNESS __TBB_ENDIAN_UNSUPPORTED | |||
#define __TBB_compiler_fence() __dmb(_ARM_BARRIER_SY) | #define __TBB_compiler_fence() __dmb(_ARM_BARRIER_SY) | |||
#define __TBB_control_consistency_helper() __TBB_compiler_fence() | #define __TBB_control_consistency_helper() __TBB_compiler_fence() | |||
#define __TBB_armv7_inner_shareable_barrier() __dmb(_ARM_BARRIER_ISH) | #define __TBB_armv7_inner_shareable_barrier() __dmb(_ARM_BARRIER_ISH) | |||
#define __TBB_acquire_consistency_helper() __TBB_armv7_inner_shareable_barr ier() | #define __TBB_acquire_consistency_helper() __TBB_armv7_inner_shareable_barr ier() | |||
#define __TBB_release_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() | #define __TBB_full_memory_fence() __TBB_armv7_inner_shareable_barrier() | |||
//-------------------------------------------------- | //-------------------------------------------------- | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
spin_mutex.h | spin_mutex.h | |||
---|---|---|---|---|
skipping to change at line 126 | skipping to change at line 126 | |||
my_mutex = &m; | my_mutex = &m; | |||
return result; | return result; | |||
#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/ | #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/ | |||
} | } | |||
//! Release lock | //! Release lock | |||
void release() { | void release() { | |||
#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT | #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT | |||
internal_release(); | internal_release(); | |||
#else | #else | |||
__TBB_UnlockByte(my_mutex->flag, 0); | __TBB_UnlockByte(my_mutex->flag); | |||
my_mutex = NULL; | my_mutex = NULL; | |||
#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ | #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ | |||
} | } | |||
//! Destroy lock. If holding a lock, releases the lock first. | //! Destroy lock. If holding a lock, releases the lock first. | |||
~scoped_lock() { | ~scoped_lock() { | |||
if( my_mutex ) { | if( my_mutex ) { | |||
#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT | #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT | |||
internal_release(); | internal_release(); | |||
#else | #else | |||
__TBB_UnlockByte(my_mutex->flag, 0); | __TBB_UnlockByte(my_mutex->flag); | |||
#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ | #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ | |||
} | } | |||
} | } | |||
}; | }; | |||
void __TBB_EXPORTED_METHOD internal_construct(); | void __TBB_EXPORTED_METHOD internal_construct(); | |||
// Mutex traits | // Mutex traits | |||
static const bool is_rw_mutex = false; | static const bool is_rw_mutex = false; | |||
static const bool is_recursive_mutex = false; | static const bool is_recursive_mutex = false; | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
sunos_sparc.h | sunos_sparc.h | |||
---|---|---|---|---|
skipping to change at line 39 | skipping to change at line 39 | |||
#if !defined(__TBB_machine_H) || defined(__TBB_machine_sunos_sparc_H) | #if !defined(__TBB_machine_H) || defined(__TBB_machine_sunos_sparc_H) | |||
#error Do not #include this internal file directly; use public TBB headers instead. | #error Do not #include this internal file directly; use public TBB headers instead. | |||
#endif | #endif | |||
#define __TBB_machine_sunos_sparc_H | #define __TBB_machine_sunos_sparc_H | |||
#include <stdint.h> | #include <stdint.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#define __TBB_WORDSIZE 8 | #define __TBB_WORDSIZE 8 | |||
#define __TBB_BIG_ENDIAN 1 // assumption (hardware may support page-specifi | // Big endian is assumed for SPARC. | |||
c bi-endianness) | // While hardware may support page-specific bi-endianness, only big endian | |||
pages may be exposed to TBB | ||||
#define __TBB_ENDIANNESS __TBB_ENDIAN_BIG | ||||
/** To those working on SPARC hardware. Consider relaxing acquire and relea se | /** To those working on SPARC hardware. Consider relaxing acquire and relea se | |||
consistency helpers to no-op (as this port covers TSO mode only). **/ | consistency helpers to no-op (as this port covers TSO mode only). **/ | |||
#define __TBB_compiler_fence() __asm__ __volatile__ ("": : :"me mory") | #define __TBB_compiler_fence() __asm__ __volatile__ ("": : :"me mory") | |||
#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_acquire_consistency_helper() __TBB_compiler_fence() | |||
#define __TBB_release_consistency_helper() __TBB_compiler_fence() | #define __TBB_release_consistency_helper() __TBB_compiler_fence() | |||
#define __TBB_full_memory_fence() __asm__ __volatile__("membar #Lo adLoad|#LoadStore|#StoreStore|#StoreLoad": : : "memory") | #define __TBB_full_memory_fence() __asm__ __volatile__("membar #Lo adLoad|#LoadStore|#StoreStore|#StoreLoad": : : "memory") | |||
//-------------------------------------------------- | //-------------------------------------------------- | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
tbb_config.h | tbb_config.h | |||
---|---|---|---|---|
skipping to change at line 75 | skipping to change at line 75 | |||
compilers they mimic (GCC, MSVC). | compilers they mimic (GCC, MSVC). | |||
TODO: The following conditions should be extended when new compilers/run times | TODO: The following conditions should be extended when new compilers/run times | |||
support added. | support added. | |||
*/ | */ | |||
#if __INTEL_COMPILER | #if __INTEL_COMPILER | |||
/** On Windows environment when using Intel C++ compiler with Visual St udio 2010*, | /** On Windows environment when using Intel C++ compiler with Visual St udio 2010*, | |||
the C++0x features supported by Visual C++ 2010 are enabled by defa ult | the C++0x features supported by Visual C++ 2010 are enabled by defa ult | |||
TODO: find a way to get know if c++0x mode is specified in command line on windows **/ | TODO: find a way to get know if c++0x mode is specified in command line on windows **/ | |||
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT ( __GXX_EXPERIMENTAL_ CXX0X__ && __VARIADIC_TEMPLATES ) | #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT ( __VARIADIC_TEMPLATE S && (__GXX_EXPERIMENTAL_CXX0X__ || _MSC_VER) ) | |||
#define __TBB_CPP11_RVALUE_REF_PRESENT ( (__GXX_EXPERIMENTAL _CXX0X__ || _MSC_VER >= 1600) && (__INTEL_COMPILER >= 1200) ) | #define __TBB_CPP11_RVALUE_REF_PRESENT ( (__GXX_EXPERIMENTAL _CXX0X__ || _MSC_VER >= 1600) && (__INTEL_COMPILER >= 1200) ) | |||
#if _MSC_VER >= 1600 | #if _MSC_VER >= 1600 | |||
#define __TBB_EXCEPTION_PTR_PRESENT ( __INTEL_COMPILER > 1300 \ | #define __TBB_EXCEPTION_PTR_PRESENT ( __INTEL_COMPILER > 1300 \ | |||
/*ICC 12.1 Upd 10 and 13 beta Upd 2 fixed exception_ptr linking issue*/ \ | /*ICC 12.1 Upd 10 and 13 beta Upd 2 fixed exception_ptr linking issue*/ \ | |||
|| (__INTEL_COMPILER == 1300 && __INTEL_COMPILER_BUILD_DATE >= 20120530) \ | || (__INTEL_COMPILER == 1300 && __INTEL_COMPILER_BUILD_DATE >= 20120530) \ | |||
|| (__INTEL_COMPILER == 1210 && __INTEL_COMPILER_BUILD_DATE >= 20120410) ) | || (__INTEL_COMPILER == 1210 && __INTEL_COMPILER_BUILD_DATE >= 20120410) ) | |||
/** libstc++ that comes with GCC 4.6 use C++11 features not supported b y ICC 12.1. | /** libstc++ that comes with GCC 4.6 use C++11 features not supported b y ICC 12.1. | |||
* Because of that ICC 12.1 does not support C++11 mode with with gcc 4 .6. (or higher) | * Because of that ICC 12.1 does not support C++11 mode with with gcc 4 .6. (or higher) | |||
* , and therefore does not define __GXX_EXPERIMENTAL_CXX0X__ macro**/ | * , and therefore does not define __GXX_EXPERIMENTAL_CXX0X__ macro**/ | |||
#elif (__TBB_GCC_VERSION >= 40404) && (__TBB_GCC_VERSION < 40600) | #elif (__TBB_GCC_VERSION >= 40404) && (__TBB_GCC_VERSION < 40600) | |||
#define __TBB_EXCEPTION_PTR_PRESENT ( __GXX_EXPERIMENTAL_CXX 0X__ && __INTEL_COMPILER >= 1200 ) | #define __TBB_EXCEPTION_PTR_PRESENT ( __GXX_EXPERIMENTAL_ CXX0X__ && __INTEL_COMPILER >= 1200 ) | |||
#elif (__TBB_GCC_VERSION >= 40600) | #elif (__TBB_GCC_VERSION >= 40600) | |||
#define __TBB_EXCEPTION_PTR_PRESENT ( __GXX_EXPERIMENTAL_CXX 0X__ && __INTEL_COMPILER >= 1300 ) | #define __TBB_EXCEPTION_PTR_PRESENT ( __GXX_EXPERIMENTAL_ CXX0X__ && __INTEL_COMPILER >= 1300 ) | |||
#else | #else | |||
#define __TBB_EXCEPTION_PTR_PRESENT 0 | #define __TBB_EXCEPTION_PTR_PRESENT 0 | |||
#endif | #endif | |||
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1700 || (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40600)) | #define __TBB_MAKE_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1700 || (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40600)) | |||
#define __TBB_STATIC_ASSERT_PRESENT ( __GXX_EXPERIMENTAL_ CXX0X__ || (_MSC_VER >= 1600) ) | #define __TBB_STATIC_ASSERT_PRESENT ( __GXX_EXPERIMENTAL_ CXX0X__ || (_MSC_VER >= 1600) ) | |||
#define __TBB_CPP11_TUPLE_PRESENT ( (_MSC_VER >= 1600) || ((__GXX_EXPERIMENTAL_CXX0X__) && (__TBB_GCC_VERSION >= 40300)) ) | #define __TBB_CPP11_TUPLE_PRESENT ( (_MSC_VER >= 1600) || ((__GXX_EXPERIMENTAL_CXX0X__) && (__TBB_GCC_VERSION >= 40300)) ) | |||
/** TODO: re-check for compiler version greater than 12.1 if it support s initializer lists**/ | /** TODO: re-check for compiler version greater than 12.1 if it support s initializer lists**/ | |||
#define __TBB_INITIALIZER_LISTS_PRESENT 0 | #define __TBB_INITIALIZER_LISTS_PRESENT 0 | |||
#define __TBB_CONSTEXPR_PRESENT 0 | #define __TBB_CONSTEXPR_PRESENT 0 | |||
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT 0 | #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT 0 | |||
End of changes. 3 change blocks. | ||||
3 lines changed or deleted | 3 lines changed or added | |||
tbb_machine.h | tbb_machine.h | |||
---|---|---|---|---|
skipping to change at line 61 | skipping to change at line 61 | |||
further. | further. | |||
Note that these generic implementations may be sub-optimal for a partic ular | Note that these generic implementations may be sub-optimal for a partic ular | |||
architecture, and thus should be relied upon only after careful evaluat ion | architecture, and thus should be relied upon only after careful evaluat ion | |||
or as the last resort. | or as the last resort. | |||
Additionally __TBB_64BIT_ATOMICS can be set to 0 on a 32-bit architectu re to | Additionally __TBB_64BIT_ATOMICS can be set to 0 on a 32-bit architectu re to | |||
indicate that the port is not going to support double word atomics. It may also | indicate that the port is not going to support double word atomics. It may also | |||
be set to 1 explicitly, though normally this is not necessary as tbb_ma chine.h | be set to 1 explicitly, though normally this is not necessary as tbb_ma chine.h | |||
will set it automatically. | will set it automatically. | |||
__TBB_BIG_ENDIAN macro can be defined by the implementation as well. | __TBB_ENDIANNESS macro can be defined by the implementation as well. | |||
It is used only if the __TBB_USE_GENERIC_PART_WORD_CAS is set. | It is used only if __TBB_USE_GENERIC_PART_WORD_CAS is set (or for testi | |||
Possible values are: | ng), | |||
- 1 if the system is big endian, | and must specify the layout of aligned 16-bit and 32-bit data anywhere | |||
- 0 if it is little endian, | within a process | |||
- or -1 to explicitly state that __TBB_USE_GENERIC_PART_WORD_CAS ca | (while the details of unaligned 16-bit or 32-bit data or of 64-bit data | |||
n not be used. | are irrelevant). | |||
-1 should be used when it is known in advance that endianness can chang | The layout must be the same at all relevant memory locations within the | |||
e in run time | current process; | |||
or it is not simple big or little but something more complex. | in case of page-specific endianness, one endianness must be kept "out o | |||
The system will try to detect it in run time if it is not set(in assump | f sight". | |||
tion that it | Possible settings, reflecting hardware and possibly O.S. convention, ar | |||
is either a big or little one). | e: | |||
- __TBB_ENDIAN_BIG for big-endian data, | ||||
- __TBB_ENDIAN_LITTLE for little-endian data, | ||||
- __TBB_ENDIAN_DETECT for run-time detection iff exactly one of the ab | ||||
ove, | ||||
- __TBB_ENDIAN_UNSUPPORTED to prevent undefined behavior if none of th | ||||
e above. | ||||
Prerequisites for each architecture port | Prerequisites for each architecture port | |||
---------------------------------------- | ---------------------------------------- | |||
The following functions and macros have no generic implementation. Ther efore they must be | The following functions and macros have no generic implementation. Ther efore they must be | |||
implemented in each machine architecture specific header either as a co nventional | implemented in each machine architecture specific header either as a co nventional | |||
function or as a functional macro. | function or as a functional macro. | |||
__TBB_WORDSIZE | __TBB_WORDSIZE | |||
This is the size of machine word in bytes, i.e. for 32 bit systems it | This is the size of machine word in bytes, i.e. for 32 bit systems it | |||
should be defined to 4. | should be defined to 4. | |||
skipping to change at line 192 | skipping to change at line 193 | |||
} \ | } \ | |||
#define __TBB_MACHINE_DEFINE_LOAD8_GENERIC_FENCED(M) \ | #define __TBB_MACHINE_DEFINE_LOAD8_GENERIC_FENCED(M) \ | |||
inline int64_t __TBB_machine_generic_load8##M(const volatile void *ptr) { \ | inline int64_t __TBB_machine_generic_load8##M(const volatile void *ptr) { \ | |||
/* Comparand and new value may be anything, they only must be equal , and */ \ | /* Comparand and new value may be anything, they only must be equal , and */ \ | |||
/* the value should have a low probability to be actually found in 'location'.*/ \ | /* the value should have a low probability to be actually found in 'location'.*/ \ | |||
const int64_t anyvalue = 2305843009213693951LL; \ | const int64_t anyvalue = 2305843009213693951LL; \ | |||
return __TBB_machine_cmpswp8##M(const_cast<volatile void *>(ptr),an yvalue,anyvalue); \ | return __TBB_machine_cmpswp8##M(const_cast<volatile void *>(ptr),an yvalue,anyvalue); \ | |||
} \ | } \ | |||
// The set of allowed values for __TBB_ENDIANNESS (see above for details) | ||||
#define __TBB_ENDIAN_UNSUPPORTED -1 | ||||
#define __TBB_ENDIAN_LITTLE 0 | ||||
#define __TBB_ENDIAN_BIG 1 | ||||
#define __TBB_ENDIAN_DETECT 2 | ||||
#if _WIN32||_WIN64 | #if _WIN32||_WIN64 | |||
#ifdef _MANAGED | #ifdef _MANAGED | |||
#pragma managed(push, off) | #pragma managed(push, off) | |||
#endif | #endif | |||
#if __MINGW64__ || __MINGW32__ | #if __MINGW64__ || __MINGW32__ | |||
extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void ); | extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void ); | |||
#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) | |||
skipping to change at line 403 | skipping to change at line 410 | |||
} | } | |||
//! Spin UNTIL the value of the variable is equal to a given value | //! Spin UNTIL the value of the variable is equal to a given value | |||
/** T and U should be comparable types. */ | /** T and U should be comparable types. */ | |||
template<typename T, typename U> | template<typename T, typename U> | |||
void spin_wait_until_eq( const volatile T& location, const U value ) { | void spin_wait_until_eq( const volatile T& location, const U value ) { | |||
atomic_backoff backoff; | atomic_backoff backoff; | |||
while( location!=value ) backoff.pause(); | while( location!=value ) backoff.pause(); | |||
} | } | |||
#if (__TBB_USE_GENERIC_PART_WORD_CAS && ( __TBB_BIG_ENDIAN==-1)) | /////////////////////////////////////////////////////////////////////////// | |||
#error generic implementation of part-word CAS was explicitly disabled | ///// | |||
for this configuration | // Generic compare-and-swap applied to only a part of a machine word. | |||
// | ||||
#ifndef __TBB_ENDIANNESS | ||||
#define __TBB_ENDIANNESS __TBB_ENDIAN_DETECT | ||||
#endif | ||||
#if __TBB_USE_GENERIC_PART_WORD_CAS && __TBB_ENDIANNESS==__TBB_ENDIAN_UNSUP | ||||
PORTED | ||||
#error Generic implementation of part-word CAS may not be used with __TBB_E | ||||
NDIAN_UNSUPPORTED | ||||
#endif | #endif | |||
#if (__TBB_BIG_ENDIAN!=-1) | #if __TBB_ENDIANNESS!=__TBB_ENDIAN_UNSUPPORTED | |||
// there are following restrictions/limitations for this operation: | // | |||
// - T should be unsigned, otherwise sign propagation will break correctne | // This function is the only use of __TBB_ENDIANNESS. | |||
ss of bit manipulations. | // The following restrictions/limitations apply for this operation: | |||
// - T should be integer type of at most 4 bytes, for the casts and calcul | // - T must be an integer type of at most 4 bytes for the casts and calcul | |||
ations to work. | ations to work | |||
// (Together, these rules limit applicability of Masked CAS to uint8_t | // - T must also be less than 4 bytes to avoid compiler warnings when comp | |||
and uint16_t only, | uting mask | |||
// as it does nothing useful for 4 bytes). | // (and for the operation to be useful at all, so no workaround is app | |||
// - The operation assumes that the architecture consistently uses either | lied) | |||
little-endian or big-endian: | // - the architecture must consistently use either little-endian or big-en | |||
// it does not support mixed-endian or page-specific bi-endian archite | dian (same for all locations) | |||
ctures. | ||||
// This function is the only use of __TBB_BIG_ENDIAN. | ||||
// | // | |||
//TODO: add static_assert for the requirements stated above | // TODO: static_assert for the type requirements stated above | |||
//TODO: check if it works with signed types | ||||
template<typename T> | template<typename T> | |||
inline T __TBB_MaskedCompareAndSwap (volatile T * const ptr, const T value, const T comparand ) { | inline T __TBB_MaskedCompareAndSwap (volatile T * const ptr, const T value, const T comparand ) { | |||
struct endianness{ static bool is_big_endian(){ | struct endianness{ static bool is_big_endian(){ | |||
#ifndef __TBB_BIG_ENDIAN | #if __TBB_ENDIANNESS==__TBB_ENDIAN_DETECT | |||
const uint32_t probe = 0x03020100; | const uint32_t probe = 0x03020100; | |||
return (((const char*)(&probe))[0]==0x03); | return (((const char*)(&probe))[0]==0x03); | |||
#elif (__TBB_BIG_ENDIAN==0) || (__TBB_BIG_ENDIAN==1) | #elif __TBB_ENDIANNESS==__TBB_ENDIAN_BIG || __TBB_ENDIANNESS==__TBB | |||
return __TBB_BIG_ENDIAN; | _ENDIAN_LITTLE | |||
return __TBB_ENDIANNESS==__TBB_ENDIAN_BIG; | ||||
#else | #else | |||
#error unexpected value of __TBB_BIG_ENDIAN | #error Unexpected value of __TBB_ENDIANNESS | |||
#endif | #endif | |||
}}; | }}; | |||
const uint32_t byte_offset = (uint32_t) ((uintptr_t)ptr & 0x 3); | const uint32_t byte_offset = (uint32_t) ((uintptr_t)ptr & 0x 3); | |||
volatile uint32_t * const aligned_ptr = (uint32_t*)((uintptr_t)ptr - by te_offset ); | volatile uint32_t * const aligned_ptr = (uint32_t*)((uintptr_t)ptr - by te_offset ); | |||
// location of T within uint32_t for a C++ shift operation | // location of T within uint32_t for a C++ shift operation | |||
const uint32_t bits_to_shift = 8*(endianness::is_big_endian() ? (4 - sizeof(T) - (byte_offset)) : byte_offset); | const uint32_t bits_to_shift = 8*(endianness::is_big_endian() ? (4 - sizeof(T) - (byte_offset)) : byte_offset); | |||
const uint32_t mask = (((uint32_t)1<<(sizeof(T)*8)) - 1 )< <bits_to_shift; | const uint32_t mask = (((uint32_t)1<<(sizeof(T)*8)) - 1 )< <bits_to_shift; | |||
// for signed T, any sign extension bits in cast value/comparand are im mediately clipped by mask | ||||
const uint32_t shifted_comparand = ((uint32_t)comparand << bits_to_shif t)&mask; | const uint32_t shifted_comparand = ((uint32_t)comparand << bits_to_shif t)&mask; | |||
const uint32_t shifted_value = ((uint32_t)value << bits_to_shif t)&mask; | const uint32_t shifted_value = ((uint32_t)value << bits_to_shif t)&mask; | |||
for(atomic_backoff b;;b.pause()) { | for(atomic_backoff b;;b.pause()) { | |||
const uint32_t surroundings = *aligned_ptr & ~mask ; // reload the aligned_ptr value which might change during the pause | const uint32_t surroundings = *aligned_ptr & ~mask ; // may have c hanged during the pause | |||
const uint32_t big_comparand = surroundings | shifted_comparand ; | const uint32_t big_comparand = surroundings | shifted_comparand ; | |||
const uint32_t big_value = surroundings | shifted_value ; | const uint32_t big_value = surroundings | shifted_value ; | |||
// __TBB_machine_cmpswp4 presumed to have full fence. | // __TBB_machine_cmpswp4 presumed to have full fence. | |||
// Cast shuts up /Wp64 warning | // Cast shuts up /Wp64 warning | |||
const uint32_t big_result = (uint32_t)__TBB_machine_cmpswp4( aligne d_ptr, big_value, big_comparand ); | const uint32_t big_result = (uint32_t)__TBB_machine_cmpswp4( aligne d_ptr, big_value, big_comparand ); | |||
if( big_result == big_comparand // CAS succeeded | if( big_result == big_comparand // CAS succeeded | |||
|| ((big_result ^ big_comparand) & mask) != 0) // CAS failed an d the bits of interest have changed | || ((big_result ^ big_comparand) & mask) != 0) // CAS failed an d the bits of interest have changed | |||
{ | { | |||
return T((big_result & mask) >> bits_to_shift); | return T((big_result & mask) >> bits_to_shift); | |||
} | } | |||
else continue; // CAS failed bu t the bits of interest were not changed | else continue; // CAS failed bu t the bits of interest were not changed | |||
} | } | |||
} | } | |||
#endif //__TBB_BIG_ENDIAN!=-1 | #endif // __TBB_ENDIANNESS!=__TBB_ENDIAN_UNSUPPORTED | |||
/////////////////////////////////////////////////////////////////////////// | ||||
///// | ||||
template<size_t S, typename T> | template<size_t S, typename T> | |||
inline T __TBB_CompareAndSwapGeneric (volatile void *ptr, T value, T compar and ); | inline T __TBB_CompareAndSwapGeneric (volatile void *ptr, T value, T compar and ); | |||
template<> | template<> | |||
inline uint8_t __TBB_CompareAndSwapGeneric <1,uint8_t> (volatile void *ptr, uint8_t value, uint8_t comparand ) { | inline uint8_t __TBB_CompareAndSwapGeneric <1,uint8_t> (volatile void *ptr, uint8_t value, uint8_t comparand ) { | |||
#if __TBB_USE_GENERIC_PART_WORD_CAS | #if __TBB_USE_GENERIC_PART_WORD_CAS | |||
return __TBB_MaskedCompareAndSwap<uint8_t>((volatile uint8_t *)ptr,valu e,comparand); | return __TBB_MaskedCompareAndSwap<uint8_t>((volatile uint8_t *)ptr,valu e,comparand); | |||
#else | #else | |||
return __TBB_machine_cmpswp1(ptr,value,comparand); | return __TBB_machine_cmpswp1(ptr,value,comparand); | |||
#endif | #endif | |||
skipping to change at line 907 | skipping to change at line 922 | |||
tbb::internal::atomic_backoff b; | tbb::internal::atomic_backoff b; | |||
do { | do { | |||
b.pause(); | b.pause(); | |||
} while ( !__TBB_TryLockByte(flag) ); | } while ( !__TBB_TryLockByte(flag) ); | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
#endif | #endif | |||
#ifndef __TBB_UnlockByte | #ifndef __TBB_UnlockByte | |||
#define __TBB_UnlockByte __TBB_store_with_release | #define __TBB_UnlockByte(addr) __TBB_store_with_release((addr),0) | |||
#endif | #endif | |||
#ifndef __TBB_ReverseByte | #ifndef __TBB_ReverseByte | |||
inline unsigned char __TBB_ReverseByte(unsigned char src) { | inline unsigned char __TBB_ReverseByte(unsigned char src) { | |||
return tbb::internal::reverse<unsigned char>::byte_table[src]; | return tbb::internal::reverse<unsigned char>::byte_table[src]; | |||
} | } | |||
#endif | #endif | |||
template<typename T> | template<typename T> | |||
T __TBB_ReverseBits(T src) { | T __TBB_ReverseBits(T src) { | |||
End of changes. 12 change blocks. | ||||
39 lines changed or deleted | 62 lines changed or added | |||
windows_ia32.h | windows_ia32.h | |||
---|---|---|---|---|
skipping to change at line 38 | skipping to change at line 38 | |||
#if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_ia32_H) | #if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_ia32_H) | |||
#error Do not #include this internal file directly; use public TBB headers instead. | #error Do not #include this internal file directly; use public TBB headers instead. | |||
#endif | #endif | |||
#define __TBB_machine_windows_ia32_H | #define __TBB_machine_windows_ia32_H | |||
#include "msvc_ia32_common.h" | #include "msvc_ia32_common.h" | |||
#define __TBB_WORDSIZE 4 | #define __TBB_WORDSIZE 4 | |||
#define __TBB_BIG_ENDIAN 0 | #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | |||
#if __INTEL_COMPILER && (__INTEL_COMPILER < 1100) | #if __INTEL_COMPILER && (__INTEL_COMPILER < 1100) | |||
#define __TBB_compiler_fence() __asm { __asm nop } | #define __TBB_compiler_fence() __asm { __asm nop } | |||
#define __TBB_full_memory_fence() __asm { __asm mfence } | #define __TBB_full_memory_fence() __asm { __asm mfence } | |||
#elif _MSC_VER >= 1300 || __INTEL_COMPILER | #elif _MSC_VER >= 1300 || __INTEL_COMPILER | |||
#pragma intrinsic(_ReadWriteBarrier) | #pragma intrinsic(_ReadWriteBarrier) | |||
#pragma intrinsic(_mm_mfence) | #pragma intrinsic(_mm_mfence) | |||
#define __TBB_compiler_fence() _ReadWriteBarrier() | #define __TBB_compiler_fence() _ReadWriteBarrier() | |||
#define __TBB_full_memory_fence() _mm_mfence() | #define __TBB_full_memory_fence() _mm_mfence() | |||
#else | #else | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
windows_intel64.h | windows_intel64.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
the GNU General Public License. | the GNU General Public License. | |||
*/ | */ | |||
#if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_intel64_H) | #if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_intel64_H) | |||
#error Do not #include this internal file directly; use public TBB headers instead. | #error Do not #include this internal file directly; use public TBB headers instead. | |||
#endif | #endif | |||
#define __TBB_machine_windows_intel64_H | #define __TBB_machine_windows_intel64_H | |||
#define __TBB_WORDSIZE 8 | #define __TBB_WORDSIZE 8 | |||
#define __TBB_BIG_ENDIAN 0 | #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE | |||
#include <intrin.h> | #include <intrin.h> | |||
#include "msvc_ia32_common.h" | #include "msvc_ia32_common.h" | |||
//TODO: Use _InterlockedXXX16 intrinsics for 2 byte operations | //TODO: Use _InterlockedXXX16 intrinsics for 2 byte operations | |||
#if !__INTEL_COMPILER | #if !__INTEL_COMPILER | |||
#pragma intrinsic(_InterlockedOr64) | #pragma intrinsic(_InterlockedOr64) | |||
#pragma intrinsic(_InterlockedAnd64) | #pragma intrinsic(_InterlockedAnd64) | |||
#pragma intrinsic(_InterlockedCompareExchange) | #pragma intrinsic(_InterlockedCompareExchange) | |||
#pragma intrinsic(_InterlockedCompareExchange64) | #pragma intrinsic(_InterlockedCompareExchange64) | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
xbox360_ppc.h | xbox360_ppc.h | |||
---|---|---|---|---|
skipping to change at line 53 | skipping to change at line 53 | |||
extern "C" void _MemoryBarrier(); | extern "C" void _MemoryBarrier(); | |||
#pragma intrinsic(_MemoryBarrier) | #pragma intrinsic(_MemoryBarrier) | |||
#define __TBB_control_consistency_helper() __isync() | #define __TBB_control_consistency_helper() __isync() | |||
#define __TBB_acquire_consistency_helper() _MemoryBarrier() | #define __TBB_acquire_consistency_helper() _MemoryBarrier() | |||
#define __TBB_release_consistency_helper() _MemoryBarrier() | #define __TBB_release_consistency_helper() _MemoryBarrier() | |||
#endif | #endif | |||
#define __TBB_full_memory_fence() __sync() | #define __TBB_full_memory_fence() __sync() | |||
#define __TBB_WORDSIZE 4 | #define __TBB_WORDSIZE 4 | |||
#define __TBB_BIG_ENDIAN 1 | #define __TBB_ENDIANNESS __TBB_ENDIAN_BIG | |||
//todo: define __TBB_USE_FENCED_ATOMICS and define acquire/release primitiv es to maximize performance | //todo: define __TBB_USE_FENCED_ATOMICS and define acquire/release primitiv es to maximize performance | |||
inline __int32 __TBB_machine_cmpswp4(volatile void *ptr, __int32 value, __i nt32 comparand ) { | inline __int32 __TBB_machine_cmpswp4(volatile void *ptr, __int32 value, __i nt32 comparand ) { | |||
__sync(); | __sync(); | |||
__int32 result = InterlockedCompareExchange((volatile LONG*)ptr, value, co mparand); | __int32 result = InterlockedCompareExchange((volatile LONG*)ptr, value, co mparand); | |||
__isync(); | __isync(); | |||
return result; | return result; | |||
} | } | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||