Skip to content

Commit b5e753a

Browse files
Yikang Xumeta-codesync[bot]
authored andcommitted
Allow custom preLoop and postLoop hooks
Summary: Hyperclient polls EventBases directly, and it would like to receive the number of events processed per loopPoll() call. The easiest way is to use eb_loop_poll_hook. However this doesn't work for us (see D93285393), because these hooks are per-process, only 1 hook is allowed. ucache already uses these hooks, and hyperclient will be in the same process with ucache, this breaks other tests (see T256167952). As a result, we would like to have per-EventBase custom preLoop and postLoop hooks. Reviewed By: spikeh Differential Revision: D93625126 fbshipit-source-id: 285d3bc9470b51dbcae8e37fa098dae8095565d8
1 parent b101f74 commit b5e753a

4 files changed

Lines changed: 644 additions & 0 deletions

File tree

third-party/folly/src/folly/io/async/EpollBackend.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ int EpollBackend::eb_event_base_loop(int flags) {
229229
if (eb_poll_loop_pre_hook) {
230230
eb_poll_loop_pre_hook(&call_time);
231231
}
232+
if (pollLoopHook_.preLoopHook) {
233+
pollLoopHook_.preLoopHook(pollLoopHook_.hookCtx);
234+
}
232235

233236
int numEvents;
234237
do {
@@ -239,6 +242,9 @@ int EpollBackend::eb_event_base_loop(int flags) {
239242
if (eb_poll_loop_post_hook) {
240243
eb_poll_loop_post_hook(call_time, numEvents);
241244
}
245+
if (pollLoopHook_.postLoopHook) {
246+
pollLoopHook_.postLoopHook(pollLoopHook_.hookCtx, numEvents);
247+
}
242248

243249
if (numEvents < 0) {
244250
return -1;

third-party/folly/src/folly/io/async/EventBaseBackendBase.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,23 @@ class EventBaseBackendBase {
114114
std::function<std::unique_ptr<folly::EventBaseBackendBase>()>;
115115
using RecvZcCallback = folly::Function<void(ssize_t)>;
116116

117+
// Per-EventBase hooks invoked around the poll syscall (epoll_wait /
118+
// io_uring CQE reaping). Only EpollBackend and IoUringBackend invoke
119+
// these hooks; other backends (e.g. LibeventBackend) do not.
120+
//
121+
// prePollLoopHook is called immediately before the poll syscall.
122+
// postPollLoopHook is called immediately after, receiving the number of
123+
// events returned by the syscall.
124+
// Both hooks share a single opaque context pointer.
125+
using PrePollLoopHook = void (*)(void* ctx);
126+
using PostPollLoopHook = void (*)(void* ctx, int numEvents);
127+
128+
struct PollLoopHook {
129+
PrePollLoopHook preLoopHook = nullptr;
130+
PostPollLoopHook postLoopHook = nullptr;
131+
void* hookCtx = nullptr;
132+
};
133+
117134
EventBaseBackendBase() = default;
118135
virtual ~EventBaseBackendBase() = default;
119136

@@ -129,6 +146,10 @@ class EventBaseBackendBase {
129146
unsigned long /*nbytes*/,
130147
RecvZcCallback&& /*callback*/) {}
131148

149+
void setPollLoopHook(PollLoopHook pollLoopHook) {
150+
pollLoopHook_ = pollLoopHook;
151+
}
152+
132153
virtual event_base* getEventBase() = 0;
133154
virtual int eb_event_base_loop(int flags) = 0;
134155
virtual int eb_event_base_loopbreak() = 0;
@@ -139,6 +160,9 @@ class EventBaseBackendBase {
139160
virtual bool eb_event_active(Event& event, int res) = 0;
140161

141162
virtual bool setEdgeTriggered(Event& /* event */) { return false; }
163+
164+
protected:
165+
PollLoopHook pollLoopHook_;
142166
};
143167

144168
} // namespace folly

third-party/folly/src/folly/io/async/IoUringBackend.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,13 +1183,20 @@ int IoUringBackend::eb_event_base_loop(int flags) {
11831183
if (eb_poll_loop_pre_hook) {
11841184
eb_poll_loop_pre_hook(&call_time);
11851185
}
1186+
if (pollLoopHook_.preLoopHook) {
1187+
pollLoopHook_.preLoopHook(pollLoopHook_.hookCtx);
1188+
}
11861189

11871190
// do not wait for events if EVLOOP_NONBLOCK is set
11881191
size_t processedEvents = getActiveEvents(waitForEvents);
11891192

11901193
if (eb_poll_loop_post_hook) {
11911194
eb_poll_loop_post_hook(call_time, static_cast<int>(processedEvents));
11921195
}
1196+
if (pollLoopHook_.postLoopHook) {
1197+
pollLoopHook_.postLoopHook(
1198+
pollLoopHook_.hookCtx, static_cast<int>(processedEvents));
1199+
}
11931200

11941201
size_t numProcessedTimers = 0;
11951202

0 commit comments

Comments
 (0)