]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kpi_socket.c
xnu-3789.70.16.tar.gz
[apple/xnu.git] / bsd / kern / kpi_socket.c
index 2251c3f6db611a07551461a79aada2a5b152dcf5..2f1b1d96a8af12006babef4a89d17f69d654b35c 100644 (file)
@@ -39,6 +39,7 @@
 #include <sys/protosw.h>
 #include <sys/domain.h>
 #include <sys/mbuf.h>
+#include <sys/mcache.h>
 #include <sys/fcntl.h>
 #include <sys/filio.h>
 #include <sys/uio_internal.h>
@@ -73,6 +74,7 @@ sock_accept(socket_t sock, struct sockaddr *from, int fromlen, int flags,
                socket_unlock(sock, 1);
                return (ENOTSUP);
        }
+check_again:
        if (((flags & MSG_DONTWAIT) != 0 || (sock->so_state & SS_NBIO) != 0) &&
            sock->so_comp.tqh_first == NULL) {
                socket_unlock(sock, 1);
@@ -106,10 +108,19 @@ sock_accept(socket_t sock, struct sockaddr *from, int fromlen, int flags,
                return (error);
        }
 
+       so_acquire_accept_list(sock, NULL);
+       if (TAILQ_EMPTY(&sock->so_comp)) {
+               so_release_accept_list(sock);
+               goto check_again;
+       }
        new_so = TAILQ_FIRST(&sock->so_comp);
        TAILQ_REMOVE(&sock->so_comp, new_so, so_list);
+       new_so->so_state &= ~SS_COMP;
+       new_so->so_head = NULL;
        sock->so_qlen--;
 
+       so_release_accept_list(sock);
+
        /*
         * Pass the pre-accepted socket to any interested socket filter(s).
         * Upon failure, the socket would have been closed by the callee.
@@ -122,7 +133,7 @@ sock_accept(socket_t sock, struct sockaddr *from, int fromlen, int flags,
                 * again once we're done with the filter(s).
                 */
                socket_unlock(sock, 0);
-               if ((error = soacceptfilter(new_so)) != 0) {
+               if ((error = soacceptfilter(new_so, sock)) != 0) {
                        /* Drop reference on listening socket */
                        sodereference(sock);
                        return (error);
@@ -136,8 +147,6 @@ sock_accept(socket_t sock, struct sockaddr *from, int fromlen, int flags,
                socket_lock(new_so, 1);
        }
 
-       new_so->so_state &= ~SS_COMP;
-       new_so->so_head = NULL;
        (void) soacceptlock(new_so, &sa, 0);
 
        socket_unlock(sock, 1); /* release the head */
@@ -961,6 +970,7 @@ sock_release(socket_t sock)
                soclose_locked(sock);
        } else {
                /* remove extra reference holding the socket */
+               VERIFY(sock->so_usecount > 1);
                sock->so_usecount--;
        }
        socket_unlock(sock, 1);