[Beignet] [PATCH] Modify the multi-thread support for queue.

junyan.he at inbox.com junyan.he at inbox.com
Wed Dec 18 02:41:47 PST 2013


From: Junyan He <junyan.he at linux.intel.com>

The old multi-thread support for queue do not work
when threads will not exit. If the thread not exit
but the queue is re-generated all the time, the
gpgpu struct resouce will leak, and will fail to
create GPU bo for gpgpu struct finally.
We modify it to check the queue version now, if the
queue version changes, we reset our gpgpu struct
context to fix this problem.

Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 src/cl_command_queue.c |  7 ++---
 src/cl_command_queue.h |  2 +-
 src/cl_thread.c        | 72 ++++++++++++++++++++++----------------------------
 src/cl_thread.h        |  8 ++----
 4 files changed, 37 insertions(+), 52 deletions(-)

diff --git a/src/cl_command_queue.c b/src/cl_command_queue.c
index 3530976..c2d93d6 100644
--- a/src/cl_command_queue.c
+++ b/src/cl_command_queue.c
@@ -44,9 +44,7 @@ cl_command_queue_new(cl_context ctx)
   queue->magic = CL_MAGIC_QUEUE_HEADER;
   queue->ref_n = 1;
   queue->ctx = ctx;
-  if ((queue->thread_data = cl_thread_data_create()) == NULL) {
-    goto error;
-  }
+  queue->queue_num_magic = cl_thread_new_queue_magic_num();
 
   /* Append the command queue in the list */
   pthread_mutex_lock(&ctx->queue_lock);
@@ -88,13 +86,12 @@ cl_command_queue_delete(cl_command_queue queue)
     queue->fulsim_out = NULL;
   }
 
-  cl_thread_data_destroy(queue->thread_data);
-  queue->thread_data = NULL;
   cl_mem_delete(queue->perf);
   cl_context_delete(queue->ctx);
   cl_free(queue->wait_events);
   queue->magic = CL_MAGIC_DEAD_HEADER; /* For safety */
   cl_free(queue);
+
 }
 
 LOCAL void
diff --git a/src/cl_command_queue.h b/src/cl_command_queue.h
index 40c272c..cb9d7d6 100644
--- a/src/cl_command_queue.h
+++ b/src/cl_command_queue.h
@@ -41,7 +41,7 @@ struct _cl_command_queue {
   cl_event  last_event;                /* The last event in the queue, for enqueue mark used */
   cl_command_queue_properties  props;  /* Queue properties */
   cl_command_queue prev, next;         /* We chain the command queues together */
-  void *thread_data;                   /* Used to store thread context data */
+  int queue_num_magic;                 /* Used to store thread context data */
   cl_mem perf;                         /* Where to put the perf counters */
   cl_mem fulsim_out;                   /* Fulsim will output this buffer */
 };
diff --git a/src/cl_thread.c b/src/cl_thread.c
index fbad5c5..416e3e8 100644
--- a/src/cl_thread.c
+++ b/src/cl_thread.c
@@ -20,53 +20,45 @@
 #include "cl_alloc.h"
 #include "cl_utils.h"
 
-cl_gpgpu cl_get_thread_gpgpu(cl_command_queue queue)
+static volatile int inited = 0;
+static pthread_key_t thread_queue_key;
+static volatile int global_queue_magic;
+static __thread volatile int thread_queue_magic = 0;
+static __thread cl_gpgpu thread_gpgpu = NULL;
+
+static void thread_data_destructor(void *data)
 {
-  pthread_key_t* key = queue->thread_data;
-  cl_gpgpu gpgpu = pthread_getspecific(*key);
+  cl_gpgpu_delete(thread_gpgpu);
+  thread_queue_magic = 0;
+}
 
-  if (!gpgpu) {
-    TRY_ALLOC_NO_ERR (gpgpu, cl_gpgpu_new(queue->ctx->drv));
+int cl_thread_new_queue_magic_num(void)
+{
+  if (!inited) {
+    pthread_key_create(&thread_queue_key, thread_data_destructor);
+    global_queue_magic = 1;
+    inited = 1;
   }
+  return atomic_inc(&global_queue_magic);
+}
 
-  if (pthread_setspecific(*key, gpgpu)) {
-    cl_gpgpu_delete(gpgpu);
-    goto error;
+cl_gpgpu cl_get_thread_gpgpu(cl_command_queue queue)
+{
+  if (!thread_gpgpu) {
+    TRY_ALLOC_NO_ERR (thread_gpgpu, cl_gpgpu_new(queue->ctx->drv));
+    thread_queue_magic = queue->queue_num_magic;
+    return thread_gpgpu;
+  }
+
+  if (thread_queue_magic != queue->queue_num_magic) {
+    cl_gpgpu_delete(thread_gpgpu);
+    TRY_ALLOC_NO_ERR (thread_gpgpu, cl_gpgpu_new(queue->ctx->drv));
+    thread_queue_magic = queue->queue_num_magic;
   }
 
 exit:
-  return gpgpu;
+  return thread_gpgpu;
 error:
-  pthread_setspecific(*key, NULL);
+  assert(thread_gpgpu != NULL);
   goto exit;
 }
-
-static void thread_data_destructor(void *data) {
-  cl_gpgpu gpgpu = (cl_gpgpu)data;
-  cl_gpgpu_delete(gpgpu);
-}
-
-/* Create the thread specific data. */
-void* cl_thread_data_create(void)
-{
-  int rc = 0;
-
-  pthread_key_t *thread_specific_key = CALLOC(pthread_key_t);
-  if (thread_specific_key == NULL)
-    return NULL;
-
-  rc = pthread_key_create(thread_specific_key, thread_data_destructor);
-
-  if (rc != 0)
-    return NULL;
-
-  return thread_specific_key;
-}
-
-/* The destructor for clean the thread specific data. */
-void cl_thread_data_destroy(void * data)
-{
-  pthread_key_t *thread_specific_key = (pthread_key_t *)data;
-  pthread_key_delete(*thread_specific_key);
-  cl_free(thread_specific_key);
-}
diff --git a/src/cl_thread.h b/src/cl_thread.h
index 65f1bcf..7993d25 100644
--- a/src/cl_thread.h
+++ b/src/cl_thread.h
@@ -23,12 +23,8 @@
 #include "cl_internals.h"
 #include "cl_command_queue.h"
 
-/* Create the thread specific data. */
-void* cl_thread_data_create(void);
-
-/* The destructor for clean the thread specific data. */
-void cl_thread_data_destroy(void * data);
-
 /* Used to get the gpgpu struct of each thread. */
 cl_gpgpu cl_get_thread_gpgpu(cl_command_queue queue);
+
+int cl_thread_new_queue_magic_num(void);
 #endif /* __CL_THREAD_H__ */
-- 
1.8.3.2



More information about the Beignet mailing list