blob: 5de4423e7f131a141c3c5cfa91840ae022755ea7 [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#ifndef AOS_EVENTS_SHM_EVENT_LOOP_H_
2#define AOS_EVENTS_SHM_EVENT_LOOP_H_
3
Alex Perrycb7da4b2019-08-28 19:35:56 -07004#include <vector>
5
Brian Silverman5120afb2020-01-31 17:44:35 -08006#include "absl/types/span.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07007
Alex Perrycb7da4b2019-08-28 19:35:56 -07008#include "aos/events/epoll.h"
9#include "aos/events/event_loop.h"
Austin Schuh39788ff2019-12-01 18:22:57 -080010#include "aos/events/event_loop_generated.h"
Adam Snaiderc8b7e752023-09-14 14:27:53 -070011#include "aos/ipc_lib/shm_base.h"
Austin Schuh5ca13112021-02-07 22:06:53 -080012#include "aos/ipc_lib/signalfd.h"
Austin Schuh3054f5f2021-07-21 15:38:01 -070013#include "aos/stl_mutex/stl_mutex.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070014
Austin Schuh99f7c6a2024-06-25 22:07:44 -070015ABSL_DECLARE_FLAG(std::string, application_name);
Jim Ostrowski2192ddb2020-06-24 19:07:31 -070016
Alex Perrycb7da4b2019-08-28 19:35:56 -070017namespace aos {
Brian Silverman148d43d2020-06-07 18:19:22 -050018namespace shm_event_loop_internal {
Alex Perrycb7da4b2019-08-28 19:35:56 -070019
Brian Silverman148d43d2020-06-07 18:19:22 -050020class ShmWatcherState;
21class ShmTimerHandler;
22class ShmPhasedLoopHandler;
Austin Schuh39788ff2019-12-01 18:22:57 -080023class ShmSender;
Austin Schuh432784f2020-06-23 17:27:35 -070024class SimpleShmFetcher;
Austin Schuh39788ff2019-12-01 18:22:57 -080025class ShmFetcher;
Brian Silvermane1fe2512022-08-14 23:18:50 -070026class ShmExitHandle;
Alex Perrycb7da4b2019-08-28 19:35:56 -070027
Brian Silverman148d43d2020-06-07 18:19:22 -050028} // namespace shm_event_loop_internal
Alex Perrycb7da4b2019-08-28 19:35:56 -070029
Brian Silverman4f4e0612020-08-12 19:54:41 -070030// Concrete implementation of EventLoop that is built from queues running out of
31// shared memory.
Alex Perrycb7da4b2019-08-28 19:35:56 -070032//
Austin Schuh39788ff2019-12-01 18:22:57 -080033// TODO(austin): Timing reports break multiple threads. Need to add back in a
34// mutex.
35// This object must be interacted with from one thread, but the Senders
36// and Fetchers may be used from multiple threads afterwords (as long as their
Alex Perrycb7da4b2019-08-28 19:35:56 -070037// destructors are called back in one thread again)
38class ShmEventLoop : public EventLoop {
39 public:
Austin Schuhcaa2a5d2020-11-01 22:38:20 -080040 ShmEventLoop(const Flatbuffer<Configuration> &configuration)
41 : ShmEventLoop(&configuration.message()) {}
Alex Perrycb7da4b2019-08-28 19:35:56 -070042 ShmEventLoop(const Configuration *configuration);
Austin Schuhad9e5eb2021-11-19 20:33:55 -080043 ShmEventLoop(const ShmEventLoop &) = delete;
Alex Perrycb7da4b2019-08-28 19:35:56 -070044 ~ShmEventLoop() override;
45
Austin Schuhad9e5eb2021-11-19 20:33:55 -080046 void operator=(ShmEventLoop const &) = delete;
47
Austin Schuh39788ff2019-12-01 18:22:57 -080048 // Runs the event loop until Exit is called, or ^C is caught.
James Kuszmaul9f998082024-05-23 15:37:35 -070049 Result<void> Run();
50 // Exits the event loop. async-signal-safe (see
51 // https://man7.org/linux/man-pages/man7/signal-safety.7.html).
52 // Will result in Run() returning a successful result when called.
Austin Schuh39788ff2019-12-01 18:22:57 -080053 void Exit();
54
James Kuszmaul9f998082024-05-23 15:37:35 -070055 // Exits the event loop with the provided status. Thread-safe, but not
56 // async-safe.
57 void ExitWithStatus(Result<void> status = {});
58
59 // Constructs an exit handle for the EventLoop. The provided ExitHandle uses
60 // ExitWithStatus().
Brian Silvermane1fe2512022-08-14 23:18:50 -070061 std::unique_ptr<ExitHandle> MakeExitHandle();
62
Stephan Pleines559fa6c2022-01-06 17:23:51 -080063 aos::monotonic_clock::time_point monotonic_now() const override {
Alex Perrycb7da4b2019-08-28 19:35:56 -070064 return aos::monotonic_clock::now();
65 }
Stephan Pleines559fa6c2022-01-06 17:23:51 -080066 aos::realtime_clock::time_point realtime_now() const override {
Alex Perrycb7da4b2019-08-28 19:35:56 -070067 return aos::realtime_clock::now();
68 }
69
70 std::unique_ptr<RawSender> MakeRawSender(const Channel *channel) override;
71 std::unique_ptr<RawFetcher> MakeRawFetcher(const Channel *channel) override;
72
73 void MakeRawWatcher(
74 const Channel *channel,
75 std::function<void(const Context &context, const void *message)> watcher)
76 override;
Brian Silverman6b8a3c32020-03-06 11:26:14 -080077 void MakeRawNoArgWatcher(
78 const Channel *channel,
79 std::function<void(const Context &context)> watcher) override;
Alex Perrycb7da4b2019-08-28 19:35:56 -070080
81 TimerHandler *AddTimer(std::function<void()> callback) override;
Brian Silverman148d43d2020-06-07 18:19:22 -050082 PhasedLoopHandler *AddPhasedLoop(std::function<void(int)> callback,
83 const monotonic_clock::duration interval,
84 const monotonic_clock::duration offset =
85 std::chrono::seconds(0)) override;
Alex Perrycb7da4b2019-08-28 19:35:56 -070086
87 void OnRun(std::function<void()> on_run) override;
Alex Perrycb7da4b2019-08-28 19:35:56 -070088
89 void SetRuntimeRealtimePriority(int priority) override;
Brian Silverman6a54ff32020-04-28 16:41:39 -070090 void SetRuntimeAffinity(const cpu_set_t &cpuset) override;
Alex Perrycb7da4b2019-08-28 19:35:56 -070091
James Kuszmaul57c2baa2020-01-19 14:52:52 -080092 void set_name(const std::string_view name) override;
James Kuszmaul3ae42262019-11-08 12:33:41 -080093 const std::string_view name() const override { return name_; }
Austin Schuh217a9782019-12-21 23:02:50 -080094 const Node *node() const override { return node_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070095
Austin Schuh65493d62022-08-17 15:10:37 -070096 int runtime_realtime_priority() const override { return priority_; }
97 const cpu_set_t &runtime_affinity() const override { return affinity_; }
Austin Schuh83c7f702021-01-19 22:36:29 -080098 const UUID &boot_uuid() const override { return boot_uuid_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070099
Brian Silverman5120afb2020-01-31 17:44:35 -0800100 // Returns the epoll loop used to run the event loop.
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800101 internal::EPoll *epoll() { return &epoll_; }
102
Brian Silverman5120afb2020-01-31 17:44:35 -0800103 // Returns the local mapping of the shared memory used by the watcher on the
104 // specified channel. A watcher must be created on this channel before calling
105 // this.
Brian Silvermana5450a92020-08-12 19:59:57 -0700106 absl::Span<const char> GetWatcherSharedMemory(const Channel *channel);
Brian Silverman5120afb2020-01-31 17:44:35 -0800107
Brian Silverman6d2b3592020-06-18 14:40:15 -0700108 // Returns the local mapping of the shared memory used by the provided Sender.
Brian Silverman5120afb2020-01-31 17:44:35 -0800109 template <typename T>
110 absl::Span<char> GetSenderSharedMemory(aos::Sender<T> *sender) const {
Austin Schuh3054f5f2021-07-21 15:38:01 -0700111 CheckCurrentThread();
Brian Silverman5120afb2020-01-31 17:44:35 -0800112 return GetShmSenderSharedMemory(GetRawSender(sender));
113 }
114
Brian Silverman6d2b3592020-06-18 14:40:15 -0700115 // Returns the local mapping of the private memory used by the provided
116 // Fetcher to hold messages.
Brian Silvermana5450a92020-08-12 19:59:57 -0700117 //
118 // Note that this may be the entire shared memory region held by this fetcher,
119 // depending on its channel's read_method.
Brian Silverman6d2b3592020-06-18 14:40:15 -0700120 template <typename T>
Brian Silvermana5450a92020-08-12 19:59:57 -0700121 absl::Span<const char> GetFetcherPrivateMemory(
122 aos::Fetcher<T> *fetcher) const {
Austin Schuh3054f5f2021-07-21 15:38:01 -0700123 CheckCurrentThread();
Brian Silverman6d2b3592020-06-18 14:40:15 -0700124 return GetShmFetcherPrivateMemory(GetRawFetcher(fetcher));
125 }
126
Brian Silverman4f4e0612020-08-12 19:54:41 -0700127 int NumberBuffers(const Channel *channel) override;
128
Austin Schuh3054f5f2021-07-21 15:38:01 -0700129 // All public-facing APIs will verify this mutex is held when they are called.
130 // For normal use with everything in a single thread, this is unnecessary.
131 //
132 // This is helpful as a safety check when using a ShmEventLoop with external
133 // synchronization across multiple threads. It will NOT reliably catch race
134 // conditions, but if you have a race condition triggered repeatedly it'll
135 // probably catch it eventually.
136 void CheckForMutex(aos::stl_mutex *check_mutex) {
137 check_mutex_ = check_mutex;
138 }
139
140 // All public-facing APIs will verify they are called in this thread.
141 // For normal use with the whole program in a single thread, this is
142 // unnecessary. It's helpful as a safety check for programs with multiple
143 // threads, where the EventLoop should only be interacted with from a single
144 // one.
145 void LockToThread() { check_tid_ = GetTid(); }
146
Alex Perrycb7da4b2019-08-28 19:35:56 -0700147 private:
Brian Silverman148d43d2020-06-07 18:19:22 -0500148 friend class shm_event_loop_internal::ShmWatcherState;
149 friend class shm_event_loop_internal::ShmTimerHandler;
150 friend class shm_event_loop_internal::ShmPhasedLoopHandler;
151 friend class shm_event_loop_internal::ShmSender;
Austin Schuh432784f2020-06-23 17:27:35 -0700152 friend class shm_event_loop_internal::SimpleShmFetcher;
Brian Silverman148d43d2020-06-07 18:19:22 -0500153 friend class shm_event_loop_internal::ShmFetcher;
Brian Silvermane1fe2512022-08-14 23:18:50 -0700154 friend class shm_event_loop_internal::ShmExitHandle;
Austin Schuh39788ff2019-12-01 18:22:57 -0800155
Austin Schuh432784f2020-06-23 17:27:35 -0700156 using EventLoop::SendTimingReport;
157
Austin Schuh3054f5f2021-07-21 15:38:01 -0700158 void CheckCurrentThread() const;
159
Austin Schuh7d87b672019-12-01 20:23:49 -0800160 void HandleEvent();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700161
Austin Schuh39788ff2019-12-01 18:22:57 -0800162 // Returns the TID of the event loop.
163 pid_t GetTid() override;
164
Brian Silverman6d2b3592020-06-18 14:40:15 -0700165 // Private method to access the shared memory mapping of a ShmSender.
Brian Silverman5120afb2020-01-31 17:44:35 -0800166 absl::Span<char> GetShmSenderSharedMemory(const aos::RawSender *sender) const;
167
Brian Silverman6d2b3592020-06-18 14:40:15 -0700168 // Private method to access the private memory mapping of a ShmFetcher.
Brian Silvermana5450a92020-08-12 19:59:57 -0700169 absl::Span<const char> GetShmFetcherPrivateMemory(
Brian Silverman6d2b3592020-06-18 14:40:15 -0700170 const aos::RawFetcher *fetcher) const;
171
Austin Schuh83c7f702021-01-19 22:36:29 -0800172 const UUID boot_uuid_;
173
Brian Silvermane1fe2512022-08-14 23:18:50 -0700174 int exit_handle_count_ = 0;
175
Austin Schuhef323c02020-09-01 14:55:28 -0700176 // Capture the --shm_base flag at construction time. This makes it much
177 // easier to make different shared memory regions for doing things like
178 // multi-node tests.
179 std::string shm_base_;
180
Alex Perrycb7da4b2019-08-28 19:35:56 -0700181 std::vector<std::function<void()>> on_run_;
182 int priority_ = 0;
Brian Silverman6a54ff32020-04-28 16:41:39 -0700183 cpu_set_t affinity_ = DefaultAffinity();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700184 std::string name_;
Austin Schuh217a9782019-12-21 23:02:50 -0800185 const Node *const node_;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700186
Austin Schuh3054f5f2021-07-21 15:38:01 -0700187 aos::stl_mutex *check_mutex_ = nullptr;
188 std::optional<pid_t> check_tid_;
189
Alex Perrycb7da4b2019-08-28 19:35:56 -0700190 internal::EPoll epoll_;
Austin Schuh5ca13112021-02-07 22:06:53 -0800191
192 // Only set during Run().
193 std::unique_ptr<ipc_lib::SignalFd> signalfd_;
James Kuszmaul9f998082024-05-23 15:37:35 -0700194
195 // Calls to Exit() are guaranteed to be thread-safe, so the exit_status_mutex_
196 // guards access to the exit_status_.
197 aos::stl_mutex exit_status_mutex_;
198 // Once exit_status_ is set once, we will not set it again until we have
199 // actually exited. This is to try to provide consistent behavior in cases
200 // where Exit() is called multiple times before Run() is aactually terminates
201 // execution.
202 std::optional<Result<void>> exit_status_{};
203 // Used by the Exit() call to provide an async-safe way of indicating that
204 // Exit() was called.
205 // Will be set once Exit() or ExitWithStatus() has been called.
206 // Note: std::atomic<> is not necessarily guaranteed to be lock-free, although
207 // std::atomic_flag is, and so is safe to use in Exit().
208 std::atomic_flag observed_exit_ = ATOMIC_FLAG_INIT;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700209};
210
Alex Perrycb7da4b2019-08-28 19:35:56 -0700211} // namespace aos
212
213#endif // AOS_EVENTS_SHM_EVENT_LOOP_H_