uipc_socket.c (98499) | uipc_socket.c (98849) |
---|---|
1/* 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94 | 1/* 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94 |
34 * $FreeBSD: head/sys/kern/uipc_socket.c 98499 2002-06-20 18:52:54Z alfred $ | 34 * $FreeBSD: head/sys/kern/uipc_socket.c 98849 2002-06-26 03:37:47Z ken $ |
35 */ 36 37#include "opt_inet.h" | 35 */ 36 37#include "opt_inet.h" |
38#include "opt_zero.h" |
|
38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/fcntl.h> 42#include <sys/lock.h> 43#include <sys/malloc.h> 44#include <sys/mbuf.h> 45#include <sys/mutex.h> --- 43 unchanged lines hidden (view full) --- 89SYSCTL_DECL(_kern_ipc); 90 91static int somaxconn = SOMAXCONN; 92SYSCTL_INT(_kern_ipc, KIPC_SOMAXCONN, somaxconn, CTLFLAG_RW, 93 &somaxconn, 0, "Maximum pending socket connection queue size"); 94static int numopensockets; 95SYSCTL_INT(_kern_ipc, OID_AUTO, numopensockets, CTLFLAG_RD, 96 &numopensockets, 0, "Number of open sockets"); | 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/fcntl.h> 43#include <sys/lock.h> 44#include <sys/malloc.h> 45#include <sys/mbuf.h> 46#include <sys/mutex.h> --- 43 unchanged lines hidden (view full) --- 90SYSCTL_DECL(_kern_ipc); 91 92static int somaxconn = SOMAXCONN; 93SYSCTL_INT(_kern_ipc, KIPC_SOMAXCONN, somaxconn, CTLFLAG_RW, 94 &somaxconn, 0, "Maximum pending socket connection queue size"); 95static int numopensockets; 96SYSCTL_INT(_kern_ipc, OID_AUTO, numopensockets, CTLFLAG_RD, 97 &numopensockets, 0, "Number of open sockets"); |
98#ifdef ZERO_COPY_SOCKETS 99/* These aren't static because they're used in other files. */ 100int so_zero_copy_send = 1; 101int so_zero_copy_receive = 1; 102SYSCTL_NODE(_kern_ipc, OID_AUTO, zero_copy, CTLFLAG_RD, 0, 103 "Zero copy controls"); 104SYSCTL_INT(_kern_ipc_zero_copy, OID_AUTO, receive, CTLFLAG_RW, 105 &so_zero_copy_receive, 0, "Enable zero copy receive"); 106SYSCTL_INT(_kern_ipc_zero_copy, OID_AUTO, send, CTLFLAG_RW, 107 &so_zero_copy_send, 0, "Enable zero copy send"); 108#endif /* ZERO_COPY_SOCKETS */ |
|
97 98 99/* 100 * Socket operation routines. 101 * These routines are called by the routines in 102 * sys_socket.c or from a system process, and 103 * implement the semantics of socket operations by 104 * switching out to the protocol specific routines. --- 361 unchanged lines hidden (view full) --- 466 * otherwise by the mbuf chain "top" (which must be null 467 * if uio is not). Data provided in mbuf chain must be small 468 * enough to send all at once. 469 * 470 * Returns nonzero on error, timeout or signal; callers 471 * must check for short counts if EINTR/ERESTART are returned. 472 * Data and control buffers are freed on return. 473 */ | 109 110 111/* 112 * Socket operation routines. 113 * These routines are called by the routines in 114 * sys_socket.c or from a system process, and 115 * implement the semantics of socket operations by 116 * switching out to the protocol specific routines. --- 361 unchanged lines hidden (view full) --- 478 * otherwise by the mbuf chain "top" (which must be null 479 * if uio is not). Data provided in mbuf chain must be small 480 * enough to send all at once. 481 * 482 * Returns nonzero on error, timeout or signal; callers 483 * must check for short counts if EINTR/ERESTART are returned. 484 * Data and control buffers are freed on return. 485 */ |
486 487#ifdef ZERO_COPY_SOCKETS 488struct so_zerocopy_stats{ 489 int size_ok; 490 int align_ok; 491 int found_ifp; 492}; 493struct so_zerocopy_stats so_zerocp_stats = {0,0,0}; 494#include <netinet/in.h> 495#include <net/route.h> 496#include <netinet/in_pcb.h> 497#include <vm/vm.h> 498#include <vm/vm_page.h> 499#include <vm/vm_object.h> 500#endif /*ZERO_COPY_SOCKETS*/ 501 |
|
474int 475sosend(so, addr, uio, top, control, flags, td) 476 register struct socket *so; 477 struct sockaddr *addr; 478 struct uio *uio; 479 struct mbuf *top; 480 struct mbuf *control; 481 int flags; 482 struct thread *td; 483{ 484 struct mbuf **mp; 485 register struct mbuf *m; 486 register long space, len, resid; 487 int clen = 0, error, s, dontroute, mlen; 488 int atomic = sosendallatonce(so) || top; | 502int 503sosend(so, addr, uio, top, control, flags, td) 504 register struct socket *so; 505 struct sockaddr *addr; 506 struct uio *uio; 507 struct mbuf *top; 508 struct mbuf *control; 509 int flags; 510 struct thread *td; 511{ 512 struct mbuf **mp; 513 register struct mbuf *m; 514 register long space, len, resid; 515 int clen = 0, error, s, dontroute, mlen; 516 int atomic = sosendallatonce(so) || top; |
517#ifdef ZERO_COPY_SOCKETS 518 int cow_send; 519#endif /* ZERO_COPY_SOCKETS */ |
|
489 490 if (uio) 491 resid = uio->uio_resid; 492 else 493 resid = top->m_pkthdr.len; 494 /* 495 * In theory resid should be unsigned. 496 * However, space must be signed, as it might be less than 0 --- 72 unchanged lines hidden (view full) --- 569 if (uio == NULL) { 570 /* 571 * Data is prepackaged in "top". 572 */ 573 resid = 0; 574 if (flags & MSG_EOR) 575 top->m_flags |= M_EOR; 576 } else do { | 520 521 if (uio) 522 resid = uio->uio_resid; 523 else 524 resid = top->m_pkthdr.len; 525 /* 526 * In theory resid should be unsigned. 527 * However, space must be signed, as it might be less than 0 --- 72 unchanged lines hidden (view full) --- 600 if (uio == NULL) { 601 /* 602 * Data is prepackaged in "top". 603 */ 604 resid = 0; 605 if (flags & MSG_EOR) 606 top->m_flags |= M_EOR; 607 } else do { |
608#ifdef ZERO_COPY_SOCKETS 609 cow_send = 0; 610#endif /* ZERO_COPY_SOCKETS */ |
|
577 if (top == 0) { 578 MGETHDR(m, M_TRYWAIT, MT_DATA); 579 if (m == NULL) { 580 error = ENOBUFS; 581 goto release; 582 } 583 mlen = MHLEN; 584 m->m_pkthdr.len = 0; 585 m->m_pkthdr.rcvif = (struct ifnet *)0; 586 } else { 587 MGET(m, M_TRYWAIT, MT_DATA); 588 if (m == NULL) { 589 error = ENOBUFS; 590 goto release; 591 } 592 mlen = MLEN; 593 } 594 if (resid >= MINCLSIZE) { | 611 if (top == 0) { 612 MGETHDR(m, M_TRYWAIT, MT_DATA); 613 if (m == NULL) { 614 error = ENOBUFS; 615 goto release; 616 } 617 mlen = MHLEN; 618 m->m_pkthdr.len = 0; 619 m->m_pkthdr.rcvif = (struct ifnet *)0; 620 } else { 621 MGET(m, M_TRYWAIT, MT_DATA); 622 if (m == NULL) { 623 error = ENOBUFS; 624 goto release; 625 } 626 mlen = MLEN; 627 } 628 if (resid >= MINCLSIZE) { |
629#ifdef ZERO_COPY_SOCKETS 630 if (so_zero_copy_send && 631 resid>=PAGE_SIZE && 632 space>=PAGE_SIZE && 633 uio->uio_iov->iov_len>=PAGE_SIZE) { 634 so_zerocp_stats.size_ok++; 635 if (!((vm_offset_t) 636 uio->uio_iov->iov_base & PAGE_MASK)){ 637 so_zerocp_stats.align_ok++; 638 cow_send = socow_setup(m, uio); 639 } 640 } 641 if (!cow_send){ 642#endif /* ZERO_COPY_SOCKETS */ |
|
595 MCLGET(m, M_TRYWAIT); 596 if ((m->m_flags & M_EXT) == 0) 597 goto nopages; 598 mlen = MCLBYTES; 599 len = min(min(mlen, resid), space); 600 } else { | 643 MCLGET(m, M_TRYWAIT); 644 if ((m->m_flags & M_EXT) == 0) 645 goto nopages; 646 mlen = MCLBYTES; 647 len = min(min(mlen, resid), space); 648 } else { |
649#ifdef ZERO_COPY_SOCKETS 650 len = PAGE_SIZE; 651 } 652 653 } else { 654#endif /* ZERO_COPY_SOCKETS */ |
|
601nopages: 602 len = min(min(mlen, resid), space); 603 /* 604 * For datagram protocols, leave room 605 * for protocol headers in first mbuf. 606 */ 607 if (atomic && top == 0 && len < mlen) 608 MH_ALIGN(m, len); 609 } 610 space -= len; | 655nopages: 656 len = min(min(mlen, resid), space); 657 /* 658 * For datagram protocols, leave room 659 * for protocol headers in first mbuf. 660 */ 661 if (atomic && top == 0 && len < mlen) 662 MH_ALIGN(m, len); 663 } 664 space -= len; |
665#ifdef ZERO_COPY_SOCKETS 666 if (cow_send) 667 error = 0; 668 else 669#endif /* ZERO_COPY_SOCKETS */ |
|
611 error = uiomove(mtod(m, caddr_t), (int)len, uio); 612 resid = uio->uio_resid; 613 m->m_len = len; 614 *mp = m; 615 top->m_pkthdr.len += len; 616 if (error) 617 goto release; 618 mp = &m->m_next; --- 95 unchanged lines hidden (view full) --- 714 if (flags & MSG_OOB) { 715 m = m_get(M_TRYWAIT, MT_DATA); 716 if (m == NULL) 717 return (ENOBUFS); 718 error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK); 719 if (error) 720 goto bad; 721 do { | 670 error = uiomove(mtod(m, caddr_t), (int)len, uio); 671 resid = uio->uio_resid; 672 m->m_len = len; 673 *mp = m; 674 top->m_pkthdr.len += len; 675 if (error) 676 goto release; 677 mp = &m->m_next; --- 95 unchanged lines hidden (view full) --- 773 if (flags & MSG_OOB) { 774 m = m_get(M_TRYWAIT, MT_DATA); 775 if (m == NULL) 776 return (ENOBUFS); 777 error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK); 778 if (error) 779 goto bad; 780 do { |
781#ifdef ZERO_COPY_SOCKETS 782 if (so_zero_copy_receive) { 783 vm_page_t pg; 784 int disposable; 785 786 if ((m->m_flags & M_EXT) 787 && (m->m_ext.ext_type == EXT_DISPOSABLE)) 788 disposable = 1; 789 else 790 disposable = 0; 791 792 pg = PHYS_TO_VM_PAGE(vtophys(mtod(m, caddr_t))); 793 if (uio->uio_offset == -1) 794 uio->uio_offset =IDX_TO_OFF(pg->pindex); 795 796 error = uiomoveco(mtod(m, caddr_t), 797 min(uio->uio_resid, m->m_len), 798 uio, pg->object, 799 disposable); 800 } else 801#endif /* ZERO_COPY_SOCKETS */ |
|
722 error = uiomove(mtod(m, caddr_t), 723 (int) min(uio->uio_resid, m->m_len), uio); 724 m = m_free(m); 725 } while (uio->uio_resid && error == 0 && m); 726bad: 727 if (m) 728 m_freem(m); 729 return (error); --- 139 unchanged lines hidden (view full) --- 869 * Otherwise copy them out via the uio, then free. 870 * Sockbuf must be consistent here (points to current mbuf, 871 * it points to next record) when we drop priority; 872 * we must note any additions to the sockbuf when we 873 * block interrupts again. 874 */ 875 if (mp == 0) { 876 splx(s); | 802 error = uiomove(mtod(m, caddr_t), 803 (int) min(uio->uio_resid, m->m_len), uio); 804 m = m_free(m); 805 } while (uio->uio_resid && error == 0 && m); 806bad: 807 if (m) 808 m_freem(m); 809 return (error); --- 139 unchanged lines hidden (view full) --- 949 * Otherwise copy them out via the uio, then free. 950 * Sockbuf must be consistent here (points to current mbuf, 951 * it points to next record) when we drop priority; 952 * we must note any additions to the sockbuf when we 953 * block interrupts again. 954 */ 955 if (mp == 0) { 956 splx(s); |
957#ifdef ZERO_COPY_SOCKETS 958 if (so_zero_copy_receive) { 959 vm_page_t pg; 960 int disposable; 961 962 if ((m->m_flags & M_EXT) 963 && (m->m_ext.ext_type == EXT_DISPOSABLE)) 964 disposable = 1; 965 else 966 disposable = 0; 967 968 pg = PHYS_TO_VM_PAGE(vtophys(mtod(m, caddr_t) + 969 moff)); 970 971 if (uio->uio_offset == -1) 972 uio->uio_offset =IDX_TO_OFF(pg->pindex); 973 974 error = uiomoveco(mtod(m, caddr_t) + moff, 975 (int)len, uio,pg->object, 976 disposable); 977 } else 978#endif /* ZERO_COPY_SOCKETS */ |
|
877 error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio); 878 s = splnet(); 879 if (error) 880 goto release; 881 } else 882 uio->uio_resid -= len; 883 if (len == m->m_len - moff) { 884 if (m->m_flags & M_EOR) --- 806 unchanged lines hidden --- | 979 error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio); 980 s = splnet(); 981 if (error) 982 goto release; 983 } else 984 uio->uio_resid -= len; 985 if (len == m->m_len - moff) { 986 if (m->m_flags & M_EOR) --- 806 unchanged lines hidden --- |