-/*
+/*
* Copyright © 2012 Intel Corporation
*
* This library is free software; you can redistribute it and/or
*/
#include "cl_platform_id.h"
-#include "cl_device_id.h"
+#include "cl_device_id.h"
#include "cl_context.h"
#include "cl_command_queue.h"
+#include "cl_enqueue.h"
+#include "cl_event.h"
#include "cl_program.h"
#include "cl_kernel.h"
#include "cl_mem.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
+#include <unistd.h>
#ifndef CL_VERSION_1_2
#define CL_MAP_WRITE_INVALIDATE_REGION (1 << 2)
return RET; \
} while(0)
+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);
+ cl_event e;
+ if(event != NULL || status == CL_ENQUEUE_EXECUTE_DEFER) {
+ e = cl_event_new(queue->ctx, queue, type, event!=NULL);
+ if(event != NULL)
+ *event = e;
+ if(status == CL_ENQUEUE_EXECUTE_DEFER) {
+ cl_event_new_enqueue_callback(e, data, num, wait_list);
+ }
+ }
+ return status;
+}
+
static cl_int
cl_check_device_type(cl_device_type device_type)
{
clWaitForEvents(cl_uint num_events,
const cl_event * event_list)
{
- NOT_IMPLEMENTED;
- return 0;
+ 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) == CL_ENQUEUE_EXECUTE_DEFER) {
+ usleep(8000); //sleep 8ms to wait other thread
+ }
+
+error:
+ return err;
}
cl_int
void * param_value,
size_t * param_value_size_ret)
{
- NOT_IMPLEMENTED;
- return 0;
+ cl_int err = CL_SUCCESS;
+ CHECK_EVENT(event);
+
+ if (param_name == CL_EVENT_COMMAND_QUEUE) {
+ if(event->queue == NULL) {
+ param_value_size_ret = 0;
+ param_value = NULL;
+ return err;
+ }
+ FILL_GETINFO_RET (cl_command_queue, 1, &event->queue, CL_SUCCESS);
+ } 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);
+ } else if (param_name == CL_EVENT_COMMAND_EXECUTION_STATUS) {
+ cl_event_update_status(event);
+ FILL_GETINFO_RET (cl_int, 1, &event->status, CL_SUCCESS);
+ } else if (param_name == CL_EVENT_REFERENCE_COUNT) {
+ cl_uint ref = event->ref_n;
+ FILL_GETINFO_RET (cl_int, 1, &ref, CL_SUCCESS);
+ } else {
+ return CL_INVALID_VALUE;
+ }
+
+error:
+ return err;
+
}
cl_event
clCreateUserEvent(cl_context context,
cl_int * errcode_ret)
{
- NOT_IMPLEMENTED;
- return NULL;
+ 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)
{
- NOT_IMPLEMENTED;
- return 0;
+ cl_int err = CL_SUCCESS;
+
+ CHECK_EVENT(event);
+ cl_event_add_ref(event);
+
+error:
+ return err;
}
cl_int
clReleaseEvent(cl_event event)
{
- NOT_IMPLEMENTED;
- return 0;
+ cl_int err = CL_SUCCESS;
+
+ CHECK_EVENT(event);
+ cl_event_delete(event);
+
+error:
+ return err;
}
cl_int
clSetUserEventStatus(cl_event event,
cl_int execution_status)
{
- NOT_IMPLEMENTED;
- return 0;
+ 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
void (CL_CALLBACK * pfn_notify) (cl_event, cl_int, void *),
void * user_data)
{
- NOT_IMPLEMENTED;
- return 0;
+ 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
cl_event * event)
{
cl_int err = CL_SUCCESS;
- void* src_ptr;
-
+ enqueue_data *data, defer_enqueue_data = { 0 };
CHECK_QUEUE(command_queue);
CHECK_MEM(buffer);
if (command_queue->ctx != buffer->ctx) {
goto error;
}
- if (!(src_ptr = cl_mem_map_auto(buffer))) {
- err = CL_MAP_FAILURE;
- goto error;
- }
+ TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, buffer->ctx);
- memcpy(ptr, (char*)src_ptr + offset, size);
+ data = &defer_enqueue_data;
+ data->type = EnqueueReadBuffer;
+ data->mem_obj = buffer;
+ data->ptr = ptr;
+ data->offset = offset;
+ data->size = size;
- err = cl_mem_unmap_auto(buffer);
+ 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(data);
+ if(event) cl_event_set_status(*event, CL_COMPLETE);
+ }
error:
return err;
cl_event * event)
{
cl_int err = CL_SUCCESS;
- void* dst_ptr;
+ enqueue_data *data, no_wait_data = { 0 };
CHECK_QUEUE(command_queue);
CHECK_MEM(buffer);
goto error;
}
- if (!(dst_ptr = cl_mem_map_auto(buffer))) {
- err = CL_MAP_FAILURE;
- goto error;
- }
+ TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, buffer->ctx);
- memcpy((char*)dst_ptr + offset, ptr, size);
+ data = &no_wait_data;
+ data->type = EnqueueWriteBuffer;
+ data->mem_obj = buffer;
+ data->const_ptr = ptr;
+ data->offset = offset;
+ data->size = size;
- err = cl_mem_unmap_auto(buffer);
+ 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(data);
+ if(event) cl_event_set_status(*event, CL_COMPLETE);
+ }
-error:
+ error:
return err;
}
cl_event * event)
{
cl_int err = CL_SUCCESS;
- void* src_ptr;
+ enqueue_data *data, no_wait_data = { 0 };
CHECK_QUEUE(command_queue);
CHECK_IMAGE(image);
goto error;
}
- if (!(src_ptr = cl_mem_map_auto(image))) {
- err = CL_MAP_FAILURE;
- goto error;
- }
-
- size_t offset = image->bpp*origin[0] + image->row_pitch*origin[1] + image->slice_pitch*origin[2];
- src_ptr = (char*)src_ptr + offset;
-
- if (!origin[0] && region[0] == image->w && row_pitch == image->row_pitch &&
- (region[2] == 1 || (!origin[1] && region[1] == image->h && slice_pitch == image->slice_pitch)))
- {
- memcpy(ptr, src_ptr, region[2] == 1 ? row_pitch*region[1] : slice_pitch*region[2]);
+ TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, image->ctx);
+
+ data = &no_wait_data;
+ data->type = EnqueueReadImage;
+ data->mem_obj = image;
+ 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_BUFFER) == CL_ENQUEUE_EXECUTE_IMM) {
+ err = cl_enqueue_handle(data);
+ if(event) cl_event_set_status(*event, CL_COMPLETE);
}
- else {
- cl_uint y, z;
- for (z = 0; z < region[2]; z++) {
- const char* src = src_ptr;
- char* dst = ptr;
- for (y = 0; y < region[1]; y++) {
- memcpy(dst, src, image->bpp*region[0]);
- src += image->row_pitch;
- dst += row_pitch;
- }
- src_ptr = (char*)src_ptr + image->slice_pitch;
- ptr = (char*)ptr + slice_pitch;
- }
- }
-
- err = cl_mem_unmap_auto(image);
error:
return err;
cl_event * event)
{
cl_int err = CL_SUCCESS;
- void* dst_ptr;
+ enqueue_data *data, no_wait_data = { 0 };
CHECK_QUEUE(command_queue);
CHECK_IMAGE(image);
goto error;
}
- if (!(dst_ptr = cl_mem_map_auto(image))) {
- err = CL_MAP_FAILURE;
- goto error;
- }
-
- size_t offset = image->bpp*origin[0] + image->row_pitch*origin[1] + image->slice_pitch*origin[2];
- dst_ptr = (char*)dst_ptr + offset;
-
- if (!origin[0] && region[0] == image->w && row_pitch == image->row_pitch &&
- (region[2] == 1 || (!origin[1] && region[1] == image->h && slice_pitch == image->slice_pitch)))
- {
- memcpy(dst_ptr, ptr, region[2] == 1 ? row_pitch*region[1] : slice_pitch*region[2]);
+ TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, image->ctx);
+
+ data = &no_wait_data;
+ data->type = EnqueueWriteImage;
+ data->mem_obj = image;
+ 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_READ_BUFFER) == CL_ENQUEUE_EXECUTE_IMM) {
+ err = cl_enqueue_handle(data);
+ if(event) cl_event_set_status(*event, CL_COMPLETE);
}
- else {
- cl_uint y, z;
- for (z = 0; z < region[2]; z++) {
- const char* src = ptr;
- char* dst = dst_ptr;
- for (y = 0; y < region[1]; y++) {
- memcpy(dst, src, image->bpp*region[0]);
- src += row_pitch;
- dst += image->row_pitch;
- }
- ptr = (char*)ptr + slice_pitch;
- dst_ptr = (char*)dst_ptr + image->slice_pitch;
- }
- }
-
- err = cl_mem_unmap_auto(image);
error:
return err;
cl_event * event,
cl_int * errcode_ret)
{
- void *ptr = NULL;
- void *mem_ptr = NULL;
cl_int err = CL_SUCCESS;
- int slot = -1;
+ enqueue_data *data, no_wait_data = { 0 };
CHECK_QUEUE(command_queue);
CHECK_MEM(buffer);
goto error;
}
- if (!(ptr = cl_mem_map_auto(buffer))) {
- err = CL_MAP_FAILURE;
- goto error;
- }
+ TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, buffer->ctx);
- ptr = (char*)ptr + offset;
+ data = &no_wait_data;
+ data->type = EnqueueMapBuffer;
+ data->mem_obj = buffer;
+ data->offset = offset;
+ data->size = size;
+ data->map_flags = map_flags;
- if(buffer->flags & CL_MEM_USE_HOST_PTR) {
- assert(buffer->host_ptr);
- memcpy(buffer->host_ptr + offset, ptr, size);
- mem_ptr = buffer->host_ptr + offset;
- } else {
- mem_ptr = ptr;
+ 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(data);
+ if(event) cl_event_set_status(*event, CL_COMPLETE);
}
- /* Record the mapped address. */
- if (!buffer->mapped_ptr_sz) {
- buffer->mapped_ptr_sz = 16;
- buffer->mapped_ptr = (cl_mapped_ptr *)malloc(
- sizeof(cl_mapped_ptr) * buffer->mapped_ptr_sz);
- if (!buffer->mapped_ptr) {
- cl_mem_unmap_auto (buffer);
- err = CL_OUT_OF_HOST_MEMORY;
- ptr = NULL;
- goto error;
- }
-
- memset(buffer->mapped_ptr, 0, buffer->mapped_ptr_sz * sizeof(cl_mapped_ptr));
- slot = 0;
- } else {
- int i = 0;
- for (; i < buffer->mapped_ptr_sz; i++) {
- if (buffer->mapped_ptr[i].ptr == NULL) {
- slot = i;
- break;
- }
- }
-
- if (i == buffer->mapped_ptr_sz) {
- cl_mapped_ptr *new_ptr = (cl_mapped_ptr *)malloc(
- sizeof(cl_mapped_ptr) * buffer->mapped_ptr_sz * 2);
- if (!new_ptr) {
- cl_mem_unmap_auto (buffer);
- err = CL_OUT_OF_HOST_MEMORY;
- ptr = NULL;
- goto error;
- }
- memset(new_ptr, 0, 2 * buffer->mapped_ptr_sz * sizeof(cl_mapped_ptr));
- memcpy(new_ptr, buffer->mapped_ptr,
- buffer->mapped_ptr_sz * sizeof(cl_mapped_ptr));
- slot = buffer->mapped_ptr_sz;
- buffer->mapped_ptr_sz *= 2;
- free(buffer->mapped_ptr);
- buffer->mapped_ptr = new_ptr;
- }
- }
-
- assert(slot != -1);
- buffer->mapped_ptr[slot].ptr = mem_ptr;
- buffer->mapped_ptr[slot].v_ptr = ptr;
- buffer->mapped_ptr[slot].size = size;
- buffer->map_ref++;
-
error:
if (errcode_ret)
*errcode_ret = err;
- return mem_ptr;
+ return data->ptr;
}
void *
cl_event * event,
cl_int * errcode_ret)
{
- void *ptr = NULL;
cl_int err = CL_SUCCESS;
+ enqueue_data *data, no_wait_data = { 0 };
CHECK_QUEUE(command_queue);
CHECK_IMAGE(image);
goto error;
}
- if (!(ptr = cl_mem_map_auto(image))) {
- err = CL_MAP_FAILURE;
- goto error;
+ TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, image->ctx);
+
+ data = &no_wait_data;
+ data->type = EnqueueMapImage;
+ data->mem_obj = image;
+ 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 = *image_row_pitch;
+ data->slice_pitch = *image_slice_pitch;
+ data->map_flags = map_flags;
+
+ 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(data);
+ if(event) cl_event_set_status(*event, CL_COMPLETE);
}
- size_t offset = image->bpp*origin[0] + image->row_pitch*origin[1] + image->slice_pitch*origin[2];
- ptr = (char*)ptr + offset;
-
error:
if (errcode_ret)
*errcode_ret = err;
- return ptr;
+ return data->ptr; //TODO: map and unmap first
}
cl_int
cl_event * event)
{
cl_int err = CL_SUCCESS;
- int i;
- size_t mapped_size = 0;
- void * v_ptr = NULL;
+ enqueue_data *data, no_wait_data = { 0 };
CHECK_QUEUE(command_queue);
CHECK_MEM(memobj);
goto error;
}
- assert(memobj->mapped_ptr_sz >= memobj->map_ref);
- INVALID_VALUE_IF(!mapped_ptr);
- for (i = 0; i < memobj->mapped_ptr_sz; i++) {
- if (memobj->mapped_ptr[i].ptr == mapped_ptr) {
- memobj->mapped_ptr[i].ptr = NULL;
- mapped_size = memobj->mapped_ptr[i].size;
- v_ptr = memobj->mapped_ptr[i].v_ptr;
- memobj->mapped_ptr[i].size = 0;
- memobj->mapped_ptr[i].v_ptr = NULL;
- memobj->map_ref--;
- break;
- }
- }
- /* can not find a mapped address? */
- INVALID_VALUE_IF(i == memobj->mapped_ptr_sz);
-
- if (memobj->flags & CL_MEM_USE_HOST_PTR) {
- assert(mapped_ptr >= memobj->host_ptr &&
- mapped_ptr + mapped_size <= memobj->host_ptr + memobj->size);
- /* Sync the data. */
- memcpy(v_ptr, mapped_ptr, mapped_size);
- } else {
- assert(v_ptr == mapped_ptr);
- }
+ TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, memobj->ctx);
- cl_mem_unmap_auto(memobj);
+ data = &no_wait_data;
+ data->type = EnqueueUnmapMemObject;
+ data->mem_obj = memobj;
+ data->ptr = mapped_ptr;
- /* shrink the mapped slot. */
- 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));
- if (!new_ptr) {
- /* Just do nothing. */
- goto error;
- }
- 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);
- }
- }
- memobj->mapped_ptr_sz = memobj->mapped_ptr_sz/2;
- free(memobj->mapped_ptr);
- memobj->mapped_ptr = new_ptr;
+ 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(data);
+ if(event) cl_event_set_status(*event, CL_COMPLETE);
}
error:
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);
}
/* Local sizes must be non-null and divide global sizes */
- if (local_work_size != NULL)
- for (i = 0; i < work_dim; ++i)
+ 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;
}
/* 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");
+ //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_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;
+
+ 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_command_queue_flush(command_queue);
+ }
error:
return err;
cl_uint num_events,
const cl_event * event_list)
{
- NOT_IMPLEMENTED;
- return 0;
+ cl_int err = CL_SUCCESS;
+ CHECK_QUEUE(command_queue);
+ err = clWaitForEvents(num_events, event_list);
+
+error:
+ return err;
}
cl_int
{
NOT_IMPLEMENTED;
return 0;
+ //return clFinish(command_queue);
}
#define EXTFUNC(x) \
-/*
+/*
* Copyright © 2012 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* 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@intel.com>
+ * Author: Rong Yang <rong.r.yang@intel.com>
*/
-struct empty {int dummy;};
+#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 <assert.h>
+#include <stdio.h>
+
+cl_event cl_event_new(cl_context ctx, cl_command_queue queue, cl_command_type type, cl_bool emplict)
+{
+ cl_event event = NULL;
+
+ /* Allocate and inialize the structure itself */
+ TRY_ALLOC_NO_ERR (event, CALLOC(struct _cl_event));
+ SET_ICD(event->dispatch)
+ event->magic = CL_MAGIC_EVENT_HEADER;
+ event->ref_n = 1;
+
+ /* Append the event in the context event list */
+ pthread_mutex_lock(&ctx->event_lock);
+ event->next = ctx->events;
+ if (ctx->events != NULL)
+ ctx->events->prev = event;
+ ctx->events = event;
+ pthread_mutex_unlock(&ctx->event_lock);
+ event->ctx = ctx;
+ cl_context_add_ref(ctx);
+
+ /* 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;
+ }
+ else {
+ event->status = CL_QUEUED;
+ event->gpgpu_event = cl_gpgpu_event_new(queue->gpgpu);
+ }
+ 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;
+}
+
+void cl_event_delete(cl_event event)
+{
+ if (UNLIKELY(event == NULL))
+ return;
+
+ if (atomic_dec(&event->ref_n) > 1)
+ return;
+
+ /* Call all user's callback if haven't execute */
+ user_callback *cb = event->user_cb;
+ while(event->user_cb) {
+ cb = event->user_cb;
+ if(cb->executed == CL_FALSE) {
+ cb->pfn_notify(event, event->status, cb->user_data);
+ }
+ event->user_cb = cb->next;
+ cl_free(cb);
+ }
+
+ /* delete gpgpu event object */
+ if(event->gpgpu_event)
+ cl_gpgpu_event_delete(event->gpgpu_event);
+
+ /* Remove it from the list */
+ assert(event->ctx);
+ pthread_mutex_lock(&event->ctx->event_lock);
+ if (event->prev)
+ event->prev->next = event->next;
+ if (event->next)
+ event->next->prev = event->prev;
+ if (event->prev == NULL && event->next == NULL)
+ event->ctx->events = NULL;
+ pthread_mutex_unlock(&event->ctx->event_lock);
+ cl_context_delete(event->ctx);
+
+ cl_free(event);
+}
+
+void cl_event_add_ref(cl_event event)
+{
+ assert(event);
+ atomic_inc(&event->ref_n);
+}
+
+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);
+
+ 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;
+
+ cb->next = event->user_cb;
+ event->user_cb = cb;
+
+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 exit;
+
+ if ((event_wait_list != NULL) &&
+ (num_events_in_wait_list == 0)){
+ goto error;
+ }
+
+ /* 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)
+ goto error;
+ }
+
+exit:
+ return err;
+error:
+ err = CL_INVALID_EVENT_WAIT_LIST; //reset error
+ goto exit;
+}
+
+cl_int cl_event_wait_events(cl_uint num_events_in_wait_list,
+ const cl_event *event_wait_list)
+{
+ cl_int i, j;
+ /* Check whether wait user events */
+ for(i=0; i<num_events_in_wait_list; i++) {
+ if(event_wait_list[i]->status <= CL_COMPLETE)
+ continue;
+
+ /* 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))){
+ for(j=0; j<num_events_in_wait_list; j++)
+ cl_event_add_ref(event_wait_list[j]); //add defer enqueue's wait event reference
+ return CL_ENQUEUE_EXECUTE_DEFER;
+ }
+ }
+
+ /* 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;
+
+ //enqueue callback haven't finish, in another thread, wait
+ if(event_wait_list[i]->enqueue_cb != NULL)
+ return CL_ENQUEUE_EXECUTE_DEFER;
+ 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
+ }
+ return CL_ENQUEUE_EXECUTE_IMM;
+}
+
+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)
+{
+ enqueue_callback *cb, *node;
+ user_event *user_events, *u_ev;
+ cl_int i;
+
+ /* Allocate and inialize the structure itself */
+ TRY_ALLOC_NO_ERR (cb, CALLOC(enqueue_callback));
+ cb->num_events = num_events_in_wait_list;
+ cb->wait_list = event_wait_list;
+ cb->event = event;
+ cb->next = NULL;
+ cb->wait_user_events = NULL;
+
+ /* Find out all user events that events 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_ALLOC_NO_ERR (u_ev, CALLOC(user_event));
+ u_ev->event = event_wait_list[i];
+ u_ev->next = cb->wait_user_events;
+ cb->wait_user_events = u_ev;
+ } 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;
+ 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_ALLOC_NO_ERR (u_ev, CALLOC(user_event));
+ u_ev->event = user_events->event;
+ u_ev->next = cb->wait_user_events;
+ cb->wait_user_events = u_ev;
+ user_events = user_events->next;
+ }
+ }
+ }
+ if(data->queue != NULL) {
+ assert(event->gpgpu_event);
+ cl_gpgpu_event_pending(data->queue->gpgpu, event->gpgpu_event);
+ data->ptr = (void *)event->gpgpu_event;
+ }
+ cb->data = *data;
+ 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_free(u_ev);
+ }
+ cl_free(cb);
+ }
+ goto exit;
+}
+
+void cl_event_set_status(cl_event event, cl_int status)
+{
+ user_callback *user_cb;
+ user_event *u_ev, *u_ev_next;
+ cl_int ret, i;
+ cl_event evt;
+
+ pthread_mutex_lock(&event->ctx->event_lock);
+ if(status >= event->status) {
+ return;
+ }
+
+ if(status <= CL_COMPLETE) {
+ if(event->enqueue_cb) {
+ for(i=0; i<event->enqueue_cb->num_events; i++)
+ cl_event_delete(event->enqueue_cb->wait_list[i]);
+
+ cl_enqueue_handle(&event->enqueue_cb->data);
+ cl_free(event->enqueue_cb);
+ event->enqueue_cb = NULL;
+ }
+ cl_event_delete(event);
+ }
+ event->status = status;
+ pthread_mutex_unlock(&event->ctx->event_lock);
+
+ /* Call user callback */
+ user_cb = event->user_cb;
+ while(user_cb) {
+ if(user_cb->status >= status) {
+ user_cb->pfn_notify(event, event->status, user_cb->user_data);
+ user_cb->executed = CL_TRUE;
+ }
+ user_cb = user_cb->next;
+ }
+
+ if(event->type != CL_COMMAND_USER)
+ return;
+
+ /* Check all defer enqueue */
+ enqueue_callback *cb, *enqueue_cb = event->waits_head;
+ while(enqueue_cb) {
+ /* Remove this user event in enqueue_cb */
+ while(enqueue_cb->wait_user_events &&
+ enqueue_cb->wait_user_events->event == event) {
+ u_ev = enqueue_cb->wait_user_events;
+ enqueue_cb->wait_user_events = enqueue_cb->wait_user_events->next;
+ cl_free(u_ev);
+ }
+
+ u_ev = enqueue_cb->wait_user_events;
+ while(u_ev) {
+ u_ev_next = u_ev->next;
+ if(u_ev_next && u_ev_next->event == event) {
+ u_ev->next = u_ev_next->next;
+ cl_free(u_ev_next);
+ } else
+ u_ev->next = u_ev_next;
+ }
+
+ /* Still wait on other user events */
+ if(enqueue_cb->wait_user_events != NULL) {
+ enqueue_cb = enqueue_cb->next;
+ continue;
+ }
+
+ /* All user events complete, now wait enqueue events */
+ ret = cl_event_wait_events(enqueue_cb->num_events, enqueue_cb->wait_list);
+ assert(ret != CL_ENQUEUE_EXECUTE_DEFER);
+
+ cb = enqueue_cb;
+ enqueue_cb = enqueue_cb->next;
+
+ /* Call the pending operation */
+ evt = cb->event;
+ cl_event_set_status(cb->event, CL_COMPLETE);
+ if(cb->event->emplict == CL_FALSE) {
+ cl_event_delete(evt);
+ }
+ }
+ event->waits_head = NULL;
+}
+
+void cl_event_update_status(cl_event event)
+{
+ if(event->status <= CL_COMPLETE)
+ return;
+ if((event->gpgpu_event) &&
+ (cl_gpgpu_event_update_status(event->gpgpu_event, 0) == command_complete))
+ cl_event_set_status(event, CL_COMPLETE);
+}