Index: subr_pool.c =================================================================== RCS file: /cvs/src/sys/kern/subr_pool.c,v retrieving revision 1.145 diff -u -p -r1.145 subr_pool.c --- subr_pool.c 12 Aug 2014 01:31:43 -0000 1.145 +++ subr_pool.c 12 Aug 2014 01:42:18 -0000 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -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 *); @@ -248,11 +252,6 @@ pool_init(struct pool *pp, size_t size, 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 @@ -340,9 +339,6 @@ pool_init(struct pool *pp, size_t size, 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 @@ -403,8 +399,21 @@ pool_init(struct pool *pp, size_t size, 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 @@ -424,6 +433,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); @@ -442,6 +452,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); @@ -1115,12 +1126,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 @@ -1428,7 +1438,6 @@ sysctl_dopool(int *name, u_int namelen, struct kinfo_pool pi; struct pool *pp; int rv = ENOENT; - int s; switch (name[0]) { case KERN_POOL_NPOOLS: @@ -1446,7 +1455,7 @@ sysctl_dopool(int *name, u_int namelen, 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) @@ -1483,10 +1492,11 @@ sysctl_dopool(int *name, u_int namelen, 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); }