mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 15:45:25 +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:
@@ -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;
|
||||||
|
@@ -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);
|
|
||||||
if (sock->parent->fd == -1) {
|
|
||||||
r = isc__nm_tcp_freebind(&sock->uv_handle.tcp,
|
r = isc__nm_tcp_freebind(&sock->uv_handle.tcp,
|
||||||
&sock->iface.type.sa, flags);
|
&sock->iface.type.sa, flags);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
isc__nm_incstats(sock, STATID_BINDFAIL);
|
isc__nm_incstats(sock, STATID_BINDFAIL);
|
||||||
UNLOCK(&sock->parent->lock);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
sock->parent->uv_handle.tcp.flags =
|
sock->parent->uv_handle.tcp.flags = sock->uv_handle.tcp.flags;
|
||||||
sock->uv_handle.tcp.flags;
|
|
||||||
sock->parent->fd = sock->fd;
|
|
||||||
} else {
|
} else {
|
||||||
/* The socket is already bound, just copy the flags */
|
/* The socket is already bound, just copy the flags */
|
||||||
sock->uv_handle.tcp.flags =
|
sock->uv_handle.tcp.flags = sock->parent->uv_handle.tcp.flags;
|
||||||
sock->parent->uv_handle.tcp.flags;
|
|
||||||
}
|
|
||||||
UNLOCK(&sock->parent->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc__nm_set_network_buffers(sock->worker->netmgr,
|
isc__nm_set_network_buffers(sock->worker->netmgr,
|
||||||
@@ -546,17 +539,14 @@ 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);
|
||||||
|
|
||||||
|
if (sock->tid != 0) {
|
||||||
isc_barrier_wait(&sock->parent->listen_barrier);
|
isc_barrier_wait(&sock->parent->listen_barrier);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tcp_connection_cb(uv_stream_t *server, int status) {
|
tcp_connection_cb(uv_stream_t *server, int status) {
|
||||||
|
@@ -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);
|
|
||||||
if (sock->parent->fd == -1) {
|
|
||||||
/* This thread is first, bind the socket */
|
/* This thread is first, bind the socket */
|
||||||
r = isc__nm_udp_freebind(&sock->uv_handle.udp,
|
r = isc__nm_udp_freebind(&sock->uv_handle.udp,
|
||||||
&sock->parent->iface.type.sa,
|
&sock->parent->iface.type.sa,
|
||||||
uv_bind_flags);
|
uv_bind_flags);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
isc__nm_incstats(sock, STATID_BINDFAIL);
|
isc__nm_incstats(sock, STATID_BINDFAIL);
|
||||||
UNLOCK(&sock->parent->lock);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
sock->parent->uv_handle.udp.flags =
|
sock->parent->uv_handle.udp.flags = sock->uv_handle.udp.flags;
|
||||||
sock->uv_handle.udp.flags;
|
|
||||||
sock->parent->fd = sock->fd;
|
|
||||||
} else {
|
} else {
|
||||||
/* The socket is already bound, just copy the flags */
|
/* The socket is already bound, just copy the flags */
|
||||||
sock->uv_handle.udp.flags =
|
sock->uv_handle.udp.flags = sock->parent->uv_handle.udp.flags;
|
||||||
sock->parent->uv_handle.udp.flags;
|
|
||||||
}
|
|
||||||
UNLOCK(&sock->parent->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc__nm_set_network_buffers(mgr, &sock->uv_handle.handle);
|
isc__nm_set_network_buffers(mgr, &sock->uv_handle.handle);
|
||||||
@@ -417,17 +410,14 @@ 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);
|
||||||
|
|
||||||
|
if (sock->tid != 0) {
|
||||||
isc_barrier_wait(&sock->parent->listen_barrier);
|
isc_barrier_wait(&sock->parent->listen_barrier);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stop_udp_child(isc_nmsocket_t *sock, uint32_t tid) {
|
stop_udp_child(isc_nmsocket_t *sock, uint32_t tid) {
|
||||||
|
Reference in New Issue
Block a user