[Bf-blender-cvs] [952afbf] master: BLI_task: Fix/enhance logic of exiting worker threads.
Bastien Montagne
noreply at git.blender.org
Mon Nov 2 16:43:13 CET 2015
Commit: 952afbf9168c8601e61fa64ffb37e6d93f1d3d61
Author: Bastien Montagne
Date: Mon Nov 2 16:35:53 2015 +0100
Branches: master
https://developer.blender.org/rB952afbf9168c8601e61fa64ffb37e6d93f1d3d61
BLI_task: Fix/enhance logic of exiting worker threads.
In previous code, worker would exit in case it gets awoken from a condition_wait() and
task queue is empty. However, there may be spurious wake up (either due to pthread itself,
or to some race condition between workers) that would lead to wrongly exiting a worker before
we actually exit the whole scheduler. See code for more details.
===================================================================
M source/blender/blenlib/intern/task.c
===================================================================
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index a125bf7..7ce230e 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -117,11 +117,22 @@ static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task
do {
Task *current_task;
- if (!scheduler->queue.first) {
+
+ /* Assuming we can only have a void queue in 'exit' case here seems logical (we should only be here after
+ * our worker thread has been woken up from a condition_wait(), which only happens after a new task was
+ * added to the queue), but it is wrong.
+ * Waiting on condition may wake up the thread even if condition is not signaled (spurious wakeups), and some
+ * race condition may also empty the queue **after** condition has been signaled, but **before** awoken thread
+ * reaches this point...
+ * See http://stackoverflow.com/questions/8594591/why-does-pthread-cond-wait-have-spurious-wakeups
+ *
+ * So we only abort here if do_exit is set.
+ */
+ if (scheduler->do_exit) {
BLI_mutex_unlock(&scheduler->queue_mutex);
- BLI_assert(scheduler->do_exit);
return false;
}
+
for (current_task = scheduler->queue.first;
current_task != NULL;
current_task = current_task->next)
More information about the Bf-blender-cvs
mailing list