void task_scheduler_observer_v3::observe( bool state ) { if( state ) { if( !my_proxy ) { if( !__TBB_InitOnce::initialization_done() ) DoOneTimeInitializations(); my_busy_count = 0; my_proxy = new observer_proxy(*this); if( generic_scheduler* s = governor::local_scheduler_if_initialized() ) { // Notify newly created observer of its own thread. // Any other pending observers are notified too. s->notify_entry_observers(); } } } else { if( observer_proxy* proxy = my_proxy ) { my_proxy = NULL; __TBB_ASSERT( proxy->gc_ref_count>=1, "reference for observer missing" ); { task_scheduler_observer_mutex_scoped_lock lock(the_task_scheduler_observer_mutex.begin()[0],/*is_writer=*/true); proxy->observer = NULL; } proxy->remove_ref_slow(); while( my_busy_count ) { __TBB_Yield(); } } } }
void governor::one_time_init() { if( !__TBB_InitOnce::initialization_done() ) DoOneTimeInitializations(); #if __TBB_SURVIVE_THREAD_SWITCH atomic_do_once( &initialize_cilk_interop, cilkrts_load_state ); #endif /* __TBB_SURVIVE_THREAD_SWITCH */ }
generic_scheduler* governor::init_scheduler( unsigned num_threads, stack_size_type stack_size, bool auto_init ) { if( !__TBB_InitOnce::initialization_done() ) DoOneTimeInitializations(); generic_scheduler* s = theTLS.get(); if( s ) { s->my_ref_count += 1; return s; } #if __TBB_SURVIVE_THREAD_SWITCH atomic_do_once( &initialize_cilk_interop, cilkrts_load_state ); #endif /* __TBB_SURVIVE_THREAD_SWITCH */ if( (int)num_threads == task_scheduler_init::automatic ) num_threads = default_num_threads(); s = generic_scheduler::create_master( market::create_arena( num_threads - 1, stack_size ? stack_size : ThreadStackSize ) ); __TBB_ASSERT(s, "Somehow a local scheduler creation for a master thread failed"); s->my_auto_initialized = auto_init; return s; }
generic_scheduler* governor::init_scheduler( unsigned num_threads, stack_size_type stack_size, bool auto_init ) { if( !__TBB_InitOnce::initialization_done() ) DoOneTimeInitializations(); generic_scheduler* s = theTLS.get(); if( s ) { s->ref_count += 1; return s; } if( (int)num_threads == task_scheduler_init::automatic ) num_threads = default_num_threads(); #if __TBB_ARENA_PER_MASTER s = generic_scheduler::create_master( market::create_arena( num_threads - 1, stack_size ? stack_size : ThreadStackSize ) ); #else /* !__TBB_ARENA_PER_MASTER */ s = generic_scheduler::create_master( *obtain_arena(num_threads, stack_size) ); #endif /* !__TBB_ARENA_PER_MASTER */ __TBB_ASSERT(s, "Somehow a local scheduler creation for a master thread failed"); s->is_auto_initialized = auto_init; return s; }
void task_scheduler_observer_v3::observe( bool enable ) { if( enable ) { if( !my_proxy ) { my_proxy = new observer_proxy( *this ); if ( !my_proxy->is_global() ) { // Local observer activation generic_scheduler* s = governor::local_scheduler_if_initialized(); #if __TBB_TASK_ARENA intptr_t tag = my_proxy->get_v6_observer()->my_context_tag; if( tag != interface6::task_scheduler_observer::implicit_tag ) { // explicit arena task_arena *a = reinterpret_cast<task_arena*>(tag); a->check_init(); my_proxy->my_list = &a->my_arena->my_observers; } else #endif { if( !s ) s = governor::init_scheduler( (unsigned)task_scheduler_init::automatic, 0, true ); __TBB_ASSERT( __TBB_InitOnce::initialization_done(), NULL ); __TBB_ASSERT( s && s->my_arena, NULL ); my_proxy->my_list = &s->my_arena->my_observers; } my_proxy->my_list->insert(my_proxy); my_busy_count = 0; // Notify newly activated observer and other pending ones if it belongs to current arena if(s && &s->my_arena->my_observers == my_proxy->my_list ) my_proxy->my_list->notify_entry_observers( s->my_last_local_observer, s->is_worker() ); } else { // Obsolete. Global observer activation if( !__TBB_InitOnce::initialization_done() ) DoOneTimeInitializations(); my_busy_count = 0; my_proxy->my_list = &the_global_observer_list; my_proxy->my_list->insert(my_proxy); if( generic_scheduler* s = governor::local_scheduler_if_initialized() ) { // Notify newly created observer of its own thread. // Any other pending observers are notified too. the_global_observer_list.notify_entry_observers( s->my_last_global_observer, s->is_worker() ); } } } } else { // Make sure that possible concurrent proxy list cleanup does not conflict // with the observer destruction here. if ( observer_proxy* proxy = (observer_proxy*)__TBB_FetchAndStoreW(&my_proxy, 0) ) { // List destruction should not touch this proxy after we've won the above interlocked exchange. __TBB_ASSERT( proxy->my_observer == this, NULL ); __TBB_ASSERT( is_alive(proxy->my_ref_count), "Observer's proxy died prematurely" ); __TBB_ASSERT( proxy->my_ref_count >= 1, "reference for observer missing" ); observer_list &list = *proxy->my_list; { // Ensure that none of the list walkers relies on observer pointer validity observer_list::scoped_lock lock(list.mutex(), /*is_writer=*/true); proxy->my_observer = NULL; } intptr_t trait = proxy->my_version == 6 ? interface6::task_scheduler_observer::v6_trait : 0; // Proxy may still be held by other threads (to track the last notified observer) list.remove_ref(proxy); while( my_busy_count ) __TBB_Yield(); store<relaxed>( my_busy_count, trait ); } } }