/* * Copyright © 2012 Intel Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ #include "cl_event.h" #include "cl_context.h" #include "cl_command_queue.h" #include "CL/cl.h" #include cl_event clCreateUserEvent(cl_context context, cl_int *errcode_ret) { cl_int err = CL_SUCCESS; cl_event event = NULL; do { if (!CL_OBJECT_IS_CONTEXT(context)) { err = CL_INVALID_CONTEXT; break; } event = cl_event_create(context, NULL, 0, NULL, CL_COMMAND_USER, &err); } while (0); if (errcode_ret) *errcode_ret = err; return event; } cl_int clSetUserEventStatus(cl_event event, cl_int execution_status) { cl_int err = CL_SUCCESS; if (!CL_OBJECT_IS_EVENT(event)) { return CL_INVALID_EVENT; } if (execution_status > CL_COMPLETE) { return CL_INVALID_VALUE; } err = cl_event_set_status(event, execution_status); return err; } /* 1.1 API, depreciated */ cl_int clEnqueueMarker(cl_command_queue command_queue, cl_event *event) { return clEnqueueMarkerWithWaitList(command_queue, 0, NULL, event); } 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; cl_event e = NULL; cl_int e_status; do { if (!CL_OBJECT_IS_COMMAND_QUEUE(command_queue)) { err = CL_INVALID_COMMAND_QUEUE; break; } err = cl_event_check_waitlist(num_events_in_wait_list, event_wait_list, event, command_queue->ctx); if (err != CL_SUCCESS) { break; } if (event == NULL) { /* Create a anonymous event, it can not be waited on and useless. */ return CL_SUCCESS; } e = cl_event_create_marker_or_barrier(command_queue, num_events_in_wait_list, event_wait_list, CL_FALSE, &err); if (err != CL_SUCCESS) { return err; } e_status = cl_event_is_ready(e); if (e_status < CL_COMPLETE) { // Error happend, cancel. err = CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST; break; } else if (e_status == CL_COMPLETE) { err = cl_event_exec(e, CL_COMPLETE, CL_FALSE); if (err != CL_SUCCESS) { break; } } else { cl_command_queue_enqueue_event(command_queue, e); } } while (0); if (event) { *event = e; } else { cl_event_delete(e); } return err; } /* 1.1 API, depreciated */ cl_int clEnqueueBarrier(cl_command_queue command_queue) { return clEnqueueBarrierWithWaitList(command_queue, 0, NULL, NULL); } 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; cl_event e = NULL; cl_int e_status; do { if (!CL_OBJECT_IS_COMMAND_QUEUE(command_queue)) { err = CL_INVALID_COMMAND_QUEUE; break; } err = cl_event_check_waitlist(num_events_in_wait_list, event_wait_list, event, command_queue->ctx); if (err != CL_SUCCESS) { break; } e = cl_event_create_marker_or_barrier(command_queue, num_events_in_wait_list, event_wait_list, CL_TRUE, &err); if (err != CL_SUCCESS) { break; } e_status = cl_event_is_ready(e); if (e_status < CL_COMPLETE) { // Error happend, cancel. err = CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST; break; } else if (e_status == CL_COMPLETE) { cl_command_queue_insert_barrier_event(command_queue, e); err = cl_event_exec(e, CL_COMPLETE, CL_FALSE); if (err != CL_SUCCESS) { break; } /* Already a completed barrier, no need to insert to queue. */ } else { cl_command_queue_insert_barrier_event(command_queue, e); cl_command_queue_enqueue_event(command_queue, e); } } while (0); if (err == CL_SUCCESS && event) { *event = e; } else { cl_event_delete(e); } return err; } cl_int clWaitForEvents(cl_uint num_events, const cl_event *event_list) { cl_int err = CL_SUCCESS; cl_uint i; if (num_events == 0 || event_list == NULL) { return CL_INVALID_VALUE; } err = cl_event_check_waitlist(num_events, event_list, NULL, NULL); if (err != CL_SUCCESS) { return err; } for (i = 0; i < num_events; i++) { if (cl_event_get_status(event_list[i]) < CL_COMPLETE) { err = CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST; return err; } } err = cl_event_wait_for_events_list(num_events, event_list); return err; } /* 1.1 API, depreciated */ cl_int clEnqueueWaitForEvents(cl_command_queue command_queue, cl_uint num_events, const cl_event *event_list) { cl_int err = CL_SUCCESS; if (!CL_OBJECT_IS_COMMAND_QUEUE(command_queue)) { return CL_INVALID_COMMAND_QUEUE; } err = clWaitForEvents(num_events, event_list); 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; if (!CL_OBJECT_IS_EVENT(event)) { return CL_INVALID_EVENT; } if ((pfn_notify == NULL) || (command_exec_callback_type > CL_SUBMITTED) || (command_exec_callback_type < CL_COMPLETE)) { return CL_INVALID_VALUE; } err = cl_event_set_callback(event, command_exec_callback_type, pfn_notify, user_data); return err; } cl_int clGetEventInfo(cl_event event, cl_event_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret) { void *src_ptr = NULL; size_t src_size = 0; cl_uint ref; cl_int status; if (!CL_OBJECT_IS_EVENT(event)) { return CL_INVALID_EVENT; } if (param_name == CL_EVENT_COMMAND_QUEUE) { src_ptr = &event->queue; src_size = sizeof(cl_command_queue); } else if (param_name == CL_EVENT_CONTEXT) { src_ptr = &event->ctx; src_size = sizeof(cl_context); } else if (param_name == CL_EVENT_COMMAND_TYPE) { src_ptr = &event->event_type; src_size = sizeof(cl_command_type); } else if (param_name == CL_EVENT_COMMAND_EXECUTION_STATUS) { status = cl_event_get_status(event); src_ptr = &status; src_size = sizeof(cl_int); } else if (param_name == CL_EVENT_REFERENCE_COUNT) { ref = CL_OBJECT_GET_REF(event); src_ptr = &ref; src_size = sizeof(cl_int); } else { return CL_INVALID_VALUE; } return cl_get_info_helper(src_ptr, src_size, param_value, param_value_size, param_value_size_ret); } cl_int clGetEventProfilingInfo(cl_event event, cl_profiling_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret) { cl_ulong ret_val; if (!CL_OBJECT_IS_EVENT(event)) { return CL_INVALID_EVENT; } assert(event->event_type == CL_COMMAND_USER || event->queue != NULL); if (event->event_type == CL_COMMAND_USER || !(event->queue->props & CL_QUEUE_PROFILING_ENABLE) || cl_event_get_status(event) != CL_COMPLETE) { return CL_PROFILING_INFO_NOT_AVAILABLE; } if (param_value && param_value_size < sizeof(cl_ulong)) { return CL_INVALID_VALUE; } if (param_name < CL_PROFILING_COMMAND_QUEUED || param_name > CL_PROFILING_COMMAND_COMPLETE) { return CL_INVALID_VALUE; } ret_val = event->timestamp[param_name - CL_PROFILING_COMMAND_QUEUED]; if (ret_val == CL_EVENT_INVALID_TIMESTAMP) { return CL_INVALID_VALUE; } if (param_value) *(cl_ulong *)param_value = ret_val; if (param_value_size_ret) *param_value_size_ret = sizeof(cl_ulong); return CL_SUCCESS; }