|
|
|
@ -969,12 +969,6 @@ static grpc_fd *fd_create(int fd, const char *name) { |
|
|
|
|
return new_fd; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
static bool fd_is_orphaned(grpc_fd *fd) { |
|
|
|
|
return (gpr_atm_acq_load(&fd->refst) & 1) == 0; |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
static int fd_wrapped_fd(grpc_fd *fd) { |
|
|
|
|
int ret_fd = -1; |
|
|
|
|
gpr_mu_lock(&fd->po.mu); |
|
|
|
@ -1812,275 +1806,10 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, |
|
|
|
|
POLL_OBJ_FD); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, |
|
|
|
|
grpc_fd *fd) { |
|
|
|
|
GPR_TIMER_BEGIN("pollset_add_fd", 0); |
|
|
|
|
|
|
|
|
|
grpc_error *error = GRPC_ERROR_NONE; |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&pollset->po.mu); |
|
|
|
|
gpr_mu_lock(&fd->po.mu); |
|
|
|
|
|
|
|
|
|
polling_island *pi_new = NULL; |
|
|
|
|
|
|
|
|
|
retry: |
|
|
|
|
/* 1) If fd->po.pi and pollset->po.pi are both non-NULL and
|
|
|
|
|
* equal, do nothing. |
|
|
|
|
* 2) If fd->po.pi and pollset->po.pi are both NULL, create |
|
|
|
|
* a new polling island (with a refcount of 2) and make the polling_island |
|
|
|
|
* fields in both fd and pollset to point to the new island |
|
|
|
|
* 3) If one of fd->po.pi or pollset->po.pi is NULL, update |
|
|
|
|
* the NULL polling_island field to point to the non-NULL polling_island |
|
|
|
|
* field (ensure that the refcount on the polling island is incremented by |
|
|
|
|
* 1 to account for the newly added reference) |
|
|
|
|
* 4) Finally, if fd->po.pi and pollset->po.pi are non-NULL |
|
|
|
|
* and different, merge both the polling islands and update the |
|
|
|
|
* polling_island fields in both fd and pollset to point to the merged |
|
|
|
|
* polling island. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
if (fd->orphaned) { |
|
|
|
|
gpr_mu_unlock(&fd->po.mu); |
|
|
|
|
gpr_mu_unlock(&pollset->po.mu); |
|
|
|
|
/* early out */ |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (fd->po.pi == pollset->po.pi) { |
|
|
|
|
pi_new = fd->po.pi; |
|
|
|
|
if (pi_new == NULL) { |
|
|
|
|
/* Unlock before creating a new polling island: the polling island will
|
|
|
|
|
create a workqueue which creates a file descriptor, and holding an fd |
|
|
|
|
lock here can eventually cause a loop to appear to TSAN (making it |
|
|
|
|
unhappy). We don't think it's a real loop (there's an epoch point where |
|
|
|
|
that loop possibility disappears), but the advantages of keeping TSAN |
|
|
|
|
happy outweigh any performance advantage we might have by keeping the |
|
|
|
|
lock held. */ |
|
|
|
|
gpr_mu_unlock(&fd->po.mu); |
|
|
|
|
pi_new = polling_island_create(exec_ctx, fd, &error); |
|
|
|
|
gpr_mu_lock(&fd->po.mu); |
|
|
|
|
/* Need to reverify any assumptions made between the initial lock and
|
|
|
|
|
getting to this branch: if they've changed, we need to throw away our |
|
|
|
|
work and figure things out again. */ |
|
|
|
|
if (fd->po.pi != NULL) { |
|
|
|
|
GRPC_POLLING_TRACE( |
|
|
|
|
"pollset_add_fd: Raced creating new polling island. pi_new: %p " |
|
|
|
|
"(fd: %d, pollset: %p)", |
|
|
|
|
(void *)pi_new, fd->fd, (void *)pollset); |
|
|
|
|
|
|
|
|
|
/* No need to lock 'pi_new' here since this is a new polling island and
|
|
|
|
|
* no one has a reference to it yet */ |
|
|
|
|
polling_island_remove_all_fds_locked(pi_new, true, &error); |
|
|
|
|
|
|
|
|
|
/* Ref and unref so that the polling island gets deleted during unref */ |
|
|
|
|
PI_ADD_REF(pi_new, "dance_of_destruction"); |
|
|
|
|
PI_UNREF(exec_ctx, pi_new, "dance_of_destruction"); |
|
|
|
|
goto retry; |
|
|
|
|
} else { |
|
|
|
|
GRPC_POLLING_TRACE( |
|
|
|
|
"pollset_add_fd: Created new polling island. pi_new: %p (fd: %d, " |
|
|
|
|
"pollset: %p)", |
|
|
|
|
(void *)pi_new, fd->fd, (void *)pollset); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (fd->po.pi == NULL) { |
|
|
|
|
pi_new = polling_island_lock(pollset->po.pi); |
|
|
|
|
polling_island_add_fds_locked(pi_new, &fd, 1, true, &error); |
|
|
|
|
gpr_mu_unlock(&pi_new->mu); |
|
|
|
|
|
|
|
|
|
GRPC_POLLING_TRACE( |
|
|
|
|
"pollset_add_fd: fd->pi was NULL. pi_new: %p (fd: %d, pollset: %p, " |
|
|
|
|
"pollset->pi: %p)", |
|
|
|
|
(void *)pi_new, fd->fd, (void *)pollset, (void *)pollset->po.pi); |
|
|
|
|
} else if (pollset->po.pi == NULL) { |
|
|
|
|
pi_new = polling_island_lock(fd->po.pi); |
|
|
|
|
gpr_mu_unlock(&pi_new->mu); |
|
|
|
|
|
|
|
|
|
GRPC_POLLING_TRACE( |
|
|
|
|
"pollset_add_fd: pollset->pi was NULL. pi_new: %p (fd: %d, pollset: " |
|
|
|
|
"%p, fd->pi: %p", |
|
|
|
|
(void *)pi_new, fd->fd, (void *)pollset, (void *)fd->po.pi); |
|
|
|
|
} else { |
|
|
|
|
pi_new = polling_island_merge(fd->po.pi, pollset->po.pi, &error); |
|
|
|
|
GRPC_POLLING_TRACE( |
|
|
|
|
"pollset_add_fd: polling islands merged. pi_new: %p (fd: %d, pollset: " |
|
|
|
|
"%p, fd->pi: %p, pollset->pi: %p)", |
|
|
|
|
(void *)pi_new, fd->fd, (void *)pollset, (void *)fd->po.pi, |
|
|
|
|
(void *)pollset->po.pi); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* At this point, pi_new is the polling island that both fd->po.pi
|
|
|
|
|
and pollset->po.pi must be pointing to */ |
|
|
|
|
|
|
|
|
|
if (fd->po.pi != pi_new) { |
|
|
|
|
PI_ADD_REF(pi_new, "fd"); |
|
|
|
|
if (fd->po.pi != NULL) { |
|
|
|
|
PI_UNREF(exec_ctx, fd->po.pi, "fd"); |
|
|
|
|
} |
|
|
|
|
fd->po.pi = pi_new; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (pollset->po.pi != pi_new) { |
|
|
|
|
PI_ADD_REF(pi_new, "ps"); |
|
|
|
|
if (pollset->po.pi != NULL) { |
|
|
|
|
PI_UNREF(exec_ctx, pollset->po.pi, "ps"); |
|
|
|
|
} |
|
|
|
|
pollset->po.pi = pi_new; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gpr_mu_unlock(&fd->po.mu); |
|
|
|
|
gpr_mu_unlock(&pollset->po.mu); |
|
|
|
|
|
|
|
|
|
GRPC_LOG_IF_ERROR("pollset_add_fd", error); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* Pollset-set Definitions |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
static grpc_pollset_set *pollset_set_create(void) { |
|
|
|
|
grpc_pollset_set *pollset_set = gpr_malloc(sizeof(*pollset_set)); |
|
|
|
|
memset(pollset_set, 0, sizeof(*pollset_set)); |
|
|
|
|
gpr_mu_init(&pollset_set->po.mu); |
|
|
|
|
return pollset_set; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pollset_set_destroy(grpc_pollset_set *pollset_set) { |
|
|
|
|
size_t i; |
|
|
|
|
gpr_mu_destroy(&pollset_set->po.mu); |
|
|
|
|
for (i = 0; i < pollset_set->fd_count; i++) { |
|
|
|
|
GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); |
|
|
|
|
} |
|
|
|
|
gpr_free(pollset_set->pollsets); |
|
|
|
|
gpr_free(pollset_set->pollset_sets); |
|
|
|
|
gpr_free(pollset_set->fds); |
|
|
|
|
gpr_free(pollset_set); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_pollset_set *pollset_set, grpc_fd *fd) { |
|
|
|
|
size_t i; |
|
|
|
|
gpr_mu_lock(&pollset_set->po.mu); |
|
|
|
|
if (pollset_set->fd_count == pollset_set->fd_capacity) { |
|
|
|
|
pollset_set->fd_capacity = GPR_MAX(8, 2 * pollset_set->fd_capacity); |
|
|
|
|
pollset_set->fds = gpr_realloc( |
|
|
|
|
pollset_set->fds, pollset_set->fd_capacity * sizeof(*pollset_set->fds)); |
|
|
|
|
} |
|
|
|
|
GRPC_FD_REF(fd, "pollset_set"); |
|
|
|
|
pollset_set->fds[pollset_set->fd_count++] = fd; |
|
|
|
|
for (i = 0; i < pollset_set->pollset_count; i++) { |
|
|
|
|
pollset_add_fd(exec_ctx, pollset_set->pollsets[i], fd); |
|
|
|
|
} |
|
|
|
|
for (i = 0; i < pollset_set->pollset_set_count; i++) { |
|
|
|
|
pollset_set_add_fd(exec_ctx, pollset_set->pollset_sets[i], fd); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&pollset_set->po.mu); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_pollset_set *pollset_set, grpc_fd *fd) { |
|
|
|
|
size_t i; |
|
|
|
|
gpr_mu_lock(&pollset_set->po.mu); |
|
|
|
|
for (i = 0; i < pollset_set->fd_count; i++) { |
|
|
|
|
if (pollset_set->fds[i] == fd) { |
|
|
|
|
pollset_set->fd_count--; |
|
|
|
|
GPR_SWAP(grpc_fd *, pollset_set->fds[i], |
|
|
|
|
pollset_set->fds[pollset_set->fd_count]); |
|
|
|
|
GRPC_FD_UNREF(fd, "pollset_set"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (i = 0; i < pollset_set->pollset_set_count; i++) { |
|
|
|
|
pollset_set_del_fd(exec_ctx, pollset_set->pollset_sets[i], fd); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&pollset_set->po.mu); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_pollset_set *pollset_set, |
|
|
|
|
grpc_pollset *pollset) { |
|
|
|
|
size_t i, j; |
|
|
|
|
gpr_mu_lock(&pollset_set->po.mu); |
|
|
|
|
if (pollset_set->pollset_count == pollset_set->pollset_capacity) { |
|
|
|
|
pollset_set->pollset_capacity = |
|
|
|
|
GPR_MAX(8, 2 * pollset_set->pollset_capacity); |
|
|
|
|
pollset_set->pollsets = |
|
|
|
|
gpr_realloc(pollset_set->pollsets, pollset_set->pollset_capacity * |
|
|
|
|
sizeof(*pollset_set->pollsets)); |
|
|
|
|
} |
|
|
|
|
pollset_set->pollsets[pollset_set->pollset_count++] = pollset; |
|
|
|
|
for (i = 0, j = 0; i < pollset_set->fd_count; i++) { |
|
|
|
|
if (fd_is_orphaned(pollset_set->fds[i])) { |
|
|
|
|
GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); |
|
|
|
|
} else { |
|
|
|
|
pollset_add_fd(exec_ctx, pollset, pollset_set->fds[i]); |
|
|
|
|
pollset_set->fds[j++] = pollset_set->fds[i]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
pollset_set->fd_count = j; |
|
|
|
|
gpr_mu_unlock(&pollset_set->po.mu); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_pollset_set *pollset_set, |
|
|
|
|
grpc_pollset *pollset) { |
|
|
|
|
size_t i; |
|
|
|
|
gpr_mu_lock(&pollset_set->po.mu); |
|
|
|
|
for (i = 0; i < pollset_set->pollset_count; i++) { |
|
|
|
|
if (pollset_set->pollsets[i] == pollset) { |
|
|
|
|
pollset_set->pollset_count--; |
|
|
|
|
GPR_SWAP(grpc_pollset *, pollset_set->pollsets[i], |
|
|
|
|
pollset_set->pollsets[pollset_set->pollset_count]); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&pollset_set->po.mu); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_pollset_set *bag, |
|
|
|
|
grpc_pollset_set *item) { |
|
|
|
|
size_t i, j; |
|
|
|
|
gpr_mu_lock(&bag->po.mu); |
|
|
|
|
if (bag->pollset_set_count == bag->pollset_set_capacity) { |
|
|
|
|
bag->pollset_set_capacity = GPR_MAX(8, 2 * bag->pollset_set_capacity); |
|
|
|
|
bag->pollset_sets = |
|
|
|
|
gpr_realloc(bag->pollset_sets, |
|
|
|
|
bag->pollset_set_capacity * sizeof(*bag->pollset_sets)); |
|
|
|
|
} |
|
|
|
|
bag->pollset_sets[bag->pollset_set_count++] = item; |
|
|
|
|
for (i = 0, j = 0; i < bag->fd_count; i++) { |
|
|
|
|
if (fd_is_orphaned(bag->fds[i])) { |
|
|
|
|
GRPC_FD_UNREF(bag->fds[i], "pollset_set"); |
|
|
|
|
} else { |
|
|
|
|
pollset_set_add_fd(exec_ctx, item, bag->fds[i]); |
|
|
|
|
bag->fds[j++] = bag->fds[i]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
bag->fd_count = j; |
|
|
|
|
gpr_mu_unlock(&bag->po.mu); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_pollset_set *bag, |
|
|
|
|
grpc_pollset_set *item) { |
|
|
|
|
size_t i; |
|
|
|
|
gpr_mu_lock(&bag->po.mu); |
|
|
|
|
for (i = 0; i < bag->pollset_set_count; i++) { |
|
|
|
|
if (bag->pollset_sets[i] == item) { |
|
|
|
|
bag->pollset_set_count--; |
|
|
|
|
GPR_SWAP(grpc_pollset_set *, bag->pollset_sets[i], |
|
|
|
|
bag->pollset_sets[bag->pollset_set_count]); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&bag->po.mu); |
|
|
|
|
} |
|
|
|
|
#endif // Pollset_set functions
|
|
|
|
|
|
|
|
|
|
static grpc_pollset_set *pollset_set_create(void) { |
|
|
|
|
grpc_pollset_set *pss = gpr_malloc(sizeof(*pss)); |
|
|
|
|
pss->po.pi = NULL; |
|
|
|
|