chromium/third_party/grpc/src/src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc

// Copyright 2022 The 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 <grpc/support/port_platform.h>

#include "src/core/lib/event_engine/posix_engine/ev_epoll1_linux.h"

#include <stdint.h>

#include <atomic>
#include <initializer_list>
#include <memory>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"

#include <grpc/event_engine/event_engine.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>

#include "src/core/lib/event_engine/poller.h"
#include "src/core/lib/event_engine/time_util.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/iomgr/port.h"

// This polling engine is only relevant on linux kernels supporting epoll
// epoll_create() or epoll_create1()
#ifdef GRPC_LINUX_EPOLL
#include <errno.h>
#include <limits.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <unistd.h>

#include "src/core/lib/event_engine/posix_engine/event_poller.h"
#include "src/core/lib/event_engine/posix_engine/lockfree_event.h"
#include "src/core/lib/event_engine/posix_engine/posix_engine_closure.h"
#include "src/core/lib/event_engine/posix_engine/wakeup_fd_posix.h"
#include "src/core/lib/event_engine/posix_engine/wakeup_fd_posix_default.h"
#include "src/core/lib/gprpp/fork.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/gprpp/strerror.h"
#include "src/core/lib/gprpp/sync.h"

#define MAX_EPOLL_EVENTS_HANDLED_PER_ITERATION

namespace grpc_event_engine {
namespace experimental {

class Epoll1EventHandle : public EventHandle {};

namespace {

int EpollCreateAndCloexec() {}

// Only used when GRPC_ENABLE_FORK_SUPPORT=1
std::list<Epoll1Poller*> fork_poller_list;

// Only used when GRPC_ENABLE_FORK_SUPPORT=1
Epoll1EventHandle* fork_fd_list_head =;
gpr_mu fork_fd_list_mu;

void ForkFdListAddHandle(Epoll1EventHandle* handle) {}

void ForkFdListRemoveHandle(Epoll1EventHandle* handle) {}

void ForkPollerListAddPoller(Epoll1Poller* poller) {}

void ForkPollerListRemovePoller(Epoll1Poller* poller) {}

bool InitEpoll1PollerLinux();

// Called by the child process's post-fork handler to close open fds,
// including the global epoll fd of each poller. This allows gRPC to shutdown in
// the child process without interfering with connections or RPCs ongoing in the
// parent.
void ResetEventManagerOnFork() {}

// It is possible that GLIBC has epoll but the underlying kernel doesn't.
// Create epoll_fd to make sure epoll support is available
bool InitEpoll1PollerLinux() {}

}  // namespace

void Epoll1EventHandle::OrphanHandle(PosixEngineClosure* on_done,
                                     int* release_fd,
                                     absl::string_view reason) {}

// if 'releasing_fd' is true, it means that we are going to detach the internal
// fd from grpc_fd structure (i.e which means we should not be calling
// shutdown() syscall on that fd)
void Epoll1EventHandle::HandleShutdownInternal(absl::Status why,
                                               bool releasing_fd) {}

Epoll1Poller::Epoll1Poller(Scheduler* scheduler)
    :{}

void Epoll1Poller::Shutdown() {}

void Epoll1Poller::Close() {}

Epoll1Poller::~Epoll1Poller() {}

EventHandle* Epoll1Poller::CreateHandle(int fd, absl::string_view /*name*/,
                                        bool track_err) {}

// Process the epoll events found by DoEpollWait() function.
// - g_epoll_set.cursor points to the index of the first event to be processed
// - This function then processes up-to max_epoll_events_to_handle and
//   updates the g_epoll_set.cursor.
// It returns true, it there was a Kick that forced invocation of this
// function. It also returns the list of closures to run to take action
// on file descriptors that became readable/writable.
bool Epoll1Poller::ProcessEpollEvents(int max_epoll_events_to_handle,
                                      Events& pending_events) {}

//  Do epoll_wait and store the events in g_epoll_set.events field. This does
//  not "process" any of the events yet; that is done in ProcessEpollEvents().
//  See ProcessEpollEvents() function for more details. It returns the number
// of events generated by epoll_wait.
int Epoll1Poller::DoEpollWait(EventEngine::Duration timeout) {}

// Might be called multiple times
void Epoll1EventHandle::ShutdownHandle(absl::Status why) {}

bool Epoll1EventHandle::IsHandleShutdown() {}

void Epoll1EventHandle::NotifyOnRead(PosixEngineClosure* on_read) {}

void Epoll1EventHandle::NotifyOnWrite(PosixEngineClosure* on_write) {}

void Epoll1EventHandle::NotifyOnError(PosixEngineClosure* on_error) {}

void Epoll1EventHandle::SetReadable() {}

void Epoll1EventHandle::SetWritable() {}

void Epoll1EventHandle::SetHasError() {}

// Polls the registered Fds for events until timeout is reached or there is a
// Kick(). If there is a Kick(), it collects and processes any previously
// un-processed events. If there are no un-processed events, it returns
// Poller::WorkResult::Kicked{}
Poller::WorkResult Epoll1Poller::Work(
    EventEngine::Duration timeout,
    absl::FunctionRef<void()> schedule_poll_again) {}

void Epoll1Poller::Kick() {}

Epoll1Poller* MakeEpoll1Poller(Scheduler* scheduler) {}

void Epoll1Poller::PrepareFork() {}

// TODO(vigneshbabu): implement
void Epoll1Poller::PostforkParent() {}

// TODO(vigneshbabu): implement
void Epoll1Poller::PostforkChild() {}

}  // namespace experimental
}  // namespace grpc_event_engine

#else  // defined(GRPC_LINUX_EPOLL)
#if defined(GRPC_POSIX_SOCKET_EV_EPOLL1)

namespace grpc_event_engine {
namespace experimental {

using ::grpc_event_engine::experimental::EventEngine;
using ::grpc_event_engine::experimental::Poller;

Epoll1Poller::Epoll1Poller(Scheduler* /* engine */) {
  grpc_core::Crash("unimplemented");
}

void Epoll1Poller::Shutdown() { grpc_core::Crash("unimplemented"); }

Epoll1Poller::~Epoll1Poller() { grpc_core::Crash("unimplemented"); }

EventHandle* Epoll1Poller::CreateHandle(int /*fd*/, absl::string_view /*name*/,
                                        bool /*track_err*/) {
  grpc_core::Crash("unimplemented");
}

bool Epoll1Poller::ProcessEpollEvents(int /*max_epoll_events_to_handle*/,
                                      Events& /*pending_events*/) {
  grpc_core::Crash("unimplemented");
}

int Epoll1Poller::DoEpollWait(EventEngine::Duration /*timeout*/) {
  grpc_core::Crash("unimplemented");
}

Poller::WorkResult Epoll1Poller::Work(
    EventEngine::Duration /*timeout*/,
    absl::FunctionRef<void()> /*schedule_poll_again*/) {
  grpc_core::Crash("unimplemented");
}

void Epoll1Poller::Kick() { grpc_core::Crash("unimplemented"); }

// If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return
// nullptr.
Epoll1Poller* MakeEpoll1Poller(Scheduler* /*scheduler*/) { return nullptr; }

void Epoll1Poller::PrepareFork() {}

void Epoll1Poller::PostforkParent() {}

void Epoll1Poller::PostforkChild() {}

}  // namespace experimental
}  // namespace grpc_event_engine

#endif  // defined(GRPC_POSIX_SOCKET_EV_EPOLL1)
#endif  // !defined(GRPC_LINUX_EPOLL)