diff options
author | Tom Stellard <[email protected]> | 2015-03-26 19:33:24 +0000 |
---|---|---|
committer | Emil Velikov <[email protected]> | 2015-05-20 22:05:52 +0100 |
commit | 097e70202b6ae5b07303274c1d5087f94bd3cf06 (patch) | |
tree | aa74accbbade1fcd1ce63609c5a6cd8097572958 /src | |
parent | 5bb7ee4fd605da1d9ca3b4aa2b6a7a28e214e0f6 (diff) |
clover: Fix a bug with multi-threaded events v2
It was possible for some events never to get triggered if one thread
was creating events and another threads was waiting for them.
This patch consolidates soft_event::wait() and hard_event::wait()
into event::wait() so that hard_event objects will now wait for
all their dependencies to be submitted before flushing the command
queue.
v2:
- Rename variables
- Use mutable varibales so we can keep event::wait() const
- Open code signalled() call so mutex can be atted to signalled
without deadlocking.
CC: 10.5 <[email protected]>
Reviewed-by: Francisco Jerez <[email protected]>
(cherry picked from commit 9c4dc98b298c74015f2a7c21571bccf0a5b6cc98)
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/state_trackers/clover/core/event.cpp | 15 | ||||
-rw-r--r-- | src/gallium/state_trackers/clover/core/event.hpp | 5 |
2 files changed, 17 insertions, 3 deletions
diff --git a/src/gallium/state_trackers/clover/core/event.cpp b/src/gallium/state_trackers/clover/core/event.cpp index 58de8884457..55793031ad1 100644 --- a/src/gallium/state_trackers/clover/core/event.cpp +++ b/src/gallium/state_trackers/clover/core/event.cpp @@ -39,6 +39,7 @@ event::~event() { void event::trigger() { if (!--wait_count) { + cv.notify_all(); action_ok(*this); while (!_chain.empty()) { @@ -73,6 +74,15 @@ event::chain(event &ev) { ev.deps.push_back(*this); } +void +event::wait() const { + for (event &ev : deps) + ev.wait(); + + std::unique_lock<std::mutex> lock(mutex); + cv.wait(lock, [=]{ return !wait_count; }); +} + hard_event::hard_event(command_queue &q, cl_command_type command, const ref_vector<event> &deps, action action) : event(q.context(), deps, profile(q, action), [](event &ev){}), @@ -120,6 +130,8 @@ void hard_event::wait() const { pipe_screen *screen = queue()->device().pipe; + event::wait(); + if (status() == CL_QUEUED) queue()->flush(); @@ -207,8 +219,7 @@ soft_event::command() const { void soft_event::wait() const { - for (event &ev : deps) - ev.wait(); + event::wait(); if (status() != CL_COMPLETE) throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); diff --git a/src/gallium/state_trackers/clover/core/event.hpp b/src/gallium/state_trackers/clover/core/event.hpp index 0e1359a3d20..e1727b8add5 100644 --- a/src/gallium/state_trackers/clover/core/event.hpp +++ b/src/gallium/state_trackers/clover/core/event.hpp @@ -23,6 +23,7 @@ #ifndef CLOVER_CORE_EVENT_HPP #define CLOVER_CORE_EVENT_HPP +#include <condition_variable> #include <functional> #include "core/object.hpp" @@ -68,7 +69,7 @@ namespace clover { virtual cl_int status() const = 0; virtual command_queue *queue() const = 0; virtual cl_command_type command() const = 0; - virtual void wait() const = 0; + virtual void wait() const; const intrusive_ref<clover::context> context; @@ -83,6 +84,8 @@ namespace clover { action action_ok; action action_fail; std::vector<intrusive_ref<event>> _chain; + mutable std::condition_variable cv; + mutable std::mutex mutex; }; /// |