[Mesa-dev] [PATCHv2 07/13] glsl: add a singleton GLSL thread pool

Chia-I Wu olvaffe at gmail.com
Wed Jul 9 00:47:48 PDT 2014


This thread pool will be used by contexts to queue compilation tasks.

Signed-off-by: Chia-I Wu <olv at lunarg.com>
---
 src/glsl/glsl_parser_extras.cpp |  4 +++
 src/glsl/threadpool.c           | 72 +++++++++++++++++++++++++++++++++++++++++
 src/glsl/threadpool.h           |  9 ++++++
 3 files changed, 85 insertions(+)

diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index ad31469..cb7d59e 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -37,6 +37,7 @@ extern "C" {
 #include "glsl_parser.h"
 #include "ir_optimization.h"
 #include "loop_analysis.h"
+#include "threadpool.h"
 
 /**
  * Format a short human-readable description of the given GLSL version.
@@ -1599,6 +1600,8 @@ extern "C" {
 void
 _mesa_destroy_shader_compiler(void)
 {
+   _mesa_glsl_destroy_threadpool();
+
    _mesa_destroy_shader_compiler_caches();
 
    _mesa_glsl_release_types();
@@ -1612,6 +1615,7 @@ _mesa_destroy_shader_compiler(void)
 void
 _mesa_destroy_shader_compiler_caches(void)
 {
+   _mesa_glsl_wait_threadpool();
    _mesa_glsl_release_builtin_functions();
 }
 
diff --git a/src/glsl/threadpool.c b/src/glsl/threadpool.c
index c069fd3..d6ed8c1 100644
--- a/src/glsl/threadpool.c
+++ b/src/glsl/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 GLSL thread pool.  \p max_threads is honored only by the
+ * first call to this function.
+ */
+struct _mesa_threadpool *
+_mesa_glsl_get_threadpool(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_glsl_wait_threadpool(void)
+{
+   mtx_lock(&threadpool_lock);
+   if (threadpool)
+      _mesa_threadpool_join(threadpool, true);
+   mtx_unlock(&threadpool_lock);
+}
+
+/**
+ * Destroy the GLSL thread pool.
+ */
+void
+_mesa_glsl_destroy_threadpool(void)
+{
+   mtx_lock(&threadpool_lock);
+   if (threadpool) {
+      /*
+       * This is called from _mesa_destroy_shader_compiler().  No new task is
+       * allowed since this point.  But contexts, who also own references to
+       * the pool, can still complete tasks that have been queued.
+       */
+      _mesa_threadpool_set_shutdown(threadpool);
+
+      _mesa_threadpool_join(threadpool, false);
+      _mesa_threadpool_unref(threadpool);
+      threadpool = NULL;
+   }
+   mtx_unlock(&threadpool_lock);
+}
diff --git a/src/glsl/threadpool.h b/src/glsl/threadpool.h
index 48e4a47..b1a8ea8 100644
--- a/src/glsl/threadpool.h
+++ b/src/glsl/threadpool.h
@@ -60,6 +60,15 @@ bool
 _mesa_threadpool_complete_task(struct _mesa_threadpool *pool,
                                struct _mesa_threadpool_task *task);
 
+struct _mesa_threadpool *
+_mesa_glsl_get_threadpool(int max_threads);
+
+void
+_mesa_glsl_wait_threadpool(void);
+
+void
+_mesa_glsl_destroy_threadpool(void);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.0.0.rc2



More information about the mesa-dev mailing list