clover: Refactor event::trigger and ::abort to prevent deadlock and reentrancy issues.
authorFrancisco Jerez <currojerez@riseup.net>
Sat, 9 May 2015 11:47:38 +0000 (14:47 +0300)
committerFrancisco Jerez <currojerez@riseup.net>
Tue, 12 May 2015 12:47:57 +0000 (15:47 +0300)
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 <thomas.stellard@amd.com>
CC: 10.5 <mesa-stable@lists.freedesktop.org>
src/gallium/state_trackers/clover/core/event.cpp
src/gallium/state_trackers/clover/core/event.hpp

index 55793031ad188ea982cd92fc92ab0110c863cbee..d03e0b42ba32403be444a736af3f0ad1c20c0084 100644 (file)
@@ -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
index 0914842ad1b2a7f7741823e957105c9a51dcc3b9..f638c5bcf15ffcabbb55f5b6c6a1ab8ea49fce50 100644 (file)
@@ -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;