diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h --- a/sys/sys/sockbuf.h +++ b/sys/sys/sockbuf.h @@ -79,9 +79,8 @@ * Locking key to struct sockbuf: * (a) locked by SOCKBUF_LOCK(). */ -struct sockbuf { - struct mtx sb_mtx; /* sockbuf lock */ - struct sx sb_sx; /* prevent I/O interlacing */ +struct sockbuf { + struct mtx *sb_mtx; /* sockbuf lock */ struct selinfo *sb_sel; /* process selecting read/write */ short sb_state; /* (a) socket state on sockbuf */ #define sb_startzero sb_flags @@ -122,7 +121,7 @@ * Per-socket buffer mutex used to protect most fields in the socket * buffer. */ -#define SOCKBUF_MTX(_sb) (&(_sb)->sb_mtx) +#define SOCKBUF_MTX(_sb) ((_sb)->sb_mtx) #define SOCKBUF_LOCK_INIT(_sb, _name) \ mtx_init(SOCKBUF_MTX(_sb), _name, NULL, MTX_DEF) #define SOCKBUF_LOCK_DESTROY(_sb) mtx_destroy(SOCKBUF_MTX(_sb)) diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -121,6 +121,17 @@ int so_ts_clock; /* type of the clock used for timestamps */ uint32_t so_max_pacing_rate; /* (f) TX rate limit in bytes/s */ + + /* + * Mutexes to prevent interleaving of socket I/O. These have to be + * outside of the socket buffers in order to interlock with listen(2). + */ + struct sx so_snd_sx __aligned(CACHE_LINE_SIZE); + struct mtx so_snd_mtx; + + struct sx so_rcv_sx __aligned(CACHE_LINE_SIZE); + struct mtx so_rcv_mtx; + union { /* Regular (data flow) socket. */ struct { @@ -256,13 +267,13 @@ #define SBL_VALID (SBL_WAIT | SBL_NOINTR) #define SOCK_IO_SEND_LOCK(so, flags) \ - soiolock((so), &(so)->so_snd.sb_sx, (flags)) + soiolock((so), &(so)->so_snd_sx, (flags)) #define SOCK_IO_SEND_UNLOCK(so) \ - soiounlock(&(so)->so_snd.sb_sx) + soiounlock(&(so)->so_snd_sx) #define SOCK_IO_RECV_LOCK(so, flags) \ - soiolock((so), &(so)->so_rcv.sb_sx, (flags)) + soiolock((so), &(so)->so_rcv_sx, (flags)) #define SOCK_IO_RECV_UNLOCK(so) \ - soiounlock(&(so)->so_rcv.sb_sx) + soiounlock(&(so)->so_rcv_sx) /* * Do we need to notify the other side when I/O is possible?