void fiber_scheduler_load_balance(fiber_scheduler_t* sched) { fiber_scheduler_wsd_t* const scheduler = (fiber_scheduler_wsd_t*)sched; size_t max_steal = 50; size_t i = 2 * (scheduler->id + 1); const size_t end = i + 2 * (fiber_scheduler_num_threads - 1); const size_t mod = 2 * fiber_scheduler_num_threads; size_t local_count = wsd_work_stealing_deque_size(scheduler->schedule_from); for(; i < end; ++i) { const size_t index = i % mod; wsd_work_stealing_deque_t* const remote_queue = fiber_scheduler_thread_queues[index]; assert(remote_queue != scheduler->queue_one); assert(remote_queue != scheduler->queue_two); if(!remote_queue) { continue; } size_t remote_count = wsd_work_stealing_deque_size(remote_queue); while(remote_count > local_count && max_steal > 0) { fiber_t* const stolen = (fiber_t*)wsd_work_stealing_deque_steal(remote_queue); if(stolen == WSD_EMPTY || stolen == WSD_ABORT) { ++scheduler->failed_steal_count; break; } wsd_work_stealing_deque_push_bottom(scheduler->schedule_from, stolen); --remote_count; ++local_count; --max_steal; ++scheduler->steal_count; } } }
static int fiber_load_balance(fiber_manager_t* manager) { size_t i = 2 * (manager->id + 1); const size_t end = i + 2 * (fiber_manager_num_threads - 1); const size_t mod = 2 * fiber_manager_num_threads; size_t local_count = wsd_work_stealing_deque_size(manager->schedule_from); for(; i < end; ++i) { const size_t index = i % mod; wsd_work_stealing_deque_t* const remote_queue = fiber_mananger_thread_queues[index]; assert(remote_queue != manager->queue_one); assert(remote_queue != manager->queue_two); if(!remote_queue) { continue; } size_t remote_count = wsd_work_stealing_deque_size(remote_queue); while(remote_count > local_count) { fiber_t* const stolen = (fiber_t*)wsd_work_stealing_deque_steal(remote_queue); if(stolen == WSD_EMPTY || stolen == WSD_ABORT) { break; } assert(stolen->state == FIBER_STATE_READY); wsd_work_stealing_deque_push_bottom(manager->schedule_from, stolen); --remote_count; ++local_count; } } return 1; }
void* run_func(void* p) { intptr_t threadId = (intptr_t)p; while(!done) { void* ret = wsd_work_stealing_deque_steal(wsd_d2); if(ret != WSD_EMPTY && ret != WSD_ABORT) { __sync_add_and_fetch(&results[threadId][(intptr_t)ret], 1); __sync_add_and_fetch(&total, (intptr_t)ret); ++run_func_count[threadId]; } } return NULL; }