Scheduler::PhysicalTaskPtr Scheduler::take_runnable_task(const Locality &locality){ const auto tid = locality.self_thread_id(); PhysicalTaskPtr task; // try to take an unstealable task task = take_unstealable_task(locality); if(task){ return task; } // try to take a local stealable task task = take_local_stealable_task(locality); if(task){ return task; } // try to steal an task task = steal_task(locality); if(task){ return task; } // attempt to sleep auto &sync = m_synchronizers[tid]; while(true){ sync.set_is_sleeping(); if(task || is_finished() || is_cancelled()){ break; } // try to take an unstealable task task = take_unstealable_task(locality); if(task){ break; } // try to steal an task task = steal_task(locality); if(task){ break; } // wait for new task sync.wait(); } sync.reset_is_sleeping(); return task; }
void run_core(std::size_t core_id) { task_pack<TASK> tmp_task; while(cores_[core_id].running) { if(cores_[core_id].queue_size() > 0) { // Still has unfinished tasks. cores_[core_id].execute(this); } else if(can_steal()) { // Steal from other cores (at random). try { tmp_task = steal_task(); } catch(...) { // The queue got emptied before steal_task() could // finnish. cores_[core_id].running = false; break; } cores_[core_id].add_task(std::move(tmp_task)); cores_[core_id].execute(this); } else { // No task in the entire schedulet that could be run // by this core. cores_[core_id].running = false; } } }
/** Steal work from another worker's task stack */ static int steal(struct generic_task_desc * _tweed_top_, struct worker_desc * victim) { struct generic_task_desc * stolenTask; struct worker_desc * me = (struct worker_desc *) thread_get_tls(); LOCK(victim->lock); stolenTask = victim->bot; // check if there is actually work to steal if (stolenTask != NULL && stolenTask->balarm == TWEED_TASK_NEW) { // try to steal task tweed_task_func_t func = steal_task(stolenTask, me); if (func == NULL) { // we didn't succeed in the steal, back off #ifndef TWEED_USE_CAS stolenTask->balarm = TWEED_TASK_INLINED; stolenTask->thief = NULL; #endif UNLOCK(victim->lock); return 0; // didn't steal anything } else { // we have stolen the task, update bot atomic_inc(&(victim->bot), stolenTask->size); UNLOCK(victim->lock); // and run task trace_event(TRACE_SUBSYS_TWEED, TRACE_EVENT_TWEED_STEAL, victim->core_id); func(_tweed_top_, stolenTask); trace_event(TRACE_SUBSYS_TWEED, TRACE_EVENT_TWEED_STEAL_END, victim->core_id); // signal task completion stolenTask->balarm |= TWEED_TASK_COMPLETE; return 1; } } else { UNLOCK(victim->lock); return 0; // didn't steal anything } }