uipc_syscalls.c (660ebf0ef21a2acf57094f034b0179375b7d8f60) | uipc_syscalls.c (411d10a600b6d3bf43415ba408b7e221f8688bc2) |
---|---|
1/* 2 * Copyright (c) 1982, 1986, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * sendfile(2) and related extensions: 6 * Copyright (c) 1998, David Greenman. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 63 unchanged lines hidden (view full) --- 72 73#include <vm/vm.h> 74#include <vm/vm_object.h> 75#include <vm/vm_page.h> 76#include <vm/vm_pageout.h> 77#include <vm/vm_kern.h> 78#include <vm/vm_extern.h> 79 | 1/* 2 * Copyright (c) 1982, 1986, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * sendfile(2) and related extensions: 6 * Copyright (c) 1998, David Greenman. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 63 unchanged lines hidden (view full) --- 72 73#include <vm/vm.h> 74#include <vm/vm_object.h> 75#include <vm/vm_page.h> 76#include <vm/vm_pageout.h> 77#include <vm/vm_kern.h> 78#include <vm/vm_extern.h> 79 |
80static void sf_buf_init(void *arg); 81SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL) 82 | |
83static int sendit(struct thread *td, int s, struct msghdr *mp, int flags); 84static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp); 85 86static int accept1(struct thread *td, struct accept_args *uap, int compat); 87static int do_sendfile(struct thread *td, struct sendfile_args *uap, int compat); 88static int getsockname1(struct thread *td, struct getsockname_args *uap, 89 int compat); 90static int getpeername1(struct thread *td, struct getpeername_args *uap, 91 int compat); 92 93/* | 80static int sendit(struct thread *td, int s, struct msghdr *mp, int flags); 81static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp); 82 83static int accept1(struct thread *td, struct accept_args *uap, int compat); 84static int do_sendfile(struct thread *td, struct sendfile_args *uap, int compat); 85static int getsockname1(struct thread *td, struct getsockname_args *uap, 86 int compat); 87static int getpeername1(struct thread *td, struct getpeername_args *uap, 88 int compat); 89 90/* |
94 * Expanded sf_freelist head. Really an SLIST_HEAD() in disguise, with the 95 * sf_freelist head with the sf_lock mutex. 96 */ 97static struct { 98 SLIST_HEAD(, sf_buf) sf_head; 99 struct mtx sf_lock; 100} sf_freelist; 101 102static u_int sf_buf_alloc_want; 103 104/* | |
105 * System call interface to the socket abstraction. 106 */ 107#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 108#define COMPAT_OLDSOCK 109#endif 110 111/* 112 * MPSAFE --- 1514 unchanged lines hidden (view full) --- 1627#endif 1628 sa->sa_len = len; 1629 *namp = sa; 1630 } 1631 return error; 1632} 1633 1634/* | 91 * System call interface to the socket abstraction. 92 */ 93#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 94#define COMPAT_OLDSOCK 95#endif 96 97/* 98 * MPSAFE --- 1514 unchanged lines hidden (view full) --- 1613#endif 1614 sa->sa_len = len; 1615 *namp = sa; 1616 } 1617 return error; 1618} 1619 1620/* |
1635 * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) 1636 */ 1637static void 1638sf_buf_init(void *arg) 1639{ 1640 struct sf_buf *sf_bufs; 1641 vm_offset_t sf_base; 1642 int i; 1643 1644 mtx_init(&sf_freelist.sf_lock, "sf_bufs list lock", NULL, MTX_DEF); 1645 mtx_lock(&sf_freelist.sf_lock); 1646 SLIST_INIT(&sf_freelist.sf_head); 1647 sf_base = kmem_alloc_nofault(kernel_map, nsfbufs * PAGE_SIZE); 1648 sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, 1649 M_NOWAIT | M_ZERO); 1650 for (i = 0; i < nsfbufs; i++) { 1651 sf_bufs[i].kva = sf_base + i * PAGE_SIZE; 1652 SLIST_INSERT_HEAD(&sf_freelist.sf_head, &sf_bufs[i], free_list); 1653 } 1654 sf_buf_alloc_want = 0; 1655 mtx_unlock(&sf_freelist.sf_lock); 1656} 1657 1658/* 1659 * Get an sf_buf from the freelist. Will block if none are available. 1660 */ 1661struct sf_buf * 1662sf_buf_alloc(struct vm_page *m) 1663{ 1664 struct sf_buf *sf; 1665 int error; 1666 1667 mtx_lock(&sf_freelist.sf_lock); 1668 while ((sf = SLIST_FIRST(&sf_freelist.sf_head)) == NULL) { 1669 sf_buf_alloc_want++; 1670 error = msleep(&sf_freelist, &sf_freelist.sf_lock, PVM|PCATCH, 1671 "sfbufa", 0); 1672 sf_buf_alloc_want--; 1673 1674 /* 1675 * If we got a signal, don't risk going back to sleep. 1676 */ 1677 if (error) 1678 break; 1679 } 1680 if (sf != NULL) { 1681 SLIST_REMOVE_HEAD(&sf_freelist.sf_head, free_list); 1682 sf->m = m; 1683 pmap_qenter(sf->kva, &sf->m, 1); 1684 } 1685 mtx_unlock(&sf_freelist.sf_lock); 1686 return (sf); 1687} 1688 1689/* 1690 * Detatch mapped page and release resources back to the system. 1691 */ 1692void 1693sf_buf_free(void *addr, void *args) 1694{ 1695 struct sf_buf *sf; 1696 struct vm_page *m; 1697 1698 sf = args; 1699 pmap_qremove((vm_offset_t)addr, 1); 1700 m = sf->m; 1701 vm_page_lock_queues(); 1702 vm_page_unwire(m, 0); 1703 /* 1704 * Check for the object going away on us. This can 1705 * happen since we don't hold a reference to it. 1706 * If so, we're responsible for freeing the page. 1707 */ 1708 if (m->wire_count == 0 && m->object == NULL) 1709 vm_page_free(m); 1710 vm_page_unlock_queues(); 1711 sf->m = NULL; 1712 mtx_lock(&sf_freelist.sf_lock); 1713 SLIST_INSERT_HEAD(&sf_freelist.sf_head, sf, free_list); 1714 if (sf_buf_alloc_want > 0) 1715 wakeup_one(&sf_freelist); 1716 mtx_unlock(&sf_freelist.sf_lock); 1717} 1718 1719/* | |
1720 * sendfile(2) 1721 * 1722 * MPSAFE 1723 * 1724 * int sendfile(int fd, int s, off_t offset, size_t nbytes, 1725 * struct sf_hdtr *hdtr, off_t *sbytes, int flags) 1726 * 1727 * Send a file specified by 'fd' and starting at 'offset' to a socket --- 371 unchanged lines hidden --- | 1621 * sendfile(2) 1622 * 1623 * MPSAFE 1624 * 1625 * int sendfile(int fd, int s, off_t offset, size_t nbytes, 1626 * struct sf_hdtr *hdtr, off_t *sbytes, int flags) 1627 * 1628 * Send a file specified by 'fd' and starting at 'offset' to a socket --- 371 unchanged lines hidden --- |