Improve zone support for OSX
I tested a build from 10.7 run on 10.7 and 10.6, and a build from 10.6 run on 10.6. The AC_COMPILE_IFELSE limbo is to avoid running a program during configure, which presumably makes it work when cross compiling for iOS.
This commit is contained in:
parent
f4d0fc310e
commit
154829d256
57
configure.ac
57
configure.ac
@ -877,39 +877,32 @@ if test "x${abi}" = "xmacho" ; then
|
|||||||
dnl releases. malloc_zone_t and malloc_introspection_t have new fields in
|
dnl releases. malloc_zone_t and malloc_introspection_t have new fields in
|
||||||
dnl 10.6, which is the only source-level indication of the change.
|
dnl 10.6, which is the only source-level indication of the change.
|
||||||
AC_MSG_CHECKING([malloc zone version])
|
AC_MSG_CHECKING([malloc zone version])
|
||||||
AC_TRY_COMPILE([#include <stdlib.h>
|
AC_DEFUN([JE_ZONE_PROGRAM],
|
||||||
#include <malloc/malloc.h>], [
|
[AC_LANG_PROGRAM(
|
||||||
static malloc_zone_t zone;
|
[#include <malloc/malloc.h>],
|
||||||
static struct malloc_introspection_t zone_introspect;
|
[static foo[[sizeof($1) $2 sizeof(void *) * $3 ? 1 : -1]]]
|
||||||
|
)])
|
||||||
|
|
||||||
zone.size = NULL;
|
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,14)],[JEMALLOC_ZONE_VERSION=3],[
|
||||||
zone.malloc = NULL;
|
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,15)],[JEMALLOC_ZONE_VERSION=5],[
|
||||||
zone.calloc = NULL;
|
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,16)],[
|
||||||
zone.valloc = NULL;
|
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,9)],[JEMALLOC_ZONE_VERSION=6],[
|
||||||
zone.free = NULL;
|
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,13)],[JEMALLOC_ZONE_VERSION=7],[JEMALLOC_ZONE_VERSION=]
|
||||||
zone.realloc = NULL;
|
)])],[
|
||||||
zone.destroy = NULL;
|
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,17)],[JEMALLOC_ZONE_VERSION=8],[
|
||||||
zone.zone_name = "jemalloc_zone";
|
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,>,17)],[JEMALLOC_ZONE_VERSION=9],[JEMALLOC_ZONE_VERSION=]
|
||||||
zone.batch_malloc = NULL;
|
)])])])])
|
||||||
zone.batch_free = NULL;
|
if test "x${JEMALLOC_ZONE_VERSION}" = "x"; then
|
||||||
zone.introspect = &zone_introspect;
|
AC_MSG_RESULT([unsupported])
|
||||||
zone.version = 6;
|
AC_MSG_ERROR([Unsupported malloc zone version])
|
||||||
zone.memalign = NULL;
|
fi
|
||||||
zone.free_definite_size = NULL;
|
if test "${JEMALLOC_ZONE_VERSION}" = 9; then
|
||||||
|
JEMALLOC_ZONE_VERSION=8
|
||||||
zone_introspect.enumerator = NULL;
|
AC_MSG_RESULT([> 8])
|
||||||
zone_introspect.good_size = NULL;
|
else
|
||||||
zone_introspect.check = NULL;
|
AC_MSG_RESULT([$JEMALLOC_ZONE_VERSION])
|
||||||
zone_introspect.print = NULL;
|
fi
|
||||||
zone_introspect.log = NULL;
|
AC_DEFINE_UNQUOTED(JEMALLOC_ZONE_VERSION, [$JEMALLOC_ZONE_VERSION])
|
||||||
zone_introspect.force_lock = NULL;
|
|
||||||
zone_introspect.force_unlock = NULL;
|
|
||||||
zone_introspect.statistics = NULL;
|
|
||||||
zone_introspect.zone_locked = NULL;
|
|
||||||
], [AC_DEFINE_UNQUOTED([JEMALLOC_ZONE_VERSION], [6])
|
|
||||||
AC_MSG_RESULT([6])],
|
|
||||||
[AC_DEFINE_UNQUOTED([JEMALLOC_ZONE_VERSION], [3])
|
|
||||||
AC_MSG_RESULT([3])])
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl ============================================================================
|
dnl ============================================================================
|
||||||
|
@ -747,15 +747,23 @@ malloc_init_hard(void)
|
|||||||
arenas[0] = init_arenas[0];
|
arenas[0] = init_arenas[0];
|
||||||
|
|
||||||
#ifdef JEMALLOC_ZONE
|
#ifdef JEMALLOC_ZONE
|
||||||
/* Register the custom zone. */
|
/* Register the custom zone. At this point it won't be the default. */
|
||||||
malloc_zone_register(create_zone());
|
malloc_zone_t *jemalloc_zone = create_zone();
|
||||||
|
malloc_zone_register(jemalloc_zone);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the default szone to an "overlay zone" that is capable of
|
* Unregister and reregister the default zone. On OSX >= 10.6,
|
||||||
* deallocating szone-allocated objects, but allocating new objects
|
* unregistering takes the last registered zone and places it at the
|
||||||
* from jemalloc.
|
* 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.
|
||||||
*/
|
*/
|
||||||
szone2ozone(malloc_default_zone());
|
do {
|
||||||
|
malloc_zone_t *default_zone = malloc_default_zone();
|
||||||
|
malloc_zone_unregister(default_zone);
|
||||||
|
malloc_zone_register(default_zone);
|
||||||
|
} while (malloc_default_zone() != jemalloc_zone);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
malloc_initialized = true;
|
malloc_initialized = true;
|
||||||
|
193
src/zone.c
193
src/zone.c
@ -6,8 +6,8 @@
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Data. */
|
/* Data. */
|
||||||
|
|
||||||
static malloc_zone_t zone, szone;
|
static malloc_zone_t zone;
|
||||||
static struct malloc_introspection_t zone_introspect, ozone_introspect;
|
static struct malloc_introspection_t zone_introspect;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Function prototypes for non-inline static functions. */
|
/* Function prototypes for non-inline static functions. */
|
||||||
@ -18,8 +18,10 @@ static void *zone_calloc(malloc_zone_t *zone, size_t num, size_t size);
|
|||||||
static void *zone_valloc(malloc_zone_t *zone, size_t size);
|
static void *zone_valloc(malloc_zone_t *zone, size_t size);
|
||||||
static void zone_free(malloc_zone_t *zone, void *ptr);
|
static void zone_free(malloc_zone_t *zone, void *ptr);
|
||||||
static void *zone_realloc(malloc_zone_t *zone, void *ptr, size_t size);
|
static void *zone_realloc(malloc_zone_t *zone, void *ptr, size_t size);
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 6)
|
#if (JEMALLOC_ZONE_VERSION >= 5)
|
||||||
static void *zone_memalign(malloc_zone_t *zone, size_t alignment,
|
static void *zone_memalign(malloc_zone_t *zone, size_t alignment,
|
||||||
|
#endif
|
||||||
|
#if (JEMALLOC_ZONE_VERSION >= 6)
|
||||||
size_t size);
|
size_t size);
|
||||||
static void zone_free_definite_size(malloc_zone_t *zone, void *ptr,
|
static void zone_free_definite_size(malloc_zone_t *zone, void *ptr,
|
||||||
size_t size);
|
size_t size);
|
||||||
@ -28,19 +30,6 @@ static void *zone_destroy(malloc_zone_t *zone);
|
|||||||
static size_t zone_good_size(malloc_zone_t *zone, size_t size);
|
static size_t zone_good_size(malloc_zone_t *zone, size_t size);
|
||||||
static void zone_force_lock(malloc_zone_t *zone);
|
static void zone_force_lock(malloc_zone_t *zone);
|
||||||
static void zone_force_unlock(malloc_zone_t *zone);
|
static void zone_force_unlock(malloc_zone_t *zone);
|
||||||
static size_t ozone_size(malloc_zone_t *zone, void *ptr);
|
|
||||||
static void ozone_free(malloc_zone_t *zone, void *ptr);
|
|
||||||
static void *ozone_realloc(malloc_zone_t *zone, void *ptr, size_t size);
|
|
||||||
static unsigned ozone_batch_malloc(malloc_zone_t *zone, size_t size,
|
|
||||||
void **results, unsigned num_requested);
|
|
||||||
static void ozone_batch_free(malloc_zone_t *zone, void **to_be_freed,
|
|
||||||
unsigned num);
|
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 6)
|
|
||||||
static void ozone_free_definite_size(malloc_zone_t *zone, void *ptr,
|
|
||||||
size_t size);
|
|
||||||
#endif
|
|
||||||
static void ozone_force_lock(malloc_zone_t *zone);
|
|
||||||
static void ozone_force_unlock(malloc_zone_t *zone);
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/*
|
/*
|
||||||
@ -101,7 +90,7 @@ zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
|
|||||||
return (je_realloc(ptr, size));
|
return (je_realloc(ptr, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 6)
|
#if (JEMALLOC_ZONE_VERSION >= 5)
|
||||||
static void *
|
static void *
|
||||||
zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
|
zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
|
||||||
{
|
{
|
||||||
@ -111,7 +100,9 @@ zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
|
|||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (JEMALLOC_ZONE_VERSION >= 6)
|
||||||
static void
|
static void
|
||||||
zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
|
zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
@ -171,10 +162,15 @@ create_zone(void)
|
|||||||
zone.batch_free = NULL;
|
zone.batch_free = NULL;
|
||||||
zone.introspect = &zone_introspect;
|
zone.introspect = &zone_introspect;
|
||||||
zone.version = JEMALLOC_ZONE_VERSION;
|
zone.version = JEMALLOC_ZONE_VERSION;
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 6)
|
#if (JEMALLOC_ZONE_VERSION >= 5)
|
||||||
zone.memalign = zone_memalign;
|
zone.memalign = zone_memalign;
|
||||||
|
#endif
|
||||||
|
#if (JEMALLOC_ZONE_VERSION >= 6)
|
||||||
zone.free_definite_size = zone_free_definite_size;
|
zone.free_definite_size = zone_free_definite_size;
|
||||||
#endif
|
#endif
|
||||||
|
#if (JEMALLOC_ZONE_VERSION >= 8)
|
||||||
|
zone.pressure_relief = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
zone_introspect.enumerator = NULL;
|
zone_introspect.enumerator = NULL;
|
||||||
zone_introspect.good_size = (void *)zone_good_size;
|
zone_introspect.good_size = (void *)zone_good_size;
|
||||||
@ -187,156 +183,15 @@ create_zone(void)
|
|||||||
#if (JEMALLOC_ZONE_VERSION >= 6)
|
#if (JEMALLOC_ZONE_VERSION >= 6)
|
||||||
zone_introspect.zone_locked = NULL;
|
zone_introspect.zone_locked = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
#if (JEMALLOC_ZONE_VERSION >= 7)
|
||||||
|
zone_introspect.enable_discharge_checking = NULL;
|
||||||
|
zone_introspect.disable_discharge_checking = NULL;
|
||||||
|
zone_introspect.discharge = NULL;
|
||||||
|
#ifdef __BLOCKS__
|
||||||
|
zone_introspect.enumerate_discharged_pointers = NULL;
|
||||||
|
#else
|
||||||
|
zone_introspect.enumerate_unavailable_without_blocks = NULL;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
return (&zone);
|
return (&zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
|
||||||
ozone_size(malloc_zone_t *zone, void *ptr)
|
|
||||||
{
|
|
||||||
size_t ret;
|
|
||||||
|
|
||||||
ret = ivsalloc(ptr);
|
|
||||||
if (ret == 0)
|
|
||||||
ret = szone.size(zone, ptr);
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ozone_free(malloc_zone_t *zone, void *ptr)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (ivsalloc(ptr) != 0)
|
|
||||||
je_free(ptr);
|
|
||||||
else {
|
|
||||||
size_t size = szone.size(zone, ptr);
|
|
||||||
if (size != 0)
|
|
||||||
(szone.free)(zone, ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
ozone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
|
|
||||||
{
|
|
||||||
size_t oldsize;
|
|
||||||
|
|
||||||
if (ptr == NULL)
|
|
||||||
return (je_malloc(size));
|
|
||||||
|
|
||||||
oldsize = ivsalloc(ptr);
|
|
||||||
if (oldsize != 0)
|
|
||||||
return (je_realloc(ptr, size));
|
|
||||||
else {
|
|
||||||
oldsize = szone.size(zone, ptr);
|
|
||||||
if (oldsize == 0)
|
|
||||||
return (je_malloc(size));
|
|
||||||
else {
|
|
||||||
void *ret = je_malloc(size);
|
|
||||||
if (ret != NULL) {
|
|
||||||
memcpy(ret, ptr, (oldsize < size) ? oldsize :
|
|
||||||
size);
|
|
||||||
(szone.free)(zone, ptr);
|
|
||||||
}
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned
|
|
||||||
ozone_batch_malloc(malloc_zone_t *zone, size_t size, void **results,
|
|
||||||
unsigned num_requested)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* Don't bother implementing this interface, since it isn't required. */
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ozone_batch_free(malloc_zone_t *zone, void **to_be_freed, unsigned num)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
for (i = 0; i < num; i++)
|
|
||||||
ozone_free(zone, to_be_freed[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 6)
|
|
||||||
static void
|
|
||||||
ozone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (ivsalloc(ptr) != 0) {
|
|
||||||
assert(ivsalloc(ptr) == size);
|
|
||||||
je_free(ptr);
|
|
||||||
} else {
|
|
||||||
assert(size == szone.size(zone, ptr));
|
|
||||||
szone.free_definite_size(zone, ptr, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
ozone_force_lock(malloc_zone_t *zone)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* jemalloc locking is taken care of by the normal jemalloc zone. */
|
|
||||||
szone.introspect->force_lock(zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ozone_force_unlock(malloc_zone_t *zone)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* jemalloc locking is taken care of by the normal jemalloc zone. */
|
|
||||||
szone.introspect->force_unlock(zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Overlay the default scalable zone (szone) such that existing allocations are
|
|
||||||
* drained, and further allocations come from jemalloc. This is necessary
|
|
||||||
* because Core Foundation directly accesses and uses the szone before the
|
|
||||||
* jemalloc library is even loaded.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
szone2ozone(malloc_zone_t *zone)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stash a copy of the original szone so that we can call its
|
|
||||||
* functions as needed. Note that the internally, the szone stores its
|
|
||||||
* bookkeeping data structures immediately following the malloc_zone_t
|
|
||||||
* header, so when calling szone functions, we need to pass a pointer
|
|
||||||
* to the original zone structure.
|
|
||||||
*/
|
|
||||||
memcpy(&szone, zone, sizeof(malloc_zone_t));
|
|
||||||
|
|
||||||
zone->size = (void *)ozone_size;
|
|
||||||
zone->malloc = (void *)zone_malloc;
|
|
||||||
zone->calloc = (void *)zone_calloc;
|
|
||||||
zone->valloc = (void *)zone_valloc;
|
|
||||||
zone->free = (void *)ozone_free;
|
|
||||||
zone->realloc = (void *)ozone_realloc;
|
|
||||||
zone->destroy = (void *)zone_destroy;
|
|
||||||
zone->zone_name = "jemalloc_ozone";
|
|
||||||
zone->batch_malloc = ozone_batch_malloc;
|
|
||||||
zone->batch_free = ozone_batch_free;
|
|
||||||
zone->introspect = &ozone_introspect;
|
|
||||||
zone->version = JEMALLOC_ZONE_VERSION;
|
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 6)
|
|
||||||
zone->memalign = zone_memalign;
|
|
||||||
zone->free_definite_size = ozone_free_definite_size;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ozone_introspect.enumerator = NULL;
|
|
||||||
ozone_introspect.good_size = (void *)zone_good_size;
|
|
||||||
ozone_introspect.check = NULL;
|
|
||||||
ozone_introspect.print = NULL;
|
|
||||||
ozone_introspect.log = NULL;
|
|
||||||
ozone_introspect.force_lock = (void *)ozone_force_lock;
|
|
||||||
ozone_introspect.force_unlock = (void *)ozone_force_unlock;
|
|
||||||
ozone_introspect.statistics = NULL;
|
|
||||||
#if (JEMALLOC_ZONE_VERSION >= 6)
|
|
||||||
ozone_introspect.zone_locked = NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user