• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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