diff options
author | Francisco Jerez <[email protected]> | 2015-05-09 14:47:38 +0300 |
---|---|---|
committer | Francisco Jerez <[email protected]> | 2015-05-12 15:47:57 +0300 |
commit | 2232b929fd9ca6f00c8dab9dc45c386986be922d (patch) | |
tree | fb57714e272144a6d65dbbdcb3c65f2ce220df77 /src/gallium | |
parent | d91d6b3f03f36d4cfef5e9aacac1534f12372c9f (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]>
Diffstat (limited to 'src/gallium')
-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 0914842ad1b..f638c5bcf15 100644 --- a/src/gallium/state_trackers/clover/core/event.hpp +++ b/src/gallium/state_trackers/clover/core/event.hpp @@ -84,6 +84,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; |