To have a real control over the number of driver threads, we almost never want more than a single thread pool.
Signed-off-by: Chia-I Wu <o...@lunarg.com> Reviewed-by: Brian Paul <bri...@vmware.com> Reviewed-by: Ian Romanick <ian.d.roman...@intel.com> v2: split glsl changes to another commit --- src/util/threadpool.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util/threadpool.h | 9 +++++++ 2 files changed, 81 insertions(+) diff --git a/src/util/threadpool.c b/src/util/threadpool.c index 224f411..9dc91f9 100644 --- a/src/util/threadpool.c +++ b/src/util/threadpool.c @@ -55,6 +55,7 @@ struct _mesa_threadpool_task { struct _mesa_threadpool { mtx_t mutex; int refcnt; + bool shutdown; enum _mesa_threadpool_control thread_control; thrd_t *threads; @@ -168,6 +169,12 @@ _mesa_threadpool_queue_task(struct _mesa_threadpool *pool, mtx_lock(&pool->mutex); + if (unlikely(pool->shutdown)) { + mtx_unlock(&pool->mutex); + free(task); + return NULL; + } + /* someone is joining with the threads */ while (unlikely(pool->thread_control != MESA_THREADPOOL_NORMAL)) cnd_wait(&pool->thread_joined, &pool->mutex); @@ -379,6 +386,17 @@ _mesa_threadpool_join(struct _mesa_threadpool *pool, bool graceful) } /** + * After this call, no task can be queued. + */ +static void +_mesa_threadpool_set_shutdown(struct _mesa_threadpool *pool) +{ + mtx_lock(&pool->mutex); + pool->shutdown = true; + mtx_unlock(&pool->mutex); +} + +/** * Decrease the reference count. Destroy \p pool when the reference count * reaches zero. */ @@ -474,3 +492,57 @@ _mesa_threadpool_create(int max_threads) return pool; } + +static mtx_t threadpool_lock = _MTX_INITIALIZER_NP; +static struct _mesa_threadpool *threadpool; + +/** + * Get the singleton thread pool. \p max_threads is honored only by the first + * call to this function. + */ +struct _mesa_threadpool * +_mesa_threadpool_get_singleton(int max_threads) +{ + mtx_lock(&threadpool_lock); + if (!threadpool) + threadpool = _mesa_threadpool_create(max_threads); + if (threadpool) + _mesa_threadpool_ref(threadpool); + mtx_unlock(&threadpool_lock); + + return threadpool; +} + +/** + * Wait until all tasks are completed and threads are joined. + */ +void +_mesa_threadpool_wait_singleton(void) +{ + mtx_lock(&threadpool_lock); + if (threadpool) + _mesa_threadpool_join(threadpool, true); + mtx_unlock(&threadpool_lock); +} + +/** + * Destroy the singleton thread pool. + */ +void +_mesa_threadpool_destroy_singleton(void) +{ + mtx_lock(&threadpool_lock); + if (threadpool) { + /* + * No new task is allowed since this point. But whoever owns references + * to the pool can still complete tasks that have been queued (which + * will simply destroy the tasks as all tasks are marked cancelled). + */ + _mesa_threadpool_set_shutdown(threadpool); + + _mesa_threadpool_join(threadpool, false); + _mesa_threadpool_unref(threadpool); + threadpool = NULL; + } + mtx_unlock(&threadpool_lock); +} diff --git a/src/util/threadpool.h b/src/util/threadpool.h index 48e4a47..aeda9d3 100644 --- a/src/util/threadpool.h +++ b/src/util/threadpool.h @@ -60,6 +60,15 @@ bool _mesa_threadpool_complete_task(struct _mesa_threadpool *pool, struct _mesa_threadpool_task *task); +struct _mesa_threadpool * +_mesa_threadpool_get_singleton(int max_threads); + +void +_mesa_threadpool_wait_singleton(void); + +void +_mesa_threadpool_destroy_singleton(void); + #ifdef __cplusplus } #endif -- 2.0.0.rc2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev