/* * * Copyright 2017 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include "src/core/lib/iomgr/is_epollexclusive_available.h" #include "src/core/lib/iomgr/port.h" #ifdef GRPC_LINUX_EPOLL_CREATE1 #include #include #include #include #include #include "src/core/lib/iomgr/sys_epoll_wrapper.h" /* This polling engine is only relevant on linux kernels supporting epoll() */ bool grpc_is_epollexclusive_available(void) { static bool logged_why_not = false; int fd = epoll_create1(EPOLL_CLOEXEC); if (fd < 0) { if (!logged_why_not) { gpr_log(GPR_DEBUG, "epoll_create1 failed with error: %d. Not using epollex polling " "engine.", fd); logged_why_not = true; } return false; } int evfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); if (evfd < 0) { if (!logged_why_not) { gpr_log(GPR_DEBUG, "eventfd failed with error: %d. Not using epollex polling " "engine.", fd); logged_why_not = true; } close(fd); return false; } struct epoll_event ev; /* choose events that should cause an error on EPOLLEXCLUSIVE enabled kernels - specifically the combination of EPOLLONESHOT and EPOLLEXCLUSIVE */ ev.events = static_cast(EPOLLET | EPOLLIN | EPOLLEXCLUSIVE | EPOLLONESHOT); ev.data.ptr = nullptr; if (epoll_ctl(fd, EPOLL_CTL_ADD, evfd, &ev) != 0) { if (errno != EINVAL) { if (!logged_why_not) { gpr_log( GPR_ERROR, "epoll_ctl with EPOLLEXCLUSIVE | EPOLLONESHOT failed with error: " "%d. Not using epollex polling engine.", errno); logged_why_not = true; } close(fd); close(evfd); return false; } } else { if (!logged_why_not) { gpr_log(GPR_DEBUG, "epoll_ctl with EPOLLEXCLUSIVE | EPOLLONESHOT succeeded. This is " "evidence of no EPOLLEXCLUSIVE support. Not using " "epollex polling engine."); logged_why_not = true; } close(fd); close(evfd); return false; } // Check that EPOLLEXCLUSIVE is supported at all. ev.events = static_cast(EPOLLET | EPOLLIN | EPOLLEXCLUSIVE); if (epoll_ctl(fd, EPOLL_CTL_ADD, evfd, &ev) != 0) { if (!logged_why_not) { gpr_log(GPR_DEBUG, "epoll_ctl with EPOLLEXCLUSIVE failed with error: " "%d. Not using epollex polling engine.", errno); logged_why_not = true; } close(fd); close(evfd); return false; } close(evfd); close(fd); return true; } #else bool grpc_is_epollexclusive_available(void) { return false; } #endif