summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorFrancisco Jerez <[email protected]>2015-05-09 14:47:38 +0300
committerFrancisco Jerez <[email protected]>2015-05-12 15:47:57 +0300
commit2232b929fd9ca6f00c8dab9dc45c386986be922d (patch)
treefb57714e272144a6d65dbbdcb3c65f2ce220df77 /src/gallium
parentd91d6b3f03f36d4cfef5e9aacac1534f12372c9f (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.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 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;