Home | History | Annotate | Download | only in api
      1 //
      2 // Copyright 2012 Francisco Jerez
      3 //
      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:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     18 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     19 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20 // SOFTWARE.
     21 //
     22 
     23 #include "api/util.hpp"
     24 #include "core/event.hpp"
     25 
     26 using namespace clover;
     27 
     28 PUBLIC cl_event
     29 clCreateUserEvent(cl_context ctx, cl_int *errcode_ret) try {
     30    if (!ctx)
     31       throw error(CL_INVALID_CONTEXT);
     32 
     33    ret_error(errcode_ret, CL_SUCCESS);
     34    return new soft_event(*ctx, {}, false);
     35 
     36 } catch(error &e) {
     37    ret_error(errcode_ret, e);
     38    return NULL;
     39 }
     40 
     41 PUBLIC cl_int
     42 clSetUserEventStatus(cl_event ev, cl_int status) {
     43    if (!dynamic_cast<soft_event *>(ev))
     44       return CL_INVALID_EVENT;
     45 
     46    if (status > 0)
     47       return CL_INVALID_VALUE;
     48 
     49    if (ev->status() <= 0)
     50       return CL_INVALID_OPERATION;
     51 
     52    if (status)
     53       ev->abort(status);
     54    else
     55       ev->trigger();
     56 
     57    return CL_SUCCESS;
     58 }
     59 
     60 PUBLIC cl_int
     61 clWaitForEvents(cl_uint num_evs, const cl_event *evs) try {
     62    if (!num_evs || !evs)
     63       throw error(CL_INVALID_VALUE);
     64 
     65    std::for_each(evs, evs + num_evs, [&](const cl_event ev) {
     66          if (!ev)
     67             throw error(CL_INVALID_EVENT);
     68 
     69          if (&ev->ctx != &evs[0]->ctx)
     70             throw error(CL_INVALID_CONTEXT);
     71 
     72          if (ev->status() < 0)
     73             throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);
     74       });
     75 
     76    // Create a temporary soft event that depends on all the events in
     77    // the wait list
     78    ref_ptr<soft_event> sev = transfer(
     79       new soft_event(evs[0]->ctx, { evs, evs + num_evs }, true));
     80 
     81    // ...and wait on it.
     82    sev->wait();
     83 
     84    return CL_SUCCESS;
     85 
     86 } catch(error &e) {
     87    return e.get();
     88 }
     89 
     90 PUBLIC cl_int
     91 clGetEventInfo(cl_event ev, cl_event_info param,
     92                size_t size, void *buf, size_t *size_ret) {
     93    if (!ev)
     94       return CL_INVALID_EVENT;
     95 
     96    switch (param) {
     97    case CL_EVENT_COMMAND_QUEUE:
     98       return scalar_property<cl_command_queue>(buf, size, size_ret, ev->queue());
     99 
    100    case CL_EVENT_CONTEXT:
    101       return scalar_property<cl_context>(buf, size, size_ret, &ev->ctx);
    102 
    103    case CL_EVENT_COMMAND_TYPE:
    104       return scalar_property<cl_command_type>(buf, size, size_ret, ev->command());
    105 
    106    case CL_EVENT_COMMAND_EXECUTION_STATUS:
    107       return scalar_property<cl_int>(buf, size, size_ret, ev->status());
    108 
    109    case CL_EVENT_REFERENCE_COUNT:
    110       return scalar_property<cl_uint>(buf, size, size_ret, ev->ref_count());
    111 
    112    default:
    113       return CL_INVALID_VALUE;
    114    }
    115 }
    116 
    117 PUBLIC cl_int
    118 clSetEventCallback(cl_event ev, cl_int type,
    119                    void (CL_CALLBACK *pfn_event_notify)(cl_event, cl_int,
    120                                                         void *),
    121                    void *user_data) try {
    122    if (!ev)
    123       throw error(CL_INVALID_EVENT);
    124 
    125    if (!pfn_event_notify || type != CL_COMPLETE)
    126       throw error(CL_INVALID_VALUE);
    127 
    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,
    132                      [=](event &) {
    133                         ev->wait();
    134                         pfn_event_notify(ev, ev->status(), user_data);
    135                      }));
    136 
    137    return CL_SUCCESS;
    138 
    139 } catch(error &e) {
    140    return e.get();
    141 }
    142 
    143 PUBLIC cl_int
    144 clRetainEvent(cl_event ev) {
    145    if (!ev)
    146       return CL_INVALID_EVENT;
    147 
    148    ev->retain();
    149    return CL_SUCCESS;
    150 }
    151 
    152 PUBLIC cl_int
    153 clReleaseEvent(cl_event ev) {
    154    if (!ev)
    155       return CL_INVALID_EVENT;
    156 
    157    if (ev->release())
    158       delete ev;
    159 
    160    return CL_SUCCESS;
    161 }
    162 
    163 PUBLIC cl_int
    164 clEnqueueMarker(cl_command_queue q, cl_event *ev) try {
    165    if (!q)
    166       throw error(CL_INVALID_COMMAND_QUEUE);
    167 
    168    if (!ev)
    169       throw error(CL_INVALID_VALUE);
    170 
    171    *ev = new hard_event(*q, CL_COMMAND_MARKER, {});
    172 
    173    return CL_SUCCESS;
    174 
    175 } catch(error &e) {
    176    return e.get();
    177 }
    178 
    179 PUBLIC cl_int
    180 clEnqueueBarrier(cl_command_queue q) {
    181    if (!q)
    182       return CL_INVALID_COMMAND_QUEUE;
    183 
    184    // No need to do anything, q preserves data ordering strictly.
    185    return CL_SUCCESS;
    186 }
    187 
    188 PUBLIC cl_int
    189 clEnqueueWaitForEvents(cl_command_queue q, cl_uint num_evs,
    190                        const cl_event *evs) try {
    191    if (!q)
    192       throw error(CL_INVALID_COMMAND_QUEUE);
    193 
    194    if (!num_evs || !evs)
    195       throw error(CL_INVALID_VALUE);
    196 
    197    std::for_each(evs, evs + num_evs, [&](const cl_event ev) {
    198          if (!ev)
    199             throw error(CL_INVALID_EVENT);
    200 
    201          if (&ev->ctx != &q->ctx)
    202             throw error(CL_INVALID_CONTEXT);
    203       });
    204 
    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 }));
    210 
    211    return CL_SUCCESS;
    212 
    213 } catch(error &e) {
    214    return e.get();
    215 }
    216 
    217 PUBLIC cl_int
    218 clGetEventProfilingInfo(cl_event ev, cl_profiling_info param,
    219                         size_t size, void *buf, size_t *size_ret) {
    220    return CL_PROFILING_INFO_NOT_AVAILABLE;
    221 }
    222 
    223 PUBLIC cl_int
    224 clFinish(cl_command_queue q) try {
    225    if (!q)
    226       throw error(CL_INVALID_COMMAND_QUEUE);
    227 
    228    // Create a temporary hard event -- it implicitly depends on all
    229    // the previously queued hard events.
    230    ref_ptr<hard_event> hev = transfer(new hard_event(*q, 0, { }));
    231 
    232    // And wait on it.
    233    hev->wait();
    234 
    235    return CL_SUCCESS;
    236 
    237 } catch(error &e) {
    238    return e.get();
    239 }
    240