2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-02 07:35:26 +00:00

Get rid of locking during UDP and TCP listen

We already have a synchronization mechanism when starting the UDP and
TCP listener children - barriers.  Change how we start the first-born
child (tid == 0), so we don't have to race for sock->parent->result and
sock->parent->fd.
This commit is contained in:
Ondřej Surý
2023-01-04 12:21:00 +01:00
parent 7900cbd9a9
commit d06602f036
3 changed files with 48 additions and 72 deletions

View File

@@ -663,8 +663,6 @@ nmsocket_cleanup(isc_nmsocket_t *sock) {
sock->magic = 0;
isc_mutex_destroy(&sock->lock);
/* Don't free child socket */
if (sock->parent == NULL) {
REQUIRE(sock->tid == isc_tid());
@@ -858,8 +856,6 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc__networker_t *worker,
.active_link = ISC_LINK_INITIALIZER,
};
isc_mutex_init(&sock->lock);
if (iface != NULL) {
family = iface->type.sa.sa_family;
sock->iface = *iface;

View File

@@ -417,20 +417,23 @@ isc_nm_listentcp(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface,
fd = isc__nm_tcp_lb_socket(mgr, iface->type.sa.sa_family);
}
start_tcp_child(mgr, iface, sock, fd, 0);
result = sock->children[0].result;
INSIST(result != ISC_R_UNSET);
for (size_t i = 1; i < sock->nchildren; i++) {
start_tcp_child(mgr, iface, sock, fd, i);
}
start_tcp_child(mgr, iface, sock, fd, 0);
isc_barrier_wait(&sock->listen_barrier);
if (!mgr->load_balance_sockets) {
isc__nm_closesocket(fd);
}
LOCK(&sock->lock);
result = sock->result;
UNLOCK(&sock->lock);
INSIST(result != ISC_R_UNSET);
for (size_t i = 1; i < sock->nchildren; i++) {
INSIST(result == sock->children[i].result);
}
atomic_store(&sock->active, true);
@@ -457,14 +460,12 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
isc_result_t result = ISC_R_UNSET;
REQUIRE(VALID_NMSOCK(ievent->sock));
REQUIRE(ievent->sock->tid == isc_tid());
REQUIRE(VALID_NMSOCK(ievent->sock->parent));
sock = ievent->sock;
sa_family = sock->iface.type.sa.sa_family;
REQUIRE(sock->type == isc_nm_tcpsocket);
REQUIRE(sock->parent != NULL);
REQUIRE(sock->tid == isc_tid());
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
@@ -499,25 +500,17 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
goto done;
}
} else {
LOCK(&sock->parent->lock);
if (sock->parent->fd == -1) {
} else if (sock->tid == 0) {
r = isc__nm_tcp_freebind(&sock->uv_handle.tcp,
&sock->iface.type.sa, flags);
if (r < 0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
UNLOCK(&sock->parent->lock);
goto done;
}
sock->parent->uv_handle.tcp.flags =
sock->uv_handle.tcp.flags;
sock->parent->fd = sock->fd;
sock->parent->uv_handle.tcp.flags = sock->uv_handle.tcp.flags;
} else {
/* The socket is already bound, just copy the flags */
sock->uv_handle.tcp.flags =
sock->parent->uv_handle.tcp.flags;
}
UNLOCK(&sock->parent->lock);
sock->uv_handle.tcp.flags = sock->parent->uv_handle.tcp.flags;
}
isc__nm_set_network_buffers(sock->worker->netmgr,
@@ -546,16 +539,13 @@ done:
sock->pquota = NULL;
}
LOCK(&sock->parent->lock);
if (sock->parent->result == ISC_R_UNSET) {
sock->parent->result = result;
} else {
REQUIRE(sock->parent->result == result);
}
UNLOCK(&sock->parent->lock);
sock->result = result;
REQUIRE(!worker->loop->paused);
if (sock->tid != 0) {
isc_barrier_wait(&sock->parent->listen_barrier);
}
}
static void

View File

@@ -163,20 +163,23 @@ isc_nm_listenudp(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface,
fd = isc__nm_udp_lb_socket(mgr, iface->type.sa.sa_family);
}
start_udp_child(mgr, iface, sock, fd, 0);
result = sock->children[0].result;
INSIST(result != ISC_R_UNSET);
for (size_t i = 1; i < sock->nchildren; i++) {
start_udp_child(mgr, iface, sock, fd, i);
}
start_udp_child(mgr, iface, sock, fd, 0);
isc_barrier_wait(&sock->listen_barrier);
if (!mgr->load_balance_sockets) {
isc__nm_closesocket(fd);
}
LOCK(&sock->lock);
result = sock->result;
UNLOCK(&sock->lock);
INSIST(result != ISC_R_UNSET);
for (size_t i = 1; i < sock->nchildren; i++) {
INSIST(result == sock->children[i].result);
}
atomic_store(&sock->active, true);
@@ -332,7 +335,6 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
isc_nm_t *mgr = NULL;
REQUIRE(VALID_NMSOCK(ievent->sock));
REQUIRE(ievent->sock->tid == isc_tid());
REQUIRE(VALID_NMSOCK(ievent->sock->parent));
sock = ievent->sock;
@@ -340,7 +342,6 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
mgr = sock->worker->netmgr;
REQUIRE(sock->type == isc_nm_udpsocket);
REQUIRE(sock->parent != NULL);
REQUIRE(sock->tid == isc_tid());
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
@@ -379,27 +380,19 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
goto done;
}
} else {
LOCK(&sock->parent->lock);
if (sock->parent->fd == -1) {
} else if (sock->tid == 0) {
/* This thread is first, bind the socket */
r = isc__nm_udp_freebind(&sock->uv_handle.udp,
&sock->parent->iface.type.sa,
uv_bind_flags);
if (r < 0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
UNLOCK(&sock->parent->lock);
goto done;
}
sock->parent->uv_handle.udp.flags =
sock->uv_handle.udp.flags;
sock->parent->fd = sock->fd;
sock->parent->uv_handle.udp.flags = sock->uv_handle.udp.flags;
} else {
/* The socket is already bound, just copy the flags */
sock->uv_handle.udp.flags =
sock->parent->uv_handle.udp.flags;
}
UNLOCK(&sock->parent->lock);
sock->uv_handle.udp.flags = sock->parent->uv_handle.udp.flags;
}
isc__nm_set_network_buffers(mgr, &sock->uv_handle.handle);
@@ -417,16 +410,13 @@ done:
result = isc_uverr2result(r);
atomic_fetch_add(&sock->parent->rchildren, 1);
LOCK(&sock->parent->lock);
if (sock->parent->result == ISC_R_UNSET) {
sock->parent->result = result;
} else {
REQUIRE(sock->parent->result == result);
}
UNLOCK(&sock->parent->lock);
sock->result = result;
REQUIRE(!worker->loop->paused);
if (sock->tid != 0) {
isc_barrier_wait(&sock->parent->listen_barrier);
}
}
static void