summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2004-04-19 22:52:34 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2004-04-19 22:52:34 +0000
commit9bc570a1a157252d3dde353d2da5ccfd24665616 (patch)
tree88a9ac63023de5d94546a8e9129d1c3ecfe7a66b /sys
parentdd55ffea5bfb74d9d44db416eb54a9c0b02fdd3a (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.c9
-rw-r--r--sys/kern/uipc_mbuf.c40
-rw-r--r--sys/sys/sysctl.h6
-rw-r--r--sys/uvm/uvm_extern.h4
-rw-r--r--sys/uvm/uvm_init.c4
-rw-r--r--sys/uvm/uvm_km.c127
-rw-r--r--sys/uvm/uvm_km.h3
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);