1*8e33eff8Schristos #include "jemalloc/internal/jemalloc_preamble.h" 2*8e33eff8Schristos #include "jemalloc/internal/jemalloc_internal_includes.h" 3*8e33eff8Schristos 4*8e33eff8Schristos #include "jemalloc/internal/assert.h" 5*8e33eff8Schristos 6*8e33eff8Schristos #ifndef JEMALLOC_ZONE 7*8e33eff8Schristos # error "This source file is for zones on Darwin (OS X)." 8*8e33eff8Schristos #endif 9*8e33eff8Schristos 10*8e33eff8Schristos /* Definitions of the following structs in malloc/malloc.h might be too old 11*8e33eff8Schristos * for the built binary to run on newer versions of OSX. So use the newest 12*8e33eff8Schristos * possible version of those structs. 13*8e33eff8Schristos */ 14*8e33eff8Schristos typedef struct _malloc_zone_t { 15*8e33eff8Schristos void *reserved1; 16*8e33eff8Schristos void *reserved2; 17*8e33eff8Schristos size_t (*size)(struct _malloc_zone_t *, const void *); 18*8e33eff8Schristos void *(*malloc)(struct _malloc_zone_t *, size_t); 19*8e33eff8Schristos void *(*calloc)(struct _malloc_zone_t *, size_t, size_t); 20*8e33eff8Schristos void *(*valloc)(struct _malloc_zone_t *, size_t); 21*8e33eff8Schristos void (*free)(struct _malloc_zone_t *, void *); 22*8e33eff8Schristos void *(*realloc)(struct _malloc_zone_t *, void *, size_t); 23*8e33eff8Schristos void (*destroy)(struct _malloc_zone_t *); 24*8e33eff8Schristos const char *zone_name; 25*8e33eff8Schristos unsigned (*batch_malloc)(struct _malloc_zone_t *, size_t, void **, unsigned); 26*8e33eff8Schristos void (*batch_free)(struct _malloc_zone_t *, void **, unsigned); 27*8e33eff8Schristos struct malloc_introspection_t *introspect; 28*8e33eff8Schristos unsigned version; 29*8e33eff8Schristos void *(*memalign)(struct _malloc_zone_t *, size_t, size_t); 30*8e33eff8Schristos void (*free_definite_size)(struct _malloc_zone_t *, void *, size_t); 31*8e33eff8Schristos size_t (*pressure_relief)(struct _malloc_zone_t *, size_t); 32*8e33eff8Schristos } malloc_zone_t; 33*8e33eff8Schristos 34*8e33eff8Schristos typedef struct { 35*8e33eff8Schristos vm_address_t address; 36*8e33eff8Schristos vm_size_t size; 37*8e33eff8Schristos } vm_range_t; 38*8e33eff8Schristos 39*8e33eff8Schristos typedef struct malloc_statistics_t { 40*8e33eff8Schristos unsigned blocks_in_use; 41*8e33eff8Schristos size_t size_in_use; 42*8e33eff8Schristos size_t max_size_in_use; 43*8e33eff8Schristos size_t size_allocated; 44*8e33eff8Schristos } malloc_statistics_t; 45*8e33eff8Schristos 46*8e33eff8Schristos typedef kern_return_t memory_reader_t(task_t, vm_address_t, vm_size_t, void **); 47*8e33eff8Schristos 48*8e33eff8Schristos typedef void vm_range_recorder_t(task_t, void *, unsigned type, vm_range_t *, unsigned); 49*8e33eff8Schristos 50*8e33eff8Schristos typedef struct malloc_introspection_t { 51*8e33eff8Schristos kern_return_t (*enumerator)(task_t, void *, unsigned, vm_address_t, memory_reader_t, vm_range_recorder_t); 52*8e33eff8Schristos size_t (*good_size)(malloc_zone_t *, size_t); 53*8e33eff8Schristos boolean_t (*check)(malloc_zone_t *); 54*8e33eff8Schristos void (*print)(malloc_zone_t *, boolean_t); 55*8e33eff8Schristos void (*log)(malloc_zone_t *, void *); 56*8e33eff8Schristos void (*force_lock)(malloc_zone_t *); 57*8e33eff8Schristos void (*force_unlock)(malloc_zone_t *); 58*8e33eff8Schristos void (*statistics)(malloc_zone_t *, malloc_statistics_t *); 59*8e33eff8Schristos boolean_t (*zone_locked)(malloc_zone_t *); 60*8e33eff8Schristos boolean_t (*enable_discharge_checking)(malloc_zone_t *); 61*8e33eff8Schristos boolean_t (*disable_discharge_checking)(malloc_zone_t *); 62*8e33eff8Schristos void (*discharge)(malloc_zone_t *, void *); 63*8e33eff8Schristos #ifdef __BLOCKS__ 64*8e33eff8Schristos void (*enumerate_discharged_pointers)(malloc_zone_t *, void (^)(void *, void *)); 65*8e33eff8Schristos #else 66*8e33eff8Schristos void *enumerate_unavailable_without_blocks; 67*8e33eff8Schristos #endif 68*8e33eff8Schristos void (*reinit_lock)(malloc_zone_t *); 69*8e33eff8Schristos } malloc_introspection_t; 70*8e33eff8Schristos 71*8e33eff8Schristos extern kern_return_t malloc_get_all_zones(task_t, memory_reader_t, vm_address_t **, unsigned *); 72*8e33eff8Schristos 73*8e33eff8Schristos extern malloc_zone_t *malloc_default_zone(void); 74*8e33eff8Schristos 75*8e33eff8Schristos extern void malloc_zone_register(malloc_zone_t *zone); 76*8e33eff8Schristos 77*8e33eff8Schristos extern void malloc_zone_unregister(malloc_zone_t *zone); 78*8e33eff8Schristos 79*8e33eff8Schristos /* 80*8e33eff8Schristos * The malloc_default_purgeable_zone() function is only available on >= 10.6. 81*8e33eff8Schristos * We need to check whether it is present at runtime, thus the weak_import. 82*8e33eff8Schristos */ 83*8e33eff8Schristos extern malloc_zone_t *malloc_default_purgeable_zone(void) 84*8e33eff8Schristos JEMALLOC_ATTR(weak_import); 85*8e33eff8Schristos 86*8e33eff8Schristos /******************************************************************************/ 87*8e33eff8Schristos /* Data. */ 88*8e33eff8Schristos 89*8e33eff8Schristos static malloc_zone_t *default_zone, *purgeable_zone; 90*8e33eff8Schristos static malloc_zone_t jemalloc_zone; 91*8e33eff8Schristos static struct malloc_introspection_t jemalloc_zone_introspect; 92*8e33eff8Schristos static pid_t zone_force_lock_pid = -1; 93*8e33eff8Schristos 94*8e33eff8Schristos /******************************************************************************/ 95*8e33eff8Schristos /* Function prototypes for non-inline static functions. */ 96*8e33eff8Schristos 97*8e33eff8Schristos static size_t zone_size(malloc_zone_t *zone, const void *ptr); 98*8e33eff8Schristos static void *zone_malloc(malloc_zone_t *zone, size_t size); 99*8e33eff8Schristos static void *zone_calloc(malloc_zone_t *zone, size_t num, size_t size); 100*8e33eff8Schristos static void *zone_valloc(malloc_zone_t *zone, size_t size); 101*8e33eff8Schristos static void zone_free(malloc_zone_t *zone, void *ptr); 102*8e33eff8Schristos static void *zone_realloc(malloc_zone_t *zone, void *ptr, size_t size); 103*8e33eff8Schristos static void *zone_memalign(malloc_zone_t *zone, size_t alignment, 104*8e33eff8Schristos size_t size); 105*8e33eff8Schristos static void zone_free_definite_size(malloc_zone_t *zone, void *ptr, 106*8e33eff8Schristos size_t size); 107*8e33eff8Schristos static void zone_destroy(malloc_zone_t *zone); 108*8e33eff8Schristos static unsigned zone_batch_malloc(struct _malloc_zone_t *zone, size_t size, 109*8e33eff8Schristos void **results, unsigned num_requested); 110*8e33eff8Schristos static void zone_batch_free(struct _malloc_zone_t *zone, 111*8e33eff8Schristos void **to_be_freed, unsigned num_to_be_freed); 112*8e33eff8Schristos static size_t zone_pressure_relief(struct _malloc_zone_t *zone, size_t goal); 113*8e33eff8Schristos static size_t zone_good_size(malloc_zone_t *zone, size_t size); 114*8e33eff8Schristos static kern_return_t zone_enumerator(task_t task, void *data, unsigned type_mask, 115*8e33eff8Schristos vm_address_t zone_address, memory_reader_t reader, 116*8e33eff8Schristos vm_range_recorder_t recorder); 117*8e33eff8Schristos static boolean_t zone_check(malloc_zone_t *zone); 118*8e33eff8Schristos static void zone_print(malloc_zone_t *zone, boolean_t verbose); 119*8e33eff8Schristos static void zone_log(malloc_zone_t *zone, void *address); 120*8e33eff8Schristos static void zone_force_lock(malloc_zone_t *zone); 121*8e33eff8Schristos static void zone_force_unlock(malloc_zone_t *zone); 122*8e33eff8Schristos static void zone_statistics(malloc_zone_t *zone, 123*8e33eff8Schristos malloc_statistics_t *stats); 124*8e33eff8Schristos static boolean_t zone_locked(malloc_zone_t *zone); 125*8e33eff8Schristos static void zone_reinit_lock(malloc_zone_t *zone); 126*8e33eff8Schristos 127*8e33eff8Schristos /******************************************************************************/ 128*8e33eff8Schristos /* 129*8e33eff8Schristos * Functions. 130*8e33eff8Schristos */ 131*8e33eff8Schristos 132*8e33eff8Schristos static size_t 133*8e33eff8Schristos zone_size(malloc_zone_t *zone, const void *ptr) { 134*8e33eff8Schristos /* 135*8e33eff8Schristos * There appear to be places within Darwin (such as setenv(3)) that 136*8e33eff8Schristos * cause calls to this function with pointers that *no* zone owns. If 137*8e33eff8Schristos * we knew that all pointers were owned by *some* zone, we could split 138*8e33eff8Schristos * our zone into two parts, and use one as the default allocator and 139*8e33eff8Schristos * the other as the default deallocator/reallocator. Since that will 140*8e33eff8Schristos * not work in practice, we must check all pointers to assure that they 141*8e33eff8Schristos * reside within a mapped extent before determining size. 142*8e33eff8Schristos */ 143*8e33eff8Schristos return ivsalloc(tsdn_fetch(), ptr); 144*8e33eff8Schristos } 145*8e33eff8Schristos 146*8e33eff8Schristos static void * 147*8e33eff8Schristos zone_malloc(malloc_zone_t *zone, size_t size) { 148*8e33eff8Schristos return je_malloc(size); 149*8e33eff8Schristos } 150*8e33eff8Schristos 151*8e33eff8Schristos static void * 152*8e33eff8Schristos zone_calloc(malloc_zone_t *zone, size_t num, size_t size) { 153*8e33eff8Schristos return je_calloc(num, size); 154*8e33eff8Schristos } 155*8e33eff8Schristos 156*8e33eff8Schristos static void * 157*8e33eff8Schristos zone_valloc(malloc_zone_t *zone, size_t size) { 158*8e33eff8Schristos void *ret = NULL; /* Assignment avoids useless compiler warning. */ 159*8e33eff8Schristos 160*8e33eff8Schristos je_posix_memalign(&ret, PAGE, size); 161*8e33eff8Schristos 162*8e33eff8Schristos return ret; 163*8e33eff8Schristos } 164*8e33eff8Schristos 165*8e33eff8Schristos static void 166*8e33eff8Schristos zone_free(malloc_zone_t *zone, void *ptr) { 167*8e33eff8Schristos if (ivsalloc(tsdn_fetch(), ptr) != 0) { 168*8e33eff8Schristos je_free(ptr); 169*8e33eff8Schristos return; 170*8e33eff8Schristos } 171*8e33eff8Schristos 172*8e33eff8Schristos free(ptr); 173*8e33eff8Schristos } 174*8e33eff8Schristos 175*8e33eff8Schristos static void * 176*8e33eff8Schristos zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) { 177*8e33eff8Schristos if (ivsalloc(tsdn_fetch(), ptr) != 0) { 178*8e33eff8Schristos return je_realloc(ptr, size); 179*8e33eff8Schristos } 180*8e33eff8Schristos 181*8e33eff8Schristos return realloc(ptr, size); 182*8e33eff8Schristos } 183*8e33eff8Schristos 184*8e33eff8Schristos static void * 185*8e33eff8Schristos zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size) { 186*8e33eff8Schristos void *ret = NULL; /* Assignment avoids useless compiler warning. */ 187*8e33eff8Schristos 188*8e33eff8Schristos je_posix_memalign(&ret, alignment, size); 189*8e33eff8Schristos 190*8e33eff8Schristos return ret; 191*8e33eff8Schristos } 192*8e33eff8Schristos 193*8e33eff8Schristos static void 194*8e33eff8Schristos zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size) { 195*8e33eff8Schristos size_t alloc_size; 196*8e33eff8Schristos 197*8e33eff8Schristos alloc_size = ivsalloc(tsdn_fetch(), ptr); 198*8e33eff8Schristos if (alloc_size != 0) { 199*8e33eff8Schristos assert(alloc_size == size); 200*8e33eff8Schristos je_free(ptr); 201*8e33eff8Schristos return; 202*8e33eff8Schristos } 203*8e33eff8Schristos 204*8e33eff8Schristos free(ptr); 205*8e33eff8Schristos } 206*8e33eff8Schristos 207*8e33eff8Schristos static void 208*8e33eff8Schristos zone_destroy(malloc_zone_t *zone) { 209*8e33eff8Schristos /* This function should never be called. */ 210*8e33eff8Schristos not_reached(); 211*8e33eff8Schristos } 212*8e33eff8Schristos 213*8e33eff8Schristos static unsigned 214*8e33eff8Schristos zone_batch_malloc(struct _malloc_zone_t *zone, size_t size, void **results, 215*8e33eff8Schristos unsigned num_requested) { 216*8e33eff8Schristos unsigned i; 217*8e33eff8Schristos 218*8e33eff8Schristos for (i = 0; i < num_requested; i++) { 219*8e33eff8Schristos results[i] = je_malloc(size); 220*8e33eff8Schristos if (!results[i]) 221*8e33eff8Schristos break; 222*8e33eff8Schristos } 223*8e33eff8Schristos 224*8e33eff8Schristos return i; 225*8e33eff8Schristos } 226*8e33eff8Schristos 227*8e33eff8Schristos static void 228*8e33eff8Schristos zone_batch_free(struct _malloc_zone_t *zone, void **to_be_freed, 229*8e33eff8Schristos unsigned num_to_be_freed) { 230*8e33eff8Schristos unsigned i; 231*8e33eff8Schristos 232*8e33eff8Schristos for (i = 0; i < num_to_be_freed; i++) { 233*8e33eff8Schristos zone_free(zone, to_be_freed[i]); 234*8e33eff8Schristos to_be_freed[i] = NULL; 235*8e33eff8Schristos } 236*8e33eff8Schristos } 237*8e33eff8Schristos 238*8e33eff8Schristos static size_t 239*8e33eff8Schristos zone_pressure_relief(struct _malloc_zone_t *zone, size_t goal) { 240*8e33eff8Schristos return 0; 241*8e33eff8Schristos } 242*8e33eff8Schristos 243*8e33eff8Schristos static size_t 244*8e33eff8Schristos zone_good_size(malloc_zone_t *zone, size_t size) { 245*8e33eff8Schristos if (size == 0) { 246*8e33eff8Schristos size = 1; 247*8e33eff8Schristos } 248*8e33eff8Schristos return sz_s2u(size); 249*8e33eff8Schristos } 250*8e33eff8Schristos 251*8e33eff8Schristos static kern_return_t 252*8e33eff8Schristos zone_enumerator(task_t task, void *data, unsigned type_mask, 253*8e33eff8Schristos vm_address_t zone_address, memory_reader_t reader, 254*8e33eff8Schristos vm_range_recorder_t recorder) { 255*8e33eff8Schristos return KERN_SUCCESS; 256*8e33eff8Schristos } 257*8e33eff8Schristos 258*8e33eff8Schristos static boolean_t 259*8e33eff8Schristos zone_check(malloc_zone_t *zone) { 260*8e33eff8Schristos return true; 261*8e33eff8Schristos } 262*8e33eff8Schristos 263*8e33eff8Schristos static void 264*8e33eff8Schristos zone_print(malloc_zone_t *zone, boolean_t verbose) { 265*8e33eff8Schristos } 266*8e33eff8Schristos 267*8e33eff8Schristos static void 268*8e33eff8Schristos zone_log(malloc_zone_t *zone, void *address) { 269*8e33eff8Schristos } 270*8e33eff8Schristos 271*8e33eff8Schristos static void 272*8e33eff8Schristos zone_force_lock(malloc_zone_t *zone) { 273*8e33eff8Schristos if (isthreaded) { 274*8e33eff8Schristos /* 275*8e33eff8Schristos * See the note in zone_force_unlock, below, to see why we need 276*8e33eff8Schristos * this. 277*8e33eff8Schristos */ 278*8e33eff8Schristos assert(zone_force_lock_pid == -1); 279*8e33eff8Schristos zone_force_lock_pid = getpid(); 280*8e33eff8Schristos jemalloc_prefork(); 281*8e33eff8Schristos } 282*8e33eff8Schristos } 283*8e33eff8Schristos 284*8e33eff8Schristos static void 285*8e33eff8Schristos zone_force_unlock(malloc_zone_t *zone) { 286*8e33eff8Schristos /* 287*8e33eff8Schristos * zone_force_lock and zone_force_unlock are the entry points to the 288*8e33eff8Schristos * forking machinery on OS X. The tricky thing is, the child is not 289*8e33eff8Schristos * allowed to unlock mutexes locked in the parent, even if owned by the 290*8e33eff8Schristos * forking thread (and the mutex type we use in OS X will fail an assert 291*8e33eff8Schristos * if we try). In the child, we can get away with reinitializing all 292*8e33eff8Schristos * the mutexes, which has the effect of unlocking them. In the parent, 293*8e33eff8Schristos * doing this would mean we wouldn't wake any waiters blocked on the 294*8e33eff8Schristos * mutexes we unlock. So, we record the pid of the current thread in 295*8e33eff8Schristos * zone_force_lock, and use that to detect if we're in the parent or 296*8e33eff8Schristos * child here, to decide which unlock logic we need. 297*8e33eff8Schristos */ 298*8e33eff8Schristos if (isthreaded) { 299*8e33eff8Schristos assert(zone_force_lock_pid != -1); 300*8e33eff8Schristos if (getpid() == zone_force_lock_pid) { 301*8e33eff8Schristos jemalloc_postfork_parent(); 302*8e33eff8Schristos } else { 303*8e33eff8Schristos jemalloc_postfork_child(); 304*8e33eff8Schristos } 305*8e33eff8Schristos zone_force_lock_pid = -1; 306*8e33eff8Schristos } 307*8e33eff8Schristos } 308*8e33eff8Schristos 309*8e33eff8Schristos static void 310*8e33eff8Schristos zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { 311*8e33eff8Schristos /* We make no effort to actually fill the values */ 312*8e33eff8Schristos stats->blocks_in_use = 0; 313*8e33eff8Schristos stats->size_in_use = 0; 314*8e33eff8Schristos stats->max_size_in_use = 0; 315*8e33eff8Schristos stats->size_allocated = 0; 316*8e33eff8Schristos } 317*8e33eff8Schristos 318*8e33eff8Schristos static boolean_t 319*8e33eff8Schristos zone_locked(malloc_zone_t *zone) { 320*8e33eff8Schristos /* Pretend no lock is being held */ 321*8e33eff8Schristos return false; 322*8e33eff8Schristos } 323*8e33eff8Schristos 324*8e33eff8Schristos static void 325*8e33eff8Schristos zone_reinit_lock(malloc_zone_t *zone) { 326*8e33eff8Schristos /* As of OSX 10.12, this function is only used when force_unlock would 327*8e33eff8Schristos * be used if the zone version were < 9. So just use force_unlock. */ 328*8e33eff8Schristos zone_force_unlock(zone); 329*8e33eff8Schristos } 330*8e33eff8Schristos 331*8e33eff8Schristos static void 332*8e33eff8Schristos zone_init(void) { 333*8e33eff8Schristos jemalloc_zone.size = zone_size; 334*8e33eff8Schristos jemalloc_zone.malloc = zone_malloc; 335*8e33eff8Schristos jemalloc_zone.calloc = zone_calloc; 336*8e33eff8Schristos jemalloc_zone.valloc = zone_valloc; 337*8e33eff8Schristos jemalloc_zone.free = zone_free; 338*8e33eff8Schristos jemalloc_zone.realloc = zone_realloc; 339*8e33eff8Schristos jemalloc_zone.destroy = zone_destroy; 340*8e33eff8Schristos jemalloc_zone.zone_name = "jemalloc_zone"; 341*8e33eff8Schristos jemalloc_zone.batch_malloc = zone_batch_malloc; 342*8e33eff8Schristos jemalloc_zone.batch_free = zone_batch_free; 343*8e33eff8Schristos jemalloc_zone.introspect = &jemalloc_zone_introspect; 344*8e33eff8Schristos jemalloc_zone.version = 9; 345*8e33eff8Schristos jemalloc_zone.memalign = zone_memalign; 346*8e33eff8Schristos jemalloc_zone.free_definite_size = zone_free_definite_size; 347*8e33eff8Schristos jemalloc_zone.pressure_relief = zone_pressure_relief; 348*8e33eff8Schristos 349*8e33eff8Schristos jemalloc_zone_introspect.enumerator = zone_enumerator; 350*8e33eff8Schristos jemalloc_zone_introspect.good_size = zone_good_size; 351*8e33eff8Schristos jemalloc_zone_introspect.check = zone_check; 352*8e33eff8Schristos jemalloc_zone_introspect.print = zone_print; 353*8e33eff8Schristos jemalloc_zone_introspect.log = zone_log; 354*8e33eff8Schristos jemalloc_zone_introspect.force_lock = zone_force_lock; 355*8e33eff8Schristos jemalloc_zone_introspect.force_unlock = zone_force_unlock; 356*8e33eff8Schristos jemalloc_zone_introspect.statistics = zone_statistics; 357*8e33eff8Schristos jemalloc_zone_introspect.zone_locked = zone_locked; 358*8e33eff8Schristos jemalloc_zone_introspect.enable_discharge_checking = NULL; 359*8e33eff8Schristos jemalloc_zone_introspect.disable_discharge_checking = NULL; 360*8e33eff8Schristos jemalloc_zone_introspect.discharge = NULL; 361*8e33eff8Schristos #ifdef __BLOCKS__ 362*8e33eff8Schristos jemalloc_zone_introspect.enumerate_discharged_pointers = NULL; 363*8e33eff8Schristos #else 364*8e33eff8Schristos jemalloc_zone_introspect.enumerate_unavailable_without_blocks = NULL; 365*8e33eff8Schristos #endif 366*8e33eff8Schristos jemalloc_zone_introspect.reinit_lock = zone_reinit_lock; 367*8e33eff8Schristos } 368*8e33eff8Schristos 369*8e33eff8Schristos static malloc_zone_t * 370*8e33eff8Schristos zone_default_get(void) { 371*8e33eff8Schristos malloc_zone_t **zones = NULL; 372*8e33eff8Schristos unsigned int num_zones = 0; 373*8e33eff8Schristos 374*8e33eff8Schristos /* 375*8e33eff8Schristos * On OSX 10.12, malloc_default_zone returns a special zone that is not 376*8e33eff8Schristos * present in the list of registered zones. That zone uses a "lite zone" 377*8e33eff8Schristos * if one is present (apparently enabled when malloc stack logging is 378*8e33eff8Schristos * enabled), or the first registered zone otherwise. In practice this 379*8e33eff8Schristos * means unless malloc stack logging is enabled, the first registered 380*8e33eff8Schristos * zone is the default. So get the list of zones to get the first one, 381*8e33eff8Schristos * instead of relying on malloc_default_zone. 382*8e33eff8Schristos */ 383*8e33eff8Schristos if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, 384*8e33eff8Schristos (vm_address_t**)&zones, &num_zones)) { 385*8e33eff8Schristos /* 386*8e33eff8Schristos * Reset the value in case the failure happened after it was 387*8e33eff8Schristos * set. 388*8e33eff8Schristos */ 389*8e33eff8Schristos num_zones = 0; 390*8e33eff8Schristos } 391*8e33eff8Schristos 392*8e33eff8Schristos if (num_zones) { 393*8e33eff8Schristos return zones[0]; 394*8e33eff8Schristos } 395*8e33eff8Schristos 396*8e33eff8Schristos return malloc_default_zone(); 397*8e33eff8Schristos } 398*8e33eff8Schristos 399*8e33eff8Schristos /* As written, this function can only promote jemalloc_zone. */ 400*8e33eff8Schristos static void 401*8e33eff8Schristos zone_promote(void) { 402*8e33eff8Schristos malloc_zone_t *zone; 403*8e33eff8Schristos 404*8e33eff8Schristos do { 405*8e33eff8Schristos /* 406*8e33eff8Schristos * Unregister and reregister the default zone. On OSX >= 10.6, 407*8e33eff8Schristos * unregistering takes the last registered zone and places it 408*8e33eff8Schristos * at the location of the specified zone. Unregistering the 409*8e33eff8Schristos * default zone thus makes the last registered one the default. 410*8e33eff8Schristos * On OSX < 10.6, unregistering shifts all registered zones. 411*8e33eff8Schristos * The first registered zone then becomes the default. 412*8e33eff8Schristos */ 413*8e33eff8Schristos malloc_zone_unregister(default_zone); 414*8e33eff8Schristos malloc_zone_register(default_zone); 415*8e33eff8Schristos 416*8e33eff8Schristos /* 417*8e33eff8Schristos * On OSX 10.6, having the default purgeable zone appear before 418*8e33eff8Schristos * the default zone makes some things crash because it thinks it 419*8e33eff8Schristos * owns the default zone allocated pointers. We thus 420*8e33eff8Schristos * unregister/re-register it in order to ensure it's always 421*8e33eff8Schristos * after the default zone. On OSX < 10.6, there is no purgeable 422*8e33eff8Schristos * zone, so this does nothing. On OSX >= 10.6, unregistering 423*8e33eff8Schristos * replaces the purgeable zone with the last registered zone 424*8e33eff8Schristos * above, i.e. the default zone. Registering it again then puts 425*8e33eff8Schristos * it at the end, obviously after the default zone. 426*8e33eff8Schristos */ 427*8e33eff8Schristos if (purgeable_zone != NULL) { 428*8e33eff8Schristos malloc_zone_unregister(purgeable_zone); 429*8e33eff8Schristos malloc_zone_register(purgeable_zone); 430*8e33eff8Schristos } 431*8e33eff8Schristos 432*8e33eff8Schristos zone = zone_default_get(); 433*8e33eff8Schristos } while (zone != &jemalloc_zone); 434*8e33eff8Schristos } 435*8e33eff8Schristos 436*8e33eff8Schristos JEMALLOC_ATTR(constructor) 437*8e33eff8Schristos void 438*8e33eff8Schristos zone_register(void) { 439*8e33eff8Schristos /* 440*8e33eff8Schristos * If something else replaced the system default zone allocator, don't 441*8e33eff8Schristos * register jemalloc's. 442*8e33eff8Schristos */ 443*8e33eff8Schristos default_zone = zone_default_get(); 444*8e33eff8Schristos if (!default_zone->zone_name || strcmp(default_zone->zone_name, 445*8e33eff8Schristos "DefaultMallocZone") != 0) { 446*8e33eff8Schristos return; 447*8e33eff8Schristos } 448*8e33eff8Schristos 449*8e33eff8Schristos /* 450*8e33eff8Schristos * The default purgeable zone is created lazily by OSX's libc. It uses 451*8e33eff8Schristos * the default zone when it is created for "small" allocations 452*8e33eff8Schristos * (< 15 KiB), but assumes the default zone is a scalable_zone. This 453*8e33eff8Schristos * obviously fails when the default zone is the jemalloc zone, so 454*8e33eff8Schristos * malloc_default_purgeable_zone() is called beforehand so that the 455*8e33eff8Schristos * default purgeable zone is created when the default zone is still 456*8e33eff8Schristos * a scalable_zone. As purgeable zones only exist on >= 10.6, we need 457*8e33eff8Schristos * to check for the existence of malloc_default_purgeable_zone() at 458*8e33eff8Schristos * run time. 459*8e33eff8Schristos */ 460*8e33eff8Schristos purgeable_zone = (malloc_default_purgeable_zone == NULL) ? NULL : 461*8e33eff8Schristos malloc_default_purgeable_zone(); 462*8e33eff8Schristos 463*8e33eff8Schristos /* Register the custom zone. At this point it won't be the default. */ 464*8e33eff8Schristos zone_init(); 465*8e33eff8Schristos malloc_zone_register(&jemalloc_zone); 466*8e33eff8Schristos 467*8e33eff8Schristos /* Promote the custom zone to be default. */ 468*8e33eff8Schristos zone_promote(); 469*8e33eff8Schristos } 470