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; sock->magic = 0;
isc_mutex_destroy(&sock->lock);
/* Don't free child socket */ /* Don't free child socket */
if (sock->parent == NULL) { if (sock->parent == NULL) {
REQUIRE(sock->tid == isc_tid()); 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, .active_link = ISC_LINK_INITIALIZER,
}; };
isc_mutex_init(&sock->lock);
if (iface != NULL) { if (iface != NULL) {
family = iface->type.sa.sa_family; family = iface->type.sa.sa_family;
sock->iface = *iface; 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); 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++) { for (size_t i = 1; i < sock->nchildren; i++) {
start_tcp_child(mgr, iface, sock, fd, 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) { if (!mgr->load_balance_sockets) {
isc__nm_closesocket(fd); isc__nm_closesocket(fd);
} }
LOCK(&sock->lock); for (size_t i = 1; i < sock->nchildren; i++) {
result = sock->result; INSIST(result == sock->children[i].result);
UNLOCK(&sock->lock); }
INSIST(result != ISC_R_UNSET);
atomic_store(&sock->active, true); 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; isc_result_t result = ISC_R_UNSET;
REQUIRE(VALID_NMSOCK(ievent->sock)); REQUIRE(VALID_NMSOCK(ievent->sock));
REQUIRE(ievent->sock->tid == isc_tid());
REQUIRE(VALID_NMSOCK(ievent->sock->parent)); REQUIRE(VALID_NMSOCK(ievent->sock->parent));
sock = ievent->sock; sock = ievent->sock;
sa_family = sock->iface.type.sa.sa_family; sa_family = sock->iface.type.sa.sa_family;
REQUIRE(sock->type == isc_nm_tcpsocket); REQUIRE(sock->type == isc_nm_tcpsocket);
REQUIRE(sock->parent != NULL);
REQUIRE(sock->tid == isc_tid()); REQUIRE(sock->tid == isc_tid());
(void)isc__nm_socket_min_mtu(sock->fd, sa_family); (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); isc__nm_incstats(sock, STATID_BINDFAIL);
goto done; goto done;
} }
} else { } else if (sock->tid == 0) {
LOCK(&sock->parent->lock); r = isc__nm_tcp_freebind(&sock->uv_handle.tcp,
if (sock->parent->fd == -1) { &sock->iface.type.sa, flags);
r = isc__nm_tcp_freebind(&sock->uv_handle.tcp, if (r < 0) {
&sock->iface.type.sa, flags); isc__nm_incstats(sock, STATID_BINDFAIL);
if (r < 0) { goto done;
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;
} 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->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;
} }
isc__nm_set_network_buffers(sock->worker->netmgr, isc__nm_set_network_buffers(sock->worker->netmgr,
@@ -546,16 +539,13 @@ done:
sock->pquota = NULL; sock->pquota = NULL;
} }
LOCK(&sock->parent->lock); sock->result = result;
if (sock->parent->result == ISC_R_UNSET) {
sock->parent->result = result;
} else {
REQUIRE(sock->parent->result == result);
}
UNLOCK(&sock->parent->lock);
REQUIRE(!worker->loop->paused); REQUIRE(!worker->loop->paused);
isc_barrier_wait(&sock->parent->listen_barrier);
if (sock->tid != 0) {
isc_barrier_wait(&sock->parent->listen_barrier);
}
} }
static void 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); 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++) { for (size_t i = 1; i < sock->nchildren; i++) {
start_udp_child(mgr, iface, sock, fd, 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) { if (!mgr->load_balance_sockets) {
isc__nm_closesocket(fd); isc__nm_closesocket(fd);
} }
LOCK(&sock->lock); for (size_t i = 1; i < sock->nchildren; i++) {
result = sock->result; INSIST(result == sock->children[i].result);
UNLOCK(&sock->lock); }
INSIST(result != ISC_R_UNSET);
atomic_store(&sock->active, true); 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; isc_nm_t *mgr = NULL;
REQUIRE(VALID_NMSOCK(ievent->sock)); REQUIRE(VALID_NMSOCK(ievent->sock));
REQUIRE(ievent->sock->tid == isc_tid());
REQUIRE(VALID_NMSOCK(ievent->sock->parent)); REQUIRE(VALID_NMSOCK(ievent->sock->parent));
sock = ievent->sock; sock = ievent->sock;
@@ -340,7 +342,6 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
mgr = sock->worker->netmgr; mgr = sock->worker->netmgr;
REQUIRE(sock->type == isc_nm_udpsocket); REQUIRE(sock->type == isc_nm_udpsocket);
REQUIRE(sock->parent != NULL);
REQUIRE(sock->tid == isc_tid()); REQUIRE(sock->tid == isc_tid());
(void)isc__nm_socket_min_mtu(sock->fd, sa_family); (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); isc__nm_incstats(sock, STATID_BINDFAIL);
goto done; goto done;
} }
} else { } else if (sock->tid == 0) {
LOCK(&sock->parent->lock); /* This thread is first, bind the socket */
if (sock->parent->fd == -1) { r = isc__nm_udp_freebind(&sock->uv_handle.udp,
/* This thread is first, bind the socket */ &sock->parent->iface.type.sa,
r = isc__nm_udp_freebind(&sock->uv_handle.udp, uv_bind_flags);
&sock->parent->iface.type.sa, if (r < 0) {
uv_bind_flags); isc__nm_incstats(sock, STATID_BINDFAIL);
if (r < 0) { goto done;
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;
} 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->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;
} }
isc__nm_set_network_buffers(mgr, &sock->uv_handle.handle); isc__nm_set_network_buffers(mgr, &sock->uv_handle.handle);
@@ -417,16 +410,13 @@ done:
result = isc_uverr2result(r); result = isc_uverr2result(r);
atomic_fetch_add(&sock->parent->rchildren, 1); atomic_fetch_add(&sock->parent->rchildren, 1);
LOCK(&sock->parent->lock); sock->result = result;
if (sock->parent->result == ISC_R_UNSET) {
sock->parent->result = result;
} else {
REQUIRE(sock->parent->result == result);
}
UNLOCK(&sock->parent->lock);
REQUIRE(!worker->loop->paused); REQUIRE(!worker->loop->paused);
isc_barrier_wait(&sock->parent->listen_barrier);
if (sock->tid != 0) {
isc_barrier_wait(&sock->parent->listen_barrier);
}
} }
static void static void