1bf215546Sopenharmony_ci// 2bf215546Sopenharmony_ci// Copyright 2012 Francisco Jerez 3bf215546Sopenharmony_ci// 4bf215546Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci// copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci// to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci// the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci// and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci// Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci// 11bf215546Sopenharmony_ci// The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci// all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci// 14bf215546Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci// OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci// 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include "api/util.hpp" 24bf215546Sopenharmony_ci#include "core/event.hpp" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ciusing namespace clover; 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ciCLOVER_API cl_event 29bf215546Sopenharmony_ciclCreateUserEvent(cl_context d_ctx, cl_int *r_errcode) try { 30bf215546Sopenharmony_ci auto &ctx = obj(d_ctx); 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci ret_error(r_errcode, CL_SUCCESS); 33bf215546Sopenharmony_ci return desc(new soft_event(ctx, {}, false)); 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci} catch (error &e) { 36bf215546Sopenharmony_ci ret_error(r_errcode, e); 37bf215546Sopenharmony_ci return NULL; 38bf215546Sopenharmony_ci} 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ciCLOVER_API cl_int 41bf215546Sopenharmony_ciclSetUserEventStatus(cl_event d_ev, cl_int status) try { 42bf215546Sopenharmony_ci auto &sev = obj<soft_event>(d_ev); 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci if (status > 0) 45bf215546Sopenharmony_ci return CL_INVALID_VALUE; 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci if (sev.status() <= 0) 48bf215546Sopenharmony_ci return CL_INVALID_OPERATION; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci if (status) 51bf215546Sopenharmony_ci sev.abort(status); 52bf215546Sopenharmony_ci else 53bf215546Sopenharmony_ci sev.trigger(); 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci return CL_SUCCESS; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci} catch (error &e) { 58bf215546Sopenharmony_ci return e.get(); 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ciCLOVER_API cl_int 62bf215546Sopenharmony_ciclWaitForEvents(cl_uint num_evs, const cl_event *d_evs) try { 63bf215546Sopenharmony_ci auto evs = objs(d_evs, num_evs); 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci for (auto &ev : evs) { 66bf215546Sopenharmony_ci if (ev.context() != evs.front().context()) 67bf215546Sopenharmony_ci throw error(CL_INVALID_CONTEXT); 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci if (ev.status() < 0) 70bf215546Sopenharmony_ci throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); 71bf215546Sopenharmony_ci } 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci // Create a temporary soft event that depends on all the events in 74bf215546Sopenharmony_ci // the wait list 75bf215546Sopenharmony_ci auto sev = create<soft_event>(evs.front().context(), evs, true); 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci // ...and wait on it. 78bf215546Sopenharmony_ci sev().wait(); 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci return CL_SUCCESS; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci} catch (error &e) { 83bf215546Sopenharmony_ci return e.get(); 84bf215546Sopenharmony_ci} 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ciCLOVER_API cl_int 87bf215546Sopenharmony_ciclGetEventInfo(cl_event d_ev, cl_event_info param, 88bf215546Sopenharmony_ci size_t size, void *r_buf, size_t *r_size) try { 89bf215546Sopenharmony_ci property_buffer buf { r_buf, size, r_size }; 90bf215546Sopenharmony_ci auto &ev = obj(d_ev); 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci switch (param) { 93bf215546Sopenharmony_ci case CL_EVENT_COMMAND_QUEUE: 94bf215546Sopenharmony_ci buf.as_scalar<cl_command_queue>() = desc(ev.queue()); 95bf215546Sopenharmony_ci break; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci case CL_EVENT_CONTEXT: 98bf215546Sopenharmony_ci buf.as_scalar<cl_context>() = desc(ev.context()); 99bf215546Sopenharmony_ci break; 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci case CL_EVENT_COMMAND_TYPE: 102bf215546Sopenharmony_ci buf.as_scalar<cl_command_type>() = ev.command(); 103bf215546Sopenharmony_ci break; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci case CL_EVENT_COMMAND_EXECUTION_STATUS: 106bf215546Sopenharmony_ci buf.as_scalar<cl_int>() = ev.status(); 107bf215546Sopenharmony_ci break; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci case CL_EVENT_REFERENCE_COUNT: 110bf215546Sopenharmony_ci buf.as_scalar<cl_uint>() = ev.ref_count(); 111bf215546Sopenharmony_ci break; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci default: 114bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 115bf215546Sopenharmony_ci } 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci return CL_SUCCESS; 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci} catch (error &e) { 120bf215546Sopenharmony_ci return e.get(); 121bf215546Sopenharmony_ci} 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ciCLOVER_API cl_int 124bf215546Sopenharmony_ciclSetEventCallback(cl_event d_ev, cl_int type, 125bf215546Sopenharmony_ci void (CL_CALLBACK *pfn_notify)(cl_event, cl_int, void *), 126bf215546Sopenharmony_ci void *user_data) try { 127bf215546Sopenharmony_ci auto &ev = obj(d_ev); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci if (!pfn_notify || 130bf215546Sopenharmony_ci (type != CL_COMPLETE && type != CL_SUBMITTED && type != CL_RUNNING)) 131bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci // Create a temporary soft event that depends on ev, with 134bf215546Sopenharmony_ci // pfn_notify as completion action. 135bf215546Sopenharmony_ci create<soft_event>(ev.context(), ref_vector<event> { ev }, true, 136bf215546Sopenharmony_ci [=, &ev](event &) { 137bf215546Sopenharmony_ci ev.wait(); 138bf215546Sopenharmony_ci pfn_notify(desc(ev), ev.status(), user_data); 139bf215546Sopenharmony_ci }); 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci return CL_SUCCESS; 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci} catch (error &e) { 144bf215546Sopenharmony_ci return e.get(); 145bf215546Sopenharmony_ci} 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ciCLOVER_API cl_int 148bf215546Sopenharmony_ciclRetainEvent(cl_event d_ev) try { 149bf215546Sopenharmony_ci obj(d_ev).retain(); 150bf215546Sopenharmony_ci return CL_SUCCESS; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci} catch (error &e) { 153bf215546Sopenharmony_ci return e.get(); 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ciCLOVER_API cl_int 157bf215546Sopenharmony_ciclReleaseEvent(cl_event d_ev) try { 158bf215546Sopenharmony_ci if (obj(d_ev).release()) 159bf215546Sopenharmony_ci delete pobj(d_ev); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci return CL_SUCCESS; 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci} catch (error &e) { 164bf215546Sopenharmony_ci return e.get(); 165bf215546Sopenharmony_ci} 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ciCLOVER_API cl_int 168bf215546Sopenharmony_ciclEnqueueMarker(cl_command_queue d_q, cl_event *rd_ev) try { 169bf215546Sopenharmony_ci auto &q = obj(d_q); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci if (!rd_ev) 172bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci *rd_ev = desc(new hard_event(q, CL_COMMAND_MARKER, {})); 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci return CL_SUCCESS; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci} catch (error &e) { 179bf215546Sopenharmony_ci return e.get(); 180bf215546Sopenharmony_ci} 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ciCLOVER_API cl_int 183bf215546Sopenharmony_ciclEnqueueMarkerWithWaitList(cl_command_queue d_q, cl_uint num_deps, 184bf215546Sopenharmony_ci const cl_event *d_deps, cl_event *rd_ev) try { 185bf215546Sopenharmony_ci auto &q = obj(d_q); 186bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci for (auto &ev : deps) { 189bf215546Sopenharmony_ci if (ev.context() != q.context()) 190bf215546Sopenharmony_ci throw error(CL_INVALID_CONTEXT); 191bf215546Sopenharmony_ci } 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci // Create a hard event that depends on the events in the wait list: 194bf215546Sopenharmony_ci // previous commands in the same queue are implicitly serialized 195bf215546Sopenharmony_ci // with respect to it -- hard events always are. 196bf215546Sopenharmony_ci auto hev = create<hard_event>(q, CL_COMMAND_MARKER, deps); 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci ret_object(rd_ev, hev); 199bf215546Sopenharmony_ci return CL_SUCCESS; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci} catch (error &e) { 202bf215546Sopenharmony_ci return e.get(); 203bf215546Sopenharmony_ci} 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ciCLOVER_API cl_int 206bf215546Sopenharmony_ciclEnqueueBarrier(cl_command_queue d_q) try { 207bf215546Sopenharmony_ci obj(d_q); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci // No need to do anything, q preserves data ordering strictly. 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci return CL_SUCCESS; 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci} catch (error &e) { 214bf215546Sopenharmony_ci return e.get(); 215bf215546Sopenharmony_ci} 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ciCLOVER_API cl_int 218bf215546Sopenharmony_ciclEnqueueBarrierWithWaitList(cl_command_queue d_q, cl_uint num_deps, 219bf215546Sopenharmony_ci const cl_event *d_deps, cl_event *rd_ev) try { 220bf215546Sopenharmony_ci auto &q = obj(d_q); 221bf215546Sopenharmony_ci auto deps = objs<wait_list_tag>(d_deps, num_deps); 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci for (auto &ev : deps) { 224bf215546Sopenharmony_ci if (ev.context() != q.context()) 225bf215546Sopenharmony_ci throw error(CL_INVALID_CONTEXT); 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci // Create a hard event that depends on the events in the wait list: 229bf215546Sopenharmony_ci // subsequent commands in the same queue will be implicitly 230bf215546Sopenharmony_ci // serialized with respect to it -- hard events always are. 231bf215546Sopenharmony_ci auto hev = create<hard_event>(q, CL_COMMAND_BARRIER, deps); 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci ret_object(rd_ev, hev); 234bf215546Sopenharmony_ci return CL_SUCCESS; 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci} catch (error &e) { 237bf215546Sopenharmony_ci return e.get(); 238bf215546Sopenharmony_ci} 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ciCLOVER_API cl_int 241bf215546Sopenharmony_ciclEnqueueWaitForEvents(cl_command_queue d_q, cl_uint num_evs, 242bf215546Sopenharmony_ci const cl_event *d_evs) try { 243bf215546Sopenharmony_ci // The wait list is mandatory for clEnqueueWaitForEvents(). 244bf215546Sopenharmony_ci objs(d_evs, num_evs); 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci return clEnqueueBarrierWithWaitList(d_q, num_evs, d_evs, NULL); 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci} catch (error &e) { 249bf215546Sopenharmony_ci return e.get(); 250bf215546Sopenharmony_ci} 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ciCLOVER_API cl_int 253bf215546Sopenharmony_ciclGetEventProfilingInfo(cl_event d_ev, cl_profiling_info param, 254bf215546Sopenharmony_ci size_t size, void *r_buf, size_t *r_size) try { 255bf215546Sopenharmony_ci property_buffer buf { r_buf, size, r_size }; 256bf215546Sopenharmony_ci hard_event &hev = dynamic_cast<hard_event &>(obj(d_ev)); 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci if (hev.status() != CL_COMPLETE) 259bf215546Sopenharmony_ci throw error(CL_PROFILING_INFO_NOT_AVAILABLE); 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci switch (param) { 262bf215546Sopenharmony_ci case CL_PROFILING_COMMAND_QUEUED: 263bf215546Sopenharmony_ci buf.as_scalar<cl_ulong>() = hev.time_queued(); 264bf215546Sopenharmony_ci break; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci case CL_PROFILING_COMMAND_SUBMIT: 267bf215546Sopenharmony_ci buf.as_scalar<cl_ulong>() = hev.time_submit(); 268bf215546Sopenharmony_ci break; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci case CL_PROFILING_COMMAND_START: 271bf215546Sopenharmony_ci buf.as_scalar<cl_ulong>() = hev.time_start(); 272bf215546Sopenharmony_ci break; 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci case CL_PROFILING_COMMAND_END: 275bf215546Sopenharmony_ci case CL_PROFILING_COMMAND_COMPLETE: 276bf215546Sopenharmony_ci buf.as_scalar<cl_ulong>() = hev.time_end(); 277bf215546Sopenharmony_ci break; 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci default: 280bf215546Sopenharmony_ci throw error(CL_INVALID_VALUE); 281bf215546Sopenharmony_ci } 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci return CL_SUCCESS; 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci} catch (std::bad_cast &) { 286bf215546Sopenharmony_ci return CL_PROFILING_INFO_NOT_AVAILABLE; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci} catch (lazy<cl_ulong>::undefined_error &) { 289bf215546Sopenharmony_ci return CL_PROFILING_INFO_NOT_AVAILABLE; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci} catch (error &e) { 292bf215546Sopenharmony_ci return e.get(); 293bf215546Sopenharmony_ci} 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ciCLOVER_API cl_int 296bf215546Sopenharmony_ciclFinish(cl_command_queue d_q) try { 297bf215546Sopenharmony_ci auto &q = obj(d_q); 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci // Create a temporary hard event -- it implicitly depends on all 300bf215546Sopenharmony_ci // the previously queued hard events. 301bf215546Sopenharmony_ci auto hev = create<hard_event>(q, 0, ref_vector<event> {}); 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci // And wait on it. 304bf215546Sopenharmony_ci hev().wait(); 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci return CL_SUCCESS; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci} catch (error &e) { 309bf215546Sopenharmony_ci return e.get(); 310bf215546Sopenharmony_ci} 311