]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/uipc_usrreq.c
xnu-792.6.61.tar.gz
[apple/xnu.git] / bsd / kern / uipc_usrreq.c
index 07f56acbdb6674202f316a170ef68b53bb50c79e..a9a2de3c00a05160526acb5aec66502ae7f0dd60 100644 (file)
@@ -3,20 +3,19 @@
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
  * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 struct zone *unp_zone;
 static unp_gen_t unp_gencnt;
 static u_int unp_count;
-static lck_mtx_t               *unp_mutex;
+
+static lck_attr_t              *unp_mtx_attr;
+static lck_grp_t               *unp_mtx_grp;
+static lck_grp_attr_t          *unp_mtx_grp_attr;
+static lck_rw_t                *unp_list_mtx;
 
 extern lck_mtx_t * uipc_lock;
 static struct unp_head unp_shead, unp_dhead;
@@ -560,7 +563,7 @@ unp_attach(struct socket *so)
        if (unp == NULL)
                return (ENOBUFS);
        bzero(unp, sizeof *unp);
-       lck_mtx_lock(unp_mutex);
+       lck_rw_lock_exclusive(unp_list_mtx);
        LIST_INIT(&unp->unp_refs);
        unp->unp_socket = so;
        unp->unp_gencnt = ++unp_gencnt;
@@ -568,16 +571,17 @@ unp_attach(struct socket *so)
        LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead
                         : &unp_shead, unp, unp_link);
        so->so_pcb = (caddr_t)unp;
-       lck_mtx_unlock(unp_mutex);
+       lck_rw_done(unp_list_mtx);
        return (0);
 }
 
 static void
 unp_detach(struct unpcb *unp)
 {
-       lck_mtx_assert(unp_mutex, LCK_MTX_ASSERT_OWNED);
+       lck_rw_lock_exclusive(unp_list_mtx);
        LIST_REMOVE(unp, unp_link);
        unp->unp_gencnt = ++unp_gencnt;
+       lck_rw_done(unp_list_mtx);
        --unp_count;
        if (unp->unp_vnode) {
                struct vnode *tvp = unp->unp_vnode;
@@ -723,7 +727,7 @@ unp_connect(
        if (error)
                goto bad;
        so2 = vp->v_socket;
-       if (so2 == 0) {
+       if (so2 == 0 || so2->so_pcb == NULL ) {
                error = ECONNREFUSED;
                goto bad;
        }
@@ -788,8 +792,10 @@ unp_connect(
        }
        error = unp_connect2(so, so2);
 bad:
-       if (so2 != NULL)
-               so2->so_usecount--; /* release count on socket */
+        
+       if (so2 != NULL) 
+                       so2->so_usecount--;     /* release count on socket */
+       
        vnode_put(vp);
        return (error);
 }
@@ -845,12 +851,13 @@ unp_disconnect(struct unpcb *unp)
 
        if (unp2 == 0)
                return;
-       lck_mtx_assert(unp_mutex, LCK_MTX_ASSERT_OWNED);
        unp->unp_conn = 0;
        switch (unp->unp_socket->so_type) {
 
        case SOCK_DGRAM:
+               lck_rw_lock_exclusive(unp_list_mtx);
                LIST_REMOVE(unp, unp_reflink);
+               lck_rw_done(unp_list_mtx);
                unp->unp_socket->so_state &= ~SS_ISCONNECTED;
                break;
 
@@ -880,7 +887,7 @@ unp_pcblist SYSCTL_HANDLER_ARGS
        struct xunpgen xug;
        struct unp_head *head;
 
-       lck_mtx_lock(unp_mutex);
+       lck_rw_lock_shared(unp_list_mtx);
        head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead);
 
        /*
@@ -891,12 +898,12 @@ unp_pcblist SYSCTL_HANDLER_ARGS
                n = unp_count;
                req->oldidx = 2 * (sizeof xug)
                        + (n + n/8) * sizeof(struct xunpcb);
-               lck_mtx_unlock(unp_mutex);
+               lck_rw_done(unp_list_mtx);
                return 0;
        }
 
        if (req->newptr != USER_ADDR_NULL) {
-               lck_mtx_unlock(unp_mutex);
+               lck_rw_done(unp_list_mtx);
                return EPERM;
        }
 
@@ -913,7 +920,7 @@ unp_pcblist SYSCTL_HANDLER_ARGS
        xug.xug_sogen = so_gencnt;
        error = SYSCTL_OUT(req, &xug, sizeof xug);
        if (error) {
-               lck_mtx_unlock(unp_mutex);
+               lck_rw_done(unp_list_mtx);
                return error;
        }
 
@@ -921,13 +928,13 @@ unp_pcblist SYSCTL_HANDLER_ARGS
         * We are done if there is no pcb
         */
        if (n == 0)  {
-           lck_mtx_unlock(unp_mutex);
+           lck_rw_done(unp_list_mtx);
            return 0;
        }
 
        MALLOC(unp_list, struct unpcb **, n * sizeof *unp_list, M_TEMP, M_WAITOK);
        if (unp_list == 0) {
-               lck_mtx_unlock(unp_mutex);
+               lck_rw_done(unp_list_mtx);
                return ENOMEM;
        }
        
@@ -979,7 +986,7 @@ unp_pcblist SYSCTL_HANDLER_ARGS
                error = SYSCTL_OUT(req, &xug, sizeof xug);
        }
        FREE(unp_list, M_TEMP);
-       lck_mtx_unlock(unp_mutex);
+       lck_rw_done(unp_list_mtx);
        return error;
 }
 
@@ -1082,7 +1089,18 @@ unp_init(void)
        LIST_INIT(&unp_dhead);
        LIST_INIT(&unp_shead);
        
-       unp_mutex = localdomain.dom_mtx;
+       /*
+        * allocate lock group attribute and group for udp pcb mutexes
+        */
+       unp_mtx_grp_attr = lck_grp_attr_alloc_init();
+
+       unp_mtx_grp = lck_grp_alloc_init("unp_list", unp_mtx_grp_attr);
+               
+       unp_mtx_attr = lck_attr_alloc_init();
+
+       if ((unp_list_mtx = lck_rw_alloc_init(unp_mtx_grp, unp_mtx_attr)) == NULL)
+               return; /* pretty much dead if this fails... */
+
 }
 
 #ifndef MIN