]> 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 09818e3b0ec0c57badc311e661da5992b4159164..2f1b1d96a8af12006babef4a89d17f69d654b35c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -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 */
@@ -495,7 +504,7 @@ so_tc_from_dscp(u_int8_t dscp)
        else if (dscp >= 0x20 && dscp <= 0x2f)
                tc = SO_TC_VI;
        else if (dscp >= 0x08 && dscp <= 0x17)
-               tc = SO_TC_BK;
+               tc = SO_TC_BK_SYS;
        else
                tc = SO_TC_BE;
 
@@ -950,11 +959,18 @@ sock_release(socket_t sock)
                    __func__, sock->so_retaincnt, sock);
                /* NOTREACHED */
        }
-       if ((sock->so_retaincnt == 0) && (sock->so_usecount == 2)) {
+       /*
+        * Check SS_NOFDREF in case a close happened as sock_retain()
+        * was grabbing the lock
+        */
+       if ((sock->so_retaincnt == 0) && (sock->so_usecount == 2) &&
+           (!(sock->so_state & SS_NOFDREF) ||
+           (sock->so_flags & SOF_MP_SUBFLOW))) {
                /* close socket only if the FD is not holding it */
                soclose_locked(sock);
        } else {
                /* remove extra reference holding the socket */
+               VERIFY(sock->so_usecount > 1);
                sock->so_usecount--;
        }
        socket_unlock(sock, 1);
@@ -1040,7 +1056,15 @@ sock_set_tcp_stream_priority(socket_t sock)
 void
 socket_set_traffic_mgt_flags_locked(socket_t sock, u_int8_t flags)
 {
-       (void) OSBitOrAtomic8(flags, &sock->so_traffic_mgt_flags);
+       u_int32_t soflags1 = 0;
+       
+       if ((flags & TRAFFIC_MGT_SO_BACKGROUND))
+               soflags1 |= SOF1_TRAFFIC_MGT_SO_BACKGROUND;
+       if ((flags & TRAFFIC_MGT_TCP_RECVBG))
+               soflags1 |= SOF1_TRAFFIC_MGT_TCP_RECVBG;
+       
+       (void) OSBitOrAtomic(soflags1, &sock->so_flags1);
+
        sock_set_tcp_stream_priority(sock);
 }
 
@@ -1058,7 +1082,15 @@ socket_set_traffic_mgt_flags(socket_t sock, u_int8_t flags)
 void
 socket_clear_traffic_mgt_flags_locked(socket_t sock, u_int8_t flags)
 {
-       (void) OSBitAndAtomic8(~flags, &sock->so_traffic_mgt_flags);
+       u_int32_t soflags1 = 0;
+
+       if ((flags & TRAFFIC_MGT_SO_BACKGROUND))
+               soflags1 |= SOF1_TRAFFIC_MGT_SO_BACKGROUND;
+       if ((flags & TRAFFIC_MGT_TCP_RECVBG))
+               soflags1 |= SOF1_TRAFFIC_MGT_TCP_RECVBG;
+       
+       (void) OSBitAndAtomic(~soflags1, &sock->so_flags1);
+
        sock_set_tcp_stream_priority(sock);
 }