1 // Copyright 2022 The gRPC Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef GRPC_SRC_CORE_LIB_EVENT_ENGINE_POSIX_ENGINE_EV_EPOLL1_LINUX_H 16 #define GRPC_SRC_CORE_LIB_EVENT_ENGINE_POSIX_ENGINE_EV_EPOLL1_LINUX_H 17 #include <grpc/event_engine/event_engine.h> 18 #include <grpc/support/port_platform.h> 19 20 #include <list> 21 #include <memory> 22 #include <string> 23 24 #include "absl/base/thread_annotations.h" 25 #include "absl/container/inlined_vector.h" 26 #include "absl/functional/function_ref.h" 27 #include "absl/strings/string_view.h" 28 #include "src/core/lib/event_engine/poller.h" 29 #include "src/core/lib/event_engine/posix_engine/event_poller.h" 30 #include "src/core/lib/event_engine/posix_engine/internal_errqueue.h" 31 #include "src/core/lib/event_engine/posix_engine/wakeup_fd_posix.h" 32 #include "src/core/lib/iomgr/port.h" 33 #include "src/core/util/sync.h" 34 35 #ifdef GRPC_LINUX_EPOLL 36 #include <sys/epoll.h> 37 #endif 38 39 #define MAX_EPOLL_EVENTS 100 40 41 namespace grpc_event_engine { 42 namespace experimental { 43 44 class Epoll1EventHandle; 45 46 // Definition of epoll1 based poller. 47 class Epoll1Poller : public PosixEventPoller { 48 public: 49 explicit Epoll1Poller(Scheduler* scheduler); 50 EventHandle* CreateHandle(int fd, absl::string_view name, 51 bool track_err) override; 52 Poller::WorkResult Work( 53 grpc_event_engine::experimental::EventEngine::Duration timeout, 54 absl::FunctionRef<void()> schedule_poll_again) override; Name()55 std::string Name() override { return "epoll1"; } 56 void Kick() override; GetScheduler()57 Scheduler* GetScheduler() { return scheduler_; } 58 void Shutdown() override; CanTrackErrors()59 bool CanTrackErrors() const override { 60 #ifdef GRPC_POSIX_SOCKET_TCP 61 return KernelSupportsErrqueue(); 62 #else 63 return false; 64 #endif 65 } 66 ~Epoll1Poller() override; 67 68 // Forkable 69 void PrepareFork() override; 70 void PostforkParent() override; 71 void PostforkChild() override; 72 73 void Close(); 74 75 private: 76 // This initial vector size may need to be tuned 77 using Events = absl::InlinedVector<Epoll1EventHandle*, 5>; 78 // Process the epoll events found by DoEpollWait() function. 79 // - g_epoll_set.cursor points to the index of the first event to be processed 80 // - This function then processes up-to max_epoll_events_to_handle and 81 // updates the g_epoll_set.cursor. 82 // It returns true, it there was a Kick that forced invocation of this 83 // function. It also returns the list of closures to run to take action 84 // on file descriptors that became readable/writable. 85 bool ProcessEpollEvents(int max_epoll_events_to_handle, 86 Events& pending_events); 87 88 // Do epoll_wait and store the events in g_epoll_set.events field. This does 89 // not "process" any of the events yet; that is done in ProcessEpollEvents(). 90 // See ProcessEpollEvents() function for more details. It returns the number 91 // of events generated by epoll_wait. 92 int DoEpollWait( 93 grpc_event_engine::experimental::EventEngine::Duration timeout); 94 class HandlesList { 95 public: HandlesList(Epoll1EventHandle * handle)96 explicit HandlesList(Epoll1EventHandle* handle) : handle(handle) {} 97 Epoll1EventHandle* handle; 98 Epoll1EventHandle* next = nullptr; 99 Epoll1EventHandle* prev = nullptr; 100 }; 101 friend class Epoll1EventHandle; 102 #ifdef GRPC_LINUX_EPOLL 103 struct EpollSet { 104 int epfd = -1; 105 106 // The epoll_events after the last call to epoll_wait() 107 struct epoll_event events[MAX_EPOLL_EVENTS]{}; 108 109 // The number of epoll_events after the last call to epoll_wait() 110 int num_events = 0; 111 112 // Index of the first event in epoll_events that has to be processed. This 113 // field is only valid if num_events > 0 114 int cursor = 0; 115 }; 116 #else 117 struct EpollSet {}; 118 #endif 119 grpc_core::Mutex mu_; 120 Scheduler* scheduler_; 121 // A singleton epoll set 122 EpollSet g_epoll_set_; 123 bool was_kicked_ ABSL_GUARDED_BY(mu_); 124 std::list<EventHandle*> free_epoll1_handles_list_ ABSL_GUARDED_BY(mu_); 125 std::unique_ptr<WakeupFd> wakeup_fd_; 126 bool closed_; 127 }; 128 129 // Return an instance of a epoll1 based poller tied to the specified event 130 // engine. 131 std::shared_ptr<Epoll1Poller> MakeEpoll1Poller(Scheduler* scheduler); 132 133 } // namespace experimental 134 } // namespace grpc_event_engine 135 136 #endif // GRPC_SRC_CORE_LIB_EVENT_ENGINE_POSIX_ENGINE_EV_EPOLL1_LINUX_H 137