[Mesa-dev] [PATCHv3 06/16] util: allow the thread pool to be used as a singleton

Chia-I Wu olvaffe at gmail.com
Tue Aug 19 23:40:27 PDT 2014


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 <olv at lunarg.com>
Reviewed-by: Brian Paul <brianp at vmware.com>
Reviewed-by: Ian Romanick <ian.d.romanick at 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



More information about the mesa-dev mailing list