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

junyan.he at inbox.com junyan.he at inbox.com
Tue Dec 24 23:02:19 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 release the GPGPU resource every
enqueuNDR finished and we re-alloc our gpgpu struct
context next time.

Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 src/cl_command_queue.c |  2 ++
 src/cl_thread.c        | 60 ++++++++++++++++++++++++++++++++++++++++----------
 src/cl_thread.h        |  4 ++++
 3 files changed, 54 insertions(+), 12 deletions(-)

diff --git a/src/cl_command_queue.c b/src/cl_command_queue.c
index 3530976..6e7c1a3 100644
--- a/src/cl_command_queue.c
+++ b/src/cl_command_queue.c
@@ -419,6 +419,8 @@ cl_command_queue_flush(cl_command_queue queue)
   GET_QUEUE_THREAD_GPGPU(queue);
 
   cl_gpgpu_flush(gpgpu);
+
+  cl_invalid_thread_gpgpu(queue);
   return CL_SUCCESS;
 }
 
diff --git a/src/cl_thread.c b/src/cl_thread.c
index fbad5c5..894af9d 100644
--- a/src/cl_thread.c
+++ b/src/cl_thread.c
@@ -20,30 +20,56 @@
 #include "cl_alloc.h"
 #include "cl_utils.h"
 
+typedef struct _cl_thread_spec_data {
+  cl_gpgpu gpgpu ;
+  int valid;
+}cl_thread_spec_data;
+
 cl_gpgpu cl_get_thread_gpgpu(cl_command_queue queue)
 {
   pthread_key_t* key = queue->thread_data;
-  cl_gpgpu gpgpu = pthread_getspecific(*key);
+  cl_thread_spec_data* thread_spec_data = pthread_getspecific(*key);
 
-  if (!gpgpu) {
-    TRY_ALLOC_NO_ERR (gpgpu, cl_gpgpu_new(queue->ctx->drv));
+  if (!thread_spec_data) {
+    TRY_ALLOC_NO_ERR(thread_spec_data, CALLOC(struct _cl_thread_spec_data));
+    if (pthread_setspecific(*key, thread_spec_data)) {
+      cl_free(thread_spec_data);
+      return NULL;
+    }
   }
 
-  if (pthread_setspecific(*key, gpgpu)) {
-    cl_gpgpu_delete(gpgpu);
-    goto error;
+  if (!thread_spec_data->valid) {
+    TRY_ALLOC_NO_ERR(thread_spec_data->gpgpu, cl_gpgpu_new(queue->ctx->drv));
+    thread_spec_data->valid = 1;
   }
 
-exit:
-  return gpgpu;
 error:
-  pthread_setspecific(*key, NULL);
-  goto exit;
+  return thread_spec_data->gpgpu;
+}
+
+void cl_invalid_thread_gpgpu(cl_command_queue queue)
+{
+  pthread_key_t* key = queue->thread_data;
+  cl_thread_spec_data* thread_spec_data = pthread_getspecific(*key);
+
+  if (!thread_spec_data) {
+    return;
+  }
+
+  if (!thread_spec_data->valid) {
+    return;
+  }
+
+  assert(thread_spec_data->gpgpu);
+  cl_gpgpu_delete(thread_spec_data->gpgpu);
+  thread_spec_data->valid = 0;
 }
 
 static void thread_data_destructor(void *data) {
-  cl_gpgpu gpgpu = (cl_gpgpu)data;
-  cl_gpgpu_delete(gpgpu);
+  cl_thread_spec_data* thread_spec_data = (cl_thread_spec_data *)data;
+  if (thread_spec_data->valid)
+    cl_gpgpu_delete(thread_spec_data->gpgpu);
+  cl_free(thread_spec_data);
 }
 
 /* Create the thread specific data. */
@@ -67,6 +93,16 @@ void* cl_thread_data_create(void)
 void cl_thread_data_destroy(void * data)
 {
   pthread_key_t *thread_specific_key = (pthread_key_t *)data;
+
+  /* First release self spec data. */
+  cl_thread_spec_data* thread_spec_data =
+         pthread_getspecific(*thread_specific_key);
+  if (thread_spec_data && thread_spec_data->valid) {
+    cl_gpgpu_delete(thread_spec_data->gpgpu);
+    if (thread_spec_data)
+      cl_free(thread_spec_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..f69c562 100644
--- a/src/cl_thread.h
+++ b/src/cl_thread.h
@@ -31,4 +31,8 @@ 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);
+
+/* Used to release the gpgpu struct of each thread. */
+void cl_invalid_thread_gpgpu(cl_command_queue queue);
+
 #endif /* __CL_THREAD_H__ */
-- 
1.8.3.2



More information about the Beignet mailing list