From 261dafa924283850e92c435cc220935b51d4e4a9 Mon Sep 17 00:00:00 2001 From: Pixelflinger Date: Fri, 19 Jul 2019 00:20:01 -0700 Subject: [PATCH] Fix a possible infinite loop In the case where we have 2 cores, we would spawn only one thread in the thread pool. If that thread got to try to steal() from another thread before the main thread was adopted, it would end-up always trying to steal from itself and enter an infinite loop. This seems to happen during windows builds. --- libs/utils/src/JobSystem.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libs/utils/src/JobSystem.cpp b/libs/utils/src/JobSystem.cpp index 12b4240efa..36f595ec51 100644 --- a/libs/utils/src/JobSystem.cpp +++ b/libs/utils/src/JobSystem.cpp @@ -243,13 +243,17 @@ inline JobSystem::ThreadState* JobSystem::getStateToStealFrom(JobSystem::ThreadS uint16_t const threadCount = mThreadCount + adopted; JobSystem::ThreadState* stateToStealFrom = nullptr; - do { - // this is biased, but frankly, we don't care. it's fast. - uint16_t index = uint16_t(state.rndGen() % threadCount); - assert(index < threadStates.size()); - stateToStealFrom = &threadStates[index]; - // don't steal from our own queue - } while (stateToStealFrom == &state); + + // don't try to steal from someone else if we're the only thread (infinite loop) + if (threadCount >= 2) { + do { + // this is biased, but frankly, we don't care. it's fast. + uint16_t index = uint16_t(state.rndGen() % threadCount); + assert(index < threadStates.size()); + stateToStealFrom = &threadStates[index]; + // don't steal from our own queue + } while (stateToStealFrom == &state); + } return stateToStealFrom; } @@ -258,7 +262,9 @@ JobSystem::Job* JobSystem::steal(JobSystem::ThreadState& state) noexcept { Job* job = nullptr; do { ThreadState* const stateToStealFrom = getStateToStealFrom(state); - job = steal(stateToStealFrom->workQueue); + if (UTILS_LIKELY(stateToStealFrom)) { + job = steal(stateToStealFrom->workQueue); + } // nullptr -> nothing to steal in that queue either, if there are active jobs, // continue to try stealing one. } while (!job && hasActiveJobs());