aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancisco Jerez <[email protected]>2015-05-09 14:47:38 +0300
committerEmil Velikov <[email protected]>2015-05-20 22:06:06 +0100
commitf25af5317f7acb29503df8685c501af0daa2b8a1 (patch)
tree6e12a0c191de0f61a9c5b032a58c63102f599d2f
parent1353ba53977e9a531fcadf3c04ad4c69c32c22c0 (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.cpp43
-rw-r--r--src/gallium/state_trackers/clover/core/event.hpp3
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;