• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
70       virtual command_queue *queue() const = 0;
71       virtual cl_command_type command() const = 0;
72       void wait_signalled() const;
73       virtual void wait() const;
74 
fence() const75       virtual struct pipe_fence_handle *fence() const {
76          return NULL;
77       }
78 
79       const intrusive_ref<clover::context> context;
80 
81    protected:
82       void chain(event &ev);
83 
84       mutable std::vector<intrusive_ref<event>> deps;
85 
86    private:
87       std::vector<intrusive_ref<event>> trigger_self();
88       std::vector<intrusive_ref<event>> abort_self(cl_int status);
89       unsigned wait_count() const;
90 
91       unsigned _wait_count;
92       cl_int _status;
93       action action_ok;
94       action action_fail;
95       std::vector<intrusive_ref<event>> _chain;
96       mutable std::condition_variable cv;
97       mutable std::mutex mutex;
98    };
99 
100    ///
101    /// Class that represents a task executed by a command queue.
102    ///
103    /// Similar to a normal clover::event.  In addition it's associated
104    /// with a given command queue \a q and a given OpenCL \a command.
105    /// hard_event instances created for the same queue are implicitly
106    /// ordered with respect to each other, and they are implicitly
107    /// triggered on construction.
108    ///
109    /// A hard_event is considered complete when the associated
110    /// hardware task finishes execution.
111    ///
112    class hard_event : public event {
113    public:
114       hard_event(command_queue &q, cl_command_type command,
115                  const ref_vector<event> &deps,
__anon44d0b66b0102(event &)116                  action action = [](event &){});
117       ~hard_event();
118 
119       virtual cl_int status() const;
120       virtual command_queue *queue() const;
121       virtual cl_command_type command() const;
122       virtual void wait() const;
123 
124       const lazy<cl_ulong> &time_queued() const;
125       const lazy<cl_ulong> &time_submit() const;
126       const lazy<cl_ulong> &time_start() const;
127       const lazy<cl_ulong> &time_end() const;
128 
129       friend class command_queue;
130 
fence() const131       virtual struct pipe_fence_handle *fence() const {
132          return _fence;
133       }
134 
135    private:
136       virtual void fence(pipe_fence_handle *fence);
137       action profile(command_queue &q, const action &action) const;
138 
139       const intrusive_ref<command_queue> _queue;
140       cl_command_type _command;
141       pipe_fence_handle *_fence;
142       lazy<cl_ulong> _time_queued, _time_submit, _time_start, _time_end;
143    };
144 
145    ///
146    /// Class that represents a software event.
147    ///
148    /// A soft_event is not associated with any specific hardware task
149    /// or command queue.  It's considered complete as soon as all its
150    /// dependencies finish execution.
151    ///
152    class soft_event : public event {
153    public:
154       soft_event(clover::context &ctx, const ref_vector<event> &deps,
__anon44d0b66b0202(event &)155                  bool trigger, action action = [](event &){});
156 
157       virtual cl_int status() const;
158       virtual command_queue *queue() const;
159       virtual cl_command_type command() const;
160       virtual void wait() const;
161    };
162 }
163 
164 #endif
165