|
|
|
@ -153,7 +153,7 @@ static void fd_global_shutdown(void); |
|
|
|
|
* Polling island Declarations |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
// #define GRPC_PI_REF_COUNT_DEBUG
|
|
|
|
|
//#define GRPC_PI_REF_COUNT_DEBUG
|
|
|
|
|
#ifdef GRPC_PI_REF_COUNT_DEBUG |
|
|
|
|
|
|
|
|
|
#define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__) |
|
|
|
@ -174,7 +174,7 @@ typedef struct polling_island { |
|
|
|
|
Once the ref count becomes zero, this structure is destroyed which means |
|
|
|
|
we should ensure that there is never a scenario where a PI_ADD_REF() is |
|
|
|
|
racing with a PI_UNREF() that just made the ref_count zero. */ |
|
|
|
|
gpr_refcount ref_count; |
|
|
|
|
gpr_atm ref_count; |
|
|
|
|
|
|
|
|
|
/* Pointer to the polling_island this merged into.
|
|
|
|
|
* merged_to value is only set once in polling_island's lifetime (and that too |
|
|
|
@ -296,7 +296,7 @@ static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi); |
|
|
|
|
|
|
|
|
|
static void pi_add_ref_dbg(polling_island *pi, char *reason, char *file, |
|
|
|
|
int line) { |
|
|
|
|
long old_cnt = gpr_atm_acq_load(&(pi->ref_count.count)); |
|
|
|
|
long old_cnt = gpr_atm_acq_load(&pi->ref_count); |
|
|
|
|
pi_add_ref(pi); |
|
|
|
|
gpr_log(GPR_DEBUG, "Add ref pi: %p, old: %ld -> new:%ld (%s) - (%s, %d)", |
|
|
|
|
(void *)pi, old_cnt, old_cnt + 1, reason, file, line); |
|
|
|
@ -304,17 +304,22 @@ static void pi_add_ref_dbg(polling_island *pi, char *reason, char *file, |
|
|
|
|
|
|
|
|
|
static void pi_unref_dbg(grpc_exec_ctx *exec_ctx, polling_island *pi, |
|
|
|
|
char *reason, char *file, int line) { |
|
|
|
|
long old_cnt = gpr_atm_acq_load(&(pi->ref_count.count)); |
|
|
|
|
long old_cnt = gpr_atm_acq_load(&pi->ref_count); |
|
|
|
|
pi_unref(exec_ctx, pi); |
|
|
|
|
gpr_log(GPR_DEBUG, "Unref pi: %p, old:%ld -> new:%ld (%s) - (%s, %d)", |
|
|
|
|
(void *)pi, old_cnt, (old_cnt - 1), reason, file, line); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
static void pi_add_ref(polling_island *pi) { gpr_ref(&pi->ref_count); } |
|
|
|
|
static void pi_add_ref(polling_island *pi) { |
|
|
|
|
gpr_atm_no_barrier_fetch_add(&pi->ref_count, 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi) { |
|
|
|
|
/* If ref count went to zero, delete the polling island.
|
|
|
|
|
/* If ref count went to one, we're back to just the workqueue owning a ref.
|
|
|
|
|
Unref the workqueue to break the loop. |
|
|
|
|
|
|
|
|
|
If ref count went to zero, delete the polling island. |
|
|
|
|
Note that this deletion not be done under a lock. Once the ref count goes |
|
|
|
|
to zero, we are guaranteed that no one else holds a reference to the |
|
|
|
|
polling island (and that there is no racing pi_add_ref() call either). |
|
|
|
@ -322,12 +327,20 @@ static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi) { |
|
|
|
|
Also, if we are deleting the polling island and the merged_to field is |
|
|
|
|
non-empty, we should remove a ref to the merged_to polling island |
|
|
|
|
*/ |
|
|
|
|
if (gpr_unref(&pi->ref_count)) { |
|
|
|
|
polling_island *next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); |
|
|
|
|
polling_island_delete(exec_ctx, pi); |
|
|
|
|
if (next != NULL) { |
|
|
|
|
PI_UNREF(exec_ctx, next, "pi_delete"); /* Recursive call */ |
|
|
|
|
switch (gpr_atm_full_fetch_add(&pi->ref_count, -1)) { |
|
|
|
|
case 2: /* last external ref: the only one now owned is by the workqueue */ |
|
|
|
|
GRPC_WORKQUEUE_UNREF(exec_ctx, pi->workqueue, "polling_island"); |
|
|
|
|
break; |
|
|
|
|
case 1: { |
|
|
|
|
polling_island *next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); |
|
|
|
|
polling_island_delete(exec_ctx, pi); |
|
|
|
|
if (next != NULL) { |
|
|
|
|
PI_UNREF(exec_ctx, next, "pi_delete"); /* Recursive call */ |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case 0: |
|
|
|
|
GPR_UNREACHABLE_CODE(return ); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -478,7 +491,7 @@ static polling_island *polling_island_create(grpc_exec_ctx *exec_ctx, |
|
|
|
|
pi->epoll_fd = -1; |
|
|
|
|
pi->workqueue = NULL; |
|
|
|
|
|
|
|
|
|
gpr_ref_init(&pi->ref_count, 0); |
|
|
|
|
gpr_atm_rel_store(&pi->ref_count, 0); |
|
|
|
|
gpr_atm_rel_store(&pi->merged_to, (gpr_atm)NULL); |
|
|
|
|
|
|
|
|
|
pi->epoll_fd = epoll_create1(EPOLL_CLOEXEC); |
|
|
|
@ -501,7 +514,7 @@ static polling_island *polling_island_create(grpc_exec_ctx *exec_ctx, |
|
|
|
|
error); |
|
|
|
|
GPR_ASSERT(pi->workqueue->wakeup_read_fd->polling_island == NULL); |
|
|
|
|
pi->workqueue->wakeup_read_fd->polling_island = pi; |
|
|
|
|
PI_ADD_REF(pi, 1); |
|
|
|
|
PI_ADD_REF(pi, "fd"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
done: |
|
|
|
@ -525,7 +538,6 @@ static void polling_island_delete(grpc_exec_ctx *exec_ctx, polling_island *pi) { |
|
|
|
|
gpr_atm_rel_store(&pi->merged_to, (gpr_atm)NULL); |
|
|
|
|
|
|
|
|
|
close(pi->epoll_fd); |
|
|
|
|
GRPC_WORKQUEUE_UNREF(exec_ctx, pi->workqueue, "polling_island"); |
|
|
|
|
gpr_mu_destroy(&pi->mu); |
|
|
|
|
gpr_free(pi->fds); |
|
|
|
|
gpr_free(pi); |
|
|
|
@ -885,6 +897,7 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, |
|
|
|
|
const char *reason) { |
|
|
|
|
bool is_fd_closed = false; |
|
|
|
|
grpc_error *error = GRPC_ERROR_NONE; |
|
|
|
|
polling_island *unref_pi = NULL; |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&fd->mu); |
|
|
|
|
fd->on_done_closure = on_done; |
|
|
|
@ -918,7 +931,7 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, |
|
|
|
|
polling_island_remove_fd_locked(pi_latest, fd, is_fd_closed, &error); |
|
|
|
|
gpr_mu_unlock(&pi_latest->mu); |
|
|
|
|
|
|
|
|
|
PI_UNREF(exec_ctx, fd->polling_island, "fd_orphan"); |
|
|
|
|
unref_pi = fd->polling_island; |
|
|
|
|
fd->polling_island = NULL; |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&fd->pi_mu); |
|
|
|
@ -927,6 +940,9 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, |
|
|
|
|
|
|
|
|
|
gpr_mu_unlock(&fd->mu); |
|
|
|
|
UNREF_BY(fd, 2, reason); /* Drop the reference */ |
|
|
|
|
if (unref_pi != NULL) { |
|
|
|
|
PI_UNREF(exec_ctx, unref_pi, "fd_orphan"); |
|
|
|
|
} |
|
|
|
|
GRPC_LOG_IF_ERROR("fd_orphan", GRPC_ERROR_REF(error)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1595,6 +1611,8 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, |
|
|
|
|
|
|
|
|
|
gpr_mu_unlock(&fd->pi_mu); |
|
|
|
|
gpr_mu_unlock(&pollset->mu); |
|
|
|
|
|
|
|
|
|
GRPC_LOG_IF_ERROR("pollset_add_fd", error); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|