diff options
Diffstat (limited to 'sys/kern/sys_socket.c')
-rw-r--r-- | sys/kern/sys_socket.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index a580b43..986edf7 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -131,21 +131,41 @@ soo_ioctl(fp, cmd, data, active_cred, td) switch (cmd) { case FIONBIO: + SOCK_LOCK(so); if (*(int *)data) so->so_state |= SS_NBIO; else so->so_state &= ~SS_NBIO; + SOCK_UNLOCK(so); return (0); case FIOASYNC: + /* + * XXXRW: This code separately acquires SOCK_LOCK(so) + * and SOCKBUF_LOCK(&so->so_rcv) even though they are + * the same mutex to avoid introducing the assumption + * that they are the same. + */ if (*(int *)data) { + SOCK_LOCK(so); so->so_state |= SS_ASYNC; + SOCK_UNLOCK(so); + SOCKBUF_LOCK(&so->so_rcv); so->so_rcv.sb_flags |= SB_ASYNC; + SOCKBUF_UNLOCK(&so->so_rcv); + SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags |= SB_ASYNC; + SOCKBUF_UNLOCK(&so->so_snd); } else { + SOCK_LOCK(so); so->so_state &= ~SS_ASYNC; + SOCK_UNLOCK(so); + SOCKBUF_LOCK(&so->so_rcv); so->so_rcv.sb_flags &= ~SB_ASYNC; + SOCKBUF_UNLOCK(&so->so_rcv); + SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags &= ~SB_ASYNC; + SOCKBUF_UNLOCK(&so->so_snd); } return (0); |