Page MenuHomeFreeBSD

D61234.1794473431.diff
No OneTemporary

Authored By
Unknown
Size
3 KB
Referenced Files
None
Subscribers
None

D61234.1794473431.diff

diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -1334,22 +1334,28 @@
}
/*
- * Frees all outstanding items in a bucket
+ * Frees count items from the end of a bucket.
*
* Arguments:
* zone The zone to free to, must be unlocked.
* bucket The free/alloc bucket with items.
+ * count The number of items to free.
*
* Returns:
* Nothing
*/
static void
-bucket_drain(uma_zone_t zone, uma_bucket_t bucket)
+bucket_drain_count(uma_zone_t zone, uma_bucket_t bucket, int count)
{
- int i;
+ int first, i;
- if (bucket->ub_cnt == 0)
+ KASSERT(count >= 0 && count <= bucket->ub_cnt,
+ ("%s: invalid count %d", __func__, count));
+ if (count == 0)
return;
+ first = bucket->ub_cnt - count;
+ KASSERT((zone->uz_flags & UMA_ZONE_SMR) == 0 || first == 0,
+ ("%s: partial SMR drain", __func__));
if ((zone->uz_flags & UMA_ZONE_SMR) != 0 &&
bucket->ub_seq != SMR_SEQ_INVALID) {
@@ -1360,18 +1366,25 @@
zone->uz_size, NULL, SKIP_NONE);
}
if (zone->uz_fini)
- for (i = 0; i < bucket->ub_cnt; i++) {
+ for (i = first; i < bucket->ub_cnt; i++) {
kasan_mark_item_valid(zone, bucket->ub_bucket[i]);
zone->uz_fini(bucket->ub_bucket[i], zone->uz_size);
kasan_mark_item_invalid(zone, bucket->ub_bucket[i]);
}
- zone->uz_release(zone->uz_arg, bucket->ub_bucket, bucket->ub_cnt);
+ zone->uz_release(zone->uz_arg, &bucket->ub_bucket[first], count);
if (zone->uz_max_items > 0)
- zone_free_limit(zone, bucket->ub_cnt);
+ zone_free_limit(zone, count);
#ifdef INVARIANTS
- bzero(bucket->ub_bucket, sizeof(void *) * bucket->ub_cnt);
+ bzero(&bucket->ub_bucket[first], sizeof(void *) * count);
#endif
- bucket->ub_cnt = 0;
+ bucket->ub_cnt = first;
+}
+
+static void
+bucket_drain(uma_zone_t zone, uma_bucket_t bucket)
+{
+
+ bucket_drain_count(zone, bucket, bucket->ub_cnt);
}
/*
@@ -4781,6 +4794,37 @@
zone_put_bucket(zone, itemdomain, bucket, udata, ws);
}
+static uma_bucket_t
+cache_free_drain_reuse(uma_zone_t zone, uma_bucket_t *bucketp)
+{
+ uma_cache_t cache;
+ uma_bucket_t bucket;
+ bool alloc;
+
+ bucket = *bucketp;
+ alloc = bucket == NULL;
+ if (bucket == NULL) {
+ critical_enter();
+ cache = &zone->uz_cpu[curcpu];
+ if (cache->uc_freebucket.ucb_bucket == NULL &&
+ cache->uc_allocbucket.ucb_bucket != NULL &&
+ cache->uc_allocbucket.ucb_cnt ==
+ cache->uc_allocbucket.ucb_entries)
+ bucket = cache_bucket_unload_alloc(cache);
+ critical_exit();
+ if (bucket == NULL)
+ return (NULL);
+ }
+ KASSERT(bucket->ub_cnt == bucket->ub_entries &&
+ bucket->ub_seq == SMR_SEQ_INVALID,
+ ("%s: bucket %p not full or SMR", __func__, bucket));
+ *bucketp = NULL;
+ /* Keep half for CPUs that also allocate from this cache. */
+ bucket_drain_count(zone, bucket,
+ alloc ? (bucket->ub_cnt + 1) / 2 : bucket->ub_cnt);
+ return (bucket);
+}
+
/*
* Populate a free or cross bucket for the current cpu cache. Free any
* existing full bucket either to the zone cache or back to the slab layer.
@@ -4841,8 +4885,14 @@
newbucket = bucket;
bucket = NULL;
}
- } else if (!bucketdisable)
+ } else if (!bucketdisable) {
newbucket = bucket_alloc(zone, udata, M_NOWAIT);
+ if (newbucket == NULL &&
+ (zone->uz_flags & (UMA_ZONE_VM | UMA_ZFLAG_CACHE |
+ UMA_ZONE_FIRSTTOUCH)) ==
+ (UMA_ZONE_VM | UMA_ZFLAG_CACHE))
+ newbucket = cache_free_drain_reuse(zone, &bucket);
+ }
if (bucket != NULL)
zone_free_bucket(zone, bucket, udata, itemdomain, true);

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 12, 8:50 AM (18 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41532455
Default Alt Text
D61234.1794473431.diff (3 KB)

Event Timeline