• 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 #include <grpc/support/port_platform.h>
16 
17 #include <utility>
18 
19 #include "absl/strings/str_cat.h"
20 #include "src/core/lib/iomgr/port.h"
21 #include "src/core/util/crash.h"  // IWYU pragma: keep
22 
23 #ifdef GRPC_LINUX_EVENTFD
24 
25 #include <errno.h>
26 #include <sys/eventfd.h>
27 #include <unistd.h>
28 
29 #include "src/core/lib/event_engine/posix_engine/wakeup_fd_posix.h"
30 #endif
31 
32 #include "src/core/lib/event_engine/posix_engine/wakeup_fd_eventfd.h"
33 #include "src/core/util/strerror.h"
34 
35 namespace grpc_event_engine {
36 namespace experimental {
37 
38 #ifdef GRPC_LINUX_EVENTFD
39 
Init()40 absl::Status EventFdWakeupFd::Init() {
41   int read_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
42   int write_fd = -1;
43   if (read_fd < 0) {
44     return absl::Status(absl::StatusCode::kInternal,
45                         absl::StrCat("eventfd: ", grpc_core::StrError(errno)));
46   }
47   SetWakeupFds(read_fd, write_fd);
48   return absl::OkStatus();
49 }
50 
ConsumeWakeup()51 absl::Status EventFdWakeupFd::ConsumeWakeup() {
52   eventfd_t value;
53   int err;
54   do {
55     err = eventfd_read(ReadFd(), &value);
56   } while (err < 0 && errno == EINTR);
57   if (err < 0 && errno != EAGAIN) {
58     return absl::Status(
59         absl::StatusCode::kInternal,
60         absl::StrCat("eventfd_read: ", grpc_core::StrError(errno)));
61   }
62   return absl::OkStatus();
63 }
64 
Wakeup()65 absl::Status EventFdWakeupFd::Wakeup() {
66   int err;
67   do {
68     err = eventfd_write(ReadFd(), 1);
69   } while (err < 0 && errno == EINTR);
70   if (err < 0) {
71     return absl::Status(
72         absl::StatusCode::kInternal,
73         absl::StrCat("eventfd_write: ", grpc_core::StrError(errno)));
74   }
75   return absl::OkStatus();
76 }
77 
~EventFdWakeupFd()78 EventFdWakeupFd::~EventFdWakeupFd() {
79   if (ReadFd() != 0) {
80     close(ReadFd());
81   }
82 }
83 
IsSupported()84 bool EventFdWakeupFd::IsSupported() {
85   EventFdWakeupFd event_fd_wakeup_fd;
86   return event_fd_wakeup_fd.Init().ok();
87 }
88 
89 absl::StatusOr<std::unique_ptr<WakeupFd>>
CreateEventFdWakeupFd()90 EventFdWakeupFd::CreateEventFdWakeupFd() {
91   static bool kIsEventFdWakeupFdSupported = EventFdWakeupFd::IsSupported();
92   if (kIsEventFdWakeupFdSupported) {
93     auto event_fd_wakeup_fd = std::make_unique<EventFdWakeupFd>();
94     auto status = event_fd_wakeup_fd->Init();
95     if (status.ok()) {
96       return std::unique_ptr<WakeupFd>(std::move(event_fd_wakeup_fd));
97     }
98     return status;
99   }
100   return absl::NotFoundError("Eventfd wakeup fd is not supported");
101 }
102 
103 #else  //  GRPC_LINUX_EVENTFD
104 
105 #include "src/core/util/crash.h"
106 
107 absl::Status EventFdWakeupFd::Init() { grpc_core::Crash("unimplemented"); }
108 
109 absl::Status EventFdWakeupFd::ConsumeWakeup() {
110   grpc_core::Crash("unimplemented");
111 }
112 
113 absl::Status EventFdWakeupFd::Wakeup() { grpc_core::Crash("unimplemented"); }
114 
115 bool EventFdWakeupFd::IsSupported() { return false; }
116 
117 absl::StatusOr<std::unique_ptr<WakeupFd>>
118 EventFdWakeupFd::CreateEventFdWakeupFd() {
119   return absl::NotFoundError("Eventfd wakeup fd is not supported");
120 }
121 
122 #endif  // GRPC_LINUX_EVENTFD
123 
124 }  // namespace experimental
125 }  // namespace grpc_event_engine
126