mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-13 10:02:38 +00:00
Don't require the socket lock for sorele().
Previously, sorele() always required the socket lock and dropped the lock if the released reference was not the last reference. Many callers locked the socket lock just before calling sorele() resulting in a wasted lock/unlock when not dropping the last reference. Move the previous implementation of sorele() into a new sorele_locked() function and use it instead of sorele() for various places in uipc_socket.c that called sorele() while already holding the socket lock. The sorele() macro now uses refcount_release_if_not_last() try to drop the socket reference without locking the socket. If that shortcut fails, it locks the socket and calls sorele_locked(). Reviewed by: kib, markj Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D32741
This commit is contained in:
parent
e818178e3a
commit
e3ba94d4f3
@ -2372,7 +2372,6 @@ t4_aiotx_task(void *context, int pending)
|
||||
NET_EPOCH_EXIT(et);
|
||||
|
||||
free_toepcb(toep);
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
@ -399,7 +399,6 @@ sendfile_iodone(void *arg, vm_page_t *pa, int count, int error)
|
||||
(void)(so->so_proto->pr_usrreqs->pru_ready)(so, sfio->m,
|
||||
sfio->npages);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
#ifdef KERN_TLS
|
||||
out_with_ref:
|
||||
|
@ -727,7 +727,6 @@ soaio_process_sb(struct socket *so, struct sockbuf *sb)
|
||||
sb->sb_flags &= ~SB_AIO_RUNNING;
|
||||
SOCKBUF_UNLOCK(sb);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
@ -2077,7 +2077,6 @@ ktls_decrypt(struct socket *so)
|
||||
SOCKBUF_UNLOCK_ASSERT(sb);
|
||||
|
||||
CURVNET_SET(so->so_vnet);
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
@ -2427,7 +2426,6 @@ ktls_encrypt(struct ktls_wq *wq, struct mbuf *top)
|
||||
mb_free_notready(top, total_pages);
|
||||
}
|
||||
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
@ -2472,7 +2470,6 @@ ktls_encrypt_cb(struct ktls_ocf_encrypt_state *state, int error)
|
||||
mb_free_notready(m, npages);
|
||||
}
|
||||
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
@ -2523,7 +2520,6 @@ ktls_encrypt_async(struct ktls_wq *wq, struct mbuf *top)
|
||||
counter_u64_add(ktls_offload_failed_crypto, 1);
|
||||
free(state, M_KTLS);
|
||||
CURVNET_SET(so->so_vnet);
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
CURVNET_RESTORE();
|
||||
break;
|
||||
@ -2539,7 +2535,6 @@ ktls_encrypt_async(struct ktls_wq *wq, struct mbuf *top)
|
||||
mb_free_notready(m, total_pages - npages);
|
||||
}
|
||||
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
@ -2732,7 +2727,6 @@ ktls_disable_ifnet_help(void *context, int pending __unused)
|
||||
}
|
||||
|
||||
out:
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
if (!in_pcbrele_wlocked(inp))
|
||||
INP_WUNLOCK(inp);
|
||||
|
@ -785,7 +785,7 @@ sonewconn(struct socket *head, int connstatus)
|
||||
sp->so_qstate = SQ_NONE;
|
||||
sp->so_listen = NULL;
|
||||
SOCK_UNLOCK(sp);
|
||||
sorele(head); /* does SOLISTEN_UNLOCK, head stays */
|
||||
sorele_locked(head); /* does SOLISTEN_UNLOCK, head stays */
|
||||
soabort(sp);
|
||||
SOLISTEN_LOCK(head);
|
||||
}
|
||||
@ -1090,7 +1090,7 @@ solisten_dequeue(struct socket *head, struct socket **ret, int flags)
|
||||
else
|
||||
so->so_state |= (flags & SOCK_NONBLOCK) ? SS_NBIO : 0;
|
||||
SOCK_UNLOCK(so);
|
||||
sorele(head);
|
||||
sorele_locked(head);
|
||||
|
||||
*ret = so;
|
||||
return (0);
|
||||
@ -1170,7 +1170,7 @@ sofree(struct socket *so)
|
||||
KASSERT(so->so_listen == NULL,
|
||||
("%s: so %p not on (in)comp with so_listen",
|
||||
__func__, so));
|
||||
sorele(sol);
|
||||
sorele_locked(sol);
|
||||
KASSERT(refcount_load(&so->so_count) == 1,
|
||||
("%s: so %p count %u", __func__, so, so->so_count));
|
||||
so->so_count = 0;
|
||||
@ -1213,6 +1213,20 @@ sofree(struct socket *so)
|
||||
sodealloc(so);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release a reference on a socket while holding the socket lock.
|
||||
* Unlocks the socket lock before returning.
|
||||
*/
|
||||
void
|
||||
sorele_locked(struct socket *so)
|
||||
{
|
||||
SOCK_LOCK_ASSERT(so);
|
||||
if (refcount_release(&so->so_count))
|
||||
sofree(so);
|
||||
else
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a socket on last file table reference removal. Initiate disconnect
|
||||
* if connected. Free socket when disconnect complete.
|
||||
@ -1282,7 +1296,7 @@ soclose(struct socket *so)
|
||||
}
|
||||
KASSERT((so->so_state & SS_NOFDREF) == 0, ("soclose: NOFDREF"));
|
||||
so->so_state |= SS_NOFDREF;
|
||||
sorele(so);
|
||||
sorele_locked(so);
|
||||
if (listening) {
|
||||
struct socket *sp, *tsp;
|
||||
|
||||
@ -4060,7 +4074,7 @@ soisconnected(struct socket *so)
|
||||
* The socket is about to soabort().
|
||||
*/
|
||||
SOCK_UNLOCK(so);
|
||||
sorele(head);
|
||||
sorele_locked(head);
|
||||
return;
|
||||
}
|
||||
last = refcount_release(&head->so_count);
|
||||
|
@ -3911,7 +3911,6 @@ sysctl_switch_tls(SYSCTL_HANDLER_ARGS)
|
||||
error = ktls_set_tx_mode(so,
|
||||
arg2 == 0 ? TCP_TLS_MODE_SW : TCP_TLS_MODE_IFNET);
|
||||
INP_WUNLOCK(inp);
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
}
|
||||
} else
|
||||
|
@ -912,7 +912,6 @@ clnt_vc_destroy(CLIENT *cl)
|
||||
}
|
||||
/* Must sorele() to get rid of reference. */
|
||||
CURVNET_SET(so->so_vnet);
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
CURVNET_RESTORE();
|
||||
} else {
|
||||
|
@ -468,7 +468,6 @@ svc_vc_destroy_common(SVCXPRT *xprt)
|
||||
}
|
||||
/* Must sorele() to get rid of reference. */
|
||||
CURVNET_SET(xprt->xp_socket->so_vnet);
|
||||
SOCK_LOCK(xprt->xp_socket);
|
||||
sorele(xprt->xp_socket);
|
||||
CURVNET_RESTORE();
|
||||
} else
|
||||
|
@ -337,11 +337,11 @@ struct socket {
|
||||
*/
|
||||
#define soref(so) refcount_acquire(&(so)->so_count)
|
||||
#define sorele(so) do { \
|
||||
SOCK_LOCK_ASSERT(so); \
|
||||
if (refcount_release(&(so)->so_count)) \
|
||||
sofree(so); \
|
||||
else \
|
||||
SOCK_UNLOCK(so); \
|
||||
SOCK_UNLOCK_ASSERT(so); \
|
||||
if (!refcount_release_if_not_last(&(so)->so_count)) { \
|
||||
SOCK_LOCK(so); \
|
||||
sorele_locked(so); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
@ -503,6 +503,7 @@ int soreceive_dgram(struct socket *so, struct sockaddr **paddr,
|
||||
int soreceive_generic(struct socket *so, struct sockaddr **paddr,
|
||||
struct uio *uio, struct mbuf **mp0, struct mbuf **controlp,
|
||||
int *flagsp);
|
||||
void sorele_locked(struct socket *so);
|
||||
int soreserve(struct socket *so, u_long sndcc, u_long rcvcc);
|
||||
void sorflush(struct socket *so);
|
||||
int sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
|
||||
|
Loading…
Reference in New Issue
Block a user