Index: subr_pool.c =================================================================== RCS file: /cvs/src/sys/kern/subr_pool.c,v retrieving revision 1.178 diff -u -p -r1.178 subr_pool.c --- subr_pool.c 19 Jan 2015 03:57:22 -0000 1.178 +++ subr_pool.c 19 Jan 2015 06:38:54 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_pool.c,v 1.178 2015/01/19 03:57:22 dlg Exp $ */ +/* $OpenBSD: subr_pool.c,v 1.177 2015/01/05 23:54:18 dlg Exp $ */ /* $NetBSD: subr_pool.c,v 1.61 2001/09/26 07:14:56 chs Exp $ */ /*- @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include @@ -160,6 +162,14 @@ void pool_print1(struct pool *, const c #define pool_sleep(pl) msleep(pl, &pl->pr_mtx, PSWP, pl->pr_wchan, 0) +/* stale page garbage collectors */ +void pool_gc_sched(void *); +struct timeout pool_gc_tick = TIMEOUT_INITIALIZER(pool_gc_sched, NULL); +void pool_gc_pages(void *, void *); +struct task pool_gc_task = TASK_INITIALIZER(pool_gc_pages, NULL, NULL); +int pool_wait_free = 1; +int pool_wait_gc = 8; + static inline int phtree_compare(struct pool_item_header *a, struct pool_item_header *b) { @@ -681,7 +691,7 @@ pool_put(struct pool *pp, void *v) /* 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) { + (ticks - ph->ph_tick) > (hz * pool_wait_free)) { freeph = ph; pool_p_remove(pp, freeph); } @@ -1338,6 +1348,47 @@ done: rw_exit_read(&pool_lock); return (rv); +} + +void +pool_gc_sched(void *null) +{ + task_add(systqmp, &pool_gc_task); +} + +void +pool_gc_pages(void *null, void *x) +{ + extern int ticks; + struct pool *pp; + struct pool_item_header *ph, *freeph; + int s; + + rw_enter_read(&pool_lock); + s = splvm(); + SIMPLEQ_FOREACH(pp, &pool_head, pr_poollist) { + if (pp->pr_nidle <= pp->pr_minpages || /* guess */ + !mtx_enter_try(&pp->pr_mtx)) /* try */ + continue; + + /* 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)) { + freeph = ph; + pool_p_remove(pp, freeph); + } else + freeph = NULL; + + mtx_leave(&pp->pr_mtx); + + if (freeph != NULL) + pool_p_free(pp, freeph); + } + splx(s); /* XXX */ + rw_exit_read(&pool_lock); + + timeout_add_sec(&pool_gc_tick, 1); } /*