summaryrefslogtreecommitdiffstats
path: root/jemalloc/src/huge.c
diff options
context:
space:
mode:
authorJason Evans <je@fb.com>2010-12-04 01:05:01 (GMT)
committerJason Evans <je@fb.com>2010-12-04 01:05:01 (GMT)
commit1c4b088b08d3bc7617a34387e196ce03716160bf (patch)
treeff0edcf0e21d136ddf6ffda51b1a205d9f12e646 /jemalloc/src/huge.c
parent0a36622dd1e2e7da0b833e161ec79398bc30cd5b (diff)
parent0e8d3d2cb9b3c9048b43588271a1e3a837ab186e (diff)
downloadjemalloc-2.1.0.zip
jemalloc-2.1.0.tar.gz
jemalloc-2.1.0.tar.bz2
Merge branch 'dev'2.1.0
Diffstat (limited to 'jemalloc/src/huge.c')
-rw-r--r--jemalloc/src/huge.c57
1 files changed, 51 insertions, 6 deletions
diff --git a/jemalloc/src/huge.c b/jemalloc/src/huge.c
index a035197..0aadc43 100644
--- a/jemalloc/src/huge.c
+++ b/jemalloc/src/huge.c
@@ -215,13 +215,56 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
* expectation that the extra bytes will be reliably preserved.
*/
copysize = (size < oldsize) ? size : oldsize;
- memcpy(ret, ptr, copysize);
- idalloc(ptr);
+
+ /*
+ * Use mremap(2) if this is a huge-->huge reallocation, and neither the
+ * source nor the destination are in swap or dss.
+ */
+#ifdef JEMALLOC_MREMAP_FIXED
+ if (oldsize >= chunksize
+# ifdef JEMALLOC_SWAP
+ && (swap_enabled == false || (chunk_in_swap(ptr) == false &&
+ chunk_in_swap(ret) == false))
+# endif
+# ifdef JEMALLOC_DSS
+ && chunk_in_dss(ptr) == false && chunk_in_dss(ret) == false
+# endif
+ ) {
+ size_t newsize = huge_salloc(ret);
+
+ if (mremap(ptr, oldsize, newsize, MREMAP_MAYMOVE|MREMAP_FIXED,
+ ret) == MAP_FAILED) {
+ /*
+ * Assuming no chunk management bugs in the allocator,
+ * the only documented way an error can occur here is
+ * if the application changed the map type for a
+ * portion of the old allocation. This is firmly in
+ * undefined behavior territory, so write a diagnostic
+ * message, and optionally abort.
+ */
+ char buf[BUFERROR_BUF];
+
+ buferror(errno, buf, sizeof(buf));
+ malloc_write("<jemalloc>: Error in mremap(): ");
+ malloc_write(buf);
+ malloc_write("\n");
+ if (opt_abort)
+ abort();
+ memcpy(ret, ptr, copysize);
+ idalloc(ptr);
+ } else
+ huge_dalloc(ptr, false);
+ } else
+#endif
+ {
+ memcpy(ret, ptr, copysize);
+ idalloc(ptr);
+ }
return (ret);
}
void
-huge_dalloc(void *ptr)
+huge_dalloc(void *ptr, bool unmap)
{
extent_node_t *node, key;
@@ -241,14 +284,16 @@ huge_dalloc(void *ptr)
malloc_mutex_unlock(&huge_mtx);
+ if (unmap) {
/* Unmap chunk. */
#ifdef JEMALLOC_FILL
#if (defined(JEMALLOC_SWAP) || defined(JEMALLOC_DSS))
- if (opt_junk)
- memset(node->addr, 0x5a, node->size);
+ if (opt_junk)
+ memset(node->addr, 0x5a, node->size);
#endif
#endif
- chunk_dealloc(node->addr, node->size);
+ chunk_dealloc(node->addr, node->size);
+ }
base_node_dealloc(node);
}