[Bf-blender-cvs] [f18373a9ab1] master: Fix: BLI_task_test deadlock on windows.

Ray Molenkamp noreply at git.blender.org
Sun May 26 01:18:20 CEST 2019


Commit: f18373a9ab1ae1534f311af92e03b9c6db1a0cc8
Author: Ray Molenkamp
Date:   Sat May 25 17:18:17 2019 -0600
Branches: master
https://developer.blender.org/rBf18373a9ab1ae1534f311af92e03b9c6db1a0cc8

Fix: BLI_task_test deadlock on windows.

This patch makes BLI_task_scheduler_create wait for all worker threads to have started before
returning to caller. For very short workloads (BLI_taks_test) there is the chance that the
worker threads have not fully started yet, and the main thread is calling pthread_join at
the same time as pthread_setspecific is being called on the worker threads which causes a
deadlock on pthreads4w.

Differential Revision: https://developer.blender.org/D4936

Reviewed By: mont29, sergey, brecht

===================================================================

M	source/blender/blenlib/intern/task.c

===================================================================

diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index 6f9ff02ce17..85d39f2f98e 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -211,6 +211,10 @@ struct TaskScheduler {
   ThreadMutex queue_mutex;
   ThreadCondition queue_cond;
 
+  ThreadMutex startup_mutex;
+  ThreadCondition startup_cond;
+  volatile int num_thread_started;
+
   volatile bool do_exit;
 
   /* NOTE: In pthread's TLS we store the whole TaskThread structure. */
@@ -429,6 +433,14 @@ static void *task_scheduler_thread_run(void *thread_p)
 
   pthread_setspecific(scheduler->tls_id_key, thread);
 
+  /* signal the main thread when all threads have started */
+  BLI_mutex_lock(&scheduler->startup_mutex);
+  scheduler->num_thread_started++;
+  if (scheduler->num_thread_started == scheduler->num_threads) {
+    BLI_condition_notify_one(&scheduler->startup_cond);
+  }
+  BLI_mutex_unlock(&scheduler->startup_mutex);
+
   /* keep popping off tasks */
   while (task_scheduler_thread_wait_pop(scheduler, &task)) {
     TaskPool *pool = task->pool;
@@ -463,6 +475,10 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
   BLI_mutex_init(&scheduler->queue_mutex);
   BLI_condition_init(&scheduler->queue_cond);
 
+  BLI_mutex_init(&scheduler->startup_mutex);
+  BLI_condition_init(&scheduler->startup_cond);
+  scheduler->num_thread_started = 0;
+
   if (num_threads == 0) {
     /* automatic number of threads will be main thread + num cores */
     num_threads = BLI_system_thread_count();
@@ -504,6 +520,17 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
     }
   }
 
+  /* Wait for all worker threads to start before returning to caller to prevent the case where
+   * threads are still starting and pthread_join is called, which causes a deadlock on pthreads4w.
+   */
+  BLI_mutex_lock(&scheduler->startup_mutex);
+  /* NOTE: Use loop here to avoid false-positive everything-is-ready caused by spontaneous thread
+   * wake up. */
+  while (scheduler->num_thread_started != num_threads) {
+    BLI_condition_wait(&scheduler->startup_cond, &scheduler->startup_mutex);
+  }
+  BLI_mutex_unlock(&scheduler->startup_mutex);
+
   return scheduler;
 }
 
@@ -551,6 +578,8 @@ void BLI_task_scheduler_free(TaskScheduler *scheduler)
   /* delete mutex/condition */
   BLI_mutex_end(&scheduler->queue_mutex);
   BLI_condition_end(&scheduler->queue_cond);
+  BLI_mutex_end(&scheduler->startup_mutex);
+  BLI_condition_end(&scheduler->startup_cond);
 
   MEM_freeN(scheduler);
 }



More information about the Bf-blender-cvs mailing list