OSDN Git Service

clover: Fix a bug with multi-threaded events v2
[android-x86/external-mesa.git] / src / gallium / state_trackers / clover / core / event.hpp
1 //
2 // Copyright 2012 Francisco Jerez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22
23 #ifndef CLOVER_CORE_EVENT_HPP
24 #define CLOVER_CORE_EVENT_HPP
25
26 #include <condition_variable>
27 #include <functional>
28
29 #include "core/object.hpp"
30 #include "core/queue.hpp"
31 #include "core/timestamp.hpp"
32 #include "util/lazy.hpp"
33
34 namespace clover {
35    ///
36    /// Class that represents a task that might be executed
37    /// asynchronously at some point in the future.
38    ///
39    /// An event consists of a list of dependencies, a boolean
40    /// signalled() flag, and an associated task.  An event is
41    /// considered signalled as soon as all its dependencies (if any)
42    /// are signalled as well, and the trigger() method is called; at
43    /// that point the associated task will be started through the
44    /// specified \a action_ok.  If the abort() method is called
45    /// instead, the specified \a action_fail is executed and the
46    /// associated task will never be started.  Dependent events will
47    /// be aborted recursively.
48    ///
49    /// The execution status of the associated task can be queried
50    /// using the status() method, and it can be waited for completion
51    /// using the wait() method.
52    ///
53    class event : public ref_counter, public _cl_event {
54    public:
55       typedef std::function<void (event &)> action;
56
57       event(clover::context &ctx, const ref_vector<event> &deps,
58             action action_ok, action action_fail);
59       virtual ~event();
60
61       event(const event &ev) = delete;
62       event &
63       operator=(const event &ev) = delete;
64
65       void trigger();
66       void abort(cl_int status);
67       bool signalled() const;
68
69       virtual cl_int status() const = 0;
70       virtual command_queue *queue() const = 0;
71       virtual cl_command_type command() const = 0;
72       virtual void wait() const;
73
74       virtual struct pipe_fence_handle *fence() const {
75          return NULL;
76       }
77
78       const intrusive_ref<clover::context> context;
79
80    protected:
81       void chain(event &ev);
82
83       cl_int _status;
84       std::vector<intrusive_ref<event>> deps;
85
86    private:
87       unsigned wait_count;
88       action action_ok;
89       action action_fail;
90       std::vector<intrusive_ref<event>> _chain;
91       mutable std::condition_variable cv;
92       mutable std::mutex mutex;
93    };
94
95    ///
96    /// Class that represents a task executed by a command queue.
97    ///
98    /// Similar to a normal clover::event.  In addition it's associated
99    /// with a given command queue \a q and a given OpenCL \a command.
100    /// hard_event instances created for the same queue are implicitly
101    /// ordered with respect to each other, and they are implicitly
102    /// triggered on construction.
103    ///
104    /// A hard_event is considered complete when the associated
105    /// hardware task finishes execution.
106    ///
107    class hard_event : public event {
108    public:
109       hard_event(command_queue &q, cl_command_type command,
110                  const ref_vector<event> &deps,
111                  action action = [](event &){});
112       ~hard_event();
113
114       virtual cl_int status() const;
115       virtual command_queue *queue() const;
116       virtual cl_command_type command() const;
117       virtual void wait() const;
118
119       const lazy<cl_ulong> &time_queued() const;
120       const lazy<cl_ulong> &time_submit() const;
121       const lazy<cl_ulong> &time_start() const;
122       const lazy<cl_ulong> &time_end() const;
123
124       friend class command_queue;
125
126       virtual struct pipe_fence_handle *fence() const {
127          return _fence;
128       }
129
130    private:
131       virtual void fence(pipe_fence_handle *fence);
132       action profile(command_queue &q, const action &action) const;
133
134       const intrusive_ref<command_queue> _queue;
135       cl_command_type _command;
136       pipe_fence_handle *_fence;
137       lazy<cl_ulong> _time_queued, _time_submit, _time_start, _time_end;
138    };
139
140    ///
141    /// Class that represents a software event.
142    ///
143    /// A soft_event is not associated with any specific hardware task
144    /// or command queue.  It's considered complete as soon as all its
145    /// dependencies finish execution.
146    ///
147    class soft_event : public event {
148    public:
149       soft_event(clover::context &ctx, const ref_vector<event> &deps,
150                  bool trigger, action action = [](event &){});
151
152       virtual cl_int status() const;
153       virtual command_queue *queue() const;
154       virtual cl_command_type command() const;
155       virtual void wait() const;
156    };
157 }
158
159 #endif