]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/uipc_socket2.c
xnu-792.13.8.tar.gz
[apple/xnu.git] / bsd / kern / uipc_socket2.c
index 1d324fc8b55a86b19b2da1d42f4754b992c5649e..2a47db5d12a814953e305bf76ecd6db5d576efdd 100644 (file)
@@ -1,23 +1,31 @@
 /*
  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
  *
 /*
  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
  * 
  * 
- * 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.
- * 
- * 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 OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
+ * 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.  The rights granted to you under the 
+ * License may not be used to create, or enable the creation or 
+ * redistribution of, unlawful or unlicensed copies of an Apple operating 
+ * system, or to circumvent, violate, or enable the circumvention or 
+ * violation of, any terms of an Apple operating system software license 
+ * agreement.
+ *
+ * Please obtain a copy of the License at 
+ * http://www.opensource.apple.com/apsl/ 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 
+ * 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.
+ *
+ * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
  */
 /* Copyright (c) 1998, 1999 Apple Computer, Inc. All Rights Reserved */
 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
  */
 /* Copyright (c) 1998, 1999 Apple Computer, Inc. All Rights Reserved */
 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
@@ -81,6 +89,7 @@
 #define DBG_FNC_SBDROP NETDBG_CODE(DBG_NETSOCK, 4)
 #define DBG_FNC_SBAPPEND       NETDBG_CODE(DBG_NETSOCK, 5)
 
 #define DBG_FNC_SBDROP NETDBG_CODE(DBG_NETSOCK, 4)
 #define DBG_FNC_SBAPPEND       NETDBG_CODE(DBG_NETSOCK, 5)
 
+static int sbcompress(struct sockbuf *, struct mbuf *, struct mbuf *);
 
 /*
  * Primitive routines for operating on sockets and socket buffers
 
 /*
  * Primitive routines for operating on sockets and socket buffers
@@ -142,18 +151,22 @@ soisconnected(so)
        sflt_notify(so, sock_evt_connected, NULL);
        
        if (head && (so->so_state & SS_INCOMP)) {
        sflt_notify(so, sock_evt_connected, NULL);
        
        if (head && (so->so_state & SS_INCOMP)) {
-               if (head->so_proto->pr_getlock != NULL) 
+               so->so_state &= ~SS_INCOMP;
+               so->so_state |= SS_COMP;
+               if (head->so_proto->pr_getlock != NULL) {
+                       socket_unlock(so, 0);
                        socket_lock(head, 1);
                        socket_lock(head, 1);
+               }
                postevent(head, 0, EV_RCONN);
                TAILQ_REMOVE(&head->so_incomp, so, so_list);
                head->so_incqlen--;
                postevent(head, 0, EV_RCONN);
                TAILQ_REMOVE(&head->so_incomp, so, so_list);
                head->so_incqlen--;
-               so->so_state &= ~SS_INCOMP;
                TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
                TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
-               so->so_state |= SS_COMP;
                sorwakeup(head);
                wakeup_one((caddr_t)&head->so_timeo);
                sorwakeup(head);
                wakeup_one((caddr_t)&head->so_timeo);
-               if (head->so_proto->pr_getlock != NULL) 
+               if (head->so_proto->pr_getlock != NULL) {
                        socket_unlock(head, 1);
                        socket_unlock(head, 1);
+                       socket_lock(so, 0);
+               }
        } else {
                postevent(so, 0, EV_WCONN);
                wakeup((caddr_t)&so->so_timeo);
        } else {
                postevent(so, 0, EV_WCONN);
                wakeup((caddr_t)&so->so_timeo);
@@ -283,6 +296,14 @@ sonewconn_internal(head, connstatus)
        so->so_pgid  = head->so_pgid;
        so->so_uid = head->so_uid;
        so->so_usecount = 1;
        so->so_pgid  = head->so_pgid;
        so->so_uid = head->so_uid;
        so->so_usecount = 1;
+       so->next_lock_lr = 0;
+       so->next_unlock_lr = 0;
+
+#ifdef __APPLE__
+       so->so_rcv.sb_flags |= SB_RECV; /* XXX */
+       so->so_rcv.sb_so = so->so_snd.sb_so = so;
+       TAILQ_INIT(&so->so_evlist);
+#endif
 
        if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat)) {
                sflt_termsock(so);
 
        if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat)) {
                sflt_termsock(so);
@@ -291,16 +312,19 @@ sonewconn_internal(head, connstatus)
        }
 
        /*
        }
 
        /*
-        * Must be done with head unlocked to avoid deadlock with pcb list
+        * Must be done with head unlocked to avoid deadlock for protocol with per socket mutexes.
         */
         */
-       socket_unlock(head, 0);
+       if (head->so_proto->pr_unlock)
+               socket_unlock(head, 0);
        if (((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL) != 0) || error) {
                sflt_termsock(so);
                sodealloc(so);
        if (((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL) != 0) || error) {
                sflt_termsock(so);
                sodealloc(so);
-               socket_lock(head, 0);
+               if (head->so_proto->pr_unlock)
+                       socket_lock(head, 0);
                return ((struct socket *)0);
        }
                return ((struct socket *)0);
        }
-       socket_lock(head, 0);
+       if (head->so_proto->pr_unlock)
+               socket_lock(head, 0);
 #ifdef __APPLE__
        so->so_proto->pr_domain->dom_refs++;
 #endif
 #ifdef __APPLE__
        so->so_proto->pr_domain->dom_refs++;
 #endif
@@ -314,12 +338,10 @@ sonewconn_internal(head, connstatus)
                head->so_incqlen++;
        }
        head->so_qlen++;
                head->so_incqlen++;
        }
        head->so_qlen++;
-#ifdef __APPLE__
-       so->so_rcv.sb_so = so->so_snd.sb_so = so;
-       TAILQ_INIT(&so->so_evlist);
 
 
-        /* Attach socket filters for this protocol */
-        sflt_initsock(so);
+#ifdef __APPLE__
+       /* Attach socket filters for this protocol */
+       sflt_initsock(so);
 #endif
        if (connstatus) {
                so->so_state |= connstatus;
 #endif
        if (connstatus) {
                so->so_state |= connstatus;
@@ -400,17 +422,13 @@ int
 sbwait(sb)
        struct sockbuf *sb;
 {
 sbwait(sb)
        struct sockbuf *sb;
 {
-       int error = 0, lr, lr_saved;
+       int error = 0, lr_saved;
        struct socket *so = sb->sb_so;
        lck_mtx_t *mutex_held;
        struct timespec ts;
 
        struct socket *so = sb->sb_so;
        lck_mtx_t *mutex_held;
        struct timespec ts;
 
-#ifdef __ppc__
-       __asm__ volatile("mflr %0" : "=r" (lr));
-       lr_saved = lr;
-#endif
+       lr_saved = (unsigned int) __builtin_return_address(0);
        
        
-
        if (so->so_proto->pr_getlock != NULL) 
                mutex_held = (*so->so_proto->pr_getlock)(so, 0);
        else 
        if (so->so_proto->pr_getlock != NULL) 
                mutex_held = (*so->so_proto->pr_getlock)(so, 0);
        else 
@@ -448,12 +466,7 @@ sb_lock(sb)
 {
        struct socket *so = sb->sb_so;
        lck_mtx_t * mutex_held;
 {
        struct socket *so = sb->sb_so;
        lck_mtx_t * mutex_held;
-       int error = 0, lr, lr_saved;
-
-#ifdef __ppc__
-       __asm__ volatile("mflr %0" : "=r" (lr));
-       lr_saved = lr;
-#endif
+       int error = 0;
        
        if (so == NULL)
                panic("sb_lock: null so back pointer sb=%x\n", sb);
        
        if (so == NULL)
                panic("sb_lock: null so back pointer sb=%x\n", sb);
@@ -466,6 +479,7 @@ sb_lock(sb)
                        mutex_held = so->so_proto->pr_domain->dom_mtx;
                if (so->so_usecount < 1)
                        panic("sb_lock: so=%x refcount=%d\n", so, so->so_usecount);
                        mutex_held = so->so_proto->pr_domain->dom_mtx;
                if (so->so_usecount < 1)
                        panic("sb_lock: so=%x refcount=%d\n", so, so->so_usecount);
+
                error = msleep((caddr_t)&sb->sb_flags, mutex_held,
                        (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sblock", 0);
                if (so->so_usecount < 1)
                error = msleep((caddr_t)&sb->sb_flags, mutex_held,
                        (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sblock", 0);
                if (so->so_usecount < 1)
@@ -731,7 +745,7 @@ sbcheck(sb)
 int
 sbappendrecord(sb, m0)
        register struct sockbuf *sb;
 int
 sbappendrecord(sb, m0)
        register struct sockbuf *sb;
-       register struct mbuf *m0;
+       struct mbuf *m0;
 {
        register struct mbuf *m;
        int result = 0;
 {
        register struct mbuf *m;
        int result = 0;
@@ -1455,13 +1469,12 @@ void
 sbunlock(struct sockbuf *sb, int keeplocked)
 {
        struct socket *so = sb->sb_so;
 sbunlock(struct sockbuf *sb, int keeplocked)
 {
        struct socket *so = sb->sb_so;
-       int lr, lr_saved;
+       int lr_saved;
        lck_mtx_t *mutex_held;
 
        lck_mtx_t *mutex_held;
 
-#ifdef __ppc__
-       __asm__ volatile("mflr %0" : "=r" (lr));
-       lr_saved = lr;
-#endif
+
+       lr_saved = (unsigned int) __builtin_return_address(0);
+
        sb->sb_flags &= ~SB_LOCK; 
 
        if (so->so_proto->pr_getlock != NULL) 
        sb->sb_flags &= ~SB_LOCK; 
 
        if (so->so_proto->pr_getlock != NULL) 
@@ -1483,7 +1496,8 @@ sbunlock(struct sockbuf *sb, int keeplocked)
                so->so_usecount--;
                if (so->so_usecount < 0)
                        panic("sbunlock: unlock on exit so=%x lr=%x sb_flags=%x\n", so, so->so_usecount,lr_saved, sb->sb_flags);
                so->so_usecount--;
                if (so->so_usecount < 0)
                        panic("sbunlock: unlock on exit so=%x lr=%x sb_flags=%x\n", so, so->so_usecount,lr_saved, sb->sb_flags);
-               so->reserved4= lr_saved;
+               so->unlock_lr[so->next_unlock_lr] = (void *)lr_saved;
+               so->next_unlock_lr = (so->next_unlock_lr+1) % SO_LCKDBG_MAX;
                lck_mtx_unlock(mutex_held);
        }
 }
                lck_mtx_unlock(mutex_held);
        }
 }