//! Test __TBB___TBB_FetchAndIncrement and __TBB___TBB_FetchAndDecrement static void TestAtomicCounter() { // "canary" is a value used to detect illegal overwrites. const internal::reference_count canary = ~(internal::uintptr)0/3; if( Verbose ) printf("testing __TBB_FetchAndIncrement\n"); struct { internal::reference_count prefix, i, suffix; } x; x.prefix = canary; x.i = 0; x.suffix = canary; for( int k=0; k<10; ++k ) { internal::reference_count j = __TBB_FetchAndIncrementWacquire((volatile void *)&x.i); ASSERT( x.prefix==canary, NULL ); ASSERT( x.suffix==canary, NULL ); ASSERT( x.i==k+1, NULL ); ASSERT( j==k, NULL ); } if( Verbose ) printf("testing __TBB_FetchAndDecrement\n"); x.i = 10; for( int k=10; k>0; --k ) { internal::reference_count j = __TBB_FetchAndDecrementWrelease((volatile void *)&x.i); ASSERT( j==k, NULL ); ASSERT( x.i==k-1, NULL ); ASSERT( x.prefix==canary, NULL ); ASSERT( x.suffix==canary, NULL ); } }
void* concurrent_vector_base::internal_push_back( size_type element_size, size_type& index ) { __TBB_ASSERT( sizeof(my_early_size)==sizeof(reference_count), NULL ); //size_t tmp = __TBB_FetchAndIncrementWacquire(*(tbb::internal::reference_count*)&my_early_size); size_t tmp = __TBB_FetchAndIncrementWacquire((tbb::internal::reference_count*)&my_early_size); index = tmp; segment_index_t k_old = segment_index_of( tmp ); size_type base = segment_base(k_old); helper::extend_segment_if_necessary(*this,k_old); segment_t& s = my_segment[k_old]; void* array = s.array; if ( !array ) { // FIXME - consider factoring this out and share with internal_grow_by if ( base==tmp ) { __TBB_ASSERT( !s.array, NULL ); size_t n = segment_size(k_old); array = NFS_Allocate( n, element_size, NULL ); ITT_NOTIFY( sync_releasing, &s.array ); s.array = array; } else { ITT_NOTIFY(sync_prepare, &s.array); spin_wait_while_eq( s.array, (void*)0 ); ITT_NOTIFY(sync_acquired, &s.array); array = s.array; } } size_type j_begin = tmp-base; return (void*)((char*)array+element_size*j_begin); }