[Beignet] [PATCH 6/9 V3] Modify all event related functions using new event handle.
junyan.he at inbox.com
junyan.he at inbox.com
Mon Sep 26 08:00:07 UTC 2016
From: Junyan He <junyan.he at intel.com>
Rewrite the cl_event, and modify all the event functions
using this new event manner. Event will co-operate with
command queue's thread together.
v2:
Fix a logic problem in event create failed.
V3:
Set enqueue default to do nothing, handle some enqueue has nothing
to do.
Signed-off-by: Junyan He <junyan.he at intel.com>
---
src/CMakeLists.txt | 5 +
src/cl_api.c | 1888 +---------------------------------------
src/cl_api_kernel.c | 27 +-
src/cl_command_queue.c | 98 ++-
src/cl_command_queue.h | 7 +-
src/cl_command_queue_enqueue.c | 8 +-
src/cl_command_queue_gen7.c | 21 +-
src/cl_enqueue.c | 502 ++++++-----
src/cl_enqueue.h | 44 +-
src/cl_event.c | 1067 ++++++++++-------------
src/cl_event.h | 146 ++--
src/cl_mem.c | 118 ++-
src/cl_mem.h | 29 +-
13 files changed, 1074 insertions(+), 2886 deletions(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 009d057..626b43f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -68,6 +68,10 @@ set(OPENCL_SRC
${KERNEL_STR_FILES}
cl_base_object.c
cl_api.c
+ cl_api_mem.c
+ cl_api_kernel.c
+ cl_api_command_queue.c
+ cl_api_event.c
cl_alloc.c
cl_kernel.c
cl_program.c
@@ -85,6 +89,7 @@ set(OPENCL_SRC
cl_command_queue.c
cl_command_queue.h
cl_command_queue_gen7.c
+ cl_command_queue_enqueue.c
cl_thread.c
cl_driver.h
cl_driver.cpp
diff --git a/src/cl_api.c b/src/cl_api.c
index a2fee15..f8c48de 100644
--- a/src/cl_api.c
+++ b/src/cl_api.c
@@ -67,92 +67,6 @@ typedef intptr_t cl_device_partition_property;
return RET; \
} while(0)
-static inline cl_int
-handle_events(cl_command_queue queue, cl_int num, const cl_event *wait_list,
- cl_event* event, enqueue_data* data, cl_command_type type)
-{
- cl_int status = cl_event_wait_events(num, wait_list, queue);
- cl_event e = NULL;
- if(event != NULL || status == CL_ENQUEUE_EXECUTE_DEFER) {
- e = cl_event_new(queue->ctx, queue, type, event!=NULL);
-
- /* if need profiling, add the submit timestamp here. */
- if (e->type != CL_COMMAND_USER &&
- e->queue->props & CL_QUEUE_PROFILING_ENABLE) {
- cl_event_get_timestamp(e, CL_PROFILING_COMMAND_QUEUED);
- cl_event_get_queued_cpu_timestamp(e);
- }
-
- if(event != NULL)
- *event = e;
- if(status == CL_ENQUEUE_EXECUTE_DEFER) {
- cl_event_new_enqueue_callback(e, data, num, wait_list);
- }
- }
- set_current_event(queue, e);
- return status;
-}
-
-/* The following code checking overlap is from Appendix of openCL spec 1.1 */
-cl_bool check_copy_overlap(const size_t src_offset[3],
- const size_t dst_offset[3],
- const size_t region[3],
- size_t row_pitch, size_t slice_pitch)
-{
- const size_t src_min[] = {src_offset[0], src_offset[1], src_offset[2]};
- const size_t src_max[] = {src_offset[0] + region[0],
- src_offset[1] + region[1],
- src_offset[2] + region[2]};
- const size_t dst_min[] = {dst_offset[0], dst_offset[1], dst_offset[2]};
- const size_t dst_max[] = {dst_offset[0] + region[0],
- dst_offset[1] + region[1],
- dst_offset[2] + region[2]};
- // Check for overlap
- cl_bool overlap = CL_TRUE;
- unsigned i;
- size_t dst_start = dst_offset[2] * slice_pitch +
- dst_offset[1] * row_pitch + dst_offset[0];
- size_t dst_end = dst_start + (region[2] * slice_pitch +
- region[1] * row_pitch + region[0]);
- size_t src_start = src_offset[2] * slice_pitch +
- src_offset[1] * row_pitch + src_offset[0];
- size_t src_end = src_start + (region[2] * slice_pitch +
- region[1] * row_pitch + region[0]);
-
- for (i=0; i != 3; ++i) {
- overlap = overlap && (src_min[i] < dst_max[i])
- && (src_max[i] > dst_min[i]);
- }
-
- if (!overlap) {
- size_t delta_src_x = (src_offset[0] + region[0] > row_pitch) ?
- src_offset[0] + region[0] - row_pitch : 0;
- size_t delta_dst_x = (dst_offset[0] + region[0] > row_pitch) ?
- dst_offset[0] + region[0] - row_pitch : 0;
- if ( (delta_src_x > 0 && delta_src_x > dst_offset[0]) ||
- (delta_dst_x > 0 && delta_dst_x > src_offset[0]) ) {
- if ( (src_start <= dst_start && dst_start < src_end) ||
- (dst_start <= src_start && src_start < dst_end) )
- overlap = CL_TRUE;
- }
- if (region[2] > 1) {
- size_t src_height = slice_pitch / row_pitch;
- size_t dst_height = slice_pitch / row_pitch;
- size_t delta_src_y = (src_offset[1] + region[1] > src_height) ?
- src_offset[1] + region[1] - src_height : 0;
- size_t delta_dst_y = (dst_offset[1] + region[1] > dst_height) ?
- dst_offset[1] + region[1] - dst_height : 0;
- if ( (delta_src_y > 0 && delta_src_y > dst_offset[1]) ||
- (delta_dst_y > 0 && delta_dst_y > src_offset[1]) ) {
- if ( (src_start <= dst_start && dst_start < src_end) ||
- (dst_start <= src_start && src_start < dst_end) )
- overlap = CL_TRUE;
- }
- }
- }
- return overlap;
-}
-
static cl_int
cl_check_device_type(cl_device_type device_type)
{
@@ -448,16 +362,6 @@ error:
}
cl_int
-clReleaseCommandQueue(cl_command_queue command_queue)
-{
- cl_int err = CL_SUCCESS;
- CHECK_QUEUE (command_queue);
- cl_command_queue_delete(command_queue);
-error:
- return err;
-}
-
-cl_int
clGetCommandQueueInfo(cl_command_queue command_queue,
cl_command_queue_info param_name,
size_t param_value_size,
@@ -1369,26 +1273,6 @@ clGetKernelSubGroupInfoKHR(cl_kernel kernel,
}
cl_int
-clWaitForEvents(cl_uint num_events,
- const cl_event * event_list)
-{
- cl_int err = CL_SUCCESS;
- cl_context ctx = NULL;
-
- if(num_events > 0 && event_list)
- ctx = event_list[0]->ctx;
-
- TRY(cl_event_check_waitlist, num_events, event_list, NULL, ctx);
-
- while(cl_event_wait_events(num_events, event_list, NULL) == CL_ENQUEUE_EXECUTE_DEFER) {
- usleep(8000); //sleep 8ms to wait other thread
- }
-
-error:
- return err;
-}
-
-cl_int
clGetEventInfo(cl_event event,
cl_event_info param_name,
size_t param_value_size,
@@ -1403,9 +1287,9 @@ clGetEventInfo(cl_event event,
} else if (param_name == CL_EVENT_CONTEXT) {
FILL_GETINFO_RET (cl_context, 1, &event->ctx, CL_SUCCESS);
} else if (param_name == CL_EVENT_COMMAND_TYPE) {
- FILL_GETINFO_RET (cl_command_type, 1, &event->type, CL_SUCCESS);
+ FILL_GETINFO_RET (cl_command_type, 1, &event->event_type, CL_SUCCESS);
} else if (param_name == CL_EVENT_COMMAND_EXECUTION_STATUS) {
- cl_event_update_status(event, 0);
+ cl_event_get_status(event);
FILL_GETINFO_RET (cl_int, 1, &event->status, CL_SUCCESS);
} else if (param_name == CL_EVENT_REFERENCE_COUNT) {
cl_uint ref = CL_OBJECT_GET_REF(event);
@@ -1419,22 +1303,6 @@ error:
}
-cl_event
-clCreateUserEvent(cl_context context,
- cl_int * errcode_ret)
-{
- cl_int err = CL_SUCCESS;
- cl_event event = NULL;
- CHECK_CONTEXT(context);
-
- TRY_ALLOC(event, cl_event_new(context, NULL, CL_COMMAND_USER, CL_TRUE));
-
-error:
- if(errcode_ret)
- *errcode_ret = err;
- return event;
-}
-
cl_int
clRetainEvent(cl_event event)
{
@@ -1459,48 +1327,6 @@ error:
return err;
}
-cl_int
-clSetUserEventStatus(cl_event event,
- cl_int execution_status)
-{
- cl_int err = CL_SUCCESS;
-
- CHECK_EVENT(event);
- if(execution_status > CL_COMPLETE) {
- err = CL_INVALID_VALUE;
- goto error;
- }
- if(event->status != CL_SUBMITTED) {
- err = CL_INVALID_OPERATION;
- goto error;
- }
-
- cl_event_set_status(event, execution_status);
-error:
- return err;
-}
-
-cl_int
-clSetEventCallback(cl_event event,
- cl_int command_exec_callback_type,
- void (CL_CALLBACK * pfn_notify) (cl_event, cl_int, void *),
- void * user_data)
-{
- cl_int err = CL_SUCCESS;
-
- CHECK_EVENT(event);
- if((pfn_notify == NULL) ||
- (command_exec_callback_type > CL_SUBMITTED) ||
- (command_exec_callback_type < CL_COMPLETE)) {
- err = CL_INVALID_VALUE;
- goto error;
- }
- err = cl_event_set_callback(event, command_exec_callback_type, pfn_notify, user_data);
-
-error:
- return err;
-
-}
cl_int
clGetEventProfilingInfo(cl_event event,
@@ -1513,9 +1339,9 @@ clGetEventProfilingInfo(cl_event event,
cl_ulong ret_val;
CHECK_EVENT(event);
- cl_event_update_status(event, 0);
+ //cl_event_update_status(event, 0);
- if (event->type == CL_COMMAND_USER ||
+ if (event->event_type == CL_COMMAND_USER ||
!(event->queue->props & CL_QUEUE_PROFILING_ENABLE) ||
event->status != CL_COMPLETE) {
err = CL_PROFILING_INFO_NOT_AVAILABLE;
@@ -1552,1712 +1378,6 @@ error:
return err;
}
-cl_int
-clFlush(cl_command_queue command_queue)
-{
- /* have nothing to do now, as currently
- * clEnqueueNDRangeKernel will flush at
- * the end of each calling. we may need
- * to optimize it latter.*/
- return 0;
-}
-
-cl_int
-clFinish(cl_command_queue command_queue)
-{
- cl_int err = CL_SUCCESS;
-
- CHECK_QUEUE (command_queue);
-
-#ifdef HAS_CMRT
- if (command_queue->cmrt_event != NULL)
- return cmrt_wait_for_task_finished(command_queue);
-#endif
-
- err = cl_command_queue_finish(command_queue);
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueReadBuffer(cl_command_queue command_queue,
- cl_mem buffer,
- cl_bool blocking_read,
- size_t offset,
- size_t size,
- void * ptr,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, defer_enqueue_data = { 0 };
- CHECK_QUEUE(command_queue);
- CHECK_MEM(buffer);
- if (command_queue->ctx != buffer->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (!ptr || !size || offset + size > buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (buffer->flags & (CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS)) {
- err = CL_INVALID_OPERATION;
- goto error;
- }
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, buffer->ctx);
-
- data = &defer_enqueue_data;
- data->type = EnqueueReadBuffer;
- data->mem_obj = buffer;
- data->ptr = ptr;
- data->offset = offset;
- data->size = size;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_READ_BUFFER) == CL_ENQUEUE_EXECUTE_IMM) {
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- }
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueReadBufferRect(cl_command_queue command_queue,
- cl_mem buffer,
- cl_bool blocking_read,
- const size_t * buffer_origin,
- const size_t * host_origin,
- const size_t * region,
- size_t buffer_row_pitch,
- size_t buffer_slice_pitch,
- size_t host_row_pitch,
- size_t host_slice_pitch,
- void * ptr,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_MEM(buffer);
-
- if (command_queue->ctx != buffer->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (buffer->flags & (CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS)) {
- err = CL_INVALID_OPERATION;
- goto error;
- }
-
- if (!ptr || !region || region[0] == 0 || region[1] == 0 || region[2] == 0) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if(buffer_row_pitch == 0)
- buffer_row_pitch = region[0];
- if(buffer_slice_pitch == 0)
- buffer_slice_pitch = region[1] * buffer_row_pitch;
-
- if(host_row_pitch == 0)
- host_row_pitch = region[0];
- if(host_slice_pitch == 0)
- host_slice_pitch = region[1] * host_row_pitch;
-
- if (buffer_row_pitch < region[0] ||
- host_row_pitch < region[0]) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if ((buffer_slice_pitch < region[1] * buffer_row_pitch || buffer_slice_pitch % buffer_row_pitch != 0 ) ||
- (host_slice_pitch < region[1] * host_row_pitch || host_slice_pitch % host_row_pitch != 0 )) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if ((buffer_origin[2] + region[2] - 1) * buffer_slice_pitch
- + (buffer_origin[1] + region[1] - 1) * buffer_row_pitch
- + buffer_origin[0] + region[0] > buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, buffer->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueReadBufferRect;
- data->mem_obj = buffer;
- data->ptr = ptr;
- data->origin[0] = buffer_origin[0]; data->origin[1] = buffer_origin[1]; data->origin[2] = buffer_origin[2];
- data->host_origin[0] = host_origin[0]; data->host_origin[1] = host_origin[1]; data->host_origin[2] = host_origin[2];
- data->region[0] = region[0]; data->region[1] = region[1]; data->region[2] = region[2];
- data->row_pitch = buffer_row_pitch;
- data->slice_pitch = buffer_slice_pitch;
- data->host_row_pitch = host_row_pitch;
- data->host_slice_pitch = host_slice_pitch;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_READ_BUFFER_RECT) == CL_ENQUEUE_EXECUTE_IMM) {
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- }
-
- error:
- return err;
-}
-
-cl_int
-clEnqueueWriteBuffer(cl_command_queue command_queue,
- cl_mem buffer,
- cl_bool blocking_write,
- size_t offset,
- size_t size,
- const void * ptr,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_MEM(buffer);
- if (command_queue->ctx != buffer->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (!ptr || !size || offset + size > buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (buffer->flags & (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS)) {
- err = CL_INVALID_OPERATION;
- goto error;
- }
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, buffer->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueWriteBuffer;
- data->mem_obj = buffer;
- data->const_ptr = ptr;
- data->offset = offset;
- data->size = size;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_WRITE_BUFFER) == CL_ENQUEUE_EXECUTE_IMM) {
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- }
-
- error:
- return err;
-}
-
-cl_int
-clEnqueueWriteBufferRect(cl_command_queue command_queue,
- cl_mem buffer,
- cl_bool blocking_write,
- const size_t * buffer_origin,
- const size_t * host_origin,
- const size_t * region,
- size_t buffer_row_pitch,
- size_t buffer_slice_pitch,
- size_t host_row_pitch,
- size_t host_slice_pitch,
- const void * ptr,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_MEM(buffer);
-
- if (command_queue->ctx != buffer->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (buffer->flags & (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS)) {
- err = CL_INVALID_OPERATION;
- goto error;
- }
-
- if (!ptr || !region || region[0] == 0 || region[1] == 0 || region[2] == 0) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if(buffer_row_pitch == 0)
- buffer_row_pitch = region[0];
- if(buffer_slice_pitch == 0)
- buffer_slice_pitch = region[1] * buffer_row_pitch;
-
- if(host_row_pitch == 0)
- host_row_pitch = region[0];
- if(host_slice_pitch == 0)
- host_slice_pitch = region[1] * host_row_pitch;
-
- if (buffer_row_pitch < region[0] ||
- host_row_pitch < region[0]) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if ((buffer_slice_pitch < region[1] * buffer_row_pitch || buffer_slice_pitch % buffer_row_pitch != 0 ) ||
- (host_slice_pitch < region[1] * host_row_pitch || host_slice_pitch % host_row_pitch != 0 )) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if ((buffer_origin[2] + region[2] - 1) * buffer_slice_pitch
- + (buffer_origin[1] + region[1] - 1) * buffer_row_pitch
- + buffer_origin[0] + region[0] > buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, buffer->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueWriteBufferRect;
- data->mem_obj = buffer;
- data->const_ptr = ptr;
- data->origin[0] = buffer_origin[0]; data->origin[1] = buffer_origin[1]; data->origin[2] = buffer_origin[2];
- data->host_origin[0] = host_origin[0]; data->host_origin[1] = host_origin[1]; data->host_origin[2] = host_origin[2];
- data->region[0] = region[0]; data->region[1] = region[1]; data->region[2] = region[2];
- data->row_pitch = buffer_row_pitch;
- data->slice_pitch = buffer_slice_pitch;
- data->host_row_pitch = host_row_pitch;
- data->host_slice_pitch = host_slice_pitch;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_WRITE_BUFFER_RECT) == CL_ENQUEUE_EXECUTE_IMM) {
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- }
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueFillImage(cl_command_queue command_queue,
- cl_mem image,
- const void * fill_color,
- const size_t * porigin,
- const size_t * pregion,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_IMAGE(image, src_image);
- FIXUP_IMAGE_REGION(src_image, pregion, region);
- FIXUP_IMAGE_ORIGIN(src_image, porigin, origin);
-
- if (command_queue->ctx != image->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (fill_color == NULL) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (!origin || !region || origin[0] + region[0] > src_image->w || origin[1] + region[1] > src_image->h || origin[2] + region[2] > src_image->depth) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (src_image->image_type == CL_MEM_OBJECT_IMAGE2D && (origin[2] != 0 || region[2] != 1)){
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (src_image->image_type == CL_MEM_OBJECT_IMAGE1D && (origin[2] != 0 ||origin[1] != 0 || region[2] != 1 || region[1] != 1)){
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- err = cl_image_fill(command_queue, fill_color, src_image, origin, region);
- if (err) {
- goto error;
- }
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, image->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueFillImage;
- data->queue = command_queue;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_FILL_BUFFER) == CL_ENQUEUE_EXECUTE_IMM) {
- if (event && (*event)->type != CL_COMMAND_USER
- && (*event)->queue->props & CL_QUEUE_PROFILING_ENABLE) {
- cl_event_get_timestamp(*event, CL_PROFILING_COMMAND_SUBMIT);
- }
-
- err = cl_command_queue_flush(command_queue);
- }
-
- if(b_output_kernel_perf)
- time_end(command_queue->ctx, "beignet internal kernel : cl_fill_image", "", command_queue);
-
- return 0;
-
- error:
- return err;
-}
-
-cl_int
-clEnqueueFillBuffer(cl_command_queue command_queue,
- cl_mem buffer,
- const void * pattern,
- size_t pattern_size,
- size_t offset,
- size_t size,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
- static size_t valid_sz[] = {1, 2, 4, 8, 16, 32, 64, 128};
- int i = 0;
-
- CHECK_QUEUE(command_queue);
- CHECK_MEM(buffer);
-
- if (command_queue->ctx != buffer->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (offset + size > buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (pattern == NULL) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- for (i = 0; i < sizeof(valid_sz) / sizeof(size_t); i++) {
- if (valid_sz[i] == pattern_size)
- break;
- }
- if (i == sizeof(valid_sz) / sizeof(size_t)) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (offset % pattern_size || size % pattern_size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- err = cl_mem_fill(command_queue, pattern, pattern_size, buffer, offset, size);
- if (err) {
- goto error;
- }
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, buffer->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueFillBuffer;
- data->queue = command_queue;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_FILL_BUFFER) == CL_ENQUEUE_EXECUTE_IMM) {
- if (event && (*event)->type != CL_COMMAND_USER
- && (*event)->queue->props & CL_QUEUE_PROFILING_ENABLE) {
- cl_event_get_timestamp(*event, CL_PROFILING_COMMAND_SUBMIT);
- }
-
- err = cl_command_queue_flush(command_queue);
- }
-
- if(b_output_kernel_perf)
- time_end(command_queue->ctx, "beignet internal kernel : cl_fill_buffer", "", command_queue);
-
- return 0;
-
- error:
- return err;
-}
-
-cl_int
-clEnqueueCopyBuffer(cl_command_queue command_queue,
- cl_mem src_buffer,
- cl_mem dst_buffer,
- size_t src_offset,
- size_t dst_offset,
- size_t cb,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_MEM(src_buffer);
- CHECK_MEM(dst_buffer);
-
- if (command_queue->ctx != src_buffer->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (command_queue->ctx != dst_buffer->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (src_offset + cb > src_buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
- if (dst_offset + cb > dst_buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- /* Check overlap */
- if (src_buffer == dst_buffer
- && (src_offset <= dst_offset && dst_offset <= src_offset + cb - 1)
- && (dst_offset <= src_offset && src_offset <= dst_offset + cb - 1)) {
- err = CL_MEM_COPY_OVERLAP;
- goto error;
- }
-
- /* Check sub overlap */
- if (src_buffer->type == CL_MEM_SUBBUFFER_TYPE && dst_buffer->type == CL_MEM_SUBBUFFER_TYPE ) {
- struct _cl_mem_buffer* src_b = (struct _cl_mem_buffer*)src_buffer;
- struct _cl_mem_buffer* dst_b = (struct _cl_mem_buffer*)dst_buffer;
- size_t src_sub_offset = src_b->sub_offset;
- size_t dst_sub_offset = dst_b->sub_offset;
-
- if ((src_offset + src_sub_offset <= dst_offset + dst_sub_offset
- && dst_offset + dst_sub_offset <= src_offset + src_sub_offset + cb - 1)
- && (dst_offset + dst_sub_offset <= src_offset + src_sub_offset
- && src_offset + src_sub_offset <= dst_offset + dst_sub_offset + cb - 1)) {
- err = CL_MEM_COPY_OVERLAP;
- goto error;
- }
- }
-
- err = cl_mem_copy(command_queue, src_buffer, dst_buffer, src_offset, dst_offset, cb);
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, src_buffer->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueCopyBuffer;
- data->queue = command_queue;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_COPY_BUFFER) == CL_ENQUEUE_EXECUTE_IMM) {
- if (event && (*event)->type != CL_COMMAND_USER
- && (*event)->queue->props & CL_QUEUE_PROFILING_ENABLE) {
- cl_event_get_timestamp(*event, CL_PROFILING_COMMAND_SUBMIT);
- }
-
- err = cl_command_queue_flush(command_queue);
- }
-
- if(b_output_kernel_perf)
- time_end(command_queue->ctx, "beignet internal kernel : cl_mem_copy", "", command_queue);
-
- return 0;
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueCopyBufferRect(cl_command_queue command_queue,
- cl_mem src_buffer,
- cl_mem dst_buffer,
- const size_t * src_origin,
- const size_t * dst_origin,
- const size_t * region,
- size_t src_row_pitch,
- size_t src_slice_pitch,
- size_t dst_row_pitch,
- size_t dst_slice_pitch,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_MEM(src_buffer);
- CHECK_MEM(dst_buffer);
-
- if ((command_queue->ctx != src_buffer->ctx) ||
- (command_queue->ctx != dst_buffer->ctx)) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (!region || region[0] == 0 || region[1] == 0 || region[2] == 0) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if(src_row_pitch == 0)
- src_row_pitch = region[0];
- if(src_slice_pitch == 0)
- src_slice_pitch = region[1] * src_row_pitch;
-
- if(dst_row_pitch == 0)
- dst_row_pitch = region[0];
- if(dst_slice_pitch == 0)
- dst_slice_pitch = region[1] * dst_row_pitch;
-
- if (src_row_pitch < region[0] ||
- dst_row_pitch < region[0]) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if ((src_slice_pitch < region[1] * src_row_pitch || src_slice_pitch % src_row_pitch != 0 ) ||
- (dst_slice_pitch < region[1] * dst_row_pitch || dst_slice_pitch % dst_row_pitch != 0 )) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if ((src_origin[2] + region[2] - 1) * src_slice_pitch
- + (src_origin[1] + region[1] - 1) * src_row_pitch
- + src_origin[0] + region[0] > src_buffer->size
- ||(dst_origin[2] + region[2] - 1) * dst_slice_pitch
- + (dst_origin[1] + region[1] - 1) * dst_row_pitch
- + dst_origin[0] + region[0] > dst_buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (src_buffer == dst_buffer && (src_row_pitch != dst_row_pitch || src_slice_pitch != dst_slice_pitch)) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (src_buffer == dst_buffer &&
- check_copy_overlap(src_origin, dst_origin, region, src_row_pitch, src_slice_pitch)) {
- err = CL_MEM_COPY_OVERLAP;
- goto error;
- }
-
- cl_mem_copy_buffer_rect(command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region,
- src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch);
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, src_buffer->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueCopyBufferRect;
- data->queue = command_queue;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_COPY_BUFFER_RECT) == CL_ENQUEUE_EXECUTE_IMM) {
- if (event && (*event)->type != CL_COMMAND_USER
- && (*event)->queue->props & CL_QUEUE_PROFILING_ENABLE) {
- cl_event_get_timestamp(*event, CL_PROFILING_COMMAND_SUBMIT);
- }
-
- err = cl_command_queue_flush(command_queue);
- }
-
- if(b_output_kernel_perf)
- time_end(command_queue->ctx, "beignet internal kernel : cl_mem_copy_buffer_rect", "", command_queue);
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueReadImage(cl_command_queue command_queue,
- cl_mem mem,
- cl_bool blocking_read,
- const size_t * porigin,
- const size_t * pregion,
- size_t row_pitch,
- size_t slice_pitch,
- void * ptr,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_IMAGE(mem, image);
- FIXUP_IMAGE_REGION(image, pregion, region);
- FIXUP_IMAGE_ORIGIN(image, porigin, origin);
- if (command_queue->ctx != mem->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (!origin || !region || origin[0] + region[0] > image->w || origin[1] + region[1] > image->h || origin[2] + region[2] > image->depth) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (!row_pitch)
- row_pitch = image->bpp*region[0];
- else if (row_pitch < image->bpp*region[0]) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (image->slice_pitch) {
- if (!slice_pitch)
- slice_pitch = row_pitch*region[1];
- else if (slice_pitch < row_pitch*region[1]) {
- err = CL_INVALID_VALUE;
- goto error;
- }
- }
- else if (slice_pitch) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (!ptr) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (mem->flags & (CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS)) {
- err = CL_INVALID_OPERATION;
- goto error;
- }
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, mem->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueReadImage;
- data->mem_obj = mem;
- data->ptr = ptr;
- data->origin[0] = origin[0]; data->origin[1] = origin[1]; data->origin[2] = origin[2];
- data->region[0] = region[0]; data->region[1] = region[1]; data->region[2] = region[2];
- data->row_pitch = row_pitch;
- data->slice_pitch = slice_pitch;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_READ_IMAGE) == CL_ENQUEUE_EXECUTE_IMM) {
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- }
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueWriteImage(cl_command_queue command_queue,
- cl_mem mem,
- cl_bool blocking_write,
- const size_t * porigin,
- const size_t * pregion,
- size_t row_pitch,
- size_t slice_pitch,
- const void * ptr,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_IMAGE(mem, image);
- FIXUP_IMAGE_REGION(image, pregion, region);
- FIXUP_IMAGE_ORIGIN(image, porigin, origin);
- if (command_queue->ctx != mem->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (!origin || !region || origin[0] + region[0] > image->w || origin[1] + region[1] > image->h || origin[2] + region[2] > image->depth) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (!row_pitch)
- row_pitch = image->bpp*region[0];
- else if (row_pitch < image->bpp*region[0]) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (image->slice_pitch) {
- if (!slice_pitch)
- slice_pitch = row_pitch*region[1];
- else if (slice_pitch < row_pitch*region[1]) {
- err = CL_INVALID_VALUE;
- goto error;
- }
- }
- else if (slice_pitch) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (!ptr) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (mem->flags & (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS)) {
- err = CL_INVALID_OPERATION;
- goto error;
- }
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, mem->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueWriteImage;
- data->mem_obj = mem;
- data->const_ptr = ptr;
- data->origin[0] = origin[0]; data->origin[1] = origin[1]; data->origin[2] = origin[2];
- data->region[0] = region[0]; data->region[1] = region[1]; data->region[2] = region[2];
- data->row_pitch = row_pitch;
- data->slice_pitch = slice_pitch;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_WRITE_IMAGE) == CL_ENQUEUE_EXECUTE_IMM) {
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- }
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueCopyImage(cl_command_queue command_queue,
- cl_mem src_mem,
- cl_mem dst_mem,
- const size_t * psrc_origin,
- const size_t * pdst_origin,
- const size_t * pregion,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
- cl_bool overlap = CL_TRUE;
- cl_int i = 0;
-
- CHECK_QUEUE(command_queue);
- CHECK_IMAGE(src_mem, src_image);
- CHECK_IMAGE(dst_mem, dst_image);
- FIXUP_IMAGE_REGION(src_image, pregion, region);
- FIXUP_IMAGE_ORIGIN(src_image, psrc_origin, src_origin);
- FIXUP_IMAGE_ORIGIN(dst_image, pdst_origin, dst_origin);
- if (command_queue->ctx != src_mem->ctx ||
- command_queue->ctx != dst_mem->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (src_image->fmt.image_channel_order != dst_image->fmt.image_channel_order ||
- src_image->fmt.image_channel_data_type != dst_image->fmt.image_channel_data_type) {
- err = CL_IMAGE_FORMAT_MISMATCH;
- goto error;
- }
-
- if (!src_origin || !region || src_origin[0] + region[0] > src_image->w ||
- src_origin[1] + region[1] > src_image->h || src_origin[2] + region[2] > src_image->depth) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (!dst_origin || !region || dst_origin[0] + region[0] > dst_image->w ||
- dst_origin[1] + region[1] > dst_image->h || dst_origin[2] + region[2] > dst_image->depth) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if ((src_image->image_type == CL_MEM_OBJECT_IMAGE2D && (src_origin[2] != 0 || region[2] != 1)) ||
- (dst_image->image_type == CL_MEM_OBJECT_IMAGE2D && (dst_origin[2] != 0 || region[2] != 1))) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (src_image == dst_image) {
- for(i = 0; i < 3; i++)
- overlap = overlap && (src_origin[i] < dst_origin[i] + region[i])
- && (dst_origin[i] < src_origin[i] + region[i]);
- if(overlap == CL_TRUE) {
- err = CL_MEM_COPY_OVERLAP;
- goto error;
- }
- }
-
- cl_mem_kernel_copy_image(command_queue, src_image, dst_image, src_origin, dst_origin, region);
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, src_mem->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueCopyImage;
- data->queue = command_queue;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_COPY_IMAGE) == CL_ENQUEUE_EXECUTE_IMM) {
- if (event && (*event)->type != CL_COMMAND_USER
- && (*event)->queue->props & CL_QUEUE_PROFILING_ENABLE) {
- cl_event_get_timestamp(*event, CL_PROFILING_COMMAND_SUBMIT);
- }
-
- err = cl_command_queue_flush(command_queue);
- }
-
- if(b_output_kernel_perf)
- time_end(command_queue->ctx, "beignet internal kernel : cl_mem_kernel_copy_image", "", command_queue);
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueCopyImageToBuffer(cl_command_queue command_queue,
- cl_mem src_mem,
- cl_mem dst_buffer,
- const size_t * psrc_origin,
- const size_t * pregion,
- size_t dst_offset,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_IMAGE(src_mem, src_image);
- CHECK_MEM(dst_buffer);
- FIXUP_IMAGE_REGION(src_image, pregion, region);
- FIXUP_IMAGE_ORIGIN(src_image, psrc_origin, src_origin);
- if (command_queue->ctx != src_mem->ctx ||
- command_queue->ctx != dst_buffer->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (dst_offset + region[0]*region[1]*region[2]*src_image->bpp > dst_buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (!src_origin || !region || src_origin[0] + region[0] > src_image->w ||
- src_origin[1] + region[1] > src_image->h || src_origin[2] + region[2] > src_image->depth) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (src_image->image_type == CL_MEM_OBJECT_IMAGE2D && (src_origin[2] != 0 || region[2] != 1)) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- cl_mem_copy_image_to_buffer(command_queue, src_image, dst_buffer, src_origin, dst_offset, region);
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, src_mem->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueCopyImageToBuffer;
- data->queue = command_queue;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_COPY_IMAGE_TO_BUFFER) == CL_ENQUEUE_EXECUTE_IMM) {
- if (event && (*event)->type != CL_COMMAND_USER
- && (*event)->queue->props & CL_QUEUE_PROFILING_ENABLE) {
- cl_event_get_timestamp(*event, CL_PROFILING_COMMAND_SUBMIT);
- }
-
- err = cl_command_queue_flush(command_queue);
- }
-
- if(b_output_kernel_perf)
- time_end(command_queue->ctx, "beignet internal kernel : cl_mem_copy_image_to_buffer", "", command_queue);
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueCopyBufferToImage(cl_command_queue command_queue,
- cl_mem src_buffer,
- cl_mem dst_mem,
- size_t src_offset,
- const size_t * pdst_origin,
- const size_t * pregion,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_MEM(src_buffer);
- CHECK_IMAGE(dst_mem, dst_image);
- FIXUP_IMAGE_REGION(dst_image, pregion, region);
- FIXUP_IMAGE_ORIGIN(dst_image, pdst_origin, dst_origin);
- if (command_queue->ctx != src_buffer->ctx ||
- command_queue->ctx != dst_mem->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (src_offset + region[0]*region[1]*region[2]*dst_image->bpp > src_buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (!dst_origin || !region || dst_origin[0] + region[0] > dst_image->w ||
- dst_origin[1] + region[1] > dst_image->h || dst_origin[2] + region[2] > dst_image->depth) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (dst_image->image_type == CL_MEM_OBJECT_IMAGE2D && (dst_origin[2] != 0 || region[2] != 1)) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- cl_mem_copy_buffer_to_image(command_queue, src_buffer, dst_image, src_offset, dst_origin, region);
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, dst_mem->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueCopyBufferToImage;
- data->queue = command_queue;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_COPY_BUFFER_TO_IMAGE) == CL_ENQUEUE_EXECUTE_IMM) {
- if (event && (*event)->type != CL_COMMAND_USER
- && (*event)->queue->props & CL_QUEUE_PROFILING_ENABLE) {
- cl_event_get_timestamp(*event, CL_PROFILING_COMMAND_SUBMIT);
- }
-
- err = cl_command_queue_flush(command_queue);
- }
-
- if(b_output_kernel_perf)
- time_end(command_queue->ctx, "beignet internal kernel : cl_mem_copy_buffer_to_image", "", command_queue);
-
-error:
- return err;
-}
-
-static cl_int _cl_map_mem(cl_mem mem, void *ptr, void **mem_ptr,
- size_t offset, size_t size,
- const size_t *origin, const size_t *region)
-{
- cl_int slot = -1;
- int err = CL_SUCCESS;
- size_t sub_offset = 0;
-
- if(mem->type == CL_MEM_SUBBUFFER_TYPE) {
- struct _cl_mem_buffer* buffer = (struct _cl_mem_buffer*)mem;
- sub_offset = buffer->sub_offset;
- }
-
- ptr = (char*)ptr + offset + sub_offset;
- if(mem->flags & CL_MEM_USE_HOST_PTR) {
- assert(mem->host_ptr);
- //only calc ptr here, will do memcpy in enqueue
- *mem_ptr = (char *)mem->host_ptr + offset + sub_offset;
- } else {
- *mem_ptr = ptr;
- }
- /* Record the mapped address. */
- if (!mem->mapped_ptr_sz) {
- mem->mapped_ptr_sz = 16;
- mem->mapped_ptr = (cl_mapped_ptr *)malloc(
- sizeof(cl_mapped_ptr) * mem->mapped_ptr_sz);
- if (!mem->mapped_ptr) {
- cl_mem_unmap_auto(mem);
- err = CL_OUT_OF_HOST_MEMORY;
- goto error;
- }
- memset(mem->mapped_ptr, 0, mem->mapped_ptr_sz * sizeof(cl_mapped_ptr));
- slot = 0;
- } else {
- int i = 0;
- for (; i < mem->mapped_ptr_sz; i++) {
- if (mem->mapped_ptr[i].ptr == NULL) {
- slot = i;
- break;
- }
- }
- if (i == mem->mapped_ptr_sz) {
- cl_mapped_ptr *new_ptr = (cl_mapped_ptr *)malloc(
- sizeof(cl_mapped_ptr) * mem->mapped_ptr_sz * 2);
- if (!new_ptr) {
- cl_mem_unmap_auto(mem);
- err = CL_OUT_OF_HOST_MEMORY;
- goto error;
- }
- memset(new_ptr, 0, 2 * mem->mapped_ptr_sz * sizeof(cl_mapped_ptr));
- memcpy(new_ptr, mem->mapped_ptr,
- mem->mapped_ptr_sz * sizeof(cl_mapped_ptr));
- slot = mem->mapped_ptr_sz;
- mem->mapped_ptr_sz *= 2;
- free(mem->mapped_ptr);
- mem->mapped_ptr = new_ptr;
- }
- }
- assert(slot != -1);
- mem->mapped_ptr[slot].ptr = *mem_ptr;
- mem->mapped_ptr[slot].v_ptr = ptr;
- mem->mapped_ptr[slot].size = size;
- if(origin) {
- assert(region);
- mem->mapped_ptr[slot].origin[0] = origin[0];
- mem->mapped_ptr[slot].origin[1] = origin[1];
- mem->mapped_ptr[slot].origin[2] = origin[2];
- mem->mapped_ptr[slot].region[0] = region[0];
- mem->mapped_ptr[slot].region[1] = region[1];
- mem->mapped_ptr[slot].region[2] = region[2];
- }
- mem->map_ref++;
-error:
- if (err != CL_SUCCESS)
- *mem_ptr = NULL;
- return err;
-}
-
-void *
-clEnqueueMapBuffer(cl_command_queue command_queue,
- cl_mem buffer,
- cl_bool blocking_map,
- cl_map_flags map_flags,
- size_t offset,
- size_t size,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event,
- cl_int * errcode_ret)
-{
- cl_int err = CL_SUCCESS;
- void *ptr = NULL;
- void *mem_ptr = NULL;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_MEM(buffer);
- if (command_queue->ctx != buffer->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (!size || offset + size > buffer->size) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if ((map_flags & CL_MAP_READ &&
- buffer->flags & (CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS)) ||
- (map_flags & (CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION) &&
- buffer->flags & (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS)))
- {
- err = CL_INVALID_OPERATION;
- goto error;
- }
-
-#ifdef HAS_CMRT
- if (command_queue->cmrt_event != NULL)
- cmrt_wait_for_task_finished(command_queue);
-#endif
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, buffer->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueMapBuffer;
- data->mem_obj = buffer;
- data->offset = offset;
- data->size = size;
- data->ptr = ptr;
- data->unsync_map = 1;
- if (map_flags & (CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION))
- data->write_map = 1;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_MAP_BUFFER) == CL_ENQUEUE_EXECUTE_IMM) {
- data->unsync_map = 0;
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if (err != CL_SUCCESS)
- goto error;
- ptr = data->ptr;
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- } else {
- if (buffer->is_userptr)
- ptr = buffer->host_ptr;
- else {
- if ((ptr = cl_mem_map_gtt_unsync(buffer)) == NULL) {
- err = CL_MAP_FAILURE;
- goto error;
- }
- }
- }
- err = _cl_map_mem(buffer, ptr, &mem_ptr, offset, size, NULL, NULL);
- if (err != CL_SUCCESS)
- goto error;
-
-error:
- if (errcode_ret)
- *errcode_ret = err;
- return mem_ptr;
-}
-
-void *
-clEnqueueMapImage(cl_command_queue command_queue,
- cl_mem mem,
- cl_bool blocking_map,
- cl_map_flags map_flags,
- const size_t * porigin,
- const size_t * pregion,
- size_t * image_row_pitch,
- size_t * image_slice_pitch,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event,
- cl_int * errcode_ret)
-{
- cl_int err = CL_SUCCESS;
- void *ptr = NULL;
- void *mem_ptr = NULL;
- size_t offset = 0;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_IMAGE(mem, image);
- FIXUP_IMAGE_REGION(image, pregion, region);
- FIXUP_IMAGE_ORIGIN(image, porigin, origin);
- if (command_queue->ctx != mem->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- if (!origin || !region || origin[0] + region[0] > image->w || origin[1] + region[1] > image->h || origin[2] + region[2] > image->depth) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (!image_row_pitch || (image->slice_pitch && !image_slice_pitch)) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if ((map_flags & CL_MAP_READ &&
- mem->flags & (CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS)) ||
- (map_flags & (CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION) &&
- mem->flags & (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS)))
- {
- err = CL_INVALID_OPERATION;
- goto error;
- }
-
-#ifdef HAS_CMRT
- if (command_queue->cmrt_event != NULL)
- cmrt_wait_for_task_finished(command_queue);
-#endif
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, mem->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueMapImage;
- data->mem_obj = mem;
- data->origin[0] = origin[0]; data->origin[1] = origin[1]; data->origin[2] = origin[2];
- data->region[0] = region[0]; data->region[1] = region[1]; data->region[2] = region[2];
- data->ptr = ptr;
- data->unsync_map = 1;
- if (map_flags & (CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION))
- data->write_map = 1;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_MAP_IMAGE) == CL_ENQUEUE_EXECUTE_IMM) {
- data->unsync_map = 0;
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if (err != CL_SUCCESS)
- goto error;
- ptr = data->ptr;
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- } else {
- if ((ptr = cl_mem_map_gtt_unsync(mem)) == NULL) {
- err = CL_MAP_FAILURE;
- goto error;
- }
- }
-
- if(mem->flags & CL_MEM_USE_HOST_PTR) {
- if (image_slice_pitch)
- *image_slice_pitch = image->host_slice_pitch;
- *image_row_pitch = image->host_row_pitch;
-
- offset = image->bpp*origin[0] + image->host_row_pitch*origin[1] + image->host_slice_pitch*origin[2];
- } else {
- if (image_slice_pitch)
- *image_slice_pitch = image->slice_pitch;
- if (image->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY)
- *image_row_pitch = image->slice_pitch;
- else
- *image_row_pitch = image->row_pitch;
-
- offset = image->bpp*origin[0] + image->row_pitch*origin[1] + image->slice_pitch*origin[2];
- }
- err = _cl_map_mem(mem, ptr, &mem_ptr, offset, 0, origin, region);
-
-error:
- if (errcode_ret)
- *errcode_ret = err;
- return mem_ptr; //TODO: map and unmap first
-}
-
-cl_int
-clEnqueueUnmapMemObject(cl_command_queue command_queue,
- cl_mem memobj,
- void * mapped_ptr,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_MEM(memobj);
- if (command_queue->ctx != memobj->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, memobj->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueUnmapMemObject;
- data->mem_obj = memobj;
- data->ptr = mapped_ptr;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_UNMAP_MEM_OBJECT) == CL_ENQUEUE_EXECUTE_IMM) {
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- }
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueMigrateMemObjects(cl_command_queue command_queue,
- cl_uint num_mem_objects,
- const cl_mem * mem_objects,
- cl_mem_migration_flags flags,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- /* So far, we just support 1 device and no subdevice. So all the command queues
- belong to the small context. There is no need to migrate the mem objects by now. */
- cl_int err = CL_SUCCESS;
- cl_uint i = 0;
- enqueue_data *data, defer_enqueue_data = { 0 };
-
- if (!flags & CL_MIGRATE_MEM_OBJECT_HOST)
- CHECK_QUEUE(command_queue);
-
- if (num_mem_objects == 0 || mem_objects == NULL) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- if (flags && flags & ~(CL_MIGRATE_MEM_OBJECT_HOST |
- CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED)) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- for (i = 0; i < num_mem_objects; i++) {
- CHECK_MEM(mem_objects[i]);
- if (mem_objects[i]->ctx != command_queue->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
- }
-
- /* really nothing to do, fill the event. */
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, command_queue->ctx);
- data = &defer_enqueue_data;
- data->type = EnqueueMigrateMemObj;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_READ_BUFFER) == CL_ENQUEUE_EXECUTE_IMM) {
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- }
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueNDRangeKernel(cl_command_queue command_queue,
- cl_kernel kernel,
- cl_uint work_dim,
- const size_t * global_work_offset,
- const size_t * global_work_size,
- const size_t * local_work_size,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- size_t fixed_global_off[] = {0,0,0};
- size_t fixed_global_sz[] = {1,1,1};
- size_t fixed_local_sz[] = {1,1,1};
- cl_int err = CL_SUCCESS;
- cl_uint i;
- enqueue_data *data, no_wait_data = { 0 };
-
- CHECK_QUEUE(command_queue);
- CHECK_KERNEL(kernel);
-
- /* Check number of dimensions we have */
- if (UNLIKELY(work_dim == 0 || work_dim > 3)) {
- err = CL_INVALID_WORK_DIMENSION;
- goto error;
- }
-
- /* We need a work size per dimension */
- if (UNLIKELY(global_work_size == NULL)) {
- err = CL_INVALID_GLOBAL_WORK_SIZE;
- goto error;
- }
-
- if (kernel->vme) {
- if (work_dim != 2) {
- err = CL_INVALID_WORK_DIMENSION;
- goto error;
- }
- if (local_work_size != NULL) {
- err = CL_INVALID_WORK_GROUP_SIZE;
- goto error;
- }
- }
-
- if (global_work_offset != NULL)
- for (i = 0; i < work_dim; ++i) {
- if (UNLIKELY(global_work_offset[i] + global_work_size[i] > (size_t)-1)) {
- err = CL_INVALID_GLOBAL_OFFSET;
- goto error;
- }
- }
-
- /* Local sizes must be non-null and divide global sizes */
- if (local_work_size != NULL)
- for (i = 0; i < work_dim; ++i)
- if (UNLIKELY(local_work_size[i] == 0 || global_work_size[i] % local_work_size[i])) {
- err = CL_INVALID_WORK_GROUP_SIZE;
- goto error;
- }
-
- /* Queue and kernel must share the same context */
- assert(kernel->program);
- if (command_queue->ctx != kernel->program->ctx) {
- err = CL_INVALID_CONTEXT;
- goto error;
- }
-
-#ifdef HAS_CMRT
- if (kernel->cmrt_kernel != NULL) {
- err = cmrt_enqueue(command_queue, kernel, global_work_size, local_work_size);
- goto error;
- }
-#endif
-
- /* XXX No event right now */
- //FATAL_IF(num_events_in_wait_list > 0, "Events are not supported");
- //FATAL_IF(event_wait_list != NULL, "Events are not supported");
- //FATAL_IF(event != NULL, "Events are not supported");
-
- if (local_work_size != NULL) {
- for (i = 0; i < work_dim; ++i)
- fixed_local_sz[i] = local_work_size[i];
- } else {
- if (kernel->vme) {
- fixed_local_sz[0] = 16;
- fixed_local_sz[1] = 1;
- } else {
- uint j, maxDimSize = 64 /* from 64? */, maxGroupSize = 256; //MAX_WORK_GROUP_SIZE may too large
- size_t realGroupSize = 1;
- for (i = 0; i< work_dim; i++) {
- for (j = maxDimSize; j > 1; j--) {
- if (global_work_size[i] % j == 0 && j <= maxGroupSize) {
- fixed_local_sz[i] = j;
- maxGroupSize = maxGroupSize /j;
- maxDimSize = maxGroupSize > maxDimSize ? maxDimSize : maxGroupSize;
- break; //choose next work_dim
- }
- }
- realGroupSize *= fixed_local_sz[i];
- }
-
- //in a loop of conformance test (such as test_api repeated_setup_cleanup), in each loop:
- //create a new context, a new command queue, and uses 'globalsize[0]=1000, localsize=NULL' to enqueu kernel
- //it triggers the following message for many times.
- //to avoid too many messages, only print it for the first time of the process.
- //just use static variable since it doesn't matter to print a few times at multi-thread case.
- static int warn_no_good_localsize = 1;
- if (realGroupSize % 8 != 0 && warn_no_good_localsize) {
- warn_no_good_localsize = 0;
- DEBUGP(DL_WARNING, "unable to find good values for local_work_size[i], please provide local_work_size[] explicitly, you can find good values with trial-and-error method.");
- }
- }
- }
-
- if (kernel->vme) {
- fixed_global_sz[0] = (global_work_size[0]+15) / 16 * 16;
- fixed_global_sz[1] = (global_work_size[1]+15) / 16;
- } else {
- for (i = 0; i < work_dim; ++i)
- fixed_global_sz[i] = global_work_size[i];
- }
- if (global_work_offset != NULL)
- for (i = 0; i < work_dim; ++i)
- fixed_global_off[i] = global_work_offset[i];
-
- if (kernel->compile_wg_sz[0] || kernel->compile_wg_sz[1] || kernel->compile_wg_sz[2]) {
- if (fixed_local_sz[0] != kernel->compile_wg_sz[0]
- || fixed_local_sz[1] != kernel->compile_wg_sz[1]
- || fixed_local_sz[2] != kernel->compile_wg_sz[2])
- {
- err = CL_INVALID_WORK_GROUP_SIZE;
- goto error;
- }
- }
-
- /* Do device specific checks are enqueue the kernel */
- err = cl_command_queue_ND_range(command_queue,
- kernel,
- work_dim,
- fixed_global_off,
- fixed_global_sz,
- fixed_local_sz);
- if(err != CL_SUCCESS)
- goto error;
-
- data = &no_wait_data;
- data->type = EnqueueNDRangeKernel;
- data->queue = command_queue;
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, command_queue->ctx);
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_NDRANGE_KERNEL) == CL_ENQUEUE_EXECUTE_IMM) {
- if (event && (*event)->type != CL_COMMAND_USER
- && (*event)->queue->props & CL_QUEUE_PROFILING_ENABLE) {
- cl_event_get_timestamp(*event, CL_PROFILING_COMMAND_SUBMIT);
- }
-
- err = cl_command_queue_flush(command_queue);
- }
-
-error:
- if(b_output_kernel_perf)
- {
- if(kernel->program->build_opts != NULL)
- time_end(command_queue->ctx, cl_kernel_get_name(kernel), kernel->program->build_opts, command_queue);
- else
- time_end(command_queue->ctx, cl_kernel_get_name(kernel), "", command_queue);
- }
-
- return err;
-}
-
-cl_int
-clEnqueueTask(cl_command_queue command_queue,
- cl_kernel kernel,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- const size_t global_size[3] = {1, 0, 0};
- const size_t local_size[3] = {1, 0, 0};
-
- return clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, global_size, local_size,
- num_events_in_wait_list, event_wait_list, event);
-}
-
-cl_int
-clEnqueueNativeKernel(cl_command_queue command_queue,
- void (*user_func)(void *),
- void * args,
- size_t cb_args,
- cl_uint num_mem_objects,
- const cl_mem * mem_list,
- const void ** args_mem_loc,
- cl_uint num_events_in_wait_list,
- const cl_event * event_wait_list,
- cl_event * event)
-{
- cl_int err = CL_SUCCESS;
- void *new_args = NULL;
- enqueue_data *data, no_wait_data = { 0 };
- cl_int i;
-
- if(user_func == NULL ||
- (args == NULL && cb_args > 0) ||
- (args == NULL && num_mem_objects ==0) ||
- (args != NULL && cb_args == 0) ||
- (num_mem_objects > 0 && (mem_list == NULL || args_mem_loc == NULL)) ||
- (num_mem_objects == 0 && (mem_list != NULL || args_mem_loc != NULL))) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- //Per spec, need copy args
- if (cb_args)
- {
- new_args = malloc(cb_args);
- if (!new_args)
- {
- err = CL_OUT_OF_HOST_MEMORY;
- goto error;
- }
- memcpy(new_args, args, cb_args);
-
- for (i=0; i<num_mem_objects; ++i)
- {
- CHECK_MEM(mem_list[i]);
- args_mem_loc[i] = new_args + (args_mem_loc[i] - args); //change to new args
- }
- }
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, command_queue->ctx);
-
- data = &no_wait_data;
- data->type = EnqueueNativeKernel;
- data->mem_list = mem_list;
- data->ptr = new_args;
- data->size = cb_args;
- data->offset = (size_t)num_mem_objects;
- data->const_ptr = args_mem_loc;
- data->user_func = user_func;
-
- if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
- event, data, CL_COMMAND_NATIVE_KERNEL) == CL_ENQUEUE_EXECUTE_IMM) {
- err = cl_enqueue_handle(event ? *event : NULL, data);
- if(event) cl_event_set_status(*event, CL_COMPLETE);
- }
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueMarker(cl_command_queue command_queue,
- cl_event *event)
-{
- cl_int err = CL_SUCCESS;
- CHECK_QUEUE(command_queue);
- if(event == NULL) {
- err = CL_INVALID_VALUE;
- goto error;
- }
-
- cl_event_marker_with_wait_list(command_queue, 0, NULL, event);
-error:
- return err;
-}
-
-cl_int
-clEnqueueMarkerWithWaitList(cl_command_queue command_queue,
- cl_uint num_events_in_wait_list,
- const cl_event *event_wait_list,
- cl_event *event)
-{
- cl_int err = CL_SUCCESS;
- CHECK_QUEUE(command_queue);
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, command_queue->ctx);
-
- cl_event_marker_with_wait_list(command_queue, num_events_in_wait_list, event_wait_list, event);
-error:
- return err;
-}
-
-cl_int
-clEnqueueWaitForEvents(cl_command_queue command_queue,
- cl_uint num_events,
- const cl_event * event_list)
-{
- cl_int err = CL_SUCCESS;
- CHECK_QUEUE(command_queue);
- err = clWaitForEvents(num_events, event_list);
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueBarrier(cl_command_queue command_queue)
-{
- cl_int err = CL_SUCCESS;
- CHECK_QUEUE(command_queue);
-
- cl_event_barrier_with_wait_list(command_queue, 0, NULL, NULL);
-
-error:
- return err;
-}
-
-cl_int
-clEnqueueBarrierWithWaitList(cl_command_queue command_queue,
- cl_uint num_events_in_wait_list,
- const cl_event *event_wait_list,
- cl_event *event)
-{
- cl_int err = CL_SUCCESS;
- CHECK_QUEUE(command_queue);
-
- TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, command_queue->ctx);
-
- cl_event_barrier_with_wait_list(command_queue, num_events_in_wait_list, event_wait_list, event);
-error:
- return err;
-}
-
#define EXTFUNC(x) \
if (strcmp(#x, func_name) == 0) \
return (void *)x;
diff --git a/src/cl_api_kernel.c b/src/cl_api_kernel.c
index a1075d7..ef494e6 100644
--- a/src/cl_api_kernel.c
+++ b/src/cl_api_kernel.c
@@ -130,10 +130,19 @@ clEnqueueNDRangeKernel(cl_command_queue command_queue,
}
realGroupSize *= fixed_local_sz[i];
}
- if (realGroupSize % 8 != 0)
+
+ //in a loop of conformance test (such as test_api repeated_setup_cleanup), in each loop:
+ //create a new context, a new command queue, and uses 'globalsize[0]=1000, localsize=NULL' to enqueu kernel
+ //it triggers the following message for many times.
+ //to avoid too many messages, only print it for the first time of the process.
+ //just use static variable since it doesn't matter to print a few times at multi-thread case.
+ static int warn_no_good_localsize = 1;
+ if (realGroupSize % 8 != 0 && warn_no_good_localsize) {
+ warn_no_good_localsize = 0;
DEBUGP(DL_WARNING, "unable to find good values for local_work_size[i], please provide\n"
- " local_work_size[] explicitly, you can find good values with\n"
- " trial-and-error method.");
+ " local_work_size[] explicitly, you can find good values with\n"
+ " trial-and-error method.");
+ }
}
}
@@ -253,10 +262,10 @@ clEnqueueNativeKernel(cl_command_queue command_queue,
//Per spec, need copy args
if (cb_args) {
- new_args = CL_MALLOC(cb_args);
+ new_args = cl_malloc(cb_args);
if (num_mem_objects) {
- new_args_mem_loc = CL_MALLOC(sizeof(void *) * num_mem_objects);
- new_mem_list = CL_MALLOC(sizeof(cl_mem) * num_mem_objects);
+ new_args_mem_loc = cl_malloc(sizeof(void *) * num_mem_objects);
+ new_mem_list = cl_malloc(sizeof(cl_mem) * num_mem_objects);
memcpy(new_mem_list, mem_list, sizeof(cl_mem) * num_mem_objects);
}
@@ -320,11 +329,11 @@ clEnqueueNativeKernel(cl_command_queue command_queue,
if (err != CL_SUCCESS) {
if (new_args)
- CL_FREE(new_args);
+ cl_free(new_args);
if (new_mem_list)
- CL_FREE(new_mem_list);
+ cl_free(new_mem_list);
if (new_args_mem_loc)
- CL_FREE(new_args_mem_loc);
+ cl_free(new_args_mem_loc);
}
if (err == CL_SUCCESS && event) {
diff --git a/src/cl_command_queue.c b/src/cl_command_queue.c
index 8d3c6b0..54a487c 100644
--- a/src/cl_command_queue.c
+++ b/src/cl_command_queue.c
@@ -45,14 +45,16 @@ cl_command_queue_new(cl_context ctx)
assert(ctx);
TRY_ALLOC_NO_ERR (queue, CALLOC(struct _cl_command_queue));
CL_OBJECT_INIT_BASE(queue, CL_OBJECT_COMMAND_QUEUE_MAGIC);
+ cl_command_queue_init_enqueue(queue);
- queue->cmrt_event = NULL;
if ((queue->thread_data = cl_thread_data_create()) == NULL) {
goto error;
}
/* Append the command queue in the list */
cl_context_add_queue(ctx, queue);
+ queue->ctx = ctx;
+ queue->cmrt_event = NULL;
exit:
return queue;
@@ -69,6 +71,8 @@ cl_command_queue_delete(cl_command_queue queue)
if (CL_OBJECT_DEC_REF(queue) > 1)
return;
+ cl_command_queue_destroy_enqueue(queue);
+
#ifdef HAS_CMRT
if (queue->cmrt_event != NULL)
cmrt_destroy_event(queue);
@@ -76,7 +80,7 @@ cl_command_queue_delete(cl_command_queue queue)
// 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);
+ //cl_event_update_last_events(queue,1);
cl_thread_data_destroy(queue);
queue->thread_data = NULL;
@@ -112,10 +116,9 @@ set_image_info(char *curbe,
}
LOCAL cl_int
-cl_command_queue_bind_image(cl_command_queue queue, cl_kernel k)
+cl_command_queue_bind_image(cl_command_queue queue, cl_kernel k, cl_gpgpu gpgpu)
{
uint32_t i;
- GET_QUEUE_THREAD_GPGPU(queue);
for (i = 0; i < k->image_sz; i++) {
int id = k->images[i].arg_idx;
@@ -149,9 +152,9 @@ cl_command_queue_bind_image(cl_command_queue queue, cl_kernel k)
}
LOCAL cl_int
-cl_command_queue_bind_surface(cl_command_queue queue, cl_kernel k)
+cl_command_queue_bind_surface(cl_command_queue queue, cl_kernel k, cl_gpgpu gpgpu)
{
- GET_QUEUE_THREAD_GPGPU(queue);
+ //GET_QUEUE_THREAD_GPGPU(queue);
/* Bind all user buffers (given by clSetKernelArg) */
uint32_t i;
@@ -175,7 +178,8 @@ cl_command_queue_bind_surface(cl_command_queue queue, cl_kernel k)
return CL_SUCCESS;
}
-extern cl_int cl_command_queue_ND_range_gen7(cl_command_queue, cl_kernel, uint32_t, const size_t *, const size_t *, const size_t *);
+extern cl_int cl_command_queue_ND_range_gen7(cl_command_queue, cl_kernel, cl_event,
+ uint32_t, const size_t *, const size_t *, const size_t *);
static cl_int
cl_kernel_check_args(cl_kernel k)
@@ -190,6 +194,7 @@ cl_kernel_check_args(cl_kernel k)
LOCAL cl_int
cl_command_queue_ND_range(cl_command_queue queue,
cl_kernel k,
+ cl_event event,
const uint32_t work_dim,
const size_t *global_wk_off,
const size_t *global_wk_sz,
@@ -203,8 +208,10 @@ cl_command_queue_ND_range(cl_command_queue queue,
/* Check that the user did not forget any argument */
TRY (cl_kernel_check_args, k);
+
if (ver == 7 || ver == 75 || ver == 8 || ver == 9)
- TRY (cl_command_queue_ND_range_gen7, queue, k, work_dim, global_wk_off, global_wk_sz, local_wk_sz);
+ TRY (cl_command_queue_ND_range_gen7, queue, k, event,
+ work_dim, global_wk_off, global_wk_sz, local_wk_sz);
else
FATAL ("Unknown Gen Device");
@@ -213,7 +220,7 @@ error:
}
LOCAL int
-cl_command_queue_flush_gpgpu(cl_command_queue queue, cl_gpgpu gpgpu)
+cl_command_queue_flush_gpgpu(cl_gpgpu gpgpu)
{
void* printf_info = cl_gpgpu_get_printf_info(gpgpu);
void* profiling_info;
@@ -246,15 +253,15 @@ cl_command_queue_flush(cl_command_queue queue)
{
int err;
GET_QUEUE_THREAD_GPGPU(queue);
- err = cl_command_queue_flush_gpgpu(queue, gpgpu);
+ err = cl_command_queue_flush_gpgpu(gpgpu);
// 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_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);
+ //err = cl_event_flush(current_event);
set_current_event(queue, NULL);
}
cl_invalid_thread_gpgpu(queue);
@@ -265,7 +272,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);
+ //cl_event_update_last_events(queue,1);
return CL_SUCCESS;
}
@@ -337,72 +344,69 @@ cl_command_queue_remove_event(cl_command_queue queue, cl_event event)
queue->wait_events_num -= 1;
}
-#define DEFAULT_WAIT_EVENTS_SIZE 16
LOCAL void
cl_command_queue_insert_barrier_event(cl_command_queue queue, cl_event event)
{
- cl_int i=0;
- cl_event *new_list;
+ cl_int i = 0;
+
+ cl_event_add_ref(event);
assert(queue != NULL);
- if(queue->barrier_events == NULL) {
- queue->barrier_events_size = DEFAULT_WAIT_EVENTS_SIZE;
- TRY_ALLOC_NO_ERR (queue->barrier_events, CALLOC_ARRAY(cl_event, queue->barrier_events_size));
+ CL_OBJECT_LOCK(queue);
+
+ if (queue->barrier_events == NULL) {
+ queue->barrier_events_size = 4;
+ queue->barrier_events = cl_calloc(queue->barrier_events_size, sizeof(cl_event));
+ assert(queue->barrier_events);
}
- for(i=0; i<queue->barrier_events_num; i++) {
- if(queue->barrier_events[i] == event)
- return; //is in the barrier_events, need to insert
+ for (i = 0; i<queue->barrier_events_num; i++) {
+ assert(queue->barrier_events[i] != event);
}
if(queue->barrier_events_num < queue->barrier_events_size) {
queue->barrier_events[queue->barrier_events_num++] = event;
+ CL_OBJECT_UNLOCK(queue);
return;
}
- //barrier_events_num == barrier_events_size, array is full
+ /* Array is full, double expand. */
queue->barrier_events_size *= 2;
- TRY_ALLOC_NO_ERR (new_list, CALLOC_ARRAY(cl_event, queue->barrier_events_size));
- memcpy(new_list, queue->barrier_events, sizeof(cl_event)*queue->barrier_events_num);
- cl_free(queue->barrier_events);
- queue->barrier_events = new_list;
- queue->barrier_events[queue->barrier_events_num++] = event;
- return;
+ queue->barrier_events = cl_realloc(queue->barrier_events,
+ queue->barrier_events_size * sizeof(cl_event));
+ assert(queue->barrier_events);
-exit:
+ queue->barrier_events[queue->barrier_events_num++] = event;
+ CL_OBJECT_UNLOCK(queue);
return;
-error:
- if(queue->barrier_events)
- cl_free(queue->barrier_events);
- queue->barrier_events = NULL;
- queue->barrier_events_size = 0;
- queue->barrier_events_num = 0;
- goto exit;
-
}
LOCAL void
cl_command_queue_remove_barrier_event(cl_command_queue queue, cl_event event)
{
- cl_int i=0;
+ cl_int i = 0;
+ assert(queue != NULL);
- if(queue->barrier_events_num == 0)
- return;
+ CL_OBJECT_LOCK(queue);
- for(i=0; i<queue->barrier_events_num; i++) {
+ assert(queue->barrier_events_num > 0);
+ assert(queue->barrier_events);
+
+ for(i = 0; i < queue->barrier_events_num; i++) {
if(queue->barrier_events[i] == event)
break;
}
+ assert(i < queue->barrier_events_num); // Must find it.
- if(i == queue->barrier_events_num)
- return;
-
- if(i == queue->barrier_events_num - 1) {
+ if(i == queue->barrier_events_num - 1) { // The last one.
queue->barrier_events[i] = NULL;
} else {
- for(; i<queue->barrier_events_num-1; i++) {
+ for(; i < queue->barrier_events_num - 1; i++) { // Move forward.
queue->barrier_events[i] = queue->barrier_events[i+1];
}
}
queue->barrier_events_num -= 1;
+ CL_OBJECT_UNLOCK(queue);
+
+ cl_event_delete(event);
}
diff --git a/src/cl_command_queue.h b/src/cl_command_queue.h
index 34886f8..470cafb 100644
--- a/src/cl_command_queue.h
+++ b/src/cl_command_queue.h
@@ -81,6 +81,7 @@ extern void cl_command_queue_add_ref(cl_command_queue);
/* Map ND range kernel from OCL API */
extern cl_int cl_command_queue_ND_range(cl_command_queue queue,
cl_kernel ker,
+ cl_event event,
const uint32_t work_dim,
const size_t *global_work_offset,
const size_t *global_work_size,
@@ -93,16 +94,16 @@ extern cl_int cl_command_queue_set_report_buffer(cl_command_queue, cl_mem);
extern cl_int cl_command_queue_flush(cl_command_queue);
/* Flush for the specified gpgpu */
-extern int cl_command_queue_flush_gpgpu(cl_command_queue, cl_gpgpu);
+extern int cl_command_queue_flush_gpgpu(cl_gpgpu);
/* Wait for the completion of the command queue */
extern cl_int cl_command_queue_finish(cl_command_queue);
/* Bind all the surfaces in the GPGPU state */
-extern cl_int cl_command_queue_bind_surface(cl_command_queue, cl_kernel);
+extern cl_int cl_command_queue_bind_surface(cl_command_queue, cl_kernel, cl_gpgpu);
/* Bind all the image surfaces in the GPGPU state */
-extern cl_int cl_command_queue_bind_image(cl_command_queue, cl_kernel);
+extern cl_int cl_command_queue_bind_image(cl_command_queue, cl_kernel, cl_gpgpu);
/* Insert a user event to command's wait_events */
extern void cl_command_queue_insert_event(cl_command_queue, cl_event);
diff --git a/src/cl_command_queue_enqueue.c b/src/cl_command_queue_enqueue.c
index 1848d50..7bc6dd3 100644
--- a/src/cl_command_queue_enqueue.c
+++ b/src/cl_command_queue_enqueue.c
@@ -18,7 +18,7 @@
*/
#include "cl_command_queue.h"
-#include "cl_event_new.h"
+#include "cl_event.h"
#include "cl_alloc.h"
#include <stdio.h>
@@ -203,7 +203,7 @@ cl_command_queue_record_in_queue_events(cl_command_queue queue, cl_uint *list_nu
}
assert(event_num > 0);
- enqueued_list = CL_CALLOC(event_num, sizeof(cl_event));
+ enqueued_list = cl_calloc(event_num, sizeof(cl_event));
assert(enqueued_list);
i = 0;
@@ -265,7 +265,7 @@ cl_command_queue_wait_flush(cl_command_queue queue)
cl_event_delete(enqueued_list[i]);
}
if (enqueued_list)
- CL_FREE(enqueued_list);
+ cl_free(enqueued_list);
return CL_SUCCESS;
}
@@ -315,7 +315,7 @@ cl_command_queue_wait_finish(cl_command_queue queue)
cl_event_delete(enqueued_list[i]);
}
if (enqueued_list)
- CL_FREE(enqueued_list);
+ cl_free(enqueued_list);
return CL_SUCCESS;
}
diff --git a/src/cl_command_queue_gen7.c b/src/cl_command_queue_gen7.c
index b6a5920..5ad3b8b 100644
--- a/src/cl_command_queue_gen7.c
+++ b/src/cl_command_queue_gen7.c
@@ -23,6 +23,7 @@
#include "cl_kernel.h"
#include "cl_device_id.h"
#include "cl_mem.h"
+#include "cl_event.h"
#include "cl_utils.h"
#include "cl_alloc.h"
@@ -123,12 +124,12 @@ error:
}
static int
-cl_upload_constant_buffer(cl_command_queue queue, cl_kernel ker)
+cl_upload_constant_buffer(cl_command_queue queue, cl_kernel ker, cl_gpgpu gpgpu)
{
/* calculate constant buffer size
* we need raw_size & aligned_size
*/
- GET_QUEUE_THREAD_GPGPU(queue);
+ //GET_QUEUE_THREAD_GPGPU(queue);
int32_t arg;
size_t offset = 0;
uint32_t raw_size = 0, aligned_size =0;
@@ -331,12 +332,14 @@ cl_alloc_printf(cl_gpgpu gpgpu, cl_kernel ker, void* printf_info, int printf_num
LOCAL cl_int
cl_command_queue_ND_range_gen7(cl_command_queue queue,
cl_kernel ker,
+ cl_event event,
const uint32_t work_dim,
const size_t *global_wk_off,
const size_t *global_wk_sz,
const size_t *local_wk_sz)
{
- GET_QUEUE_THREAD_GPGPU(queue);
+ //GET_QUEUE_THREAD_GPGPU(queue);
+ cl_gpgpu gpgpu = cl_gpgpu_new(queue->ctx->drv);
cl_context ctx = queue->ctx;
char *final_curbe = NULL; /* Includes them and one sub-buffer per group */
cl_gpgpu_kernel kernel;
@@ -403,9 +406,9 @@ cl_command_queue_ND_range_gen7(cl_command_queue queue,
}
/* Bind user buffers */
- cl_command_queue_bind_surface(queue, ker);
+ cl_command_queue_bind_surface(queue, ker, gpgpu);
/* Bind user images */
- if(UNLIKELY(err = cl_command_queue_bind_image(queue, ker) != CL_SUCCESS))
+ if(UNLIKELY(err = cl_command_queue_bind_image(queue, ker, gpgpu) != CL_SUCCESS))
return err;
/* Bind all samplers */
if (ker->vme)
@@ -419,7 +422,7 @@ cl_command_queue_ND_range_gen7(cl_command_queue queue,
/* Bind a stack if needed */
cl_bind_stack(gpgpu, ker);
- if (cl_upload_constant_buffer(queue, ker) != 0)
+ if (cl_upload_constant_buffer(queue, ker, gpgpu) != 0)
goto error;
cl_gpgpu_states_setup(gpgpu, &kernel);
@@ -440,7 +443,7 @@ cl_command_queue_ND_range_gen7(cl_command_queue queue,
batch_sz = cl_kernel_compute_batch_sz(ker);
if (cl_gpgpu_batch_reset(gpgpu, batch_sz) != 0)
goto error;
- cl_set_thread_batch_buf(queue, cl_gpgpu_ref_batch_buf(gpgpu));
+ //cl_set_thread_batch_buf(queue, cl_gpgpu_ref_batch_buf(gpgpu));
cl_gpgpu_batch_start(gpgpu);
/* Issue the GPGPU_WALKER command */
@@ -448,6 +451,10 @@ cl_command_queue_ND_range_gen7(cl_command_queue queue,
/* Close the batch buffer and submit it */
cl_gpgpu_batch_end(gpgpu, 0);
+
+ event->exec_data.gpgpu = gpgpu;
+ event->exec_data.type = EnqueueNDRangeKernel;
+
return CL_SUCCESS;
error:
diff --git a/src/cl_enqueue.c b/src/cl_enqueue.c
index 54c0ffa..ac29ebe 100644
--- a/src/cl_enqueue.c
+++ b/src/cl_enqueue.c
@@ -16,93 +16,101 @@
*
* Author: Rong Yang <rong.r.yang at intel.com>
*/
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <pthread.h>
+//#include "cl_image.h"
#include "cl_enqueue.h"
-#include "cl_image.h"
#include "cl_driver.h"
#include "cl_event.h"
#include "cl_command_queue.h"
#include "cl_utils.h"
+#include "cl_alloc.h"
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <pthread.h>
-
-cl_int cl_enqueue_read_buffer(enqueue_data* data)
+static cl_int
+cl_enqueue_read_buffer(enqueue_data *data, cl_int status)
{
cl_int err = CL_SUCCESS;
cl_mem mem = data->mem_obj;
+
+ if (status != CL_COMPLETE)
+ return err;
+
assert(mem->type == CL_MEM_BUFFER_TYPE ||
mem->type == CL_MEM_SUBBUFFER_TYPE);
- struct _cl_mem_buffer* buffer = (struct _cl_mem_buffer*)mem;
+ struct _cl_mem_buffer *buffer = (struct _cl_mem_buffer *)mem;
//cl_buffer_get_subdata sometime is very very very slow in linux kernel, in skl and chv,
//and it is randomly. So temporary disable it, use map/copy/unmap to read.
//Should re-enable it after find root cause.
if (0 && !mem->is_userptr) {
if (cl_buffer_get_subdata(mem->bo, data->offset + buffer->sub_offset,
- data->size, data->ptr) != 0)
+ data->size, data->ptr) != 0)
err = CL_MAP_FAILURE;
} else {
- void* src_ptr = cl_mem_map_auto(mem, 0);
+ void *src_ptr = cl_mem_map_auto(mem, 0);
if (src_ptr == NULL)
err = CL_MAP_FAILURE;
else {
//sometimes, application invokes read buffer, instead of map buffer, even if userptr is enabled
//memcpy is not necessary for this case
- if (data->ptr != (char*)src_ptr + data->offset + buffer->sub_offset)
- memcpy(data->ptr, (char*)src_ptr + data->offset + buffer->sub_offset, data->size);
+ if (data->ptr != (char *)src_ptr + data->offset + buffer->sub_offset)
+ memcpy(data->ptr, (char *)src_ptr + data->offset + buffer->sub_offset, data->size);
cl_mem_unmap_auto(mem);
}
}
return err;
}
-cl_int cl_enqueue_read_buffer_rect(enqueue_data* data)
+static cl_int
+cl_enqueue_read_buffer_rect(enqueue_data *data, cl_int status)
{
cl_int err = CL_SUCCESS;
- void* src_ptr;
- void* dst_ptr;
+ void *src_ptr;
+ void *dst_ptr;
- const size_t* origin = data->origin;
- const size_t* host_origin = data->host_origin;
- const size_t* region = data->region;
+ const size_t *origin = data->origin;
+ const size_t *host_origin = data->host_origin;
+ const size_t *region = data->region;
cl_mem mem = data->mem_obj;
+
+ if (status != CL_COMPLETE)
+ return err;
+
assert(mem->type == CL_MEM_BUFFER_TYPE ||
mem->type == CL_MEM_SUBBUFFER_TYPE);
- struct _cl_mem_buffer* buffer = (struct _cl_mem_buffer*)mem;
+ struct _cl_mem_buffer *buffer = (struct _cl_mem_buffer *)mem;
if (!(src_ptr = cl_mem_map_auto(mem, 0))) {
err = CL_MAP_FAILURE;
goto error;
}
- size_t offset = origin[0] + data->row_pitch*origin[1] + data->slice_pitch*origin[2];
- src_ptr = (char*)src_ptr + offset + buffer->sub_offset;
-
- offset = host_origin[0] + data->host_row_pitch*host_origin[1] + data->host_slice_pitch*host_origin[2];
- dst_ptr = (char *)data->ptr + offset;
-
- if (data->row_pitch == region[0] && data->row_pitch == data->host_row_pitch &&
- (region[2] == 1 || (data->slice_pitch == region[0]*region[1] && data->slice_pitch == data->host_slice_pitch)))
- {
- memcpy(dst_ptr, src_ptr, region[2] == 1 ? data->row_pitch*region[1] : data->slice_pitch*region[2]);
- }
- else {
- cl_uint y, z;
- for (z = 0; z < region[2]; z++) {
- const char* src = src_ptr;
- char* dst = dst_ptr;
- for (y = 0; y < region[1]; y++) {
- memcpy(dst, src, region[0]);
- src += data->row_pitch;
- dst += data->host_row_pitch;
- }
- src_ptr = (char*)src_ptr + data->slice_pitch;
- dst_ptr = (char*)dst_ptr + data->host_slice_pitch;
- }
- }
+ size_t offset = origin[0] + data->row_pitch * origin[1] + data->slice_pitch * origin[2];
+ src_ptr = (char *)src_ptr + offset + buffer->sub_offset;
+
+ offset = host_origin[0] + data->host_row_pitch * host_origin[1] + data->host_slice_pitch * host_origin[2];
+ dst_ptr = (char *)data->ptr + offset;
+
+ if (data->row_pitch == region[0] && data->row_pitch == data->host_row_pitch &&
+ (region[2] == 1 || (data->slice_pitch == region[0] * region[1] && data->slice_pitch == data->host_slice_pitch))) {
+ memcpy(dst_ptr, src_ptr, region[2] == 1 ? data->row_pitch * region[1] : data->slice_pitch * region[2]);
+ } else {
+ cl_uint y, z;
+ for (z = 0; z < region[2]; z++) {
+ const char *src = src_ptr;
+ char *dst = dst_ptr;
+ for (y = 0; y < region[1]; y++) {
+ memcpy(dst, src, region[0]);
+ src += data->row_pitch;
+ dst += data->host_row_pitch;
+ }
+ src_ptr = (char *)src_ptr + data->slice_pitch;
+ dst_ptr = (char *)dst_ptr + data->host_slice_pitch;
+ }
+ }
err = cl_mem_unmap_auto(mem);
@@ -110,75 +118,80 @@ error:
return err;
}
-cl_int cl_enqueue_write_buffer(enqueue_data *data)
+static cl_int
+cl_enqueue_write_buffer(enqueue_data *data, cl_int status)
{
cl_int err = CL_SUCCESS;
cl_mem mem = data->mem_obj;
assert(mem->type == CL_MEM_BUFFER_TYPE ||
mem->type == CL_MEM_SUBBUFFER_TYPE);
- struct _cl_mem_buffer* buffer = (struct _cl_mem_buffer*)mem;
+ struct _cl_mem_buffer *buffer = (struct _cl_mem_buffer *)mem;
+
+ if (status != CL_COMPLETE)
+ return err;
if (mem->is_userptr) {
- void* dst_ptr = cl_mem_map_auto(mem, 1);
+ void *dst_ptr = cl_mem_map_auto(mem, 1);
if (dst_ptr == NULL)
err = CL_MAP_FAILURE;
else {
- memcpy((char*)dst_ptr + data->offset + buffer->sub_offset, data->const_ptr, data->size);
+ memcpy((char *)dst_ptr + data->offset + buffer->sub_offset, data->const_ptr, data->size);
cl_mem_unmap_auto(mem);
}
- }
- else {
+ } else {
if (cl_buffer_subdata(mem->bo, data->offset + buffer->sub_offset,
- data->size, data->const_ptr) != 0)
+ data->size, data->const_ptr) != 0)
err = CL_MAP_FAILURE;
}
return err;
}
-cl_int cl_enqueue_write_buffer_rect(enqueue_data *data)
+static cl_int
+cl_enqueue_write_buffer_rect(enqueue_data *data, cl_int status)
{
cl_int err = CL_SUCCESS;
- void* src_ptr;
- void* dst_ptr;
+ void *src_ptr;
+ void *dst_ptr;
- const size_t* origin = data->origin;
- const size_t* host_origin = data->host_origin;
- const size_t* region = data->region;
+ const size_t *origin = data->origin;
+ const size_t *host_origin = data->host_origin;
+ const size_t *region = data->region;
cl_mem mem = data->mem_obj;
assert(mem->type == CL_MEM_BUFFER_TYPE ||
mem->type == CL_MEM_SUBBUFFER_TYPE);
- struct _cl_mem_buffer* buffer = (struct _cl_mem_buffer*)mem;
+ struct _cl_mem_buffer *buffer = (struct _cl_mem_buffer *)mem;
+
+ if (status != CL_COMPLETE)
+ return err;
if (!(dst_ptr = cl_mem_map_auto(mem, 1))) {
err = CL_MAP_FAILURE;
goto error;
}
- size_t offset = origin[0] + data->row_pitch*origin[1] + data->slice_pitch*origin[2];
+ size_t offset = origin[0] + data->row_pitch * origin[1] + data->slice_pitch * origin[2];
dst_ptr = (char *)dst_ptr + offset + buffer->sub_offset;
- offset = host_origin[0] + data->host_row_pitch*host_origin[1] + data->host_slice_pitch*host_origin[2];
- src_ptr = (char*)data->const_ptr + offset;
+ offset = host_origin[0] + data->host_row_pitch * host_origin[1] + data->host_slice_pitch * host_origin[2];
+ src_ptr = (char *)data->const_ptr + offset;
if (data->row_pitch == region[0] && data->row_pitch == data->host_row_pitch &&
- (region[2] == 1 || (data->slice_pitch == region[0]*region[1] && data->slice_pitch == data->host_slice_pitch)))
- {
- memcpy(dst_ptr, src_ptr, region[2] == 1 ? data->row_pitch*region[1] : data->slice_pitch*region[2]);
- }
- else {
+ (region[2] == 1 || (data->slice_pitch == region[0] * region[1] && data->slice_pitch == data->host_slice_pitch))) {
+ memcpy(dst_ptr, src_ptr, region[2] == 1 ? data->row_pitch * region[1] : data->slice_pitch * region[2]);
+ } else {
cl_uint y, z;
for (z = 0; z < region[2]; z++) {
- const char* src = src_ptr;
- char* dst = dst_ptr;
+ const char *src = src_ptr;
+ char *dst = dst_ptr;
for (y = 0; y < region[1]; y++) {
memcpy(dst, src, region[0]);
src += data->host_row_pitch;
dst += data->row_pitch;
}
- src_ptr = (char*)src_ptr + data->host_slice_pitch;
- dst_ptr = (char*)dst_ptr + data->slice_pitch;
+ src_ptr = (char *)src_ptr + data->host_slice_pitch;
+ dst_ptr = (char *)dst_ptr + data->slice_pitch;
}
}
@@ -188,16 +201,19 @@ error:
return err;
}
-
-cl_int cl_enqueue_read_image(enqueue_data *data)
+static cl_int
+cl_enqueue_read_image(enqueue_data *data, cl_int status)
{
cl_int err = CL_SUCCESS;
- void* src_ptr;
+ void *src_ptr;
cl_mem mem = data->mem_obj;
CHECK_IMAGE(mem, image);
- const size_t* origin = data->origin;
- const size_t* region = data->region;
+ const size_t *origin = data->origin;
+ const size_t *region = data->region;
+
+ if (status != CL_COMPLETE)
+ return err;
if (!(src_ptr = cl_mem_map_auto(mem, 0))) {
err = CL_MAP_FAILURE;
@@ -208,40 +224,42 @@ cl_int cl_enqueue_read_image(enqueue_data *data)
src_ptr = (char*)src_ptr + offset;
if (!origin[0] && region[0] == image->w && data->row_pitch == image->row_pitch &&
- (region[2] == 1 || (!origin[1] && region[1] == image->h && data->slice_pitch == image->slice_pitch)))
- {
- memcpy(data->ptr, src_ptr, region[2] == 1 ? data->row_pitch*region[1] : data->slice_pitch*region[2]);
- }
- else {
+ (region[2] == 1 || (!origin[1] && region[1] == image->h && data->slice_pitch == image->slice_pitch))) {
+ memcpy(data->ptr, src_ptr, region[2] == 1 ? data->row_pitch * region[1] : data->slice_pitch * region[2]);
+ } else {
cl_uint y, z;
for (z = 0; z < region[2]; z++) {
- const char* src = src_ptr;
- char* dst = data->ptr;
+ const char *src = src_ptr;
+ char *dst = data->ptr;
for (y = 0; y < region[1]; y++) {
- memcpy(dst, src, image->bpp*region[0]);
+ memcpy(dst, src, image->bpp * region[0]);
src += image->row_pitch;
dst += data->row_pitch;
}
- src_ptr = (char*)src_ptr + image->slice_pitch;
- data->ptr = (char*)data->ptr + data->slice_pitch;
+ src_ptr = (char *)src_ptr + image->slice_pitch;
+ data->ptr = (char *)data->ptr + data->slice_pitch;
}
}
- err = cl_mem_unmap_auto(mem);
+ err = cl_mem_unmap_auto(mem);
error:
return err;
-
}
-cl_int cl_enqueue_write_image(enqueue_data *data)
+static cl_int
+cl_enqueue_write_image(enqueue_data *data, cl_int status)
{
cl_int err = CL_SUCCESS;
- void* dst_ptr;
+ void *dst_ptr;
cl_mem mem = data->mem_obj;
+
CHECK_IMAGE(mem, image);
+ if (status != CL_COMPLETE)
+ return err;
+
if (!(dst_ptr = cl_mem_map_auto(mem, 1))) {
err = CL_MAP_FAILURE;
goto error;
@@ -255,45 +273,57 @@ cl_int cl_enqueue_write_image(enqueue_data *data)
error:
return err;
-
}
-cl_int cl_enqueue_map_buffer(enqueue_data *data)
+static cl_int
+cl_enqueue_map_buffer(enqueue_data *data, cl_int status)
{
void *ptr = NULL;
cl_int err = CL_SUCCESS;
cl_mem mem = data->mem_obj;
assert(mem->type == CL_MEM_BUFFER_TYPE ||
mem->type == CL_MEM_SUBBUFFER_TYPE);
- struct _cl_mem_buffer* buffer = (struct _cl_mem_buffer*)mem;
+ struct _cl_mem_buffer *buffer = (struct _cl_mem_buffer *)mem;
- if (mem->is_userptr)
- ptr = cl_mem_map_auto(mem, data->write_map ? 1 : 0);
- else {
- if(data->unsync_map == 1)
- //because using unsync map in clEnqueueMapBuffer, so force use map_gtt here
- ptr = cl_mem_map_gtt(mem);
- else
+ if (status == CL_SUBMITTED) {
+ if (buffer->base.is_userptr) {
+ ptr = buffer->base.host_ptr;
+ } else {
+ if ((ptr = cl_mem_map_gtt_unsync(&buffer->base)) == NULL) {
+ err = CL_MAP_FAILURE;
+ return err;
+ }
+ }
+ data->ptr = ptr;
+ } else if (status == CL_COMPLETE) {
+ if (mem->is_userptr)
ptr = cl_mem_map_auto(mem, data->write_map ? 1 : 0);
- }
+ else {
+ if (data->unsync_map == 1)
+ //because using unsync map in clEnqueueMapBuffer, so force use map_gtt here
+ ptr = cl_mem_map_gtt(mem);
+ else
+ ptr = cl_mem_map_auto(mem, data->write_map ? 1 : 0);
+ }
- if (ptr == NULL) {
- err = CL_MAP_FAILURE;
- goto error;
- }
- data->ptr = ptr;
+ if (ptr == NULL) {
+ err = CL_MAP_FAILURE;
+ return err;
+ }
+ data->ptr = ptr;
- if((mem->flags & CL_MEM_USE_HOST_PTR) && !mem->is_userptr) {
- assert(mem->host_ptr);
- ptr = (char*)ptr + data->offset + buffer->sub_offset;
- memcpy(mem->host_ptr + data->offset + buffer->sub_offset, ptr, data->size);
+ if ((mem->flags & CL_MEM_USE_HOST_PTR) && !mem->is_userptr) {
+ assert(mem->host_ptr);
+ ptr = (char *)ptr + data->offset + buffer->sub_offset;
+ memcpy(mem->host_ptr + data->offset + buffer->sub_offset, ptr, data->size);
+ }
}
-error:
return err;
}
-cl_int cl_enqueue_map_image(enqueue_data *data)
+static cl_int
+cl_enqueue_map_image(enqueue_data *data, cl_int status)
{
cl_int err = CL_SUCCESS;
cl_mem mem = data->mem_obj;
@@ -301,46 +331,59 @@ cl_int cl_enqueue_map_image(enqueue_data *data)
size_t row_pitch = 0;
CHECK_IMAGE(mem, image);
- if(data->unsync_map == 1)
- //because using unsync map in clEnqueueMapBuffer, so force use map_gtt here
- ptr = cl_mem_map_gtt(mem);
- else
- ptr = cl_mem_map_auto(mem, data->write_map ? 1 : 0);
+ if (status == CL_SUBMITTED) {
+ if ((ptr = cl_mem_map_gtt_unsync(mem)) == NULL) {
+ err = CL_MAP_FAILURE;
+ goto error;
+ }
+ data->ptr = ptr;
+ } else if (status == CL_COMPLETE) {
+ if (data->unsync_map == 1)
+ //because using unsync map in clEnqueueMapBuffer, so force use map_gtt here
+ ptr = cl_mem_map_gtt(mem);
+ else
+ ptr = cl_mem_map_auto(mem, data->write_map ? 1 : 0);
+
+ if (ptr == NULL) {
+ err = CL_MAP_FAILURE;
+ goto error;
+ }
- if (ptr == NULL) {
- err = CL_MAP_FAILURE;
- goto error;
- }
- data->ptr = (char*)ptr + image->offset;
- if (image->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY)
- row_pitch = image->slice_pitch;
- else
- row_pitch = image->row_pitch;
-
- if(mem->flags & CL_MEM_USE_HOST_PTR) {
- assert(mem->host_ptr);
- if (!mem->is_userptr)
- //src and dst need add offset in function cl_mem_copy_image_region
- cl_mem_copy_image_region(data->origin, data->region,
- mem->host_ptr, image->host_row_pitch, image->host_slice_pitch,
- data->ptr, row_pitch, image->slice_pitch, image, CL_TRUE, CL_TRUE);
+ data->ptr = (char*)ptr + image->offset;
+ if (image->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY)
+ row_pitch = image->slice_pitch;
+ else
+ row_pitch = image->row_pitch;
+
+ if(mem->flags & CL_MEM_USE_HOST_PTR) {
+ assert(mem->host_ptr);
+ if (!mem->is_userptr)
+ //src and dst need add offset in function cl_mem_copy_image_region
+ cl_mem_copy_image_region(data->origin, data->region,
+ mem->host_ptr, image->host_row_pitch, image->host_slice_pitch,
+ data->ptr, row_pitch, image->slice_pitch, image, CL_TRUE, CL_TRUE);
+ }
}
error:
return err;
}
-cl_int cl_enqueue_unmap_mem_object(enqueue_data *data)
+static cl_int
+cl_enqueue_unmap_mem_object(enqueue_data *data, cl_int status)
{
cl_int err = CL_SUCCESS;
int i, j;
size_t mapped_size = 0;
size_t origin[3], region[3];
- void * v_ptr = NULL;
- void * mapped_ptr = data->ptr;
+ void *v_ptr = NULL;
+ void *mapped_ptr = data->ptr;
cl_mem memobj = data->mem_obj;
size_t row_pitch = 0;
+ if (status != CL_COMPLETE)
+ return err;
+
assert(memobj->mapped_ptr_sz >= memobj->map_ref);
INVALID_VALUE_IF(!mapped_ptr);
for (i = 0; i < memobj->mapped_ptr_sz; i++) {
@@ -348,7 +391,7 @@ cl_int cl_enqueue_unmap_mem_object(enqueue_data *data)
memobj->mapped_ptr[i].ptr = NULL;
mapped_size = memobj->mapped_ptr[i].size;
v_ptr = memobj->mapped_ptr[i].v_ptr;
- for(j=0; j<3; j++) {
+ for (j = 0; j < 3; j++) {
region[j] = memobj->mapped_ptr[i].region[j];
origin[j] = memobj->mapped_ptr[i].origin[j];
memobj->mapped_ptr[i].region[j] = 0;
@@ -364,10 +407,10 @@ cl_int cl_enqueue_unmap_mem_object(enqueue_data *data)
INVALID_VALUE_IF(i == memobj->mapped_ptr_sz);
if (memobj->flags & CL_MEM_USE_HOST_PTR) {
- if(memobj->type == CL_MEM_BUFFER_TYPE ||
- memobj->type == CL_MEM_SUBBUFFER_TYPE) {
+ if (memobj->type == CL_MEM_BUFFER_TYPE ||
+ memobj->type == CL_MEM_SUBBUFFER_TYPE) {
assert(mapped_ptr >= memobj->host_ptr &&
- mapped_ptr + mapped_size <= memobj->host_ptr + memobj->size);
+ mapped_ptr + mapped_size <= memobj->host_ptr + memobj->size);
/* Sync the data. */
if (!memobj->is_userptr)
memcpy(v_ptr, mapped_ptr, mapped_size);
@@ -381,8 +424,8 @@ cl_int cl_enqueue_unmap_mem_object(enqueue_data *data)
if (!memobj->is_userptr)
//v_ptr have added offset, host_ptr have not added offset.
cl_mem_copy_image_region(origin, region, v_ptr, row_pitch, image->slice_pitch,
- memobj->host_ptr, image->host_row_pitch, image->host_slice_pitch,
- image, CL_FALSE, CL_TRUE);
+ memobj->host_ptr, image->host_row_pitch, image->host_slice_pitch,
+ image, CL_FALSE, CL_TRUE);
}
} else {
assert(v_ptr == mapped_ptr);
@@ -391,24 +434,24 @@ cl_int cl_enqueue_unmap_mem_object(enqueue_data *data)
cl_mem_unmap_auto(memobj);
/* shrink the mapped slot. */
- if (memobj->mapped_ptr_sz/2 > memobj->map_ref) {
+ if (memobj->mapped_ptr_sz / 2 > memobj->map_ref) {
int j = 0;
cl_mapped_ptr *new_ptr = (cl_mapped_ptr *)malloc(
- sizeof(cl_mapped_ptr) * (memobj->mapped_ptr_sz/2));
+ sizeof(cl_mapped_ptr) * (memobj->mapped_ptr_sz / 2));
if (!new_ptr) {
/* Just do nothing. */
goto error;
}
- memset(new_ptr, 0, (memobj->mapped_ptr_sz/2) * sizeof(cl_mapped_ptr));
+ memset(new_ptr, 0, (memobj->mapped_ptr_sz / 2) * sizeof(cl_mapped_ptr));
for (i = 0; i < memobj->mapped_ptr_sz; i++) {
if (memobj->mapped_ptr[i].ptr) {
new_ptr[j] = memobj->mapped_ptr[i];
j++;
- assert(j < memobj->mapped_ptr_sz/2);
+ assert(j < memobj->mapped_ptr_sz / 2);
}
}
- memobj->mapped_ptr_sz = memobj->mapped_ptr_sz/2;
+ memobj->mapped_ptr_sz = memobj->mapped_ptr_sz / 2;
free(memobj->mapped_ptr);
memobj->mapped_ptr = new_ptr;
}
@@ -417,7 +460,8 @@ error:
return err;
}
-cl_int cl_enqueue_native_kernel(enqueue_data *data)
+static cl_int
+cl_enqueue_native_kernel(enqueue_data *data, cl_int status)
{
cl_int err = CL_SUCCESS;
cl_uint num_mem_objects = (cl_uint)data->offset;
@@ -425,18 +469,19 @@ cl_int cl_enqueue_native_kernel(enqueue_data *data)
const void **args_mem_loc = (const void **)data->const_ptr;
cl_uint i;
- for (i=0; i<num_mem_objects; ++i)
- {
- const cl_mem buffer = mem_list[i];
- CHECK_MEM(buffer);
+ if (status != CL_COMPLETE)
+ return err;
+
+ for (i = 0; i < num_mem_objects; ++i) {
+ const cl_mem buffer = mem_list[i];
+ CHECK_MEM(buffer);
- *((void **)args_mem_loc[i]) = cl_mem_map_auto(buffer, 0);
+ *((void **)args_mem_loc[i]) = cl_mem_map_auto(buffer, 0);
}
data->user_func(data->ptr);
- for (i=0; i<num_mem_objects; ++i)
- {
- cl_mem_unmap_auto(mem_list[i]);
+ for (i = 0; i < num_mem_objects; ++i) {
+ cl_mem_unmap_auto(mem_list[i]);
}
free(data->ptr);
@@ -444,46 +489,115 @@ error:
return err;
}
-cl_int cl_enqueue_handle(cl_event event, enqueue_data* data)
+static cl_int
+cl_enqueue_ndrange(enqueue_data *data, cl_int status)
{
- /* if need profiling, add the submit timestamp here. */
- if (event && event->type != CL_COMMAND_USER
- && event->queue->props & CL_QUEUE_PROFILING_ENABLE) {
- cl_event_get_timestamp(event, CL_PROFILING_COMMAND_SUBMIT);
+ cl_int err = CL_SUCCESS;
+
+ if (status == CL_SUBMITTED) {
+ err = cl_command_queue_flush_gpgpu(data->gpgpu);
+ } else if (status == CL_COMPLETE) {
+ void *batch_buf = cl_gpgpu_ref_batch_buf(data->gpgpu);
+ cl_gpgpu_sync(batch_buf);
+ cl_gpgpu_unref_batch_buf(batch_buf);
+ /* Finished, we can release the gpgpu now. */
+ cl_gpgpu_delete(data->gpgpu);
+ data->gpgpu = NULL;
}
- switch(data->type) {
- case EnqueueReadBuffer:
- return cl_enqueue_read_buffer(data);
- case EnqueueReadBufferRect:
- return cl_enqueue_read_buffer_rect(data);
- case EnqueueWriteBuffer:
- return cl_enqueue_write_buffer(data);
- case EnqueueWriteBufferRect:
- return cl_enqueue_write_buffer_rect(data);
- case EnqueueReadImage:
- return cl_enqueue_read_image(data);
- case EnqueueWriteImage:
- return cl_enqueue_write_image(data);
- case EnqueueMapBuffer:
- return cl_enqueue_map_buffer(data);
- case EnqueueMapImage:
- return cl_enqueue_map_image(data);
- case EnqueueUnmapMemObject:
- return cl_enqueue_unmap_mem_object(data);
- case EnqueueCopyBufferRect:
- case EnqueueCopyBuffer:
- case EnqueueCopyImage:
- case EnqueueCopyBufferToImage:
- case EnqueueCopyImageToBuffer:
- case EnqueueNDRangeKernel:
- case EnqueueFillBuffer:
- case EnqueueFillImage:
- return cl_event_flush(event);
- case EnqueueNativeKernel:
- return cl_enqueue_native_kernel(data);
- case EnqueueMigrateMemObj:
- default:
- return CL_SUCCESS;
+ return err;
+}
+
+static cl_int
+cl_enqueue_marker_or_barrier(enqueue_data *data, cl_int status)
+{
+ return CL_COMPLETE;
+}
+
+LOCAL void
+cl_enqueue_delete(enqueue_data *data)
+{
+ if (data == NULL)
+ return;
+
+ if (data->type == EnqueueCopyBufferRect ||
+ data->type == EnqueueCopyBuffer ||
+ data->type == EnqueueCopyImage ||
+ data->type == EnqueueCopyBufferToImage ||
+ data->type == EnqueueCopyImageToBuffer ||
+ data->type == EnqueueNDRangeKernel ||
+ data->type == EnqueueFillBuffer ||
+ data->type == EnqueueFillImage) {
+ if (data->gpgpu) {
+ cl_gpgpu_delete(data->gpgpu);
+ data->gpgpu = NULL;
+ }
+ return;
+ }
+
+ if (data->type == EnqueueNativeKernel) {
+ if (data->mem_list) {
+ cl_free((void*)data->mem_list);
+ data->mem_list = NULL;
+ }
+ if (data->ptr) {
+ cl_free((void*)data->ptr);
+ data->ptr = NULL;
+ }
+ if (data->const_ptr) {
+ cl_free((void*)data->const_ptr);
+ data->const_ptr = NULL;
+ }
+ }
+}
+
+LOCAL cl_int
+cl_enqueue_handle(enqueue_data *data, cl_int status)
+{
+ /* if need profiling, add the submit timestamp here. */
+ // if (event && event->event_type != CL_COMMAND_USER &&
+ // event->queue->props & CL_QUEUE_PROFILING_ENABLE) {
+ // cl_event_get_timestamp(event, CL_PROFILING_COMMAND_SUBMIT);
+ // }
+
+ switch (data->type) {
+ case EnqueueReturnSuccesss:
+ return CL_SUCCESS;
+ case EnqueueReadBuffer:
+ return cl_enqueue_read_buffer(data, status);
+ case EnqueueReadBufferRect:
+ return cl_enqueue_read_buffer_rect(data, status);
+ case EnqueueWriteBuffer:
+ return cl_enqueue_write_buffer(data, status);
+ case EnqueueWriteBufferRect:
+ return cl_enqueue_write_buffer_rect(data, status);
+ case EnqueueReadImage:
+ return cl_enqueue_read_image(data, status);
+ case EnqueueWriteImage:
+ return cl_enqueue_write_image(data, status);
+ case EnqueueMapBuffer:
+ return cl_enqueue_map_buffer(data, status);
+ case EnqueueMapImage:
+ return cl_enqueue_map_image(data, status);
+ case EnqueueUnmapMemObject:
+ return cl_enqueue_unmap_mem_object(data, status);
+ case EnqueueMarker:
+ case EnqueueBarrier:
+ return cl_enqueue_marker_or_barrier(data, status);
+ case EnqueueCopyBufferRect:
+ case EnqueueCopyBuffer:
+ case EnqueueCopyImage:
+ case EnqueueCopyBufferToImage:
+ case EnqueueCopyImageToBuffer:
+ case EnqueueNDRangeKernel:
+ case EnqueueFillBuffer:
+ case EnqueueFillImage:
+ //return cl_event_flush(event);
+ return cl_enqueue_ndrange(data, status);
+ case EnqueueNativeKernel:
+ return cl_enqueue_native_kernel(data, status);
+ case EnqueueMigrateMemObj:
+ default:
+ return CL_SUCCESS;
}
}
diff --git a/src/cl_enqueue.h b/src/cl_enqueue.h
index 09305af..f8fff9d 100644
--- a/src/cl_enqueue.h
+++ b/src/cl_enqueue.h
@@ -24,7 +24,8 @@
#include "CL/cl.h"
typedef enum {
- EnqueueReadBuffer = 0,
+ EnqueueReturnSuccesss = 0, /* For some case, we have nothing to do, just return SUCCESS. */
+ EnqueueReadBuffer,
EnqueueReadBufferRect,
EnqueueWriteBuffer,
EnqueueWriteBufferRect,
@@ -49,26 +50,29 @@ typedef enum {
} enqueue_type;
typedef struct _enqueue_data {
- enqueue_type type; /* Command type */
- cl_mem mem_obj; /* Enqueue's cl_mem */
- cl_command_queue queue; /* Command queue */
- size_t offset; /* Mem object's offset */
- size_t size; /* Size */
- size_t origin[3]; /* Origin */
- size_t host_origin[3]; /* Origin */
- size_t region[3]; /* Region */
- size_t row_pitch; /* Row pitch */
- size_t slice_pitch; /* Slice pitch */
- size_t host_row_pitch; /* Host row pitch, used in read/write buffer rect */
- size_t host_slice_pitch; /* Host slice pitch, used in read/write buffer rect */
- const void * const_ptr; /* Const ptr for memory read */
- void * ptr; /* Ptr for write and return value */
- const cl_mem* mem_list; /* mem_list of clEnqueueNativeKernel */
- uint8_t unsync_map; /* Indicate the clEnqueueMapBuffer/Image is unsync map */
- uint8_t write_map; /* Indicate if the clEnqueueMapBuffer is write enable */
- void (*user_func)(void *); /* pointer to a host-callable user function */
+ enqueue_type type; /* Command type */
+ cl_mem mem_obj; /* Enqueue's cl_mem */
+ cl_command_queue queue; /* Command queue */
+ size_t offset; /* Mem object's offset */
+ size_t size; /* Size */
+ size_t origin[3]; /* Origin */
+ size_t host_origin[3]; /* Origin */
+ size_t region[3]; /* Region */
+ size_t row_pitch; /* Row pitch */
+ size_t slice_pitch; /* Slice pitch */
+ size_t host_row_pitch; /* Host row pitch, used in read/write buffer rect */
+ size_t host_slice_pitch; /* Host slice pitch, used in read/write buffer rect */
+ const void *const_ptr; /* Const ptr for memory read */
+ void *ptr; /* Ptr for write and return value */
+ const cl_mem *mem_list; /* mem_list of clEnqueueNativeKernel */
+ uint8_t unsync_map; /* Indicate the clEnqueueMapBuffer/Image is unsync map */
+ uint8_t write_map; /* Indicate if the clEnqueueMapBuffer is write enable */
+ void (*user_func)(void *); /* pointer to a host-callable user function */
+ cl_gpgpu gpgpu;
} enqueue_data;
/* Do real enqueue commands */
-cl_int cl_enqueue_handle(cl_event event, enqueue_data* data);
+extern cl_int cl_enqueue_handle(enqueue_data *data, cl_int status);
+extern void cl_enqueue_delete(enqueue_data *data);
+
#endif /* __CL_ENQUEUE_H__ */
diff --git a/src/cl_event.c b/src/cl_event.c
index 6c7c2e0..4acd619 100644
--- a/src/cl_event.c
+++ b/src/cl_event.c
@@ -14,750 +14,615 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
- * Author: Rong Yang <rong.r.yang at intel.com>
*/
#include "cl_event.h"
#include "cl_context.h"
-#include "cl_utils.h"
-#include "cl_alloc.h"
-#include "cl_khr_icd.h"
-#include "cl_kernel.h"
#include "cl_command_queue.h"
-
-#include <assert.h>
+#include "cl_alloc.h"
+#include <string.h>
#include <stdio.h>
-void cl_event_update_last_events(cl_command_queue queue, int wait)
+LOCAL cl_int
+cl_event_get_timestamp(cl_event event, cl_profiling_info param_name)
{
- 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;
- }
+ // TODO:
+ return CL_INVALID_VALUE;
}
-void cl_event_insert_last_events(cl_command_queue queue,cl_event event)
+LOCAL cl_ulong
+cl_event_get_timestamp_delta(cl_ulong start_timestamp, cl_ulong end_timestamp)
{
- 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;
+ cl_ulong ret_val;
+
+ if (end_timestamp > start_timestamp) {
+ ret_val = end_timestamp - start_timestamp;
+ } else {
+ /*if start time stamp is greater than end timstamp then set ret value to max*/
+ ret_val = ((cl_ulong)1 << 32);
}
- else set_last_event(queue,event);
+
+ return ret_val;
}
-static inline cl_bool
-cl_event_is_gpu_command_type(cl_command_type type)
+LOCAL cl_ulong
+cl_event_get_start_timestamp(cl_event event)
{
- switch(type) {
- case CL_COMMAND_COPY_BUFFER:
- case CL_COMMAND_FILL_BUFFER:
- case CL_COMMAND_COPY_IMAGE:
- case CL_COMMAND_COPY_IMAGE_TO_BUFFER:
- case CL_COMMAND_COPY_BUFFER_TO_IMAGE:
- case CL_COMMAND_COPY_BUFFER_RECT:
- case CL_COMMAND_TASK:
- case CL_COMMAND_NDRANGE_KERNEL:
- return CL_TRUE;
- default:
- return CL_FALSE;
- }
+ cl_ulong ret_val;
+
+ ret_val = cl_event_get_timestamp_delta(event->timestamp[0], event->timestamp[2]);
+
+ return ret_val;
}
-int cl_event_flush(cl_event event)
+LOCAL cl_ulong
+cl_event_get_end_timestamp(cl_event event)
{
- int err = CL_SUCCESS;
- if(!event) {
- err = CL_INVALID_VALUE;
- return err;
- }
+ cl_ulong ret_val;
- assert(event->gpgpu_event != NULL);
- if (event->gpgpu) {
- err = cl_command_queue_flush_gpgpu(event->queue, event->gpgpu);
- cl_gpgpu_delete(event->gpgpu);
- event->gpgpu = NULL;
- }
- cl_gpgpu_event_flush(event->gpgpu_event);
- cl_event_insert_last_events(event->queue,event);
- return err;
+ ret_val = cl_event_get_timestamp_delta(event->timestamp[0], event->timestamp[3]);
+
+ return ret_val;
}
-cl_event cl_event_new(cl_context ctx, cl_command_queue queue, cl_command_type type, cl_bool emplict)
+LOCAL void
+cl_event_add_ref(cl_event event)
{
- cl_event event = NULL;
- GET_QUEUE_THREAD_GPGPU(queue);
+ assert(event);
+ CL_OBJECT_INC_REF(event);
+}
- /* Allocate and inialize the structure itself */
- TRY_ALLOC_NO_ERR (event, CALLOC(struct _cl_event));
- CL_OBJECT_INIT_BASE(event, CL_OBJECT_EVENT_MAGIC);
+LOCAL cl_int
+cl_event_get_status(cl_event event)
+{
+ cl_int ret;
+
+ assert(event);
+ CL_OBJECT_LOCK(event);
+ ret = event->status;
+ CL_OBJECT_UNLOCK(event);
+ return ret;
+}
+
+static cl_event
+cl_event_new(cl_context ctx, cl_command_queue queue, cl_command_type type,
+ cl_uint num_events, cl_event *event_list)
+{
+ cl_event e = cl_calloc(1, sizeof(_cl_event));
+ if (e == NULL)
+ return NULL;
+
+ CL_OBJECT_INIT_BASE(e, CL_OBJECT_EVENT_MAGIC);
/* Append the event in the context event list */
- cl_context_add_event(ctx, event);
-
- /* Initialize all members and create GPGPU event object */
- event->queue = queue;
- event->type = type;
- event->gpgpu_event = NULL;
- if(type == CL_COMMAND_USER) {
- event->status = CL_SUBMITTED;
+ cl_context_add_event(ctx, e);
+ e->queue = queue;
+
+ list_init(&e->callbacks);
+ list_init(&e->enqueue_node);
+
+ assert(type >= CL_COMMAND_NDRANGE_KERNEL && type <= CL_COMMAND_FILL_IMAGE);
+ e->event_type = type;
+ if (type == CL_COMMAND_USER) {
+ e->status = CL_SUBMITTED;
+ } else {
+ e->status = CL_QUEUED;
}
- else {
- event->status = CL_QUEUED;
- if(cl_event_is_gpu_command_type(event->type))
- event->gpgpu_event = cl_gpgpu_event_new(gpgpu);
+
+ if (type == CL_COMMAND_USER) {
+ assert(queue == NULL);
}
- cl_event_add_ref(event); //dec when complete
- event->user_cb = NULL;
- event->enqueue_cb = NULL;
- event->waits_head = NULL;
- event->emplict = emplict;
-
-exit:
- return event;
-error:
- cl_event_delete(event);
- event = NULL;
- goto exit;
+
+ e->depend_events = event_list;
+ e->depend_event_num = num_events;
+ return e;
}
-void cl_event_delete(cl_event event)
+LOCAL void
+cl_event_delete(cl_event event)
{
+ int i;
+ cl_event_user_callback cb;
+
if (UNLIKELY(event == NULL))
return;
- cl_event_update_status(event, 0);
-
if (CL_OBJECT_DEC_REF(event) > 1)
return;
- /* 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
+ cl_enqueue_delete(&event->exec_data);
- /* delete gpgpu event object */
- if(event->gpgpu_event)
- cl_gpgpu_event_delete(event->gpgpu_event);
+ assert(list_empty(&event->enqueue_node));
- /* Remove it from the list */
- cl_context_remove_event(event->ctx, event);
+ if (event->depend_events) {
+ assert(event->depend_event_num);
+ for (i = 0; i < event->depend_event_num; i++) {
+ cl_event_delete(event->depend_events[i]);
+ }
+ cl_free(event->depend_events);
+ }
- if (event->gpgpu) {
- fprintf(stderr, "Warning: a event is deleted with a pending enqueued task.\n");
- cl_gpgpu_delete(event->gpgpu);
- event->gpgpu = NULL;
+ /* Free all the callbacks. Last ref, no need to lock. */
+ while (!list_empty(&event->callbacks)) {
+ cb = list_entry(event->callbacks.next, _cl_event_user_callback, node);
+ list_del(&cb->node);
+ cl_free(cb);
}
+ /* Remove it from the list */
+ assert(event->ctx);
+ cl_context_remove_event(event->ctx, event);
+
CL_OBJECT_DESTROY_BASE(event);
cl_free(event);
}
-void cl_event_add_ref(cl_event event)
+LOCAL cl_event
+cl_event_create(cl_context ctx, cl_command_queue queue, cl_uint num_events,
+ const cl_event *event_list, cl_command_type type, cl_int *errcode_ret)
{
- assert(event);
- CL_OBJECT_INC_REF(event);
-}
+ cl_event e = NULL;
+ cl_event *depend_events = NULL;
+ cl_int err = CL_SUCCESS;
+ cl_uint total_events = 0;
+ int i;
-cl_int cl_event_set_callback(cl_event event ,
- cl_int command_exec_callback_type,
- EVENT_NOTIFY pfn_notify,
- void* user_data)
-{
- assert(event);
- assert(pfn_notify);
+ assert(ctx);
- cl_int err = CL_SUCCESS;
- user_callback *cb;
- TRY_ALLOC(cb, CALLOC(user_callback));
-
- cb->pfn_notify = pfn_notify;
- cb->user_data = user_data;
- cb->status = command_exec_callback_type;
- cb->executed = CL_FALSE;
-
-
- // It is possible that the event enqueued is already completed.
- // clEnqueueReadBuffer can be synchronous and when the callback
- // is registered after, it still needs to get executed.
- CL_OBJECT_LOCK(event); // Thread safety required: operations on the event->status can be made from many different threads
- if(event->status <= command_exec_callback_type) {
- /* Call user callback */
- CL_OBJECT_UNLOCK(event); // pfn_notify can call clFunctions that use the event_lock and from here it's not required
- cb->pfn_notify(event, event->status, cb->user_data);
- cl_free(cb);
- } else {
- // Enqueue to callback list
- cb->next = event->user_cb;
- event->user_cb = cb;
- CL_OBJECT_UNLOCK(event);
- }
+ do {
+ if (event_list)
+ assert(num_events);
-exit:
- return err;
-error:
- err = CL_OUT_OF_HOST_MEMORY;
- cl_free(cb);
- goto exit;
-};
-
-cl_int cl_event_check_waitlist(cl_uint num_events_in_wait_list,
- const cl_event *event_wait_list,
- cl_event *event,cl_context ctx)
-{
- cl_int err = CL_SUCCESS;
- cl_int i;
- /* check the event_wait_list and num_events_in_wait_list */
- if((event_wait_list == NULL) &&
- (num_events_in_wait_list > 0))
- goto error;
-
- if ((event_wait_list != NULL) &&
- (num_events_in_wait_list == 0)){
- goto error;
- }
+ if (queue == NULL) {
+ assert(type == CL_COMMAND_USER);
+ assert(event_list == NULL);
+ assert(num_events == 0);
- /* check the event and context */
- for(i=0; i<num_events_in_wait_list; i++) {
- CHECK_EVENT(event_wait_list[i]);
- if(event_wait_list[i]->status < CL_COMPLETE) {
- err = CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST;
- goto exit;
- }
- if(event && event == &event_wait_list[i])
- goto error;
- if(event_wait_list[i]->ctx != ctx) {
- err = CL_INVALID_CONTEXT;
- goto exit;
- }
- }
+ e = cl_event_new(ctx, queue, type, 0, NULL);
+ if (e == NULL) {
+ err = CL_OUT_OF_HOST_MEMORY;
+ break;
+ }
+ } else {
+ CL_OBJECT_LOCK(queue);
+ total_events = queue->barrier_events_num + num_events;
+
+ if (total_events) {
+ depend_events = cl_calloc(total_events, sizeof(cl_event));
+ if (depend_events == NULL) {
+ CL_OBJECT_UNLOCK(queue);
+ err = CL_OUT_OF_HOST_MEMORY;
+ break;
+ }
+ }
-exit:
- return err;
-error:
- err = CL_INVALID_EVENT_WAIT_LIST; //reset error
- goto exit;
-}
+ /* Add all the barrier events as depend events. */
+ for (i = 0; i < queue->barrier_events_num; i++) {
+ assert(CL_EVENT_IS_BARRIER(queue->barrier_events[i]));
+ cl_event_add_ref(queue->barrier_events[i]);
+ depend_events[num_events + i] = queue->barrier_events[i];
+ }
-cl_int cl_event_wait_events(cl_uint num_events_in_wait_list, const cl_event *event_wait_list,
- cl_command_queue queue)
-{
- cl_int i;
+ CL_OBJECT_UNLOCK(queue);
- /* Check whether wait user events */
- for(i=0; i<num_events_in_wait_list; i++) {
- if(event_wait_list[i]->status <= CL_COMPLETE)
- continue;
+ for (i = 0; i < num_events; i++) {
+ assert(event_list[i]);
+ assert(event_list[i]->ctx == ctx);
+ assert(CL_OBJECT_IS_EVENT(event_list[i]));
+ cl_event_add_ref(event_list[i]);
+ depend_events[i] = event_list[i];
+ }
- /* Need wait on user event, return and do enqueue defer */
- if((event_wait_list[i]->type == CL_COMMAND_USER) ||
- (event_wait_list[i]->enqueue_cb &&
- (event_wait_list[i]->enqueue_cb->wait_user_events != NULL))){
- return CL_ENQUEUE_EXECUTE_DEFER;
- }
- }
+ if (depend_events)
+ assert(total_events);
- if(queue && queue->barrier_events_num )
- return CL_ENQUEUE_EXECUTE_DEFER;
+ e = cl_event_new(ctx, queue, type, total_events, depend_events);
+ if (e == NULL) {
+ err = CL_OUT_OF_HOST_MEMORY;
+ break;
+ }
+ depend_events = NULL;
+ }
+ } while (0);
- /* Non user events or all user event finished, wait all enqueue events finish */
- for(i=0; i<num_events_in_wait_list; i++) {
- if(event_wait_list[i]->status <= CL_COMPLETE)
- continue;
+ if (err != CL_SUCCESS) {
+ if (depend_events) {
+ for (i = 0; i < total_events; i++) {
+ cl_event_delete(depend_events[i]);
+ }
+ cl_free(depend_events);
+ }
- //enqueue callback haven't finish, in another thread, wait
- if(event_wait_list[i]->enqueue_cb != NULL)
- return CL_ENQUEUE_EXECUTE_DEFER;
- if(event_wait_list[i]->gpgpu_event)
- cl_gpgpu_event_update_status(event_wait_list[i]->gpgpu_event, 1);
- cl_event_set_status(event_wait_list[i], CL_COMPLETE); //Execute user's callback
+ // if set depend_events, must succeed.
+ assert(e->depend_events == NULL);
+ cl_event_delete(e);
}
- return CL_ENQUEUE_EXECUTE_IMM;
+
+ if (errcode_ret)
+ *errcode_ret = err;
+
+ return e;
}
-void cl_event_new_enqueue_callback(cl_event event,
- enqueue_data *data,
- cl_uint num_events_in_wait_list,
- const cl_event *event_wait_list)
+LOCAL cl_int
+cl_event_set_callback(cl_event event, cl_int exec_type, cl_event_notify_cb pfn_notify, void *user_data)
{
- enqueue_callback *cb, *node;
- user_event *user_events, *u_ev;
- cl_command_queue queue = event ? event->queue : NULL;
- cl_int i;
cl_int err = CL_SUCCESS;
+ cl_event_user_callback cb;
+ cl_bool exec_imm = CL_FALSE;
- /* Allocate and initialize the structure itself */
- TRY_ALLOC_NO_ERR (cb, CALLOC(enqueue_callback));
- cb->num_events = 0;
- TRY_ALLOC_NO_ERR (cb->wait_list, CALLOC_ARRAY(cl_event, num_events_in_wait_list));
- for(i=0; i<num_events_in_wait_list; i++) {
- //user event will insert to cb->wait_user_events, need not in wait list, avoid ref twice
- if(event_wait_list[i]->type != CL_COMMAND_USER) {
- cb->wait_list[cb->num_events++] = event_wait_list[i];
- cl_event_add_ref(event_wait_list[i]); //add defer enqueue's wait event reference
- }
- }
- cb->event = event;
- cb->next = NULL;
- cb->wait_user_events = NULL;
-
- if(queue && queue->barrier_events_num > 0) {
- for(i=0; i<queue->barrier_events_num; i++) {
- /* Insert the enqueue_callback to user event list */
- node = queue->wait_events[i]->waits_head;
- if(node == NULL)
- queue->wait_events[i]->waits_head = cb;
- else{
- while((node != cb) && node->next)
- node = node->next;
- if(node == cb) //wait on dup user event
- continue;
- node->next = cb;
- }
+ assert(event);
+ assert(pfn_notify);
- /* Insert the user event to enqueue_callback's wait_user_events */
- TRY(cl_event_insert_user_event, &cb->wait_user_events, queue->wait_events[i]);
- cl_event_add_ref(queue->wait_events[i]);
+ do {
+ cb = cl_calloc(1, sizeof(_cl_event_user_callback));
+ if (cb == NULL) {
+ err = CL_OUT_OF_HOST_MEMORY;
+ break;
}
- }
- /* Find out all user events that in event_wait_list wait */
- for(i=0; i<num_events_in_wait_list; i++) {
- if(event_wait_list[i]->status <= CL_COMPLETE)
- continue;
-
- if(event_wait_list[i]->type == CL_COMMAND_USER) {
- /* Insert the enqueue_callback to user event list */
- node = event_wait_list[i]->waits_head;
- if(node == NULL)
- event_wait_list[i]->waits_head = cb;
- else {
- while((node != cb) && node->next)
- node = node->next;
- if(node == cb) //wait on dup user event
- continue;
- node->next = cb;
- }
- /* Insert the user event to enqueue_callback's wait_user_events */
- TRY(cl_event_insert_user_event, &cb->wait_user_events, event_wait_list[i]);
- cl_event_add_ref(event_wait_list[i]);
- if(queue)
- cl_command_queue_insert_event(queue, event_wait_list[i]);
- if(queue && data->type == EnqueueBarrier){
- cl_command_queue_insert_barrier_event(queue, event_wait_list[i]);
- }
- } else if(event_wait_list[i]->enqueue_cb != NULL) {
- user_events = event_wait_list[i]->enqueue_cb->wait_user_events;
- while(user_events != NULL) {
- /* Insert the enqueue_callback to user event's waits_tail */
- node = user_events->event->waits_head;
- if(node == NULL)
- event_wait_list[i]->waits_head = cb;
- else{
- while((node != cb) && node->next)
- node = node->next;
- if(node == cb) { //wait on dup user event
- user_events = user_events->next;
- continue;
- }
- node->next = cb;
- }
-
- /* Insert the user event to enqueue_callback's wait_user_events */
- TRY(cl_event_insert_user_event, &cb->wait_user_events, user_events->event);
- cl_event_add_ref(user_events->event);
- if(queue)
- cl_command_queue_insert_event(event->queue, user_events->event);
- if(queue && data->type == EnqueueBarrier){
- cl_command_queue_insert_barrier_event(event->queue, user_events->event);
- }
- user_events = user_events->next;
- }
- }
- }
- if(event != NULL && event->queue != NULL && event->gpgpu_event != NULL) {
- event->gpgpu = cl_thread_gpgpu_take(event->queue);
- data->ptr = (void *)event->gpgpu_event;
- }
- cb->data = *data;
- if(event)
- event->enqueue_cb = cb;
-
-exit:
- return;
-error:
- if(cb) {
- while(cb->wait_user_events) {
- u_ev = cb->wait_user_events;
- cb->wait_user_events = cb->wait_user_events->next;
- cl_event_delete(u_ev->event);
- cl_free(u_ev);
+ list_init(&cb->node);
+ cb->pfn_notify = pfn_notify;
+ cb->user_data = user_data;
+ cb->status = exec_type;
+ cb->executed = CL_FALSE;
+
+ CL_OBJECT_LOCK(event);
+ if (event->status > exec_type) {
+ list_add_tail(&cb->node, &event->callbacks);
+ cb = NULL;
+ } else {
+ /* The state has already OK, call it immediately. */
+ exec_imm = CL_TRUE;
}
- for(i=0; i<cb->num_events; i++) {
- if(cb->wait_list[i]) {
- cl_event_delete(cb->wait_list[i]);
- }
- }
- cl_free(cb);
- }
- goto exit;
-}
+ CL_OBJECT_UNLOCK(event);
-void cl_event_call_callback(cl_event event, cl_int status, cl_bool free_cb) {
- user_callback *user_cb = NULL;
- user_callback *queue_cb = NULL; // For thread safety, we create a queue that holds user_callback's pfn_notify contents
- user_callback *temp_cb = NULL;
- user_cb = event->user_cb;
- CL_OBJECT_LOCK(event);
- while(user_cb) {
- if(user_cb->status >= status
- && user_cb->executed == CL_FALSE) { // Added check to not execute a callback when it was already handled
- user_cb->executed = CL_TRUE;
- temp_cb = cl_malloc(sizeof(user_callback));
- if(!temp_cb) {
- break; // Out of memory
- }
- temp_cb->pfn_notify = user_cb->pfn_notify; // Minor struct copy to call ppfn_notify out of the pthread_mutex
- temp_cb->user_data = user_cb->user_data;
- if(free_cb) {
- cl_free(user_cb);
- }
- if(!queue_cb) {
- queue_cb = temp_cb;
- queue_cb->next = NULL;
- } else { // Enqueue First
- temp_cb->next = queue_cb;
- queue_cb = temp_cb;
- }
+ if (exec_imm) {
+ cb->pfn_notify(event, event->status, cb->user_data);
}
- user_cb = user_cb->next;
- }
- CL_OBJECT_UNLOCK(event);
- // Calling the callbacks outside of the event_lock is required because the callback can call cl_api functions and get deadlocked
- while(queue_cb) { // For each callback queued, actually execute the callback
- queue_cb->pfn_notify(event, event->status, queue_cb->user_data);
- temp_cb = queue_cb;
- queue_cb = queue_cb->next;
- cl_free(temp_cb);
- }
+ } while (0);
+
+ if (cb)
+ cl_free(cb);
+
+ return err;
}
-void cl_event_set_status(cl_event event, cl_int status)
+LOCAL cl_int
+cl_event_set_status(cl_event event, cl_int status)
{
- cl_int ret, i;
- cl_event evt;
+ list_head tmp_callbacks;
+ list_head *n;
+ list_head *pos;
+ cl_bool notify_queue = CL_FALSE;
+ cl_event_user_callback cb;
+
+ assert(event);
CL_OBJECT_LOCK(event);
- if(status >= event->status) {
+ if (event->status <= CL_COMPLETE) { // Already set to error or completed
CL_OBJECT_UNLOCK(event);
- return;
+ return CL_INVALID_OPERATION;
}
- if(event->status <= CL_COMPLETE) {
- event->status = status; //have done enqueue before or doing in another thread
- CL_OBJECT_UNLOCK(event);
- return;
+
+ if (CL_EVENT_IS_USER(event)) {
+ assert(event->status != CL_RUNNING && event->status != CL_QUEUED);
+ } else {
+ assert(event->queue); // Must belong to some queue.
}
- if(status <= CL_COMPLETE) {
- if(event->enqueue_cb) {
- if(status == CL_COMPLETE) {
- cl_enqueue_handle(event, &event->enqueue_cb->data);
- if(event->gpgpu_event)
- cl_gpgpu_event_update_status(event->gpgpu_event, 1); //now set complet, need refine
- } else {
- if(event->gpgpu_event) {
- // Error then cancel the enqueued event.
- cl_gpgpu_delete(event->gpgpu);
- event->gpgpu = NULL;
- }
- }
+ if (status >= event->status) { // Should never go back.
+ CL_OBJECT_UNLOCK(event);
+ return CL_INVALID_OPERATION;
+ }
- event->status = status; //Change the event status after enqueue and befor unlock
+ event->status = status;
+ /* Call all the callbacks. */
+ if (!list_empty(&event->callbacks)) {
+ do {
+ status = event->status;
+ list_init(&tmp_callbacks);
+ list_replace(&event->callbacks, &tmp_callbacks);
+ list_init(&event->callbacks);
+ /* Call all the callbacks without lock. */
CL_OBJECT_UNLOCK(event);
- for(i=0; i<event->enqueue_cb->num_events; i++)
- cl_event_delete(event->enqueue_cb->wait_list[i]);
+
+ list_for_each_safe(pos, n, &tmp_callbacks)
+ {
+ cb = list_entry(pos, _cl_event_user_callback, node);
+
+ assert(cb->executed == CL_FALSE);
+
+ if (cb->status < status)
+ continue;
+
+ list_del(&cb->node);
+ cb->executed = CL_TRUE;
+ cb->pfn_notify(event, status, cb->user_data);
+ cl_free(cb);
+ }
+
CL_OBJECT_LOCK(event);
- if(event->enqueue_cb->wait_list)
- cl_free(event->enqueue_cb->wait_list);
- cl_free(event->enqueue_cb);
- event->enqueue_cb = NULL;
- }
+ // Set back the uncalled callbacks.
+ list_splice_tail(&tmp_callbacks, &event->callbacks);
+
+ /* Status may changed because we unlock. need to check again. */
+ } while (status != event->status);
}
- if(event->status >= status) //maybe changed in other threads
- event->status = status;
+
+ /* Wakeup all the waiter for status change. */
+ CL_OBJECT_NOTIFY_COND(event);
+
+ if (event->status <= CL_COMPLETE) {
+ notify_queue = CL_TRUE;
+ }
+
CL_OBJECT_UNLOCK(event);
- /* Call user callback */
- cl_event_call_callback(event, status, CL_FALSE);
+ /* Need to notify all the command queue within the same context. */
+ if (notify_queue) {
+ cl_command_queue *q_list = NULL;
+ cl_uint queue_num = 0;
+ int i = 0;
+ int cookie = 0;
+
+ /*First, we need to remove it from queue's barrier list. */
+ if (CL_EVENT_IS_BARRIER(event)) {
+ assert(event->queue);
+ cl_command_queue_remove_barrier_event(event->queue, event);
+ }
- if(event->type == CL_COMMAND_USER) {
- /* Check all defer enqueue */
- enqueue_callback *cb, *enqueue_cb = event->waits_head;
- while(enqueue_cb) {
- /* Remove this user event in enqueue_cb, update the header if needed. */
- cl_event_remove_user_event(&enqueue_cb->wait_user_events, event);
- cl_event_delete(event);
+ /* Then, notify all the queues within the same context. */
+ CL_OBJECT_LOCK(event->ctx);
+ do {
+ queue_num = event->ctx->queue_num;
+ cookie = event->ctx->queue_cookie;
+
+ if (queue_num > 0) {
+ q_list = cl_calloc(queue_num, sizeof(cl_command_queue));
+ assert(q_list);
+ i = 0;
+ list_for_each(pos, &event->ctx->queues)
+ {
+ q_list[i] = (cl_command_queue)(list_entry(pos, _cl_base_object, node));
+ assert(i < queue_num);
+ i++;
+ }
- /* Still wait on other user events */
- if(enqueue_cb->wait_user_events != NULL) {
- enqueue_cb = enqueue_cb->next;
- continue;
- }
+ CL_OBJECT_UNLOCK(event->ctx); // Update status without context lock.
- //remove user event frome enqueue_cb's ctx
- cl_command_queue_remove_event(enqueue_cb->event->queue, event);
- cl_command_queue_remove_barrier_event(enqueue_cb->event->queue, event);
-
- /* All user events complete, now wait enqueue events */
- ret = cl_event_wait_events(enqueue_cb->num_events, enqueue_cb->wait_list,
- enqueue_cb->event->queue);
- assert(ret != CL_ENQUEUE_EXECUTE_DEFER);
- ret = ~ret;
- cb = enqueue_cb;
- enqueue_cb = enqueue_cb->next;
-
- /* Call the pending operation */
- evt = cb->event;
- /* TODO: if this event wait on several events, one event's
- status is error, the others is complete, what's the status
- of this event? Can't find the description in OpenCL spec.
- Simply update to latest finish wait event.*/
- cl_event_set_status(cb->event, status);
- if(evt->emplict == CL_FALSE) {
- cl_event_delete(evt);
+ for (i = 0; i < queue_num; i++) {
+ cl_command_queue_notify(q_list[i]);
+ }
+
+ CL_OBJECT_LOCK(event->ctx); // Lock again.
+ } else {
+ /* No queue? Just do nothing. */
}
- }
- event->waits_head = NULL;
- }
- 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);
+ } while (cookie != event->ctx->queue_cookie); // Some queue may be added when we unlock.
+ CL_OBJECT_UNLOCK(event->ctx);
+
+ if (q_list)
+ cl_free(q_list);
}
+
+ return CL_SUCCESS;
}
-void cl_event_update_status(cl_event event, int wait)
+LOCAL cl_int
+cl_event_wait_for_event_ready(const cl_event event)
{
- if(event->status <= CL_COMPLETE)
- return;
- if((event->gpgpu_event) &&
- (cl_gpgpu_event_update_status(event->gpgpu_event, wait) == command_complete))
- cl_event_set_status(event, CL_COMPLETE);
+ assert(CL_OBJECT_IS_EVENT(event));
+ return cl_event_wait_for_events_list(event->depend_event_num, event->depend_events);
}
-cl_int cl_event_marker_with_wait_list(cl_command_queue queue,
- cl_uint num_events_in_wait_list,
- const cl_event *event_wait_list,
- cl_event* event)
+LOCAL cl_int
+cl_event_wait_for_events_list(cl_uint num_events, const cl_event *event_list)
{
- enqueue_data data = { 0 };
+ int i;
cl_event e;
+ cl_int ret = CL_SUCCESS;
- e = cl_event_new(queue->ctx, queue, CL_COMMAND_MARKER, CL_TRUE);
- if(e == NULL)
- return CL_OUT_OF_HOST_MEMORY;
-
- if(event != NULL ){
- *event = e;
- }
+ for (i = 0; i < num_events; i++) {
+ e = event_list[i];
+ assert(e);
+ assert(CL_OBJECT_IS_EVENT(e));
-//enqueues a marker command which waits for either a list of events to complete, or if the list is
-//empty it waits for all commands previously enqueued in command_queue to complete before it completes.
- if(num_events_in_wait_list > 0){
- if(cl_event_wait_events(num_events_in_wait_list, event_wait_list, queue) == CL_ENQUEUE_EXECUTE_DEFER) {
- data.type = EnqueueMarker;
- cl_event_new_enqueue_callback(event?*event:NULL, &data, num_events_in_wait_list, event_wait_list);
- return CL_SUCCESS;
+ CL_OBJECT_LOCK(e);
+ while (e->status > CL_COMPLETE) {
+ CL_OBJECT_WAIT_ON_COND(e);
}
- } else if(queue->wait_events_num > 0) {
- data.type = EnqueueMarker;
- cl_event_new_enqueue_callback(event?*event:NULL, &data, queue->wait_events_num, queue->wait_events);
- return CL_SUCCESS;
+ /* Iff some error happened, return the error. */
+ if (e->status < CL_COMPLETE) {
+ ret = CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST;
+ }
+ CL_OBJECT_UNLOCK(e);
}
- cl_event_update_last_events(queue,1);
-
- cl_event_set_status(e, CL_COMPLETE);
- return CL_SUCCESS;
+ return ret;
}
-cl_int cl_event_barrier_with_wait_list(cl_command_queue queue,
- cl_uint num_events_in_wait_list,
- const cl_event *event_wait_list,
- cl_event* event)
+LOCAL cl_int
+cl_event_check_waitlist(cl_uint num_events_in_wait_list, const cl_event *event_wait_list,
+ cl_event *event, cl_context ctx)
{
- enqueue_data data = { 0 };
- cl_event e;
-
- e = cl_event_new(queue->ctx, queue, CL_COMMAND_BARRIER, CL_TRUE);
- if(e == NULL)
- return CL_OUT_OF_HOST_MEMORY;
+ cl_int err = CL_SUCCESS;
+ cl_int i;
- if(event != NULL ){
- *event = e;
- }
-//enqueues a barrier command which waits for either a list of events to complete, or if the list is
-//empty it waits for all commands previously enqueued in command_queue to complete before it completes.
- if(num_events_in_wait_list > 0){
- if(cl_event_wait_events(num_events_in_wait_list, event_wait_list, queue) == CL_ENQUEUE_EXECUTE_DEFER) {
- data.type = EnqueueBarrier;
- cl_event_new_enqueue_callback(e, &data, num_events_in_wait_list, event_wait_list);
- return CL_SUCCESS;
+ do {
+ /* check the event_wait_list and num_events_in_wait_list */
+ if ((event_wait_list == NULL) && (num_events_in_wait_list > 0)) {
+ err = CL_INVALID_EVENT_WAIT_LIST;
+ break;
}
- } else if(queue->wait_events_num > 0) {
- data.type = EnqueueBarrier;
- cl_event_new_enqueue_callback(e, &data, queue->wait_events_num, queue->wait_events);
- return CL_SUCCESS;
- }
- cl_event_update_last_events(queue,1);
+ if ((event_wait_list != NULL) && (num_events_in_wait_list == 0)) {
+ err = CL_INVALID_EVENT_WAIT_LIST;
+ break;
+ }
- cl_event_set_status(e, CL_COMPLETE);
- return CL_SUCCESS;
-}
+ /* check the event and context */
+ for (i = 0; i < num_events_in_wait_list; i++) {
+ if (event_wait_list[i] == NULL || !CL_OBJECT_IS_EVENT(event_wait_list[i])) {
+ err = CL_INVALID_EVENT;
+ break;
+ }
-cl_ulong cl_event_get_cpu_timestamp(cl_ulong *cpu_time)
-{
- struct timespec ts;
+ if (cl_event_get_status(event_wait_list[i]) < CL_COMPLETE) {
+ err = CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST;
+ break;
+ }
- if(clock_gettime(CLOCK_MONOTONIC_RAW,&ts) != 0){
- printf("CPU Timmer error\n");
- return CL_FALSE;
- }
- *cpu_time = (1000000000.0) * (cl_ulong) ts.tv_sec + (cl_ulong) ts.tv_nsec;
+ if (event == event_wait_list + i) { /* Pointer of element of the wait list */
+ err = CL_INVALID_EVENT_WAIT_LIST;
+ break;
+ }
- return CL_SUCCESS;
-}
+ /* check all belong to same context. */
+ if (ctx == NULL) {
+ ctx = event_wait_list[i]->ctx;
+ }
+ if (event_wait_list[i]->ctx != ctx) {
+ err = CL_INVALID_CONTEXT;
+ break;
+ }
+ }
-cl_int cl_event_get_queued_cpu_timestamp(cl_event event)
-{
- cl_int ret_val;
+ if (err != CL_SUCCESS)
+ break;
- ret_val = cl_event_get_cpu_timestamp(&event->queued_timestamp);
+ } while (0);
- return ret_val;
+ return err;
}
-cl_ulong cl_event_get_timestamp_delta(cl_ulong start_timestamp,cl_ulong end_timestamp)
+LOCAL void
+cl_event_exec(cl_event event, cl_int exec_status)
{
- cl_ulong ret_val;
+ /* We are MT safe here, no one should call this
+ at the same time. No need to lock */
+ cl_int ret = CL_SUCCESS;
+ cl_int status = cl_event_get_status(event);
+ cl_int depend_status;
- if(end_timestamp > start_timestamp){
- ret_val = end_timestamp - start_timestamp;
- }
- else {
- /*if start time stamp is greater than end timstamp then set ret value to max*/
- ret_val = ((cl_ulong) 1 << 32);
+ if (status < CL_COMPLETE || status <= exec_status) {
+ return;
}
- return ret_val;
-}
-
-cl_ulong cl_event_get_start_timestamp(cl_event event)
-{
- cl_ulong ret_val;
+ depend_status = cl_event_is_ready(event);
+ assert(depend_status <= CL_COMPLETE);
+ if (depend_status < CL_COMPLETE) { // Error happend, cancel exec.
+ ret = cl_event_set_status(event, depend_status);
+ return;
+ }
- ret_val = cl_event_get_timestamp_delta(event->timestamp[0],event->timestamp[2]);
+ /* Do the according thing based on event type. */
+ ret = cl_enqueue_handle(&event->exec_data, exec_status);
- return ret_val;
+ if (ret != CL_SUCCESS) {
+ assert(ret < 0);
+ DEBUGP(DL_WARNING, "Exec event %p error, type is %d, error staus is %d",
+ event, event->event_type, ret);
+ ret = cl_event_set_status(event, ret);
+ assert(ret == CL_SUCCESS);
+ } else {
+ ret = cl_event_set_status(event, exec_status);
+ assert(ret == CL_SUCCESS);
+ }
}
-cl_ulong cl_event_get_end_timestamp(cl_event event)
+/* 0 means ready, >0 means not ready, <0 means error. */
+LOCAL cl_int
+cl_event_is_ready(cl_event event)
{
- cl_ulong ret_val;
-
- ret_val = cl_event_get_timestamp_delta(event->timestamp[0],event->timestamp[3]);
+ int i;
+ int status;
- return ret_val;
-}
+ for (i = 0; i < event->depend_event_num; i++) {
+ status = cl_event_get_status(event->depend_events[i]);
-cl_int cl_event_get_timestamp(cl_event event, cl_profiling_info param_name)
-{
- cl_ulong ret_val = 0;
- GET_QUEUE_THREAD_GPGPU(event->queue);
-
- if (!event->gpgpu_event) {
- cl_gpgpu_event_get_gpu_cur_timestamp(gpgpu, &ret_val);
- event->timestamp[param_name - CL_PROFILING_COMMAND_QUEUED] = ret_val;
- return CL_SUCCESS;
+ if (status != CL_COMPLETE) {
+ return status;
+ }
}
- if(param_name == CL_PROFILING_COMMAND_SUBMIT ||
- param_name == CL_PROFILING_COMMAND_QUEUED) {
- cl_gpgpu_event_get_gpu_cur_timestamp(gpgpu, &ret_val);
- event->timestamp[param_name - CL_PROFILING_COMMAND_QUEUED] = ret_val;
- return CL_SUCCESS;
- } else if(param_name == CL_PROFILING_COMMAND_START) {
- cl_gpgpu_event_get_exec_timestamp(gpgpu, event->gpgpu_event, 0, &ret_val);
- event->timestamp[param_name - CL_PROFILING_COMMAND_QUEUED] = ret_val;
- return CL_SUCCESS;
- } else if (param_name == CL_PROFILING_COMMAND_END) {
- cl_gpgpu_event_get_exec_timestamp(gpgpu, event->gpgpu_event, 1, &ret_val);
- event->timestamp[param_name - CL_PROFILING_COMMAND_QUEUED] = ret_val;
- return CL_SUCCESS;
- }
- return CL_INVALID_VALUE;
+ return CL_COMPLETE;
}
-cl_int cl_event_insert_user_event(user_event** p_u_ev, cl_event event)
+LOCAL cl_event
+cl_event_create_marker_or_barrier(cl_command_queue queue, cl_uint num_events_in_wait_list,
+ const cl_event *event_wait_list, cl_bool is_barrier, cl_int *error)
{
- user_event * u_iter = *p_u_ev;
- user_event * u_ev;
-
- while(u_iter)
- {
- if(u_iter->event == event)
- return CL_SUCCESS;
- u_iter = u_iter->next;
- }
+ cl_event e = NULL;
+ cl_int err = CL_SUCCESS;
+ cl_command_type type = CL_COMMAND_MARKER;
+ enqueue_type eq_type = EnqueueMarker;
- TRY_ALLOC_NO_ERR (u_ev, CALLOC(user_event));
- u_ev->event = event;
- u_ev->next = *p_u_ev;
- *p_u_ev = u_ev;
+ if (is_barrier) {
+ type = CL_COMMAND_BARRIER;
+ eq_type = EnqueueBarrier;
+ }
+ if (event_wait_list) {
+ assert(num_events_in_wait_list > 0);
- return CL_SUCCESS;
-error:
- return CL_FALSE;
-}
+ e = cl_event_create(queue->ctx, queue, num_events_in_wait_list,
+ event_wait_list, type, &err);
+ if (err != CL_SUCCESS) {
+ *error = err;
+ return NULL;
+ }
+ } else { /* The marker depends on all events in the queue now. */
+ cl_command_queue_enqueue_worker worker = &queue->worker;
+ cl_uint i;
+ cl_uint event_num;
+ cl_event *depend_events;
+
+ CL_OBJECT_LOCK(queue);
+
+ /* First, wait for the command queue retire all in executing event. */
+ while (1) {
+ if (worker->quit) { // already destroy the queue?
+ CL_OBJECT_UNLOCK(queue);
+ *error = CL_INVALID_COMMAND_QUEUE;
+ return NULL;
+ }
-cl_int cl_event_remove_user_event(user_event** p_u_ev, cl_event event)
-{
- user_event * u_iter = *p_u_ev;
- user_event * u_prev = *p_u_ev;
-
- while(u_iter){
- if(u_iter->event == event ){
- if(u_iter == *p_u_ev){
- *p_u_ev = u_iter->next;
- }else{
- u_prev->next = u_iter->next;
+ if (worker->in_exec_status != CL_COMPLETE) {
+ CL_OBJECT_WAIT_ON_COND(queue);
+ continue;
}
- cl_free(u_iter);
+
break;
}
- u_prev = u_iter;
- u_iter = u_iter->next;
+
+ event_num = 0;
+ depend_events = NULL;
+ if (!list_empty(&worker->enqueued_events)) {
+ depend_events = cl_command_queue_record_in_queue_events(queue, &event_num);
+ }
+
+ CL_OBJECT_UNLOCK(queue);
+
+ e = cl_event_create(queue->ctx, queue, event_num, depend_events, type, &err);
+
+ for (i = 0; i < event_num; i++) { //unref the temp
+ cl_event_delete(depend_events[i]);
+ }
+ if (depend_events)
+ cl_free(depend_events);
+
+ if (err != CL_SUCCESS) {
+ *error = err;
+ return NULL;
+ }
}
- return CL_SUCCESS;
+ e->exec_data.type = eq_type;
+ *error = CL_SUCCESS;
+ return e;
}
diff --git a/src/cl_event.h b/src/cl_event.h
index 85cd53e..f67299c 100644
--- a/src/cl_event.h
+++ b/src/cl_event.h
@@ -14,111 +14,75 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
- * Author: Benjamin Segovia <benjamin.segovia at intel.com>
*/
-#ifndef __CL_EVENT_H__
-#define __CL_EVENT_H__
+#ifndef __CL_EVENT_H_
+#define __CL_EVENT_H_
#include <semaphore.h>
#include "cl_base_object.h"
-#include "cl_driver.h"
#include "cl_enqueue.h"
#include "CL/cl.h"
-#define CL_ENQUEUE_EXECUTE_IMM 0
-#define CL_ENQUEUE_EXECUTE_DEFER 1
+typedef void(CL_CALLBACK *cl_event_notify_cb)(cl_event event, cl_int event_command_exec_status, void *user_data);
-typedef struct _user_event {
- cl_event event; /* The user event */
- struct _user_event* next; /* Next user event in list */
-} user_event;
+typedef struct _cl_event_user_callback {
+ cl_int status; /* The execution status */
+ cl_bool executed; /* Indicat the callback function been called or not */
+ cl_event_notify_cb pfn_notify; /* Callback function */
+ void *user_data; /* Callback user data */
+ list_head node; /* Event callback list node */
+} _cl_event_user_callback;
-typedef struct _enqueue_callback {
- cl_event event; /* The event relative this enqueue callback */
- enqueue_data data; /* Hold all enqueue callback's infomation */
- cl_uint num_events; /* num events in wait list */
- cl_event* wait_list; /* All event wait list this callback wait on */
- user_event* wait_user_events; /* The head of user event list the callback wait on */
- struct _enqueue_callback* next; /* The next enqueue callback in wait list */
-} enqueue_callback;
+typedef _cl_event_user_callback *cl_event_user_callback;
-typedef void (CL_CALLBACK *EVENT_NOTIFY)(cl_event event, cl_int event_command_exec_status, void *user_data);
-
-typedef struct _user_callback {
- cl_int status; /* The execution status */
- cl_bool executed; /* Indicat the callback function been called or not */
- EVENT_NOTIFY pfn_notify; /* Callback function */
- void* user_data; /* Callback user data */
- struct _user_callback* next; /* Next event callback in list */
-} user_callback;
-
-struct _cl_event {
- _cl_base_object base;
- cl_context ctx; /* The context associated with event */
- cl_command_queue queue; /* The command queue associated with event */
- cl_command_type type; /* The command type associated with event */
- cl_int status; /* The execution status */
- cl_gpgpu gpgpu; /* Current gpgpu, owned by this structure. */
- cl_gpgpu_event gpgpu_event; /* The event object communicate with hardware */
- user_callback* user_cb; /* The event callback functions */
- enqueue_callback* enqueue_cb; /* This event's enqueue */
- enqueue_callback* waits_head; /* The head of enqueues list wait on this 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*/
-};
+typedef struct _cl_event {
+ _cl_base_object base;
+ cl_context ctx; /* The context associated with event */
+ cl_command_queue queue; /* The command queue associated with event */
+ cl_command_type event_type; /* Event type. */
+ cl_bool is_barrier; /* Is this event a barrier */
+ cl_int status; /* The execution status */
+ cl_event *depend_events; /* The events must complete before this. */
+ cl_uint depend_event_num; /* The depend events number. */
+ list_head callbacks; /* The events The event callback functions */
+ list_head enqueue_node; /* The node in the enqueue list. */
+ cl_ulong timestamp[4]; /* The time stamps for profiling. */
+ cl_ulong queued_timestamp;
+ enqueue_data exec_data; /* Context for execute this event. */
+} _cl_event;
#define CL_OBJECT_EVENT_MAGIC 0x8324a9f810ebf90fLL
-#define CL_OBJECT_IS_EVENT(obj) (((cl_base_object)obj)->magic == CL_OBJECT_EVENT_MAGIC)
+#define CL_OBJECT_IS_EVENT(obj) ((obj && \
+ ((cl_base_object)obj)->magic == CL_OBJECT_EVENT_MAGIC && \
+ CL_OBJECT_GET_REF(obj) >= 1))
+
+#define CL_EVENT_IS_MARKER(E) (E->event_type == CL_COMMAND_MARKER)
+#define CL_EVENT_IS_BARRIER(E) (E->event_type == CL_COMMAND_BARRIER)
+#define CL_EVENT_IS_USER(E) (E->event_type == CL_COMMAND_USER)
/* Create a new event object */
-cl_event cl_event_new(cl_context, cl_command_queue, cl_command_type, cl_bool);
-/* Unref the object and delete it if no more reference on it */
-void cl_event_delete(cl_event);
-/* Add one more reference to this object */
-void cl_event_add_ref(cl_event);
-/* Register a user callback function for specific commond execution status */
-cl_int cl_event_set_callback(cl_event, cl_int, EVENT_NOTIFY, void *);
-/* Execute the event's callback if the event's status supersedes the callback's status. Free the callback if specified */
-void cl_event_call_callback(cl_event event, cl_int status, cl_bool free_cb);
-/* Check events wait list for enqueue commonds */
-cl_int cl_event_check_waitlist(cl_uint, const cl_event *, cl_event *, cl_context);
-/* Wait the all events in wait list complete */
-cl_int cl_event_wait_events(cl_uint, const cl_event *, cl_command_queue);
-/* New a enqueue suspend task */
-void cl_event_new_enqueue_callback(cl_event, enqueue_data *, cl_uint, const cl_event *);
-/* Set the event status and call all callbacks */
-void cl_event_set_status(cl_event, cl_int);
-/* Check and update event status */
-void cl_event_update_status(cl_event, cl_int);
-/* Create the marker event */
-cl_int cl_event_marker_with_wait_list(cl_command_queue, cl_uint, const cl_event *, cl_event*);
-/* Create the barrier event */
-cl_int cl_event_barrier_with_wait_list(cl_command_queue, cl_uint, const cl_event *, cl_event*);
-/* Get the cpu time */
-cl_ulong cl_event_get_cpu_timestamp(cl_ulong *cpu_time);
-/*Get the cpu time for queued*/
-cl_int cl_event_get_queued_cpu_timestamp(cl_event event);
-/*get timestamp delate between end and start*/
-cl_ulong cl_event_get_timestamp_delta(cl_ulong start_timestamp,cl_ulong end_timestamp);
-/*Get start time stamp*/
-cl_ulong cl_event_get_start_timestamp(cl_event event);
-/*Get end time stamp*/
-cl_ulong cl_event_get_end_timestamp(cl_event event);
-/* Do the event profiling */
-cl_int cl_event_get_timestamp(cl_event event, cl_profiling_info param_name);
-/* insert the user event */
-cl_int cl_event_insert_user_event(user_event** p_u_ev, cl_event event);
-/* remove the user 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);
+extern cl_event cl_event_create(cl_context ctx, cl_command_queue queue, cl_uint num_events,
+ const cl_event *event_list, cl_command_type type, cl_int *errcode_ret);
+extern cl_int cl_event_check_waitlist(cl_uint num_events_in_wait_list, const cl_event *event_wait_list,
+ cl_event* event, cl_context ctx);
+extern void cl_event_exec(cl_event event, cl_int exec_status);
+/* 0 means ready, >0 means not ready, <0 means error. */
+extern cl_int cl_event_is_ready(cl_event event);
+extern cl_int cl_event_get_status(cl_event event);
+extern void cl_event_add_ref(cl_event event);
+extern void cl_event_delete(cl_event event);
+extern cl_int cl_event_set_status(cl_event event, cl_int status);
+extern cl_int cl_event_set_callback(cl_event event, cl_int exec_type,
+ cl_event_notify_cb pfn_notify, void *user_data);
+extern cl_int cl_event_wait_for_events_list(cl_uint num_events, const cl_event *event_list);
+extern cl_int cl_event_wait_for_event_ready(cl_event event);
+extern cl_ulong cl_event_get_timestamp_delta(cl_ulong start_timestamp, cl_ulong end_timestamp);
+extern cl_ulong cl_event_get_start_timestamp(cl_event event);
+extern cl_ulong cl_event_get_end_timestamp(cl_event event);
+extern cl_int cl_event_get_timestamp(cl_event event, cl_profiling_info param_name);
+extern cl_event cl_event_create_marker_or_barrier(cl_command_queue queue, cl_uint num_events_in_wait_list,
+ const cl_event *event_wait_list, cl_bool is_barrier,
+ cl_int* error);
#endif /* __CL_EVENT_H__ */
-
diff --git a/src/cl_mem.c b/src/cl_mem.c
index 06a4d5a..333ffc9 100644
--- a/src/cl_mem.c
+++ b/src/cl_mem.c
@@ -28,6 +28,7 @@
#include "cl_kernel.h"
#include "cl_command_queue.h"
#include "cl_cmrt.h"
+#include "cl_enqueue.h"
#include "CL/cl.h"
#include "CL/cl_intel.h"
@@ -1264,7 +1265,7 @@ cl_mem_add_ref(cl_mem mem)
#define LOCAL_SZ_2 4
LOCAL cl_int
-cl_mem_copy(cl_command_queue queue, cl_mem src_buf, cl_mem dst_buf,
+cl_mem_copy(cl_command_queue queue, cl_event event, cl_mem src_buf, cl_mem dst_buf,
size_t src_offset, size_t dst_offset, size_t cb)
{
cl_int ret = CL_SUCCESS;
@@ -1317,7 +1318,7 @@ cl_mem_copy(cl_command_queue queue, cl_mem src_buf, cl_mem dst_buf,
cl_kernel_set_arg(ker, 2, sizeof(cl_mem), &dst_buf);
cl_kernel_set_arg(ker, 3, sizeof(int), &dw_dst_offset);
cl_kernel_set_arg(ker, 4, sizeof(int), &cb);
- ret = cl_command_queue_ND_range(queue, ker, 1, global_off, global_sz, local_sz);
+ ret = cl_command_queue_ND_range(queue, ker, event, 1, global_off, global_sz, local_sz);
cl_kernel_delete(ker);
return ret;
}
@@ -1358,7 +1359,7 @@ cl_mem_copy(cl_command_queue queue, cl_mem src_buf, cl_mem dst_buf,
cl_kernel_set_arg(ker, 4, sizeof(int), &dw_num);
cl_kernel_set_arg(ker, 5, sizeof(int), &first_mask);
cl_kernel_set_arg(ker, 6, sizeof(int), &last_mask);
- ret = cl_command_queue_ND_range(queue, ker, 1, global_off, global_sz, local_sz);
+ ret = cl_command_queue_ND_range(queue, ker, event, 1, global_off, global_sz, local_sz);
cl_kernel_delete(ker);
return ret;
}
@@ -1388,7 +1389,7 @@ cl_mem_copy(cl_command_queue queue, cl_mem src_buf, cl_mem dst_buf,
cl_kernel_set_arg(ker, 6, sizeof(int), &last_mask);
cl_kernel_set_arg(ker, 7, sizeof(int), &shift);
cl_kernel_set_arg(ker, 8, sizeof(int), &dw_mask);
- ret = cl_command_queue_ND_range(queue, ker, 1, global_off, global_sz, local_sz);
+ ret = cl_command_queue_ND_range(queue, ker, event, 1, global_off, global_sz, local_sz);
cl_kernel_delete(ker);
return ret;
}
@@ -1420,7 +1421,7 @@ cl_mem_copy(cl_command_queue queue, cl_mem src_buf, cl_mem dst_buf,
cl_kernel_set_arg(ker, 7, sizeof(int), &shift);
cl_kernel_set_arg(ker, 8, sizeof(int), &dw_mask);
cl_kernel_set_arg(ker, 9, sizeof(int), &src_less);
- ret = cl_command_queue_ND_range(queue, ker, 1, global_off, global_sz, local_sz);
+ ret = cl_command_queue_ND_range(queue, ker, event, 1, global_off, global_sz, local_sz);
cl_kernel_delete(ker);
return ret;
}
@@ -1493,13 +1494,13 @@ cl_image_fill(cl_command_queue queue, const void * pattern, struct _cl_mem_image
cl_kernel_set_arg(ker, 6, sizeof(cl_int), &origin[1]);
cl_kernel_set_arg(ker, 7, sizeof(cl_int), &origin[2]);
- ret = cl_command_queue_ND_range(queue, ker, 3, global_off, global_sz, local_sz);
+ ret = cl_command_queue_ND_range(queue, ker, NULL, 3, global_off, global_sz, local_sz);
cl_kernel_delete(ker);
return ret;
}
LOCAL cl_int
-cl_mem_fill(cl_command_queue queue, const void * pattern, size_t pattern_size,
+cl_mem_fill(cl_command_queue queue, cl_event e, const void * pattern, size_t pattern_size,
cl_mem buffer, size_t offset, size_t size)
{
cl_int ret = CL_SUCCESS;
@@ -1596,13 +1597,13 @@ cl_mem_fill(cl_command_queue queue, const void * pattern, size_t pattern_size,
if (is_128)
cl_kernel_set_arg(ker, 4, pattern_size, pattern1);
- ret = cl_command_queue_ND_range(queue, ker, 1, global_off, global_sz, local_sz);
+ ret = cl_command_queue_ND_range(queue, ker, e, 1, global_off, global_sz, local_sz);
cl_kernel_delete(ker);
return ret;
}
LOCAL cl_int
-cl_mem_copy_buffer_rect(cl_command_queue queue, cl_mem src_buf, cl_mem dst_buf,
+cl_mem_copy_buffer_rect(cl_command_queue queue, cl_event event, cl_mem src_buf, cl_mem dst_buf,
const size_t *src_origin, const size_t *dst_origin, const size_t *region,
size_t src_row_pitch, size_t src_slice_pitch,
size_t dst_row_pitch, size_t dst_slice_pitch) {
@@ -1617,7 +1618,7 @@ cl_mem_copy_buffer_rect(cl_command_queue queue, cl_mem src_buf, cl_mem dst_buf,
cl_int src_offset = src_origin[2]*src_slice_pitch + src_origin[1]*src_row_pitch + src_origin[0];
cl_int dst_offset = dst_origin[2]*dst_slice_pitch + dst_origin[1]*dst_row_pitch + dst_origin[0];
cl_int size = region[0]*region[1]*region[2];
- ret = cl_mem_copy(queue, src_buf, dst_buf,src_offset, dst_offset, size);
+ ret = cl_mem_copy(queue, NULL, src_buf, dst_buf,src_offset, dst_offset, size);
return ret;
}
@@ -1669,14 +1670,15 @@ cl_mem_copy_buffer_rect(cl_command_queue queue, cl_mem src_buf, cl_mem dst_buf,
cl_kernel_set_arg(ker, 9, sizeof(cl_int), &dst_row_pitch);
cl_kernel_set_arg(ker, 10, sizeof(cl_int), &dst_slice_pitch);
- ret = cl_command_queue_ND_range(queue, ker, 1, global_off, global_sz, local_sz);
+ ret = cl_command_queue_ND_range(queue, ker, event, 1, global_off, global_sz, local_sz);
cl_kernel_delete(ker);
return ret;
}
LOCAL cl_int
-cl_mem_kernel_copy_image(cl_command_queue queue, struct _cl_mem_image* src_image, struct _cl_mem_image* dst_image,
- const size_t *src_origin, const size_t *dst_origin, const size_t *region) {
+cl_mem_kernel_copy_image(cl_command_queue queue, cl_event event, struct _cl_mem_image* src_image,
+ struct _cl_mem_image* dst_image, const size_t *src_origin,
+ const size_t *dst_origin, const size_t *region) {
cl_int ret;
cl_kernel ker = NULL;
size_t global_off[] = {0,0,0};
@@ -1817,7 +1819,7 @@ cl_mem_kernel_copy_image(cl_command_queue queue, struct _cl_mem_image* src_image
cl_kernel_set_arg(ker, 9, sizeof(cl_int), &dst_origin[1]);
cl_kernel_set_arg(ker, 10, sizeof(cl_int), &dst_origin[2]);
- ret = cl_command_queue_ND_range(queue, ker, 1, global_off, global_sz, local_sz);
+ ret = cl_command_queue_ND_range(queue, ker, event, 1, global_off, global_sz, local_sz);
fail:
@@ -1830,7 +1832,7 @@ fail:
}
LOCAL cl_int
-cl_mem_copy_image_to_buffer(cl_command_queue queue, struct _cl_mem_image* image, cl_mem buffer,
+cl_mem_copy_image_to_buffer(cl_command_queue queue, cl_event event, struct _cl_mem_image* image, cl_mem buffer,
const size_t *src_origin, const size_t dst_offset, const size_t *region) {
cl_int ret;
cl_kernel ker = NULL;
@@ -1919,7 +1921,7 @@ cl_mem_copy_image_to_buffer(cl_command_queue queue, struct _cl_mem_image* image,
cl_kernel_set_arg(ker, 7, sizeof(cl_int), &src_origin[2]);
cl_kernel_set_arg(ker, 8, sizeof(cl_int), &kn_dst_offset);
- ret = cl_command_queue_ND_range(queue, ker, 1, global_off, global_sz, local_sz);
+ ret = cl_command_queue_ND_range(queue, ker, event, 1, global_off, global_sz, local_sz);
fail:
@@ -1933,7 +1935,7 @@ fail:
LOCAL cl_int
-cl_mem_copy_buffer_to_image(cl_command_queue queue, cl_mem buffer, struct _cl_mem_image* image,
+cl_mem_copy_buffer_to_image(cl_command_queue queue, cl_event event, cl_mem buffer, struct _cl_mem_image* image,
const size_t src_offset, const size_t *dst_origin, const size_t *region) {
cl_int ret;
cl_kernel ker = NULL;
@@ -2019,7 +2021,7 @@ cl_mem_copy_buffer_to_image(cl_command_queue queue, cl_mem buffer, struct _cl_me
cl_kernel_set_arg(ker, 7, sizeof(cl_int), &dst_origin[2]);
cl_kernel_set_arg(ker, 8, sizeof(cl_int), &kn_src_offset);
- ret = cl_command_queue_ND_range(queue, ker, 1, global_off, global_sz, local_sz);
+ ret = cl_command_queue_ND_range(queue, ker, event, 1, global_off, global_sz, local_sz);
cl_kernel_delete(ker);
image->intel_fmt = intel_fmt;
@@ -2308,3 +2310,83 @@ error:
mem = NULL;
goto exit;
}
+
+LOCAL cl_int
+cl_mem_record_map_mem(cl_mem mem, void *ptr, void **mem_ptr, size_t offset,
+ size_t size, const size_t *origin, const size_t *region)
+{
+ // TODO: Need to add MT safe logic.
+
+ cl_int slot = -1;
+ int err = CL_SUCCESS;
+ size_t sub_offset = 0;
+
+ if(mem->type == CL_MEM_SUBBUFFER_TYPE) {
+ struct _cl_mem_buffer* buffer = (struct _cl_mem_buffer*)mem;
+ sub_offset = buffer->sub_offset;
+ }
+
+ ptr = (char*)ptr + offset + sub_offset;
+ if(mem->flags & CL_MEM_USE_HOST_PTR) {
+ assert(mem->host_ptr);
+ //only calc ptr here, will do memcpy in enqueue
+ *mem_ptr = (char *)mem->host_ptr + offset + sub_offset;
+ } else {
+ *mem_ptr = ptr;
+ }
+ /* Record the mapped address. */
+ if (!mem->mapped_ptr_sz) {
+ mem->mapped_ptr_sz = 16;
+ mem->mapped_ptr = (cl_mapped_ptr *)malloc(
+ sizeof(cl_mapped_ptr) * mem->mapped_ptr_sz);
+ if (!mem->mapped_ptr) {
+ cl_mem_unmap_auto(mem);
+ err = CL_OUT_OF_HOST_MEMORY;
+ goto error;
+ }
+ memset(mem->mapped_ptr, 0, mem->mapped_ptr_sz * sizeof(cl_mapped_ptr));
+ slot = 0;
+ } else {
+ int i = 0;
+ for (; i < mem->mapped_ptr_sz; i++) {
+ if (mem->mapped_ptr[i].ptr == NULL) {
+ slot = i;
+ break;
+ }
+ }
+ if (i == mem->mapped_ptr_sz) {
+ cl_mapped_ptr *new_ptr = (cl_mapped_ptr *)malloc(
+ sizeof(cl_mapped_ptr) * mem->mapped_ptr_sz * 2);
+ if (!new_ptr) {
+ cl_mem_unmap_auto(mem);
+ err = CL_OUT_OF_HOST_MEMORY;
+ goto error;
+ }
+ memset(new_ptr, 0, 2 * mem->mapped_ptr_sz * sizeof(cl_mapped_ptr));
+ memcpy(new_ptr, mem->mapped_ptr,
+ mem->mapped_ptr_sz * sizeof(cl_mapped_ptr));
+ slot = mem->mapped_ptr_sz;
+ mem->mapped_ptr_sz *= 2;
+ free(mem->mapped_ptr);
+ mem->mapped_ptr = new_ptr;
+ }
+ }
+ assert(slot != -1);
+ mem->mapped_ptr[slot].ptr = *mem_ptr;
+ mem->mapped_ptr[slot].v_ptr = ptr;
+ mem->mapped_ptr[slot].size = size;
+ if(origin) {
+ assert(region);
+ mem->mapped_ptr[slot].origin[0] = origin[0];
+ mem->mapped_ptr[slot].origin[1] = origin[1];
+ mem->mapped_ptr[slot].origin[2] = origin[2];
+ mem->mapped_ptr[slot].region[0] = region[0];
+ mem->mapped_ptr[slot].region[1] = region[1];
+ mem->mapped_ptr[slot].region[2] = region[2];
+ }
+ mem->map_ref++;
+error:
+ if (err != CL_SUCCESS)
+ *mem_ptr = NULL;
+ return err;
+}
diff --git a/src/cl_mem.h b/src/cl_mem.h
index 9bb5c47..82f30f6 100644
--- a/src/cl_mem.h
+++ b/src/cl_mem.h
@@ -101,7 +101,17 @@ typedef struct _cl_mem {
} _cl_mem;
#define CL_OBJECT_MEM_MAGIC 0x381a27b9ee6504dfLL
-#define CL_OBJECT_IS_MEM(obj) (((cl_base_object)obj)->magic == CL_OBJECT_MEM_MAGIC)
+#define CL_OBJECT_IS_MEM(obj) ((obj && \
+ ((cl_base_object)obj)->magic == CL_OBJECT_MEM_MAGIC && \
+ CL_OBJECT_GET_REF(obj) >= 1))
+#define CL_OBJECT_IS_IMAGE(mem) ((mem && \
+ ((cl_base_object)mem)->magic == CL_OBJECT_MEM_MAGIC && \
+ CL_OBJECT_GET_REF(mem) >= 1 && \
+ mem->type >= CL_MEM_IMAGE_TYPE))
+#define CL_OBJECT_IS_BUFFER(mem) ((mem && \
+ ((cl_base_object)mem)->magic == CL_OBJECT_MEM_MAGIC && \
+ CL_OBJECT_GET_REF(mem) >= 1 && \
+ mem->type < CL_MEM_IMAGE_TYPE))
struct _cl_mem_image {
_cl_mem base;
@@ -221,30 +231,30 @@ extern void cl_mem_gl_delete(struct _cl_mem_gl_image *);
extern void cl_mem_add_ref(cl_mem);
/* api clEnqueueCopyBuffer help function */
-extern cl_int cl_mem_copy(cl_command_queue queue, cl_mem src_buf, cl_mem dst_buf,
+extern cl_int cl_mem_copy(cl_command_queue queue, cl_event event, cl_mem src_buf, cl_mem dst_buf,
size_t src_offset, size_t dst_offset, size_t cb);
-extern cl_int cl_mem_fill(cl_command_queue queue, const void * pattern, size_t pattern_size,
+extern cl_int cl_mem_fill(cl_command_queue queue, cl_event e, const void * pattern, size_t pattern_size,
cl_mem buffer, size_t offset, size_t size);
extern cl_int cl_image_fill(cl_command_queue queue, const void * pattern, struct _cl_mem_image*,
const size_t *, const size_t *);
/* api clEnqueueCopyBufferRect help function */
-extern cl_int cl_mem_copy_buffer_rect(cl_command_queue, cl_mem, cl_mem,
+extern cl_int cl_mem_copy_buffer_rect(cl_command_queue, cl_event event, cl_mem, cl_mem,
const size_t *, const size_t *, const size_t *,
size_t, size_t, size_t, size_t);
/* api clEnqueueCopyImage help function */
-extern cl_int cl_mem_kernel_copy_image(cl_command_queue, struct _cl_mem_image*, struct _cl_mem_image*,
- const size_t *, const size_t *, const size_t *);
+extern cl_int cl_mem_kernel_copy_image(cl_command_queue, cl_event event, struct _cl_mem_image*,
+ struct _cl_mem_image*, const size_t *, const size_t *, const size_t *);
/* api clEnqueueCopyImageToBuffer help function */
-extern cl_int cl_mem_copy_image_to_buffer(cl_command_queue, struct _cl_mem_image*, cl_mem,
+extern cl_int cl_mem_copy_image_to_buffer(cl_command_queue, cl_event, struct _cl_mem_image*, cl_mem,
const size_t *, const size_t, const size_t *);
/* api clEnqueueCopyBufferToImage help function */
-extern cl_int cl_mem_copy_buffer_to_image(cl_command_queue, cl_mem, struct _cl_mem_image*,
+extern cl_int cl_mem_copy_buffer_to_image(cl_command_queue, cl_event, cl_mem, struct _cl_mem_image*,
const size_t, const size_t *, const size_t *);
/* Directly map a memory object */
@@ -318,5 +328,8 @@ extern cl_mem cl_mem_new_image_from_fd(cl_context ctx,
size_t row_pitch,
cl_int *errcode);
+extern cl_int cl_mem_record_map_mem(cl_mem mem, void *ptr, void **mem_ptr, size_t offset,
+ size_t size, const size_t *origin, const size_t *region);
+
#endif /* __CL_MEM_H__ */
--
2.7.4
More information about the Beignet
mailing list