|
|
|
@ -160,6 +160,7 @@ struct grpc_fd { |
|
|
|
|
|
|
|
|
|
grpc_core::ManualConstructor<grpc_core::LockfreeEvent> read_closure; |
|
|
|
|
grpc_core::ManualConstructor<grpc_core::LockfreeEvent> write_closure; |
|
|
|
|
grpc_core::ManualConstructor<grpc_core::LockfreeEvent> error_closure; |
|
|
|
|
|
|
|
|
|
struct grpc_fd* freelist_next; |
|
|
|
|
grpc_closure* on_done_closure; |
|
|
|
@ -169,6 +170,9 @@ struct grpc_fd { |
|
|
|
|
gpr_atm read_notifier_pollset; |
|
|
|
|
|
|
|
|
|
grpc_iomgr_object iomgr_object; |
|
|
|
|
|
|
|
|
|
/* Do we need to track EPOLLERR events separately? */ |
|
|
|
|
bool track_err; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void fd_global_init(void); |
|
|
|
@ -294,6 +298,7 @@ static void fd_destroy(void* arg, grpc_error* error) { |
|
|
|
|
|
|
|
|
|
fd->read_closure->DestroyEvent(); |
|
|
|
|
fd->write_closure->DestroyEvent(); |
|
|
|
|
fd->error_closure->DestroyEvent(); |
|
|
|
|
|
|
|
|
|
gpr_mu_unlock(&fd_freelist_mu); |
|
|
|
|
} |
|
|
|
@ -333,7 +338,7 @@ static void fd_global_shutdown(void) { |
|
|
|
|
gpr_mu_destroy(&fd_freelist_mu); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static grpc_fd* fd_create(int fd, const char* name) { |
|
|
|
|
static grpc_fd* fd_create(int fd, const char* name, bool track_err) { |
|
|
|
|
grpc_fd* new_fd = nullptr; |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&fd_freelist_mu); |
|
|
|
@ -347,6 +352,7 @@ static grpc_fd* fd_create(int fd, const char* name) { |
|
|
|
|
new_fd = static_cast<grpc_fd*>(gpr_malloc(sizeof(grpc_fd))); |
|
|
|
|
new_fd->read_closure.Init(); |
|
|
|
|
new_fd->write_closure.Init(); |
|
|
|
|
new_fd->error_closure.Init(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gpr_mu_init(&new_fd->pollable_mu); |
|
|
|
@ -354,8 +360,10 @@ static grpc_fd* fd_create(int fd, const char* name) { |
|
|
|
|
new_fd->pollable_obj = nullptr; |
|
|
|
|
gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); |
|
|
|
|
new_fd->fd = fd; |
|
|
|
|
new_fd->track_err = track_err; |
|
|
|
|
new_fd->read_closure->InitEvent(); |
|
|
|
|
new_fd->write_closure->InitEvent(); |
|
|
|
|
new_fd->error_closure->InitEvent(); |
|
|
|
|
gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); |
|
|
|
|
|
|
|
|
|
new_fd->freelist_next = nullptr; |
|
|
|
@ -424,6 +432,7 @@ static void fd_shutdown(grpc_fd* fd, grpc_error* why) { |
|
|
|
|
if (fd->read_closure->SetShutdown(GRPC_ERROR_REF(why))) { |
|
|
|
|
shutdown(fd->fd, SHUT_RDWR); |
|
|
|
|
fd->write_closure->SetShutdown(GRPC_ERROR_REF(why)); |
|
|
|
|
fd->error_closure->SetShutdown(GRPC_ERROR_REF(why)); |
|
|
|
|
} |
|
|
|
|
GRPC_ERROR_UNREF(why); |
|
|
|
|
} |
|
|
|
@ -436,6 +445,10 @@ static void fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) { |
|
|
|
|
fd->write_closure->NotifyOn(closure); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) { |
|
|
|
|
fd->error_closure->NotifyOn(closure); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* Pollable Definitions |
|
|
|
|
*/ |
|
|
|
@ -524,7 +537,11 @@ static grpc_error* pollable_add_fd(pollable* p, grpc_fd* fd) { |
|
|
|
|
struct epoll_event ev_fd; |
|
|
|
|
ev_fd.events = |
|
|
|
|
static_cast<uint32_t>(EPOLLET | EPOLLIN | EPOLLOUT | EPOLLEXCLUSIVE); |
|
|
|
|
ev_fd.data.ptr = fd; |
|
|
|
|
/* Use the second least significant bit of ev_fd.data.ptr to store track_err
|
|
|
|
|
* to avoid synchronization issues when accessing it after receiving an event. |
|
|
|
|
*/ |
|
|
|
|
ev_fd.data.ptr = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(fd) | |
|
|
|
|
(fd->track_err ? 2 : 0)); |
|
|
|
|
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd->fd, &ev_fd) != 0) { |
|
|
|
|
switch (errno) { |
|
|
|
|
case EEXIST: |
|
|
|
@ -724,6 +741,8 @@ static void fd_become_readable(grpc_fd* fd, grpc_pollset* notifier) { |
|
|
|
|
|
|
|
|
|
static void fd_become_writable(grpc_fd* fd) { fd->write_closure->SetReady(); } |
|
|
|
|
|
|
|
|
|
static void fd_has_errors(grpc_fd* fd) { fd->error_closure->SetReady(); } |
|
|
|
|
|
|
|
|
|
static grpc_error* fd_get_or_become_pollable(grpc_fd* fd, pollable** p) { |
|
|
|
|
gpr_mu_lock(&fd->pollable_mu); |
|
|
|
|
grpc_error* error = GRPC_ERROR_NONE; |
|
|
|
@ -792,20 +811,28 @@ static grpc_error* pollable_process_events(grpc_pollset* pollset, |
|
|
|
|
(intptr_t)data_ptr)), |
|
|
|
|
err_desc); |
|
|
|
|
} else { |
|
|
|
|
grpc_fd* fd = static_cast<grpc_fd*>(data_ptr); |
|
|
|
|
bool cancel = (ev->events & (EPOLLERR | EPOLLHUP)) != 0; |
|
|
|
|
grpc_fd* fd = |
|
|
|
|
reinterpret_cast<grpc_fd*>(reinterpret_cast<intptr_t>(data_ptr) & ~2); |
|
|
|
|
bool track_err = reinterpret_cast<intptr_t>(data_ptr) & 2; |
|
|
|
|
bool cancel = (ev->events & EPOLLHUP) != 0; |
|
|
|
|
bool error = (ev->events & EPOLLERR) != 0; |
|
|
|
|
bool read_ev = (ev->events & (EPOLLIN | EPOLLPRI)) != 0; |
|
|
|
|
bool write_ev = (ev->events & EPOLLOUT) != 0; |
|
|
|
|
bool err_fallback = error && !track_err; |
|
|
|
|
|
|
|
|
|
if (grpc_polling_trace.enabled()) { |
|
|
|
|
gpr_log(GPR_DEBUG, |
|
|
|
|
"PS:%p got fd %p: cancel=%d read=%d " |
|
|
|
|
"write=%d", |
|
|
|
|
pollset, fd, cancel, read_ev, write_ev); |
|
|
|
|
} |
|
|
|
|
if (read_ev || cancel) { |
|
|
|
|
if (error && !err_fallback) { |
|
|
|
|
fd_has_errors(fd); |
|
|
|
|
} |
|
|
|
|
if (read_ev || cancel || err_fallback) { |
|
|
|
|
fd_become_readable(fd, pollset); |
|
|
|
|
} |
|
|
|
|
if (write_ev || cancel) { |
|
|
|
|
if (write_ev || cancel || err_fallback) { |
|
|
|
|
fd_become_writable(fd); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1447,6 +1474,7 @@ static void shutdown_engine(void) { |
|
|
|
|
|
|
|
|
|
static const grpc_event_engine_vtable vtable = { |
|
|
|
|
sizeof(grpc_pollset), |
|
|
|
|
true, |
|
|
|
|
|
|
|
|
|
fd_create, |
|
|
|
|
fd_wrapped_fd, |
|
|
|
@ -1454,6 +1482,7 @@ static const grpc_event_engine_vtable vtable = { |
|
|
|
|
fd_shutdown, |
|
|
|
|
fd_notify_on_read, |
|
|
|
|
fd_notify_on_write, |
|
|
|
|
fd_notify_on_error, |
|
|
|
|
fd_is_shutdown, |
|
|
|
|
fd_get_read_notifier_pollset, |
|
|
|
|
|
|
|
|
|