Cleanup: comments (long lines) in blenlib
[blender.git] / source / blender / blenlib / intern / task.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup bli
19  *
20  * A generic task system which can be used for any task based subsystem.
21  */
22
23 #include <stdlib.h>
24
25 #include "MEM_guardedalloc.h"
26
27 #include "DNA_listBase.h"
28
29 #include "BLI_listbase.h"
30 #include "BLI_math.h"
31 #include "BLI_mempool.h"
32 #include "BLI_task.h"
33 #include "BLI_threads.h"
34
35 #include "atomic_ops.h"
36
37 /* Define this to enable some detailed statistic print. */
38 #undef DEBUG_STATS
39
40 /* Types */
41
42 /* Number of per-thread pre-allocated tasks.
43  *
44  * For more details see description of TaskMemPool.
45  */
46 #define MEMPOOL_SIZE 256
47
48 /* Number of tasks which are pushed directly to local thread queue.
49  *
50  * This allows thread to fetch next task without locking the whole queue.
51  */
52 #define LOCAL_QUEUE_SIZE 1
53
54 /* Number of tasks which are allowed to be scheduled in a delayed manner.
55  *
56  * This allows to use less locks per graph node children schedule. More details
57  * could be found at TaskThreadLocalStorage::do_delayed_push.
58  */
59 #define DELAYED_QUEUE_SIZE 4096
60
61 #ifndef NDEBUG
62 #  define ASSERT_THREAD_ID(scheduler, thread_id) \
63     do { \
64       if (!BLI_thread_is_main()) { \
65         TaskThread *thread = pthread_getspecific(scheduler->tls_id_key); \
66         if (thread == NULL) { \
67           BLI_assert(thread_id == 0); \
68         } \
69         else { \
70           BLI_assert(thread_id == thread->id); \
71         } \
72       } \
73       else { \
74         BLI_assert(thread_id == 0); \
75       } \
76     } while (false)
77 #else
78 #  define ASSERT_THREAD_ID(scheduler, thread_id)
79 #endif
80
81 typedef struct Task {
82   struct Task *next, *prev;
83
84   TaskRunFunction run;
85   void *taskdata;
86   bool free_taskdata;
87   TaskFreeFunction freedata;
88   TaskPool *pool;
89 } Task;
90
91 /* This is a per-thread storage of pre-allocated tasks.
92  *
93  * The idea behind this is simple: reduce amount of malloc() calls when pushing
94  * new task to the pool. This is done by keeping memory from the tasks which
95  * were finished already, so instead of freeing that memory we put it to the
96  * pool for the later re-use.
97  *
98  * The tricky part here is to avoid any inter-thread synchronization, hence no
99  * lock must exist around this pool. The pool will become an owner of the pointer
100  * from freed task, and only corresponding thread will be able to use this pool
101  * (no memory stealing and such).
102  *
103  * This leads to the following use of the pool:
104  *
105  * - task_push() should provide proper thread ID from which the task is being
106  *   pushed from.
107  *
108  * - Task allocation function which check corresponding memory pool and if there
109  *   is any memory in there it'll mark memory as re-used, remove it from the pool
110  *   and use that memory for the new task.
111  *
112  *   At this moment task queue owns the memory.
113  *
114  * - When task is done and task_free() is called the memory will be put to the
115  *   pool which corresponds to a thread which handled the task.
116  */
117 typedef struct TaskMemPool {
118   /* Number of pre-allocated tasks in the pool. */
119   int num_tasks;
120   /* Pre-allocated task memory pointers. */
121   Task *tasks[MEMPOOL_SIZE];
122 } TaskMemPool;
123
124 #ifdef DEBUG_STATS
125 typedef struct TaskMemPoolStats {
126   /* Number of allocations. */
127   int num_alloc;
128   /* Number of avoided allocations (pointer was re-used from the pool). */
129   int num_reuse;
130   /* Number of discarded memory due to pool saturation, */
131   int num_discard;
132 } TaskMemPoolStats;
133 #endif
134
135 typedef struct TaskThreadLocalStorage {
136   /* Memory pool for faster task allocation.
137    * The idea is to re-use memory of finished/discarded tasks by this thread.
138    */
139   TaskMemPool task_mempool;
140
141   /* Local queue keeps thread alive by keeping small amount of tasks ready
142    * to be picked up without causing global thread locks for synchronization.
143    */
144   int num_local_queue;
145   Task *local_queue[LOCAL_QUEUE_SIZE];
146
147   /* Thread can be marked for delayed tasks push. This is helpful when it's
148    * know that lots of subsequent task pushed will happen from the same thread
149    * without "interrupting" for task execution.
150    *
151    * We try to accumulate as much tasks as possible in a local queue without
152    * any locks first, and then we push all of them into a scheduler's queue
153    * from within a single mutex lock.
154    */
155   bool do_delayed_push;
156   int num_delayed_queue;
157   Task *delayed_queue[DELAYED_QUEUE_SIZE];
158 } TaskThreadLocalStorage;
159
160 struct TaskPool {
161   TaskScheduler *scheduler;
162
163   volatile size_t num;
164   ThreadMutex num_mutex;
165   ThreadCondition num_cond;
166
167   void *userdata;
168   ThreadMutex user_mutex;
169
170   volatile bool do_cancel;
171   volatile bool do_work;
172
173   volatile bool is_suspended;
174   bool start_suspended;
175   ListBase suspended_queue;
176   size_t num_suspended;
177
178   /* If set, this pool may never be work_and_wait'ed, which means TaskScheduler
179    * has to use its special background fallback thread in case we are in
180    * single-threaded situation.
181    */
182   bool run_in_background;
183
184   /* This is a task scheduler's ID of a thread at which pool was constructed.
185    * It will be used to access task TLS.
186    */
187   int thread_id;
188
189   /* For the pools which are created from non-main thread which is not a
190    * scheduler worker thread we can't re-use any of scheduler's threads TLS
191    * and have to use our own one.
192    */
193   bool use_local_tls;
194   TaskThreadLocalStorage local_tls;
195 #ifndef NDEBUG
196   pthread_t creator_thread_id;
197 #endif
198
199 #ifdef DEBUG_STATS
200   TaskMemPoolStats *mempool_stats;
201 #endif
202 };
203
204 struct TaskScheduler {
205   pthread_t *threads;
206   struct TaskThread *task_threads;
207   int num_threads;
208   bool background_thread_only;
209
210   ListBase queue;
211   ThreadMutex queue_mutex;
212   ThreadCondition queue_cond;
213
214   volatile bool do_exit;
215
216   /* NOTE: In pthread's TLS we store the whole TaskThread structure. */
217   pthread_key_t tls_id_key;
218 };
219
220 typedef struct TaskThread {
221   TaskScheduler *scheduler;
222   int id;
223   TaskThreadLocalStorage tls;
224 } TaskThread;
225
226 /* Helper */
227 BLI_INLINE void task_data_free(Task *task, const int thread_id)
228 {
229   if (task->free_taskdata) {
230     if (task->freedata) {
231       task->freedata(task->pool, task->taskdata, thread_id);
232     }
233     else {
234       MEM_freeN(task->taskdata);
235     }
236   }
237 }
238
239 BLI_INLINE void initialize_task_tls(TaskThreadLocalStorage *tls)
240 {
241   memset(tls, 0, sizeof(TaskThreadLocalStorage));
242 }
243
244 BLI_INLINE TaskThreadLocalStorage *get_task_tls(TaskPool *pool, const int thread_id)
245 {
246   TaskScheduler *scheduler = pool->scheduler;
247   BLI_assert(thread_id >= 0);
248   BLI_assert(thread_id <= scheduler->num_threads);
249   if (pool->use_local_tls && thread_id == 0) {
250     BLI_assert(pool->thread_id == 0);
251     BLI_assert(!BLI_thread_is_main());
252     BLI_assert(pthread_equal(pthread_self(), pool->creator_thread_id));
253     return &pool->local_tls;
254   }
255   if (thread_id == 0) {
256     BLI_assert(BLI_thread_is_main());
257     return &scheduler->task_threads[pool->thread_id].tls;
258   }
259   return &scheduler->task_threads[thread_id].tls;
260 }
261
262 BLI_INLINE void free_task_tls(TaskThreadLocalStorage *tls)
263 {
264   TaskMemPool *task_mempool = &tls->task_mempool;
265   for (int i = 0; i < task_mempool->num_tasks; ++i) {
266     MEM_freeN(task_mempool->tasks[i]);
267   }
268 }
269
270 static Task *task_alloc(TaskPool *pool, const int thread_id)
271 {
272   BLI_assert(thread_id <= pool->scheduler->num_threads);
273   if (thread_id != -1) {
274     BLI_assert(thread_id >= 0);
275     BLI_assert(thread_id <= pool->scheduler->num_threads);
276     TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
277     TaskMemPool *task_mempool = &tls->task_mempool;
278     /* Try to re-use task memory from a thread local storage. */
279     if (task_mempool->num_tasks > 0) {
280       --task_mempool->num_tasks;
281       /* Success! We've just avoided task allocation. */
282 #ifdef DEBUG_STATS
283       pool->mempool_stats[thread_id].num_reuse++;
284 #endif
285       return task_mempool->tasks[task_mempool->num_tasks];
286     }
287     /* We are doomed to allocate new task data. */
288 #ifdef DEBUG_STATS
289     pool->mempool_stats[thread_id].num_alloc++;
290 #endif
291   }
292   return MEM_mallocN(sizeof(Task), "New task");
293 }
294
295 static void task_free(TaskPool *pool, Task *task, const int thread_id)
296 {
297   task_data_free(task, thread_id);
298   BLI_assert(thread_id >= 0);
299   BLI_assert(thread_id <= pool->scheduler->num_threads);
300   if (thread_id == 0) {
301     BLI_assert(pool->use_local_tls || BLI_thread_is_main());
302   }
303   TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
304   TaskMemPool *task_mempool = &tls->task_mempool;
305   if (task_mempool->num_tasks < MEMPOOL_SIZE - 1) {
306     /* Successfully allowed the task to be re-used later. */
307     task_mempool->tasks[task_mempool->num_tasks] = task;
308     ++task_mempool->num_tasks;
309   }
310   else {
311     /* Local storage saturated, no other way than just discard
312      * the memory.
313      *
314      * TODO(sergey): We can perhaps store such pointer in a global
315      * scheduler pool, maybe it'll be faster than discarding and
316      * allocating again.
317      */
318     MEM_freeN(task);
319 #ifdef DEBUG_STATS
320     pool->mempool_stats[thread_id].num_discard++;
321 #endif
322   }
323 }
324
325 /* Task Scheduler */
326
327 static void task_pool_num_decrease(TaskPool *pool, size_t done)
328 {
329   BLI_mutex_lock(&pool->num_mutex);
330
331   BLI_assert(pool->num >= done);
332
333   pool->num -= done;
334
335   if (pool->num == 0) {
336     BLI_condition_notify_all(&pool->num_cond);
337   }
338
339   BLI_mutex_unlock(&pool->num_mutex);
340 }
341
342 static void task_pool_num_increase(TaskPool *pool, size_t new)
343 {
344   BLI_mutex_lock(&pool->num_mutex);
345
346   pool->num += new;
347   BLI_condition_notify_all(&pool->num_cond);
348
349   BLI_mutex_unlock(&pool->num_mutex);
350 }
351
352 static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task)
353 {
354   bool found_task = false;
355   BLI_mutex_lock(&scheduler->queue_mutex);
356
357   while (!scheduler->queue.first && !scheduler->do_exit) {
358     BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex);
359   }
360
361   do {
362     Task *current_task;
363
364     /* Assuming we can only have a void queue in 'exit' case here seems logical
365      * (we should only be here after our worker thread has been woken up from a
366      * condition_wait(), which only happens after a new task was added to the queue),
367      * but it is wrong.
368      * Waiting on condition may wake up the thread even if condition is not signaled
369      * (spurious wake-ups), and some race condition may also empty the queue **after**
370      * condition has been signaled, but **before** awoken thread reaches this point...
371      * See http://stackoverflow.com/questions/8594591
372      *
373      * So we only abort here if do_exit is set.
374      */
375     if (scheduler->do_exit) {
376       BLI_mutex_unlock(&scheduler->queue_mutex);
377       return false;
378     }
379
380     for (current_task = scheduler->queue.first; current_task != NULL;
381          current_task = current_task->next) {
382       TaskPool *pool = current_task->pool;
383
384       if (scheduler->background_thread_only && !pool->run_in_background) {
385         continue;
386       }
387
388       *task = current_task;
389       found_task = true;
390       BLI_remlink(&scheduler->queue, *task);
391       break;
392     }
393     if (!found_task) {
394       BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex);
395     }
396   } while (!found_task);
397
398   BLI_mutex_unlock(&scheduler->queue_mutex);
399
400   return true;
401 }
402
403 BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls, const int thread_id)
404 {
405   BLI_assert(!tls->do_delayed_push);
406   while (tls->num_local_queue > 0) {
407     /* We pop task from queue before handling it so handler of the task can
408      * push next job to the local queue.
409      */
410     tls->num_local_queue--;
411     Task *local_task = tls->local_queue[tls->num_local_queue];
412     /* TODO(sergey): Double-check work_and_wait() doesn't handle other's
413      * pool tasks.
414      */
415     TaskPool *local_pool = local_task->pool;
416     local_task->run(local_pool, local_task->taskdata, thread_id);
417     task_free(local_pool, local_task, thread_id);
418   }
419   BLI_assert(!tls->do_delayed_push);
420 }
421
422 static void *task_scheduler_thread_run(void *thread_p)
423 {
424   TaskThread *thread = (TaskThread *)thread_p;
425   TaskThreadLocalStorage *tls = &thread->tls;
426   TaskScheduler *scheduler = thread->scheduler;
427   int thread_id = thread->id;
428   Task *task;
429
430   pthread_setspecific(scheduler->tls_id_key, thread);
431
432   /* keep popping off tasks */
433   while (task_scheduler_thread_wait_pop(scheduler, &task)) {
434     TaskPool *pool = task->pool;
435
436     /* run task */
437     BLI_assert(!tls->do_delayed_push);
438     task->run(pool, task->taskdata, thread_id);
439     BLI_assert(!tls->do_delayed_push);
440
441     /* delete task */
442     task_free(pool, task, thread_id);
443
444     /* Handle all tasks from local queue. */
445     handle_local_queue(tls, thread_id);
446
447     /* notify pool task was done */
448     task_pool_num_decrease(pool, 1);
449   }
450
451   return NULL;
452 }
453
454 TaskScheduler *BLI_task_scheduler_create(int num_threads)
455 {
456   TaskScheduler *scheduler = MEM_callocN(sizeof(TaskScheduler), "TaskScheduler");
457
458   /* multiple places can use this task scheduler, sharing the same
459    * threads, so we keep track of the number of users. */
460   scheduler->do_exit = false;
461
462   BLI_listbase_clear(&scheduler->queue);
463   BLI_mutex_init(&scheduler->queue_mutex);
464   BLI_condition_init(&scheduler->queue_cond);
465
466   if (num_threads == 0) {
467     /* automatic number of threads will be main thread + num cores */
468     num_threads = BLI_system_thread_count();
469   }
470
471   /* main thread will also work, so we count it too */
472   num_threads -= 1;
473
474   /* Add background-only thread if needed. */
475   if (num_threads == 0) {
476     scheduler->background_thread_only = true;
477     num_threads = 1;
478   }
479
480   scheduler->task_threads = MEM_mallocN(sizeof(TaskThread) * (num_threads + 1),
481                                         "TaskScheduler task threads");
482
483   /* Initialize TLS for main thread. */
484   initialize_task_tls(&scheduler->task_threads[0].tls);
485
486   pthread_key_create(&scheduler->tls_id_key, NULL);
487
488   /* launch threads that will be waiting for work */
489   if (num_threads > 0) {
490     int i;
491
492     scheduler->num_threads = num_threads;
493     scheduler->threads = MEM_callocN(sizeof(pthread_t) * num_threads, "TaskScheduler threads");
494
495     for (i = 0; i < num_threads; i++) {
496       TaskThread *thread = &scheduler->task_threads[i + 1];
497       thread->scheduler = scheduler;
498       thread->id = i + 1;
499       initialize_task_tls(&thread->tls);
500
501       if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) {
502         fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads);
503       }
504     }
505   }
506
507   return scheduler;
508 }
509
510 void BLI_task_scheduler_free(TaskScheduler *scheduler)
511 {
512   Task *task;
513
514   /* stop all waiting threads */
515   BLI_mutex_lock(&scheduler->queue_mutex);
516   scheduler->do_exit = true;
517   BLI_condition_notify_all(&scheduler->queue_cond);
518   BLI_mutex_unlock(&scheduler->queue_mutex);
519
520   pthread_key_delete(scheduler->tls_id_key);
521
522   /* delete threads */
523   if (scheduler->threads) {
524     int i;
525
526     for (i = 0; i < scheduler->num_threads; i++) {
527       if (pthread_join(scheduler->threads[i], NULL) != 0) {
528         fprintf(stderr, "TaskScheduler failed to join thread %d/%d\n", i, scheduler->num_threads);
529       }
530     }
531
532     MEM_freeN(scheduler->threads);
533   }
534
535   /* Delete task thread data */
536   if (scheduler->task_threads) {
537     for (int i = 0; i < scheduler->num_threads + 1; ++i) {
538       TaskThreadLocalStorage *tls = &scheduler->task_threads[i].tls;
539       free_task_tls(tls);
540     }
541
542     MEM_freeN(scheduler->task_threads);
543   }
544
545   /* delete leftover tasks */
546   for (task = scheduler->queue.first; task; task = task->next) {
547     task_data_free(task, 0);
548   }
549   BLI_freelistN(&scheduler->queue);
550
551   /* delete mutex/condition */
552   BLI_mutex_end(&scheduler->queue_mutex);
553   BLI_condition_end(&scheduler->queue_cond);
554
555   MEM_freeN(scheduler);
556 }
557
558 int BLI_task_scheduler_num_threads(TaskScheduler *scheduler)
559 {
560   return scheduler->num_threads + 1;
561 }
562
563 static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriority priority)
564 {
565   task_pool_num_increase(task->pool, 1);
566
567   /* add task to queue */
568   BLI_mutex_lock(&scheduler->queue_mutex);
569
570   if (priority == TASK_PRIORITY_HIGH) {
571     BLI_addhead(&scheduler->queue, task);
572   }
573   else {
574     BLI_addtail(&scheduler->queue, task);
575   }
576
577   BLI_condition_notify_one(&scheduler->queue_cond);
578   BLI_mutex_unlock(&scheduler->queue_mutex);
579 }
580
581 static void task_scheduler_push_all(TaskScheduler *scheduler,
582                                     TaskPool *pool,
583                                     Task **tasks,
584                                     int num_tasks)
585 {
586   if (num_tasks == 0) {
587     return;
588   }
589
590   task_pool_num_increase(pool, num_tasks);
591
592   BLI_mutex_lock(&scheduler->queue_mutex);
593
594   for (int i = 0; i < num_tasks; i++) {
595     BLI_addhead(&scheduler->queue, tasks[i]);
596   }
597
598   BLI_condition_notify_all(&scheduler->queue_cond);
599   BLI_mutex_unlock(&scheduler->queue_mutex);
600 }
601
602 static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool)
603 {
604   Task *task, *nexttask;
605   size_t done = 0;
606
607   BLI_mutex_lock(&scheduler->queue_mutex);
608
609   /* free all tasks from this pool from the queue */
610   for (task = scheduler->queue.first; task; task = nexttask) {
611     nexttask = task->next;
612
613     if (task->pool == pool) {
614       task_data_free(task, pool->thread_id);
615       BLI_freelinkN(&scheduler->queue, task);
616
617       done++;
618     }
619   }
620
621   BLI_mutex_unlock(&scheduler->queue_mutex);
622
623   /* notify done */
624   task_pool_num_decrease(pool, done);
625 }
626
627 /* Task Pool */
628
629 static TaskPool *task_pool_create_ex(TaskScheduler *scheduler,
630                                      void *userdata,
631                                      const bool is_background,
632                                      const bool is_suspended)
633 {
634   TaskPool *pool = MEM_mallocN(sizeof(TaskPool), "TaskPool");
635
636 #ifndef NDEBUG
637   /* Assert we do not try to create a background pool from some parent task -
638    * those only work OK from main thread. */
639   if (is_background) {
640     const pthread_t thread_id = pthread_self();
641     int i = scheduler->num_threads;
642
643     while (i--) {
644       BLI_assert(!pthread_equal(scheduler->threads[i], thread_id));
645     }
646   }
647 #endif
648
649   pool->scheduler = scheduler;
650   pool->num = 0;
651   pool->do_cancel = false;
652   pool->do_work = false;
653   pool->is_suspended = is_suspended;
654   pool->start_suspended = is_suspended;
655   pool->num_suspended = 0;
656   pool->suspended_queue.first = pool->suspended_queue.last = NULL;
657   pool->run_in_background = is_background;
658   pool->use_local_tls = false;
659
660   BLI_mutex_init(&pool->num_mutex);
661   BLI_condition_init(&pool->num_cond);
662
663   pool->userdata = userdata;
664   BLI_mutex_init(&pool->user_mutex);
665
666   if (BLI_thread_is_main()) {
667     pool->thread_id = 0;
668   }
669   else {
670     TaskThread *thread = pthread_getspecific(scheduler->tls_id_key);
671     if (thread == NULL) {
672       /* NOTE: Task pool is created from non-main thread which is not
673        * managed by the task scheduler. We identify ourselves as thread ID
674        * 0 but we do not use scheduler's TLS storage and use our own
675        * instead to avoid any possible threading conflicts.
676        */
677       pool->thread_id = 0;
678       pool->use_local_tls = true;
679 #ifndef NDEBUG
680       pool->creator_thread_id = pthread_self();
681 #endif
682       initialize_task_tls(&pool->local_tls);
683     }
684     else {
685       pool->thread_id = thread->id;
686     }
687   }
688
689 #ifdef DEBUG_STATS
690   pool->mempool_stats = MEM_callocN(sizeof(*pool->mempool_stats) * (scheduler->num_threads + 1),
691                                     "per-taskpool mempool stats");
692 #endif
693
694   /* Ensure malloc will go fine from threads,
695    *
696    * This is needed because we could be in main thread here
697    * and malloc could be non-thread safe at this point because
698    * no other jobs are running.
699    */
700   BLI_threaded_malloc_begin();
701
702   return pool;
703 }
704
705 /**
706  * Create a normal task pool.
707  * This means that in single-threaded context, it will not be executed at all until you call
708  * \a BLI_task_pool_work_and_wait() on it.
709  */
710 TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata)
711 {
712   return task_pool_create_ex(scheduler, userdata, false, false);
713 }
714
715 /**
716  * Create a background task pool.
717  * In multi-threaded context, there is no differences with #BLI_task_pool_create(),
718  * but in single-threaded case it is ensured to have at least one worker thread to run on
719  * (i.e. you don't have to call #BLI_task_pool_work_and_wait
720  * on it to be sure it will be processed).
721  *
722  * \note Background pools are non-recursive
723  * (that is, you should not create other background pools in tasks assigned to a background pool,
724  * they could end never being executed, since the 'fallback' background thread is already
725  * busy with parent task in single-threaded context).
726  */
727 TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, void *userdata)
728 {
729   return task_pool_create_ex(scheduler, userdata, true, false);
730 }
731
732 /**
733  * Similar to BLI_task_pool_create() but does not schedule any tasks for execution
734  * for until BLI_task_pool_work_and_wait() is called. This helps reducing threading
735  * overhead when pushing huge amount of small initial tasks from the main thread.
736  */
737 TaskPool *BLI_task_pool_create_suspended(TaskScheduler *scheduler, void *userdata)
738 {
739   return task_pool_create_ex(scheduler, userdata, false, true);
740 }
741
742 void BLI_task_pool_free(TaskPool *pool)
743 {
744   BLI_task_pool_cancel(pool);
745
746   BLI_mutex_end(&pool->num_mutex);
747   BLI_condition_end(&pool->num_cond);
748
749   BLI_mutex_end(&pool->user_mutex);
750
751 #ifdef DEBUG_STATS
752   printf("Thread ID    Allocated   Reused   Discarded\n");
753   for (int i = 0; i < pool->scheduler->num_threads + 1; ++i) {
754     printf("%02d           %05d       %05d    %05d\n",
755            i,
756            pool->mempool_stats[i].num_alloc,
757            pool->mempool_stats[i].num_reuse,
758            pool->mempool_stats[i].num_discard);
759   }
760   MEM_freeN(pool->mempool_stats);
761 #endif
762
763   if (pool->use_local_tls) {
764     free_task_tls(&pool->local_tls);
765   }
766
767   MEM_freeN(pool);
768
769   BLI_threaded_malloc_end();
770 }
771
772 BLI_INLINE bool task_can_use_local_queues(TaskPool *pool, int thread_id)
773 {
774   return (thread_id != -1 && (thread_id != pool->thread_id || pool->do_work));
775 }
776
777 static void task_pool_push(TaskPool *pool,
778                            TaskRunFunction run,
779                            void *taskdata,
780                            bool free_taskdata,
781                            TaskFreeFunction freedata,
782                            TaskPriority priority,
783                            int thread_id)
784 {
785   /* Allocate task and fill it's properties. */
786   Task *task = task_alloc(pool, thread_id);
787   task->run = run;
788   task->taskdata = taskdata;
789   task->free_taskdata = free_taskdata;
790   task->freedata = freedata;
791   task->pool = pool;
792   /* For suspended pools we put everything yo a global queue first
793    * and exit as soon as possible.
794    *
795    * This tasks will be moved to actual execution when pool is
796    * activated by work_and_wait().
797    */
798   if (pool->is_suspended) {
799     BLI_addhead(&pool->suspended_queue, task);
800     atomic_fetch_and_add_z(&pool->num_suspended, 1);
801     return;
802   }
803   /* Populate to any local queue first, this is cheapest push ever. */
804   if (task_can_use_local_queues(pool, thread_id)) {
805     ASSERT_THREAD_ID(pool->scheduler, thread_id);
806     TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
807     /* Try to push to a local execution queue.
808      * These tasks will be picked up next.
809      */
810     if (tls->num_local_queue < LOCAL_QUEUE_SIZE) {
811       tls->local_queue[tls->num_local_queue] = task;
812       tls->num_local_queue++;
813       return;
814     }
815     /* If we are in the delayed tasks push mode, we push tasks to a
816      * temporary local queue first without any locks, and then move them
817      * to global execution queue with a single lock.
818      */
819     if (tls->do_delayed_push && tls->num_delayed_queue < DELAYED_QUEUE_SIZE) {
820       tls->delayed_queue[tls->num_delayed_queue] = task;
821       tls->num_delayed_queue++;
822       return;
823     }
824   }
825   /* Do push to a global execution pool, slowest possible method,
826    * causes quite reasonable amount of threading overhead.
827    */
828   task_scheduler_push(pool->scheduler, task, priority);
829 }
830
831 void BLI_task_pool_push_ex(TaskPool *pool,
832                            TaskRunFunction run,
833                            void *taskdata,
834                            bool free_taskdata,
835                            TaskFreeFunction freedata,
836                            TaskPriority priority)
837 {
838   task_pool_push(pool, run, taskdata, free_taskdata, freedata, priority, -1);
839 }
840
841 void BLI_task_pool_push(
842     TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskPriority priority)
843 {
844   BLI_task_pool_push_ex(pool, run, taskdata, free_taskdata, NULL, priority);
845 }
846
847 void BLI_task_pool_push_from_thread(TaskPool *pool,
848                                     TaskRunFunction run,
849                                     void *taskdata,
850                                     bool free_taskdata,
851                                     TaskPriority priority,
852                                     int thread_id)
853 {
854   task_pool_push(pool, run, taskdata, free_taskdata, NULL, priority, thread_id);
855 }
856
857 void BLI_task_pool_work_and_wait(TaskPool *pool)
858 {
859   TaskThreadLocalStorage *tls = get_task_tls(pool, pool->thread_id);
860   TaskScheduler *scheduler = pool->scheduler;
861
862   if (atomic_fetch_and_and_uint8((uint8_t *)&pool->is_suspended, 0)) {
863     if (pool->num_suspended) {
864       task_pool_num_increase(pool, pool->num_suspended);
865       BLI_mutex_lock(&scheduler->queue_mutex);
866
867       BLI_movelisttolist(&scheduler->queue, &pool->suspended_queue);
868
869       BLI_condition_notify_all(&scheduler->queue_cond);
870       BLI_mutex_unlock(&scheduler->queue_mutex);
871
872       pool->num_suspended = 0;
873     }
874   }
875
876   pool->do_work = true;
877
878   ASSERT_THREAD_ID(pool->scheduler, pool->thread_id);
879
880   handle_local_queue(tls, pool->thread_id);
881
882   BLI_mutex_lock(&pool->num_mutex);
883
884   while (pool->num != 0) {
885     Task *task, *work_task = NULL;
886     bool found_task = false;
887
888     BLI_mutex_unlock(&pool->num_mutex);
889
890     BLI_mutex_lock(&scheduler->queue_mutex);
891
892     /* find task from this pool. if we get a task from another pool,
893      * we can get into deadlock */
894
895     for (task = scheduler->queue.first; task; task = task->next) {
896       if (task->pool == pool) {
897         work_task = task;
898         found_task = true;
899         BLI_remlink(&scheduler->queue, task);
900         break;
901       }
902     }
903
904     BLI_mutex_unlock(&scheduler->queue_mutex);
905
906     /* if found task, do it, otherwise wait until other tasks are done */
907     if (found_task) {
908       /* run task */
909       BLI_assert(!tls->do_delayed_push);
910       work_task->run(pool, work_task->taskdata, pool->thread_id);
911       BLI_assert(!tls->do_delayed_push);
912
913       /* delete task */
914       task_free(pool, task, pool->thread_id);
915
916       /* Handle all tasks from local queue. */
917       handle_local_queue(tls, pool->thread_id);
918
919       /* notify pool task was done */
920       task_pool_num_decrease(pool, 1);
921     }
922
923     BLI_mutex_lock(&pool->num_mutex);
924     if (pool->num == 0) {
925       break;
926     }
927
928     if (!found_task) {
929       BLI_condition_wait(&pool->num_cond, &pool->num_mutex);
930     }
931   }
932
933   BLI_mutex_unlock(&pool->num_mutex);
934
935   BLI_assert(tls->num_local_queue == 0);
936 }
937
938 void BLI_task_pool_work_wait_and_reset(TaskPool *pool)
939 {
940   BLI_task_pool_work_and_wait(pool);
941
942   pool->do_work = false;
943   pool->is_suspended = pool->start_suspended;
944 }
945
946 void BLI_task_pool_cancel(TaskPool *pool)
947 {
948   pool->do_cancel = true;
949
950   task_scheduler_clear(pool->scheduler, pool);
951
952   /* wait until all entries are cleared */
953   BLI_mutex_lock(&pool->num_mutex);
954   while (pool->num) {
955     BLI_condition_wait(&pool->num_cond, &pool->num_mutex);
956   }
957   BLI_mutex_unlock(&pool->num_mutex);
958
959   pool->do_cancel = false;
960 }
961
962 bool BLI_task_pool_canceled(TaskPool *pool)
963 {
964   return pool->do_cancel;
965 }
966
967 void *BLI_task_pool_userdata(TaskPool *pool)
968 {
969   return pool->userdata;
970 }
971
972 ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool)
973 {
974   return &pool->user_mutex;
975 }
976
977 void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id)
978 {
979   if (task_can_use_local_queues(pool, thread_id)) {
980     ASSERT_THREAD_ID(pool->scheduler, thread_id);
981     TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
982     tls->do_delayed_push = true;
983   }
984 }
985
986 void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id)
987 {
988   if (task_can_use_local_queues(pool, thread_id)) {
989     ASSERT_THREAD_ID(pool->scheduler, thread_id);
990     TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
991     BLI_assert(tls->do_delayed_push);
992     task_scheduler_push_all(pool->scheduler, pool, tls->delayed_queue, tls->num_delayed_queue);
993     tls->do_delayed_push = false;
994     tls->num_delayed_queue = 0;
995   }
996 }
997
998 /* Parallel range routines */
999
1000 /**
1001  *
1002  * Main functions:
1003  * - #BLI_task_parallel_range
1004  * - #BLI_task_parallel_listbase (#ListBase - double linked list)
1005  *
1006  * TODO:
1007  * - #BLI_task_parallel_foreach_link (#Link - single linked list)
1008  * - #BLI_task_parallel_foreach_ghash/gset (#GHash/#GSet - hash & set)
1009  * - #BLI_task_parallel_foreach_mempool (#BLI_mempool - iterate over mempools)
1010  */
1011
1012 /* Allows to avoid using malloc for userdata_chunk in tasks, when small enough. */
1013 #define MALLOCA(_size) ((_size) <= 8192) ? alloca((_size)) : MEM_mallocN((_size), __func__)
1014 #define MALLOCA_FREE(_mem, _size) \
1015   if (((_mem) != NULL) && ((_size) > 8192)) \
1016   MEM_freeN((_mem))
1017
1018 typedef struct ParallelRangeState {
1019   int start, stop;
1020   void *userdata;
1021
1022   TaskParallelRangeFunc func;
1023
1024   int iter;
1025   int chunk_size;
1026 } ParallelRangeState;
1027
1028 BLI_INLINE bool parallel_range_next_iter_get(ParallelRangeState *__restrict state,
1029                                              int *__restrict iter,
1030                                              int *__restrict count)
1031 {
1032   int previter = atomic_fetch_and_add_int32(&state->iter, state->chunk_size);
1033
1034   *iter = previter;
1035   *count = max_ii(0, min_ii(state->chunk_size, state->stop - previter));
1036
1037   return (previter < state->stop);
1038 }
1039
1040 static void parallel_range_func(TaskPool *__restrict pool, void *userdata_chunk, int thread_id)
1041 {
1042   ParallelRangeState *__restrict state = BLI_task_pool_userdata(pool);
1043   ParallelRangeTLS tls = {
1044       .thread_id = thread_id,
1045       .userdata_chunk = userdata_chunk,
1046   };
1047   int iter, count;
1048   while (parallel_range_next_iter_get(state, &iter, &count)) {
1049     for (int i = 0; i < count; ++i) {
1050       state->func(state->userdata, iter + i, &tls);
1051     }
1052   }
1053 }
1054
1055 static void parallel_range_single_thread(const int start,
1056                                          int const stop,
1057                                          void *userdata,
1058                                          TaskParallelRangeFunc func,
1059                                          const ParallelRangeSettings *settings)
1060 {
1061   void *userdata_chunk = settings->userdata_chunk;
1062   const size_t userdata_chunk_size = settings->userdata_chunk_size;
1063   void *userdata_chunk_local = NULL;
1064   const bool use_userdata_chunk = (userdata_chunk_size != 0) && (userdata_chunk != NULL);
1065   if (use_userdata_chunk) {
1066     userdata_chunk_local = MALLOCA(userdata_chunk_size);
1067     memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size);
1068   }
1069   ParallelRangeTLS tls = {
1070       .thread_id = 0,
1071       .userdata_chunk = userdata_chunk_local,
1072   };
1073   for (int i = start; i < stop; ++i) {
1074     func(userdata, i, &tls);
1075   }
1076   if (settings->func_finalize != NULL) {
1077     settings->func_finalize(userdata, userdata_chunk_local);
1078   }
1079   MALLOCA_FREE(userdata_chunk_local, userdata_chunk_size);
1080 }
1081
1082 /**
1083  * This function allows to parallelized for loops in a similar way to OpenMP's
1084  * 'parallel for' statement.
1085  *
1086  * See public API doc of ParallelRangeSettings for description of all settings.
1087  */
1088 void BLI_task_parallel_range(const int start,
1089                              const int stop,
1090                              void *userdata,
1091                              TaskParallelRangeFunc func,
1092                              const ParallelRangeSettings *settings)
1093 {
1094   TaskScheduler *task_scheduler;
1095   TaskPool *task_pool;
1096   ParallelRangeState state;
1097   int i, num_threads, num_tasks;
1098
1099   void *userdata_chunk = settings->userdata_chunk;
1100   const size_t userdata_chunk_size = settings->userdata_chunk_size;
1101   void *userdata_chunk_local = NULL;
1102   void *userdata_chunk_array = NULL;
1103   const bool use_userdata_chunk = (userdata_chunk_size != 0) && (userdata_chunk != NULL);
1104
1105   if (start == stop) {
1106     return;
1107   }
1108
1109   BLI_assert(start < stop);
1110   if (userdata_chunk_size != 0) {
1111     BLI_assert(userdata_chunk != NULL);
1112   }
1113
1114   /* If it's not enough data to be crunched, don't bother with tasks at all,
1115    * do everything from the main thread.
1116    */
1117   if (!settings->use_threading) {
1118     parallel_range_single_thread(start, stop, userdata, func, settings);
1119     return;
1120   }
1121
1122   task_scheduler = BLI_task_scheduler_get();
1123   num_threads = BLI_task_scheduler_num_threads(task_scheduler);
1124
1125   /* The idea here is to prevent creating task for each of the loop iterations
1126    * and instead have tasks which are evenly distributed across CPU cores and
1127    * pull next iter to be crunched using the queue.
1128    */
1129   num_tasks = num_threads + 2;
1130
1131   state.start = start;
1132   state.stop = stop;
1133   state.userdata = userdata;
1134   state.func = func;
1135   state.iter = start;
1136   switch (settings->scheduling_mode) {
1137     case TASK_SCHEDULING_STATIC:
1138       state.chunk_size = max_ii(settings->min_iter_per_thread, (stop - start) / (num_tasks));
1139       break;
1140     case TASK_SCHEDULING_DYNAMIC:
1141       /* TODO(sergey): Make it configurable from min_iter_per_thread. */
1142       state.chunk_size = 32;
1143       break;
1144   }
1145
1146   num_tasks = min_ii(num_tasks, max_ii(1, (stop - start) / state.chunk_size));
1147
1148   if (num_tasks == 1) {
1149     parallel_range_single_thread(start, stop, userdata, func, settings);
1150     return;
1151   }
1152
1153   task_pool = BLI_task_pool_create_suspended(task_scheduler, &state);
1154
1155   /* NOTE: This way we are adding a memory barrier and ensure all worker
1156    * threads can read and modify the value, without any locks. */
1157   atomic_fetch_and_add_int32(&state.iter, 0);
1158
1159   if (use_userdata_chunk) {
1160     userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks);
1161   }
1162
1163   for (i = 0; i < num_tasks; i++) {
1164     if (use_userdata_chunk) {
1165       userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i);
1166       memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size);
1167     }
1168     /* Use this pool's pre-allocated tasks. */
1169     BLI_task_pool_push_from_thread(task_pool,
1170                                    parallel_range_func,
1171                                    userdata_chunk_local,
1172                                    false,
1173                                    TASK_PRIORITY_HIGH,
1174                                    task_pool->thread_id);
1175   }
1176
1177   BLI_task_pool_work_and_wait(task_pool);
1178   BLI_task_pool_free(task_pool);
1179
1180   if (use_userdata_chunk) {
1181     if (settings->func_finalize != NULL) {
1182       for (i = 0; i < num_tasks; i++) {
1183         userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i);
1184         settings->func_finalize(userdata, userdata_chunk_local);
1185       }
1186     }
1187     MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks);
1188   }
1189 }
1190
1191 #undef MALLOCA
1192 #undef MALLOCA_FREE
1193
1194 typedef struct ParallelListbaseState {
1195   void *userdata;
1196   TaskParallelListbaseFunc func;
1197
1198   int chunk_size;
1199   int index;
1200   Link *link;
1201   SpinLock lock;
1202 } ParallelListState;
1203
1204 BLI_INLINE Link *parallel_listbase_next_iter_get(ParallelListState *__restrict state,
1205                                                  int *__restrict index,
1206                                                  int *__restrict count)
1207 {
1208   int task_count = 0;
1209   BLI_spin_lock(&state->lock);
1210   Link *result = state->link;
1211   if (LIKELY(result != NULL)) {
1212     *index = state->index;
1213     while (state->link != NULL && task_count < state->chunk_size) {
1214       ++task_count;
1215       state->link = state->link->next;
1216     }
1217     state->index += task_count;
1218   }
1219   BLI_spin_unlock(&state->lock);
1220   *count = task_count;
1221   return result;
1222 }
1223
1224 static void parallel_listbase_func(TaskPool *__restrict pool,
1225                                    void *UNUSED(taskdata),
1226                                    int UNUSED(threadid))
1227 {
1228   ParallelListState *__restrict state = BLI_task_pool_userdata(pool);
1229   Link *link;
1230   int index, count;
1231
1232   while ((link = parallel_listbase_next_iter_get(state, &index, &count)) != NULL) {
1233     for (int i = 0; i < count; ++i) {
1234       state->func(state->userdata, link, index + i);
1235       link = link->next;
1236     }
1237   }
1238 }
1239
1240 static void task_parallel_listbase_no_threads(struct ListBase *listbase,
1241                                               void *userdata,
1242                                               TaskParallelListbaseFunc func)
1243 {
1244   int i = 0;
1245   for (Link *link = listbase->first; link != NULL; link = link->next, ++i) {
1246     func(userdata, link, i);
1247   }
1248 }
1249
1250 /* NOTE: The idea here is to compensate for rather measurable threading
1251  * overhead caused by fetching tasks. With too many CPU threads we are starting
1252  * to spend too much time in those overheads. */
1253 BLI_INLINE int task_parallel_listbasecalc_chunk_size(const int num_threads)
1254 {
1255   if (num_threads > 32) {
1256     return 128;
1257   }
1258   else if (num_threads > 16) {
1259     return 64;
1260   }
1261   return 32;
1262 }
1263
1264 /**
1265  * This function allows to parallelize for loops over ListBase items.
1266  *
1267  * \param listbase: The double linked list to loop over.
1268  * \param userdata: Common userdata passed to all instances of \a func.
1269  * \param func: Callback function.
1270  * \param use_threading: If \a true, actually split-execute loop in threads,
1271  * else just do a sequential forloop
1272  * (allows caller to use any kind of test to switch on parallelization or not).
1273  *
1274  * \note There is no static scheduling here,
1275  * since it would need another full loop over items to count them.
1276  */
1277 void BLI_task_parallel_listbase(struct ListBase *listbase,
1278                                 void *userdata,
1279                                 TaskParallelListbaseFunc func,
1280                                 const bool use_threading)
1281 {
1282   if (BLI_listbase_is_empty(listbase)) {
1283     return;
1284   }
1285   if (!use_threading) {
1286     task_parallel_listbase_no_threads(listbase, userdata, func);
1287     return;
1288   }
1289   TaskScheduler *task_scheduler = BLI_task_scheduler_get();
1290   const int num_threads = BLI_task_scheduler_num_threads(task_scheduler);
1291   /* TODO(sergey): Consider making chunk size configurable. */
1292   const int chunk_size = task_parallel_listbasecalc_chunk_size(num_threads);
1293   const int num_tasks = min_ii(num_threads, BLI_listbase_count(listbase) / chunk_size);
1294   if (num_tasks <= 1) {
1295     task_parallel_listbase_no_threads(listbase, userdata, func);
1296     return;
1297   }
1298
1299   ParallelListState state;
1300   TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state);
1301
1302   state.index = 0;
1303   state.link = listbase->first;
1304   state.userdata = userdata;
1305   state.func = func;
1306   state.chunk_size = chunk_size;
1307   BLI_spin_init(&state.lock);
1308
1309   BLI_assert(num_tasks > 0);
1310   for (int i = 0; i < num_tasks; i++) {
1311     /* Use this pool's pre-allocated tasks. */
1312     BLI_task_pool_push_from_thread(
1313         task_pool, parallel_listbase_func, NULL, false, TASK_PRIORITY_HIGH, task_pool->thread_id);
1314   }
1315
1316   BLI_task_pool_work_and_wait(task_pool);
1317   BLI_task_pool_free(task_pool);
1318
1319   BLI_spin_end(&state.lock);
1320 }
1321
1322 typedef struct ParallelMempoolState {
1323   void *userdata;
1324   TaskParallelMempoolFunc func;
1325 } ParallelMempoolState;
1326
1327 static void parallel_mempool_func(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid))
1328 {
1329   ParallelMempoolState *__restrict state = BLI_task_pool_userdata(pool);
1330   BLI_mempool_iter *iter = taskdata;
1331   MempoolIterData *item;
1332
1333   while ((item = BLI_mempool_iterstep(iter)) != NULL) {
1334     state->func(state->userdata, item);
1335   }
1336 }
1337
1338 /**
1339  * This function allows to parallelize for loops over Mempool items.
1340  *
1341  * \param mempool: The iterable BLI_mempool to loop over.
1342  * \param userdata: Common userdata passed to all instances of \a func.
1343  * \param func: Callback function.
1344  * \param use_threading: If \a true, actually split-execute loop in threads,
1345  * else just do a sequential for loop
1346  * (allows caller to use any kind of test to switch on parallelization or not).
1347  *
1348  * \note There is no static scheduling here.
1349  */
1350 void BLI_task_parallel_mempool(BLI_mempool *mempool,
1351                                void *userdata,
1352                                TaskParallelMempoolFunc func,
1353                                const bool use_threading)
1354 {
1355   TaskScheduler *task_scheduler;
1356   TaskPool *task_pool;
1357   ParallelMempoolState state;
1358   int i, num_threads, num_tasks;
1359
1360   if (BLI_mempool_len(mempool) == 0) {
1361     return;
1362   }
1363
1364   if (!use_threading) {
1365     BLI_mempool_iter iter;
1366     BLI_mempool_iternew(mempool, &iter);
1367
1368     for (void *item = BLI_mempool_iterstep(&iter); item != NULL;
1369          item = BLI_mempool_iterstep(&iter)) {
1370       func(userdata, item);
1371     }
1372     return;
1373   }
1374
1375   task_scheduler = BLI_task_scheduler_get();
1376   task_pool = BLI_task_pool_create_suspended(task_scheduler, &state);
1377   num_threads = BLI_task_scheduler_num_threads(task_scheduler);
1378
1379   /* The idea here is to prevent creating task for each of the loop iterations
1380    * and instead have tasks which are evenly distributed across CPU cores and
1381    * pull next item to be crunched using the threaded-aware BLI_mempool_iter.
1382    */
1383   num_tasks = num_threads + 2;
1384
1385   state.userdata = userdata;
1386   state.func = func;
1387
1388   BLI_mempool_iter *mempool_iterators = BLI_mempool_iter_threadsafe_create(mempool,
1389                                                                            (size_t)num_tasks);
1390
1391   for (i = 0; i < num_tasks; i++) {
1392     /* Use this pool's pre-allocated tasks. */
1393     BLI_task_pool_push_from_thread(task_pool,
1394                                    parallel_mempool_func,
1395                                    &mempool_iterators[i],
1396                                    false,
1397                                    TASK_PRIORITY_HIGH,
1398                                    task_pool->thread_id);
1399   }
1400
1401   BLI_task_pool_work_and_wait(task_pool);
1402   BLI_task_pool_free(task_pool);
1403
1404   BLI_mempool_iter_threadsafe_free(mempool_iterators);
1405 }