Blender  V3.3
threads.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2006 Blender Foundation. All rights reserved. */
3 
8 #include <cerrno>
9 #include <cstdlib>
10 #include <cstring>
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "BLI_gsqueue.h"
15 #include "BLI_listbase.h"
16 #include "BLI_system.h"
17 #include "BLI_task.h"
18 #include "BLI_threads.h"
19 
20 #include "PIL_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 
40 #if defined(__APPLE__) && defined(_OPENMP) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) && \
41  !defined(__clang__)
42 # define USE_APPLE_OMP_FIX
43 #endif
44 
45 #ifdef USE_APPLE_OMP_FIX
46 /* ************** libgomp (Apple gcc 4.2.1) TLS bug workaround *************** */
47 extern pthread_key_t gomp_tls_key;
48 static void *thread_tls_data;
49 #endif
50 
101 static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER;
102 static pthread_mutex_t _image_draw_lock = PTHREAD_MUTEX_INITIALIZER;
103 static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER;
104 static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER;
105 static pthread_mutex_t _nodes_lock = PTHREAD_MUTEX_INITIALIZER;
106 static pthread_mutex_t _movieclip_lock = PTHREAD_MUTEX_INITIALIZER;
107 static pthread_mutex_t _colormanage_lock = PTHREAD_MUTEX_INITIALIZER;
108 static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER;
109 static pthread_mutex_t _view3d_lock = PTHREAD_MUTEX_INITIALIZER;
110 static pthread_t mainid;
111 static unsigned int thread_levels = 0; /* threads can be invoked inside threads */
112 static int threads_override_num = 0;
113 
114 /* just a max for security reasons */
115 #define RE_MAX_THREAD BLENDER_MAX_THREADS
116 
117 struct ThreadSlot {
118  struct ThreadSlot *next, *prev;
119  void *(*do_thread)(void *);
120  void *callerdata;
121  pthread_t pthread;
122  int avail;
123 };
124 
126 {
127  mainid = pthread_self();
128 }
129 
131 {
132 }
133 
134 void BLI_threadpool_init(ListBase *threadbase, void *(*do_thread)(void *), int tot)
135 {
136  int a;
137 
138  if (threadbase != nullptr && tot > 0) {
139  BLI_listbase_clear(threadbase);
140 
141  if (tot > RE_MAX_THREAD) {
142  tot = RE_MAX_THREAD;
143  }
144  else if (tot < 1) {
145  tot = 1;
146  }
147 
148  for (a = 0; a < tot; a++) {
149  ThreadSlot *tslot = static_cast<ThreadSlot *>(MEM_callocN(sizeof(ThreadSlot), "threadslot"));
150  BLI_addtail(threadbase, tslot);
151  tslot->do_thread = do_thread;
152  tslot->avail = 1;
153  }
154  }
155 
156  unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1);
157  if (level == 0) {
158 #ifdef USE_APPLE_OMP_FIX
159  /* Workaround for Apple gcc 4.2.1 OMP vs background thread bug,
160  * we copy GOMP thread local storage pointer to setting it again
161  * inside the thread that we start. */
162  thread_tls_data = pthread_getspecific(gomp_tls_key);
163 #endif
164  }
165 }
166 
168 {
169  int counter = 0;
170 
171  LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
172  if (tslot->avail) {
173  counter++;
174  }
175  }
176 
177  return counter;
178 }
179 
181 {
182  int counter = 0;
183 
184  LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
185  if (tslot->avail) {
186  return counter;
187  }
188  ++counter;
189  }
190 
191  return 0;
192 }
193 
194 static void *tslot_thread_start(void *tslot_p)
195 {
196  ThreadSlot *tslot = (ThreadSlot *)tslot_p;
197 
198 #ifdef USE_APPLE_OMP_FIX
199  /* Workaround for Apple gcc 4.2.1 OMP vs background thread bug,
200  * set GOMP thread local storage pointer which was copied beforehand */
201  pthread_setspecific(gomp_tls_key, thread_tls_data);
202 #endif
203 
204  return tslot->do_thread(tslot->callerdata);
205 }
206 
208 {
209  return pthread_equal(pthread_self(), mainid);
210 }
211 
212 void BLI_threadpool_insert(ListBase *threadbase, void *callerdata)
213 {
214  LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
215  if (tslot->avail) {
216  tslot->avail = 0;
217  tslot->callerdata = callerdata;
218  pthread_create(&tslot->pthread, nullptr, tslot_thread_start, tslot);
219  return;
220  }
221  }
222  printf("ERROR: could not insert thread slot\n");
223 }
224 
225 void BLI_threadpool_remove(ListBase *threadbase, void *callerdata)
226 {
227  LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
228  if (tslot->callerdata == callerdata) {
229  pthread_join(tslot->pthread, nullptr);
230  tslot->callerdata = nullptr;
231  tslot->avail = 1;
232  }
233  }
234 }
235 
236 void BLI_threadpool_remove_index(ListBase *threadbase, int index)
237 {
238  int counter = 0;
239 
240  LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
241  if (counter == index && tslot->avail == 0) {
242  pthread_join(tslot->pthread, nullptr);
243  tslot->callerdata = nullptr;
244  tslot->avail = 1;
245  break;
246  }
247  ++counter;
248  }
249 }
250 
252 {
253  LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
254  if (tslot->avail == 0) {
255  pthread_join(tslot->pthread, nullptr);
256  tslot->callerdata = nullptr;
257  tslot->avail = 1;
258  }
259  }
260 }
261 
262 void BLI_threadpool_end(ListBase *threadbase)
263 {
264 
265  /* Only needed if there's actually some stuff to end
266  * this way we don't end up decrementing thread_levels on an empty `threadbase`. */
267  if (threadbase == nullptr || BLI_listbase_is_empty(threadbase)) {
268  return;
269  }
270 
271  LISTBASE_FOREACH (ThreadSlot *, tslot, threadbase) {
272  if (tslot->avail == 0) {
273  pthread_join(tslot->pthread, nullptr);
274  }
275  }
276  BLI_freelistN(threadbase);
277 }
278 
279 /* System Information */
280 
282 {
283  static int t = -1;
284 
285  if (threads_override_num != 0) {
286  return threads_override_num;
287  }
288  if (LIKELY(t != -1)) {
289  return t;
290  }
291 
292  {
293 #ifdef WIN32
294  SYSTEM_INFO info;
295  GetSystemInfo(&info);
296  t = (int)info.dwNumberOfProcessors;
297 #else
298 # ifdef __APPLE__
299  int mib[2];
300  size_t len;
301 
302  mib[0] = CTL_HW;
303  mib[1] = HW_NCPU;
304  len = sizeof(t);
305  sysctl(mib, 2, &t, &len, nullptr, 0);
306 # else
307  t = (int)sysconf(_SC_NPROCESSORS_ONLN);
308 # endif
309 #endif
310  }
311 
312  CLAMP(t, 1, RE_MAX_THREAD);
313 
314  return t;
315 }
316 
318 {
319  threads_override_num = num;
320 }
321 
323 {
324  return threads_override_num;
325 }
326 
327 /* Global Mutex Locks */
328 
330 {
331  switch (type) {
332  case LOCK_IMAGE:
333  return &_image_lock;
334  case LOCK_DRAW_IMAGE:
335  return &_image_draw_lock;
336  case LOCK_VIEWER:
337  return &_viewer_lock;
338  case LOCK_CUSTOM1:
339  return &_custom1_lock;
340  case LOCK_NODES:
341  return &_nodes_lock;
342  case LOCK_MOVIECLIP:
343  return &_movieclip_lock;
344  case LOCK_COLORMANAGE:
345  return &_colormanage_lock;
346  case LOCK_FFTW:
347  return &_fftw_lock;
348  case LOCK_VIEW3D:
349  return &_view3d_lock;
350  default:
352  return nullptr;
353  }
354 }
355 
357 {
358  pthread_mutex_lock(global_mutex_from_type(type));
359 }
360 
362 {
363  pthread_mutex_unlock(global_mutex_from_type(type));
364 }
365 
366 /* Mutex Locks */
367 
369 {
370  pthread_mutex_init(mutex, nullptr);
371 }
372 
374 {
375  pthread_mutex_lock(mutex);
376 }
377 
379 {
380  pthread_mutex_unlock(mutex);
381 }
382 
384 {
385  return (pthread_mutex_trylock(mutex) == 0);
386 }
387 
389 {
390  pthread_mutex_destroy(mutex);
391 }
392 
394 {
395  ThreadMutex *mutex = static_cast<ThreadMutex *>(MEM_callocN(sizeof(ThreadMutex), "ThreadMutex"));
397  return mutex;
398 }
399 
401 {
403  MEM_freeN(mutex);
404 }
405 
406 /* Spin Locks */
407 
408 #ifdef WITH_TBB
409 static tbb::spin_mutex *tbb_spin_mutex_cast(SpinLock *spin)
410 {
411  static_assert(sizeof(SpinLock) >= sizeof(tbb::spin_mutex),
412  "SpinLock must match tbb::spin_mutex");
413  static_assert(alignof(SpinLock) % alignof(tbb::spin_mutex) == 0,
414  "SpinLock must be aligned same as tbb::spin_mutex");
415  return reinterpret_cast<tbb::spin_mutex *>(spin);
416 }
417 #endif
418 
420 {
421 #ifdef WITH_TBB
422  tbb::spin_mutex *spin_mutex = tbb_spin_mutex_cast(spin);
423  new (spin_mutex) tbb::spin_mutex();
424 #elif defined(__APPLE__)
426 #elif defined(_MSC_VER)
427  *spin = 0;
428 #else
429  pthread_spin_init(spin, 0);
430 #endif
431 }
432 
434 {
435 #ifdef WITH_TBB
436  tbb::spin_mutex *spin_mutex = tbb_spin_mutex_cast(spin);
437  spin_mutex->lock();
438 #elif defined(__APPLE__)
440 #elif defined(_MSC_VER)
441  while (InterlockedExchangeAcquire(spin, 1)) {
442  while (*spin) {
443  /* Spin-lock hint for processors with hyper-threading. */
444  YieldProcessor();
445  }
446  }
447 #else
448  pthread_spin_lock(spin);
449 #endif
450 }
451 
453 {
454 #ifdef WITH_TBB
455  tbb::spin_mutex *spin_mutex = tbb_spin_mutex_cast(spin);
456  spin_mutex->unlock();
457 #elif defined(__APPLE__)
459 #elif defined(_MSC_VER)
460  _ReadWriteBarrier();
461  *spin = 0;
462 #else
463  pthread_spin_unlock(spin);
464 #endif
465 }
466 
468 {
469 #ifdef WITH_TBB
470  tbb::spin_mutex *spin_mutex = tbb_spin_mutex_cast(spin);
471  spin_mutex->~spin_mutex();
472 #elif defined(__APPLE__)
474 #elif defined(_MSC_VER)
475  /* Nothing to do, spin is a simple integer type. */
476 #else
477  pthread_spin_destroy(spin);
478 #endif
479 }
480 
481 /* Read/Write Mutex Lock */
482 
484 {
485  pthread_rwlock_init(mutex, nullptr);
486 }
487 
489 {
490  if (mode == THREAD_LOCK_READ) {
491  pthread_rwlock_rdlock(mutex);
492  }
493  else {
494  pthread_rwlock_wrlock(mutex);
495  }
496 }
497 
499 {
500  pthread_rwlock_unlock(mutex);
501 }
502 
504 {
505  pthread_rwlock_destroy(mutex);
506 }
507 
509 {
510  ThreadRWMutex *mutex = static_cast<ThreadRWMutex *>(
511  MEM_callocN(sizeof(ThreadRWMutex), "ThreadRWMutex"));
513  return mutex;
514 }
515 
517 {
519  MEM_freeN(mutex);
520 }
521 
522 /* Ticket Mutex Lock */
523 
524 struct TicketMutex {
525  pthread_cond_t cond;
526  pthread_mutex_t mutex;
527  unsigned int queue_head, queue_tail;
528 };
529 
531 {
532  TicketMutex *ticket = static_cast<TicketMutex *>(
533  MEM_callocN(sizeof(TicketMutex), "TicketMutex"));
534 
535  pthread_cond_init(&ticket->cond, nullptr);
536  pthread_mutex_init(&ticket->mutex, nullptr);
537 
538  return ticket;
539 }
540 
542 {
543  pthread_mutex_destroy(&ticket->mutex);
544  pthread_cond_destroy(&ticket->cond);
545  MEM_freeN(ticket);
546 }
547 
549 {
550  unsigned int queue_me;
551 
552  pthread_mutex_lock(&ticket->mutex);
553  queue_me = ticket->queue_tail++;
554 
555  while (queue_me != ticket->queue_head) {
556  pthread_cond_wait(&ticket->cond, &ticket->mutex);
557  }
558 
559  pthread_mutex_unlock(&ticket->mutex);
560 }
561 
563 {
564  pthread_mutex_lock(&ticket->mutex);
565  ticket->queue_head++;
566  pthread_cond_broadcast(&ticket->cond);
567  pthread_mutex_unlock(&ticket->mutex);
568 }
569 
570 /* ************************************************ */
571 
572 /* Condition */
573 
575 {
576  pthread_cond_init(cond, nullptr);
577 }
578 
580 {
581  pthread_cond_wait(cond, mutex);
582 }
583 
585 {
586  pthread_cond_wait(cond, global_mutex_from_type(type));
587 }
588 
590 {
591  pthread_cond_signal(cond);
592 }
593 
595 {
596  pthread_cond_broadcast(cond);
597 }
598 
600 {
601  pthread_cond_destroy(cond);
602 }
603 
604 /* ************************************************ */
605 
606 struct ThreadQueue {
608  pthread_mutex_t mutex;
609  pthread_cond_t push_cond;
610  pthread_cond_t finish_cond;
611  volatile int nowait;
612  volatile int canceled;
613 };
614 
616 {
618 
619  queue = static_cast<ThreadQueue *>(MEM_callocN(sizeof(ThreadQueue), "ThreadQueue"));
620  queue->queue = BLI_gsqueue_new(sizeof(void *));
621 
622  pthread_mutex_init(&queue->mutex, nullptr);
623  pthread_cond_init(&queue->push_cond, nullptr);
624  pthread_cond_init(&queue->finish_cond, nullptr);
625 
626  return queue;
627 }
628 
630 {
631  /* destroy everything, assumes no one is using queue anymore */
632  pthread_cond_destroy(&queue->finish_cond);
633  pthread_cond_destroy(&queue->push_cond);
634  pthread_mutex_destroy(&queue->mutex);
635 
636  BLI_gsqueue_free(queue->queue);
637 
638  MEM_freeN(queue);
639 }
640 
642 {
643  pthread_mutex_lock(&queue->mutex);
644 
645  BLI_gsqueue_push(queue->queue, &work);
646 
647  /* signal threads waiting to pop */
648  pthread_cond_signal(&queue->push_cond);
649  pthread_mutex_unlock(&queue->mutex);
650 }
651 
653 {
654  void *work = nullptr;
655 
656  /* wait until there is work */
657  pthread_mutex_lock(&queue->mutex);
658  while (BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) {
659  pthread_cond_wait(&queue->push_cond, &queue->mutex);
660  }
661 
662  /* if we have something, pop it */
663  if (!BLI_gsqueue_is_empty(queue->queue)) {
664  BLI_gsqueue_pop(queue->queue, &work);
665 
666  if (BLI_gsqueue_is_empty(queue->queue)) {
667  pthread_cond_broadcast(&queue->finish_cond);
668  }
669  }
670 
671  pthread_mutex_unlock(&queue->mutex);
672 
673  return work;
674 }
675 
676 static void wait_timeout(struct timespec *timeout, int ms)
677 {
678  ldiv_t div_result;
679  long sec, usec, x;
680 
681 #ifdef WIN32
682  {
683  struct _timeb now;
684  _ftime(&now);
685  sec = now.time;
686  usec = now.millitm * 1000; /* microsecond precision would be better */
687  }
688 #else
689  {
690  struct timeval now;
691  gettimeofday(&now, nullptr);
692  sec = now.tv_sec;
693  usec = now.tv_usec;
694  }
695 #endif
696 
697  /* add current time + millisecond offset */
698  div_result = ldiv(ms, 1000);
699  timeout->tv_sec = sec + div_result.quot;
700 
701  x = usec + (div_result.rem * 1000);
702 
703  if (x >= 1000000) {
704  timeout->tv_sec++;
705  x -= 1000000;
706  }
707 
708  timeout->tv_nsec = x * 1000;
709 }
710 
712 {
713  double t;
714  void *work = nullptr;
715  struct timespec timeout;
716 
718  wait_timeout(&timeout, ms);
719 
720  /* wait until there is work */
721  pthread_mutex_lock(&queue->mutex);
722  while (BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) {
723  if (pthread_cond_timedwait(&queue->push_cond, &queue->mutex, &timeout) == ETIMEDOUT) {
724  break;
725  }
726  if (PIL_check_seconds_timer() - t >= ms * 0.001) {
727  break;
728  }
729  }
730 
731  /* if we have something, pop it */
732  if (!BLI_gsqueue_is_empty(queue->queue)) {
733  BLI_gsqueue_pop(queue->queue, &work);
734 
735  if (BLI_gsqueue_is_empty(queue->queue)) {
736  pthread_cond_broadcast(&queue->finish_cond);
737  }
738  }
739 
740  pthread_mutex_unlock(&queue->mutex);
741 
742  return work;
743 }
744 
746 {
747  int size;
748 
749  pthread_mutex_lock(&queue->mutex);
750  size = BLI_gsqueue_len(queue->queue);
751  pthread_mutex_unlock(&queue->mutex);
752 
753  return size;
754 }
755 
757 {
758  bool is_empty;
759 
760  pthread_mutex_lock(&queue->mutex);
761  is_empty = BLI_gsqueue_is_empty(queue->queue);
762  pthread_mutex_unlock(&queue->mutex);
763 
764  return is_empty;
765 }
766 
768 {
769  pthread_mutex_lock(&queue->mutex);
770 
771  queue->nowait = 1;
772 
773  /* signal threads waiting to pop */
774  pthread_cond_broadcast(&queue->push_cond);
775  pthread_mutex_unlock(&queue->mutex);
776 }
777 
779 {
780  /* wait for finish condition */
781  pthread_mutex_lock(&queue->mutex);
782 
783  while (!BLI_gsqueue_is_empty(queue->queue)) {
784  pthread_cond_wait(&queue->finish_cond, &queue->mutex);
785  }
786 
787  pthread_mutex_unlock(&queue->mutex);
788 }
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
void BLI_gsqueue_free(GSQueue *queue)
Definition: gsqueue.c:90
GSQueue * BLI_gsqueue_new(size_t elem_size)
Definition: gsqueue.c:69
void BLI_gsqueue_push(GSQueue *queue, const void *item)
Definition: gsqueue.c:97
void BLI_gsqueue_pop(GSQueue *queue, void *r_item)
Definition: gsqueue.c:131
bool BLI_gsqueue_is_empty(const GSQueue *queue)
Definition: gsqueue.c:159
size_t BLI_gsqueue_len(const GSQueue *queue)
Definition: gsqueue.c:154
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:110
@ LOCK_NODES
Definition: BLI_threads.h:70
@ LOCK_VIEW3D
Definition: BLI_threads.h:74
@ LOCK_DRAW_IMAGE
Definition: BLI_threads.h:67
@ LOCK_COLORMANAGE
Definition: BLI_threads.h:72
@ LOCK_MOVIECLIP
Definition: BLI_threads.h:71
@ LOCK_CUSTOM1
Definition: BLI_threads.h:69
@ LOCK_IMAGE
Definition: BLI_threads.h:66
@ LOCK_VIEWER
Definition: BLI_threads.h:68
@ LOCK_FFTW
Definition: BLI_threads.h:73
pthread_rwlock_t ThreadRWMutex
Definition: BLI_threads.h:125
#define THREAD_LOCK_READ
Definition: BLI_threads.h:120
pthread_cond_t ThreadCondition
Definition: BLI_threads.h:150
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:82
#define LIKELY(x)
ThreadMutex mutex
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
Platform independent time functions.
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.c:162
SyclQueue * queue
int len
Definition: draw_manager.c:108
ccl_gpu_kernel_postfix ccl_global int * counter
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static unsigned a[3]
Definition: RandGen.cpp:78
volatile int nowait
Definition: threads.cc:611
volatile int canceled
Definition: threads.cc:612
GSQueue * queue
Definition: threads.cc:607
pthread_cond_t push_cond
Definition: threads.cc:609
pthread_cond_t finish_cond
Definition: threads.cc:610
pthread_mutex_t mutex
Definition: threads.cc:608
void * callerdata
Definition: threads.cc:120
struct ThreadSlot * next
Definition: threads.cc:118
pthread_t pthread
Definition: threads.cc:121
int avail
Definition: threads.cc:122
void *(* do_thread)(void *)
Definition: threads.cc:119
struct ThreadSlot * prev
Definition: threads.cc:118
unsigned int queue_tail
Definition: threads.cc:527
pthread_cond_t cond
Definition: threads.cc:525
unsigned int queue_head
Definition: threads.cc:527
pthread_mutex_t mutex
Definition: threads.cc:526
void BLI_condition_notify_all(ThreadCondition *cond)
Definition: threads.cc:594
bool BLI_mutex_trylock(ThreadMutex *mutex)
Definition: threads.cc:383
void BLI_rw_mutex_end(ThreadRWMutex *mutex)
Definition: threads.cc:503
void BLI_thread_queue_push(ThreadQueue *queue, void *work)
Definition: threads.cc:641
void BLI_threadapi_init()
Definition: threads.cc:125
void BLI_thread_unlock(int type)
Definition: threads.cc:361
void BLI_ticket_mutex_unlock(TicketMutex *ticket)
Definition: threads.cc:562
static pthread_mutex_t _image_lock
Definition: threads.cc:101
void BLI_mutex_end(ThreadMutex *mutex)
Definition: threads.cc:388
#define RE_MAX_THREAD
Definition: threads.cc:115
void BLI_threadapi_exit()
Definition: threads.cc:130
void BLI_mutex_free(ThreadMutex *mutex)
Definition: threads.cc:400
static pthread_mutex_t _custom1_lock
Definition: threads.cc:104
void BLI_threadpool_clear(ListBase *threadbase)
Definition: threads.cc:251
void BLI_threadpool_init(ListBase *threadbase, void *(*do_thread)(void *), int tot)
Definition: threads.cc:134
void BLI_thread_lock(int type)
Definition: threads.cc:356
int BLI_thread_is_main()
Definition: threads.cc:207
void BLI_threadpool_remove(ListBase *threadbase, void *callerdata)
Definition: threads.cc:225
static pthread_mutex_t _view3d_lock
Definition: threads.cc:109
ThreadMutex * BLI_mutex_alloc()
Definition: threads.cc:393
void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
Definition: threads.cc:579
static unsigned int thread_levels
Definition: threads.cc:111
int BLI_system_num_threads_override_get()
Definition: threads.cc:322
static int threads_override_num
Definition: threads.cc:112
int BLI_threadpool_available_thread_index(ListBase *threadbase)
Definition: threads.cc:180
void * BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)
Definition: threads.cc:711
void BLI_mutex_init(ThreadMutex *mutex)
Definition: threads.cc:368
static pthread_mutex_t _viewer_lock
Definition: threads.cc:103
void BLI_system_num_threads_override_set(int num)
Definition: threads.cc:317
void BLI_condition_end(ThreadCondition *cond)
Definition: threads.cc:599
void BLI_thread_queue_free(ThreadQueue *queue)
Definition: threads.cc:629
static pthread_mutex_t _colormanage_lock
Definition: threads.cc:107
static pthread_mutex_t _fftw_lock
Definition: threads.cc:108
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
Definition: threads.cc:488
void BLI_ticket_mutex_lock(TicketMutex *ticket)
Definition: threads.cc:548
static void * tslot_thread_start(void *tslot_p)
Definition: threads.cc:194
void BLI_condition_notify_one(ThreadCondition *cond)
Definition: threads.cc:589
bool BLI_thread_queue_is_empty(ThreadQueue *queue)
Definition: threads.cc:756
void BLI_ticket_mutex_free(TicketMutex *ticket)
Definition: threads.cc:541
void BLI_condition_wait_global_mutex(ThreadCondition *cond, const int type)
Definition: threads.cc:584
static pthread_mutex_t _image_draw_lock
Definition: threads.cc:102
void BLI_threadpool_end(ListBase *threadbase)
Definition: threads.cc:262
void BLI_condition_init(ThreadCondition *cond)
Definition: threads.cc:574
static pthread_t mainid
Definition: threads.cc:110
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:373
void BLI_thread_queue_nowait(ThreadQueue *queue)
Definition: threads.cc:767
int BLI_system_thread_count()
Definition: threads.cc:281
void BLI_thread_queue_wait_finish(ThreadQueue *queue)
Definition: threads.cc:778
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:378
void BLI_rw_mutex_init(ThreadRWMutex *mutex)
Definition: threads.cc:483
ThreadQueue * BLI_thread_queue_init()
Definition: threads.cc:615
static pthread_mutex_t _nodes_lock
Definition: threads.cc:105
static void wait_timeout(struct timespec *timeout, int ms)
Definition: threads.cc:676
ThreadRWMutex * BLI_rw_mutex_alloc()
Definition: threads.cc:508
void BLI_threadpool_insert(ListBase *threadbase, void *callerdata)
Definition: threads.cc:212
static pthread_mutex_t _movieclip_lock
Definition: threads.cc:106
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:419
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:452
void BLI_threadpool_remove_index(ListBase *threadbase, int index)
Definition: threads.cc:236
int BLI_available_threads(ListBase *threadbase)
Definition: threads.cc:167
void * BLI_thread_queue_pop(ThreadQueue *queue)
Definition: threads.cc:652
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:433
void BLI_rw_mutex_free(ThreadRWMutex *mutex)
Definition: threads.cc:516
TicketMutex * BLI_ticket_mutex_alloc()
Definition: threads.cc:530
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
Definition: threads.cc:498
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:467
int BLI_thread_queue_len(ThreadQueue *queue)
Definition: threads.cc:745
static ThreadMutex * global_mutex_from_type(const int type)
Definition: threads.cc:329
double PIL_check_seconds_timer(void)
Definition: time.c:64