blob: 526c6a75e5d7d52a515334a5c8bebaddb6ed5b1d [file] [log] [blame]
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001#ifndef AOS_EVENTS_EPOLL_H_
2#define AOS_EVENTS_EPOLL_H_
3
4#include <fcntl.h>
5#include <sys/epoll.h>
6#include <sys/timerfd.h>
7#include <unistd.h>
Austin Schuh4c839682021-07-21 15:30:44 -07008
Austin Schuh6b6dfa52019-06-12 20:16:20 -07009#include <atomic>
Alex Perrycb7da4b2019-08-28 19:35:56 -070010#include <functional>
Austin Schuh6b6dfa52019-06-12 20:16:20 -070011#include <vector>
12
Austin Schuh6b6dfa52019-06-12 20:16:20 -070013#include "aos/time/time.h"
14
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080015namespace aos::internal {
Austin Schuh6b6dfa52019-06-12 20:16:20 -070016
17// Class wrapping up timerfd.
18class TimerFd {
19 public:
20 TimerFd();
Austin Schuhf257f3c2019-10-27 21:00:43 -070021 ~TimerFd();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070022
23 TimerFd(const TimerFd &) = delete;
24 TimerFd &operator=(const TimerFd &) = delete;
25 TimerFd(TimerFd &&) = delete;
26 TimerFd &operator=(TimerFd &&) = delete;
27
28 // Sets the trigger time and repeat for the timerfd.
29 // An interval of 0 results in a single expiration.
30 void SetTime(monotonic_clock::time_point start,
31 monotonic_clock::duration interval);
32
33 // Disarms the timer.
34 void Disable() {
35 // Disarm the timer by feeding zero values
36 SetTime(::aos::monotonic_clock::epoch(), ::aos::monotonic_clock::zero());
37 }
38
Austin Schuhde8a8ff2019-11-30 15:25:36 -080039 // Reads the event. Returns the number of elapsed cycles.
40 uint64_t Read();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070041
42 // Returns the file descriptor associated with the timerfd.
43 int fd() { return fd_; }
44
45 private:
46 int fd_ = -1;
47};
48
49// Class to wrap epoll and call a callback when an event happens.
50class EPoll {
51 public:
52 EPoll();
53 ~EPoll();
54 EPoll(const EPoll &) = delete;
55 EPoll &operator=(const EPoll &) = delete;
56 EPoll(EPoll &&) = delete;
57 EPoll &operator=(EPoll &&) = delete;
58
59 // Runs until Quit() is called.
60 void Run();
61
James Kuszmaulc8e657e2020-12-14 23:49:45 -080062 // Consumes a single epoll event. Blocks indefinitely if block is true, or
63 // does not block at all. Returns true if an event was consumed, and false on
64 // any retryable error or if no events are available. Dies fatally on
65 // non-retryable errors.
66 bool Poll(bool block);
67
Austin Schuh6b6dfa52019-06-12 20:16:20 -070068 // Quits. Async safe.
69 void Quit();
70
Austin Schuh4c839682021-07-21 15:30:44 -070071 // Adds a function which will be called before waiting on the epoll file
72 // descriptor.
Austin Schuh219b7782020-12-21 12:01:40 -080073 void BeforeWait(std::function<void()> function);
74
Austin Schuh6b6dfa52019-06-12 20:16:20 -070075 // Registers a function to be called if the fd becomes readable.
Brian Silverman441591b2020-01-31 17:44:32 -080076 // Only one function may be registered for readability on each fd.
Austin Schuh4c839682021-07-21 15:30:44 -070077 // A fd may be registered exclusively with OnReadable/OnWriteable/OnError OR
78 // OnEvents.
Austin Schuh6b6dfa52019-06-12 20:16:20 -070079 void OnReadable(int fd, ::std::function<void()> function);
80
Austin Schuh603419f2021-04-24 18:15:20 -070081 // Registers a function to be called if the fd reports an error.
82 // Only one function may be registered for errors on each fd.
Austin Schuh4c839682021-07-21 15:30:44 -070083 // A fd may be registered exclusively with OnReadable/OnWriteable/OnError OR
84 // OnEvents.
Austin Schuh603419f2021-04-24 18:15:20 -070085 void OnError(int fd, ::std::function<void()> function);
86
Brian Silverman441591b2020-01-31 17:44:32 -080087 // Registers a function to be called if the fd becomes writeable.
88 // Only one function may be registered for writability on each fd.
Austin Schuh4c839682021-07-21 15:30:44 -070089 // A fd may be registered exclusively with OnReadable/OnWriteable/OnError OR
90 // OnEvents.
Brian Silverman441591b2020-01-31 17:44:32 -080091 void OnWriteable(int fd, ::std::function<void()> function);
92
Austin Schuh4c839682021-07-21 15:30:44 -070093 // Registers a function to be called when the configured events occur on fd.
94 // Which events occur will be passed to the function.
95 // A fd may be registered exclusively with OnReadable/OnWriteable/OnError OR
96 // OnEvents.
97 void OnEvents(int fd, ::std::function<void(uint32_t)> function);
98
Austin Schuh6b6dfa52019-06-12 20:16:20 -070099 // Removes fd from the event loop.
100 // All Fds must be cleaned up before this class is destroyed.
101 void DeleteFd(int fd);
102
Austin Schuh219b7782020-12-21 12:01:40 -0800103 // Removes a closed fd. When fds are closed, they are automatically
104 // unregistered by the kernel. But we need to clean up any state here.
105 // All Fds must be cleaned up before this class is destroyed.
106 void ForgetClosedFd(int fd);
107
Brian Silverman441591b2020-01-31 17:44:32 -0800108 // Enables calling the existing function registered for fd when it becomes
109 // writeable.
110 void EnableWriteable(int fd) { EnableEvents(fd, kOutEvents); }
111
112 // Disables calling the existing function registered for fd when it becomes
113 // writeable.
114 void DisableWriteable(int fd) { DisableEvents(fd, kOutEvents); }
115
Austin Schuh4c839682021-07-21 15:30:44 -0700116 // Sets the epoll events for the given fd. Be careful using this with
117 // OnReadable/OnWriteable/OnError: enabled events which fire with no handler
118 // registered will result in a crash.
119 void SetEvents(int fd, uint32_t events);
120
121 // Returns whether we're currently running. This changes to false when we
122 // start draining events to finish.
123 bool should_run() const { return run_; }
124
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700125 private:
Brian Silverman441591b2020-01-31 17:44:32 -0800126 // Structure whose pointer should be returned by epoll. Makes looking up the
127 // function fast and easy.
128 struct EventData {
129 EventData(int fd_in) : fd(fd_in) {}
Austin Schuh4c839682021-07-21 15:30:44 -0700130 virtual ~EventData() = default;
131
Brian Silverman441591b2020-01-31 17:44:32 -0800132 // We use pointers to these objects as persistent identifiers, so they can't
133 // be moved.
134 EventData(const EventData &) = delete;
135 EventData &operator=(const EventData &) = delete;
136
Austin Schuh4c839682021-07-21 15:30:44 -0700137 // Calls the appropriate callbacks when events are returned from the kernel.
138 virtual void DoCallbacks(uint32_t events) = 0;
139
Brian Silverman441591b2020-01-31 17:44:32 -0800140 const int fd;
141 uint32_t events = 0;
Austin Schuh4c839682021-07-21 15:30:44 -0700142 };
143
144 struct InOutEventData : public EventData {
145 InOutEventData(int fd) : EventData(fd) {}
146 ~InOutEventData() override = default;
147
Austin Schuh603419f2021-04-24 18:15:20 -0700148 std::function<void()> in_fn, out_fn, err_fn;
Austin Schuh4c839682021-07-21 15:30:44 -0700149
150 void DoCallbacks(uint32_t events) override;
151 };
152
153 struct SingleEventData : public EventData {
154 SingleEventData(int fd) : EventData(fd) {}
155 ~SingleEventData() override = default;
156
157 std::function<void(uint32_t)> fn;
158
159 void DoCallbacks(uint32_t events) override { fn(events); }
Brian Silverman441591b2020-01-31 17:44:32 -0800160 };
161
162 void EnableEvents(int fd, uint32_t events);
163 void DisableEvents(int fd, uint32_t events);
164
165 EventData *GetEventData(int fd);
166
167 void DoEpollCtl(EventData *event_data, uint32_t new_events);
168
169 // TODO(Brian): Figure out a nicer way to handle EPOLLPRI than lumping it in
170 // with input.
171 static constexpr uint32_t kInEvents = EPOLLIN | EPOLLPRI;
172 static constexpr uint32_t kOutEvents = EPOLLOUT;
Austin Schuh603419f2021-04-24 18:15:20 -0700173 static constexpr uint32_t kErrorEvents = EPOLLERR;
Brian Silverman441591b2020-01-31 17:44:32 -0800174
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700175 ::std::atomic<bool> run_{true};
176
177 // Main epoll fd.
178 int epoll_fd_;
179
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700180 ::std::vector<::std::unique_ptr<EventData>> fns_;
181
182 // Pipe pair for handling quit.
183 int quit_signal_fd_;
184 int quit_epoll_fd_;
Austin Schuh219b7782020-12-21 12:01:40 -0800185
186 std::vector<std::function<void()>> before_epoll_wait_functions_;
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700187};
188
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800189} // namespace aos::internal
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700190
191#endif // AOS_EVENTS_EPOLL_H_