diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2004-04-19 22:52:34 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2004-04-19 22:52:34 +0000 |
commit | 9bc570a1a157252d3dde353d2da5ccfd24665616 (patch) | |
tree | 88a9ac63023de5d94546a8e9129d1c3ecfe7a66b /sys | |
parent | dd55ffea5bfb74d9d44db416eb54a9c0b02fdd3a (diff) |
introduce a new km_page allocator that gets pages from kernel_map using
an interrupt safe thread.
use this as the new backend for mbpool and mclpool, eliminating the mb_map.
introduce a sysctl kern.maxclusters which controls the limit of clusters
allocated.
testing by many people, works everywhere but m68k. ok deraadt@
this essentially deprecates the NMBCLUSTERS option, don't use it.
this should reduce pressure on the kmem_map and the uvm reserve of static
map entries.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_sysctl.c | 9 | ||||
-rw-r--r-- | sys/kern/uipc_mbuf.c | 40 | ||||
-rw-r--r-- | sys/sys/sysctl.h | 6 | ||||
-rw-r--r-- | sys/uvm/uvm_extern.h | 4 | ||||
-rw-r--r-- | sys/uvm/uvm_init.c | 4 | ||||
-rw-r--r-- | sys/uvm/uvm_km.c | 127 | ||||
-rw-r--r-- | sys/uvm/uvm_km.h | 3 |
7 files changed, 166 insertions, 27 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 0d785eb7b39..ece5249fa89 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.105 2004/04/15 00:22:42 tedu Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.106 2004/04/19 22:52:33 tedu Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -90,6 +90,8 @@ extern struct disklist_head disklist; extern fixpt_t ccpu; extern long numvnodes; +extern void nmbclust_update(void); + int sysctl_diskinit(int, struct proc *); int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *); int sysctl_intrcnt(int *, u_int, void *, size_t *); @@ -495,6 +497,11 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) case KERN_EMUL: return (sysctl_emul(name + 1, namelen - 1, oldp, oldlenp, newp, newlen)); + case KERN_MAXCLUSTERS: + error = sysctl_int(oldp, oldlenp, newp, newlen, &nmbclust); + if (!error) + nmbclust_update(); + return (error); default: return (EOPNOTSUPP); } diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 13c00cb32d5..9a8fd13e121 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_mbuf.c,v 1.66 2004/04/17 10:18:12 mcbride Exp $ */ +/* $OpenBSD: uipc_mbuf.c,v 1.67 2004/04/19 22:52:33 tedu Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* @@ -102,9 +102,11 @@ int max_datalen; /* MHLEN - max_hdr */ void *mclpool_alloc(struct pool *, int); void mclpool_release(struct pool *, void *); struct mbuf *m_copym0(struct mbuf *, int, int, int, int); +void nmbclust_update(void); + const char *mclpool_warnmsg = - "WARNING: mclpool limit reached; increase NMBCLUSTERS"; + "WARNING: mclpool limit reached; increase kern.maxclusters"; struct pool_allocator mclpool_allocator = { mclpool_alloc, mclpool_release, 0, @@ -116,24 +118,13 @@ struct pool_allocator mclpool_allocator = { void mbinit() { - vaddr_t minaddr, maxaddr; - - minaddr = vm_map_min(kernel_map); - mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, - nmbclust*(MCLBYTES), VM_MAP_INTRSAFE, FALSE, NULL); - - pool_init(&mbpool, MSIZE, 0, 0, 0, "mbpl", NULL); + pool_init(&mbpool, MSIZE, 0, 0, 0, "mbpl", &mclpool_allocator); pool_init(&mclpool, MCLBYTES, 0, 0, 0, "mclpl", &mclpool_allocator); pool_set_drain_hook(&mbpool, m_reclaim, NULL); pool_set_drain_hook(&mclpool, m_reclaim, NULL); - /* - * Set the hard limit on the mclpool to the number of - * mbuf clusters the kernel is to support. Log the limit - * reached message max once a minute. - */ - (void)pool_sethardlimit(&mclpool, nmbclust, mclpool_warnmsg, 60); + nmbclust_update(); /* * Set a low water mark for both mbufs and clusters. This should @@ -145,20 +136,29 @@ mbinit() pool_setlowat(&mclpool, mcllowat); } +void +nmbclust_update(void) +{ + /* + * Set the hard limit on the mclpool to the number of + * mbuf clusters the kernel is to support. Log the limit + * reached message max once a minute. + */ + (void)pool_sethardlimit(&mclpool, nmbclust, mclpool_warnmsg, 60); +} + + void * mclpool_alloc(struct pool *pp, int flags) { - boolean_t waitok = (flags & PR_WAITOK) ? TRUE : FALSE; - - return ((void *)uvm_km_alloc_poolpage1(mb_map, uvmexp.mb_object, - waitok)); + return uvm_km_getpage(); } void mclpool_release(struct pool *pp, void *v) { - uvm_km_free_poolpage1(mb_map, (vaddr_t)v); + uvm_km_putpage(v); } void diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 32bb152664b..5bf14091529 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sysctl.h,v 1.76 2004/02/27 21:46:44 grange Exp $ */ +/* $OpenBSD: sysctl.h,v 1.77 2004/04/19 22:52:33 tedu Exp $ */ /* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */ /* @@ -179,7 +179,8 @@ struct ctlname { #define KERN_WATCHDOG 64 /* node: watchdog */ #define KERN_EMUL 65 /* node: emuls */ #define KERN_PROC2 66 /* struct: process entries */ -#define KERN_MAXID 67 /* number of valid kern ids */ +#define KERN_MAXCLUSTERS 67 /* number of mclusters */ +#define KERN_MAXID 68 /* number of valid kern ids */ #define CTL_KERN_NAMES { \ { 0, 0 }, \ @@ -249,6 +250,7 @@ struct ctlname { { "watchdog", CTLTYPE_NODE }, \ { "emul", CTLTYPE_NODE }, \ { "proc2", CTLTYPE_STRUCT }, \ + { "maxclusters", CTLTYPE_INT }, \ } /* diff --git a/sys/uvm/uvm_extern.h b/sys/uvm/uvm_extern.h index f1eb2cf02f0..d20e6d25639 100644 --- a/sys/uvm/uvm_extern.h +++ b/sys/uvm/uvm_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_extern.h,v 1.50 2003/08/10 00:04:50 miod Exp $ */ +/* $OpenBSD: uvm_extern.h,v 1.51 2004/04/19 22:52:33 tedu Exp $ */ /* $NetBSD: uvm_extern.h,v 1.57 2001/03/09 01:02:12 chs Exp $ */ /* @@ -511,6 +511,8 @@ void uvm_km_free_poolpage1(vm_map_t, vaddr_t); #define uvm_km_alloc_poolpage(waitok) uvm_km_alloc_poolpage1(kmem_map, \ uvmexp.kmem_object, (waitok)) #define uvm_km_free_poolpage(addr) uvm_km_free_poolpage1(kmem_map, (addr)) +void *uvm_km_getpage(void); +void uvm_km_putpage(void *); /* uvm_map.c */ int uvm_map(vm_map_t, vaddr_t *, vsize_t, diff --git a/sys/uvm/uvm_init.c b/sys/uvm/uvm_init.c index a9915e88040..47b9c469bbe 100644 --- a/sys/uvm/uvm_init.c +++ b/sys/uvm/uvm_init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_init.c,v 1.10 2001/11/06 01:35:04 art Exp $ */ +/* $OpenBSD: uvm_init.c,v 1.11 2004/04/19 22:52:33 tedu Exp $ */ /* $NetBSD: uvm_init.c,v 1.14 2000/06/27 17:29:23 mrg Exp $ */ /* @@ -150,6 +150,8 @@ uvm_init() uao_create(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS, UAO_FLAG_KERNSWAP); + uvm_km_page_init(); + /* * done! */ diff --git a/sys/uvm/uvm_km.c b/sys/uvm/uvm_km.c index d343a59e4f9..a07be5b0b8f 100644 --- a/sys/uvm/uvm_km.c +++ b/sys/uvm/uvm_km.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_km.c,v 1.35 2004/02/23 06:19:32 drahn Exp $ */ +/* $OpenBSD: uvm_km.c,v 1.36 2004/04/19 22:52:33 tedu Exp $ */ /* $NetBSD: uvm_km.c,v 1.42 2001/01/14 02:10:01 thorpej Exp $ */ /* @@ -144,6 +144,7 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/kthread.h> #include <uvm/uvm.h> @@ -915,3 +916,127 @@ uvm_km_free_poolpage1(map, addr) splx(s); #endif /* PMAP_UNMAP_POOLPAGE */ } + +int uvm_km_pages_lowat; +int uvm_km_pages_free; +struct km_page { + struct km_page *next; +} *uvm_km_pages_head; + +void uvm_km_createthread(void *); +void uvm_km_thread(void *); + +void +uvm_km_page_init(void) +{ + struct km_page *head, *page; + int i; + + + head = NULL; + for (i = 0; i < uvm_km_pages_lowat * 4; i++) { +#if defined(PMAP_MAP_POOLPAGE) + struct vm_page *pg; + vaddr_t va; + + pg = uvm_pagealloc(NULL, 0, NULL, 0); + if (__predict_false(pg == NULL)) + break; + + va = PMAP_MAP_POOLPAGE(pg); + if (__predict_false(va == 0)) { + uvm_pagefree(pg); + break; + } + page = (void *)va; +#else + page = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE); +#endif + page->next = head; + head = page; + } + uvm_km_pages_head = head; + uvm_km_pages_free = i; + + kthread_create_deferred(uvm_km_createthread, NULL); +} + +void +uvm_km_createthread(void *arg) +{ + kthread_create(uvm_km_thread, NULL, NULL, "kmthread"); +} + +void +uvm_km_thread(void *arg) +{ + struct km_page *head, *tail, *page; + int i, s, want; + + for (;;) { + if (uvm_km_pages_free >= uvm_km_pages_lowat) + tsleep(&uvm_km_pages_head, PVM, "kmalloc", 0); + want = uvm_km_pages_lowat - uvm_km_pages_free; + if (want < 16) + want = 16; + for (i = 0; i < want; i++) { +#if defined(PMAP_MAP_POOLPAGE) + struct vm_page *pg; + vaddr_t va; + + pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE); + if (__predict_false(pg == NULL)) + break; + va = PMAP_MAP_POOLPAGE(pg); + if (__predict_false(va == 0)) { + uvm_pagefree(pg); + break; + } + page = (void *)va; +#else + page = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE); +#endif + if (i == 0) + head = tail = page; + page->next = head; + head = page; + } + s = splvm(); + tail->next = uvm_km_pages_head; + uvm_km_pages_head = head; + uvm_km_pages_free += i; + splx(s); + } +} + + +void * +uvm_km_getpage(void) +{ + struct km_page *page; + int s; + + s = splvm(); + page = uvm_km_pages_head; + if (page) { + uvm_km_pages_head = page->next; + uvm_km_pages_free--; + } + splx(s); + if (uvm_km_pages_free < uvm_km_pages_lowat) + wakeup(&uvm_km_pages_head); + return (page); +} + +void +uvm_km_putpage(void *v) +{ + struct km_page *page = v; + int s; + + s = splvm(); + page->next = uvm_km_pages_head; + uvm_km_pages_head = page; + uvm_km_pages_free++; + splx(s); +} diff --git a/sys/uvm/uvm_km.h b/sys/uvm/uvm_km.h index 7c1bc043879..1162b4dc29a 100644 --- a/sys/uvm/uvm_km.h +++ b/sys/uvm/uvm_km.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_km.h,v 1.7 2002/03/14 01:27:18 millert Exp $ */ +/* $OpenBSD: uvm_km.h,v 1.8 2004/04/19 22:52:33 tedu Exp $ */ /* $NetBSD: uvm_km.h,v 1.9 1999/06/21 17:25:11 thorpej Exp $ */ /* @@ -49,6 +49,7 @@ */ void uvm_km_init(vaddr_t, vaddr_t); +void uvm_km_page_init(void); void uvm_km_pgremove(struct uvm_object *, vaddr_t, vaddr_t); void uvm_km_pgremove_intrsafe(struct uvm_object *, vaddr_t, vaddr_t); |