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 * The Original Code is Copyright (C) 2006 Blender Foundation. 17 * All rights reserved. 18 */ 19 20 #pragma once 21 22 /** \file 23 * \ingroup bli 24 */ 25 26 #include <pthread.h> 27 28 #include "BLI_sys_types.h" 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 /* for tables, button in UI, etc */ 35 #define BLENDER_MAX_THREADS 1024 36 37 struct ListBase; 38 struct TaskScheduler; 39 40 /* Threading API */ 41 42 /*this is run once at startup*/ 43 void BLI_threadapi_init(void); 44 void BLI_threadapi_exit(void); 45 46 void BLI_threadpool_init(struct ListBase *threadbase, void *(*do_thread)(void *), int tot); 47 int BLI_available_threads(struct ListBase *threadbase); 48 int BLI_threadpool_available_thread_index(struct ListBase *threadbase); 49 void BLI_threadpool_insert(struct ListBase *threadbase, void *callerdata); 50 void BLI_threadpool_remove(struct ListBase *threadbase, void *callerdata); 51 void BLI_threadpool_remove_index(struct ListBase *threadbase, int index); 52 void BLI_threadpool_clear(struct ListBase *threadbase); 53 void BLI_threadpool_end(struct ListBase *threadbase); 54 int BLI_thread_is_main(void); 55 56 /* System Information */ 57 58 int BLI_system_thread_count(void); /* gets the number of threads the system can make use of */ 59 void BLI_system_num_threads_override_set(int num); 60 int BLI_system_num_threads_override_get(void); 61 62 /** 63 * Global Mutex Locks 64 * 65 * One custom lock available now. can be extended. 66 */ 67 enum { 68 LOCK_IMAGE = 0, 69 LOCK_DRAW_IMAGE, 70 LOCK_VIEWER, 71 LOCK_CUSTOM1, 72 LOCK_NODES, 73 LOCK_MOVIECLIP, 74 LOCK_COLORMANAGE, 75 LOCK_FFTW, 76 LOCK_VIEW3D, 77 }; 78 79 void BLI_thread_lock(int type); 80 void BLI_thread_unlock(int type); 81 82 /* Mutex Lock */ 83 84 typedef pthread_mutex_t ThreadMutex; 85 #define BLI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 86 87 void BLI_mutex_init(ThreadMutex *mutex); 88 void BLI_mutex_end(ThreadMutex *mutex); 89 90 ThreadMutex *BLI_mutex_alloc(void); 91 void BLI_mutex_free(ThreadMutex *mutex); 92 93 void BLI_mutex_lock(ThreadMutex *mutex); 94 bool BLI_mutex_trylock(ThreadMutex *mutex); 95 void BLI_mutex_unlock(ThreadMutex *mutex); 96 97 /* Spin Lock */ 98 99 /* By default we use TBB for spin lock on all platforms. When building without 100 * TBB fall-back to spin lock implementation which is native to the platform. 101 * 102 * On macOS we use mutex lock instead of spin since the spin lock has been 103 * deprecated in SDK 10.12 and is discouraged from use. */ 104 105 #ifdef WITH_TBB 106 typedef uint32_t SpinLock; 107 #elif defined(__APPLE__) 108 typedef ThreadMutex SpinLock; 109 #elif defined(_MSC_VER) 110 typedef volatile unsigned int SpinLock; 111 #else 112 typedef pthread_spinlock_t SpinLock; 113 #endif 114 115 void BLI_spin_init(SpinLock *spin); 116 void BLI_spin_lock(SpinLock *spin); 117 void BLI_spin_unlock(SpinLock *spin); 118 void BLI_spin_end(SpinLock *spin); 119 120 /* Read/Write Mutex Lock */ 121 122 #define THREAD_LOCK_READ 1 123 #define THREAD_LOCK_WRITE 2 124 125 #define BLI_RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER 126 127 typedef pthread_rwlock_t ThreadRWMutex; 128 129 void BLI_rw_mutex_init(ThreadRWMutex *mutex); 130 void BLI_rw_mutex_end(ThreadRWMutex *mutex); 131 132 ThreadRWMutex *BLI_rw_mutex_alloc(void); 133 void BLI_rw_mutex_free(ThreadRWMutex *mutex); 134 135 void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode); 136 void BLI_rw_mutex_unlock(ThreadRWMutex *mutex); 137 138 /* Ticket Mutex Lock 139 * 140 * This is a 'fair' mutex in that it will grant the lock to the first thread 141 * that requests it. */ 142 143 typedef struct TicketMutex TicketMutex; 144 145 TicketMutex *BLI_ticket_mutex_alloc(void); 146 void BLI_ticket_mutex_free(TicketMutex *ticket); 147 void BLI_ticket_mutex_lock(TicketMutex *ticket); 148 void BLI_ticket_mutex_unlock(TicketMutex *ticket); 149 150 /* Condition */ 151 152 typedef pthread_cond_t ThreadCondition; 153 154 void BLI_condition_init(ThreadCondition *cond); 155 void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex); 156 void BLI_condition_wait_global_mutex(ThreadCondition *cond, const int type); 157 void BLI_condition_notify_one(ThreadCondition *cond); 158 void BLI_condition_notify_all(ThreadCondition *cond); 159 void BLI_condition_end(ThreadCondition *cond); 160 161 /* ThreadWorkQueue 162 * 163 * Thread-safe work queue to push work/pointers between threads. */ 164 165 typedef struct ThreadQueue ThreadQueue; 166 167 ThreadQueue *BLI_thread_queue_init(void); 168 void BLI_thread_queue_free(ThreadQueue *queue); 169 170 void BLI_thread_queue_push(ThreadQueue *queue, void *work); 171 void *BLI_thread_queue_pop(ThreadQueue *queue); 172 void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms); 173 int BLI_thread_queue_len(ThreadQueue *queue); 174 bool BLI_thread_queue_is_empty(ThreadQueue *queue); 175 176 void BLI_thread_queue_wait_finish(ThreadQueue *queue); 177 void BLI_thread_queue_nowait(ThreadQueue *queue); 178 179 /* Thread local storage */ 180 181 #if defined(__APPLE__) 182 # define ThreadLocal(type) pthread_key_t 183 # define BLI_thread_local_create(name) pthread_key_create(&name, NULL) 184 # define BLI_thread_local_delete(name) pthread_key_delete(name) 185 # define BLI_thread_local_get(name) pthread_getspecific(name) 186 # define BLI_thread_local_set(name, value) pthread_setspecific(name, value) 187 #else /* defined(__APPLE__) */ 188 # ifdef _MSC_VER 189 # define ThreadLocal(type) __declspec(thread) type 190 # else 191 # define ThreadLocal(type) __thread type 192 # endif 193 # define BLI_thread_local_create(name) 194 # define BLI_thread_local_delete(name) 195 # define BLI_thread_local_get(name) name 196 # define BLI_thread_local_set(name, value) name = value 197 #endif /* defined(__APPLE__) */ 198 199 /* **** Special functions to help performance on crazy NUMA setups. **** */ 200 201 /* Make sure process/thread is using NUMA node with fast memory access. */ 202 void BLI_thread_put_process_on_fast_node(void); 203 void BLI_thread_put_thread_on_fast_node(void); 204 205 #ifdef __cplusplus 206 } 207 #endif 208