blob: 0d70573f0c7218c0affddfbcf1d7ac05e4e9d0de [file] [log] [blame]
/*
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_market_H
#define _TBB_market_H
#include "tbb/tbb_stddef.h"
#if __TBB_ARENA_PER_MASTER
#include "tbb/atomic.h"
#include "tbb/spin_mutex.h"
#include "../rml/include/rml_tbb.h"
#include "intrusive_list.h"
#if defined(_MSC_VER) && defined(_Wp64)
// Workaround for overzealous compiler warnings in /Wp64 mode
#pragma warning (push)
#pragma warning (disable: 4244)
#endif
namespace tbb {
class task_group_context;
namespace internal {
class arena;
class generic_scheduler;
//------------------------------------------------------------------------
// Class market
//------------------------------------------------------------------------
class market : no_copy, rml::tbb_client {
friend void ITT_DoUnsafeOneTimeInitialization ();
typedef intrusive_list<arena> arena_list_type;
//! Currently active global market
static market* theMarket;
typedef spin_mutex global_market_mutex_type;
//! Mutex guarding creation/destruction of theMarket, insertions/deletions in my_arenas, and cancellation propagation
static global_market_mutex_type theMarketMutex;
//! Reference count controlling market object lifetime
intptr_t my_ref_count;
//! List of active arenas
arena_list_type my_arenas;
//! The first arena to be checked when idle worker seeks for an arena to enter
/** The check happens in round-robin fashion. **/
arena_list_type::iterator my_next_arena;
//! Lightweight mutex guarding accounting operations with arenas list
spin_mutex my_arenas_list_mutex;
//! Number of workers that were requested by all arenas
atomic<int> my_total_demand;
//! Pointer to the RML server object that services this TBB instance.
rml::tbb_server* my_server;
//! Stack size of worker threads
size_t my_stack_size;
//! Number of workers requested from the underlying resource manager
unsigned my_max_num_workers;
#if __TBB_COUNT_TASK_NODES
//! Net number of nodes that have been allocated from heap.
/** Updated each time a scheduler or arena is destroyed. */
atomic<intptr_t> my_task_node_count;
#endif /* __TBB_COUNT_TASK_NODES */
//! Number of workers that have been delivered by RML
atomic<unsigned> my_num_workers;
//! Constructor
market ( unsigned max_num_workers, size_t stack_size );
//! Factory method creating new market object
static market& global_market ( unsigned max_num_workers, size_t stack_size );
//! Destroys and deallocates market object created by market::create()
void destroy ();
//! Returns next arena that needs more workers, or NULL.
arena* arena_in_need ();
//! Recalculates the number of workers assigned to each arena.
/** The actual number of workers servicing a particular arena may temporarily
deviate from the calculated value. **/
void update_allotment ( int max_workers );
//! Returns number of masters doing computational (CPU-intensive) work
int num_active_masters () { return 1; } // APM TODO: replace with a real mechanism
// // //
// Implementation of rml::tbb_client interface methods
/*override*/ version_type version () const { return 0; }
/*override*/ unsigned max_job_count () const { return my_max_num_workers; }
/*override*/ size_t min_stack_size () const { return worker_stack_size(); }
/*override*/ policy_type policy () const { return throughput; }
/*override*/ job* create_one_job ();
/*override*/ void cleanup( job& j );
/*override*/ void acknowledge_close_connection ();
/*override*/ void process( job& j );
public:
//! Creates an arena object
/** If necessary, also creates global market instance, and boosts its ref count.
Each call to create_arena() must be matched by the call to arena::free_arena(). **/
static arena& create_arena ( unsigned max_num_workers, size_t stack_size );
//! Removes the arena from the market's list
void detach_arena ( arena& );
//! Decrements market's refcount and destroys it in the end
void release ();
//! Request that arena's need in workers should be adjusted.
/** Concurrent invocations are possible only on behalf of different arenas. **/
void adjust_demand ( arena&, int delta );
//! Returns the requested stack size of worker threads.
size_t worker_stack_size () const { return my_stack_size; }
#if __TBB_COUNT_TASK_NODES
//! Returns the number of task objects "living" in worker threads
intptr_t workers_task_node_count();
//! Net number of nodes that have been allocated from heap.
/** Updated each time a scheduler or arena is destroyed. */
void update_task_node_count( intptr_t delta ) { my_task_node_count += delta; }
#endif /* __TBB_COUNT_TASK_NODES */
#if __TBB_TASK_GROUP_CONTEXT
//! Propagates cancellation request to all descendants of the context.
void propagate_cancellation ( task_group_context& ctx );
//! Array of pointers to the registered workers
/** Used by cancellation propagation mechanism.
Must be the last data member of the class market. **/
generic_scheduler* my_workers[1];
#endif /* __TBB_TASK_GROUP_CONTEXT */
#if __TBB_ARENA_PER_MASTER && ( _WIN32||_WIN64 )
//! register master with the resource manager
void register_master( ::rml::server::execution_resource_t& rsc_handle ) {
__TBB_ASSERT( my_server, "RML server not defined?" );
// the server may ignore registration and set master_exec_resource to NULL.
my_server->register_master( rsc_handle );
}
//! unregister master with the resource manager
void unregister_master( ::rml::server::execution_resource_t& rsc_handle ) const {
my_server->unregister_master( rsc_handle );
}
#endif /* !__TBB_ARENA_PER_MASTER && ( _WIN32||_WIN64 ) */
}; // class market
} // namespace internal
} // namespace tbb
#if defined(_MSC_VER) && defined(_Wp64)
// Workaround for overzealous compiler warnings in /Wp64 mode
#pragma warning (pop)
#endif // warning 4244 is back
#endif /* __TBB_ARENA_PER_MASTER */
#endif /* _TBB_market_H */