summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2002-05-13 05:08:18 +0000
committerjeff <jeff@FreeBSD.org>2002-05-13 05:08:18 +0000
commit7b96796a72f59117d800cf5406c3de05cad1d43c (patch)
tree8614ce5746f83b45db2523cc42c33d1732094ed4 /sys
parent08b1ec116047eb21b3e5e07675847989c2d2ef90 (diff)
downloadFreeBSD-src-7b96796a72f59117d800cf5406c3de05cad1d43c.zip
FreeBSD-src-7b96796a72f59117d800cf5406c3de05cad1d43c.tar.gz
Don't call the uz free function while the zone lock is held. This can lead
to lock order reversals. uma_reclaim now builds a list of freeable slabs and then unlocks the zones to do all of the frees.
Diffstat (limited to 'sys')
-rw-r--r--sys/vm/uma_core.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index 0274ccb..df79668 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -575,6 +575,7 @@ cache_drain(uma_zone_t zone)
static void
zone_drain(uma_zone_t zone)
{
+ struct slabhead freeslabs = {};
uma_slab_t slab;
uma_slab_t n;
u_int64_t extra;
@@ -621,6 +622,26 @@ zone_drain(uma_zone_t zone)
LIST_REMOVE(slab, us_link);
zone->uz_pages -= zone->uz_ppera;
zone->uz_free -= zone->uz_ipers;
+
+ if (zone->uz_flags & UMA_ZFLAG_MALLOC) {
+ mtx_lock(&malloc_mtx);
+ UMA_HASH_REMOVE(mallochash, slab, slab->us_data);
+ mtx_unlock(&malloc_mtx);
+ }
+ if (zone->uz_flags & UMA_ZFLAG_OFFPAGE &&
+ !(zone->uz_flags & UMA_ZFLAG_MALLOC))
+ UMA_HASH_REMOVE(&zone->uz_hash, slab, slab->us_data);
+
+ SLIST_INSERT_HEAD(&freeslabs, slab, us_hlink);
+
+ slab = n;
+ extra--;
+ }
+finished:
+ ZONE_UNLOCK(zone);
+
+ while ((slab = SLIST_FIRST(&freeslabs)) != NULL) {
+ SLIST_REMOVE(&freeslabs, slab, uma_slab, us_hlink);
if (zone->uz_fini)
for (i = 0; i < zone->uz_ipers; i++)
zone->uz_fini(
@@ -628,16 +649,7 @@ zone_drain(uma_zone_t zone)
zone->uz_size);
flags = slab->us_flags;
mem = slab->us_data;
- if (zone->uz_flags & UMA_ZFLAG_MALLOC) {
- mtx_lock(&malloc_mtx);
- UMA_HASH_REMOVE(mallochash, slab, slab->us_data);
- mtx_unlock(&malloc_mtx);
- }
if (zone->uz_flags & UMA_ZFLAG_OFFPAGE) {
- if (!(zone->uz_flags & UMA_ZFLAG_MALLOC)) {
- UMA_HASH_REMOVE(&zone->uz_hash,
- slab, slab->us_data);
- }
uma_zfree_internal(slabzone, slab, NULL, 0);
}
#ifdef UMA_DEBUG
@@ -645,13 +657,8 @@ zone_drain(uma_zone_t zone)
zone->uz_name, UMA_SLAB_SIZE * zone->uz_ppera);
#endif
zone->uz_freef(mem, UMA_SLAB_SIZE * zone->uz_ppera, flags);
-
- slab = n;
- extra--;
}
-finished:
- ZONE_UNLOCK(zone);
}
/*
OpenPOWER on IntegriCloud