1 /*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/iomgr/port.h"
22
23 #include "src/core/lib/iomgr/is_epollexclusive_available.h"
24
25 #ifdef GRPC_LINUX_EPOLL_CREATE1
26
27 #include <grpc/support/log.h>
28
29 #include <errno.h>
30 #include <sys/epoll.h>
31 #include <sys/eventfd.h>
32 #include <unistd.h>
33
34 #include "src/core/lib/iomgr/sys_epoll_wrapper.h"
35
36 /* This polling engine is only relevant on linux kernels supporting epoll() */
grpc_is_epollexclusive_available(void)37 bool grpc_is_epollexclusive_available(void) {
38 static bool logged_why_not = false;
39
40 int fd = epoll_create1(EPOLL_CLOEXEC);
41 if (fd < 0) {
42 if (!logged_why_not) {
43 gpr_log(GPR_DEBUG,
44 "epoll_create1 failed with error: %d. Not using epollex polling "
45 "engine.",
46 fd);
47 logged_why_not = true;
48 }
49 return false;
50 }
51 int evfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
52 if (evfd < 0) {
53 if (!logged_why_not) {
54 gpr_log(GPR_DEBUG,
55 "eventfd failed with error: %d. Not using epollex polling "
56 "engine.",
57 fd);
58 logged_why_not = true;
59 }
60 close(fd);
61 return false;
62 }
63 struct epoll_event ev;
64 /* choose events that should cause an error on
65 EPOLLEXCLUSIVE enabled kernels - specifically the combination of
66 EPOLLONESHOT and EPOLLEXCLUSIVE */
67 ev.events =
68 static_cast<uint32_t>(EPOLLET | EPOLLIN | EPOLLEXCLUSIVE | EPOLLONESHOT);
69 ev.data.ptr = nullptr;
70 if (epoll_ctl(fd, EPOLL_CTL_ADD, evfd, &ev) != 0) {
71 if (errno != EINVAL) {
72 if (!logged_why_not) {
73 gpr_log(
74 GPR_ERROR,
75 "epoll_ctl with EPOLLEXCLUSIVE | EPOLLONESHOT failed with error: "
76 "%d. Not using epollex polling engine.",
77 errno);
78 logged_why_not = true;
79 }
80 close(fd);
81 close(evfd);
82 return false;
83 }
84 } else {
85 if (!logged_why_not) {
86 gpr_log(GPR_DEBUG,
87 "epoll_ctl with EPOLLEXCLUSIVE | EPOLLONESHOT succeeded. This is "
88 "evidence of no EPOLLEXCLUSIVE support. Not using "
89 "epollex polling engine.");
90 logged_why_not = true;
91 }
92 close(fd);
93 close(evfd);
94 return false;
95 }
96 close(evfd);
97 close(fd);
98 return true;
99 }
100
101 #else
102
grpc_is_epollexclusive_available(void)103 bool grpc_is_epollexclusive_available(void) { return false; }
104
105 #endif
106