sock->fd = (uv_os_sock_t)-1;
isc__nmsocket_barrier_init(sock);
- atomic_init(&sock->rchildren, sock->nchildren);
sock->listening = true;
*sockp = sock;
REQUIRE(VALID_NMSOCK(sock));
sock->closed = true;
- atomic_store_release(&sock->active, false);
+ sock->active = false;
session = sock->h2.session;
if (session != NULL && session->sending == 0 && !session->reading) {
isc_nmsocket_h2_t *next = ISC_LIST_NEXT(h2data, link);
ISC_LIST_DEQUEUE(session->sstreams, h2data, link);
/* Cleanup socket in place */
- atomic_store_release(&h2data->psock->active, false);
+ h2data->psock->active = false;
h2data->psock->closed = true;
isc__nmsocket_detach(&h2data->psock);
/*% Unlocked, RO */
int magic;
uint32_t tid;
+ isc_refcount_t references;
isc_nmsocket_type type;
isc__networker_t *worker;
isc_nmsocket_t *parent;
/*% Listener socket this connection was accepted on */
isc_nmsocket_t *listener;
- /*% Self socket */
- isc_nmsocket_t *self;
/*% TLS stuff */
struct tlsstream {
/*% Peer address */
isc_sockaddr_t peer;
- /* Atomic */
- /*% Number of running (e.g. listening) child sockets */
- atomic_uint_fast32_t rchildren;
-
/*%
* Socket is active if it's listening, working, etc. If it's
* closing, then it doesn't make a sense, for example, to
* push handles or reqs for reuse.
- *
- * We might be accessing sock->parent->active from a different
- * thread, so .active has to be atomic.
*/
- atomic_bool active;
+ bool active;
bool destroying;
bool route_sock;
bool accepting;
bool reading;
bool timedout;
- isc_refcount_t references;
/*%
* Established an outgoing connection, as client not server.
isc_nm_accept_cb_t accept_cb;
void *accept_cbarg;
- atomic_int_fast32_t active_child_connections;
-
bool barriers_initialised;
bool manual_read_timer;
#if ISC_NETMGR_TRACE
* or, for child sockets, 'sock->parent->active'.
*/
-bool
-isc__nmsocket_deactivate(isc_nmsocket_t *sock);
-/*%<
- * @brief Deactivate active socket
- *
- * Atomically deactive the socket by setting @p sock->active or, for child
- * sockets, @p sock->parent->active to @c false
- *
- * @param[in] sock - valid nmsocket
- * @return @c false if the socket was already inactive, @c true otherwise
- */
-
void
isc__nmsocket_clearcb(isc_nmsocket_t *sock);
/*%<
bool
isc__nmsocket_active(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
- if (sock->parent != NULL) {
- return (atomic_load_acquire(&sock->parent->active));
- }
-
- return (atomic_load_acquire(&sock->active));
-}
-
-bool
-isc__nmsocket_deactivate(isc_nmsocket_t *sock) {
- REQUIRE(VALID_NMSOCK(sock));
-
- if (sock->parent != NULL) {
- return (atomic_compare_exchange_strong_acq_rel(
- &sock->parent->active, &(bool){ true }, false));
- }
- return (atomic_compare_exchange_strong_acq_rel(&sock->active,
- &(bool){ true }, false));
+ return (sock->active);
}
void
}
REQUIRE(!sock->destroying);
- REQUIRE(!atomic_load_acquire(&sock->active));
+ REQUIRE(!sock->active);
if (!sock->closed) {
return;
* destroying the socket, but we have to wait for all the inflight
* handles to finish first.
*/
- atomic_store_release(&sock->active, false);
+ sock->active = false;
/*
- * If the socket has children, they'll need to be marked inactive
- * so they can be cleaned up too.
+ * If the socket has children, they have been marked inactive by the
+ * shutdown uv_walk
*/
- if (sock->children != NULL) {
- for (size_t i = 0; i < sock->nchildren; i++) {
- atomic_store_relaxed(&sock->children[i].active, false);
- }
- }
/*
* If we're here then we already stopped listening; otherwise
.result = ISC_R_UNSET,
.active_handles = ISC_LIST_INITIALIZER,
.active_link = ISC_LINK_INITIALIZER,
+ .active = true,
};
if (iface != NULL) {
"\n",
sock, isc_refcount_current(&sock->references));
- atomic_init(&sock->active, true);
-
- atomic_init(&sock->active_child_connections, 0);
-
#if HAVE_LIBNGHTTP2
isc__nm_http_initsocket(sock);
#endif
#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__)
nmhandle_free(sock, handle);
#else
- if (atomic_load_acquire(&sock->active)) {
+ if (sock->active) {
ISC_LIST_APPEND(sock->inactive_handles, handle, inactive_link);
} else {
nmhandle_free(sock, handle);
nmsocket_stop_cb(void *arg) {
isc_nmsocket_t *listener = arg;
- (void)atomic_fetch_sub(&listener->rchildren, 1);
isc_barrier_wait(&listener->stop_barrier);
}
}
nmsocket_stop_cb(listener);
- INSIST(atomic_load(&listener->rchildren) == 0);
listener->listening = false;
}
isc_nmhandle_attach(handle, &sock->outerhandle);
- atomic_store_release(&sock->active, true);
+ sock->active = true;
handle->sock->streamdns.sock = sock;
NULL);
nsock->read_timeout = initial;
nsock->accepting = true;
- atomic_store_release(&nsock->active, true);
+ nsock->active = true;
isc__nmsocket_attach(listensock, &nsock->listener);
isc_nmhandle_attach(handle, &nsock->outerhandle);
}
listener->result = result;
- atomic_store_release(&listener->active, true);
+ listener->active = true;
listener->listening = true;
INSIST(listener->outer->streamdns.listener == NULL);
listener->nchildren = listener->outer->nchildren;
isc__nmsocket_barrier_init(listener);
- atomic_init(&listener->rchildren, listener->outer->nchildren);
isc__nmsocket_attach(listener, &listener->outer->streamdns.listener);
*sockp = listener;
/* Further cleanup performed in isc__nm_streamdns_cleanup_data() */
isc_dnsstream_assembler_clear(sock->streamdns.input);
sock->closed = true;
- atomic_store_release(&sock->active, false);
+ sock->active = false;
}
void
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
(void)isc__nm_socket_tcp_maxseg(sock->fd, NM_MAXSEG);
- atomic_store_release(&sock->active, true);
+ sock->active = true;
result = tcp_connect_direct(sock, req);
if (result != ISC_R_SUCCESS) {
- atomic_store_release(&sock->active, false);
+ sock->active = false;
isc__nm_tcp_close(sock);
isc__nm_connectcb(sock, req, result, true);
}
result = isc_uverr2result(r);
done_result:
- atomic_fetch_add(&sock->parent->rchildren, 1);
-
if (result != ISC_R_SUCCESS) {
sock->pquota = NULL;
}
sock = isc_mem_get(worker->mctx, sizeof(*sock));
isc__nmsocket_init(sock, worker, isc_nm_tcplistener, iface, NULL);
- atomic_init(&sock->rchildren, 0);
sock->nchildren = (workers == ISC_NM_LISTEN_ALL) ? (uint32_t)mgr->nloops
: workers;
children_size = sock->nchildren * sizeof(sock->children[0]);
}
if (result != ISC_R_SUCCESS) {
- atomic_store_release(&sock->active, false);
+ sock->active = false;
isc__nm_tcp_stoplistening(sock);
isc_nmsocket_close(&sock);
return (result);
}
- atomic_store_release(&sock->active, true);
- REQUIRE(atomic_load(&sock->rchildren) == sock->nchildren);
+ sock->active = true;
+
*sockp = sock;
return (ISC_R_SUCCESS);
}
REQUIRE(sock->type == isc_nm_tcpsocket);
REQUIRE(!sock->closing);
+ sock->active = false;
sock->closing = true;
/*
isc__nmsocket_timer_stop(sock);
uv_close(&sock->read_timer, NULL);
- (void)atomic_fetch_sub(&sock->parent->rchildren, 1);
-
REQUIRE(!sock->worker->loop->paused);
isc_barrier_wait(&sock->parent->stop_barrier);
}
stop_tcp_child(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
- atomic_store_release(&sock->active, false);
if (sock->tid == 0) {
stop_tcp_child_job(sock);
} else {
sock->closing = true;
/* Mark the parent socket inactive */
- atomic_store_release(&sock->active, false);
+ sock->active = false;
/* Stop all the other threads' children */
for (size_t i = 1; i < sock->nchildren; i++) {
return (ISC_R_SUCCESS);
failure:
- atomic_store_release(&csock->active, false);
+ csock->active = false;
failed_accept_cb(csock, result);
* If the socket is active, mark it inactive and
* continue. If it isn't active, stop now.
*/
- if (!isc__nmsocket_deactivate(sock)) {
+ if (!sock->active) {
return;
}
+ sock->active = false;
if (sock->accepting) {
return;
return;
}
- /*
- * Otherwise, we just send the socket to abyss...
- */
+ /* Destroy the non-listening socket */
if (sock->parent == NULL) {
isc__nmsocket_prep_destroy(sock);
+ return;
+ }
+
+ /* Destroy the listening socket if on the same loop */
+ if (sock->tid == sock->parent->tid) {
+ isc__nmsocket_prep_destroy(sock->parent);
}
}
/* wait for listen result */
isc__nmsocket_attach(tlssock->outer, &tsock);
tlssock->result = result;
- atomic_store_release(&tlssock->active, true);
+ tlssock->active = true;
INSIST(tlssock->outer->tlsstream.tlslistener == NULL);
isc__nmsocket_attach(tlssock, &tlssock->outer->tlsstream.tlslistener);
isc__nmsocket_detach(&tsock);
tlssock->nchildren = tlssock->outer->nchildren;
isc__nmsocket_barrier_init(tlssock);
- atomic_init(&tlssock->rchildren, tlssock->nchildren);
if (result == ISC_R_SUCCESS) {
tlssock->listening = true;
/* Further cleanup performed in isc__nm_tls_cleanup_data() */
sock->closed = true;
- atomic_store_release(&sock->active, false);
+ sock->active = false;
sock->tlsstream.state = TLS_CLOSED;
}
}
tlssock->peer = isc_nmhandle_peeraddr(handle);
isc_nmhandle_attach(handle, &tlssock->outerhandle);
- atomic_store_release(&tlssock->active, true);
+ tlssock->active = true;
if (tlssock->tlsstream.client_sess_cache != NULL) {
isc_tlsctx_client_session_cache_reuse_sockaddr(
done:
result = isc_uverr2result(r);
- atomic_fetch_add(&sock->parent->rchildren, 1);
sock->result = result;
sock = isc_mem_get(worker->mctx, sizeof(isc_nmsocket_t));
isc__nmsocket_init(sock, worker, isc_nm_udplistener, iface, NULL);
- atomic_init(&sock->rchildren, 0);
sock->nchildren = (workers == ISC_NM_LISTEN_ALL) ? (uint32_t)mgr->nloops
: workers;
children_size = sock->nchildren * sizeof(sock->children[0]);
}
if (result != ISC_R_SUCCESS) {
- atomic_store_release(&sock->active, false);
+ sock->active = false;
isc__nm_udp_stoplistening(sock);
isc_nmsocket_close(&sock);
return (result);
}
- atomic_store_release(&sock->active, true);
- INSIST(atomic_load(&sock->rchildren) == sock->nchildren);
+ sock->active = true;
+
*sockp = sock;
return (ISC_R_SUCCESS);
}
req->cbarg = cbarg;
req->handle = isc__nmhandle_get(sock, NULL, NULL);
- atomic_store_release(&sock->active, true);
+ sock->active = true;
result = route_connect_direct(sock);
if (result != ISC_R_SUCCESS) {
- atomic_store_release(&sock->active, false);
+ sock->active = false;
isc__nm_udp_close(sock);
}
REQUIRE(sock->tid == isc_tid());
REQUIRE(sock->parent != NULL);
- isc__nm_udp_close(sock);
+ sock->active = false;
- (void)atomic_fetch_sub(&sock->parent->rchildren, 1);
+ isc__nm_udp_close(sock);
REQUIRE(!sock->worker->loop->paused);
isc_barrier_wait(&sock->parent->stop_barrier);
stop_udp_child(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
- atomic_store_release(&sock->active, false);
if (sock->tid == 0) {
stop_udp_child_job(sock);
} else {
sock->closing = true;
/* Mark the parent socket inactive */
- atomic_store_release(&sock->active, false);
+ sock->active = false;
/* Stop all the other threads' children */
for (size_t i = 1; i < sock->nchildren; i++) {
req->local = *local;
req->handle = isc__nmhandle_get(sock, &req->peer, &sock->iface);
- atomic_store_release(&sock->active, true);
+ sock->active = true;
sock->connecting = true;
result = udp_connect_direct(sock, req);
if (result != ISC_R_SUCCESS) {
- atomic_store_release(&sock->active, false);
+ sock->active = false;
isc__nm_failed_connect_cb(sock, req, result, true);
isc__nmsocket_detach(&sock);
return;
* If the socket is active, mark it inactive and
* continue. If it isn't active, stop now.
*/
- if (!isc__nmsocket_deactivate(sock)) {
+ if (!sock->active) {
return;
}
+ sock->active = false;
/* uv_udp_connect is synchronous, we can't be in connected state */
REQUIRE(!sock->connecting);
return;
}
- /*
- * Ignore the listening sockets
- */
- if (sock->parent != NULL) {
+ /* Destroy the non-listening socket */
+ if (sock->parent == NULL) {
+ isc__nmsocket_prep_destroy(sock);
return;
}
- /*
- * Otherwise, we just send the socket to abyss...
- */
- isc__nmsocket_prep_destroy(sock);
+ /* Destroy the listening socket if on the same loop */
+ if (sock->tid == sock->parent->tid) {
+ isc__nmsocket_prep_destroy(sock->parent);
+ }
}
static void