diff options
author | Francisco Jerez <[email protected]> | 2015-05-09 14:47:38 +0300 |
---|---|---|
committer | Emil Velikov <[email protected]> | 2015-05-20 22:06:06 +0100 |
commit | f25af5317f7acb29503df8685c501af0daa2b8a1 (patch) | |
tree | 6e12a0c191de0f61a9c5b032a58c63102f599d2f | |
parent | 1353ba53977e9a531fcadf3c04ad4c69c32c22c0 (diff) |
clover: Refactor event::trigger and ::abort to prevent deadlock and reentrancy issues.
Refactor ::trigger and ::abort to split out the operations that access
concurrently modified data members and require locking from the
recursive and possibly re-entrant part of these methods. This will
avoid some deadlock situations when locking is implemented.
Tested-by: Tom Stellard <[email protected]>
CC: 10.5 <[email protected]>
(cherry picked from commit 2232b929fd9ca6f00c8dab9dc45c386986be922d)
-rw-r--r-- | src/gallium/state_trackers/clover/core/event.cpp | 43 | ||||
-rw-r--r-- | src/gallium/state_trackers/clover/core/event.hpp | 3 |
2 files changed, 34 insertions, 12 deletions
diff --git a/src/gallium/state_trackers/clover/core/event.cpp b/src/gallium/state_trackers/clover/core/event.cpp index 55793031ad1..d03e0b42ba3 100644 --- a/src/gallium/state_trackers/clover/core/event.cpp +++ b/src/gallium/state_trackers/clover/core/event.cpp @@ -36,28 +36,47 @@ event::event(clover::context &ctx, const ref_vector<event> &deps, event::~event() { } +std::vector<intrusive_ref<event>> +event::trigger_self() { + std::vector<intrusive_ref<event>> evs; + + if (!--wait_count) + std::swap(_chain, evs); + + return evs; +} + void event::trigger() { - if (!--wait_count) { - cv.notify_all(); - action_ok(*this); + auto evs = trigger_self(); - while (!_chain.empty()) { - _chain.back()().trigger(); - _chain.pop_back(); - } + if (signalled()) { + action_ok(*this); + cv.notify_all(); } + + for (event &ev : evs) + ev.trigger(); +} + +std::vector<intrusive_ref<event>> +event::abort_self(cl_int status) { + std::vector<intrusive_ref<event>> evs; + + _status = status; + std::swap(_chain, evs); + + return evs; } void event::abort(cl_int status) { - _status = status; + auto evs = abort_self(status); + action_fail(*this); - while (!_chain.empty()) { - _chain.back()().abort(status); - _chain.pop_back(); - } + for (event &ev : evs) + ev.abort(status); } bool diff --git a/src/gallium/state_trackers/clover/core/event.hpp b/src/gallium/state_trackers/clover/core/event.hpp index e1727b8add5..32acb2d1bca 100644 --- a/src/gallium/state_trackers/clover/core/event.hpp +++ b/src/gallium/state_trackers/clover/core/event.hpp @@ -80,6 +80,9 @@ namespace clover { std::vector<intrusive_ref<event>> deps; private: + std::vector<intrusive_ref<event>> trigger_self(); + std::vector<intrusive_ref<event>> abort_self(cl_int status); + unsigned wait_count; action action_ok; action action_fail; |