arena::arena ( market& m, unsigned max_num_workers ) { __TBB_ASSERT( !my_guard, "improperly allocated arena?" ); __TBB_ASSERT( sizeof(slot[0]) % NFS_GetLineSize()==0, "arena::slot size not multiple of cache line size" ); __TBB_ASSERT( (uintptr_t)this % NFS_GetLineSize()==0, "arena misaligned" ); my_market = &m; my_limit = 1; // Two slots are mandatory: for the master, and for 1 worker (required to support starvation resistant tasks). my_num_slots = max(2u, max_num_workers + 1); my_max_num_workers = max_num_workers; my_num_threads_active = 1; // accounts for the master __TBB_ASSERT ( my_max_num_workers < my_num_slots, NULL ); // Construct mailboxes. Mark internal synchronization elements for the tools. for( unsigned i = 0; i < my_num_slots; ++i ) { __TBB_ASSERT( !slot[i].my_scheduler && !slot[i].task_pool, NULL ); ITT_SYNC_CREATE(slot + i, SyncType_Scheduler, SyncObj_WorkerTaskPool); mailbox(i+1).construct(); ITT_SYNC_CREATE(&mailbox(i+1), SyncType_Scheduler, SyncObj_Mailbox); #if __TBB_STATISTICS slot[i].my_counters = new ( NFS_Allocate(sizeof(statistics_counters), 1, NULL) ) statistics_counters; #endif /* __TBB_STATISTICS */ } my_task_stream.initialize(my_num_slots); ITT_SYNC_CREATE(&my_task_stream, SyncType_Scheduler, SyncObj_TaskStream); my_mandatory_concurrency = false; #if __TBB_TASK_GROUP_CONTEXT my_master_default_ctx = NULL; #endif }
//------------------------------------------------------------------------ // concurrent_queue_base //------------------------------------------------------------------------ concurrent_queue_base::concurrent_queue_base( size_t item_size ) { items_per_page = item_size<=8 ? 32 : item_size<=16 ? 16 : item_size<=32 ? 8 : item_size<=64 ? 4 : item_size<=128 ? 2 : 1; my_capacity = size_t(-1)/(item_size>1 ? item_size : 2); my_rep = cache_aligned_allocator<concurrent_queue_rep>().allocate(1); __TBB_ASSERT( (size_t)my_rep % NFS_GetLineSize()==0, "alignment error" ); __TBB_ASSERT( (size_t)&my_rep->head_counter % NFS_GetLineSize()==0, "alignment error" ); __TBB_ASSERT( (size_t)&my_rep->tail_counter % NFS_GetLineSize()==0, "alignment error" ); __TBB_ASSERT( (size_t)&my_rep->array % NFS_GetLineSize()==0, "alignment error" ); memset(my_rep,0,sizeof(concurrent_queue_rep)); this->item_size = item_size; }
arena& arena::allocate_arena( market& m, unsigned max_num_workers ) { __TBB_ASSERT( sizeof(base_type) + sizeof(arena_slot) == sizeof(arena), "All arena data fields must go to arena_base" ); __TBB_ASSERT( sizeof(base_type) % NFS_GetLineSize() == 0, "arena slots area misaligned: wrong padding" ); __TBB_ASSERT( sizeof(mail_outbox) == NFS_MaxLineSize, "Mailbox padding is wrong" ); size_t n = allocation_size(max_num_workers); unsigned char* storage = (unsigned char*)NFS_Allocate( n, 1, NULL ); // Zero all slots to indicate that they are empty memset( storage, 0, n ); return *new( storage + num_slots_to_reserve(max_num_workers) * sizeof(mail_outbox) ) arena(m, max_num_workers); }
arena* arena::allocate_arena( unsigned number_of_slots, unsigned number_of_workers, stack_size_type stack_size ) { __TBB_ASSERT( sizeof(ArenaPrefix) % NFS_GetLineSize()==0, "ArenaPrefix not multiple of cache line size" ); __TBB_ASSERT( sizeof(mail_outbox)==NFS_MaxLineSize, NULL ); __TBB_ASSERT( stack_size>0, NULL ); size_t n = sizeof(ArenaPrefix) + number_of_slots*(sizeof(mail_outbox)+sizeof(arena_slot)); unsigned char* storage = (unsigned char*)NFS_Allocate( n, 1, NULL ); // Zero all slots to indicate that they are empty memset( storage, 0, n ); arena* a = (arena*)(storage + sizeof(ArenaPrefix)+ number_of_slots*(sizeof(mail_outbox))); __TBB_ASSERT( sizeof(a->slot[0]) % NFS_GetLineSize()==0, "arena::slot size not multiple of cache line size" ); __TBB_ASSERT( (uintptr_t)a % NFS_GetLineSize()==0, NULL ); new( &a->prefix() ) ArenaPrefix( number_of_slots, number_of_workers ); // Allocate the worker_list WorkerDescriptor * w = new WorkerDescriptor[number_of_workers]; memset( w, 0, sizeof(WorkerDescriptor)*(number_of_workers)); a->prefix().worker_list = w; // Construct mailboxes. for( unsigned j=1; j<=number_of_slots; ++j ) a->mailbox(j).construct(); a->prefix().stack_size = stack_size; size_t k; // Mark each internal sync element for the tools for( k=0; k<number_of_workers; ++k ) { ITT_SYNC_CREATE(a->slot + k, SyncType_Scheduler, SyncObj_WorkerTaskPool); ITT_SYNC_CREATE(&w[k].scheduler, SyncType_Scheduler, SyncObj_WorkerLifeCycleMgmt); ITT_SYNC_CREATE(&a->mailbox(k+1), SyncType_Scheduler, SyncObj_Mailbox); } for( ; k<number_of_slots; ++k ) { ITT_SYNC_CREATE(a->slot + k, SyncType_Scheduler, SyncObj_MasterTaskPool); ITT_SYNC_CREATE(&a->mailbox(k+1), SyncType_Scheduler, SyncObj_Mailbox); } return a; }