Use of so_state: File/Function Use Locks Held Comment ------------- --- ---------- ------- sys_socket.c:soo_ioctl() FIONBIO, so_state |= SS_NBIO - Problem - SOCK_LOCK(so)? sys_socket.c:soo_ioctl() FIONBIO, so_state &= ~SS_NBIO - Problem - SOCK_LOCK(so)? sys_socket.c:soo_ioctl() FIOASYNC, so_state |= SS_ASYNC - Problem - SOCK_LOCK(so)? sys_socket.c:soo_ioctl() FIOASYNC, so_state &= ~SS_ASYNC - Problem - SOCK_LOCK(so)? sys_socket.c:soo_ioctl() SIOCATMARK, (so_state & SS_RCVATMARK) != 0 - sys_socket.c:soo_stat() (so->so_state & SS_CANTRCVMORE) == 0 - Unlocked read -- OK sys_socket.c:soo_stat() (so->so_state & SS_CANTSNDMORE) == 0 - Unlocked read -- OK uipc_socket.c:socreate() so_state |= SS_NOFDREF SOCK_LOCK(so) uipc_socket.c:solisten() so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING) - Probably needs atomic T&S uipc_socket.c:sofree() (so->so_state & SS_NOFDREF) == 0 SOCK_LOCK(so) uipc_socket.c:sofree() (so->so_state & SS_INCOMP) SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:sofree() (so->so_state & SS_COMP) SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:sofree() so->so_state &= ~SS_INCOMP SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:soclose() so->so_state &= ~SS_COMP - Should be SOCKBUF_LOCK(&so->so_rcv)? uipc_socket.c:soclose() so->so_state & SS_ISCONNECTED SOCK_LOCK(so) uipc_socket.c:soclose() (so->so_state & SS_ISDISCONNECTING) == 0 SOCK_LOCK(so) uipc_socket.c:soclose() (so->so_state & SS_ISDISCONNECTING) SOCK_LOCK(so) uipc_socket.c:soclose() (so->so_state & SS_NBIO) SOCK_LOCK(so) uipc_socket.c:soclose() (so->so_state & SS_ISCONNECTED) SOCK_LOCK(so) uipc_socket.c:soclose() (so->so_state & SS_NOFDREF) SOCK_LOCK(so) uipc_socket.c:soclose() so->so_state |= SS_NOFDREF SOCK_LOCK(so) uipc_socket.c:soaccept() (so->so_state & SS_NOFDREF) == 0 - Should be SOCK_LOCK(so)? uipc_socket.c:soaccept() so->so_state &= ~SS_NOFDREF - Should be SOCK_LOCK(so)? uipc_socket.c:soconnect() (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) - uipc_socket.c:sodisconnect() (so->so_state & SS_ISCONNECTED) == 0 - uipc_socket.c:sodisconnect() (so->so_state & SS_ISDISCONNECTING) - uipc_socket.c:sosend() (so->so_state & SS_CANTSENDMORE) SOCKBUF_LOCK(&so->so_snd) uipc_socket.c:sosend() (so->so_state & SS_ISCONNECTED) == 0 SOCKBUF_LOCK(&so->so_snd) uipc_socket.c:sosend() (so->so_state & SS_ISCONFIRMING) == 0 SOCKBUF_LOCK(&so->so_snd) uipc_socket.c:sosend() (so->so_state & SS_NBIO) SOCKBUF_LOCK(&so->so_snd) uipc_socket.c:soreceive() (so->so_state & SS_ISCONFIRMING) - uipc_socket.c:soreceive() (so->so_state & SS_CANTRCVMORE) SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:soreceive() ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:soreceive() (so->so_state & SS_NBIO) SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:soreceive() so->so_state &= ~SS_RCVATMARK SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:soreceive() so->so_state |= SS_RCVATMARK SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:soreceive() (so->so_state & SS_CANTRCVMORE) SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:soreceive() (so->so_state & SS_CANTRCVMORE) SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:sopoll() sowriteable(so) - uipc_socket.c:sopoll() soreadable(so) - uipc_socket.c:sopoll() (so->so_state & SS_RCVATMARK) - uipc_socket.c:filt_soread() (so->so_state & SS_CANTRCVMORE) SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:sopoll() (so->so_state & SS_RCVATMARK) - uipc_socket.c:filt_soread() (so->so_state & SS_CANTRCVMORE) SOCKBUF_LOCK(&so->so_rcv) uipc_socket.c:filt_sowrite() (so->so_state & SS_CANTSENDMORE) SOCKBUF_LOCK(&so->so_snd) uipc_socket.c:filt_sowrite() (so->so_state & SS_ISCONNECTED) == 0 SOCKBUF_LOCK(&so->so_snd) uipc_socket2.c:soisconnecting() so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING) SOCK_LOCK(so) uipc_socket2.c:soisconnecting() so->so_state |= SS_ISCONNECTING SOCK_LOCK(so) uipc_socket2.c:soisconnected() so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING) SOCK_LOCK(so) uipc_socket2.c:soisconnected() so->so_state |= SS_ISCONNECTED SOCK_LOCK(so) uipc_socket2.c:soisconnected() (so->so_state & SS_INCOMP) SOCK_LOCK(so) Maybe SOCKBUF_LOCK(&so->so_rcv)? uipc_socket2.c:soisconnected() so->so_state &= ~SS_INCOMP SOCK_LOCK(so) maybe Should be always or so_rcv? uipc_socket2.c:soisconnected() so->so_state |= SS_COMP SOCK_LOCK(so) maybe Should be always or so_rcv? uipc_socket2.c:soisdisconnecting() so->so_state &= ~SS_ISCONNECTING SOCK_LOCK(so) uipc_socket2.c:soisdisconnecting() so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE) SOCK_LOCK(so) Perhaps sockbuf locks also? uipc_socket2.c:soisdisconnected() so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING) SOCK_LOCK(so) uipc_socket2.c:soisdisconnected() so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED) SOCK_LOCK(so) Perhaps sockbuf locks also? uipc_socket2.c:sonewconn() so->so_state = head->so_state | SS_NOFDREF - so is new - OK uipc_socket2.c:sonewconn() so->so_state |= SS_COMP - so is new - OK uipc_socket2.c:sonewconn() so->so_state |= SS_INCOMP - so is new - OK uipc_socket2.c:sonewconn() so->so_state |= connstatus // connstatus might be SS_ISCONNECTED - so is new -- but reachable? uipc_socket2.c:socantsendmore() so->so_state |= SS_CANTSENDMORE - Should be SOCKBUF_LOCK(&so->so_snd)? uipc_socket2.c:socandsendmore_locked() so->so_state |= SS_CANDSENDMORE SOCKBUF_LOCK(&so->so_snd) uipc_socket2.c:socantrcvmore() so->so_state |= SS_CANTRCVMORE - Should be SOCKBUF_LOCK(&so->so_rcv)? uipc_socket2.c:socantrcvmore_locked() so->so_state |= SS_CANTRCVMORE SOCKBUF_LOCK(&so->so_rcv) uipc_socket2.c:sowakeup_locked() (so->so_state & SS_ASYNC) SOCKBUF_LOCK(sb) uipc_socket2.c:sowakeup() (so->so_state & SS_ASYNC) - uipc_socket2.c:sotoxssocket() xso->so_state = so->so_state - uipc_syscalls.c:accept1() (head->so_state & SS_CANTRCVMORE) SOCK_LOCK(head) uipc_syscalls.c:accept1() (head->so_state & SS_NBIO) SOCK_LOCK(head) uipc_syscalls.c:accept1() so->so_state &= ~SS_COMP - Should be so_rcv? uipc_syscalls.c:kern_connect() (so->so_state & SS_ISCONNECTING) - uipc_syscalls.c:kern_connect() (so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING) - uipc_syscalls.c:kern_connect() (so->so_state & SS_ISCONNECTING) SOCK_LOCK(so) uipc_syscalls.c:kern_connect() so->so_state &= ~SS_ISCONNECTING - uipc_syscalls.c:getpeername1() (so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0 - uipc_syscalls.c:do_sendfile() (so->so_state & SS_ISCONNECTED) == 0 - uipc_syscalls.c:do_sendfile() (so->so_state & SS_NBIO) SOCKBUF_LOCK(&so->so_snd) uipc_syscalls.c:do_sendfile() (so->so_state & SS_CANTSENDMORE) SOCKBUF_LOCK(&so->so_snd) uipc_syscalls.c:do_sendfile() (so->so_state & SS_CANTSENDMORE) SOCKBUF_LOCK(&so->so_snd) uipc_syscalls.c:do_sendfile() (so->so_state & SS_CANTSENDMORE) SOCKBUF_LOCK(&so->so_snd) uipc_syscalls.c:do_sendfile() (so->so_state & SS_CANTSENDMORE) SOCKBUF_LOCK(&so->so_snd) uipc_syscalls.c:do_sendfile() (so->so_state & SS_NBIO) SOCKBUF_LOCK(&so->so_snd) uipc_usrreq.c:uipc_send() (so->so_state & SS_ISCONNECTED) == 0 SOCKBUF_LOCK(&so->so_snd) uipc_usrreq.c:uipc_send() (so->so_state & SS_CANTSENDMORE) SOCKBUF_LOCK(&so->so_snd) uipc_usrreq.c:unp_disconnect() unp->unp_socket->so_state &= ~SS_ISCONNECTED UNP_LOCK(unp) fifo_vnops.c:fifo_open() rso->so_state |= SS_CANTRCVMORE - fifo_vnops.c:fifo_open() fip->fi_writesock->so_state &= ~SS_CANTSENDMORE - Should be so_rcv? fifo_vnops.c:fifo_open() fip->fi_readsock->so_state &= ~SS_CANTRCVMORE - Should be so_snd? fifo_vnops.c:fifo_read() rso->so_state |= SS_NBIO - Should be SOCK_LOCK(so)? fifo_vnops.c:fifo_read() rso->so_state &= ~SS_NBIO - Should be SOCK_LOCK(so)? fifo_vnops.c:fifo_write() wso->so_state |= SS_NBIO - Should be SOCK_LOCK(so)? fifo_vnops.c:fifo_write() wso->so_state &= ~SS_NBIO - Should be SOCK_LOCK(so)? fifo_vnops.c:filt_fiforead() (so->so_state & SS_CANTRCVMORE) SOCKBUF_LOCK(&so->so_rcv) fifo_vnops.c:filt_fifowrite() (so->so_state & SS_CANTSENDMORE) SOCKBUF_LOCK(&so->so_snd) accf_http.c:sohashttpget() (so->so_state & SS_CANTRCVMORE) == 0 - accf_http.c:soparsehttpvers() (so->so_state & SS_CANTRCVMORE) != 0 - accf_http.c:soishttpconnected() (so->so_state & SS_CANTRCVMORE) != 0 - in_pcb.c:in_pcbdisconnect() (inp->inp_socket->so_state & SS_NOFDREF) INP_LOCK(inp) ip_divert.c:div_attach() so->so_state |= SS_ISCONNECTED - Should be SOCK_LOCK(so)? ip_divert.c:div_disconnect() (so->so_state & SS_ISCONNECTED) == 0 - raw_ip.c:rip_abort() (so->so_state & SS_NOFDREF) INP_LOCK(inp); ripcbinfo raw_ip.c:rip_disconnect() (so->so_state & SS_ISCONNECTED) == 0 - raw_ip.c:rip_send() (so->so_state & SS_ISCONNECTED) ripcbinfo tcp_input.c:359:tcp_reass() (so->so_state & SS_CANTRCVMORE) - tcp_input.c:1245:tcp_input() (so->so_state & SS_CANTRCVMORE) - (?) tcp_input.c:1706:tcp_input() (so->so_state & SS_NOFDREF) - (?) tcp_input.c:2143:tcp_input() (so->so_state & SS_CANTRCVMORE) - (?) tcp_input.c:2254:tcp_input() so->so_state |= SS_RCVATMARK - (?) so_rcv? tcp_input.c:2316:tcp_input() (so->so_state & SS_CANTRCVMORE) - (?) tcp_usrreq.c:tcp_usr_accept() (so->so_state & SS_ISDISCONNECTED) - tcp_usrreq.c:tcp6_usr_accept() (so->so_state & SS_ISDISCONNECTED) - tcp_usrreq.c:tcp_usr_rcvoob() (so->so_state & SS_RCVATMARK) == 0 INI_READ tcp_usrreq.c:tcp_attach() (so->so_state & SS_NOFDREF) - (new?) tcp_usrreq.c:tcp_attach() so->so_state &= ~SS_NOFDREF - (new?) tcp_usrreq.c:tcp_attach() so->so_state |= nofd // (so->so_state & SS_NOFREF) - (new?) udp_usrreq.c:udp_disconnect() so->so_state &= ~SS_ISCONNECTED - smb_trantcp.c:nb_connect_in() (so->so_state & SS_ISCONNECTING) - smb_trantcp.c:nb_connect_in() (so->so_state & SS_ISCONNECTING) - smb_trantcp.c:nb_connect_in() so->so_state &= ~SS_ISCONNECTING - smb_trantcp.c:nbssn_recv() (so->so_state & (SS_ISDISCONNECTING | SS_ISDISCONNECTED | SS_CANTRCVMORE) - socketvar.h:soreadable() (so->so_state & SS_CANTRECVMORE) (various) socketvar.h:sowriteable() (so->so_state & SS_ISCONNECTED) (various) socketvar.h:sowriteable() (so->so_state & SS_CANTSENDMORE) (various) Thoughts: Break out so_state into so_state, so->so_rcv.sb_state, so->so_snd.sb_state, lock with socket lock and socket buffer locks respectively. Review tests to make sure test-and-set consumers result in atomicity. In particular, relating to connection state.