mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
Remove two simultaneous acquisitions of multiple unpcb locks from
uipc_send in cases where only a global read lock is held by breaking them out and avoiding the unpcb lock acquire in the common case. This avoids deadlocks which manifested with X11, and should also marginally further improve performance. Reported by: sepotvin, brooks
This commit is contained in:
parent
6fccc5ecd4
commit
ede6e136f8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=167133
@ -774,21 +774,18 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
|
||||
unp2 = unp->unp_conn;
|
||||
if (nam != NULL) {
|
||||
UNP_GLOBAL_WLOCK_ASSERT();
|
||||
if (unp2 != NULL) {
|
||||
error = EISCONN;
|
||||
UNP_PCB_LOCK(unp);
|
||||
break;
|
||||
}
|
||||
error = unp_connect(so, nam, td);
|
||||
UNP_PCB_LOCK(unp);
|
||||
if (error)
|
||||
break;
|
||||
unp2 = unp->unp_conn;
|
||||
} else {
|
||||
UNP_PCB_LOCK(unp);
|
||||
if (unp2 == NULL) {
|
||||
error = ENOTCONN;
|
||||
UNP_PCB_LOCK(unp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -799,19 +796,19 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
* return the slightly counter-intuitive but otherwise
|
||||
* correct error that the socket is not connected.
|
||||
*/
|
||||
UNP_PCB_LOCK_ASSERT(unp);
|
||||
if (unp2 == NULL) {
|
||||
error = ENOTCONN;
|
||||
break;
|
||||
}
|
||||
UNP_PCB_LOCK(unp2);
|
||||
so2 = unp2->unp_socket;
|
||||
/* Lockless read. */
|
||||
if (unp2->unp_flags & UNP_WANTCRED)
|
||||
control = unp_addsockcred(td, control);
|
||||
UNP_PCB_LOCK(unp);
|
||||
if (unp->unp_addr != NULL)
|
||||
from = (struct sockaddr *)unp->unp_addr;
|
||||
else
|
||||
from = &sun_noname;
|
||||
if (unp2->unp_flags & UNP_WANTCRED)
|
||||
control = unp_addsockcred(td, control);
|
||||
so2 = unp2->unp_socket;
|
||||
SOCKBUF_LOCK(&so2->so_rcv);
|
||||
if (sbappendaddr_locked(&so2->so_rcv, from, m, control)) {
|
||||
sorwakeup_locked(so2);
|
||||
@ -821,9 +818,13 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
SOCKBUF_UNLOCK(&so2->so_rcv);
|
||||
error = ENOBUFS;
|
||||
}
|
||||
if (nam != NULL)
|
||||
if (nam != NULL) {
|
||||
UNP_GLOBAL_WLOCK_ASSERT();
|
||||
UNP_PCB_LOCK(unp2);
|
||||
unp_disconnect(unp, unp2);
|
||||
UNP_PCB_UNLOCK(unp2);
|
||||
UNP_PCB_UNLOCK(unp2);
|
||||
}
|
||||
UNP_PCB_UNLOCK(unp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -836,18 +837,15 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
*/
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
if (nam != NULL) {
|
||||
UNP_GLOBAL_WLOCK_ASSERT();
|
||||
error = unp_connect(so, nam, td);
|
||||
UNP_PCB_LOCK(unp);
|
||||
if (error)
|
||||
break; /* XXX */
|
||||
} else {
|
||||
error = ENOTCONN;
|
||||
UNP_PCB_LOCK(unp);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
UNP_PCB_LOCK(unp);
|
||||
UNP_PCB_LOCK_ASSERT(unp);
|
||||
}
|
||||
|
||||
/* Lockless read. */
|
||||
if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
|
||||
@ -874,13 +872,12 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
error = ENOTCONN;
|
||||
break;
|
||||
}
|
||||
UNP_PCB_LOCK(unp2);
|
||||
so2 = unp2->unp_socket;
|
||||
UNP_PCB_LOCK(unp2);
|
||||
SOCKBUF_LOCK(&so2->so_rcv);
|
||||
if (unp2->unp_flags & UNP_WANTCRED) {
|
||||
/*
|
||||
* Credentials are passed only once on
|
||||
* SOCK_STREAM.
|
||||
* Credentials are passed only once on SOCK_STREAM.
|
||||
*/
|
||||
unp2->unp_flags &= ~UNP_WANTCRED;
|
||||
control = unp_addsockcred(td, control);
|
||||
@ -915,14 +912,14 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
}
|
||||
|
||||
/*
|
||||
* SEND_EOF is equivalent to a SEND followed by
|
||||
* a SHUTDOWN.
|
||||
* SEND_EOF is equivalent to a SEND followed by a SHUTDOWN.
|
||||
*/
|
||||
if (flags & PRUS_EOF) {
|
||||
UNP_PCB_LOCK(unp);
|
||||
socantsendmore(so);
|
||||
unp_shutdown(unp);
|
||||
UNP_PCB_UNLOCK(unp);
|
||||
}
|
||||
UNP_PCB_UNLOCK(unp);
|
||||
|
||||
if ((nam != NULL) || (flags & PRUS_EOF))
|
||||
UNP_GLOBAL_WUNLOCK();
|
||||
|
Loading…
Reference in New Issue
Block a user