2 // Copyright 2012 Francisco Jerez
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
23 #include "api/util.hpp"
24 #include "core/event.hpp"
26 using namespace clover
;
29 clCreateUserEvent(cl_context ctx
, cl_int
*errcode_ret
) try {
31 throw error(CL_INVALID_CONTEXT
);
33 ret_error(errcode_ret
, CL_SUCCESS
);
34 return new soft_event(*ctx
, {}, false);
37 ret_error(errcode_ret
, e
);
42 clSetUserEventStatus(cl_event ev
, cl_int status
) {
43 if (!dynamic_cast<soft_event
*>(ev
))
44 return CL_INVALID_EVENT
;
47 return CL_INVALID_VALUE
;
49 if (ev
->status() <= 0)
50 return CL_INVALID_OPERATION
;
61 clWaitForEvents(cl_uint num_evs
, const cl_event
*evs
) try {
63 throw error(CL_INVALID_VALUE
);
65 std::for_each(evs
, evs
+ num_evs
, [&](const cl_event ev
) {
67 throw error(CL_INVALID_EVENT
);
69 if (&ev
->ctx
!= &evs
[0]->ctx
)
70 throw error(CL_INVALID_CONTEXT
);
73 throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST
);
76 // Create a temporary soft event that depends on all the events in
78 ref_ptr
<soft_event
> sev
= transfer(
79 new soft_event(evs
[0]->ctx
, { evs
, evs
+ num_evs
}, true));
91 clGetEventInfo(cl_event ev
, cl_event_info param
,
92 size_t size
, void *buf
, size_t *size_ret
) {
94 return CL_INVALID_EVENT
;
97 case CL_EVENT_COMMAND_QUEUE
:
98 return scalar_property
<cl_command_queue
>(buf
, size
, size_ret
, ev
->queue());
100 case CL_EVENT_CONTEXT
:
101 return scalar_property
<cl_context
>(buf
, size
, size_ret
, &ev
->ctx
);
103 case CL_EVENT_COMMAND_TYPE
:
104 return scalar_property
<cl_command_type
>(buf
, size
, size_ret
, ev
->command());
106 case CL_EVENT_COMMAND_EXECUTION_STATUS
:
107 return scalar_property
<cl_int
>(buf
, size
, size_ret
, ev
->status());
109 case CL_EVENT_REFERENCE_COUNT
:
110 return scalar_property
<cl_uint
>(buf
, size
, size_ret
, ev
->ref_count());
113 return CL_INVALID_VALUE
;
118 clSetEventCallback(cl_event ev
, cl_int type
,
119 void (CL_CALLBACK
*pfn_event_notify
)(cl_event
, cl_int
,
121 void *user_data
) try {
123 throw error(CL_INVALID_EVENT
);
125 if (!pfn_event_notify
|| type
!= CL_COMPLETE
)
126 throw error(CL_INVALID_VALUE
);
128 // Create a temporary soft event that depends on ev, with
129 // pfn_event_notify as completion action.
130 ref_ptr
<soft_event
> sev
= transfer(
131 new soft_event(ev
->ctx
, { ev
}, true,
134 pfn_event_notify(ev
, ev
->status(), user_data
);
144 clRetainEvent(cl_event ev
) {
146 return CL_INVALID_EVENT
;
153 clReleaseEvent(cl_event ev
) {
155 return CL_INVALID_EVENT
;
164 clEnqueueMarker(cl_command_queue q
, cl_event
*ev
) try {
166 throw error(CL_INVALID_COMMAND_QUEUE
);
169 throw error(CL_INVALID_VALUE
);
171 *ev
= new hard_event(*q
, CL_COMMAND_MARKER
, {});
180 clEnqueueBarrier(cl_command_queue q
) {
182 return CL_INVALID_COMMAND_QUEUE
;
184 // No need to do anything, q preserves data ordering strictly.
189 clEnqueueWaitForEvents(cl_command_queue q
, cl_uint num_evs
,
190 const cl_event
*evs
) try {
192 throw error(CL_INVALID_COMMAND_QUEUE
);
194 if (!num_evs
|| !evs
)
195 throw error(CL_INVALID_VALUE
);
197 std::for_each(evs
, evs
+ num_evs
, [&](const cl_event ev
) {
199 throw error(CL_INVALID_EVENT
);
201 if (&ev
->ctx
!= &q
->ctx
)
202 throw error(CL_INVALID_CONTEXT
);
205 // Create a hard event that depends on the events in the wait list:
206 // subsequent commands in the same queue will be implicitly
207 // serialized with respect to it -- hard events always are.
208 ref_ptr
<hard_event
> hev
= transfer(
209 new hard_event(*q
, 0, { evs
, evs
+ num_evs
}));
218 clGetEventProfilingInfo(cl_event ev
, cl_profiling_info param
,
219 size_t size
, void *buf
, size_t *size_ret
) try {
220 hard_event
*hev
= dynamic_cast<hard_event
*>(ev
);
223 return CL_INVALID_EVENT
;
225 if (!hev
|| hev
->status() != CL_COMPLETE
)
226 return CL_PROFILING_INFO_NOT_AVAILABLE
;
229 case CL_PROFILING_COMMAND_QUEUED
:
230 return scalar_property
<cl_ulong
>(buf
, size
, size_ret
, hev
->time_queued());
232 case CL_PROFILING_COMMAND_SUBMIT
:
233 return scalar_property
<cl_ulong
>(buf
, size
, size_ret
, hev
->time_submit());
235 case CL_PROFILING_COMMAND_START
:
236 return scalar_property
<cl_ulong
>(buf
, size
, size_ret
, hev
->time_start());
238 case CL_PROFILING_COMMAND_END
:
239 return scalar_property
<cl_ulong
>(buf
, size
, size_ret
, hev
->time_end());
242 return CL_INVALID_VALUE
;
245 } catch (lazy
<cl_ulong
>::undefined_error
&e
) {
246 return CL_PROFILING_INFO_NOT_AVAILABLE
;
253 clFinish(cl_command_queue q
) try {
255 throw error(CL_INVALID_COMMAND_QUEUE
);
257 // Create a temporary hard event -- it implicitly depends on all
258 // the previously queued hard events.
259 ref_ptr
<hard_event
> hev
= transfer(new hard_event(*q
, 0, { }));