24# include <sys/timeb.h>
26#elif defined(__APPLE__)
27# include <sys/sysctl.h>
28# include <sys/types.h>
35# include <tbb/spin_mutex.h>
90static pthread_mutex_t
_image_lock = PTHREAD_MUTEX_INITIALIZER;
94static pthread_mutex_t
_nodes_lock = PTHREAD_MUTEX_INITIALIZER;
97static pthread_mutex_t
_fftw_lock = PTHREAD_MUTEX_INITIALIZER;
104#define RE_MAX_THREAD BLENDER_MAX_THREADS
108 void *(*do_thread)(
void *);
125 if (threadbase !=
nullptr && tot > 0) {
135 for (a = 0; a < tot; a++) {
181 return pthread_equal(pthread_self(),
mainid);
189 tslot->callerdata = callerdata;
194 printf(
"ERROR: could not insert thread slot\n");
200 if (tslot->callerdata == callerdata) {
201 pthread_join(tslot->pthread,
nullptr);
202 tslot->callerdata =
nullptr;
213 if (counter == index && tslot->avail == 0) {
214 pthread_join(tslot->pthread,
nullptr);
215 tslot->callerdata =
nullptr;
226 if (tslot->avail == 0) {
227 pthread_join(tslot->pthread,
nullptr);
228 tslot->callerdata =
nullptr;
244 if (tslot->avail == 0) {
245 pthread_join(tslot->pthread,
nullptr);
267 GetSystemInfo(&info);
268 t = int(info.dwNumberOfProcessors);
277 sysctl(mib, 2, &t, &
len,
nullptr, 0);
279 t = int(sysconf(_SC_NPROCESSORS_ONLN));
342 pthread_mutex_init(
mutex,
nullptr);
347 pthread_mutex_lock(
mutex);
352 pthread_mutex_unlock(
mutex);
357 return (pthread_mutex_trylock(
mutex) == 0);
362 pthread_mutex_destroy(
mutex);
381static tbb::spin_mutex *tbb_spin_mutex_cast(
SpinLock *spin)
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);
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)
401 pthread_spin_init(spin, 0);
408 tbb::spin_mutex *spin_mutex = tbb_spin_mutex_cast(spin);
410#elif defined(__APPLE__)
412#elif defined(_MSC_VER)
413# if defined(_M_ARM64)
416 while (InterlockedExchangeAcquire((
volatile long *)spin, 1)) {
418 while (InterlockedExchangeAcquire(spin, 1)) {
426 pthread_spin_lock(spin);
433 tbb::spin_mutex *spin_mutex = tbb_spin_mutex_cast(spin);
434 spin_mutex->unlock();
435#elif defined(__APPLE__)
437#elif defined(_MSC_VER)
441 pthread_spin_unlock(spin);
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)
456 pthread_spin_destroy(spin);
464 pthread_rwlock_init(
mutex,
nullptr);
470 pthread_rwlock_rdlock(
mutex);
473 pthread_rwlock_wrlock(
mutex);
479 pthread_rwlock_unlock(
mutex);
484 pthread_rwlock_destroy(
mutex);
514 pthread_cond_init(&ticket->
cond,
nullptr);
515 pthread_mutex_init(&ticket->
mutex,
nullptr);
522 pthread_mutex_destroy(&ticket->
mutex);
523 pthread_cond_destroy(&ticket->
cond);
531 pthread_mutex_lock(&ticket->
mutex);
534 if (check_recursive && ticket->
has_owner && pthread_equal(pthread_self(), ticket->
owner)) {
535 pthread_mutex_unlock(&ticket->
mutex);
542 pthread_cond_wait(&ticket->
cond, &ticket->
mutex);
545 ticket->
owner = pthread_self();
548 pthread_mutex_unlock(&ticket->
mutex);
564 pthread_mutex_lock(&ticket->
mutex);
567 pthread_cond_broadcast(&ticket->
cond);
568 pthread_mutex_unlock(&ticket->
mutex);
577 pthread_cond_init(cond,
nullptr);
582 pthread_cond_wait(cond,
mutex);
592 pthread_cond_signal(cond);
597 pthread_cond_broadcast(cond);
602 pthread_cond_destroy(cond);
626 ThreadQueue *queue = MEM_new<ThreadQueue>(__func__);
628 pthread_mutex_init(&queue->
mutex,
nullptr);
629 pthread_cond_init(&queue->
push_cond,
nullptr);
640 pthread_mutex_destroy(&queue->
mutex);
649 pthread_mutex_lock(&queue->
mutex);
652 work_reference.
work = work;
669 pthread_mutex_unlock(&queue->
mutex);
671 return work_reference.
id;
686 pthread_mutex_lock(&queue->
mutex);
690 if (work.id == work_id) {
697 auto cancel = [&](std::deque<ThreadQueueWork> &sub_queue) {
698 sub_queue.erase(std::remove_if(sub_queue.begin(), sub_queue.end(), check), sub_queue.end());
709 pthread_mutex_unlock(&queue->
mutex);
717 pthread_mutex_lock(&queue->
mutex);
725 for (std::deque<ThreadQueueWork> *sub_queue :
728 if (sub_queue->empty()) {
731 work_reference = sub_queue->front();
732 sub_queue->pop_front();
738 if (work_reference.
work) {
742 pthread_mutex_unlock(&queue->
mutex);
744 return work_reference.
work;
757 usec = now.millitm * 1000;
762 gettimeofday(&now,
nullptr);
769 div_result = ldiv(ms, 1000);
770 timeout->tv_sec = sec + div_result.quot;
772 x = usec + (div_result.rem * 1000);
779 timeout->tv_nsec =
x * 1000;
792 pthread_mutex_lock(&queue->
mutex);
796 if (pthread_cond_timedwait(&queue->
push_cond, &queue->
mutex, &timeout) == ETIMEDOUT) {
805 for (std::deque<ThreadQueueWork> *sub_queue :
808 if (sub_queue->empty()) {
811 work_reference = sub_queue->front();
812 sub_queue->pop_front();
818 if (work_reference.
work) {
822 pthread_mutex_unlock(&queue->
mutex);
824 return work_reference.
work;
831 pthread_mutex_lock(&queue->
mutex);
834 pthread_mutex_unlock(&queue->
mutex);
843 pthread_mutex_lock(&queue->
mutex);
846 pthread_mutex_unlock(&queue->
mutex);
853 pthread_mutex_lock(&queue->
mutex);
858 pthread_cond_broadcast(&queue->
push_cond);
859 pthread_mutex_unlock(&queue->
mutex);
865 pthread_mutex_lock(&queue->
mutex);
873 pthread_mutex_unlock(&queue->
mutex);
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
ATTR_WARN_UNUSED_RESULT const size_t num
@ BLI_THREAD_QUEUE_WORK_PRIORITY_LOW
@ BLI_THREAD_QUEUE_WORK_PRIORITY_HIGH
@ BLI_THREAD_QUEUE_WORK_PRIORITY_NORMAL
pthread_spinlock_t SpinLock
pthread_rwlock_t ThreadRWMutex
pthread_cond_t ThreadCondition
pthread_mutex_t ThreadMutex
Platform independent time functions.
double BLI_time_now_seconds(void)
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)
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
void * MEM_callocN(size_t len, const char *str)
void MEM_freeN(void *vmemh)
std::deque< ThreadQueueWork > queue_low_priority
std::deque< ThreadQueueWork > queue_high_priority
pthread_cond_t finish_cond
std::deque< ThreadQueueWork > queue_normal_priority
void *(* do_thread)(void *)
void BLI_condition_notify_all(ThreadCondition *cond)
void BLI_thread_queue_cancel_work(ThreadQueue *queue, uint64_t work_id)
bool BLI_mutex_trylock(ThreadMutex *mutex)
void BLI_rw_mutex_end(ThreadRWMutex *mutex)
void BLI_threadapi_init()
void * BLI_thread_queue_pop(ThreadQueue *queue)
void BLI_thread_unlock(int type)
void BLI_ticket_mutex_unlock(TicketMutex *ticket)
ThreadRWMutex * BLI_rw_mutex_alloc()
static pthread_mutex_t _image_lock
void BLI_mutex_end(ThreadMutex *mutex)
static void * tslot_thread_start(void *tslot_p)
void BLI_threadapi_exit()
void BLI_mutex_free(ThreadMutex *mutex)
static pthread_mutex_t _custom1_lock
void BLI_threadpool_clear(ListBase *threadbase)
void BLI_threadpool_init(ListBase *threadbase, void *(*do_thread)(void *), int tot)
void BLI_thread_lock(int type)
bool BLI_ticket_mutex_lock_check_recursive(TicketMutex *ticket)
void BLI_threadpool_remove(ListBase *threadbase, void *callerdata)
TicketMutex * BLI_ticket_mutex_alloc()
static pthread_mutex_t _view3d_lock
void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
int BLI_system_num_threads_override_get()
static int threads_override_num
int BLI_threadpool_available_thread_index(ListBase *threadbase)
static void wait_timeout(timespec *timeout, int ms)
static bool ticket_mutex_lock(TicketMutex *ticket, const bool check_recursive)
void BLI_mutex_init(ThreadMutex *mutex)
static pthread_mutex_t _viewer_lock
void BLI_system_num_threads_override_set(int num)
void BLI_condition_end(ThreadCondition *cond)
static ThreadMutex * global_mutex_from_type(const int type)
void BLI_thread_queue_free(ThreadQueue *queue)
static uint thread_levels
ThreadQueue * BLI_thread_queue_init()
static pthread_mutex_t _colormanage_lock
static pthread_mutex_t _fftw_lock
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
void BLI_ticket_mutex_lock(TicketMutex *ticket)
void BLI_condition_notify_one(ThreadCondition *cond)
bool BLI_thread_queue_is_empty(ThreadQueue *queue)
void BLI_ticket_mutex_free(TicketMutex *ticket)
void BLI_condition_wait_global_mutex(ThreadCondition *cond, const int type)
uint64_t BLI_thread_queue_push(ThreadQueue *queue, void *work, ThreadQueueWorkPriority priority)
static pthread_mutex_t _image_draw_lock
static void check_finalization(ThreadQueue *queue)
void BLI_threadpool_end(ListBase *threadbase)
void BLI_condition_init(ThreadCondition *cond)
void BLI_mutex_lock(ThreadMutex *mutex)
void BLI_thread_queue_nowait(ThreadQueue *queue)
int BLI_system_thread_count()
void BLI_thread_queue_wait_finish(ThreadQueue *queue)
void BLI_mutex_unlock(ThreadMutex *mutex)
void BLI_rw_mutex_init(ThreadRWMutex *mutex)
static pthread_mutex_t _nodes_lock
void BLI_threadpool_insert(ListBase *threadbase, void *callerdata)
static pthread_mutex_t _movieclip_lock
void BLI_spin_init(SpinLock *spin)
void BLI_spin_unlock(SpinLock *spin)
void BLI_threadpool_remove_index(ListBase *threadbase, int index)
int BLI_available_threads(ListBase *threadbase)
void BLI_spin_lock(SpinLock *spin)
void BLI_rw_mutex_free(ThreadRWMutex *mutex)
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
void BLI_spin_end(SpinLock *spin)
ThreadMutex * BLI_mutex_alloc()
void * BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)
int BLI_thread_queue_len(ThreadQueue *queue)