diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2014-08-20 00:00:47 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2014-08-20 00:00:47 +0000 |
commit | a8078e17e95e05b865117842de85bf69f5ad99f8 (patch) | |
tree | 823f6d77cd0df316cd13a1701034fb8c71c06a01 | |
parent | 6c3db4655a79f00f0d21cd75cc3994ce3ebb5daa (diff) |
bring back r1.130:
add an explicit rwlock around the global state (the pool list and serial
number) rather than rely on implicit process exclusion, splhigh and splvm.
the only things touching the global state come from process context so we
can get away with an rwlock instead of a mutex. thankfully.
ok matthew@
-rw-r--r-- | sys/kern/subr_pool.c | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/sys/kern/subr_pool.c b/sys/kern/subr_pool.c index ccf6d60160f..5d72eb4f90e 100644 --- a/sys/kern/subr_pool.c +++ b/sys/kern/subr_pool.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_pool.c,v 1.146 2014/08/18 01:28:44 dlg Exp $ */ +/* $OpenBSD: subr_pool.c,v 1.147 2014/08/20 00:00:46 dlg Exp $ */ /* $NetBSD: subr_pool.c,v 1.61 2001/09/26 07:14:56 chs Exp $ */ /*- @@ -39,6 +39,7 @@ #include <sys/malloc.h> #include <sys/pool.h> #include <sys/syslog.h> +#include <sys/rwlock.h> #include <sys/sysctl.h> #include <uvm/uvm_extern.h> @@ -60,6 +61,16 @@ /* List of all pools */ SIMPLEQ_HEAD(,pool) pool_head = SIMPLEQ_HEAD_INITIALIZER(pool_head); +/* + * Every pool gets a unique serial number assigned to it. If this counter + * wraps, we're screwed, but we shouldn't create so many pools anyway. + */ +unsigned int pool_serial; +unsigned int pool_count; + +/* Lock the previous variables making up the global pool state */ +struct rwlock pool_lock = RWLOCK_INITIALIZER("pools"); + /* Private pool for page header structures */ struct pool phpool; @@ -92,13 +103,6 @@ int pool_debug = 0; #define POOL_NEEDS_CATCHUP(pp) \ ((pp)->pr_nitems < (pp)->pr_minitems) -/* - * Every pool gets a unique serial number assigned to it. If this counter - * wraps, we're screwed, but we shouldn't create so many pools anyway. - */ -unsigned int pool_serial; -unsigned int pool_count; - int pool_catchup(struct pool *); void pool_prime_page(struct pool *, caddr_t, struct pool_item_header *); void pool_update_curpage(struct pool *); @@ -245,11 +249,6 @@ pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags, int off, slack; #ifdef DIAGNOSTIC struct pool *iter; - - SIMPLEQ_FOREACH(iter, &pool_head, pr_poollist) { - if (iter == pp) - panic("init pool already on list"); - } #endif #ifdef MALLOC_DEBUG @@ -337,9 +336,6 @@ pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags, pp->pr_hardlimit_ratecap.tv_usec = 0; pp->pr_hardlimit_warning_last.tv_sec = 0; pp->pr_hardlimit_warning_last.tv_usec = 0; - pp->pr_serial = ++pool_serial; - if (pool_serial == 0) - panic("pool_init: too much uptime"); /* * Decide whether to put the page header off page to avoid @@ -400,8 +396,21 @@ pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags, pp->pr_crange = &kp_dirty; /* Insert this into the list of all pools. */ + rw_enter_write(&pool_lock); +#ifdef DIAGNOSTIC + SIMPLEQ_FOREACH(iter, &pool_head, pr_poollist) { + if (iter == pp) + panic("init pool already on list"); + } +#endif + + pp->pr_serial = ++pool_serial; + if (pool_serial == 0) + panic("pool_init: too much uptime"); + SIMPLEQ_INSERT_HEAD(&pool_head, pp, pr_poollist); pool_count++; + rw_exit_write(&pool_lock); } void @@ -421,6 +430,7 @@ pool_destroy(struct pool *pp) struct pool *prev, *iter; /* Remove from global pool list */ + rw_enter_write(&pool_lock); pool_count--; if (pp == SIMPLEQ_FIRST(&pool_head)) SIMPLEQ_REMOVE_HEAD(&pool_head, pr_poollist); @@ -439,6 +449,7 @@ pool_destroy(struct pool *pp) #endif } removed: + rw_exit_write(&pool_lock); #ifdef DIAGNOSTIC if (pp->pr_nout != 0) panic("pool_destroy: pool busy: still out: %u", pp->pr_nout); @@ -1110,12 +1121,11 @@ void pool_reclaim_all(void) { struct pool *pp; - int s; - s = splhigh(); + rw_enter_read(&pool_lock); SIMPLEQ_FOREACH(pp, &pool_head, pr_poollist) pool_reclaim(pp); - splx(s); + rw_exit_read(&pool_lock); } #ifdef DDB @@ -1423,7 +1433,6 @@ sysctl_dopool(int *name, u_int namelen, char *oldp, size_t *oldlenp) struct kinfo_pool pi; struct pool *pp; int rv = ENOENT; - int s; switch (name[0]) { case KERN_POOL_NPOOLS: @@ -1441,7 +1450,7 @@ sysctl_dopool(int *name, u_int namelen, char *oldp, size_t *oldlenp) if (namelen != 2) return (ENOTDIR); - s = splvm(); + rw_enter_read(&pool_lock); SIMPLEQ_FOREACH(pp, &pool_head, pr_poollist) { if (name[1] == pp->pr_serial) @@ -1478,10 +1487,11 @@ sysctl_dopool(int *name, u_int namelen, char *oldp, size_t *oldlenp) mtx_leave(&pp->pr_mtx); rv = sysctl_rdstruct(oldp, oldlenp, NULL, &pi, sizeof(pi)); + break; } done: - splx(s); + rw_exit_read(&pool_lock); return (rv); } |