summaryrefslogtreecommitdiffstats
path: root/src/extent.c
diff options
context:
space:
mode:
authorJason Evans <jasone@canonware.com>2016-09-23 19:11:01 (GMT)
committerJason Evans <jasone@canonware.com>2016-09-23 19:21:25 (GMT)
commitfd96974040b54538a43951f630e9fea461408384 (patch)
treef4f8df4fc6720e5f962f9d7512b63e11cc9f91e5 /src/extent.c
parentf6d01ff4b7322eeed56c61a11e3e3397765d3f22 (diff)
downloadjemalloc-fd96974040b54538a43951f630e9fea461408384.zip
jemalloc-fd96974040b54538a43951f630e9fea461408384.tar.gz
jemalloc-fd96974040b54538a43951f630e9fea461408384.tar.bz2
Add new_addr validation in extent_recycle().
Diffstat (limited to 'src/extent.c')
-rw-r--r--src/extent.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/src/extent.c b/src/extent.c
index 522cbb9..3ab48ca 100644
--- a/src/extent.c
+++ b/src/extent.c
@@ -400,6 +400,25 @@ extent_recycle(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
assert(new_addr == NULL || !slab);
assert(pad == 0 || !slab);
+ if (config_debug && new_addr != NULL) {
+ extent_t *prev;
+
+ /*
+ * Non-NULL new_addr has two use cases:
+ *
+ * 1) Recycle a known-extant extent, e.g. during purging.
+ * 2) Perform in-place expanding reallocation.
+ *
+ * Regardless of use case, new_addr must either refer to a
+ * non-existing extent, or to the base of an extant extent,
+ * since only active slabs support interior lookups (which of
+ * course cannot be recycled).
+ */
+ assert(PAGE_ADDR2BASE(new_addr) == new_addr);
+ prev = extent_lookup(tsdn, (void *)((uintptr_t)new_addr - PAGE),
+ false);
+ assert(prev == NULL || extent_past_get(prev) == new_addr);
+ }
size = usize + pad;
alloc_size = s2u(size + PAGE_CEILING(alignment) - PAGE);
@@ -417,17 +436,20 @@ extent_recycle(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
if (elm != NULL) {
extent = rtree_elm_read_acquired(tsdn, &extents_rtree,
elm);
- if (extent != NULL && (extent_arena_get(extent) != arena
- || extent_active_get(extent) ||
- extent_retained_get(extent) == cache))
- extent = NULL;
+ if (extent != NULL) {
+ assert(extent_base_get(extent) == new_addr);
+ if (extent_arena_get(extent) != arena ||
+ extent_size_get(extent) < size ||
+ extent_active_get(extent) ||
+ extent_retained_get(extent) == cache)
+ extent = NULL;
+ }
rtree_elm_release(tsdn, &extents_rtree, elm);
} else
extent = NULL;
} else
extent = extent_first_best_fit(arena, extent_heaps, alloc_size);
- if (extent == NULL || (new_addr != NULL && extent_size_get(extent) <
- size)) {
+ if (extent == NULL) {
if (!locked)
malloc_mutex_unlock(tsdn, &arena->extents_mtx);
return (NULL);