summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPan Xiuli <xiuli.pan@intel.com>2015-10-13 12:51:14 +0800
committerYang Rong <rong.r.yang@intel.com>2015-12-18 14:05:58 +0800
commit16562545dd532d06dfd89092098f64e907b90cbe (patch)
treef5d7290a350ea975c82e27b8ac87338ae79dcbd3
parent930381f84cc899f1caa8a52201d9e4e66843341a (diff)
runtime: refine the last_event in queue to a list
Refine the event struct to make last_event become a list to store all uncompeleted events and update them every queue flush. This can make sure all events created in the runtime have a chance to update status and run callback functions and then be deleted. We will also fix the memory leak problem casued by uncompeted events. This is a bugfix for https://bugs.freedesktop.org/show_bug.cgi?id=91710 The leaked events with gpu buffers will be unreferenced and cause other drm buffer leak and result in terrible memory leak. Signed-off-by: Pan Xiuli <xiuli.pan@intel.com> Reviewed-by: "Yang, Rong R" <rong.r.yang@intel.com>
-rw-r--r--src/cl_command_queue.c22
-rw-r--r--src/cl_event.c52
-rw-r--r--src/cl_event.h5
3 files changed, 55 insertions, 24 deletions
diff --git a/src/cl_command_queue.c b/src/cl_command_queue.c
index 4e4ebfba..50436fc5 100644
--- a/src/cl_command_queue.c
+++ b/src/cl_command_queue.c
@@ -76,11 +76,9 @@ cl_command_queue_delete(cl_command_queue queue)
assert(queue);
if (atomic_dec(&queue->ref_n) != 1) return;
- // If there is a valid last event, we need to give it a chance to
- // call the call-back function.
- cl_event last_event = get_last_event(queue);
- if (last_event && last_event->user_cb)
- cl_event_update_status(last_event, 1);
+ // If there is a list of valid events, we need to give them
+ // a chance to call the call-back function.
+ cl_event_update_last_events(queue,1);
/* Remove it from the list */
assert(queue->ctx);
pthread_mutex_lock(&queue->ctx->queue_lock);
@@ -255,14 +253,11 @@ cl_command_queue_flush(cl_command_queue queue)
int err;
GET_QUEUE_THREAD_GPGPU(queue);
err = cl_command_queue_flush_gpgpu(queue, gpgpu);
- // As we don't have a deadicate timer thread to take care the possible
- // event which has a call back function registerred and the event will
- // be released at the call back function, no other function will access
- // the event any more. If we don't do this here, we will leak that event
- // and all the corresponding buffers which is really bad.
- cl_event last_event = get_last_event(queue);
- if (last_event && last_event->user_cb)
- cl_event_update_status(last_event, 1);
+ // We now keep a list of uncompleted events and check if they compelte
+ // every flush. This can make sure all events created have chance to be
+ // update status, so the callback functions or reference can be handled.
+ cl_event_update_last_events(queue,0);
+
cl_event current_event = get_current_event(queue);
if (current_event && err == CL_SUCCESS) {
err = cl_event_flush(current_event);
@@ -276,6 +271,7 @@ LOCAL cl_int
cl_command_queue_finish(cl_command_queue queue)
{
cl_gpgpu_sync(cl_get_thread_batch_buf(queue));
+ cl_event_update_last_events(queue,1);
return CL_SUCCESS;
}
diff --git a/src/cl_event.c b/src/cl_event.c
index bf441977..bd4d7006 100644
--- a/src/cl_event.c
+++ b/src/cl_event.c
@@ -28,6 +28,33 @@
#include <assert.h>
#include <stdio.h>
+void cl_event_update_last_events(cl_command_queue queue, int wait)
+{
+ cl_event last_event = get_last_event(queue);
+ if(!last_event) return;
+ cl_event next, now;
+ now = last_event;
+ while(now){
+ next = now->last_next;//get next first in case set status maintain it
+ cl_event_update_status(now,wait);//update event status
+ now = next;
+ }
+}
+
+void cl_event_insert_last_events(cl_command_queue queue,cl_event event)
+{
+ if(!event) return;
+ cl_event last_event = get_last_event(queue);
+ if(last_event){
+ cl_event now = last_event;
+ while(now->last_next)
+ now = now->last_next;
+ now->last_next = event;
+ event->last_prev = now;
+ }
+ else set_last_event(queue,event);
+}
+
inline cl_bool
cl_event_is_gpu_command_type(cl_command_type type)
{
@@ -56,7 +83,7 @@ int cl_event_flush(cl_event event)
event->gpgpu = NULL;
}
cl_gpgpu_event_flush(event->gpgpu_event);
- set_last_event(event->queue, event);
+ cl_event_insert_last_events(event->queue,event);
return err;
}
@@ -117,9 +144,6 @@ void cl_event_delete(cl_event event)
if (atomic_dec(&event->ref_n) > 1)
return;
- if(event->queue && get_last_event(event->queue) == event)
- set_last_event(event->queue, NULL);
-
/* Call all user's callback if haven't execute */
cl_event_call_callback(event, CL_COMPLETE, CL_TRUE); // CL_COMPLETE status will force all callbacks that are not executed to run
@@ -525,8 +549,18 @@ void cl_event_set_status(cl_event event, cl_int status)
event->waits_head = NULL;
}
- if(event->status <= CL_COMPLETE)
+ if(event->status <= CL_COMPLETE){
+ /* Maintain the last_list when event completed*/
+ if (event->last_prev)
+ event->last_prev->last_next = event->last_next;
+ if (event->last_next)
+ event->last_next->last_prev = event->last_prev;
+ if(event->queue && get_last_event(event->queue) == event)
+ set_last_event(event->queue, event->last_next);
+ event->last_prev = NULL;
+ event->last_next = NULL;
cl_event_delete(event);
+ }
}
void cl_event_update_status(cl_event event, int wait)
@@ -568,9 +602,7 @@ cl_int cl_event_marker_with_wait_list(cl_command_queue queue,
return CL_SUCCESS;
}
- cl_event last_event = get_last_event(queue);
- if(last_event && last_event->gpgpu_event)
- cl_gpgpu_event_update_status(last_event->gpgpu_event, 1);
+ cl_event_update_last_events(queue,1);
cl_event_set_status(e, CL_COMPLETE);
return CL_SUCCESS;
@@ -605,9 +637,7 @@ cl_int cl_event_barrier_with_wait_list(cl_command_queue queue,
return CL_SUCCESS;
}
- cl_event last_event = get_last_event(queue);
- if(last_event && last_event->gpgpu_event)
- cl_gpgpu_event_update_status(last_event->gpgpu_event, 1);
+ cl_event_update_last_events(queue,1);
cl_event_set_status(e, CL_COMPLETE);
return CL_SUCCESS;
diff --git a/src/cl_event.h b/src/cl_event.h
index f7bf09f9..67fab190 100644
--- a/src/cl_event.h
+++ b/src/cl_event.h
@@ -71,6 +71,7 @@ struct _cl_event {
cl_bool emplict; /* Identify this event whether created by api emplict*/
cl_ulong timestamp[4];/* The time stamps for profiling. */
cl_ulong queued_timestamp;
+ cl_event last_next, last_prev;/* We need a list to monitor untouchable api event*/
};
/* Create a new event object */
@@ -115,5 +116,9 @@ cl_int cl_event_insert_user_event(user_event** p_u_ev, cl_event event);
cl_int cl_event_remove_user_event(user_event** p_u_ev, cl_event event);
/* flush the event's pending gpgpu batch buffer and notify driver this gpgpu event has been flushed. */
cl_int cl_event_flush(cl_event event);
+/* monitor or block wait all events in the last_event list */
+void cl_event_update_last_events(cl_command_queue queuet, int wait);
+/* insert the event into the last_event list in queue */
+void cl_event_insert_last_events(cl_command_queue queue, cl_event event);
#endif /* __CL_EVENT_H__ */