diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -4273,10 +4273,16 @@ { struct socket *so = arg; - if (SOLISTENING(so)) - SOCK_LOCK(so); - else +retry: + if (SOLISTENING(so)) { + SOLISTEN_LOCK(so); + } else { SOCK_RECVBUF_LOCK(so); + if (__predict_false(SOLISTENING(so))) { + SOCK_RECVBUF_UNLOCK(so); + goto retry; + } + } } static void @@ -4285,7 +4291,7 @@ struct socket *so = arg; if (SOLISTENING(so)) - SOCK_UNLOCK(so); + SOLISTEN_UNLOCK(so); else SOCK_RECVBUF_UNLOCK(so); } @@ -4297,12 +4303,12 @@ if (what == LA_LOCKED) { if (SOLISTENING(so)) - SOCK_LOCK_ASSERT(so); + SOLISTEN_LOCK_ASSERT(so); else SOCK_RECVBUF_LOCK_ASSERT(so); } else { if (SOLISTENING(so)) - SOCK_UNLOCK_ASSERT(so); + SOLISTEN_UNLOCK_ASSERT(so); else SOCK_RECVBUF_UNLOCK_ASSERT(so); } @@ -4313,10 +4319,16 @@ { struct socket *so = arg; - if (SOLISTENING(so)) - SOCK_LOCK(so); - else +retry: + if (SOLISTENING(so)) { + SOLISTEN_LOCK(so); + } else { SOCK_SENDBUF_LOCK(so); + if (__predict_false(SOLISTENING(so))) { + SOCK_SENDBUF_UNLOCK(so); + goto retry; + } + } } static void @@ -4325,7 +4337,7 @@ struct socket *so = arg; if (SOLISTENING(so)) - SOCK_UNLOCK(so); + SOLISTEN_UNLOCK(so); else SOCK_SENDBUF_UNLOCK(so); } @@ -4337,12 +4349,12 @@ if (what == LA_LOCKED) { if (SOLISTENING(so)) - SOCK_LOCK_ASSERT(so); + SOLISTEN_LOCK_ASSERT(so); else SOCK_SENDBUF_LOCK_ASSERT(so); } else { if (SOLISTENING(so)) - SOCK_UNLOCK_ASSERT(so); + SOLISTEN_UNLOCK_ASSERT(so); else SOCK_SENDBUF_UNLOCK_ASSERT(so); } diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -254,6 +254,11 @@ KASSERT(SOLISTENING(sol), \ ("%s: %p not listening", __func__, (sol))); \ } while (0) +#define SOLISTEN_UNLOCK_ASSERT(sol) do { \ + mtx_assert(&(sol)->so_lock, MA_NOTOWNED); \ + KASSERT(SOLISTENING(sol), \ + ("%s: %p not listening", __func__, (sol))); \ +} while (0) /* * Socket buffer locks. These are strongly preferred over SOCKBUF_LOCK(sb)