blob: 425d334b23b135e38d685ba48f42452e8d176b1d [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"
Alex Perrycb7da4b2019-08-28 19:35:56 -07007#include "aos/events/epoll.h"
8#include "aos/events/event_loop.h"
Austin Schuh39788ff2019-12-01 18:22:57 -08009#include "aos/events/event_loop_generated.h"
Austin Schuh5ca13112021-02-07 22:06:53 -080010#include "aos/ipc_lib/signalfd.h"
Austin Schuh3054f5f2021-07-21 15:38:01 -070011#include "aos/stl_mutex/stl_mutex.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070012
Jim Ostrowski2192ddb2020-06-24 19:07:31 -070013DECLARE_string(application_name);
14DECLARE_string(shm_base);
15
Alex Perrycb7da4b2019-08-28 19:35:56 -070016namespace aos {
Brian Silverman148d43d2020-06-07 18:19:22 -050017namespace shm_event_loop_internal {
Alex Perrycb7da4b2019-08-28 19:35:56 -070018
Brian Silverman148d43d2020-06-07 18:19:22 -050019class ShmWatcherState;
20class ShmTimerHandler;
21class ShmPhasedLoopHandler;
Austin Schuh39788ff2019-12-01 18:22:57 -080022class ShmSender;
Austin Schuh432784f2020-06-23 17:27:35 -070023class SimpleShmFetcher;
Austin Schuh39788ff2019-12-01 18:22:57 -080024class ShmFetcher;
Brian Silvermane1fe2512022-08-14 23:18:50 -070025class ShmExitHandle;
Alex Perrycb7da4b2019-08-28 19:35:56 -070026
Brian Silverman148d43d2020-06-07 18:19:22 -050027} // namespace shm_event_loop_internal
Alex Perrycb7da4b2019-08-28 19:35:56 -070028
Brian Silverman4f4e0612020-08-12 19:54:41 -070029// Concrete implementation of EventLoop that is built from queues running out of
30// shared memory.
Alex Perrycb7da4b2019-08-28 19:35:56 -070031//
Austin Schuh39788ff2019-12-01 18:22:57 -080032// TODO(austin): Timing reports break multiple threads. Need to add back in a
33// mutex.
34// This object must be interacted with from one thread, but the Senders
35// and Fetchers may be used from multiple threads afterwords (as long as their
Alex Perrycb7da4b2019-08-28 19:35:56 -070036// destructors are called back in one thread again)
37class ShmEventLoop : public EventLoop {
38 public:
Austin Schuhcaa2a5d2020-11-01 22:38:20 -080039 ShmEventLoop(const Flatbuffer<Configuration> &configuration)
40 : ShmEventLoop(&configuration.message()) {}
Alex Perrycb7da4b2019-08-28 19:35:56 -070041 ShmEventLoop(const Configuration *configuration);
Austin Schuhad9e5eb2021-11-19 20:33:55 -080042 ShmEventLoop(const ShmEventLoop &) = delete;
Alex Perrycb7da4b2019-08-28 19:35:56 -070043 ~ShmEventLoop() override;
44
Austin Schuhad9e5eb2021-11-19 20:33:55 -080045 void operator=(ShmEventLoop const &) = delete;
46
Austin Schuh39788ff2019-12-01 18:22:57 -080047 // Runs the event loop until Exit is called, or ^C is caught.
48 void Run();
49 // Exits the event loop. Async safe.
50 void Exit();
51
Brian Silvermane1fe2512022-08-14 23:18:50 -070052 std::unique_ptr<ExitHandle> MakeExitHandle();
53
Stephan Pleines559fa6c2022-01-06 17:23:51 -080054 aos::monotonic_clock::time_point monotonic_now() const override {
Alex Perrycb7da4b2019-08-28 19:35:56 -070055 return aos::monotonic_clock::now();
56 }
Stephan Pleines559fa6c2022-01-06 17:23:51 -080057 aos::realtime_clock::time_point realtime_now() const override {
Alex Perrycb7da4b2019-08-28 19:35:56 -070058 return aos::realtime_clock::now();
59 }
60
61 std::unique_ptr<RawSender> MakeRawSender(const Channel *channel) override;
62 std::unique_ptr<RawFetcher> MakeRawFetcher(const Channel *channel) override;
63
64 void MakeRawWatcher(
65 const Channel *channel,
66 std::function<void(const Context &context, const void *message)> watcher)
67 override;
Brian Silverman6b8a3c32020-03-06 11:26:14 -080068 void MakeRawNoArgWatcher(
69 const Channel *channel,
70 std::function<void(const Context &context)> watcher) override;
Alex Perrycb7da4b2019-08-28 19:35:56 -070071
72 TimerHandler *AddTimer(std::function<void()> callback) override;
Brian Silverman148d43d2020-06-07 18:19:22 -050073 PhasedLoopHandler *AddPhasedLoop(std::function<void(int)> callback,
74 const monotonic_clock::duration interval,
75 const monotonic_clock::duration offset =
76 std::chrono::seconds(0)) override;
Alex Perrycb7da4b2019-08-28 19:35:56 -070077
78 void OnRun(std::function<void()> on_run) override;
Alex Perrycb7da4b2019-08-28 19:35:56 -070079
80 void SetRuntimeRealtimePriority(int priority) override;
Brian Silverman6a54ff32020-04-28 16:41:39 -070081 void SetRuntimeAffinity(const cpu_set_t &cpuset) override;
Alex Perrycb7da4b2019-08-28 19:35:56 -070082
James Kuszmaul57c2baa2020-01-19 14:52:52 -080083 void set_name(const std::string_view name) override;
James Kuszmaul3ae42262019-11-08 12:33:41 -080084 const std::string_view name() const override { return name_; }
Austin Schuh217a9782019-12-21 23:02:50 -080085 const Node *node() const override { return node_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070086
Austin Schuh39788ff2019-12-01 18:22:57 -080087 int priority() const override { return priority_; }
Austin Schuh83c7f702021-01-19 22:36:29 -080088 const UUID &boot_uuid() const override { return boot_uuid_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070089
Brian Silverman5120afb2020-01-31 17:44:35 -080090 // Returns the epoll loop used to run the event loop.
Austin Schuhe84c3ed2019-12-14 15:29:48 -080091 internal::EPoll *epoll() { return &epoll_; }
92
Brian Silverman5120afb2020-01-31 17:44:35 -080093 // Returns the local mapping of the shared memory used by the watcher on the
94 // specified channel. A watcher must be created on this channel before calling
95 // this.
Brian Silvermana5450a92020-08-12 19:59:57 -070096 absl::Span<const char> GetWatcherSharedMemory(const Channel *channel);
Brian Silverman5120afb2020-01-31 17:44:35 -080097
Brian Silverman6d2b3592020-06-18 14:40:15 -070098 // Returns the local mapping of the shared memory used by the provided Sender.
Brian Silverman5120afb2020-01-31 17:44:35 -080099 template <typename T>
100 absl::Span<char> GetSenderSharedMemory(aos::Sender<T> *sender) const {
Austin Schuh3054f5f2021-07-21 15:38:01 -0700101 CheckCurrentThread();
Brian Silverman5120afb2020-01-31 17:44:35 -0800102 return GetShmSenderSharedMemory(GetRawSender(sender));
103 }
104
Brian Silverman6d2b3592020-06-18 14:40:15 -0700105 // Returns the local mapping of the private memory used by the provided
106 // Fetcher to hold messages.
Brian Silvermana5450a92020-08-12 19:59:57 -0700107 //
108 // Note that this may be the entire shared memory region held by this fetcher,
109 // depending on its channel's read_method.
Brian Silverman6d2b3592020-06-18 14:40:15 -0700110 template <typename T>
Brian Silvermana5450a92020-08-12 19:59:57 -0700111 absl::Span<const char> GetFetcherPrivateMemory(
112 aos::Fetcher<T> *fetcher) const {
Austin Schuh3054f5f2021-07-21 15:38:01 -0700113 CheckCurrentThread();
Brian Silverman6d2b3592020-06-18 14:40:15 -0700114 return GetShmFetcherPrivateMemory(GetRawFetcher(fetcher));
115 }
116
Brian Silverman4f4e0612020-08-12 19:54:41 -0700117 int NumberBuffers(const Channel *channel) override;
118
Austin Schuh3054f5f2021-07-21 15:38:01 -0700119 // All public-facing APIs will verify this mutex is held when they are called.
120 // For normal use with everything in a single thread, this is unnecessary.
121 //
122 // This is helpful as a safety check when using a ShmEventLoop with external
123 // synchronization across multiple threads. It will NOT reliably catch race
124 // conditions, but if you have a race condition triggered repeatedly it'll
125 // probably catch it eventually.
126 void CheckForMutex(aos::stl_mutex *check_mutex) {
127 check_mutex_ = check_mutex;
128 }
129
130 // All public-facing APIs will verify they are called in this thread.
131 // For normal use with the whole program in a single thread, this is
132 // unnecessary. It's helpful as a safety check for programs with multiple
133 // threads, where the EventLoop should only be interacted with from a single
134 // one.
135 void LockToThread() { check_tid_ = GetTid(); }
136
Alex Perrycb7da4b2019-08-28 19:35:56 -0700137 private:
Brian Silverman148d43d2020-06-07 18:19:22 -0500138 friend class shm_event_loop_internal::ShmWatcherState;
139 friend class shm_event_loop_internal::ShmTimerHandler;
140 friend class shm_event_loop_internal::ShmPhasedLoopHandler;
141 friend class shm_event_loop_internal::ShmSender;
Austin Schuh432784f2020-06-23 17:27:35 -0700142 friend class shm_event_loop_internal::SimpleShmFetcher;
Brian Silverman148d43d2020-06-07 18:19:22 -0500143 friend class shm_event_loop_internal::ShmFetcher;
Brian Silvermane1fe2512022-08-14 23:18:50 -0700144 friend class shm_event_loop_internal::ShmExitHandle;
Austin Schuh39788ff2019-12-01 18:22:57 -0800145
Austin Schuh432784f2020-06-23 17:27:35 -0700146 using EventLoop::SendTimingReport;
147
Brian Silverman6a54ff32020-04-28 16:41:39 -0700148 static cpu_set_t DefaultAffinity() {
149 cpu_set_t result;
150 for (int i = 0; i < CPU_SETSIZE; ++i) {
151 CPU_SET(i, &result);
152 }
153 return result;
154 }
155
Austin Schuh3054f5f2021-07-21 15:38:01 -0700156 void CheckCurrentThread() const;
157
Austin Schuh7d87b672019-12-01 20:23:49 -0800158 void HandleEvent();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700159
Austin Schuh39788ff2019-12-01 18:22:57 -0800160 // Returns the TID of the event loop.
161 pid_t GetTid() override;
162
Brian Silverman6d2b3592020-06-18 14:40:15 -0700163 // Private method to access the shared memory mapping of a ShmSender.
Brian Silverman5120afb2020-01-31 17:44:35 -0800164 absl::Span<char> GetShmSenderSharedMemory(const aos::RawSender *sender) const;
165
Brian Silverman6d2b3592020-06-18 14:40:15 -0700166 // Private method to access the private memory mapping of a ShmFetcher.
Brian Silvermana5450a92020-08-12 19:59:57 -0700167 absl::Span<const char> GetShmFetcherPrivateMemory(
Brian Silverman6d2b3592020-06-18 14:40:15 -0700168 const aos::RawFetcher *fetcher) const;
169
Austin Schuh83c7f702021-01-19 22:36:29 -0800170 const UUID boot_uuid_;
171
Brian Silvermane1fe2512022-08-14 23:18:50 -0700172 int exit_handle_count_ = 0;
173
Austin Schuhef323c02020-09-01 14:55:28 -0700174 // Capture the --shm_base flag at construction time. This makes it much
175 // easier to make different shared memory regions for doing things like
176 // multi-node tests.
177 std::string shm_base_;
178
Alex Perrycb7da4b2019-08-28 19:35:56 -0700179 std::vector<std::function<void()>> on_run_;
180 int priority_ = 0;
Brian Silverman6a54ff32020-04-28 16:41:39 -0700181 cpu_set_t affinity_ = DefaultAffinity();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700182 std::string name_;
Austin Schuh217a9782019-12-21 23:02:50 -0800183 const Node *const node_;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700184
Austin Schuh3054f5f2021-07-21 15:38:01 -0700185 aos::stl_mutex *check_mutex_ = nullptr;
186 std::optional<pid_t> check_tid_;
187
Alex Perrycb7da4b2019-08-28 19:35:56 -0700188 internal::EPoll epoll_;
Austin Schuh5ca13112021-02-07 22:06:53 -0800189
190 // Only set during Run().
191 std::unique_ptr<ipc_lib::SignalFd> signalfd_;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700192};
193
Alex Perrycb7da4b2019-08-28 19:35:56 -0700194} // namespace aos
195
196#endif // AOS_EVENTS_SHM_EVENT_LOOP_H_