Blender V4.3
threads.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2006 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cerrno>
10#include <cstdlib>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_gsqueue.h"
16#include "BLI_listbase.h"
17#include "BLI_system.h"
18#include "BLI_task.h"
19#include "BLI_threads.h"
20#include "BLI_time.h"
21
22/* for checking system threads - BLI_system_thread_count */
23#ifdef WIN32
24# include <sys/timeb.h>
25# include <windows.h>
26#elif defined(__APPLE__)
27# include <sys/sysctl.h>
28# include <sys/types.h>
29#else
30# include <sys/time.h>
31# include <unistd.h>
32#endif
33
34#ifdef WITH_TBB
35# include <tbb/spin_mutex.h>
36#endif
37
38#include "atomic_ops.h"
39
90static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER;
91static pthread_mutex_t _image_draw_lock = PTHREAD_MUTEX_INITIALIZER;
92static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER;
93static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER;
94static pthread_mutex_t _nodes_lock = PTHREAD_MUTEX_INITIALIZER;
95static pthread_mutex_t _movieclip_lock = PTHREAD_MUTEX_INITIALIZER;
96static pthread_mutex_t _colormanage_lock = PTHREAD_MUTEX_INITIALIZER;
97static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER;
98static pthread_mutex_t _view3d_lock = PTHREAD_MUTEX_INITIALIZER;
99static pthread_t mainid;
100static uint thread_levels = 0; /* threads can be invoked inside threads */
101static int threads_override_num = 0;
102
103/* just a max for security reasons */
104#define RE_MAX_THREAD BLENDER_MAX_THREADS
105
108 void *(*do_thread)(void *);
110 pthread_t pthread;
111 int avail;
112};
113
115{
116 mainid = pthread_self();
117}
118
120
121void BLI_threadpool_init(ListBase *threadbase, void *(*do_thread)(void *), int tot)
122{
123 int a;
124
125 if (threadbase != nullptr && tot > 0) {
126 BLI_listbase_clear(threadbase);
127
128 if (tot > RE_MAX_THREAD) {
129 tot = RE_MAX_THREAD;
130 }
131 else if (tot < 1) {
132 tot = 1;
133 }
134
135 for (a = 0; a < tot; a++) {
136 ThreadSlot *tslot = static_cast<ThreadSlot *>(MEM_callocN(sizeof(ThreadSlot), "threadslot"));
137 BLI_addtail(threadbase, tslot);
138 tslot->do_thread = do_thread;
139 tslot->avail = 1;
140 }
141 }
142
144}
145
147{
148 int counter = 0;
149
150 LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
151 if (tslot->avail) {
152 counter++;
153 }
154 }
155
156 return counter;
157}
158
160{
161 int counter = 0;
162
163 LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
164 if (tslot->avail) {
165 return counter;
166 }
167 ++counter;
168 }
169
170 return 0;
171}
172
173static void *tslot_thread_start(void *tslot_p)
174{
175 ThreadSlot *tslot = (ThreadSlot *)tslot_p;
176 return tslot->do_thread(tslot->callerdata);
177}
178
180{
181 return pthread_equal(pthread_self(), mainid);
182}
183
184void BLI_threadpool_insert(ListBase *threadbase, void *callerdata)
185{
186 LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
187 if (tslot->avail) {
188 tslot->avail = 0;
189 tslot->callerdata = callerdata;
190 pthread_create(&tslot->pthread, nullptr, tslot_thread_start, tslot);
191 return;
192 }
193 }
194 printf("ERROR: could not insert thread slot\n");
195}
196
197void BLI_threadpool_remove(ListBase *threadbase, void *callerdata)
198{
199 LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
200 if (tslot->callerdata == callerdata) {
201 pthread_join(tslot->pthread, nullptr);
202 tslot->callerdata = nullptr;
203 tslot->avail = 1;
204 }
205 }
206}
207
208void BLI_threadpool_remove_index(ListBase *threadbase, int index)
209{
210 int counter = 0;
211
212 LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
213 if (counter == index && tslot->avail == 0) {
214 pthread_join(tslot->pthread, nullptr);
215 tslot->callerdata = nullptr;
216 tslot->avail = 1;
217 break;
218 }
219 ++counter;
220 }
221}
222
224{
225 LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
226 if (tslot->avail == 0) {
227 pthread_join(tslot->pthread, nullptr);
228 tslot->callerdata = nullptr;
229 tslot->avail = 1;
230 }
231 }
232}
233
235{
236
237 /* Only needed if there's actually some stuff to end
238 * this way we don't end up decrementing thread_levels on an empty `threadbase`. */
239 if (threadbase == nullptr || BLI_listbase_is_empty(threadbase)) {
240 return;
241 }
242
243 LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
244 if (tslot->avail == 0) {
245 pthread_join(tslot->pthread, nullptr);
246 }
247 }
248 BLI_freelistN(threadbase);
249}
250
251/* System Information */
252
254{
255 static int t = -1;
256
257 if (threads_override_num != 0) {
259 }
260 if (LIKELY(t != -1)) {
261 return t;
262 }
263
264 {
265#ifdef WIN32
266 SYSTEM_INFO info;
267 GetSystemInfo(&info);
268 t = int(info.dwNumberOfProcessors);
269#else
270# ifdef __APPLE__
271 int mib[2];
272 size_t len;
273
274 mib[0] = CTL_HW;
275 mib[1] = HW_NCPU;
276 len = sizeof(t);
277 sysctl(mib, 2, &t, &len, nullptr, 0);
278# else
279 t = int(sysconf(_SC_NPROCESSORS_ONLN));
280# endif
281#endif
282 }
283
284 CLAMP(t, 1, RE_MAX_THREAD);
285
286 return t;
287}
288
293
298
299/* Global Mutex Locks */
300
301static ThreadMutex *global_mutex_from_type(const int type)
302{
303 switch (type) {
304 case LOCK_IMAGE:
305 return &_image_lock;
306 case LOCK_DRAW_IMAGE:
307 return &_image_draw_lock;
308 case LOCK_VIEWER:
309 return &_viewer_lock;
310 case LOCK_CUSTOM1:
311 return &_custom1_lock;
312 case LOCK_NODES:
313 return &_nodes_lock;
314 case LOCK_MOVIECLIP:
315 return &_movieclip_lock;
316 case LOCK_COLORMANAGE:
317 return &_colormanage_lock;
318 case LOCK_FFTW:
319 return &_fftw_lock;
320 case LOCK_VIEW3D:
321 return &_view3d_lock;
322 default:
324 return nullptr;
325 }
326}
327
328void BLI_thread_lock(int type)
329{
330 pthread_mutex_lock(global_mutex_from_type(type));
331}
332
333void BLI_thread_unlock(int type)
334{
335 pthread_mutex_unlock(global_mutex_from_type(type));
336}
337
338/* Mutex Locks */
339
341{
342 pthread_mutex_init(mutex, nullptr);
343}
344
346{
347 pthread_mutex_lock(mutex);
348}
349
351{
352 pthread_mutex_unlock(mutex);
353}
354
356{
357 return (pthread_mutex_trylock(mutex) == 0);
358}
359
361{
362 pthread_mutex_destroy(mutex);
363}
364
366{
367 ThreadMutex *mutex = static_cast<ThreadMutex *>(MEM_callocN(sizeof(ThreadMutex), "ThreadMutex"));
369 return mutex;
370}
371
377
378/* Spin Locks */
379
380#ifdef WITH_TBB
381static tbb::spin_mutex *tbb_spin_mutex_cast(SpinLock *spin)
382{
383 static_assert(sizeof(SpinLock) >= sizeof(tbb::spin_mutex),
384 "SpinLock must match tbb::spin_mutex");
385 static_assert(alignof(SpinLock) % alignof(tbb::spin_mutex) == 0,
386 "SpinLock must be aligned same as tbb::spin_mutex");
387 return reinterpret_cast<tbb::spin_mutex *>(spin);
388}
389#endif
390
392{
393#ifdef WITH_TBB
394 tbb::spin_mutex *spin_mutex = tbb_spin_mutex_cast(spin);
395 new (spin_mutex) tbb::spin_mutex();
396#elif defined(__APPLE__)
398#elif defined(_MSC_VER)
399 *spin = 0;
400#else
401 pthread_spin_init(spin, 0);
402#endif
403}
404
406{
407#ifdef WITH_TBB
408 tbb::spin_mutex *spin_mutex = tbb_spin_mutex_cast(spin);
409 spin_mutex->lock();
410#elif defined(__APPLE__)
412#elif defined(_MSC_VER)
413# if defined(_M_ARM64)
414 // InterlockedExchangeAcquire takes a long arg on MSVC ARM64
415 static_assert(sizeof(long) == sizeof(SpinLock));
416 while (InterlockedExchangeAcquire((volatile long *)spin, 1)) {
417# else
418 while (InterlockedExchangeAcquire(spin, 1)) {
419# endif
420 while (*spin) {
421 /* Spin-lock hint for processors with hyper-threading. */
422 YieldProcessor();
423 }
424 }
425#else
426 pthread_spin_lock(spin);
427#endif
428}
429
431{
432#ifdef WITH_TBB
433 tbb::spin_mutex *spin_mutex = tbb_spin_mutex_cast(spin);
434 spin_mutex->unlock();
435#elif defined(__APPLE__)
437#elif defined(_MSC_VER)
438 _ReadWriteBarrier();
439 *spin = 0;
440#else
441 pthread_spin_unlock(spin);
442#endif
443}
444
446{
447#ifdef WITH_TBB
448 tbb::spin_mutex *spin_mutex = tbb_spin_mutex_cast(spin);
449 spin_mutex->~spin_mutex();
450#elif defined(__APPLE__)
452#elif defined(_MSC_VER)
453 /* Nothing to do, spin is a simple integer type. */
455#else
456 pthread_spin_destroy(spin);
457#endif
458}
459
460/* Read/Write Mutex Lock */
461
463{
464 pthread_rwlock_init(mutex, nullptr);
465}
466
468{
469 if (mode == THREAD_LOCK_READ) {
470 pthread_rwlock_rdlock(mutex);
471 }
472 else {
473 pthread_rwlock_wrlock(mutex);
474 }
475}
476
478{
479 pthread_rwlock_unlock(mutex);
480}
481
483{
484 pthread_rwlock_destroy(mutex);
485}
486
488{
489 ThreadRWMutex *mutex = static_cast<ThreadRWMutex *>(
490 MEM_callocN(sizeof(ThreadRWMutex), "ThreadRWMutex"));
492 return mutex;
493}
494
500
501/* Ticket Mutex Lock */
502
504 pthread_cond_t cond;
505 pthread_mutex_t mutex;
507 pthread_t owner;
509};
510
512{
513 TicketMutex *ticket = static_cast<TicketMutex *>(
514 MEM_callocN(sizeof(TicketMutex), "TicketMutex"));
515
516 pthread_cond_init(&ticket->cond, nullptr);
517 pthread_mutex_init(&ticket->mutex, nullptr);
518
519 return ticket;
520}
521
523{
524 pthread_mutex_destroy(&ticket->mutex);
525 pthread_cond_destroy(&ticket->cond);
526 MEM_freeN(ticket);
527}
528
529static bool ticket_mutex_lock(TicketMutex *ticket, const bool check_recursive)
530{
531 uint queue_me;
532
533 pthread_mutex_lock(&ticket->mutex);
534
535 /* Check for recursive locks, for debugging only. */
536 if (check_recursive && ticket->has_owner && pthread_equal(pthread_self(), ticket->owner)) {
537 pthread_mutex_unlock(&ticket->mutex);
538 return false;
539 }
540
541 queue_me = ticket->queue_tail++;
542
543 while (queue_me != ticket->queue_head) {
544 pthread_cond_wait(&ticket->cond, &ticket->mutex);
545 }
546
547 ticket->owner = pthread_self();
548 ticket->has_owner = true;
549
550 pthread_mutex_unlock(&ticket->mutex);
551 return true;
552}
553
555{
556 ticket_mutex_lock(ticket, false);
557}
558
560{
561 return ticket_mutex_lock(ticket, true);
562}
563
565{
566 pthread_mutex_lock(&ticket->mutex);
567 ticket->queue_head++;
568 ticket->has_owner = false;
569 pthread_cond_broadcast(&ticket->cond);
570 pthread_mutex_unlock(&ticket->mutex);
571}
572
573/* ************************************************ */
574
575/* Condition */
576
578{
579 pthread_cond_init(cond, nullptr);
580}
581
583{
584 pthread_cond_wait(cond, mutex);
585}
586
588{
589 pthread_cond_wait(cond, global_mutex_from_type(type));
590}
591
593{
594 pthread_cond_signal(cond);
595}
596
598{
599 pthread_cond_broadcast(cond);
600}
601
603{
604 pthread_cond_destroy(cond);
605}
606
607/* ************************************************ */
608
611 pthread_mutex_t mutex;
612 pthread_cond_t push_cond;
613 pthread_cond_t finish_cond;
614 volatile int nowait;
615 volatile int canceled;
616};
617
619{
620 ThreadQueue *queue;
621
622 queue = static_cast<ThreadQueue *>(MEM_callocN(sizeof(ThreadQueue), "ThreadQueue"));
623 queue->queue = BLI_gsqueue_new(sizeof(void *));
624
625 pthread_mutex_init(&queue->mutex, nullptr);
626 pthread_cond_init(&queue->push_cond, nullptr);
627 pthread_cond_init(&queue->finish_cond, nullptr);
628
629 return queue;
630}
631
633{
634 /* destroy everything, assumes no one is using queue anymore */
635 pthread_cond_destroy(&queue->finish_cond);
636 pthread_cond_destroy(&queue->push_cond);
637 pthread_mutex_destroy(&queue->mutex);
638
639 BLI_gsqueue_free(queue->queue);
640
641 MEM_freeN(queue);
642}
643
644void BLI_thread_queue_push(ThreadQueue *queue, void *work)
645{
646 pthread_mutex_lock(&queue->mutex);
647
648 BLI_gsqueue_push(queue->queue, &work);
649
650 /* signal threads waiting to pop */
651 pthread_cond_signal(&queue->push_cond);
652 pthread_mutex_unlock(&queue->mutex);
653}
654
656{
657 void *work = nullptr;
658
659 /* wait until there is work */
660 pthread_mutex_lock(&queue->mutex);
661 while (BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) {
662 pthread_cond_wait(&queue->push_cond, &queue->mutex);
663 }
664
665 /* if we have something, pop it */
666 if (!BLI_gsqueue_is_empty(queue->queue)) {
667 BLI_gsqueue_pop(queue->queue, &work);
668
669 if (BLI_gsqueue_is_empty(queue->queue)) {
670 pthread_cond_broadcast(&queue->finish_cond);
671 }
672 }
673
674 pthread_mutex_unlock(&queue->mutex);
675
676 return work;
677}
678
679static void wait_timeout(timespec *timeout, int ms)
680{
681 ldiv_t div_result;
682 long sec, usec, x;
683
684#ifdef WIN32
685 {
686 struct _timeb now;
687 _ftime(&now);
688 sec = now.time;
689 usec = now.millitm * 1000; /* microsecond precision would be better */
690 }
691#else
692 {
693 timeval now;
694 gettimeofday(&now, nullptr);
695 sec = now.tv_sec;
696 usec = now.tv_usec;
697 }
698#endif
699
700 /* add current time + millisecond offset */
701 div_result = ldiv(ms, 1000);
702 timeout->tv_sec = sec + div_result.quot;
703
704 x = usec + (div_result.rem * 1000);
705
706 if (x >= 1000000) {
707 timeout->tv_sec++;
708 x -= 1000000;
709 }
710
711 timeout->tv_nsec = x * 1000;
712}
713
715{
716 double t;
717 void *work = nullptr;
718 timespec timeout;
719
721 wait_timeout(&timeout, ms);
722
723 /* wait until there is work */
724 pthread_mutex_lock(&queue->mutex);
725 while (BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) {
726 if (pthread_cond_timedwait(&queue->push_cond, &queue->mutex, &timeout) == ETIMEDOUT) {
727 break;
728 }
729 if (BLI_time_now_seconds() - t >= ms * 0.001) {
730 break;
731 }
732 }
733
734 /* if we have something, pop it */
735 if (!BLI_gsqueue_is_empty(queue->queue)) {
736 BLI_gsqueue_pop(queue->queue, &work);
737
738 if (BLI_gsqueue_is_empty(queue->queue)) {
739 pthread_cond_broadcast(&queue->finish_cond);
740 }
741 }
742
743 pthread_mutex_unlock(&queue->mutex);
744
745 return work;
746}
747
749{
750 int size;
751
752 pthread_mutex_lock(&queue->mutex);
753 size = BLI_gsqueue_len(queue->queue);
754 pthread_mutex_unlock(&queue->mutex);
755
756 return size;
757}
758
760{
761 bool is_empty;
762
763 pthread_mutex_lock(&queue->mutex);
764 is_empty = BLI_gsqueue_is_empty(queue->queue);
765 pthread_mutex_unlock(&queue->mutex);
766
767 return is_empty;
768}
769
771{
772 pthread_mutex_lock(&queue->mutex);
773
774 queue->nowait = 1;
775
776 /* signal threads waiting to pop */
777 pthread_cond_broadcast(&queue->push_cond);
778 pthread_mutex_unlock(&queue->mutex);
779}
780
782{
783 /* wait for finish condition */
784 pthread_mutex_lock(&queue->mutex);
785
786 while (!BLI_gsqueue_is_empty(queue->queue)) {
787 pthread_cond_wait(&queue->finish_cond, &queue->mutex);
788 }
789
790 pthread_mutex_unlock(&queue->mutex);
791}
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
void BLI_gsqueue_free(GSQueue *queue)
Definition gsqueue.c:93
void BLI_gsqueue_push(GSQueue *queue, const void *item)
Definition gsqueue.c:100
void BLI_gsqueue_pop(GSQueue *queue, void *r_item)
Definition gsqueue.c:134
GSQueue * BLI_gsqueue_new(size_t elem_size)
Definition gsqueue.c:72
bool BLI_gsqueue_is_empty(const GSQueue *queue)
Definition gsqueue.c:162
size_t BLI_gsqueue_len(const GSQueue *queue)
Definition gsqueue.c:157
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
unsigned int uint
pthread_spinlock_t SpinLock
pthread_rwlock_t ThreadRWMutex
#define THREAD_LOCK_READ
pthread_cond_t ThreadCondition
@ LOCK_NODES
Definition BLI_threads.h:71
@ LOCK_VIEW3D
Definition BLI_threads.h:75
@ LOCK_DRAW_IMAGE
Definition BLI_threads.h:68
@ LOCK_COLORMANAGE
Definition BLI_threads.h:73
@ LOCK_MOVIECLIP
Definition BLI_threads.h:72
@ LOCK_CUSTOM1
Definition BLI_threads.h:70
@ LOCK_IMAGE
Definition BLI_threads.h:67
@ LOCK_VIEWER
Definition BLI_threads.h:69
@ LOCK_FFTW
Definition BLI_threads.h:74
pthread_mutex_t ThreadMutex
Definition BLI_threads.h:83
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.c:65
#define CLAMP(a, b, c)
#define UNUSED_VARS(...)
#define LIKELY(x)
ThreadMutex mutex
Read Guarded memory(de)allocation.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE unsigned int atomic_fetch_and_add_u(unsigned int *p, unsigned int x)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static SpinLock spin
Definition cachefile.cc:154
#define printf
int len
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
volatile int nowait
Definition threads.cc:614
volatile int canceled
Definition threads.cc:615
GSQueue * queue
Definition threads.cc:610
pthread_cond_t push_cond
Definition threads.cc:612
pthread_cond_t finish_cond
Definition threads.cc:613
pthread_mutex_t mutex
Definition threads.cc:611
void * callerdata
Definition threads.cc:109
void *(* do_thread)(void *)
Definition threads.cc:108
pthread_t pthread
Definition threads.cc:110
ThreadSlot * next
Definition threads.cc:107
ThreadSlot * prev
Definition threads.cc:107
bool has_owner
Definition threads.cc:508
pthread_cond_t cond
Definition threads.cc:504
pthread_t owner
Definition threads.cc:507
uint queue_head
Definition threads.cc:506
pthread_mutex_t mutex
Definition threads.cc:505
uint queue_tail
Definition threads.cc:506
void BLI_condition_notify_all(ThreadCondition *cond)
Definition threads.cc:597
bool BLI_mutex_trylock(ThreadMutex *mutex)
Definition threads.cc:355
void BLI_rw_mutex_end(ThreadRWMutex *mutex)
Definition threads.cc:482
void BLI_thread_queue_push(ThreadQueue *queue, void *work)
Definition threads.cc:644
void BLI_threadapi_init()
Definition threads.cc:114
void * BLI_thread_queue_pop(ThreadQueue *queue)
Definition threads.cc:655
void BLI_thread_unlock(int type)
Definition threads.cc:333
void BLI_ticket_mutex_unlock(TicketMutex *ticket)
Definition threads.cc:564
ThreadRWMutex * BLI_rw_mutex_alloc()
Definition threads.cc:487
static pthread_mutex_t _image_lock
Definition threads.cc:90
void BLI_mutex_end(ThreadMutex *mutex)
Definition threads.cc:360
static void * tslot_thread_start(void *tslot_p)
Definition threads.cc:173
#define RE_MAX_THREAD
Definition threads.cc:104
void BLI_threadapi_exit()
Definition threads.cc:119
void BLI_mutex_free(ThreadMutex *mutex)
Definition threads.cc:372
static pthread_mutex_t _custom1_lock
Definition threads.cc:93
void BLI_threadpool_clear(ListBase *threadbase)
Definition threads.cc:223
void BLI_threadpool_init(ListBase *threadbase, void *(*do_thread)(void *), int tot)
Definition threads.cc:121
void BLI_thread_lock(int type)
Definition threads.cc:328
int BLI_thread_is_main()
Definition threads.cc:179
bool BLI_ticket_mutex_lock_check_recursive(TicketMutex *ticket)
Definition threads.cc:559
void BLI_threadpool_remove(ListBase *threadbase, void *callerdata)
Definition threads.cc:197
TicketMutex * BLI_ticket_mutex_alloc()
Definition threads.cc:511
static pthread_mutex_t _view3d_lock
Definition threads.cc:98
void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
Definition threads.cc:582
int BLI_system_num_threads_override_get()
Definition threads.cc:294
static int threads_override_num
Definition threads.cc:101
int BLI_threadpool_available_thread_index(ListBase *threadbase)
Definition threads.cc:159
static void wait_timeout(timespec *timeout, int ms)
Definition threads.cc:679
static bool ticket_mutex_lock(TicketMutex *ticket, const bool check_recursive)
Definition threads.cc:529
void BLI_mutex_init(ThreadMutex *mutex)
Definition threads.cc:340
static pthread_mutex_t _viewer_lock
Definition threads.cc:92
void BLI_system_num_threads_override_set(int num)
Definition threads.cc:289
void BLI_condition_end(ThreadCondition *cond)
Definition threads.cc:602
static ThreadMutex * global_mutex_from_type(const int type)
Definition threads.cc:301
void BLI_thread_queue_free(ThreadQueue *queue)
Definition threads.cc:632
static uint thread_levels
Definition threads.cc:100
ThreadQueue * BLI_thread_queue_init()
Definition threads.cc:618
static pthread_mutex_t _colormanage_lock
Definition threads.cc:96
static pthread_mutex_t _fftw_lock
Definition threads.cc:97
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
Definition threads.cc:467
void BLI_ticket_mutex_lock(TicketMutex *ticket)
Definition threads.cc:554
void BLI_condition_notify_one(ThreadCondition *cond)
Definition threads.cc:592
bool BLI_thread_queue_is_empty(ThreadQueue *queue)
Definition threads.cc:759
void BLI_ticket_mutex_free(TicketMutex *ticket)
Definition threads.cc:522
void BLI_condition_wait_global_mutex(ThreadCondition *cond, const int type)
Definition threads.cc:587
static pthread_mutex_t _image_draw_lock
Definition threads.cc:91
void BLI_threadpool_end(ListBase *threadbase)
Definition threads.cc:234
void BLI_condition_init(ThreadCondition *cond)
Definition threads.cc:577
static pthread_t mainid
Definition threads.cc:99
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_thread_queue_nowait(ThreadQueue *queue)
Definition threads.cc:770
int BLI_system_thread_count()
Definition threads.cc:253
void BLI_thread_queue_wait_finish(ThreadQueue *queue)
Definition threads.cc:781
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
void BLI_rw_mutex_init(ThreadRWMutex *mutex)
Definition threads.cc:462
static pthread_mutex_t _nodes_lock
Definition threads.cc:94
void BLI_threadpool_insert(ListBase *threadbase, void *callerdata)
Definition threads.cc:184
static pthread_mutex_t _movieclip_lock
Definition threads.cc:95
void BLI_spin_init(SpinLock *spin)
Definition threads.cc:391
void BLI_spin_unlock(SpinLock *spin)
Definition threads.cc:430
void BLI_threadpool_remove_index(ListBase *threadbase, int index)
Definition threads.cc:208
int BLI_available_threads(ListBase *threadbase)
Definition threads.cc:146
void BLI_spin_lock(SpinLock *spin)
Definition threads.cc:405
void BLI_rw_mutex_free(ThreadRWMutex *mutex)
Definition threads.cc:495
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
Definition threads.cc:477
void BLI_spin_end(SpinLock *spin)
Definition threads.cc:445
ThreadMutex * BLI_mutex_alloc()
Definition threads.cc:365
void * BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)
Definition threads.cc:714
int BLI_thread_queue_len(ThreadQueue *queue)
Definition threads.cc:748