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 ---