Index: subr_pool.c =================================================================== RCS file: /cvs/src/sys/kern/subr_pool.c,v retrieving revision 1.206 diff -u -p -d -r1.206 subr_pool.c --- subr_pool.c 8 Feb 2017 05:28:30 -0000 1.206 +++ subr_pool.c 8 Feb 2017 05:42:47 -0000 @@ -132,6 +132,8 @@ struct pool_cache { void *pool_cache_get(struct pool *); void pool_cache_put(struct pool *, void *); void pool_cache_destroy(struct pool *); +struct pool_cache_item * + pool_cache_list_put(struct pool *, struct pool_cache_item *); #endif void pool_cache_info(struct pool *, struct kinfo_pool *); @@ -151,6 +153,7 @@ void pool_p_free(struct pool *, struct void pool_update_curpage(struct pool *); void *pool_do_get(struct pool *, int, int *); +void pool_do_put(struct pool *, void *); int pool_chk_page(struct pool *, struct pool_page_header *, int); int pool_chk(struct pool *); void pool_get_done(void *, void *); @@ -706,7 +709,6 @@ pool_do_get(struct pool *pp, int flags, void pool_put(struct pool *pp, void *v) { - struct pool_item *pi = v; struct pool_page_header *ph, *freeph = NULL; #ifdef DIAGNOSTIC @@ -723,6 +725,37 @@ pool_put(struct pool *pp, void *v) mtx_enter(&pp->pr_mtx); + pool_do_put(pp, v); + + pp->pr_nout--; + pp->pr_nput++; + + /* is it time to free a page? */ + if (pp->pr_nidle > pp->pr_maxpages && + (ph = TAILQ_FIRST(&pp->pr_emptypages)) != NULL && + (ticks - ph->ph_tick) > (hz * pool_wait_free)) { + freeph = ph; + pool_p_remove(pp, freeph); + } + + mtx_leave(&pp->pr_mtx); + + if (freeph != NULL) + pool_p_free(pp, freeph); + + if (!TAILQ_EMPTY(&pp->pr_requests)) { + mtx_enter(&pp->pr_requests_mtx); + pool_runqueue(pp, PR_NOWAIT); + mtx_leave(&pp->pr_requests_mtx); + } +} + +void +pool_do_put(struct pool *pp, void *v) +{ + struct pool_item *pi = v; + struct pool_page_header *ph; + splassert(pp->pr_ipl); ph = pr_find_pagehead(pp, v); @@ -766,27 +799,6 @@ pool_put(struct pool *pp, void *v) TAILQ_INSERT_TAIL(&pp->pr_emptypages, ph, ph_entry); pool_update_curpage(pp); } - - pp->pr_nout--; - pp->pr_nput++; - - /* is it time to free a page? */ - if (pp->pr_nidle > pp->pr_maxpages && - (ph = TAILQ_FIRST(&pp->pr_emptypages)) != NULL && - (ticks - ph->ph_tick) > (hz * pool_wait_free)) { - freeph = ph; - pool_p_remove(pp, freeph); - } - mtx_leave(&pp->pr_mtx); - - if (freeph != NULL) - pool_p_free(pp, freeph); - - if (!TAILQ_EMPTY(&pp->pr_requests)) { - mtx_enter(&pp->pr_requests_mtx); - pool_runqueue(pp, PR_NOWAIT); - mtx_leave(&pp->pr_requests_mtx); - } } /* @@ -1446,9 +1458,32 @@ pool_gc_pages(void *null) { struct pool *pp; struct pool_page_header *ph, *freeph; + int diff = hz * pool_wait_gc; rw_enter_read(&pool_lock); SIMPLEQ_FOREACH(pp, &pool_head, pr_poollist) { +#ifdef MULTIPROCESSOR + /* if there's percpu caches, try and gc a list of items */ + if (pp->pr_cache != NULL && + (ticks - pp->pr_cache_tick) > diff && + !TAILQ_EMPTY(&pp->pr_cache_lists) && + mtx_enter_try(&pp->pr_cache_mtx)) { + struct pool_cache_item *pl = NULL; + + if ((ticks - pp->pr_cache_tick) > diff && + (pl = TAILQ_FIRST(&pp->pr_cache_lists)) != NULL) { + TAILQ_REMOVE(&pp->pr_cache_lists, pl, ci_nextl); + pp->pr_cache_tick = ticks; + pp->pr_cache_nlist--; + } + + mtx_leave(&pp->pr_cache_mtx); + + if (pl != NULL) + pool_cache_list_put(pp, pl); + } +#endif + if (pp->pr_nidle <= pp->pr_minpages || /* guess */ !mtx_enter_try(&pp->pr_mtx)) /* try */ continue; @@ -1456,7 +1491,7 @@ pool_gc_pages(void *null) /* is it time to free a page? */ if (pp->pr_nidle > pp->pr_minpages && (ph = TAILQ_FIRST(&pp->pr_emptypages)) != NULL && - (ticks - ph->ph_tick) > (hz * pool_wait_gc)) { + (ticks - ph->ph_tick) > diff) { freeph = ph; pool_p_remove(pp, freeph); } else @@ -1705,6 +1740,9 @@ pool_cache_list_free(struct pool *pp, st struct pool_cache_item *ci) { pool_list_enter(pp); + if (TAILQ_EMPTY(&pp->pr_cache_lists)) + pp->pr_cache_tick = ticks; + TAILQ_INSERT_TAIL(&pp->pr_cache_lists, ci, ci_nextl); pp->pr_cache_nlist++; @@ -1837,11 +1875,13 @@ pool_cache_list_put(struct pool *pp, str rpl = TAILQ_NEXT(pl, ci_nextl); + mtx_enter(&pp->pr_mtx); do { next = pl->ci_next; - pool_put(pp, pl); + pool_do_put(pp, pl); pl = next; } while (pl != NULL); + mtx_leave(&pp->pr_mtx); return (rpl); }