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 "core/event.hpp" 24 #include "pipe/p_screen.h" 25 26 using namespace clover; 27 28 _cl_event::_cl_event(clover::context &ctx, 29 std::vector<clover::event *> deps, 30 action action_ok, action action_fail) : 31 ctx(ctx), __status(0), wait_count(1), 32 action_ok(action_ok), action_fail(action_fail) { 33 for (auto ev : deps) 34 ev->chain(this); 35 } 36 37 _cl_event::~_cl_event() { 38 } 39 40 void 41 _cl_event::trigger() { 42 if (!--wait_count) { 43 action_ok(*this); 44 45 while (!__chain.empty()) { 46 __chain.back()->trigger(); 47 __chain.pop_back(); 48 } 49 } 50 } 51 52 void 53 _cl_event::abort(cl_int status) { 54 __status = status; 55 action_fail(*this); 56 57 while (!__chain.empty()) { 58 __chain.back()->abort(status); 59 __chain.pop_back(); 60 } 61 } 62 63 bool 64 _cl_event::signalled() const { 65 return !wait_count; 66 } 67 68 void 69 _cl_event::chain(clover::event *ev) { 70 if (wait_count) { 71 ev->wait_count++; 72 __chain.push_back(ev); 73 ev->deps.push_back(this); 74 } 75 } 76 77 hard_event::hard_event(clover::command_queue &q, cl_command_type command, 78 std::vector<clover::event *> deps, action action) : 79 _cl_event(q.ctx, deps, action, [](event &ev){}), 80 __queue(q), __command(command), __fence(NULL) { 81 q.sequence(this); 82 trigger(); 83 } 84 85 hard_event::~hard_event() { 86 pipe_screen *screen = queue()->dev.pipe; 87 screen->fence_reference(screen, &__fence, NULL); 88 } 89 90 cl_int 91 hard_event::status() const { 92 pipe_screen *screen = queue()->dev.pipe; 93 94 if (__status < 0) 95 return __status; 96 97 else if (!__fence) 98 return CL_QUEUED; 99 100 else if (!screen->fence_signalled(screen, __fence)) 101 return CL_SUBMITTED; 102 103 else 104 return CL_COMPLETE; 105 } 106 107 cl_command_queue 108 hard_event::queue() const { 109 return &__queue; 110 } 111 112 cl_command_type 113 hard_event::command() const { 114 return __command; 115 } 116 117 void 118 hard_event::wait() const { 119 pipe_screen *screen = queue()->dev.pipe; 120 121 if (status() == CL_QUEUED) 122 queue()->flush(); 123 124 if (!__fence || 125 !screen->fence_finish(screen, __fence, PIPE_TIMEOUT_INFINITE)) 126 throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); 127 } 128 129 void 130 hard_event::fence(pipe_fence_handle *fence) { 131 pipe_screen *screen = queue()->dev.pipe; 132 screen->fence_reference(screen, &__fence, fence); 133 } 134 135 soft_event::soft_event(clover::context &ctx, 136 std::vector<clover::event *> deps, 137 bool __trigger, action action) : 138 _cl_event(ctx, deps, action, action) { 139 if (__trigger) 140 trigger(); 141 } 142 143 cl_int 144 soft_event::status() const { 145 if (__status < 0) 146 return __status; 147 148 else if (!signalled() || 149 any_of([](const ref_ptr<event> &ev) { 150 return ev->status() != CL_COMPLETE; 151 }, deps.begin(), deps.end())) 152 return CL_SUBMITTED; 153 154 else 155 return CL_COMPLETE; 156 } 157 158 cl_command_queue 159 soft_event::queue() const { 160 return NULL; 161 } 162 163 cl_command_type 164 soft_event::command() const { 165 return CL_COMMAND_USER; 166 } 167 168 void 169 soft_event::wait() const { 170 for (auto ev : deps) 171 ev->wait(); 172 173 if (status() != CL_COMPLETE) 174 throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); 175 } 176