aboutsummaryrefslogtreecommitdiff
path: root/src/zone.c
diff options
context:
space:
mode:
authorMike Hommey <mh@glandium.org>2012-03-27 14:20:13 +0200
committerJason Evans <jasone@canonware.com>2012-03-30 11:03:20 -0700
commit3c2ba0dcbc2f4896a892fad84d5dcf5bd4c30a81 (patch)
tree16e472235d441ea69c1170c5be3384809cf56ebd /src/zone.c
parent71a93b8725fb52ae393ab88e2fccd5afa84c66a0 (diff)
downloadjemalloc-3c2ba0dcbc2f4896a892fad84d5dcf5bd4c30a81.tar.gz
Avoid crashes when system libraries use the purgeable zone allocator
Diffstat (limited to 'src/zone.c')
-rw-r--r--src/zone.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/src/zone.c b/src/zone.c
index 4b6c75e..9fc87bb 100644
--- a/src/zone.c
+++ b/src/zone.c
@@ -3,6 +3,13 @@
# error "This source file is for zones on Darwin (OS X)."
#endif
+/*
+ * The malloc_default_purgeable_zone function is only available on >= 10.6.
+ * We need to check whether it is present at runtime, thus the weak_import.
+ */
+extern malloc_zone_t *malloc_default_purgeable_zone(void)
+JEMALLOC_ATTR(weak_import);
+
/******************************************************************************/
/* Data. */
@@ -207,15 +214,29 @@ register_zone(void)
#endif
#endif
- /* Register the custom zone. At this point it won't be the default. */
+ /*
+ * The default purgeable zone is created lazily by OSX's libc. It uses
+ * the default zone when it is created for "small" allocations
+ * (< 15 KiB), but assumes the default zone is a scalable_zone. This
+ * obviously fails when the default zone is the jemalloc zone, so
+ * malloc_default_purgeable_zone is called beforehand so that the
+ * default purgeable zone is created when the default zone is still
+ * a scalable_zone. As purgeable zones only exist on >= 10.6, we need
+ * to check for the existence of malloc_default_purgeable_zone() at
+ * run time.
+ */
+ if (malloc_default_purgeable_zone != NULL)
+ malloc_default_purgeable_zone();
+
+ /* Register the custom zone. At this point it won't be the default. */
malloc_zone_register(&zone);
/*
- * Unregister and reregister the default zone. On OSX >= 10.6,
+ * Unregister and reregister the default zone. On OSX >= 10.6,
* unregistering takes the last registered zone and places it at the
- * location of the specified zone. Unregistering the default zone thus
- * makes the last registered one the default. On OSX < 10.6,
- * unregistering shifts all registered zones. The first registered zone
+ * location of the specified zone. Unregistering the default zone thus
+ * makes the last registered one the default. On OSX < 10.6,
+ * unregistering shifts all registered zones. The first registered zone
* then becomes the default.
*/
do {