Changeset View
Standalone View
source/blender/blenlib/intern/threads.c
| Show First 20 Lines • Show All 178 Lines • ▼ Show 20 Lines | TaskScheduler *BLI_task_scheduler_get(void) | ||||
| return task_scheduler; | return task_scheduler; | ||||
| } | } | ||||
| /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) | /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) | ||||
| * problem otherwise: scene render will kill of the mutex! | * problem otherwise: scene render will kill of the mutex! | ||||
| */ | */ | ||||
| void BLI_threadpool_init(ListBase *threadbase, void *(*do_thread)(void *), int tot) | void BLI_threadpool_init(ListBase *threadbase, | ||||
| void *(*do_thread)(void *), | |||||
| int tot, | |||||
| const char *thread_name) | |||||
| { | { | ||||
| int a; | int a; | ||||
| if (threadbase != NULL && tot > 0) { | if (threadbase != NULL && tot > 0) { | ||||
| BLI_listbase_clear(threadbase); | BLI_listbase_clear(threadbase); | ||||
| if (tot > RE_MAX_THREAD) { | if (tot > RE_MAX_THREAD) { | ||||
| tot = RE_MAX_THREAD; | tot = RE_MAX_THREAD; | ||||
| } | } | ||||
| else if (tot < 1) { | else if (tot < 1) { | ||||
| tot = 1; | tot = 1; | ||||
| } | } | ||||
| for (a = 0; a < tot; a++) { | for (a = 0; a < tot; a++) { | ||||
| ThreadSlot *tslot = MEM_callocN(sizeof(ThreadSlot), "threadslot"); | ThreadSlot *tslot = MEM_callocN(sizeof(ThreadSlot), "threadslot"); | ||||
| BLI_addtail(threadbase, tslot); | BLI_addtail(threadbase, tslot); | ||||
| tslot->do_thread = do_thread; | tslot->do_thread = do_thread; | ||||
| tslot->avail = 1; | tslot->avail = 1; | ||||
| } | } | ||||
| } | } | ||||
| BLI_thread_name_set(thread_name ? thread_name : "Thread Pool"); | |||||
sybren: Is `pool_name` this the name of the pool or the name of the thread? It seems to be used as both… | |||||
Done Inline ActionsWell it's the pool name, but it's only use by the implementation is to set it as a thread name. You're right, I'll just name it thread_name, since I also need to make the < 15 chars requirement clear. velocity: Well it's the pool name, but it's only use by the implementation is to set it as a thread name. | |||||
| unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); | unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); | ||||
| if (level == 0) { | if (level == 0) { | ||||
Done Inline ActionsDon't use unnecessary abbreviations like "TPool" or "Sched". brecht: Don't use unnecessary abbreviations like "TPool" or "Sched". | |||||
Done Inline ActionsYeah I'd like to use more expressive names, but it's a POSIX limitation that the thread name can't be longer than 15 characters, so I had to abbreviate. I should probably mention this in the documentation for BLI_threadpool_init too (after I rename it to thread_name). Alternatively, I could not have this limitatin for the threadpool API and cull to the last 15 characters (or something like that) when naming the thread, what do you think? velocity: Yeah I'd like to use more expressive names, but it's a [[ https://linux.die. | |||||
| MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); | MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); | ||||
| #ifdef USE_APPLE_OMP_FIX | #ifdef USE_APPLE_OMP_FIX | ||||
| /* workaround for Apple gcc 4.2.1 omp vs background thread bug, | /* workaround for Apple gcc 4.2.1 omp vs background thread bug, | ||||
| * we copy gomp thread local storage pointer to setting it again | * we copy gomp thread local storage pointer to setting it again | ||||
| * inside the thread that we start */ | * inside the thread that we start */ | ||||
| thread_tls_data = pthread_getspecific(gomp_tls_key); | thread_tls_data = pthread_getspecific(gomp_tls_key); | ||||
| #endif | #endif | ||||
| ▲ Show 20 Lines • Show All 589 Lines • ▼ Show 20 Lines | bool BLI_thread_queue_is_empty(ThreadQueue *queue) | ||||
| is_empty = BLI_gsqueue_is_empty(queue->queue); | is_empty = BLI_gsqueue_is_empty(queue->queue); | ||||
| pthread_mutex_unlock(&queue->mutex); | pthread_mutex_unlock(&queue->mutex); | ||||
| return is_empty; | return is_empty; | ||||
| } | } | ||||
| void BLI_thread_queue_nowait(ThreadQueue *queue) | void BLI_thread_queue_nowait(ThreadQueue *queue) | ||||
| { | { | ||||
| pthread_mutex_lock(&queue->mutex); | pthread_mutex_lock(&queue->mutex); | ||||
Not Done Inline ActionsSeems that thread_name will be considered unused with pedantic compiler? Easy to fix when applying though. sergey: Seems that `thread_name` will be considered unused with pedantic compiler? Easy to fix when… | |||||
Done Inline ActionsIs there any good reason just to do this for debug builds? I tend to profile RelWithDebinfo Builds a lot and named threads would be nice there as well. LazyDodo: Is there any good reason just to do this for debug builds? I tend to profile RelWithDebinfo… | |||||
Done Inline ActionsNot really, I just didn't think it'd be useful, but touche, I'll enable it on release builds too. velocity: Not really, I just didn't think it'd be useful, but touche, I'll enable it on release builds… | |||||
| queue->nowait = 1; | queue->nowait = 1; | ||||
| /* signal threads waiting to pop */ | /* signal threads waiting to pop */ | ||||
| pthread_cond_broadcast(&queue->push_cond); | pthread_cond_broadcast(&queue->push_cond); | ||||
| pthread_mutex_unlock(&queue->mutex); | pthread_mutex_unlock(&queue->mutex); | ||||
| } | } | ||||
Done Inline Actions
sergey: - Put { at the same line
- Would prefer to have early output rather than having a whole block… | |||||
| void BLI_thread_name_set(const char *thread_name) | |||||
Done Inline ActionsNDEBUG is already checked. sergey: `NDEBUG` is already checked. | |||||
Done Inline ActionsI fixed this yesterday, I probably messed something up updating the patch. velocity: I fixed this yesterday, I probably messed something up updating the patch. | |||||
| { | |||||
| BLI_assert(strlen(thread_name) <= 15); | |||||
| #ifndef NDEBUG | |||||
| if (!thread_name) | |||||
| return; | |||||
Not Done Inline Actions# if defined(_WIN32) || (defined(__linux__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 12)) try this? LazyDodo: ```
# if defined(_WIN32) || (defined(__linux__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >=… | |||||
| # if defined(_WIN32) || defined(__linux__) | |||||
| pthread_setname_np(pthread_self(), thread_name); | |||||
| # elif defined(__APPLE__) | |||||
| pthread_setname_np(thread_name); | |||||
| # elif defined(__FreeBSD__) | |||||
| pthread_setname_np(pthread_self(), "%s", thread_name); | |||||
| # endif | |||||
| #endif | |||||
| } | |||||
| void BLI_thread_queue_wait_finish(ThreadQueue *queue) | void BLI_thread_queue_wait_finish(ThreadQueue *queue) | ||||
| { | { | ||||
| /* wait for finish condition */ | /* wait for finish condition */ | ||||
| pthread_mutex_lock(&queue->mutex); | pthread_mutex_lock(&queue->mutex); | ||||
| while (!BLI_gsqueue_is_empty(queue->queue)) { | while (!BLI_gsqueue_is_empty(queue->queue)) { | ||||
| pthread_cond_wait(&queue->finish_cond, &queue->mutex); | pthread_cond_wait(&queue->finish_cond, &queue->mutex); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 136 Lines • Show Last 20 Lines | |||||
Is pool_name this the name of the pool or the name of the thread? It seems to be used as both, which I find confusing.