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