Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-3]: src/sys/kern Pull up revision 1.101 (requested by thorpej in ...
details: https://anonhg.NetBSD.org/src/rev/46a70b55ba2c
branches: netbsd-3
changeset: 576307:46a70b55ba2c
user: tron <tron%NetBSD.org@localhost>
date: Sat Jun 18 11:13:12 2005 +0000
description:
Pull up revision 1.101 (requested by thorpej in ticket #474):
Fix some locking issues:
- Make the locking rules for pr_rmpage() sane, and don't modify fields
protected by the pool lock without actually holding it.
- Always defer freeing the pool page to the back-end allocator, to avoid
invoking the pool_allocator with the pool locked (which would violate
the pool_allocator -> pool locking order).
- Fix pool_reclaim() to not violate the pool_cache -> pool locking order
by using a trylock.
Reviewed by Chuq Silvers.
diffstat:
sys/kern/subr_pool.c | 198 +++++++++++++++++++++++++++++---------------------
1 files changed, 114 insertions(+), 84 deletions(-)
diffs (truncated from 357 to 300 lines):
diff -r 19e8e09a95bc -r 46a70b55ba2c sys/kern/subr_pool.c
--- a/sys/kern/subr_pool.c Sat Jun 18 11:04:52 2005 +0000
+++ b/sys/kern/subr_pool.c Sat Jun 18 11:13:12 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_pool.c,v 1.99 2005/01/01 21:09:56 yamt Exp $ */
+/* $NetBSD: subr_pool.c,v 1.99.8.1 2005/06/18 11:13:12 tron Exp $ */
/*-
* Copyright (c) 1997, 1999, 2000 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_pool.c,v 1.99 2005/01/01 21:09:56 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_pool.c,v 1.99.8.1 2005/06/18 11:13:12 tron Exp $");
#include "opt_pool.h"
#include "opt_poollog.h"
@@ -174,7 +174,7 @@
/* The cache group pool. */
static struct pool pcgpool;
-static void pool_cache_reclaim(struct pool_cache *);
+static void pool_cache_reclaim(struct pool_cache *, struct pool_pagelist *);
static int pool_catchup(struct pool *);
static void pool_prime_page(struct pool *, caddr_t,
@@ -384,6 +384,23 @@
return ph;
}
+static void
+pr_pagelist_free(struct pool *pp, struct pool_pagelist *pq)
+{
+ struct pool_item_header *ph;
+ int s;
+
+ while ((ph = LIST_FIRST(pq)) != NULL) {
+ LIST_REMOVE(ph, ph_pagelist);
+ pool_allocator_free(pp, ph->ph_page);
+ if ((pp->pr_roflags & PR_PHINPAGE) == 0) {
+ s = splvm();
+ pool_put(pp->pr_phpool, ph);
+ splx(s);
+ }
+ }
+}
+
/*
* Remove a page from the pool.
*/
@@ -391,9 +408,8 @@
pr_rmpage(struct pool *pp, struct pool_item_header *ph,
struct pool_pagelist *pq)
{
- int s;
- LOCK_ASSERT(!simple_lock_held(&pp->pr_slock) || pq != NULL);
+ LOCK_ASSERT(simple_lock_held(&pp->pr_slock));
/*
* If the page was idle, decrement the idle page count.
@@ -411,21 +427,13 @@
pp->pr_nitems -= pp->pr_itemsperpage;
/*
- * Unlink a page from the pool and release it (or queue it for release).
+ * Unlink the page from the pool and queue it for release.
*/
LIST_REMOVE(ph, ph_pagelist);
if ((pp->pr_roflags & PR_PHINPAGE) == 0)
SPLAY_REMOVE(phtree, &pp->pr_phtree, ph);
- if (pq) {
- LIST_INSERT_HEAD(pq, ph, ph_pagelist);
- } else {
- pool_allocator_free(pp, ph->ph_page);
- if ((pp->pr_roflags & PR_PHINPAGE) == 0) {
- s = splvm();
- pool_put(pp->pr_phpool, ph);
- splx(s);
- }
- }
+ LIST_INSERT_HEAD(pq, ph, ph_pagelist);
+
pp->pr_npages--;
pp->pr_npagefree++;
@@ -696,20 +704,28 @@
void
pool_destroy(struct pool *pp)
{
+ struct pool_pagelist pq;
struct pool_item_header *ph;
- struct pool_cache *pc;
int s;
- /* Locking order: pool_allocator -> pool */
+ /* Remove from global pool list */
+ simple_lock(&pool_head_slock);
+ TAILQ_REMOVE(&pool_head, pp, pr_poollist);
+ if (drainpp == pp)
+ drainpp = NULL;
+ simple_unlock(&pool_head_slock);
+
+ /* Remove this pool from its allocator's list of pools. */
s = splvm();
simple_lock(&pp->pr_alloc->pa_slock);
TAILQ_REMOVE(&pp->pr_alloc->pa_list, pp, pr_alloc_list);
simple_unlock(&pp->pr_alloc->pa_slock);
splx(s);
- /* Destroy all caches for this pool. */
- while ((pc = TAILQ_FIRST(&pp->pr_cachelist)) != NULL)
- pool_cache_destroy(pc);
+ s = splvm();
+ simple_lock(&pp->pr_slock);
+
+ KASSERT(TAILQ_EMPTY(&pp->pr_cachelist));
#ifdef DIAGNOSTIC
if (pp->pr_nout != 0) {
@@ -719,19 +735,18 @@
}
#endif
- /* Remove all pages */
- while ((ph = LIST_FIRST(&pp->pr_emptypages)) != NULL)
- pr_rmpage(pp, ph, NULL);
KASSERT(LIST_EMPTY(&pp->pr_fullpages));
KASSERT(LIST_EMPTY(&pp->pr_partpages));
- /* Remove from global pool list */
- simple_lock(&pool_head_slock);
- TAILQ_REMOVE(&pool_head, pp, pr_poollist);
- if (drainpp == pp) {
- drainpp = NULL;
- }
- simple_unlock(&pool_head_slock);
+ /* Remove all pages */
+ LIST_INIT(&pq);
+ while ((ph = LIST_FIRST(&pp->pr_emptypages)) != NULL)
+ pr_rmpage(pp, ph, &pq);
+
+ simple_unlock(&pp->pr_slock);
+ splx(s);
+
+ pr_pagelist_free(pp, &pq);
#ifdef POOL_DIAGNOSTIC
if ((pp->pr_roflags & PR_LOGGING) != 0)
@@ -1037,7 +1052,7 @@
* Internal version of pool_put(). Pool is already locked/entered.
*/
static void
-pool_do_put(struct pool *pp, void *v)
+pool_do_put(struct pool *pp, void *v, struct pool_pagelist *pq)
{
struct pool_item *pi = v;
struct pool_item_header *ph;
@@ -1125,9 +1140,7 @@
if (pp->pr_npages > pp->pr_minpages &&
(pp->pr_npages > pp->pr_maxpages ||
(pp->pr_alloc->pa_flags & PA_WANT) != 0)) {
- simple_unlock(&pp->pr_slock);
- pr_rmpage(pp, ph, NULL);
- simple_lock(&pp->pr_slock);
+ pr_rmpage(pp, ph, pq);
} else {
LIST_REMOVE(ph, ph_pagelist);
LIST_INSERT_HEAD(&pp->pr_emptypages, ph, ph_pagelist);
@@ -1165,16 +1178,22 @@
void
_pool_put(struct pool *pp, void *v, const char *file, long line)
{
+ struct pool_pagelist pq;
+
+ LIST_INIT(&pq);
simple_lock(&pp->pr_slock);
pr_enter(pp, file, line);
pr_log(pp, v, PRLOG_PUT, file, line);
- pool_do_put(pp, v);
+ pool_do_put(pp, v, &pq);
pr_leave(pp);
simple_unlock(&pp->pr_slock);
+
+ if (! LIST_EMPTY(&pq))
+ pr_pagelist_free(pp, &pq);
}
#undef pool_put
#endif /* POOL_DIAGNOSTIC */
@@ -1182,12 +1201,16 @@
void
pool_put(struct pool *pp, void *v)
{
+ struct pool_pagelist pq;
+
+ LIST_INIT(&pq);
simple_lock(&pp->pr_slock);
+ pool_do_put(pp, v, &pq);
+ simple_unlock(&pp->pr_slock);
- pool_do_put(pp, v);
-
- simple_unlock(&pp->pr_slock);
+ if (! LIST_EMPTY(&pq))
+ pr_pagelist_free(pp, &pq);
}
#ifdef POOL_DIAGNOSTIC
@@ -1469,7 +1492,7 @@
* Reclaim items from the pool's caches.
*/
TAILQ_FOREACH(pc, &pp->pr_cachelist, pc_poollist)
- pool_cache_reclaim(pc);
+ pool_cache_reclaim(pc, &pq);
s = splclock();
curtime = mono_time;
@@ -1503,17 +1526,7 @@
if (LIST_EMPTY(&pq))
return (0);
- while ((ph = LIST_FIRST(&pq)) != NULL) {
- LIST_REMOVE(ph, ph_pagelist);
- pool_allocator_free(pp, ph->ph_page);
- if (pp->pr_roflags & PR_PHINPAGE) {
- continue;
- }
- s = splvm();
- pool_put(pp->pr_phpool, ph);
- splx(s);
- }
-
+ pr_pagelist_free(pp, &pq);
return (1);
}
@@ -2024,18 +2037,22 @@
}
/*
- * pool_cache_do_invalidate:
+ * pool_cache_invalidate:
*
- * This internal function implements pool_cache_invalidate() and
- * pool_cache_reclaim().
+ * Invalidate a pool cache (destruct and release all of the
+ * cached objects).
*/
-static void
-pool_cache_do_invalidate(struct pool_cache *pc, int free_groups,
- void (*putit)(struct pool *, void *))
+void
+pool_cache_invalidate(struct pool_cache *pc)
{
+ struct pool_pagelist pq;
struct pool_cache_group *pcg, *npcg;
void *object;
- int s;
+
+ LIST_INIT(&pq);
+
+ simple_lock(&pc->pc_slock);
+ simple_lock(&pc->pc_pool->pr_slock);
for (pcg = TAILQ_FIRST(&pc->pc_grouplist); pcg != NULL;
pcg = npcg) {
@@ -2047,33 +2064,15 @@
pc->pc_allocfrom = NULL;
if (pc->pc_dtor != NULL)
(*pc->pc_dtor)(pc->pc_arg, object);
- (*putit)(pc->pc_pool, object);
- }
- if (free_groups) {
- pc->pc_ngroups--;
- TAILQ_REMOVE(&pc->pc_grouplist, pcg, pcg_list);
- if (pc->pc_freeto == pcg)
- pc->pc_freeto = NULL;
- s = splvm();
- pool_put(&pcgpool, pcg);
- splx(s);
+ pool_do_put(pc->pc_pool, object, &pq);
}
}
-}
-/*
- * pool_cache_invalidate:
- *
- * Invalidate a pool cache (destruct and release all of the
- * cached objects).
- */
-void
-pool_cache_invalidate(struct pool_cache *pc)
-{
Home |
Main Index |
Thread Index |
Old Index