Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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 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.
  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.