Don't rely on OSX SDK malloc/malloc.h for malloc_zone struct definitions

The SDK jemalloc is built against might be not be the latest for various
reasons, but the resulting binary ought to work on newer versions of
OSX.

In order to ensure this, we need the fullest definitions possible, so
copy what we need from the latest version of malloc/malloc.h available
on opensource.apple.com.
This commit is contained in:
Mike Hommey 2017-01-17 15:54:36 +09:00 committed by Jason Evans
parent 1ff09534b5
commit 0f7376eb62
4 changed files with 86 additions and 69 deletions

View File

@ -1869,37 +1869,6 @@ if test "x${enable_zone_allocator}" = "x1" ; then
AC_MSG_ERROR([--enable-zone-allocator is only supported on Darwin]) AC_MSG_ERROR([--enable-zone-allocator is only supported on Darwin])
fi fi
AC_DEFINE([JEMALLOC_ZONE], [ ]) AC_DEFINE([JEMALLOC_ZONE], [ ])
dnl The szone version jumped from 3 to 6 between the OS X 10.5.x and 10.6
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.
AC_MSG_CHECKING([malloc zone version])
AC_DEFUN([JE_ZONE_PROGRAM],
[AC_LANG_PROGRAM(
[#include <malloc/malloc.h>],
[static int foo[[sizeof($1) $2 sizeof(void *) * $3 ? 1 : -1]]]
)])
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,14)],[JEMALLOC_ZONE_VERSION=3],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,15)],[JEMALLOC_ZONE_VERSION=5],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,16)],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,9)],[JEMALLOC_ZONE_VERSION=6],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,13)],[JEMALLOC_ZONE_VERSION=7],[JEMALLOC_ZONE_VERSION=]
)])],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,17)],[JEMALLOC_ZONE_VERSION=8],[
AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,>,17)],[JEMALLOC_ZONE_VERSION=9],[JEMALLOC_ZONE_VERSION=]
)])])])])
if test "x${JEMALLOC_ZONE_VERSION}" = "x"; then
AC_MSG_RESULT([unsupported])
AC_MSG_ERROR([Unsupported malloc zone version])
fi
if test "${JEMALLOC_ZONE_VERSION}" = 9; then
JEMALLOC_ZONE_VERSION=8
AC_MSG_RESULT([> 8])
else
AC_MSG_RESULT([$JEMALLOC_ZONE_VERSION])
fi
AC_DEFINE_UNQUOTED(JEMALLOC_ZONE_VERSION, [$JEMALLOC_ZONE_VERSION])
fi fi
dnl ============================================================================ dnl ============================================================================

View File

@ -162,7 +162,6 @@ static const bool have_thp =
#include <mach/mach_error.h> #include <mach/mach_error.h>
#include <mach/mach_init.h> #include <mach/mach_init.h>
#include <mach/vm_map.h> #include <mach/vm_map.h>
#include <malloc/malloc.h>
#endif #endif
#include "jemalloc/internal/ph.h" #include "jemalloc/internal/ph.h"

View File

@ -243,7 +243,6 @@
* Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings. * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings.
*/ */
#undef JEMALLOC_ZONE #undef JEMALLOC_ZONE
#undef JEMALLOC_ZONE_VERSION
/* /*
* Methods for determining whether the OS overcommits. * Methods for determining whether the OS overcommits.

View File

@ -3,6 +3,75 @@
# error "This source file is for zones on Darwin (OS X)." # error "This source file is for zones on Darwin (OS X)."
#endif #endif
/* Definitions of the following structs in malloc/malloc.h might be too old
* for the built binary to run on newer versions of OSX. So use the newest
* possible version of those structs.
*/
typedef struct _malloc_zone_t {
void *reserved1;
void *reserved2;
size_t (*size)(struct _malloc_zone_t *, const void *);
void *(*malloc)(struct _malloc_zone_t *, size_t);
void *(*calloc)(struct _malloc_zone_t *, size_t, size_t);
void *(*valloc)(struct _malloc_zone_t *, size_t);
void (*free)(struct _malloc_zone_t *, void *);
void *(*realloc)(struct _malloc_zone_t *, void *, size_t);
void (*destroy)(struct _malloc_zone_t *);
const char *zone_name;
unsigned (*batch_malloc)(struct _malloc_zone_t *, size_t, void **, unsigned);
void (*batch_free)(struct _malloc_zone_t *, void **, unsigned);
struct malloc_introspection_t *introspect;
unsigned version;
void *(*memalign)(struct _malloc_zone_t *, size_t, size_t);
void (*free_definite_size)(struct _malloc_zone_t *, void *, size_t);
size_t (*pressure_relief)(struct _malloc_zone_t *, size_t);
} malloc_zone_t;
typedef struct {
vm_address_t address;
vm_size_t size;
} vm_range_t;
typedef struct malloc_statistics_t {
unsigned blocks_in_use;
size_t size_in_use;
size_t max_size_in_use;
size_t size_allocated;
} malloc_statistics_t;
typedef kern_return_t memory_reader_t(task_t, vm_address_t, vm_size_t, void **);
typedef void vm_range_recorder_t(task_t, void *, unsigned type, vm_range_t *, unsigned);
typedef struct malloc_introspection_t {
kern_return_t (*enumerator)(task_t, void *, unsigned, vm_address_t, memory_reader_t, vm_range_recorder_t);
size_t (*good_size)(malloc_zone_t *, size_t);
boolean_t (*check)(malloc_zone_t *);
void (*print)(malloc_zone_t *, boolean_t);
void (*log)(malloc_zone_t *, void *);
void (*force_lock)(malloc_zone_t *);
void (*force_unlock)(malloc_zone_t *);
void (*statistics)(malloc_zone_t *, malloc_statistics_t *);
boolean_t (*zone_locked)(malloc_zone_t *);
boolean_t (*enable_discharge_checking)(malloc_zone_t *);
boolean_t (*disable_discharge_checking)(malloc_zone_t *);
void (*discharge)(malloc_zone_t *, void *);
#ifdef __BLOCKS__
void (*enumerate_discharged_pointers)(malloc_zone_t *, void (^)(void *, void *));
#else
void *enumerate_unavailable_without_blocks;
#endif
void (*reinit_lock)(malloc_zone_t *);
} malloc_introspection_t;
extern kern_return_t malloc_get_all_zones(task_t, memory_reader_t, vm_address_t **, unsigned *);
extern malloc_zone_t *malloc_default_zone(void);
extern void malloc_zone_register(malloc_zone_t *zone);
extern void malloc_zone_unregister(malloc_zone_t *zone);
/* /*
* The malloc_default_purgeable_zone() function is only available on >= 10.6. * 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. * We need to check whether it is present at runtime, thus the weak_import.
@ -20,21 +89,17 @@ static struct malloc_introspection_t jemalloc_zone_introspect;
/******************************************************************************/ /******************************************************************************/
/* Function prototypes for non-inline static functions. */ /* Function prototypes for non-inline static functions. */
static size_t zone_size(malloc_zone_t *zone, void *ptr); static size_t zone_size(malloc_zone_t *zone, const void *ptr);
static void *zone_malloc(malloc_zone_t *zone, size_t size); static void *zone_malloc(malloc_zone_t *zone, size_t size);
static void *zone_calloc(malloc_zone_t *zone, size_t num, size_t size); 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 >= 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);
#endif static void zone_destroy(malloc_zone_t *zone);
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);
@ -45,7 +110,7 @@ static void zone_force_unlock(malloc_zone_t *zone);
*/ */
static size_t static size_t
zone_size(malloc_zone_t *zone, void *ptr) zone_size(malloc_zone_t *zone, const void *ptr)
{ {
/* /*
* There appear to be places within Darwin (such as setenv(3)) that * There appear to be places within Darwin (such as setenv(3)) that
@ -101,7 +166,6 @@ zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
return (realloc(ptr, size)); return (realloc(ptr, size));
} }
#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,9 +175,7 @@ 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)
{ {
@ -128,14 +190,12 @@ zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
free(ptr); free(ptr);
} }
#endif
static void * static void
zone_destroy(malloc_zone_t *zone) zone_destroy(malloc_zone_t *zone)
{ {
/* This function should never be called. */ /* This function should never be called. */
not_reached(); not_reached();
return (NULL);
} }
static size_t static size_t
@ -170,40 +230,31 @@ zone_force_unlock(malloc_zone_t *zone)
static void static void
zone_init(void) zone_init(void)
{ {
jemalloc_zone.size = (void *)zone_size; jemalloc_zone.size = zone_size;
jemalloc_zone.malloc = (void *)zone_malloc; jemalloc_zone.malloc = zone_malloc;
jemalloc_zone.calloc = (void *)zone_calloc; jemalloc_zone.calloc = zone_calloc;
jemalloc_zone.valloc = (void *)zone_valloc; jemalloc_zone.valloc = zone_valloc;
jemalloc_zone.free = (void *)zone_free; jemalloc_zone.free = zone_free;
jemalloc_zone.realloc = (void *)zone_realloc; jemalloc_zone.realloc = zone_realloc;
jemalloc_zone.destroy = (void *)zone_destroy; jemalloc_zone.destroy = zone_destroy;
jemalloc_zone.zone_name = "jemalloc_zone"; jemalloc_zone.zone_name = "jemalloc_zone";
jemalloc_zone.batch_malloc = NULL; jemalloc_zone.batch_malloc = NULL;
jemalloc_zone.batch_free = NULL; jemalloc_zone.batch_free = NULL;
jemalloc_zone.introspect = &jemalloc_zone_introspect; jemalloc_zone.introspect = &jemalloc_zone_introspect;
jemalloc_zone.version = JEMALLOC_ZONE_VERSION; jemalloc_zone.version = 8;
#if (JEMALLOC_ZONE_VERSION >= 5)
jemalloc_zone.memalign = zone_memalign; jemalloc_zone.memalign = zone_memalign;
#endif
#if (JEMALLOC_ZONE_VERSION >= 6)
jemalloc_zone.free_definite_size = zone_free_definite_size; jemalloc_zone.free_definite_size = zone_free_definite_size;
#endif
#if (JEMALLOC_ZONE_VERSION >= 8)
jemalloc_zone.pressure_relief = NULL; jemalloc_zone.pressure_relief = NULL;
#endif
jemalloc_zone_introspect.enumerator = NULL; jemalloc_zone_introspect.enumerator = NULL;
jemalloc_zone_introspect.good_size = (void *)zone_good_size; jemalloc_zone_introspect.good_size = zone_good_size;
jemalloc_zone_introspect.check = NULL; jemalloc_zone_introspect.check = NULL;
jemalloc_zone_introspect.print = NULL; jemalloc_zone_introspect.print = NULL;
jemalloc_zone_introspect.log = NULL; jemalloc_zone_introspect.log = NULL;
jemalloc_zone_introspect.force_lock = (void *)zone_force_lock; jemalloc_zone_introspect.force_lock = zone_force_lock;
jemalloc_zone_introspect.force_unlock = (void *)zone_force_unlock; jemalloc_zone_introspect.force_unlock = zone_force_unlock;
jemalloc_zone_introspect.statistics = NULL; jemalloc_zone_introspect.statistics = NULL;
#if (JEMALLOC_ZONE_VERSION >= 6)
jemalloc_zone_introspect.zone_locked = NULL; jemalloc_zone_introspect.zone_locked = NULL;
#endif
#if (JEMALLOC_ZONE_VERSION >= 7)
jemalloc_zone_introspect.enable_discharge_checking = NULL; jemalloc_zone_introspect.enable_discharge_checking = NULL;
jemalloc_zone_introspect.disable_discharge_checking = NULL; jemalloc_zone_introspect.disable_discharge_checking = NULL;
jemalloc_zone_introspect.discharge = NULL; jemalloc_zone_introspect.discharge = NULL;
@ -212,7 +263,6 @@ zone_init(void)
#else #else
jemalloc_zone_introspect.enumerate_unavailable_without_blocks = NULL; jemalloc_zone_introspect.enumerate_unavailable_without_blocks = NULL;
#endif #endif
#endif
} }
static malloc_zone_t * static malloc_zone_t *