Intel(R) Threading Building Blocks Doxygen Documentation  version 4.2.3
tbb::internal::generic_scheduler Class Referenceabstract

Work stealing task scheduler. More...

#include <scheduler.h>

Inheritance diagram for tbb::internal::generic_scheduler:
Collaboration diagram for tbb::internal::generic_scheduler:

Public Member Functions

bool is_task_pool_published () const
 
bool is_local_task_pool_quiescent () const
 
bool is_quiescent_local_task_pool_empty () const
 
bool is_quiescent_local_task_pool_reset () const
 
void attach_mailbox (affinity_id id)
 
void init_stack_info ()
 Sets up the data necessary for the stealing limiting heuristics. More...
 
bool can_steal ()
 Returns true if stealing is allowed. More...
 
void publish_task_pool ()
 Used by workers to enter the task pool. More...
 
void leave_task_pool ()
 Leave the task pool. More...
 
void reset_task_pool_and_leave ()
 Resets head and tail indices to 0, and leaves task pool. More...
 
task ** lock_task_pool (arena_slot *victim_arena_slot) const
 Locks victim's task pool, and returns pointer to it. The pointer can be NULL. More...
 
void unlock_task_pool (arena_slot *victim_arena_slot, task **victim_task_pool) const
 Unlocks victim's task pool. More...
 
void acquire_task_pool () const
 Locks the local task pool. More...
 
void release_task_pool () const
 Unlocks the local task pool. More...
 
taskprepare_for_spawning (task *t)
 Checks if t is affinitized to another thread, and if so, bundles it as proxy. More...
 
void commit_spawned_tasks (size_t new_tail)
 Makes newly spawned tasks visible to thieves. More...
 
void commit_relocated_tasks (size_t new_tail)
 Makes relocated tasks visible to thieves and releases the local task pool. More...
 
taskget_task (__TBB_ISOLATION_EXPR(isolation_tag isolation))
 Get a task from the local pool. More...
 
taskget_task (size_t T)
 Get a task from the local pool at specified location T. More...
 
taskget_mailbox_task (__TBB_ISOLATION_EXPR(isolation_tag isolation))
 Attempt to get a task from the mailbox. More...
 
tasksteal_task (__TBB_ISOLATION_ARG(arena_slot &victim_arena_slot, isolation_tag isolation))
 Steal task from another scheduler's ready pool. More...
 
size_t prepare_task_pool (size_t n)
 Makes sure that the task pool can accommodate at least n more elements. More...
 
bool cleanup_master (bool blocking_terminate)
 Perform necessary cleanup when a master thread stops using TBB. More...
 
void assert_task_pool_valid () const
 
void attach_arena (arena *, size_t index, bool is_master)
 
void nested_arena_entry (arena *, size_t)
 
void nested_arena_exit ()
 
void wait_until_empty ()
 
void spawn (task &first, task *&next) __TBB_override
 For internal use only. More...
 
void spawn_root_and_wait (task &first, task *&next) __TBB_override
 For internal use only. More...
 
void enqueue (task &, void *reserved) __TBB_override
 For internal use only. More...
 
void local_spawn (task *first, task *&next)
 
void local_spawn_root_and_wait (task *first, task *&next)
 
virtual void local_wait_for_all (task &parent, task *child)=0
 
void free_scheduler ()
 Destroy and deallocate this scheduler object. More...
 
taskallocate_task (size_t number_of_bytes, __TBB_CONTEXT_ARG(task *parent, task_group_context *context))
 Allocate task object, either from the heap or a free list. More...
 
template<free_task_hint h>
void free_task (task &t)
 Put task on free list. More...
 
void deallocate_task (task &t)
 Return task object to the memory allocator. More...
 
bool is_worker () const
 True if running on a worker thread, false otherwise. More...
 
bool outermost_level () const
 True if the scheduler is on the outermost dispatch level. More...
 
bool master_outermost_level () const
 True if the scheduler is on the outermost dispatch level in a master thread. More...
 
bool worker_outermost_level () const
 True if the scheduler is on the outermost dispatch level in a worker thread. More...
 
unsigned max_threads_in_arena ()
 Returns the concurrency limit of the current arena. More...
 
virtual taskreceive_or_steal_task (__TBB_ISOLATION_ARG(__TBB_atomic reference_count &completion_ref_count, isolation_tag isolation))=0
 Try getting a task from other threads (via mailbox, stealing, FIFO queue, orphans adoption). More...
 
void free_nonlocal_small_task (task &t)
 Free a small task t that that was allocated by a different scheduler. More...
 
- Public Member Functions inherited from tbb::internal::scheduler
virtual void wait_for_all (task &parent, task *child)=0
 For internal use only. More...
 
virtual ~scheduler ()=0
 Pure virtual destructor;. More...
 

Static Public Member Functions

static bool is_version_3_task (task &t)
 
static bool is_proxy (const task &t)
 True if t is a task_proxy. More...
 
static generic_schedulercreate_master (arena *a)
 Initialize a scheduler for a master thread. More...
 
static generic_schedulercreate_worker (market &m, size_t index)
 Initialize a scheduler for a worker thread. More...
 
static void cleanup_worker (void *arg, bool worker)
 Perform necessary cleanup when a worker thread finishes. More...
 
static taskplugged_return_list ()
 Special value used to mark my_return_list as not taking any more entries. More...
 

Public Attributes

uintptr_t my_stealing_threshold
 Position in the call stack specifying its maximal filling when stealing is still allowed. More...
 
marketmy_market
 The market I am in. More...
 
FastRandom my_random
 Random number generator used for picking a random victim from which to steal. More...
 
taskmy_free_list
 Free list of small tasks that can be reused. More...
 
taskmy_dummy_task
 Fake root task created by slave threads. More...
 
long my_ref_count
 Reference count for scheduler. More...
 
bool my_auto_initialized
 True if *this was created by automatic TBB initialization. More...
 
__TBB_atomic intptr_t my_small_task_count
 Number of small tasks that have been allocated by this scheduler. More...
 
taskmy_return_list
 List of small tasks that have been returned to this scheduler by other schedulers. More...
 
- Public Attributes inherited from tbb::internal::intrusive_list_node
intrusive_list_nodemy_prev_node
 
intrusive_list_nodemy_next_node
 
- Public Attributes inherited from tbb::internal::scheduler_state
size_t my_arena_index
 Index of the arena slot the scheduler occupies now, or occupied last time. More...
 
arena_slotmy_arena_slot
 Pointer to the slot in the arena we own at the moment. More...
 
arenamy_arena
 The arena that I own (if master) or am servicing at the moment (if worker) More...
 
taskmy_innermost_running_task
 Innermost task whose task::execute() is running. A dummy task on the outermost level. More...
 
mail_inbox my_inbox
 
affinity_id my_affinity_id
 The mailbox id assigned to this scheduler. More...
 
scheduler_properties my_properties
 

Static Public Attributes

static const size_t quick_task_size = 256-task_prefix_reservation_size
 If sizeof(task) is <=quick_task_size, it is handled on a free list instead of malloc'd. More...
 
static const size_t null_arena_index = ~size_t(0)
 
static const size_t min_task_pool_size = 64
 

Protected Member Functions

 generic_scheduler (market &)
 

Friends

template<typename SchedulerTraits >
class custom_scheduler
 

Detailed Description

Work stealing task scheduler.

None of the fields here are ever read or written by threads other than the thread that creates the instance.

Class generic_scheduler is an abstract base class that contains most of the scheduler, except for tweaks specific to processors and tools (e.g. VTune). The derived template class custom_scheduler<SchedulerTraits> fills in the tweaks.

Definition at line 115 of file scheduler.h.

Constructor & Destructor Documentation

◆ generic_scheduler()

tbb::internal::generic_scheduler::generic_scheduler ( market m)
protected

Definition at line 88 of file scheduler.cpp.

89  : my_market(&m)
90  , my_random(this)
91  , my_ref_count(1)
92  , my_small_task_count(1) // Extra 1 is a guard reference
93 #if __TBB_SURVIVE_THREAD_SWITCH && TBB_USE_ASSERT
94  , my_cilk_state(cs_none)
95 #endif /* __TBB_SURVIVE_THREAD_SWITCH && TBB_USE_ASSERT */
96 {
97  __TBB_ASSERT( !my_arena_index, "constructor expects the memory being zero-initialized" );
98  __TBB_ASSERT( governor::is_set(NULL), "scheduler is already initialized for this thread" );
99 
100  my_innermost_running_task = my_dummy_task = &allocate_task( sizeof(task), __TBB_CONTEXT_ARG(NULL, &the_dummy_context) );
101  my_properties.outermost = true;
102 #if __TBB_TASK_PRIORITY
103  my_ref_top_priority = &m.my_global_top_priority;
104  my_ref_reload_epoch = &m.my_global_reload_epoch;
105 #endif /* __TBB_TASK_PRIORITY */
106 #if __TBB_TASK_GROUP_CONTEXT
107  // Sync up the local cancellation state with the global one. No need for fence here.
108  my_context_state_propagation_epoch = the_context_state_propagation_epoch;
109  my_context_list_head.my_prev = &my_context_list_head;
110  my_context_list_head.my_next = &my_context_list_head;
111  ITT_SYNC_CREATE(&my_context_list_mutex, SyncType_Scheduler, SyncObj_ContextsList);
112 #endif /* __TBB_TASK_GROUP_CONTEXT */
113  ITT_SYNC_CREATE(&my_dummy_task->prefix().ref_count, SyncType_Scheduler, SyncObj_WorkerLifeCycleMgmt);
114  ITT_SYNC_CREATE(&my_return_list, SyncType_Scheduler, SyncObj_TaskReturnList);
115 }
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
task & allocate_task(size_t number_of_bytes, __TBB_CONTEXT_ARG(task *parent, task_group_context *context))
Allocate task object, either from the heap or a free list.
Definition: scheduler.cpp:298
FastRandom my_random
Random number generator used for picking a random victim from which to steal.
Definition: scheduler.h:149
__TBB_atomic intptr_t my_small_task_count
Number of small tasks that have been allocated by this scheduler.
Definition: scheduler.h:358
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
scheduler_properties my_properties
Definition: scheduler.h:86
task * my_dummy_task
Fake root task created by slave threads.
Definition: scheduler.h:160
static bool is_set(generic_scheduler *s)
Used to check validity of the local scheduler TLS contents.
Definition: governor.cpp:124
#define ITT_SYNC_CREATE(obj, type, name)
Definition: itt_notify.h:120
#define __TBB_CONTEXT_ARG(arg1, context)
market * my_market
The market I am in.
Definition: scheduler.h:146
long my_ref_count
Reference count for scheduler.
Definition: scheduler.h:164
bool outermost
Indicates that a scheduler is on outermost level.
Definition: scheduler.h:57
size_t my_arena_index
Index of the arena slot the scheduler occupies now, or occupied last time.
Definition: scheduler.h:64
internal::task_prefix & prefix(internal::version_tag *=NULL) const
Get reference to corresponding task_prefix.
Definition: task.h:920
task * my_return_list
List of small tasks that have been returned to this scheduler by other schedulers.
Definition: scheduler.h:362
task * my_innermost_running_task
Innermost task whose task::execute() is running. A dummy task on the outermost level.
Definition: scheduler.h:73

References __TBB_ASSERT, __TBB_CONTEXT_ARG, allocate_task(), tbb::internal::governor::is_set(), ITT_SYNC_CREATE, tbb::internal::scheduler_state::my_arena_index, my_dummy_task, tbb::internal::scheduler_state::my_innermost_running_task, tbb::internal::scheduler_state::my_properties, my_return_list, tbb::internal::scheduler_properties::outermost, and tbb::task::prefix().

Here is the call graph for this function:

Member Function Documentation

◆ acquire_task_pool()

void tbb::internal::generic_scheduler::acquire_task_pool ( ) const
inline

Locks the local task pool.

Garbles my_arena_slot->task_pool for the duration of the lock. Requires correctly set my_arena_slot->task_pool_ptr.

ATTENTION: This method is mostly the same as generic_scheduler::lock_task_pool(), with a little different logic of slot state checks (slot is either locked or points to our task pool). Thus if either of them is changed, consider changing the counterpart as well.

Definition at line 454 of file scheduler.cpp.

454  {
455  if ( !is_task_pool_published() )
456  return; // we are not in arena - nothing to lock
457  bool sync_prepare_done = false;
458  for( atomic_backoff b;;b.pause() ) {
459 #if TBB_USE_ASSERT
460  __TBB_ASSERT( my_arena_slot == my_arena->my_slots + my_arena_index, "invalid arena slot index" );
461  // Local copy of the arena slot task pool pointer is necessary for the next
462  // assertion to work correctly to exclude asynchronous state transition effect.
463  task** tp = my_arena_slot->task_pool;
464  __TBB_ASSERT( tp == LockedTaskPool || tp == my_arena_slot->task_pool_ptr, "slot ownership corrupt?" );
465 #endif
468  {
469  // We acquired our own slot
470  ITT_NOTIFY(sync_acquired, my_arena_slot);
471  break;
472  }
473  else if( !sync_prepare_done ) {
474  // Start waiting
475  ITT_NOTIFY(sync_prepare, my_arena_slot);
476  sync_prepare_done = true;
477  }
478  // Someone else acquired a lock, so pause and do exponential backoff.
479  }
480  __TBB_ASSERT( my_arena_slot->task_pool == LockedTaskPool, "not really acquired task pool" );
481 } // generic_scheduler::acquire_task_pool
#define LockedTaskPool
Definition: scheduler.h:47
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
atomic< T > & as_atomic(T &t)
Definition: atomic.h:547
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
size_t my_arena_index
Index of the arena slot the scheduler occupies now, or occupied last time.
Definition: scheduler.h:64
arena_slot my_slots[1]
Definition: arena.h:283

References __TBB_ASSERT, tbb::internal::as_atomic(), is_task_pool_published(), ITT_NOTIFY, LockedTaskPool, tbb::internal::scheduler_state::my_arena, tbb::internal::scheduler_state::my_arena_index, tbb::internal::scheduler_state::my_arena_slot, tbb::internal::arena::my_slots, tbb::internal::atomic_backoff::pause(), tbb::internal::arena_slot_line1::task_pool, and tbb::internal::arena_slot_line2::task_pool_ptr.

Referenced by cleanup_master(), get_task(), and prepare_task_pool().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ allocate_task()

task & tbb::internal::generic_scheduler::allocate_task ( size_t  number_of_bytes,
__TBB_CONTEXT_ARG(task *parent, task_group_context *context)   
)

Allocate task object, either from the heap or a free list.

Returns uninitialized task object with initialized prefix.

Definition at line 298 of file scheduler.cpp.

299  {
300  GATHER_STATISTIC(++my_counters.active_tasks);
301  task *t;
302  if( number_of_bytes<=quick_task_size ) {
303 #if __TBB_HOARD_NONLOCAL_TASKS
304  if( (t = my_nonlocal_free_list) ) {
305  GATHER_STATISTIC(--my_counters.free_list_length);
306  __TBB_ASSERT( t->state()==task::freed, "free list of tasks is corrupted" );
307  my_nonlocal_free_list = t->prefix().next;
308  } else
309 #endif
310  if( (t = my_free_list) ) {
311  GATHER_STATISTIC(--my_counters.free_list_length);
312  __TBB_ASSERT( t->state()==task::freed, "free list of tasks is corrupted" );
313  my_free_list = t->prefix().next;
314  } else if( my_return_list ) {
315  // No fence required for read of my_return_list above, because __TBB_FetchAndStoreW has a fence.
316  t = (task*)__TBB_FetchAndStoreW( &my_return_list, 0 ); // with acquire
317  __TBB_ASSERT( t, "another thread emptied the my_return_list" );
318  __TBB_ASSERT( t->prefix().origin==this, "task returned to wrong my_return_list" );
319  ITT_NOTIFY( sync_acquired, &my_return_list );
320  my_free_list = t->prefix().next;
321  } else {
323 #if __TBB_COUNT_TASK_NODES
324  ++my_task_node_count;
325 #endif /* __TBB_COUNT_TASK_NODES */
326  t->prefix().origin = this;
327  t->prefix().next = 0;
329  }
330 #if __TBB_PREFETCHING
331  task *t_next = t->prefix().next;
332  if( !t_next ) { // the task was last in the list
333 #if __TBB_HOARD_NONLOCAL_TASKS
334  if( my_free_list )
335  t_next = my_free_list;
336  else
337 #endif
338  if( my_return_list ) // enable prefetching, gives speedup
339  t_next = my_free_list = (task*)__TBB_FetchAndStoreW( &my_return_list, 0 );
340  }
341  if( t_next ) { // gives speedup for both cache lines
342  __TBB_cl_prefetch(t_next);
343  __TBB_cl_prefetch(&t_next->prefix());
344  }
345 #endif /* __TBB_PREFETCHING */
346  } else {
347  GATHER_STATISTIC(++my_counters.big_tasks);
348  t = (task*)((char*)NFS_Allocate( 1, task_prefix_reservation_size+number_of_bytes, NULL ) + task_prefix_reservation_size );
349 #if __TBB_COUNT_TASK_NODES
350  ++my_task_node_count;
351 #endif /* __TBB_COUNT_TASK_NODES */
352  t->prefix().origin = NULL;
353  }
354  task_prefix& p = t->prefix();
355 #if __TBB_TASK_GROUP_CONTEXT
356  p.context = context;
357 #endif /* __TBB_TASK_GROUP_CONTEXT */
358  // Obsolete. But still in use, so has to be assigned correct value here.
359  p.owner = this;
360  p.ref_count = 0;
361  // Obsolete. Assign some not outrageously out-of-place value for a while.
362  p.depth = 0;
363  p.parent = parent;
364  // In TBB 2.1 and later, the constructor for task sets extra_state to indicate the version of the tbb/task.h header.
365  // In TBB 2.0 and earlier, the constructor leaves extra_state as zero.
366  p.extra_state = 0;
367  p.affinity = 0;
368  p.state = task::allocated;
369  __TBB_ISOLATION_EXPR( p.isolation = no_isolation );
370  return *t;
371 }
task object is freshly allocated or recycled.
Definition: task.h:604
const size_t task_prefix_reservation_size
Number of bytes reserved for a task prefix.
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
task * my_free_list
Free list of small tasks that can be reused.
Definition: scheduler.h:152
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id parent
__TBB_atomic intptr_t my_small_task_count
Number of small tasks that have been allocated by this scheduler.
Definition: scheduler.h:358
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync p
static const size_t quick_task_size
If sizeof(task) is <=quick_task_size, it is handled on a free list instead of malloc'd.
Definition: scheduler.h:122
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117
#define __TBB_cl_prefetch(p)
Definition: mic_common.h:37
#define __TBB_ISOLATION_EXPR(isolation)
void *__TBB_EXPORTED_FUNC NFS_Allocate(size_t n_element, size_t element_size, void *hint)
Allocate memory on cache/sector line boundary.
task object is on free list, or is going to be put there, or was just taken off.
Definition: task.h:606
internal::task_prefix & prefix(internal::version_tag *=NULL) const
Get reference to corresponding task_prefix.
Definition: task.h:920
task * my_return_list
List of small tasks that have been returned to this scheduler by other schedulers.
Definition: scheduler.h:362
const isolation_tag no_isolation
Definition: task.h:127
#define GATHER_STATISTIC(x)

References __TBB_ASSERT, __TBB_cl_prefetch, __TBB_ISOLATION_EXPR, tbb::task::allocated, tbb::task::freed, GATHER_STATISTIC, ITT_NOTIFY, my_free_list, my_return_list, my_small_task_count, tbb::internal::NFS_Allocate(), tbb::internal::no_isolation, p, parent, tbb::task::prefix(), quick_task_size, tbb::task::state(), and tbb::internal::task_prefix_reservation_size.

Referenced by generic_scheduler(), and prepare_for_spawning().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ assert_task_pool_valid()

void tbb::internal::generic_scheduler::assert_task_pool_valid ( ) const
inline

Definition at line 298 of file scheduler.h.

298 {}

Referenced by local_spawn(), prepare_task_pool(), and tbb::task::self().

Here is the caller graph for this function:

◆ attach_arena()

void tbb::internal::generic_scheduler::attach_arena ( arena a,
size_t  index,
bool  is_master 
)

Definition at line 40 of file arena.cpp.

40  {
41  __TBB_ASSERT( a->my_market == my_market, NULL );
42  my_arena = a;
43  my_arena_index = index;
44  my_arena_slot = a->my_slots + index;
45  attach_mailbox( affinity_id(index+1) );
46  if ( is_master && my_inbox.is_idle_state( true ) ) {
47  // Master enters an arena with its own task to be executed. It means that master is not
48  // going to enter stealing loop and take affinity tasks.
49  my_inbox.set_is_idle( false );
50  }
51 #if __TBB_TASK_GROUP_CONTEXT
52  // Context to be used by root tasks by default (if the user has not specified one).
53  if( !is_master )
54  my_dummy_task->prefix().context = a->my_default_ctx;
55 #endif /* __TBB_TASK_GROUP_CONTEXT */
56 #if __TBB_TASK_PRIORITY
57  // In the current implementation master threads continue processing even when
58  // there are other masters with higher priority. Only TBB worker threads are
59  // redistributed between arenas based on the latters' priority. Thus master
60  // threads use arena's top priority as a reference point (in contrast to workers
61  // that use my_market->my_global_top_priority).
62  if( is_master ) {
63  my_ref_top_priority = &a->my_top_priority;
64  my_ref_reload_epoch = &a->my_reload_epoch;
65  }
66  my_local_reload_epoch = *my_ref_reload_epoch;
67  __TBB_ASSERT( !my_offloaded_tasks, NULL );
68 #endif /* __TBB_TASK_PRIORITY */
69 }
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
bool is_idle_state(bool value) const
Indicate whether thread that reads this mailbox is idle.
Definition: mailbox.h:222
void set_is_idle(bool value)
Indicate whether thread that reads this mailbox is idle.
Definition: mailbox.h:215
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
task * my_dummy_task
Fake root task created by slave threads.
Definition: scheduler.h:160
void attach_mailbox(affinity_id id)
Definition: scheduler.h:564
market * my_market
The market I am in.
Definition: scheduler.h:146
unsigned short affinity_id
An id as used for specifying affinity.
Definition: task.h:122
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
size_t my_arena_index
Index of the arena slot the scheduler occupies now, or occupied last time.
Definition: scheduler.h:64
internal::task_prefix & prefix(internal::version_tag *=NULL) const
Get reference to corresponding task_prefix.
Definition: task.h:920

References __TBB_ASSERT, attach_mailbox(), tbb::internal::mail_inbox::is_idle_state(), tbb::internal::scheduler_state::my_arena, tbb::internal::scheduler_state::my_arena_index, tbb::internal::scheduler_state::my_arena_slot, my_dummy_task, tbb::internal::scheduler_state::my_inbox, tbb::internal::arena_base::my_market, my_market, tbb::internal::arena::my_slots, tbb::task::prefix(), and tbb::internal::mail_inbox::set_is_idle().

Referenced by nested_arena_entry().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ attach_mailbox()

void tbb::internal::generic_scheduler::attach_mailbox ( affinity_id  id)
inline

Definition at line 564 of file scheduler.h.

564  {
565  __TBB_ASSERT(id>0,NULL);
567  my_affinity_id = id;
568 }
affinity_id my_affinity_id
The mailbox id assigned to this scheduler.
Definition: scheduler.h:84
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id id
mail_outbox & mailbox(affinity_id id)
Get reference to mailbox corresponding to given affinity_id.
Definition: arena.h:191
void attach(mail_outbox &putter)
Attach inbox to a corresponding outbox.
Definition: mailbox.h:197

References __TBB_ASSERT, tbb::internal::mail_inbox::attach(), id, tbb::internal::arena::mailbox(), tbb::internal::scheduler_state::my_affinity_id, tbb::internal::scheduler_state::my_arena, and tbb::internal::scheduler_state::my_inbox.

Referenced by attach_arena().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ can_steal()

bool tbb::internal::generic_scheduler::can_steal ( )
inline

Returns true if stealing is allowed.

Definition at line 182 of file scheduler.h.

182  {
183  int anchor;
184  // TODO IDEA: Add performance warning?
185 #if __TBB_ipf
186  return my_stealing_threshold < (uintptr_t)&anchor && (uintptr_t)__TBB_get_bsp() < my_rsb_stealing_threshold;
187 #else
188  return my_stealing_threshold < (uintptr_t)&anchor;
189 #endif
190  }
uintptr_t my_stealing_threshold
Position in the call stack specifying its maximal filling when stealing is still allowed.
Definition: scheduler.h:129
void * __TBB_get_bsp()
Retrieves the current RSE backing store pointer. IA64 specific.

References __TBB_get_bsp(), and my_stealing_threshold.

Here is the call graph for this function:

◆ cleanup_master()

bool tbb::internal::generic_scheduler::cleanup_master ( bool  blocking_terminate)

Perform necessary cleanup when a master thread stops using TBB.

Definition at line 1211 of file scheduler.cpp.

1211  {
1212  arena* const a = my_arena;
1213  market * const m = my_market;
1214  __TBB_ASSERT( my_market, NULL );
1215  if( a && is_task_pool_published() ) {
1219  {
1220  // Local task pool is empty
1221  leave_task_pool();
1222  }
1223  else {
1224  // Master's local task pool may e.g. contain proxies of affinitized tasks.
1226  __TBB_ASSERT ( governor::is_set(this), "TLS slot is cleared before the task pool cleanup" );
1229  __TBB_ASSERT ( governor::is_set(this), "Other thread reused our TLS key during the task pool cleanup" );
1230  }
1231  }
1232 #if __TBB_ARENA_OBSERVER
1233  if( a )
1234  a->my_observers.notify_exit_observers( my_last_local_observer, /*worker=*/false );
1235 #endif
1236 #if __TBB_SCHEDULER_OBSERVER
1237  the_global_observer_list.notify_exit_observers( my_last_global_observer, /*worker=*/false );
1238 #endif /* __TBB_SCHEDULER_OBSERVER */
1239 #if _WIN32||_WIN64
1240  m->unregister_master( master_exec_resource );
1241 #endif /* _WIN32||_WIN64 */
1242  if( a ) {
1243  __TBB_ASSERT(a->my_slots+0 == my_arena_slot, NULL);
1244 #if __TBB_STATISTICS
1245  *my_arena_slot->my_counters += my_counters;
1246 #endif /* __TBB_STATISTICS */
1248  }
1249 #if __TBB_TASK_GROUP_CONTEXT
1250  else { // task_group_context ownership was not transferred to arena
1251  default_context()->~task_group_context();
1252  NFS_Free(default_context());
1253  }
1254  context_state_propagation_mutex_type::scoped_lock lock(the_context_state_propagation_mutex);
1255  my_market->my_masters.remove( *this );
1256  lock.release();
1257 #endif /* __TBB_TASK_GROUP_CONTEXT */
1258  my_arena_slot = NULL; // detached from slot
1259  free_scheduler(); // do not use scheduler state after this point
1260 
1261  if( a )
1262  a->on_thread_leaving<arena::ref_external>();
1263  // If there was an associated arena, it added a public market reference
1264  return m->release( /*is_public*/ a != NULL, blocking_terminate );
1265 }
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void __TBB_store_with_release(volatile T &location, V value)
Definition: tbb_machine.h:717
void free_scheduler()
Destroy and deallocate this scheduler object.
Definition: scheduler.cpp:261
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
task * my_dummy_task
Fake root task created by slave threads.
Definition: scheduler.h:160
static const unsigned ref_external
Reference increment values for externals and workers.
Definition: arena.h:213
static bool is_set(generic_scheduler *s)
Used to check validity of the local scheduler TLS contents.
Definition: governor.cpp:124
void release_task_pool() const
Unlocks the local task pool.
Definition: scheduler.cpp:483
__TBB_atomic size_t head
Index of the first ready task in the deque.
void acquire_task_pool() const
Locks the local task pool.
Definition: scheduler.cpp:454
__TBB_atomic size_t tail
Index of the element following the last ready task in the deque.
market * my_market
The market I am in.
Definition: scheduler.h:146
virtual void local_wait_for_all(task &parent, task *child)=0
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
void __TBB_EXPORTED_FUNC NFS_Free(void *)
Free memory allocated by NFS_Allocate.
T __TBB_load_relaxed(const volatile T &location)
Definition: tbb_machine.h:739
void leave_task_pool()
Leave the task pool.
Definition: scheduler.cpp:1133
generic_scheduler * my_scheduler
Scheduler of the thread attached to the slot.
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void * lock
#define EmptyTaskPool
Definition: scheduler.h:46

References __TBB_ASSERT, tbb::internal::__TBB_load_relaxed(), tbb::internal::__TBB_store_with_release(), acquire_task_pool(), EmptyTaskPool, free_scheduler(), tbb::internal::arena_slot_line1::head, tbb::internal::governor::is_set(), is_task_pool_published(), leave_task_pool(), local_wait_for_all(), lock, tbb::internal::scheduler_state::my_arena, tbb::internal::scheduler_state::my_arena_slot, my_dummy_task, my_market, tbb::internal::arena_slot_line1::my_scheduler, tbb::internal::arena::my_slots, tbb::internal::NFS_Free(), tbb::internal::arena::on_thread_leaving(), tbb::internal::arena::ref_external, tbb::internal::market::release(), release_task_pool(), tbb::internal::arena_slot_line2::tail, and tbb::internal::arena_slot_line1::task_pool.

Here is the call graph for this function:

◆ cleanup_worker()

void tbb::internal::generic_scheduler::cleanup_worker ( void arg,
bool  worker 
)
static

Perform necessary cleanup when a worker thread finishes.

Definition at line 1201 of file scheduler.cpp.

1201  {
1203  __TBB_ASSERT( !s.my_arena_slot, "cleaning up attached worker" );
1204 #if __TBB_SCHEDULER_OBSERVER
1205  if ( worker ) // can be called by master for worker, do not notify master twice
1206  the_global_observer_list.notify_exit_observers( s.my_last_global_observer, /*worker=*/true );
1207 #endif /* __TBB_SCHEDULER_OBSERVER */
1208  s.free_scheduler();
1209 }
void const char const char int ITT_FORMAT __itt_group_sync s
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169

References __TBB_ASSERT, and s.

Referenced by tbb::internal::market::cleanup().

Here is the caller graph for this function:

◆ commit_relocated_tasks()

void tbb::internal::generic_scheduler::commit_relocated_tasks ( size_t  new_tail)
inline

Makes relocated tasks visible to thieves and releases the local task pool.

Obviously, the task pool must be locked when calling this method.

Definition at line 616 of file scheduler.h.

616  {
618  "Task pool must be locked when calling commit_relocated_tasks()" );
620  // Tail is updated last to minimize probability of a thread making arena
621  // snapshot being misguided into thinking that this task pool is empty.
622  __TBB_store_release( my_arena_slot->tail, new_tail );
624 }
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
#define __TBB_store_release
Definition: tbb_machine.h:861
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void release_task_pool() const
Unlocks the local task pool.
Definition: scheduler.cpp:483
__TBB_atomic size_t head
Index of the first ready task in the deque.
void __TBB_store_relaxed(volatile T &location, V value)
Definition: tbb_machine.h:743
bool is_local_task_pool_quiescent() const
Definition: scheduler.h:530
__TBB_atomic size_t tail
Index of the element following the last ready task in the deque.

References __TBB_ASSERT, tbb::internal::__TBB_store_relaxed(), __TBB_store_release, tbb::internal::arena_slot_line1::head, is_local_task_pool_quiescent(), tbb::internal::scheduler_state::my_arena_slot, release_task_pool(), and tbb::internal::arena_slot_line2::tail.

Referenced by prepare_task_pool().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ commit_spawned_tasks()

void tbb::internal::generic_scheduler::commit_spawned_tasks ( size_t  new_tail)
inline

Makes newly spawned tasks visible to thieves.

Definition at line 607 of file scheduler.h.

607  {
608  __TBB_ASSERT ( new_tail <= my_arena_slot->my_task_pool_size, "task deque end was overwritten" );
609  // emit "task was released" signal
610  ITT_NOTIFY(sync_releasing, (void*)((uintptr_t)my_arena_slot+sizeof(uintptr_t)));
611  // Release fence is necessary to make sure that previously stored task pointers
612  // are visible to thieves.
614 }
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void __TBB_store_with_release(volatile T &location, V value)
Definition: tbb_machine.h:717
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p sync_releasing
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117
__TBB_atomic size_t tail
Index of the element following the last ready task in the deque.

References __TBB_ASSERT, tbb::internal::__TBB_store_with_release(), ITT_NOTIFY, tbb::internal::scheduler_state::my_arena_slot, sync_releasing, and tbb::internal::arena_slot_line2::tail.

Referenced by local_spawn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_master()

generic_scheduler * tbb::internal::generic_scheduler::create_master ( arena a)
static

Initialize a scheduler for a master thread.

Definition at line 1159 of file scheduler.cpp.

1159  {
1160  // add an internal market reference; the public reference is possibly added in create_arena
1161  generic_scheduler* s = allocate_scheduler( market::global_market(/*is_public=*/false) );
1162  __TBB_ASSERT( !s->my_arena, NULL );
1163  __TBB_ASSERT( s->my_market, NULL );
1164  task& t = *s->my_dummy_task;
1165  s->my_properties.type = scheduler_properties::master;
1166  t.prefix().ref_count = 1;
1167 #if __TBB_TASK_GROUP_CONTEXT
1168  t.prefix().context = new ( NFS_Allocate(1, sizeof(task_group_context), NULL) )
1170 #if __TBB_FP_CONTEXT
1171  s->default_context()->capture_fp_settings();
1172 #endif
1173  // Do not call init_stack_info before the scheduler is set as master or worker.
1174  s->init_stack_info();
1175  context_state_propagation_mutex_type::scoped_lock lock(the_context_state_propagation_mutex);
1176  s->my_market->my_masters.push_front( *s );
1177  lock.release();
1178 #endif /* __TBB_TASK_GROUP_CONTEXT */
1179  if( a ) {
1180  // Master thread always occupies the first slot
1181  s->attach_arena( a, /*index*/0, /*is_master*/true );
1182  s->my_arena_slot->my_scheduler = s;
1183  a->my_default_ctx = s->default_context(); // also transfers implied ownership
1184  }
1185  __TBB_ASSERT( s->my_arena_index == 0, "Master thread must occupy the first slot in its arena" );
1187 
1188 #if _WIN32||_WIN64
1189  s->my_market->register_master( s->master_exec_resource );
1190 #endif /* _WIN32||_WIN64 */
1191  // Process any existing observers.
1192 #if __TBB_ARENA_OBSERVER
1193  __TBB_ASSERT( !a || a->my_observers.empty(), "Just created arena cannot have any observers associated with it" );
1194 #endif
1195 #if __TBB_SCHEDULER_OBSERVER
1196  the_global_observer_list.notify_entry_observers( s->my_last_global_observer, /*worker=*/false );
1197 #endif /* __TBB_SCHEDULER_OBSERVER */
1198  return s;
1199 }
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
static void sign_on(generic_scheduler *s)
Register TBB scheduler instance in thread-local storage.
Definition: governor.cpp:128
generic_scheduler * allocate_scheduler(market &m)
Definition: scheduler.cpp:41
void const char const char int ITT_FORMAT __itt_group_sync s
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
static market & global_market(bool is_public, unsigned max_num_workers=0, size_t stack_size=0)
Factory method creating new market object.
Definition: market.cpp:100
void *__TBB_EXPORTED_FUNC NFS_Allocate(size_t n_element, size_t element_size, void *hint)
Allocate memory on cache/sector line boundary.
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void * lock

References __TBB_ASSERT, tbb::internal::allocate_scheduler(), tbb::task_group_context::default_traits, tbb::internal::market::global_market(), tbb::task_group_context::isolated, lock, tbb::internal::scheduler_properties::master, tbb::internal::NFS_Allocate(), tbb::task::prefix(), s, and tbb::internal::governor::sign_on().

Referenced by tbb::internal::governor::init_scheduler(), and tbb::internal::governor::init_scheduler_weak().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_worker()

generic_scheduler * tbb::internal::generic_scheduler::create_worker ( market m,
size_t  index 
)
static

Initialize a scheduler for a worker thread.

Definition at line 1146 of file scheduler.cpp.

1146  {
1148  __TBB_ASSERT(index, "workers should have index > 0");
1149  s->my_arena_index = index; // index is not a real slot in arena yet
1150  s->my_dummy_task->prefix().ref_count = 2;
1151  s->my_properties.type = scheduler_properties::worker;
1152  // Do not call init_stack_info before the scheduler is set as master or worker.
1153  s->init_stack_info();
1155  return s;
1156 }
static void sign_on(generic_scheduler *s)
Register TBB scheduler instance in thread-local storage.
Definition: governor.cpp:128
generic_scheduler * allocate_scheduler(market &m)
Definition: scheduler.cpp:41
void const char const char int ITT_FORMAT __itt_group_sync s
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169

References __TBB_ASSERT, tbb::internal::allocate_scheduler(), s, tbb::internal::governor::sign_on(), and tbb::internal::scheduler_properties::worker.

Referenced by tbb::internal::market::create_one_job().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ deallocate_task()

void tbb::internal::generic_scheduler::deallocate_task ( task t)
inline

Return task object to the memory allocator.

Definition at line 580 of file scheduler.h.

580  {
581 #if TBB_USE_ASSERT
582  task_prefix& p = t.prefix();
583  p.state = 0xFF;
584  p.extra_state = 0xFF;
585  poison_pointer(p.next);
586 #endif /* TBB_USE_ASSERT */
588 #if __TBB_COUNT_TASK_NODES
589  --my_task_node_count;
590 #endif /* __TBB_COUNT_TASK_NODES */
591 }
const size_t task_prefix_reservation_size
Number of bytes reserved for a task prefix.
void poison_pointer(T *__TBB_atomic &)
Definition: tbb_stddef.h:309
void const char const char int ITT_FORMAT __itt_group_sync p
void __TBB_EXPORTED_FUNC NFS_Free(void *)
Free memory allocated by NFS_Allocate.

References tbb::internal::NFS_Free(), p, tbb::internal::poison_pointer(), tbb::task::prefix(), and tbb::internal::task_prefix_reservation_size.

Referenced by free_nonlocal_small_task(), free_scheduler(), and free_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ enqueue()

void tbb::internal::generic_scheduler::enqueue ( task t,
void reserved 
)
virtual

For internal use only.

Implements tbb::internal::scheduler.

Definition at line 681 of file scheduler.cpp.

681  {
683  // these redirections are due to bw-compatibility, consider reworking some day
684  __TBB_ASSERT( s->my_arena, "thread is not in any arena" );
685  s->my_arena->enqueue_task(t, (intptr_t)prio, s->my_random );
686 }
void const char const char int ITT_FORMAT __itt_group_sync s
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
static generic_scheduler * local_scheduler()
Obtain the thread-local instance of the TBB scheduler.
Definition: governor.h:126

References __TBB_ASSERT, tbb::internal::governor::local_scheduler(), and s.

Here is the call graph for this function:

◆ free_nonlocal_small_task()

void tbb::internal::generic_scheduler::free_nonlocal_small_task ( task t)

Free a small task t that that was allocated by a different scheduler.

Definition at line 373 of file scheduler.cpp.

373  {
374  __TBB_ASSERT( t.state()==task::freed, NULL );
375  generic_scheduler& s = *static_cast<generic_scheduler*>(t.prefix().origin);
376  __TBB_ASSERT( &s!=this, NULL );
377  for(;;) {
378  task* old = s.my_return_list;
379  if( old==plugged_return_list() )
380  break;
381  // Atomically insert t at head of s.my_return_list
382  t.prefix().next = old;
383  ITT_NOTIFY( sync_releasing, &s.my_return_list );
384  if( as_atomic(s.my_return_list).compare_and_swap(&t, old )==old ) {
385 #if __TBB_PREFETCHING
386  __TBB_cl_evict(&t.prefix());
387  __TBB_cl_evict(&t);
388 #endif
389  return;
390  }
391  }
392  deallocate_task(t);
393  if( __TBB_FetchAndDecrementWrelease( &s.my_small_task_count )==1 ) {
394  // We freed the last task allocated by scheduler s, so it's our responsibility
395  // to free the scheduler.
396  NFS_Free( &s );
397  }
398 }
void deallocate_task(task &t)
Return task object to the memory allocator.
Definition: scheduler.h:580
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
atomic< T > & as_atomic(T &t)
Definition: atomic.h:547
void const char const char int ITT_FORMAT __itt_group_sync s
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p sync_releasing
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117
#define __TBB_cl_evict(p)
Definition: mic_common.h:38
static task * plugged_return_list()
Special value used to mark my_return_list as not taking any more entries.
Definition: scheduler.h:355
#define __TBB_FetchAndDecrementWrelease(P)
Definition: tbb_machine.h:315
task object is on free list, or is going to be put there, or was just taken off.
Definition: task.h:606
void __TBB_EXPORTED_FUNC NFS_Free(void *)
Free memory allocated by NFS_Allocate.

References __TBB_ASSERT, __TBB_cl_evict, __TBB_FetchAndDecrementWrelease, tbb::internal::as_atomic(), deallocate_task(), tbb::task::freed, ITT_NOTIFY, tbb::internal::NFS_Free(), plugged_return_list(), tbb::task::prefix(), s, tbb::task::state(), and sync_releasing.

Referenced by free_scheduler(), and free_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_scheduler()

void tbb::internal::generic_scheduler::free_scheduler ( )

Destroy and deallocate this scheduler object.

Definition at line 261 of file scheduler.cpp.

261  {
262  __TBB_ASSERT( !my_arena_slot, NULL );
263 #if __TBB_TASK_GROUP_CONTEXT
264  cleanup_local_context_list();
265 #endif /* __TBB_TASK_GROUP_CONTEXT */
266  free_task<small_local_task>( *my_dummy_task );
267 
268 #if __TBB_HOARD_NONLOCAL_TASKS
269  while( task* t = my_nonlocal_free_list ) {
270  task_prefix& p = t->prefix();
271  my_nonlocal_free_list = p.next;
272  __TBB_ASSERT( p.origin && p.origin!=this, NULL );
274  }
275 #endif
276  // k accounts for a guard reference and each task that we deallocate.
277  intptr_t k = 1;
278  for(;;) {
279  while( task* t = my_free_list ) {
280  my_free_list = t->prefix().next;
281  deallocate_task(*t);
282  ++k;
283  }
285  break;
286  my_free_list = (task*)__TBB_FetchAndStoreW( &my_return_list, (intptr_t)plugged_return_list() );
287  }
288 #if __TBB_COUNT_TASK_NODES
289  my_market->update_task_node_count( my_task_node_count );
290 #endif /* __TBB_COUNT_TASK_NODES */
291  // Update my_small_task_count last. Doing so sooner might cause another thread to free *this.
292  __TBB_ASSERT( my_small_task_count>=k, "my_small_task_count corrupted" );
293  governor::sign_off(this);
294  if( __TBB_FetchAndAddW( &my_small_task_count, -k )==k )
295  NFS_Free( this );
296 }
void deallocate_task(task &t)
Return task object to the memory allocator.
Definition: scheduler.h:580
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
task * my_free_list
Free list of small tasks that can be reused.
Definition: scheduler.h:152
__TBB_atomic intptr_t my_small_task_count
Number of small tasks that have been allocated by this scheduler.
Definition: scheduler.h:358
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync p
task * my_dummy_task
Fake root task created by slave threads.
Definition: scheduler.h:160
void free_nonlocal_small_task(task &t)
Free a small task t that that was allocated by a different scheduler.
Definition: scheduler.cpp:373
static task * plugged_return_list()
Special value used to mark my_return_list as not taking any more entries.
Definition: scheduler.h:355
market * my_market
The market I am in.
Definition: scheduler.h:146
static void sign_off(generic_scheduler *s)
Unregister TBB scheduler instance from thread-local storage.
Definition: governor.cpp:149
void __TBB_EXPORTED_FUNC NFS_Free(void *)
Free memory allocated by NFS_Allocate.
internal::task_prefix & prefix(internal::version_tag *=NULL) const
Get reference to corresponding task_prefix.
Definition: task.h:920
task * my_return_list
List of small tasks that have been returned to this scheduler by other schedulers.
Definition: scheduler.h:362

References __TBB_ASSERT, deallocate_task(), free_nonlocal_small_task(), tbb::internal::scheduler_state::my_arena_slot, my_dummy_task, my_free_list, my_market, my_return_list, my_small_task_count, tbb::internal::NFS_Free(), p, plugged_return_list(), tbb::task::prefix(), and tbb::internal::governor::sign_off().

Referenced by cleanup_master().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_task()

template<free_task_hint hint>
void tbb::internal::generic_scheduler::free_task ( task t)

Put task on free list.

Does not call destructor.

Definition at line 627 of file scheduler.h.

627  {
628 #if __TBB_HOARD_NONLOCAL_TASKS
629  static const int h = hint&(~local_task);
630 #else
631  static const free_task_hint h = hint;
632 #endif
633  GATHER_STATISTIC(--my_counters.active_tasks);
634  task_prefix& p = t.prefix();
635  // Verify that optimization hints are correct.
636  __TBB_ASSERT( h!=small_local_task || p.origin==this, NULL );
637  __TBB_ASSERT( !(h&small_task) || p.origin, NULL );
638  __TBB_ASSERT( !(h&local_task) || (!p.origin || uintptr_t(p.origin) > uintptr_t(4096)), "local_task means allocated");
639  poison_value(p.depth);
640  poison_value(p.ref_count);
641  poison_pointer(p.owner);
642  __TBB_ASSERT( 1L<<t.state() & (1L<<task::executing|1L<<task::allocated), NULL );
643  p.state = task::freed;
644  if( h==small_local_task || p.origin==this ) {
645  GATHER_STATISTIC(++my_counters.free_list_length);
646  p.next = my_free_list;
647  my_free_list = &t;
648  } else if( !(h&local_task) && p.origin && uintptr_t(p.origin) < uintptr_t(4096) ) {
649  // a special value reserved for future use, do nothing since
650  // origin is not pointing to a scheduler instance
651  } else if( !(h&local_task) && p.origin ) {
652  GATHER_STATISTIC(++my_counters.free_list_length);
653 #if __TBB_HOARD_NONLOCAL_TASKS
654  if( !(h&no_cache) ) {
655  p.next = my_nonlocal_free_list;
656  my_nonlocal_free_list = &t;
657  } else
658 #endif
660  } else {
661  GATHER_STATISTIC(--my_counters.big_tasks);
662  deallocate_task(t);
663  }
664 }
task object is freshly allocated or recycled.
Definition: task.h:604
void deallocate_task(task &t)
Return task object to the memory allocator.
Definition: scheduler.h:580
void poison_pointer(T *__TBB_atomic &)
Definition: tbb_stddef.h:309
task * my_free_list
Free list of small tasks that can be reused.
Definition: scheduler.h:152
free_task_hint
Optimization hint to free_task that enables it omit unnecessary tests and code.
Bitwise-OR of local_task and small_task.
task is running, and will be destroyed after method execute() completes.
Definition: task.h:598
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync p
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function h
void free_nonlocal_small_task(task &t)
Free a small task t that that was allocated by a different scheduler.
Definition: scheduler.cpp:373
Disable caching for a small task.
Task is known to have been allocated by this scheduler.
Task is known to be a small task.
task object is on free list, or is going to be put there, or was just taken off.
Definition: task.h:606
#define GATHER_STATISTIC(x)
#define poison_value(g)

References __TBB_ASSERT, tbb::task::allocated, deallocate_task(), tbb::task::executing, free_nonlocal_small_task(), tbb::task::freed, GATHER_STATISTIC, h, tbb::internal::local_task, my_free_list, tbb::internal::no_cache, p, tbb::internal::poison_pointer(), poison_value, tbb::task::prefix(), tbb::internal::small_local_task, tbb::internal::small_task, and tbb::task::state().

Referenced by tbb::interface5::internal::task_base::destroy(), tbb::internal::allocate_additional_child_of_proxy::free(), tbb::internal::allocate_continuation_proxy::free(), tbb::internal::allocate_child_proxy::free(), and tbb::internal::auto_empty_task::~auto_empty_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_mailbox_task()

task * tbb::internal::generic_scheduler::get_mailbox_task ( __TBB_ISOLATION_EXPR(isolation_tag isolation)  )

Attempt to get a task from the mailbox.

Gets a task only if it has not been executed by its sender or a thief that has stolen it from the sender's task pool. Otherwise returns NULL.

This method is intended to be used only by the thread extracting the proxy from its mailbox. (In contrast to local task pool, mailbox can be read only by its owner).

Definition at line 1107 of file scheduler.cpp.

1107  {
1108  __TBB_ASSERT( my_affinity_id>0, "not in arena" );
1109  while ( task_proxy* const tp = my_inbox.pop( __TBB_ISOLATION_EXPR( isolation ) ) ) {
1110  if ( task* result = tp->extract_task<task_proxy::mailbox_bit>() ) {
1111  ITT_NOTIFY( sync_acquired, my_inbox.outbox() );
1112  result->prefix().extra_state |= es_task_is_stolen;
1113  return result;
1114  }
1115  // We have exclusive access to the proxy, and can destroy it.
1116  free_task<no_cache_small_task>(*tp);
1117  }
1118  return NULL;
1119 }
static const intptr_t mailbox_bit
Definition: mailbox.h:35
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
affinity_id my_affinity_id
The mailbox id assigned to this scheduler.
Definition: scheduler.h:84
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117
#define __TBB_ISOLATION_EXPR(isolation)
Set if the task has been stolen.
task_proxy * pop(__TBB_ISOLATION_EXPR(isolation_tag isolation))
Get next piece of mail, or NULL if mailbox is empty.
Definition: mailbox.h:206

References __TBB_ASSERT, __TBB_ISOLATION_EXPR, tbb::internal::es_task_is_stolen, ITT_NOTIFY, tbb::internal::task_proxy::mailbox_bit, tbb::internal::scheduler_state::my_affinity_id, tbb::internal::scheduler_state::my_inbox, and tbb::internal::mail_inbox::pop().

Here is the call graph for this function:

◆ get_task() [1/2]

task * tbb::internal::generic_scheduler::get_task ( __TBB_ISOLATION_EXPR(isolation_tag isolation)  )
inline

Get a task from the local pool.

Called only by the pool owner. Returns the pointer to the task or NULL if a suitable task is not found. Resets the pool if it is empty.

Definition at line 945 of file scheduler.cpp.

945  {
947  // The current task position in the task pool.
948  size_t T0 = __TBB_load_relaxed( my_arena_slot->tail );
949  // The bounds of available tasks in the task pool. H0 is only used when the head bound is reached.
950  size_t H0 = (size_t)-1, T = T0;
951  task* result = NULL;
952  bool task_pool_empty = false;
953  __TBB_ISOLATION_EXPR( bool tasks_omitted = false );
954  do {
955  __TBB_ASSERT( !result, NULL );
957  atomic_fence();
958  if ( (intptr_t)__TBB_load_relaxed( my_arena_slot->head ) > (intptr_t)T ) {
961  if ( (intptr_t)H0 > (intptr_t)T ) {
962  // The thief has not backed off - nothing to grab.
965  && H0 == T + 1, "victim/thief arbitration algorithm failure" );
967  // No tasks in the task pool.
968  task_pool_empty = true;
969  break;
970  } else if ( H0 == T ) {
971  // There is only one task in the task pool.
973  task_pool_empty = true;
974  } else {
975  // Release task pool if there are still some tasks.
976  // After the release, the tail will be less than T, thus a thief
977  // will not attempt to get a task at position T.
979  }
980  }
981  __TBB_control_consistency_helper(); // on my_arena_slot->head
982 #if __TBB_TASK_ISOLATION
983  result = get_task( T, isolation, tasks_omitted );
984  if ( result ) {
986  break;
987  } else if ( !tasks_omitted ) {
989  __TBB_ASSERT( T0 == T+1, NULL );
990  T0 = T;
991  }
992 #else
993  result = get_task( T );
994 #endif /* __TBB_TASK_ISOLATION */
995  } while ( !result && !task_pool_empty );
996 
997 #if __TBB_TASK_ISOLATION
998  if ( tasks_omitted ) {
999  if ( task_pool_empty ) {
1000  // All tasks have been checked. The task pool should be in reset state.
1001  // We just restore the bounds for the available tasks.
1002  // TODO: Does it have sense to move them to the beginning of the task pool?
1004  if ( result ) {
1005  // If we have a task, it should be at H0 position.
1006  __TBB_ASSERT( H0 == T, NULL );
1007  ++H0;
1008  }
1009  __TBB_ASSERT( H0 <= T0, NULL );
1010  if ( H0 < T0 ) {
1011  // Restore the task pool if there are some tasks.
1014  // The release fence is used in publish_task_pool.
1016  // Synchronize with snapshot as we published some tasks.
1018  }
1019  } else {
1020  // A task has been obtained. We need to make a hole in position T.
1022  __TBB_ASSERT( result, NULL );
1023  my_arena_slot->task_pool_ptr[T] = NULL;
1025  // Synchronize with snapshot as we published some tasks.
1026  // TODO: consider some approach not to call wakeup for each time. E.g. check if the tail reached the head.
1028  }
1029 
1030  // Now it is safe to call note_affinity because the task pool is restored.
1031  if ( my_innermost_running_task == result ) {
1032  assert_task_valid( result );
1033  result->note_affinity( my_affinity_id );
1034  }
1035  }
1036 #endif /* __TBB_TASK_ISOLATION */
1037  __TBB_ASSERT( (intptr_t)__TBB_load_relaxed( my_arena_slot->tail ) >= 0, NULL );
1038  __TBB_ASSERT( result || __TBB_ISOLATION_EXPR( tasks_omitted || ) is_quiescent_local_task_pool_reset(), NULL );
1039  return result;
1040 } // generic_scheduler::get_task
#define __TBB_control_consistency_helper()
Definition: gcc_generic.h:64
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void poison_pointer(T *__TBB_atomic &)
Definition: tbb_stddef.h:309
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
void __TBB_store_with_release(volatile T &location, V value)
Definition: tbb_machine.h:717
affinity_id my_affinity_id
The mailbox id assigned to this scheduler.
Definition: scheduler.h:84
task * get_task(__TBB_ISOLATION_EXPR(isolation_tag isolation))
Get a task from the local pool.
Definition: scheduler.cpp:945
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
bool is_quiescent_local_task_pool_reset() const
Definition: scheduler.h:541
void release_task_pool() const
Unlocks the local task pool.
Definition: scheduler.cpp:483
__TBB_atomic size_t head
Index of the first ready task in the deque.
#define __TBB_ISOLATION_EXPR(isolation)
void advertise_new_work()
If necessary, raise a flag that there is new job in arena.
Definition: arena.h:376
void acquire_task_pool() const
Locks the local task pool.
Definition: scheduler.cpp:454
void __TBB_store_relaxed(volatile T &location, V value)
Definition: tbb_machine.h:743
__TBB_atomic size_t tail
Index of the element following the last ready task in the deque.
void assert_task_valid(const task *)
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
void atomic_fence()
Sequentially consistent full memory fence.
Definition: tbb_machine.h:343
T __TBB_load_relaxed(const volatile T &location)
Definition: tbb_machine.h:739
void publish_task_pool()
Used by workers to enter the task pool.
Definition: scheduler.cpp:1121
void reset_task_pool_and_leave()
Resets head and tail indices to 0, and leaves task pool.
Definition: scheduler.h:599
task * my_innermost_running_task
Innermost task whose task::execute() is running. A dummy task on the outermost level.
Definition: scheduler.h:73

References __TBB_ASSERT, __TBB_control_consistency_helper, __TBB_ISOLATION_EXPR, tbb::internal::__TBB_load_relaxed(), tbb::internal::__TBB_store_relaxed(), tbb::internal::__TBB_store_with_release(), acquire_task_pool(), tbb::internal::arena::advertise_new_work(), tbb::internal::assert_task_valid(), tbb::atomic_fence(), tbb::internal::arena_slot_line1::head, is_quiescent_local_task_pool_reset(), is_task_pool_published(), tbb::internal::scheduler_state::my_affinity_id, tbb::internal::scheduler_state::my_arena, tbb::internal::scheduler_state::my_arena_slot, tbb::internal::scheduler_state::my_innermost_running_task, tbb::task::note_affinity(), tbb::internal::poison_pointer(), publish_task_pool(), release_task_pool(), reset_task_pool_and_leave(), tbb::internal::arena_slot_line2::tail, tbb::internal::arena_slot_line2::task_pool_ptr, and tbb::internal::arena::wakeup.

Here is the call graph for this function:

◆ get_task() [2/2]

task * tbb::internal::generic_scheduler::get_task ( size_t  T)
inline

Get a task from the local pool at specified location T.

Returns the pointer to the task or NULL if the task cannot be executed, e.g. proxy has been deallocated or isolation constraint is not met. tasks_omitted tells if some tasks have been omitted. Called only by the pool owner. The caller should guarantee that the position T is not available for a thief.

Definition at line 893 of file scheduler.cpp.

895 {
897  || is_local_task_pool_quiescent(), "Is it safe to get a task at position T?" );
898 
899  task* result = my_arena_slot->task_pool_ptr[T];
900  __TBB_ASSERT( !is_poisoned( result ), "The poisoned task is going to be processed" );
901 #if __TBB_TASK_ISOLATION
902  if ( !result )
903  return NULL;
904 
905  bool omit = isolation != no_isolation && isolation != result->prefix().isolation;
906  if ( !omit && !is_proxy( *result ) )
907  return result;
908  else if ( omit ) {
909  tasks_omitted = true;
910  return NULL;
911  }
912 #else
914  if ( !result || !is_proxy( *result ) )
915  return result;
916 #endif /* __TBB_TASK_ISOLATION */
917 
918  task_proxy& tp = static_cast<task_proxy&>(*result);
919  if ( task *t = tp.extract_task<task_proxy::pool_bit>() ) {
920  GATHER_STATISTIC( ++my_counters.proxies_executed );
921  // Following assertion should be true because TBB 2.0 tasks never specify affinity, and hence are not proxied.
922  __TBB_ASSERT( is_version_3_task( *t ), "backwards compatibility with TBB 2.0 broken" );
924  my_innermost_running_task = t; // prepare for calling note_affinity()
925 #if __TBB_TASK_ISOLATION
926  // Task affinity has changed. Postpone calling note_affinity because the task pool is in invalid state.
927  if ( !tasks_omitted )
928 #endif /* __TBB_TASK_ISOLATION */
929  {
931  t->note_affinity( my_affinity_id );
932  }
933  return t;
934  }
935 
936  // Proxy was empty, so it's our responsibility to free it
937  free_task<small_task>( tp );
938 #if __TBB_TASK_ISOLATION
939  if ( tasks_omitted )
940  my_arena_slot->task_pool_ptr[T] = NULL;
941 #endif /* __TBB_TASK_ISOLATION */
942  return NULL;
943 }
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void poison_pointer(T *__TBB_atomic &)
Definition: tbb_stddef.h:309
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
affinity_id my_affinity_id
The mailbox id assigned to this scheduler.
Definition: scheduler.h:84
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
bool is_local_task_pool_quiescent() const
Definition: scheduler.h:530
__TBB_atomic size_t tail
Index of the element following the last ready task in the deque.
T __TBB_load_relaxed(const volatile T &location)
Definition: tbb_machine.h:739
static bool is_proxy(const task &t)
True if t is a task_proxy.
Definition: scheduler.h:260
static bool is_version_3_task(task &t)
Definition: scheduler.h:124
const isolation_tag no_isolation
Definition: task.h:127
static const intptr_t pool_bit
Definition: mailbox.h:34
task * my_innermost_running_task
Innermost task whose task::execute() is running. A dummy task on the outermost level.
Definition: scheduler.h:73
#define GATHER_STATISTIC(x)

References __TBB_ASSERT, tbb::internal::__TBB_load_relaxed(), tbb::internal::task_proxy::extract_task(), GATHER_STATISTIC, tbb::internal::no_isolation, tbb::internal::poison_pointer(), tbb::internal::task_proxy::pool_bit, and tbb::task::prefix().

Here is the call graph for this function:

◆ init_stack_info()

void tbb::internal::generic_scheduler::init_stack_info ( )

Sets up the data necessary for the stealing limiting heuristics.

Definition at line 147 of file scheduler.cpp.

147  {
148  // Stacks are growing top-down. Highest address is called "stack base",
149  // and the lowest is "stack limit".
150  __TBB_ASSERT( !my_stealing_threshold, "Stealing threshold has already been calculated" );
151  size_t stack_size = my_market->worker_stack_size();
152 #if USE_WINTHREAD
153 #if defined(_MSC_VER)&&_MSC_VER<1400 && !_WIN64
154  NT_TIB *pteb;
155  __asm mov eax, fs:[0x18]
156  __asm mov pteb, eax
157 #else
158  NT_TIB *pteb = (NT_TIB*)NtCurrentTeb();
159 #endif
160  __TBB_ASSERT( &pteb < pteb->StackBase && &pteb > pteb->StackLimit, "invalid stack info in TEB" );
161  __TBB_ASSERT( stack_size >0, "stack_size not initialized?" );
162  // When a thread is created with the attribute STACK_SIZE_PARAM_IS_A_RESERVATION, stack limit
163  // in the TIB points to the committed part of the stack only. This renders the expression
164  // "(uintptr_t)pteb->StackBase / 2 + (uintptr_t)pteb->StackLimit / 2" virtually useless.
165  // Thus for worker threads we use the explicit stack size we used while creating them.
166  // And for master threads we rely on the following fact and assumption:
167  // - the default stack size of a master thread on Windows is 1M;
168  // - if it was explicitly set by the application it is at least as large as the size of a worker stack.
169  if ( is_worker() || stack_size < MByte )
170  my_stealing_threshold = (uintptr_t)pteb->StackBase - stack_size / 2;
171  else
172  my_stealing_threshold = (uintptr_t)pteb->StackBase - MByte / 2;
173 #else /* USE_PTHREAD */
174  // There is no portable way to get stack base address in Posix, so we use
175  // non-portable method (on all modern Linux) or the simplified approach
176  // based on the common sense assumptions. The most important assumption
177  // is that the main thread's stack size is not less than that of other threads.
178  // See also comment 3 at the end of this file
179  void *stack_base = &stack_size;
180 #if __linux__ && !__bg__
181 #if __TBB_ipf
182  void *rsb_base = __TBB_get_bsp();
183 #endif
184  size_t np_stack_size = 0;
185  void *stack_limit = NULL;
186  pthread_attr_t np_attr_stack;
187  if( 0 == pthread_getattr_np(pthread_self(), &np_attr_stack) ) {
188  if ( 0 == pthread_attr_getstack(&np_attr_stack, &stack_limit, &np_stack_size) ) {
189 #if __TBB_ipf
190  pthread_attr_t attr_stack;
191  if ( 0 == pthread_attr_init(&attr_stack) ) {
192  if ( 0 == pthread_attr_getstacksize(&attr_stack, &stack_size) ) {
193  if ( np_stack_size < stack_size ) {
194  // We are in a secondary thread. Use reliable data.
195  // IA-64 architecture stack is split into RSE backup and memory parts
196  rsb_base = stack_limit;
197  stack_size = np_stack_size/2;
198  // Limit of the memory part of the stack
199  stack_limit = (char*)stack_limit + stack_size;
200  }
201  // We are either in the main thread or this thread stack
202  // is bigger that that of the main one. As we cannot discern
203  // these cases we fall back to the default (heuristic) values.
204  }
205  pthread_attr_destroy(&attr_stack);
206  }
207  // IA-64 architecture stack is split into RSE backup and memory parts
208  my_rsb_stealing_threshold = (uintptr_t)((char*)rsb_base + stack_size/2);
209 #endif /* __TBB_ipf */
210  // Size of the stack free part
211  stack_size = size_t((char*)stack_base - (char*)stack_limit);
212  }
213  pthread_attr_destroy(&np_attr_stack);
214  }
215 #endif /* __linux__ */
216  __TBB_ASSERT( stack_size>0, "stack size must be positive" );
217  my_stealing_threshold = (uintptr_t)((char*)stack_base - stack_size/2);
218 #endif /* USE_PTHREAD */
219 }
uintptr_t my_stealing_threshold
Position in the call stack specifying its maximal filling when stealing is still allowed.
Definition: scheduler.h:129
void * __TBB_get_bsp()
Retrieves the current RSE backing store pointer. IA64 specific.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
market * my_market
The market I am in.
Definition: scheduler.h:146
const size_t MByte
Definition: tbb_misc.h:44
size_t worker_stack_size() const
Returns the requested stack size of worker threads.
Definition: market.h:298
bool is_worker() const
True if running on a worker thread, false otherwise.
Definition: scheduler.h:570

References __TBB_ASSERT, __TBB_get_bsp(), is_worker(), tbb::internal::MByte, my_market, my_stealing_threshold, and tbb::internal::market::worker_stack_size().

Here is the call graph for this function:

◆ is_local_task_pool_quiescent()

bool tbb::internal::generic_scheduler::is_local_task_pool_quiescent ( ) const
inline

Definition at line 530 of file scheduler.h.

530  {
532  task** tp = my_arena_slot->task_pool;
533  return tp == EmptyTaskPool || tp == LockedTaskPool;
534 }
#define LockedTaskPool
Definition: scheduler.h:47
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
#define EmptyTaskPool
Definition: scheduler.h:46

References __TBB_ASSERT, EmptyTaskPool, LockedTaskPool, tbb::internal::scheduler_state::my_arena_slot, and tbb::internal::arena_slot_line1::task_pool.

Referenced by commit_relocated_tasks(), is_quiescent_local_task_pool_empty(), and is_quiescent_local_task_pool_reset().

Here is the caller graph for this function:

◆ is_proxy()

static bool tbb::internal::generic_scheduler::is_proxy ( const task t)
inlinestatic

True if t is a task_proxy.

Definition at line 260 of file scheduler.h.

260  {
261  return t.prefix().extra_state==es_task_proxy;
262  }
Tag for v3 task_proxy.

References tbb::internal::es_task_proxy, and tbb::task::prefix().

Referenced by steal_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_quiescent_local_task_pool_empty()

bool tbb::internal::generic_scheduler::is_quiescent_local_task_pool_empty ( ) const
inline

Definition at line 536 of file scheduler.h.

536  {
537  __TBB_ASSERT( is_local_task_pool_quiescent(), "Task pool is not quiescent" );
539 }
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
__TBB_atomic size_t head
Index of the first ready task in the deque.
bool is_local_task_pool_quiescent() const
Definition: scheduler.h:530
__TBB_atomic size_t tail
Index of the element following the last ready task in the deque.
T __TBB_load_relaxed(const volatile T &location)
Definition: tbb_machine.h:739

References __TBB_ASSERT, tbb::internal::__TBB_load_relaxed(), tbb::internal::arena_slot_line1::head, is_local_task_pool_quiescent(), tbb::internal::scheduler_state::my_arena_slot, and tbb::internal::arena_slot_line2::tail.

Referenced by leave_task_pool().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_quiescent_local_task_pool_reset()

bool tbb::internal::generic_scheduler::is_quiescent_local_task_pool_reset ( ) const
inline

Definition at line 541 of file scheduler.h.

541  {
542  __TBB_ASSERT( is_local_task_pool_quiescent(), "Task pool is not quiescent" );
544 }
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
__TBB_atomic size_t head
Index of the first ready task in the deque.
bool is_local_task_pool_quiescent() const
Definition: scheduler.h:530
__TBB_atomic size_t tail
Index of the element following the last ready task in the deque.
T __TBB_load_relaxed(const volatile T &location)
Definition: tbb_machine.h:739

References __TBB_ASSERT, tbb::internal::__TBB_load_relaxed(), tbb::internal::arena_slot_line1::head, is_local_task_pool_quiescent(), tbb::internal::scheduler_state::my_arena_slot, and tbb::internal::arena_slot_line2::tail.

Referenced by get_task(), and prepare_task_pool().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_task_pool_published()

bool tbb::internal::generic_scheduler::is_task_pool_published ( ) const
inline

Definition at line 525 of file scheduler.h.

525  {
528 }
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
#define EmptyTaskPool
Definition: scheduler.h:46

References __TBB_ASSERT, EmptyTaskPool, tbb::internal::scheduler_state::my_arena_slot, and tbb::internal::arena_slot_line1::task_pool.

Referenced by acquire_task_pool(), cleanup_master(), get_task(), leave_task_pool(), local_spawn(), prepare_task_pool(), and release_task_pool().

Here is the caller graph for this function:

◆ is_version_3_task()

static bool tbb::internal::generic_scheduler::is_version_3_task ( task t)
inlinestatic

Definition at line 124 of file scheduler.h.

124  {
125  return (t.prefix().extra_state & 0x0F)>=0x1;
126  }

References tbb::task::prefix().

Referenced by prepare_for_spawning().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_worker()

bool tbb::internal::generic_scheduler::is_worker ( ) const
inline

True if running on a worker thread, false otherwise.

Definition at line 570 of file scheduler.h.

570  {
572 }
scheduler_properties my_properties
Definition: scheduler.h:86
bool type
Indicates that a scheduler acts as a master or a worker.
Definition: scheduler.h:54

References tbb::internal::scheduler_state::my_properties, tbb::internal::scheduler_properties::type, and tbb::internal::scheduler_properties::worker.

Referenced by tbb::internal::market::cleanup(), init_stack_info(), master_outermost_level(), nested_arena_entry(), nested_arena_exit(), and worker_outermost_level().

Here is the caller graph for this function:

◆ leave_task_pool()

void tbb::internal::generic_scheduler::leave_task_pool ( )
inline

Leave the task pool.

Leaving task pool automatically releases the task pool if it is locked.

Definition at line 1133 of file scheduler.cpp.

1133  {
1134  __TBB_ASSERT( is_task_pool_published(), "Not in arena" );
1135  // Do not reset my_arena_index. It will be used to (attempt to) re-acquire the slot next time
1136  __TBB_ASSERT( &my_arena->my_slots[my_arena_index] == my_arena_slot, "arena slot and slot index mismatch" );
1137  __TBB_ASSERT ( my_arena_slot->task_pool == LockedTaskPool, "Task pool must be locked when leaving arena" );
1138  __TBB_ASSERT ( is_quiescent_local_task_pool_empty(), "Cannot leave arena when the task pool is not empty" );
1140  // No release fence is necessary here as this assignment precludes external
1141  // accesses to the local task pool when becomes visible. Thus it is harmless
1142  // if it gets hoisted above preceding local bookkeeping manipulations.
1144 }
#define LockedTaskPool
Definition: scheduler.h:47
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p sync_releasing
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117
void __TBB_store_relaxed(volatile T &location, V value)
Definition: tbb_machine.h:743
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
size_t my_arena_index
Index of the arena slot the scheduler occupies now, or occupied last time.
Definition: scheduler.h:64
bool is_quiescent_local_task_pool_empty() const
Definition: scheduler.h:536
arena_slot my_slots[1]
Definition: arena.h:283
#define EmptyTaskPool
Definition: scheduler.h:46

References __TBB_ASSERT, tbb::internal::__TBB_store_relaxed(), EmptyTaskPool, is_quiescent_local_task_pool_empty(), is_task_pool_published(), ITT_NOTIFY, LockedTaskPool, tbb::internal::scheduler_state::my_arena, tbb::internal::scheduler_state::my_arena_index, tbb::internal::scheduler_state::my_arena_slot, tbb::internal::arena::my_slots, sync_releasing, and tbb::internal::arena_slot_line1::task_pool.

Referenced by cleanup_master(), and reset_task_pool_and_leave().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ local_spawn()

void tbb::internal::generic_scheduler::local_spawn ( task first,
task *&  next 
)

Conceptually, this method should be a member of class scheduler. But doing so would force us to publish class scheduler in the headers.

Definition at line 596 of file scheduler.cpp.

596  {
597  __TBB_ASSERT( first, NULL );
598  __TBB_ASSERT( governor::is_set(this), NULL );
599 #if __TBB_TODO
600  // We need to consider capping the max task pool size and switching
601  // to in-place task execution whenever it is reached.
602 #endif
603  if ( &first->prefix().next == &next ) {
604  // Single task is being spawned
605 #if __TBB_TODO
606  // TODO:
607  // In the future we need to add overloaded spawn method for a single task,
608  // and a method accepting an array of task pointers (we may also want to
609  // change the implementation of the task_list class). But since such changes
610  // may affect the binary compatibility, we postpone them for a while.
611 #endif
612  size_t T = prepare_task_pool( 1 );
614  commit_spawned_tasks( T + 1 );
615  }
616  else {
617  // Task list is being spawned
618 #if __TBB_TODO
619  // TODO: add task_list::front() and implement&document the local execution ordering which is
620  // opposite to the current implementation. The idea is to remove hackish fast_reverse_vector
621  // and use push_back/push_front when accordingly LIFO and FIFO order of local execution is
622  // desired. It also requires refactoring of the reload_tasks method and my_offloaded_tasks list.
623  // Additional benefit may come from adding counter to the task_list so that it can reserve enough
624  // space in the task pool in advance and move all the tasks directly without any intermediate
625  // storages. But it requires dealing with backward compatibility issues and still supporting
626  // counter-less variant (though not necessarily fast implementation).
627 #endif
628  task *arr[min_task_pool_size];
629  fast_reverse_vector<task*> tasks(arr, min_task_pool_size);
630  task *t_next = NULL;
631  for( task* t = first; ; t = t_next ) {
632  // If t is affinitized to another thread, it may already be executed
633  // and destroyed by the time prepare_for_spawning returns.
634  // So milk it while it is alive.
635  bool end = &t->prefix().next == &next;
636  t_next = t->prefix().next;
637  tasks.push_back( prepare_for_spawning(t) );
638  if( end )
639  break;
640  }
641  size_t num_tasks = tasks.size();
642  size_t T = prepare_task_pool( num_tasks );
643  tasks.copy_memory( my_arena_slot->task_pool_ptr + T );
644  commit_spawned_tasks( T + num_tasks );
645  }
646  if ( !is_task_pool_published() )
650 }
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
auto first(Container &c) -> decltype(begin(c))
task * prepare_for_spawning(task *t)
Checks if t is affinitized to another thread, and if so, bundles it as proxy.
Definition: scheduler.cpp:556
static const size_t min_task_pool_size
Definition: scheduler.h:269
void commit_spawned_tasks(size_t new_tail)
Makes newly spawned tasks visible to thieves.
Definition: scheduler.h:607
size_t prepare_task_pool(size_t n)
Makes sure that the task pool can accommodate at least n more elements.
Definition: scheduler.cpp:400
static bool is_set(generic_scheduler *s)
Used to check validity of the local scheduler TLS contents.
Definition: governor.cpp:124
void advertise_new_work()
If necessary, raise a flag that there is new job in arena.
Definition: arena.h:376
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp end
void publish_task_pool()
Used by workers to enter the task pool.
Definition: scheduler.cpp:1121

References __TBB_ASSERT, tbb::internal::arena::advertise_new_work(), assert_task_pool_valid(), commit_spawned_tasks(), tbb::internal::fast_reverse_vector< T, max_segments >::copy_memory(), end, tbb::internal::first(), tbb::internal::governor::is_set(), is_task_pool_published(), min_task_pool_size, tbb::internal::scheduler_state::my_arena, tbb::internal::scheduler_state::my_arena_slot, tbb::task::prefix(), prepare_for_spawning(), prepare_task_pool(), publish_task_pool(), tbb::internal::fast_reverse_vector< T, max_segments >::push_back(), tbb::internal::fast_reverse_vector< T, max_segments >::size(), tbb::internal::arena_slot_line2::task_pool_ptr, and tbb::internal::arena::work_spawned.

Referenced by local_spawn_root_and_wait(), spawn(), and tbb::internal::custom_scheduler< SchedulerTraits >::tally_completion_of_predecessor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ local_spawn_root_and_wait()

void tbb::internal::generic_scheduler::local_spawn_root_and_wait ( task first,
task *&  next 
)

Definition at line 652 of file scheduler.cpp.

652  {
653  __TBB_ASSERT( governor::is_set(this), NULL );
654  __TBB_ASSERT( first, NULL );
655  auto_empty_task dummy( __TBB_CONTEXT_ARG(this, first->prefix().context) );
657  for( task* t=first; ; t=t->prefix().next ) {
658  ++n;
659  __TBB_ASSERT( !t->prefix().parent, "not a root task, or already running" );
660  t->prefix().parent = &dummy;
661  if( &t->prefix().next==&next ) break;
662 #if __TBB_TASK_GROUP_CONTEXT
663  __TBB_ASSERT( t->prefix().context == t->prefix().next->prefix().context,
664  "all the root tasks in list must share the same context");
665 #endif /* __TBB_TASK_GROUP_CONTEXT */
666  }
667  dummy.prefix().ref_count = n+1;
668  if( n>1 )
669  local_spawn( first->prefix().next, next );
670  local_wait_for_all( dummy, first );
671 }
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
void local_spawn(task *first, task *&next)
Definition: scheduler.cpp:596
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
auto first(Container &c) -> decltype(begin(c))
static bool is_set(generic_scheduler *s)
Used to check validity of the local scheduler TLS contents.
Definition: governor.cpp:124
#define __TBB_CONTEXT_ARG(arg1, context)
virtual void local_wait_for_all(task &parent, task *child)=0
intptr_t reference_count
A reference count.
Definition: task.h:119

References __TBB_ASSERT, __TBB_CONTEXT_ARG, tbb::internal::first(), tbb::internal::governor::is_set(), local_spawn(), local_wait_for_all(), tbb::internal::auto_empty_task::prefix(), and tbb::internal::task_prefix::ref_count.

Referenced by spawn_root_and_wait().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ local_wait_for_all()

virtual void tbb::internal::generic_scheduler::local_wait_for_all ( task parent,
task child 
)
pure virtual

Implemented in tbb::internal::custom_scheduler< SchedulerTraits >.

Referenced by cleanup_master(), local_spawn_root_and_wait(), and wait_until_empty().

Here is the caller graph for this function:

◆ lock_task_pool()

task ** tbb::internal::generic_scheduler::lock_task_pool ( arena_slot victim_arena_slot) const
inline

Locks victim's task pool, and returns pointer to it. The pointer can be NULL.

Garbles victim_arena_slot->task_pool for the duration of the lock.

ATTENTION: This method is mostly the same as generic_scheduler::acquire_task_pool(), with a little different logic of slot state checks (slot can be empty, locked or point to any task pool other than ours, and asynchronous transitions between all these states are possible). Thus if any of them is changed, consider changing the counterpart as well

Definition at line 498 of file scheduler.cpp.

498  {
499  task** victim_task_pool;
500  bool sync_prepare_done = false;
501  for( atomic_backoff backoff;; /*backoff pause embedded in the loop*/) {
502  victim_task_pool = victim_arena_slot->task_pool;
503  // NOTE: Do not use comparison of head and tail indices to check for
504  // the presence of work in the victim's task pool, as they may give
505  // incorrect indication because of task pool relocations and resizes.
506  if ( victim_task_pool == EmptyTaskPool ) {
507  // The victim thread emptied its task pool - nothing to lock
508  if( sync_prepare_done )
509  ITT_NOTIFY(sync_cancel, victim_arena_slot);
510  break;
511  }
512  if( victim_task_pool != LockedTaskPool &&
513  as_atomic(victim_arena_slot->task_pool).compare_and_swap(LockedTaskPool, victim_task_pool ) == victim_task_pool )
514  {
515  // We've locked victim's task pool
516  ITT_NOTIFY(sync_acquired, victim_arena_slot);
517  break;
518  }
519  else if( !sync_prepare_done ) {
520  // Start waiting
521  ITT_NOTIFY(sync_prepare, victim_arena_slot);
522  sync_prepare_done = true;
523  }
524  GATHER_STATISTIC( ++my_counters.thieves_conflicts );
525  // Someone else acquired a lock, so pause and do exponential backoff.
526 #if __TBB_STEALING_ABORT_ON_CONTENTION
527  if(!backoff.bounded_pause()) {
528  // the 16 was acquired empirically and a theory behind it supposes
529  // that number of threads becomes much bigger than number of
530  // tasks which can be spawned by one thread causing excessive contention.
531  // TODO: However even small arenas can benefit from the abort on contention
532  // if preemption of a thief is a problem
533  if(my_arena->my_limit >= 16)
534  return EmptyTaskPool;
535  __TBB_Yield();
536  }
537 #else
538  backoff.pause();
539 #endif
540  }
541  __TBB_ASSERT( victim_task_pool == EmptyTaskPool ||
542  (victim_arena_slot->task_pool == LockedTaskPool && victim_task_pool != LockedTaskPool),
543  "not really locked victim's task pool?" );
544  return victim_task_pool;
545 } // generic_scheduler::lock_task_pool
#define LockedTaskPool
Definition: scheduler.h:47
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
atomic< T > & as_atomic(T &t)
Definition: atomic.h:547
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p sync_cancel
atomic< unsigned > my_limit
The maximal number of currently busy slots.
Definition: arena.h:65
#define __TBB_Yield()
Definition: ibm_aix51.h:48
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
#define EmptyTaskPool
Definition: scheduler.h:46
#define GATHER_STATISTIC(x)

References __TBB_ASSERT, __TBB_Yield, tbb::internal::as_atomic(), EmptyTaskPool, GATHER_STATISTIC, ITT_NOTIFY, LockedTaskPool, tbb::internal::scheduler_state::my_arena, tbb::internal::arena_base::my_limit, sync_cancel, and tbb::internal::arena_slot_line1::task_pool.

Referenced by steal_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ master_outermost_level()

bool tbb::internal::generic_scheduler::master_outermost_level ( ) const
inline

True if the scheduler is on the outermost dispatch level in a master thread.

Returns true when this scheduler instance is associated with an application thread, and is not executing any TBB task. This includes being in a TBB dispatch loop (one of wait_for_all methods) invoked directly from that thread.

Definition at line 550 of file scheduler.h.

550  {
551  return !is_worker() && outermost_level();
552 }
bool outermost_level() const
True if the scheduler is on the outermost dispatch level.
Definition: scheduler.h:546
bool is_worker() const
True if running on a worker thread, false otherwise.
Definition: scheduler.h:570

References is_worker(), and outermost_level().

Here is the call graph for this function:

◆ max_threads_in_arena()

unsigned tbb::internal::generic_scheduler::max_threads_in_arena ( )
inline

Returns the concurrency limit of the current arena.

Definition at line 574 of file scheduler.h.

574  {
575  __TBB_ASSERT(my_arena, NULL);
576  return my_arena->my_num_slots;
577 }
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
unsigned my_num_slots
The number of slots in the arena.
Definition: arena.h:136
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70

References __TBB_ASSERT, tbb::internal::scheduler_state::my_arena, and tbb::internal::arena_base::my_num_slots.

Referenced by tbb::internal::get_initial_auto_partitioner_divisor(), and tbb::internal::affinity_partitioner_base_v3::resize().

Here is the caller graph for this function:

◆ nested_arena_entry()

void tbb::internal::generic_scheduler::nested_arena_entry ( arena a,
size_t  slot_index 
)

Definition at line 631 of file arena.cpp.

631  {
632  __TBB_ASSERT( is_alive(a->my_guard), NULL );
633  __TBB_ASSERT( a!=my_arena, NULL);
634 
635  // overwrite arena settings
636 #if __TBB_TASK_PRIORITY
637  if ( my_offloaded_tasks )
638  my_arena->orphan_offloaded_tasks( *this );
639  my_offloaded_tasks = NULL;
640 #endif /* __TBB_TASK_PRIORITY */
641  attach_arena( a, slot_index, /*is_master*/true );
642  __TBB_ASSERT( my_arena == a, NULL );
644  // TODO? ITT_NOTIFY(sync_acquired, a->my_slots + index);
645  // TODO: it requires market to have P workers (not P-1)
646  // TODO: a preempted worker should be excluded from assignment to other arenas e.g. my_slack--
647  if( !is_worker() && slot_index >= my_arena->my_num_reserved_slots )
649 #if __TBB_ARENA_OBSERVER
650  my_last_local_observer = 0; // TODO: try optimize number of calls
651  my_arena->my_observers.notify_entry_observers( my_last_local_observer, /*worker=*/false );
652 #endif
653 }
market * my_market
The market that owns this arena.
Definition: arena.h:118
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void attach_arena(arena *, size_t index, bool is_master)
Definition: arena.cpp:40
void adjust_demand(arena &, int delta)
Request that arena's need in workers should be adjusted.
Definition: market.cpp:590
static void assume_scheduler(generic_scheduler *s)
Temporarily set TLS slot to the given scheduler.
Definition: governor.cpp:120
unsigned my_num_reserved_slots
The number of reserved slots (can be occupied only by masters).
Definition: arena.h:139
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
bool is_worker() const
True if running on a worker thread, false otherwise.
Definition: scheduler.h:570

References __TBB_ASSERT, tbb::internal::market::adjust_demand(), tbb::internal::governor::assume_scheduler(), attach_arena(), is_worker(), tbb::internal::scheduler_state::my_arena, tbb::internal::arena_base::my_market, and tbb::internal::arena_base::my_num_reserved_slots.

Here is the call graph for this function:

◆ nested_arena_exit()

void tbb::internal::generic_scheduler::nested_arena_exit ( )

Definition at line 655 of file arena.cpp.

655  {
656 #if __TBB_ARENA_OBSERVER
657  my_arena->my_observers.notify_exit_observers( my_last_local_observer, /*worker=*/false );
658 #endif /* __TBB_ARENA_OBSERVER */
659 #if __TBB_TASK_PRIORITY
660  if ( my_offloaded_tasks )
661  my_arena->orphan_offloaded_tasks( *this );
662 #endif
665  // Free the master slot.
666  __TBB_ASSERT(my_arena->my_slots[my_arena_index].my_scheduler, "A slot is already empty");
668  my_arena->my_exit_monitors.notify_one(); // do not relax!
669 }
void __TBB_store_with_release(volatile T &location, V value)
Definition: tbb_machine.h:717
market * my_market
The market that owns this arena.
Definition: arena.h:118
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void adjust_demand(arena &, int delta)
Request that arena's need in workers should be adjusted.
Definition: market.cpp:590
void notify_one()
Notify one thread about the event.
unsigned my_num_reserved_slots
The number of reserved slots (can be occupied only by masters).
Definition: arena.h:139
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
generic_scheduler * my_scheduler
Scheduler of the thread attached to the slot.
size_t my_arena_index
Index of the arena slot the scheduler occupies now, or occupied last time.
Definition: scheduler.h:64
bool is_worker() const
True if running on a worker thread, false otherwise.
Definition: scheduler.h:570
concurrent_monitor my_exit_monitors
Waiting object for master threads that cannot join the arena.
Definition: arena.h:154
arena_slot my_slots[1]
Definition: arena.h:283

References __TBB_ASSERT, tbb::internal::__TBB_store_with_release(), tbb::internal::market::adjust_demand(), is_worker(), tbb::internal::scheduler_state::my_arena, tbb::internal::scheduler_state::my_arena_index, tbb::internal::arena_base::my_exit_monitors, tbb::internal::arena_base::my_market, tbb::internal::arena_base::my_num_reserved_slots, tbb::internal::arena_slot_line1::my_scheduler, tbb::internal::arena::my_slots, and tbb::internal::concurrent_monitor::notify_one().

Referenced by tbb::internal::nested_arena_context::~nested_arena_context().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ outermost_level()

bool tbb::internal::generic_scheduler::outermost_level ( ) const
inline

True if the scheduler is on the outermost dispatch level.

Definition at line 546 of file scheduler.h.

546  {
547  return my_properties.outermost;
548 }
scheduler_properties my_properties
Definition: scheduler.h:86
bool outermost
Indicates that a scheduler is on outermost level.
Definition: scheduler.h:57

References tbb::internal::scheduler_state::my_properties, and tbb::internal::scheduler_properties::outermost.

Referenced by master_outermost_level(), and worker_outermost_level().

Here is the caller graph for this function:

◆ plugged_return_list()

static task* tbb::internal::generic_scheduler::plugged_return_list ( )
inlinestatic

Special value used to mark my_return_list as not taking any more entries.

Definition at line 355 of file scheduler.h.

355 {return (task*)(intptr_t)(-1);}
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task

Referenced by free_nonlocal_small_task(), and free_scheduler().

Here is the caller graph for this function:

◆ prepare_for_spawning()

task * tbb::internal::generic_scheduler::prepare_for_spawning ( task t)
inline

Checks if t is affinitized to another thread, and if so, bundles it as proxy.

Returns either t or proxy containing t.

Definition at line 556 of file scheduler.cpp.

556  {
557  __TBB_ASSERT( t->state()==task::allocated, "attempt to spawn task that is not in 'allocated' state" );
558  t->prefix().state = task::ready;
559 #if TBB_USE_ASSERT
560  if( task* parent = t->parent() ) {
561  internal::reference_count ref_count = parent->prefix().ref_count;
562  __TBB_ASSERT( ref_count>=0, "attempt to spawn task whose parent has a ref_count<0" );
563  __TBB_ASSERT( ref_count!=0, "attempt to spawn task whose parent has a ref_count==0 (forgot to set_ref_count?)" );
564  parent->prefix().extra_state |= es_ref_count_active;
565  }
566 #endif /* TBB_USE_ASSERT */
567  affinity_id dst_thread = t->prefix().affinity;
568  __TBB_ASSERT( dst_thread == 0 || is_version_3_task(*t),
569  "backwards compatibility to TBB 2.0 tasks is broken" );
570 #if __TBB_TASK_ISOLATION
571  isolation_tag isolation = my_innermost_running_task->prefix().isolation;
572  t->prefix().isolation = isolation;
573 #endif /* __TBB_TASK_ISOLATION */
574  if( dst_thread != 0 && dst_thread != my_affinity_id ) {
575  task_proxy& proxy = (task_proxy&)allocate_task( sizeof(task_proxy),
576  __TBB_CONTEXT_ARG(NULL, NULL) );
577  // Mark as a proxy
578  proxy.prefix().extra_state = es_task_proxy;
579  proxy.outbox = &my_arena->mailbox(dst_thread);
580  // Mark proxy as present in both locations (sender's task pool and destination mailbox)
581  proxy.task_and_tag = intptr_t(t) | task_proxy::location_mask;
582 #if __TBB_TASK_PRIORITY
583  poison_pointer( proxy.prefix().context );
584 #endif /* __TBB_TASK_PRIORITY */
585  __TBB_ISOLATION_EXPR( proxy.prefix().isolation = isolation );
586  ITT_NOTIFY( sync_releasing, proxy.outbox );
587  // Mail the proxy - after this point t may be destroyed by another thread at any moment.
588  proxy.outbox->push(&proxy);
589  return &proxy;
590  }
591  return t;
592 }
task object is freshly allocated or recycled.
Definition: task.h:604
void poison_pointer(T *__TBB_atomic &)
Definition: tbb_stddef.h:309
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
task & allocate_task(size_t number_of_bytes, __TBB_CONTEXT_ARG(task *parent, task_group_context *context))
Allocate task object, either from the heap or a free list.
Definition: scheduler.cpp:298
affinity_id my_affinity_id
The mailbox id assigned to this scheduler.
Definition: scheduler.h:84
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id parent
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p sync_releasing
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117
task is in ready pool, or is going to be put there, or was just taken off.
Definition: task.h:602
intptr_t isolation_tag
A tag for task isolation.
Definition: task.h:126
#define __TBB_ISOLATION_EXPR(isolation)
static const intptr_t location_mask
Definition: mailbox.h:36
#define __TBB_CONTEXT_ARG(arg1, context)
Set if ref_count might be changed by another thread. Used for debugging.
Tag for v3 task_proxy.
unsigned short affinity_id
An id as used for specifying affinity.
Definition: task.h:122
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
mail_outbox & mailbox(affinity_id id)
Get reference to mailbox corresponding to given affinity_id.
Definition: arena.h:191
internal::task_prefix & prefix(internal::version_tag *=NULL) const
Get reference to corresponding task_prefix.
Definition: task.h:920
intptr_t reference_count
A reference count.
Definition: task.h:119
static bool is_version_3_task(task &t)
Definition: scheduler.h:124
task * my_innermost_running_task
Innermost task whose task::execute() is running. A dummy task on the outermost level.
Definition: scheduler.h:73

References __TBB_ASSERT, __TBB_CONTEXT_ARG, __TBB_ISOLATION_EXPR, allocate_task(), tbb::task::allocated, tbb::task::context(), tbb::internal::es_ref_count_active, tbb::internal::es_task_proxy, is_version_3_task(), ITT_NOTIFY, tbb::internal::task_proxy::location_mask, tbb::internal::arena::mailbox(), tbb::internal::scheduler_state::my_affinity_id, tbb::internal::scheduler_state::my_arena, tbb::internal::scheduler_state::my_innermost_running_task, tbb::internal::task_proxy::outbox, parent, tbb::task::parent(), tbb::internal::poison_pointer(), tbb::task::prefix(), tbb::internal::mail_outbox::push(), tbb::task::ready, tbb::task::state(), sync_releasing, and tbb::internal::task_proxy::task_and_tag.

Referenced by local_spawn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ prepare_task_pool()

size_t tbb::internal::generic_scheduler::prepare_task_pool ( size_t  n)
inline

Makes sure that the task pool can accommodate at least n more elements.

If necessary relocates existing task pointers or grows the ready task deque. Returns (possible updated) tail index (not accounting for n).

Definition at line 400 of file scheduler.cpp.

400  {
401  size_t T = __TBB_load_relaxed(my_arena_slot->tail); // mirror
402  if ( T + num_tasks <= my_arena_slot->my_task_pool_size )
403  return T;
404 
405  size_t new_size = num_tasks;
406 
410  if ( num_tasks < min_task_pool_size ) new_size = min_task_pool_size;
412  return 0;
413  }
414 
416  size_t H = __TBB_load_relaxed( my_arena_slot->head ); // mirror
417  task** task_pool = my_arena_slot->task_pool_ptr;;
419  // Count not skipped tasks. Consider using std::count_if.
420  for ( size_t i = H; i < T; ++i )
421  if ( task_pool[i] ) ++new_size;
422  // If the free space at the beginning of the task pool is too short, we
423  // are likely facing a pathological single-producer-multiple-consumers
424  // scenario, and thus it's better to expand the task pool
426  if ( allocate ) {
427  // Grow task pool. As this operation is rare, and its cost is asymptotically
428  // amortizable, we can tolerate new task pool allocation done under the lock.
429  if ( new_size < 2 * my_arena_slot->my_task_pool_size )
431  my_arena_slot->allocate_task_pool( new_size ); // updates my_task_pool_size
432  }
433  // Filter out skipped tasks. Consider using std::copy_if.
434  size_t T1 = 0;
435  for ( size_t i = H; i < T; ++i )
436  if ( task_pool[i] )
437  my_arena_slot->task_pool_ptr[T1++] = task_pool[i];
438  // Deallocate the previous task pool if a new one has been allocated.
439  if ( allocate )
440  NFS_Free( task_pool );
441  else
443  // Publish the new state.
446  return T1;
447 }
void allocate_task_pool(size_t n)
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
void fill_with_canary_pattern(size_t, size_t)
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
static const size_t min_task_pool_size
Definition: scheduler.h:269
size_t my_task_pool_size
Capacity of the primary task pool (number of elements - pointers to task).
bool is_quiescent_local_task_pool_reset() const
Definition: scheduler.h:541
__TBB_atomic size_t head
Index of the first ready task in the deque.
void acquire_task_pool() const
Locks the local task pool.
Definition: scheduler.cpp:454
__TBB_atomic size_t tail
Index of the element following the last ready task in the deque.
void commit_relocated_tasks(size_t new_tail)
Makes relocated tasks visible to thieves and releases the local task pool.
Definition: scheduler.h:616
void __TBB_EXPORTED_FUNC NFS_Free(void *)
Free memory allocated by NFS_Allocate.
T __TBB_load_relaxed(const volatile T &location)
Definition: tbb_machine.h:739
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t new_size

References __TBB_ASSERT, tbb::internal::__TBB_load_relaxed(), acquire_task_pool(), tbb::internal::arena_slot::allocate_task_pool(), assert_task_pool_valid(), commit_relocated_tasks(), tbb::internal::arena_slot::fill_with_canary_pattern(), tbb::internal::arena_slot_line1::head, is_quiescent_local_task_pool_reset(), is_task_pool_published(), min_task_pool_size, tbb::internal::scheduler_state::my_arena_slot, tbb::internal::arena_slot_line2::my_task_pool_size, new_size, tbb::internal::NFS_Free(), tbb::internal::arena_slot_line2::tail, and tbb::internal::arena_slot_line2::task_pool_ptr.

Referenced by local_spawn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ publish_task_pool()

void tbb::internal::generic_scheduler::publish_task_pool ( )
inline

Used by workers to enter the task pool.

Does not lock the task pool in case if arena slot has been successfully grabbed.

Definition at line 1121 of file scheduler.cpp.

1121  {
1122  __TBB_ASSERT ( my_arena, "no arena: initialization not completed?" );
1123  __TBB_ASSERT ( my_arena_index < my_arena->my_num_slots, "arena slot index is out-of-bound" );
1125  __TBB_ASSERT ( my_arena_slot->task_pool == EmptyTaskPool, "someone else grabbed my arena slot?" );
1127  "entering arena without tasks to share" );
1128  // Release signal on behalf of previously spawned tasks (when this thread was not in arena yet)
1131 }
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void __TBB_store_with_release(volatile T &location, V value)
Definition: tbb_machine.h:717
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p sync_releasing
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117
__TBB_atomic size_t head
Index of the first ready task in the deque.
__TBB_atomic size_t tail
Index of the element following the last ready task in the deque.
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
T __TBB_load_relaxed(const volatile T &location)
Definition: tbb_machine.h:739
size_t my_arena_index
Index of the arena slot the scheduler occupies now, or occupied last time.
Definition: scheduler.h:64
arena_slot my_slots[1]
Definition: arena.h:283
#define EmptyTaskPool
Definition: scheduler.h:46

References __TBB_ASSERT, tbb::internal::__TBB_load_relaxed(), tbb::internal::__TBB_store_with_release(), EmptyTaskPool, tbb::internal::arena_slot_line1::head, ITT_NOTIFY, tbb::internal::scheduler_state::my_arena, tbb::internal::scheduler_state::my_arena_index, tbb::internal::scheduler_state::my_arena_slot, tbb::internal::arena::my_slots, sync_releasing, tbb::internal::arena_slot_line2::tail, tbb::internal::arena_slot_line1::task_pool, and tbb::internal::arena_slot_line2::task_pool_ptr.

Referenced by get_task(), and local_spawn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ receive_or_steal_task()

virtual task* tbb::internal::generic_scheduler::receive_or_steal_task ( __TBB_ISOLATION_ARG(__TBB_atomic reference_count &completion_ref_count, isolation_tag isolation)  )
pure virtual

Try getting a task from other threads (via mailbox, stealing, FIFO queue, orphans adoption).

Returns obtained task or NULL if all attempts fail.

Implemented in tbb::internal::custom_scheduler< SchedulerTraits >.

◆ release_task_pool()

void tbb::internal::generic_scheduler::release_task_pool ( ) const
inline

Unlocks the local task pool.

Restores my_arena_slot->task_pool munged by acquire_task_pool. Requires correctly set my_arena_slot->task_pool_ptr.

Definition at line 483 of file scheduler.cpp.

483  {
484  if ( !is_task_pool_published() )
485  return; // we are not in arena - nothing to unlock
486  __TBB_ASSERT( my_arena_slot, "we are not in arena" );
487  __TBB_ASSERT( my_arena_slot->task_pool == LockedTaskPool, "arena slot is not locked" );
490 }
#define LockedTaskPool
Definition: scheduler.h:47
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
void __TBB_store_with_release(volatile T &location, V value)
Definition: tbb_machine.h:717
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p sync_releasing
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117

References __TBB_ASSERT, tbb::internal::__TBB_store_with_release(), is_task_pool_published(), ITT_NOTIFY, LockedTaskPool, tbb::internal::scheduler_state::my_arena_slot, sync_releasing, tbb::internal::arena_slot_line1::task_pool, and tbb::internal::arena_slot_line2::task_pool_ptr.

Referenced by cleanup_master(), commit_relocated_tasks(), and get_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_task_pool_and_leave()

void tbb::internal::generic_scheduler::reset_task_pool_and_leave ( )
inline

Resets head and tail indices to 0, and leaves task pool.

The task pool must be locked by the owner (via acquire_task_pool).

Definition at line 599 of file scheduler.h.

599  {
600  __TBB_ASSERT( my_arena_slot->task_pool == LockedTaskPool, "Task pool must be locked when resetting task pool" );
603  leave_task_pool();
604 }
#define LockedTaskPool
Definition: scheduler.h:47
arena_slot * my_arena_slot
Pointer to the slot in the arena we own at the moment.
Definition: scheduler.h:67
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
__TBB_atomic size_t head
Index of the first ready task in the deque.
void __TBB_store_relaxed(volatile T &location, V value)
Definition: tbb_machine.h:743
__TBB_atomic size_t tail
Index of the element following the last ready task in the deque.
void leave_task_pool()
Leave the task pool.
Definition: scheduler.cpp:1133

References __TBB_ASSERT, tbb::internal::__TBB_store_relaxed(), tbb::internal::arena_slot_line1::head, leave_task_pool(), LockedTaskPool, tbb::internal::scheduler_state::my_arena_slot, tbb::internal::arena_slot_line2::tail, and tbb::internal::arena_slot_line1::task_pool.

Referenced by get_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ spawn()

void tbb::internal::generic_scheduler::spawn ( task first,
task *&  next 
)
virtual

For internal use only.

Implements tbb::internal::scheduler.

Definition at line 673 of file scheduler.cpp.

673  {
675 }
void local_spawn(task *first, task *&next)
Definition: scheduler.cpp:596
auto first(Container &c) -> decltype(begin(c))
static generic_scheduler * local_scheduler()
Obtain the thread-local instance of the TBB scheduler.
Definition: governor.h:126

References tbb::internal::first(), tbb::internal::governor::local_scheduler(), and local_spawn().

Here is the call graph for this function:

◆ spawn_root_and_wait()

void tbb::internal::generic_scheduler::spawn_root_and_wait ( task first,
task *&  next 
)
virtual

For internal use only.

Implements tbb::internal::scheduler.

Definition at line 677 of file scheduler.cpp.

677  {
679 }
auto first(Container &c) -> decltype(begin(c))
void local_spawn_root_and_wait(task *first, task *&next)
Definition: scheduler.cpp:652
static generic_scheduler * local_scheduler()
Obtain the thread-local instance of the TBB scheduler.
Definition: governor.h:126

References tbb::internal::first(), tbb::internal::governor::local_scheduler(), and local_spawn_root_and_wait().

Here is the call graph for this function:

◆ steal_task()

task * tbb::internal::generic_scheduler::steal_task ( __TBB_ISOLATION_ARG(arena_slot &victim_arena_slot, isolation_tag isolation)  )

Steal task from another scheduler's ready pool.

Definition at line 1042 of file scheduler.cpp.

1042  {
1043  task** victim_pool = lock_task_pool( &victim_slot );
1044  if ( !victim_pool )
1045  return NULL;
1046  task* result = NULL;
1047  size_t H = __TBB_load_relaxed(victim_slot.head); // mirror
1048  size_t H0 = H;
1049  bool tasks_omitted = false;
1050  do {
1051  __TBB_store_relaxed( victim_slot.head, ++H );
1052  atomic_fence();
1053  if ( (intptr_t)H > (intptr_t)__TBB_load_relaxed( victim_slot.tail ) ) {
1054  // Stealing attempt failed, deque contents has not been changed by us
1055  GATHER_STATISTIC( ++my_counters.thief_backoffs );
1056  __TBB_store_relaxed( victim_slot.head, /*dead: H = */ H0 );
1057  __TBB_ASSERT( !result, NULL );
1058  goto unlock;
1059  }
1060  __TBB_control_consistency_helper(); // on victim_slot.tail
1061  result = victim_pool[H-1];
1062  __TBB_ASSERT( !is_poisoned( result ), NULL );
1063 
1064  if ( result ) {
1065  __TBB_ISOLATION_EXPR( if ( isolation == no_isolation || isolation == result->prefix().isolation ) )
1066  {
1067  if ( !is_proxy( *result ) )
1068  break;
1069  task_proxy& tp = *static_cast<task_proxy*>(result);
1070  // If mailed task is likely to be grabbed by its destination thread, skip it.
1071  if ( !(task_proxy::is_shared( tp.task_and_tag ) && tp.outbox->recipient_is_idle()) )
1072  break;
1073  GATHER_STATISTIC( ++my_counters.proxies_bypassed );
1074  }
1075  // The task cannot be executed either due to isolation or proxy contraints.
1076  result = NULL;
1077  tasks_omitted = true;
1078  } else if ( !tasks_omitted ) {
1079  // Cleanup the task pool from holes until a task is skipped.
1080  __TBB_ASSERT( H0 == H-1, NULL );
1081  poison_pointer( victim_pool[H0] );
1082  H0 = H;
1083  }
1084  } while ( !result );
1085  __TBB_ASSERT( result, NULL );
1086 
1087  // emit "task was consumed" signal
1088  ITT_NOTIFY( sync_acquired, (void*)((uintptr_t)&victim_slot+sizeof( uintptr_t )) );
1089  poison_pointer( victim_pool[H-1] );
1090  if ( tasks_omitted ) {
1091  // Some proxies in the task pool have been omitted. Set the stolen task to NULL.
1092  victim_pool[H-1] = NULL;
1093  __TBB_store_relaxed( victim_slot.head, /*dead: H = */ H0 );
1094  }
1095 unlock:
1096  unlock_task_pool( &victim_slot, victim_pool );
1097 #if __TBB_PREFETCHING
1098  __TBB_cl_evict(&victim_slot.head);
1099  __TBB_cl_evict(&victim_slot.tail);
1100 #endif
1101  if ( tasks_omitted )
1102  // Synchronize with snapshot as the head and tail can be bumped which can falsely trigger EMPTY state
1104  return result;
1105 }
#define __TBB_control_consistency_helper()
Definition: gcc_generic.h:64
void poison_pointer(T *__TBB_atomic &)
Definition: tbb_stddef.h:309
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
static bool is_shared(intptr_t tat)
True if the proxy is stored both in its sender's pool and in the destination mailbox.
Definition: mailbox.h:50
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117
#define __TBB_cl_evict(p)
Definition: mic_common.h:38
task ** lock_task_pool(arena_slot *victim_arena_slot) const
Locks victim's task pool, and returns pointer to it. The pointer can be NULL.
Definition: scheduler.cpp:498
#define __TBB_ISOLATION_EXPR(isolation)
void advertise_new_work()
If necessary, raise a flag that there is new job in arena.
Definition: arena.h:376
void __TBB_store_relaxed(volatile T &location, V value)
Definition: tbb_machine.h:743
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
void atomic_fence()
Sequentially consistent full memory fence.
Definition: tbb_machine.h:343
T __TBB_load_relaxed(const volatile T &location)
Definition: tbb_machine.h:739
static bool is_proxy(const task &t)
True if t is a task_proxy.
Definition: scheduler.h:260
void unlock_task_pool(arena_slot *victim_arena_slot, task **victim_task_pool) const
Unlocks victim's task pool.
Definition: scheduler.cpp:547
const isolation_tag no_isolation
Definition: task.h:127
#define GATHER_STATISTIC(x)

References __TBB_ASSERT, __TBB_cl_evict, __TBB_control_consistency_helper, __TBB_ISOLATION_EXPR, tbb::internal::__TBB_load_relaxed(), tbb::internal::__TBB_store_relaxed(), tbb::internal::arena::advertise_new_work(), tbb::atomic_fence(), GATHER_STATISTIC, tbb::internal::arena_slot_line1::head, is_proxy(), tbb::internal::task_proxy::is_shared(), ITT_NOTIFY, lock_task_pool(), tbb::internal::scheduler_state::my_arena, tbb::internal::no_isolation, tbb::internal::task_proxy::outbox, tbb::internal::poison_pointer(), tbb::task::prefix(), tbb::internal::mail_outbox::recipient_is_idle(), tbb::internal::arena_slot_line2::tail, tbb::internal::task_proxy::task_and_tag, unlock_task_pool(), and tbb::internal::arena::wakeup.

Here is the call graph for this function:

◆ unlock_task_pool()

void tbb::internal::generic_scheduler::unlock_task_pool ( arena_slot victim_arena_slot,
task **  victim_task_pool 
) const
inline

Unlocks victim's task pool.

Restores victim_arena_slot->task_pool munged by lock_task_pool.

Definition at line 547 of file scheduler.cpp.

548  {
549  __TBB_ASSERT( victim_arena_slot, "empty victim arena slot pointer" );
550  __TBB_ASSERT( victim_arena_slot->task_pool == LockedTaskPool, "victim arena slot is not locked" );
551  ITT_NOTIFY(sync_releasing, victim_arena_slot);
552  __TBB_store_with_release( victim_arena_slot->task_pool, victim_task_pool );
553 }
#define LockedTaskPool
Definition: scheduler.h:47
void __TBB_store_with_release(volatile T &location, V value)
Definition: tbb_machine.h:717
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p sync_releasing
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:117

References __TBB_ASSERT, tbb::internal::__TBB_store_with_release(), ITT_NOTIFY, LockedTaskPool, sync_releasing, and tbb::internal::arena_slot_line1::task_pool.

Referenced by steal_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_until_empty()

void tbb::internal::generic_scheduler::wait_until_empty ( )

Definition at line 671 of file arena.cpp.

671  {
672  my_dummy_task->prefix().ref_count++; // prevents exit from local_wait_for_all when local work is done enforcing the stealing
675  my_dummy_task->prefix().ref_count--;
676 }
task * my_dummy_task
Fake root task created by slave threads.
Definition: scheduler.h:160
static const pool_state_t SNAPSHOT_EMPTY
No tasks to steal since last snapshot was taken.
Definition: arena.h:204
virtual void local_wait_for_all(task &parent, task *child)=0
arena * my_arena
The arena that I own (if master) or am servicing at the moment (if worker)
Definition: scheduler.h:70
tbb::atomic< uintptr_t > my_pool_state
Current task pool state and estimate of available tasks amount.
Definition: arena.h:86
internal::task_prefix & prefix(internal::version_tag *=NULL) const
Get reference to corresponding task_prefix.
Definition: task.h:920

References local_wait_for_all(), tbb::internal::scheduler_state::my_arena, my_dummy_task, tbb::internal::arena_base::my_pool_state, tbb::task::prefix(), and tbb::internal::arena::SNAPSHOT_EMPTY.

Here is the call graph for this function:

◆ worker_outermost_level()

bool tbb::internal::generic_scheduler::worker_outermost_level ( ) const
inline

True if the scheduler is on the outermost dispatch level in a worker thread.

Definition at line 554 of file scheduler.h.

554  {
555  return is_worker() && outermost_level();
556 }
bool outermost_level() const
True if the scheduler is on the outermost dispatch level.
Definition: scheduler.h:546
bool is_worker() const
True if running on a worker thread, false otherwise.
Definition: scheduler.h:570

References is_worker(), and outermost_level().

Here is the call graph for this function:

Friends And Related Function Documentation

◆ custom_scheduler

template<typename SchedulerTraits >
friend class custom_scheduler
friend

Definition at line 289 of file scheduler.h.

Member Data Documentation

◆ min_task_pool_size

const size_t tbb::internal::generic_scheduler::min_task_pool_size = 64
static

Initial size of the task deque sufficient to serve without reallocation 4 nested parallel_for calls with iteration space of 65535 grains each.

Definition at line 269 of file scheduler.h.

Referenced by local_spawn(), and prepare_task_pool().

◆ my_auto_initialized

bool tbb::internal::generic_scheduler::my_auto_initialized

True if *this was created by automatic TBB initialization.

Definition at line 171 of file scheduler.h.

◆ my_dummy_task

task* tbb::internal::generic_scheduler::my_dummy_task

Fake root task created by slave threads.

The task is used as the "parent" argument to method wait_for_all.

Definition at line 160 of file scheduler.h.

Referenced by attach_arena(), cleanup_master(), free_scheduler(), generic_scheduler(), tbb::internal::nested_arena_context::mimic_outermost_level(), wait_until_empty(), and tbb::internal::nested_arena_context::~nested_arena_context().

◆ my_free_list

task* tbb::internal::generic_scheduler::my_free_list

Free list of small tasks that can be reused.

Definition at line 152 of file scheduler.h.

Referenced by allocate_task(), free_scheduler(), and free_task().

◆ my_market

market* tbb::internal::generic_scheduler::my_market

The market I am in.

Definition at line 146 of file scheduler.h.

Referenced by attach_arena(), cleanup_master(), free_scheduler(), and init_stack_info().

◆ my_random

FastRandom tbb::internal::generic_scheduler::my_random

Random number generator used for picking a random victim from which to steal.

Definition at line 149 of file scheduler.h.

Referenced by tbb::internal::custom_scheduler< SchedulerTraits >::tally_completion_of_predecessor().

◆ my_ref_count

long tbb::internal::generic_scheduler::my_ref_count

Reference count for scheduler.

Number of task_scheduler_init objects that point to this scheduler

Definition at line 164 of file scheduler.h.

◆ my_return_list

task* tbb::internal::generic_scheduler::my_return_list

List of small tasks that have been returned to this scheduler by other schedulers.

Definition at line 362 of file scheduler.h.

Referenced by allocate_task(), free_scheduler(), and generic_scheduler().

◆ my_small_task_count

__TBB_atomic intptr_t tbb::internal::generic_scheduler::my_small_task_count

Number of small tasks that have been allocated by this scheduler.

Definition at line 358 of file scheduler.h.

Referenced by allocate_task(), and free_scheduler().

◆ my_stealing_threshold

uintptr_t tbb::internal::generic_scheduler::my_stealing_threshold

Position in the call stack specifying its maximal filling when stealing is still allowed.

Definition at line 129 of file scheduler.h.

Referenced by can_steal(), and init_stack_info().

◆ null_arena_index

const size_t tbb::internal::generic_scheduler::null_arena_index = ~size_t(0)
static

Definition at line 135 of file scheduler.h.

◆ quick_task_size

const size_t tbb::internal::generic_scheduler::quick_task_size = 256-task_prefix_reservation_size
static

If sizeof(task) is <=quick_task_size, it is handled on a free list instead of malloc'd.

Definition at line 122 of file scheduler.h.

Referenced by allocate_task().


The documentation for this class was generated from the following files:

Copyright © 2005-2018 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.