Refine neighbourhood reassignment
diff --git a/src/core/lib/iomgr/ev_epoll1_linux.c b/src/core/lib/iomgr/ev_epoll1_linux.c
index fcccccc..99e4441 100644
--- a/src/core/lib/iomgr/ev_epoll1_linux.c
+++ b/src/core/lib/iomgr/ev_epoll1_linux.c
@@ -117,6 +117,7 @@
struct grpc_pollset {
gpr_mu mu;
pollset_neighbourhood *neighbourhood;
+ bool reassigning_neighbourhood;
grpc_pollset_worker *root_worker;
bool kicked_without_poller;
bool seen_inactive;
@@ -394,20 +395,33 @@
*mu = &pollset->mu;
pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()];
pollset->seen_inactive = true;
- pollset->next = pollset->prev = pollset;
}
static void pollset_destroy(grpc_pollset *pollset) {
+ gpr_mu_lock(&pollset->mu);
if (!pollset->seen_inactive) {
- gpr_mu_lock(&pollset->neighbourhood->mu);
- pollset->prev->next = pollset->next;
- pollset->next->prev = pollset->prev;
- if (pollset == pollset->neighbourhood->active_root) {
- pollset->neighbourhood->active_root =
- pollset->next == pollset ? NULL : pollset->next;
+ pollset_neighbourhood *neighbourhood = pollset->neighbourhood;
+ gpr_mu_unlock(&pollset->mu);
+retry_lock_neighbourhood:
+ gpr_mu_lock(&neighbourhood->mu);
+ gpr_mu_lock(&pollset->mu);
+ if (!pollset->seen_inactive) {
+ if (pollset->neighbourhood != neighbourhood) {
+ gpr_mu_unlock(&neighbourhood->mu);
+ neighbourhood = pollset->neighbourhood;
+ gpr_mu_unlock(&pollset->mu);
+ goto retry_lock_neighbourhood;
+ }
+ pollset->prev->next = pollset->next;
+ pollset->next->prev = pollset->prev;
+ if (pollset == pollset->neighbourhood->active_root) {
+ pollset->neighbourhood->active_root =
+ pollset->next == pollset ? NULL : pollset->next;
+ }
}
gpr_mu_unlock(&pollset->neighbourhood->mu);
}
+ gpr_mu_unlock(&pollset->mu);
gpr_mu_destroy(&pollset->mu);
}
@@ -543,8 +557,13 @@
if (pollset->seen_inactive) {
// pollset has been observed to be inactive, we need to move back to the
// active list
- pollset_neighbourhood *neighbourhood = pollset->neighbourhood =
- &g_neighbourhoods[choose_neighbourhood()];
+ bool is_reassigning = false;
+ if (!pollset->reassigning_neighbourhood) {
+ is_reassigning = true;
+ pollset->reassigning_neighbourhood = true;
+ pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()];
+ }
+ pollset_neighbourhood *neighbourhood = pollset->neighbourhood;
gpr_mu_unlock(&pollset->mu);
// pollset unlocked: state may change (even worker->kick_state)
retry_lock_neighbourhood:
@@ -569,6 +588,10 @@
pollset->next->prev = pollset->prev->next = pollset;
}
}
+ if (is_reassigning) {
+ GPR_ASSERT(pollset->reassigning_neighbourhood);
+ pollset->reassigning_neighbourhood = false;
+ }
gpr_mu_unlock(&neighbourhood->mu);
}
worker_insert(pollset, worker);
@@ -629,14 +652,11 @@
if (!found_worker) {
inspect->seen_inactive = true;
if (inspect == neighbourhood->active_root) {
- if (inspect->next == neighbourhood->active_root) {
- neighbourhood->active_root = NULL;
- } else {
- neighbourhood->active_root = inspect->next;
- }
+ neighbourhood->active_root = inspect->next == inspect ? NULL : inspect->next;
}
inspect->next->prev = inspect->prev;
inspect->prev->next = inspect->next;
+ inspect->next = inspect->prev = NULL;
}
gpr_mu_unlock(&inspect->mu);
} while (!found_worker);