From 4860553a547b21c933c6f7c0316f07b98b0f9937 Mon Sep 17 00:00:00 2001 From: Jeffrey Hsu Date: Wed, 10 Dec 2003 23:48:07 +0000 Subject: [PATCH] Pull the sf_buf routines and structures out into its own files in anticipation of wider future use. Requested and reviewed by: dillon --- sys/conf/files | 3 +- sys/kern/kern_sfbuf.c | 175 +++++++++++++++++++++++++++++++++++++++ sys/kern/uipc_syscalls.c | 139 +------------------------------ sys/sys/mbuf.h | 3 +- sys/sys/sfbuf.h | 46 ++++++++++ sys/sys/socketvar.h | 14 +--- 6 files changed, 227 insertions(+), 153 deletions(-) create mode 100644 sys/kern/kern_sfbuf.c create mode 100644 sys/sys/sfbuf.h diff --git a/sys/conf/files b/sys/conf/files index a4ff861bcd..399c7cdca2 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $ -# $DragonFly: src/sys/conf/files,v 1.35 2003/12/10 22:27:26 dillon Exp $ +# $DragonFly: src/sys/conf/files,v 1.36 2003/12/10 23:48:07 hsu Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -631,6 +631,7 @@ kern/kern_mpipe.c standard kern/kern_shutdown.c standard kern/kern_sig.c standard kern/kern_upcall.c standard +kern/kern_sfbuf.c standard kern/kern_subr.c standard kern/kern_switch.c standard kern/lwkt_thread.c standard diff --git a/sys/kern/kern_sfbuf.c b/sys/kern/kern_sfbuf.c new file mode 100644 index 0000000000..d67dc2e046 --- /dev/null +++ b/sys/kern/kern_sfbuf.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 1998 David Greenman. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $DragonFly: src/sys/kern/kern_sfbuf.c,v 1.1 2003/12/10 23:48:07 hsu Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void sf_buf_init(void *arg); +SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL) + +LIST_HEAD(sf_buf_list, sf_buf); + +/* + * A hash table of active sendfile(2) buffers + */ +static struct sf_buf_list *sf_buf_hashtable; +static u_long sf_buf_hashmask; + +#define SF_BUF_HASH(m) (((m) - vm_page_array) & sf_buf_hashmask) + +static TAILQ_HEAD(, sf_buf) sf_buf_freelist; +static u_int sf_buf_alloc_want; + +static vm_offset_t sf_base; +static struct sf_buf *sf_bufs; + +/* + * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) + */ +static void +sf_buf_init(void *arg) +{ + int i; + + sf_buf_hashtable = hashinit(nsfbufs, M_TEMP, &sf_buf_hashmask); + TAILQ_INIT(&sf_buf_freelist); + sf_base = kmem_alloc_pageable(kernel_map, nsfbufs * PAGE_SIZE); + sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, + M_NOWAIT | M_ZERO); + for (i = 0; i < nsfbufs; i++) { + sf_bufs[i].kva = sf_base + i * PAGE_SIZE; + TAILQ_INSERT_TAIL(&sf_buf_freelist, &sf_bufs[i], free_entry); + } +} + +/* + * Get an sf_buf from the freelist. Will block if none are available. + */ +struct sf_buf * +sf_buf_alloc(struct vm_page *m) +{ + struct sf_buf_list *hash_chain; + struct sf_buf *sf; + int s; + int error; + + s = splimp(); + hash_chain = &sf_buf_hashtable[SF_BUF_HASH(m)]; + LIST_FOREACH(sf, hash_chain, list_entry) { + if (sf->m == m) { + if (sf->refcnt == 0) { + /* reclaim cached entry off freelist */ + TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry); + } + ++sf->refcnt; + goto done; /* found existing mapping */ + } + } + + /* + * Didn't find old mapping. Get a buffer off the freelist. + */ + while ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) { + ++sf_buf_alloc_want; + error = tsleep(&sf_buf_freelist, PCATCH, "sfbufa", 0); + --sf_buf_alloc_want; + + /* If we got a signal, don't risk going back to sleep. */ + if (error) + goto done; + } + TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry); + + if (sf->m != NULL) /* remove previous mapping from hash table */ + LIST_REMOVE(sf, list_entry); + LIST_INSERT_HEAD(hash_chain, sf, list_entry); + sf->refcnt = 1; + sf->m = m; + pmap_qenter(sf->kva, &sf->m, 1); +done: + splx(s); + return (sf); +} + +#define dtosf(x) (&sf_bufs[((uintptr_t)(x) - (uintptr_t)sf_base) >> PAGE_SHIFT]) + +void +sf_buf_ref(caddr_t addr, u_int size) +{ + struct sf_buf *sf; + + sf = dtosf(addr); + if (sf->refcnt == 0) + panic("sf_buf_ref: referencing a free sf_buf"); + sf->refcnt++; +} + +/* + * Lose a reference to an sf_buf. When none left, detach mapped page + * and release resources back to the system. + * + * Must be called at splimp. + */ +void +sf_buf_free(caddr_t addr, u_int size) +{ + struct sf_buf *sf; + struct vm_page *m; + int s; + + sf = dtosf(addr); + if (sf->refcnt == 0) + panic("sf_buf_free: freeing free sf_buf"); + sf->refcnt--; + if (sf->refcnt == 0) { + m = sf->m; + s = splvm(); + vm_page_unwire(m, 0); + /* + * Check for the object going away on us. This can + * happen since we don't hold a reference to it. + * If so, we're responsible for freeing the page. + */ + if (m->wire_count == 0 && m->object == NULL) + vm_page_free(m); + splx(s); + + TAILQ_INSERT_TAIL(&sf_buf_freelist, sf, free_entry); + if (sf_buf_alloc_want > 0) + wakeup_one(&sf_buf_freelist); + } +} diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 9aa515e559..cb61b22ddc 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -35,7 +35,7 @@ * * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 * $FreeBSD: src/sys/kern/uipc_syscalls.c,v 1.65.2.17 2003/04/04 17:11:16 tegge Exp $ - * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.21 2003/12/10 22:26:19 hsu Exp $ + * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.22 2003/12/10 23:48:07 hsu Exp $ */ #include "opt_ktrace.h" @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -72,25 +73,6 @@ #include #include -static void sf_buf_init(void *arg); -SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL) - -LIST_HEAD(sf_buf_list, sf_buf); - -/* - * A hash table of active sendfile(2) buffers - */ -static struct sf_buf_list *sf_buf_hashtable; -static u_long sf_buf_hashmask; - -#define SF_BUF_HASH(m) (((m) - vm_page_array) & sf_buf_hashmask) - -static TAILQ_HEAD(, sf_buf) sf_buf_freelist; -static u_int sf_buf_alloc_want; - -static vm_offset_t sf_base; -static struct sf_buf *sf_bufs; - /* * System call interface to the socket abstraction. */ @@ -1242,123 +1224,6 @@ holdsock(fdp, fdes, fpp) return(error); } -/* - * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) - */ -static void -sf_buf_init(void *arg) -{ - int i; - - sf_buf_hashtable = hashinit(nsfbufs, M_TEMP, &sf_buf_hashmask); - TAILQ_INIT(&sf_buf_freelist); - sf_base = kmem_alloc_pageable(kernel_map, nsfbufs * PAGE_SIZE); - sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, - M_NOWAIT | M_ZERO); - for (i = 0; i < nsfbufs; i++) { - sf_bufs[i].kva = sf_base + i * PAGE_SIZE; - TAILQ_INSERT_TAIL(&sf_buf_freelist, &sf_bufs[i], free_entry); - } -} - -/* - * Get an sf_buf from the freelist. Will block if none are available. - */ -struct sf_buf * -sf_buf_alloc(struct vm_page *m) -{ - struct sf_buf_list *hash_chain; - struct sf_buf *sf; - int s; - int error; - - s = splimp(); - hash_chain = &sf_buf_hashtable[SF_BUF_HASH(m)]; - LIST_FOREACH(sf, hash_chain, list_entry) { - if (sf->m == m) { - if (sf->refcnt == 0) { - /* reclaim cached entry off freelist */ - TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry); - } - ++sf->refcnt; - goto done; /* found existing mapping */ - } - } - - /* - * Didn't find old mapping. Get a buffer off the freelist. - */ - while ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) { - ++sf_buf_alloc_want; - error = tsleep(&sf_buf_freelist, PCATCH, "sfbufa", 0); - --sf_buf_alloc_want; - - /* If we got a signal, don't risk going back to sleep. */ - if (error) - goto done; - } - TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry); - - if (sf->m != NULL) /* remove previous mapping from hash table */ - LIST_REMOVE(sf, list_entry); - LIST_INSERT_HEAD(hash_chain, sf, list_entry); - sf->refcnt = 1; - sf->m = m; - pmap_qenter(sf->kva, &sf->m, 1); -done: - splx(s); - return (sf); -} - -#define dtosf(x) (&sf_bufs[((uintptr_t)(x) - (uintptr_t)sf_base) >> PAGE_SHIFT]) - -void -sf_buf_ref(caddr_t addr, u_int size) -{ - struct sf_buf *sf; - - sf = dtosf(addr); - if (sf->refcnt == 0) - panic("sf_buf_ref: referencing a free sf_buf"); - sf->refcnt++; -} - -/* - * Lose a reference to an sf_buf. When none left, detach mapped page - * and release resources back to the system. - * - * Must be called at splimp. - */ -void -sf_buf_free(caddr_t addr, u_int size) -{ - struct sf_buf *sf; - struct vm_page *m; - int s; - - sf = dtosf(addr); - if (sf->refcnt == 0) - panic("sf_buf_free: freeing free sf_buf"); - sf->refcnt--; - if (sf->refcnt == 0) { - m = sf->m; - s = splvm(); - vm_page_unwire(m, 0); - /* - * Check for the object going away on us. This can - * happen since we don't hold a reference to it. - * If so, we're responsible for freeing the page. - */ - if (m->wire_count == 0 && m->object == NULL) - vm_page_free(m); - splx(s); - - TAILQ_INSERT_TAIL(&sf_buf_freelist, sf, free_entry); - if (sf_buf_alloc_want > 0) - wakeup_one(&sf_buf_freelist); - } -} - /* * sendfile(2). * int sendfile(int fd, int s, off_t offset, size_t nbytes, diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 1ba2d17744..d572d9ddba 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -32,7 +32,7 @@ * * @(#)mbuf.h 8.5 (Berkeley) 2/19/95 * $FreeBSD: src/sys/sys/mbuf.h,v 1.44.2.17 2003/04/15 06:15:02 silby Exp $ - * $DragonFly: src/sys/sys/mbuf.h,v 1.6 2003/07/28 05:03:25 hmp Exp $ + * $DragonFly: src/sys/sys/mbuf.h,v 1.7 2003/12/10 23:48:07 hsu Exp $ */ #ifndef _SYS_MBUF_H_ @@ -457,7 +457,6 @@ extern union mcluster *mclfree; extern struct mbuf *mmbfree; extern int nmbclusters; extern int nmbufs; -extern int nsfbufs; void m_adj(struct mbuf *, int); void m_cat(struct mbuf *, struct mbuf *); diff --git a/sys/sys/sfbuf.h b/sys/sys/sfbuf.h new file mode 100644 index 0000000000..3821805f66 --- /dev/null +++ b/sys/sys/sfbuf.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2003 Alan L. Cox . All rights reserved. + * Copyright (c) 1998 David Greenman. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $DragonFly: src/sys/sys/sfbuf.h,v 1.1 2003/12/10 23:48:07 hsu Exp $ + */ + +#ifndef _SFBUF_H_ +#define _SFBUF_H_ + +struct sf_buf { + LIST_ENTRY(sf_buf) list_entry; /* hash chain of active buffers */ + TAILQ_ENTRY(sf_buf) free_entry; /* list of free buffers */ + struct vm_page *m; /* currently mapped page */ + vm_offset_t kva; /* va of mapping */ + int refcnt; /* usage of this mapping */ +}; + +extern int nsfbufs; + +struct sf_buf *sf_buf_alloc(struct vm_page *); +void sf_buf_free(caddr_t addr, u_int size); +void sf_buf_ref(caddr_t addr, u_int size); + +#endif diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 49e9948002..5051c4559e 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -32,7 +32,7 @@ * * @(#)socketvar.h 8.3 (Berkeley) 2/19/95 * $FreeBSD: src/sys/sys/socketvar.h,v 1.46.2.10 2003/08/24 08:24:39 hsu Exp $ - * $DragonFly: src/sys/sys/socketvar.h,v 1.7 2003/12/10 22:26:19 hsu Exp $ + * $DragonFly: src/sys/sys/socketvar.h,v 1.8 2003/12/10 23:48:07 hsu Exp $ */ #ifndef _SYS_SOCKETVAR_H_ @@ -270,14 +270,6 @@ struct sockopt { struct thread *sopt_td; /* calling thread or null if kernel */ }; -struct sf_buf { - LIST_ENTRY(sf_buf) list_entry; /* hash chain of active buffers */ - TAILQ_ENTRY(sf_buf) free_entry; /* list of free buffers */ - struct vm_page *m; /* currently mapped page */ - vm_offset_t kva; /* va of mapping */ - int refcnt; /* usage of this mapping */ -}; - struct accept_filter { char accf_name[16]; void (*accf_callback) @@ -350,10 +342,6 @@ int sbreserve (struct sockbuf *sb, u_long cc, struct socket *so, void sbtoxsockbuf (struct sockbuf *sb, struct xsockbuf *xsb); int sbwait (struct sockbuf *sb); int sb_lock (struct sockbuf *sb); -struct sf_buf * - sf_buf_alloc(struct vm_page *); -void sf_buf_free(caddr_t addr, u_int size); -void sf_buf_ref(caddr_t addr, u_int size); int soabort (struct socket *so); int soaccept (struct socket *so, struct sockaddr **nam); struct socket *soalloc (int waitok); -- 2.35.2