Improve JobSystem::wait

JobSystem::waitAndRelease used to spin to wait for the job to finish,
usually this wasn't a problem because the spinning thread was
able to handle other jobs. However, in cases where no job was
available it would actually spin in burn cpu cycles.

we now use a (separate) condition variable to handle that case.
This commit is contained in:
Mathias Agopian
2018-12-12 17:52:44 -08:00
committed by Mathias Agopian
parent 8ae1b06bce
commit e38870ebf5
3 changed files with 26 additions and 23 deletions

View File

@@ -205,16 +205,13 @@ JobSystem* JobSystem::getJobSystem() noexcept {
}
void JobSystem::requestExit() noexcept {
mLock.lock();
// memory_order_relaxed is okay because we're surrounded by lock/unlock, we just want atomicity here.
mExitRequested.store(true, std::memory_order_relaxed);
mLock.unlock();
mCondition.notify_all();
#if __ARM_ARCH_7A__
// on ARMv7a SEL is needed
__dsb(0xA); // ISHST = 0xA (b1010)
UTILS_SIGNAL_EVENT();
#endif
mExitRequested.store(true);
{ std::lock_guard<Mutex> lock(mLooperLock); }
mLooperCondition.notify_all();
{ std::lock_guard<Mutex> lock(mWaiterLock); }
mWaiterCondition.notify_all();
}
inline bool JobSystem::exitRequested() const noexcept {
@@ -289,9 +286,9 @@ void JobSystem::loop(ThreadState* state) noexcept {
// run our main loop...
do {
if (!execute(*state)) {
std::unique_lock<Mutex> lock(mLock);
std::unique_lock<Mutex> lock(mLooperLock);
while (!exitRequested() && !(mActiveJobs.load(std::memory_order_relaxed))) {
mCondition.wait(lock);
mLooperCondition.wait(lock);
setThreadAffinityById(state->id);
}
}
@@ -327,11 +324,9 @@ void JobSystem::finish(Job* job) noexcept {
}
} while (job);
#if __ARM_ARCH_7A__
// on ARMv7a SEL is needed
__dsb(0xA); // ISHST = 0xA (b1010)
UTILS_SIGNAL_EVENT();
#endif
// wake-up all threads that could potentially be waiting on this job finishing
{ std::lock_guard<Mutex> lock(mWaiterLock); }
mWaiterCondition.notify_all();
}
// -----------------------------------------------------------------------------------------------
@@ -397,8 +392,8 @@ void JobSystem::run(JobSystem::Job*& job, uint32_t flags) noexcept {
// wake-up a thread if needed...
if (!(flags & DONT_SIGNAL)) {
// wake-up a queue
{ std::lock_guard<Mutex> lock(mLock); }
mCondition.notify_one();
{ std::lock_guard<Mutex> lock(mLooperLock); }
mLooperCondition.notify_one();
}
// after run() returns, the job is virtually invalid (it'll die on its own)
@@ -420,10 +415,13 @@ void JobSystem::waitAndRelease(Job*& job) noexcept {
ThreadState& state(getState());
do {
if (!execute(state)) {
// we're a waiter so we spin!!!
UTILS_WAIT_FOR_EVENT();
std::unique_lock<Mutex> lock(mWaiterLock);
while (!hasJobCompleted(job) && !exitRequested()) {
mWaiterCondition.wait(lock);
}
}
} while (!hasJobCompleted(job) && !exitRequested());
release(job);
}