| /* |
| Copyright 2005-2010 Intel Corporation. All Rights Reserved. |
| |
| This file is part of Threading Building Blocks. |
| |
| Threading Building Blocks is free software; you can redistribute it |
| and/or modify it under the terms of the GNU General Public License |
| version 2 as published by the Free Software Foundation. |
| |
| Threading Building Blocks is distributed in the hope that it will be |
| useful, but WITHOUT ANY WARRANTY; without even the implied warranty |
| of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with Threading Building Blocks; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| |
| As a special exception, you may use this file as part of a free software |
| library without restriction. Specifically, if other files instantiate |
| templates or use macros or inline functions from this file, or you compile |
| 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 |
| the GNU General Public License. This exception does not however |
| invalidate any other reasons why the executable file might be covered by |
| the GNU General Public License. |
| */ |
| |
| #ifndef _TBB_governor_H |
| #define _TBB_governor_H |
| |
| #include "tbb/task_scheduler_init.h" |
| #if !__TBB_ARENA_PER_MASTER |
| #include "tbb/mutex.h" |
| #endif /* !__TBB_ARENA_PER_MASTER */ |
| #include "../rml/include/rml_tbb.h" |
| |
| #include "tbb_misc.h" // for DetectNumberOfWorkers and ThreadStackSize |
| #include "tls.h" |
| |
| namespace tbb { |
| namespace internal { |
| |
| #if __TBB_ARENA_PER_MASTER |
| class market; |
| #else /* !__TBB_ARENA_PER_MASTER */ |
| class arena; |
| #endif /* !__TBB_ARENA_PER_MASTER */ |
| class generic_scheduler; |
| class __TBB_InitOnce; |
| |
| //------------------------------------------------------------------------ |
| // Class governor |
| //------------------------------------------------------------------------ |
| |
| #if __TBB_ARENA_PER_MASTER |
| //! The class handles access to the single instance of market, and to TLS to keep scheduler instances. |
| #else /* !__TBB_ARENA_PER_MASTER */ |
| //! The class handles access to the single instance of arena, and to TLS to keep scheduler instances. |
| #endif /* !__TBB_ARENA_PER_MASTER */ |
| /** It also supports automatic on-demand intialization of the TBB scheduler. |
| The class contains only static data members and methods.*/ |
| class governor { |
| friend class __TBB_InitOnce; |
| #if __TBB_ARENA_PER_MASTER |
| friend class market; |
| #else /* !__TBB_ARENA_PER_MASTER */ |
| friend void ITT_DoUnsafeOneTimeInitialization (); |
| #endif /* __TBB_ARENA_PER_MASTER */ |
| |
| //! TLS for scheduler instances associated with individual threads |
| static basic_tls<generic_scheduler*> theTLS; |
| |
| #if !__TBB_ARENA_PER_MASTER |
| //! Currently active arena |
| static arena* theArena; |
| |
| //! Mutex guarding creation/destruction of theArena |
| static mutex theArenaMutex; |
| |
| //! Caches the number of workers in the currently active arena |
| static unsigned NumWorkers; |
| #endif /* !__TBB_ARENA_PER_MASTER */ |
| |
| //! Caches the maximal level of paralellism supported by the hardware |
| static unsigned DefaultNumberOfThreads; |
| |
| static rml::tbb_factory theRMLServerFactory; |
| |
| static bool UsePrivateRML; |
| |
| //! Create key for thread-local storage and initialize RML. |
| static void acquire_resources (); |
| |
| //! Destroy the thread-local storage key and deinitialize RML. |
| static void release_resources (); |
| |
| static rml::tbb_server* create_rml_server ( rml::tbb_client& ); |
| |
| #if !__TBB_ARENA_PER_MASTER |
| //! Obtain the instance of arena to register a new master thread |
| /** If there is no active arena, create one. */ |
| static arena* obtain_arena( int number_of_threads, stack_size_type thread_stack_size ); |
| #endif /* !__TBB_ARENA_PER_MASTER */ |
| |
| //! The internal routine to undo automatic initialization. |
| /** The signature is written with void* so that the routine |
| can be the destructor argument to pthread_key_create. */ |
| static void auto_terminate(void* scheduler); |
| |
| public: |
| static unsigned default_num_threads () { |
| // No memory fence required, because at worst each invoking thread calls DetectNumberOfWorkers once. |
| return DefaultNumberOfThreads ? DefaultNumberOfThreads : |
| DefaultNumberOfThreads = DetectNumberOfWorkers(); |
| } |
| //! Processes scheduler initialization request (possibly nested) in a master thread |
| /** If necessary creates new instance of arena and/or local scheduler. |
| The auto_init argument specifies if the call is due to automatic initialization. **/ |
| static generic_scheduler* init_scheduler( unsigned num_threads, stack_size_type stack_size, bool auto_init = false ); |
| |
| //! Processes scheduler termination request (possibly nested) in a master thread |
| static void terminate_scheduler( generic_scheduler* s ); |
| |
| #if __TBB_ARENA_PER_MASTER |
| //! Returns number of worker threads in the currently active arena. |
| inline static unsigned max_number_of_workers (); |
| |
| #else /* !__TBB_ARENA_PER_MASTER */ |
| //! Dereference arena when a master thread stops using TBB. |
| /** If no more masters in the arena, terminate workers and destroy it. */ |
| static void finish_with_arena(); |
| |
| static unsigned max_number_of_workers() { |
| __TBB_ASSERT( theArena, "thread did not activate a task_scheduler_init object?" ); |
| return NumWorkers; |
| } |
| #endif /* !__TBB_ARENA_PER_MASTER */ |
| |
| //! Register TBB scheduler instance in thread local storage. |
| static void sign_on(generic_scheduler* s); |
| |
| //! Unregister TBB scheduler instance from thread local storage. |
| static void sign_off(generic_scheduler* s); |
| |
| //! Used to check validity of the local scheduler TLS contents. |
| static bool is_set ( generic_scheduler* s ) { return theTLS.get() == s; } |
| |
| //! Temporarily set TLS slot to the given scheduler |
| static void assume_scheduler( generic_scheduler* s ) { |
| #if !__TBB_ARENA_PER_MASTER |
| // should be called by a Master |
| __TBB_ASSERT( !s || !theTLS.get(), "should be called by master" ); |
| #endif |
| theTLS.set( s ); |
| } |
| |
| //! Obtain the thread local instance of the TBB scheduler. |
| /** If the scheduler has not been initialized yet, initialization is done automatically. |
| Note that auto-initialized scheduler instance is destroyed only when its thread terminates. **/ |
| static generic_scheduler* local_scheduler () { |
| generic_scheduler* s = theTLS.get(); |
| return s ? s : init_scheduler( (unsigned)task_scheduler_init::automatic, 0, true ); |
| } |
| |
| static generic_scheduler* local_scheduler_if_initialized () { |
| return theTLS.get(); |
| } |
| |
| //! Undo automatic initialization if necessary; call when a thread exits. |
| static void terminate_auto_initialized_scheduler() { |
| auto_terminate( theTLS.get() ); |
| } |
| |
| static void print_version_info (); |
| }; // class governor |
| |
| } // namespace internal |
| } // namespace tbb |
| |
| #if __TBB_ARENA_PER_MASTER |
| #include "scheduler.h" |
| |
| inline unsigned tbb::internal::governor::max_number_of_workers () { |
| return local_scheduler()->number_of_workers_in_my_arena(); |
| } |
| #endif /* __TBB_ARENA_PER_MASTER */ |
| |
| #endif /* _TBB_governor_H */ |