You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
concurrentqueue/benchmarks/tbb/governor.h

147 lines
6.0 KiB
C++

/*
Copyright 2005-2014 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"
#include "../rml/include/rml_tbb.h"
#include "tbb_misc.h" // for AvailableHwConcurrency and ThreadStackSize
#include "tls.h"
#if __TBB_SURVIVE_THREAD_SWITCH
#include "cilk-tbb-interop.h"
#endif /* __TBB_SURVIVE_THREAD_SWITCH */
namespace tbb {
namespace internal {
class market;
class generic_scheduler;
class __TBB_InitOnce;
//------------------------------------------------------------------------
// Class governor
//------------------------------------------------------------------------
//! The class handles access to the single instance of market, and to TLS to keep scheduler instances.
/** It also supports automatic on-demand initialization of the TBB scheduler.
The class contains only static data members and methods.*/
class governor {
friend class __TBB_InitOnce;
friend class market;
//! TLS for scheduler instances associated with individual threads
static basic_tls<generic_scheduler*> theTLS;
//! Caches the maximal level of parallelism supported by the hardware
static unsigned DefaultNumberOfThreads;
static rml::tbb_factory theRMLServerFactory;
static bool UsePrivateRML;
//! Instance of task_scheduler_init that requested blocking termination.
static const task_scheduler_init *BlockingTSI;
#if TBB_USE_ASSERT
static bool IsBlockingTerminationInProgress;
#endif
static bool is_speculation_enabled;
//! 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& );
//! 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 AvailableHwConcurrency once.
return DefaultNumberOfThreads ? DefaultNumberOfThreads :
DefaultNumberOfThreads = AvailableHwConcurrency();
}
//! 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, const task_scheduler_init *tsi_ptr );
//! 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 ) { 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 ();
static void initialize_rml_factory ();
static bool needsWaitWorkers () { return BlockingTSI!=NULL; }
//! Must be called before init_scheduler
static void setBlockingTerminate(const task_scheduler_init *tsi);
#if __TBB_SURVIVE_THREAD_SWITCH
static __cilk_tbb_retcode stack_op_handler( __cilk_tbb_stack_op op, void* );
#endif /* __TBB_SURVIVE_THREAD_SWITCH */
static bool speculation_enabled() { return is_speculation_enabled; }
}; // class governor
} // namespace internal
} // namespace tbb
#endif /* _TBB_governor_H */