From: Junyan He <[email protected]> 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 <[email protected]> --- 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 _______________________________________________ Beignet mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/beignet
