1 #include "jemalloc/internal/jemalloc_internal.h"
3 # error "This source file is for zones on Darwin (OS X)."
6 /******************************************************************************/
9 static malloc_zone_t zone
, szone
;
10 static struct malloc_introspection_t zone_introspect
, ozone_introspect
;
12 /******************************************************************************/
13 /* Function prototypes for non-inline static functions. */
15 static size_t zone_size(malloc_zone_t
*zone
, void *ptr
);
16 static void *zone_malloc(malloc_zone_t
*zone
, size_t size
);
17 static void *zone_calloc(malloc_zone_t
*zone
, size_t num
, size_t size
);
18 static void *zone_valloc(malloc_zone_t
*zone
, size_t size
);
19 static void zone_free(malloc_zone_t
*zone
, void *ptr
);
20 static void *zone_realloc(malloc_zone_t
*zone
, void *ptr
, size_t size
);
21 #if (JEMALLOC_ZONE_VERSION >= 6)
22 static void *zone_memalign(malloc_zone_t
*zone
, size_t alignment
,
24 static void zone_free_definite_size(malloc_zone_t
*zone
, void *ptr
,
27 static void *zone_destroy(malloc_zone_t
*zone
);
28 static size_t zone_good_size(malloc_zone_t
*zone
, size_t size
);
29 static void zone_force_lock(malloc_zone_t
*zone
);
30 static void zone_force_unlock(malloc_zone_t
*zone
);
31 static size_t ozone_size(malloc_zone_t
*zone
, void *ptr
);
32 static void ozone_free(malloc_zone_t
*zone
, void *ptr
);
33 static void *ozone_realloc(malloc_zone_t
*zone
, void *ptr
, size_t size
);
34 static unsigned ozone_batch_malloc(malloc_zone_t
*zone
, size_t size
,
35 void **results
, unsigned num_requested
);
36 static void ozone_batch_free(malloc_zone_t
*zone
, void **to_be_freed
,
38 #if (JEMALLOC_ZONE_VERSION >= 6)
39 static void ozone_free_definite_size(malloc_zone_t
*zone
, void *ptr
,
42 static void ozone_force_lock(malloc_zone_t
*zone
);
43 static void ozone_force_unlock(malloc_zone_t
*zone
);
45 /******************************************************************************/
51 zone_size(malloc_zone_t
*zone
, void *ptr
)
55 * There appear to be places within Darwin (such as setenv(3)) that
56 * cause calls to this function with pointers that *no* zone owns. If
57 * we knew that all pointers were owned by *some* zone, we could split
58 * our zone into two parts, and use one as the default allocator and
59 * the other as the default deallocator/reallocator. Since that will
60 * not work in practice, we must check all pointers to assure that they
61 * reside within a mapped chunk before determining size.
63 return (ivsalloc(ptr
));
67 zone_malloc(malloc_zone_t
*zone
, size_t size
)
70 return (JEMALLOC_P(malloc
)(size
));
74 zone_calloc(malloc_zone_t
*zone
, size_t num
, size_t size
)
77 return (JEMALLOC_P(calloc
)(num
, size
));
81 zone_valloc(malloc_zone_t
*zone
, size_t size
)
83 void *ret
= NULL
; /* Assignment avoids useless compiler warning. */
85 JEMALLOC_P(posix_memalign
)(&ret
, PAGE_SIZE
, size
);
91 zone_free(malloc_zone_t
*zone
, void *ptr
)
94 JEMALLOC_P(free
)(ptr
);
98 zone_realloc(malloc_zone_t
*zone
, void *ptr
, size_t size
)
101 return (JEMALLOC_P(realloc
)(ptr
, size
));
104 #if (JEMALLOC_ZONE_VERSION >= 6)
106 zone_memalign(malloc_zone_t
*zone
, size_t alignment
, size_t size
)
108 void *ret
= NULL
; /* Assignment avoids useless compiler warning. */
110 JEMALLOC_P(posix_memalign
)(&ret
, alignment
, size
);
116 zone_free_definite_size(malloc_zone_t
*zone
, void *ptr
, size_t size
)
119 assert(ivsalloc(ptr
) == size
);
120 JEMALLOC_P(free
)(ptr
);
125 zone_destroy(malloc_zone_t
*zone
)
128 /* This function should never be called. */
134 zone_good_size(malloc_zone_t
*zone
, size_t size
)
140 * Actually create an object of the appropriate size, then find out
141 * how large it could have been without moving up to the next size
144 p
= JEMALLOC_P(malloc
)(size
);
155 zone_force_lock(malloc_zone_t
*zone
)
163 zone_force_unlock(malloc_zone_t
*zone
)
174 zone
.size
= (void *)zone_size
;
175 zone
.malloc
= (void *)zone_malloc
;
176 zone
.calloc
= (void *)zone_calloc
;
177 zone
.valloc
= (void *)zone_valloc
;
178 zone
.free
= (void *)zone_free
;
179 zone
.realloc
= (void *)zone_realloc
;
180 zone
.destroy
= (void *)zone_destroy
;
181 zone
.zone_name
= "jemalloc_zone";
182 zone
.batch_malloc
= NULL
;
183 zone
.batch_free
= NULL
;
184 zone
.introspect
= &zone_introspect
;
185 zone
.version
= JEMALLOC_ZONE_VERSION
;
186 #if (JEMALLOC_ZONE_VERSION >= 6)
187 zone
.memalign
= zone_memalign
;
188 zone
.free_definite_size
= zone_free_definite_size
;
191 zone_introspect
.enumerator
= NULL
;
192 zone_introspect
.good_size
= (void *)zone_good_size
;
193 zone_introspect
.check
= NULL
;
194 zone_introspect
.print
= NULL
;
195 zone_introspect
.log
= NULL
;
196 zone_introspect
.force_lock
= (void *)zone_force_lock
;
197 zone_introspect
.force_unlock
= (void *)zone_force_unlock
;
198 zone_introspect
.statistics
= NULL
;
199 #if (JEMALLOC_ZONE_VERSION >= 6)
200 zone_introspect
.zone_locked
= NULL
;
207 ozone_size(malloc_zone_t
*zone
, void *ptr
)
213 ret
= szone
.size(zone
, ptr
);
219 ozone_free(malloc_zone_t
*zone
, void *ptr
)
222 if (ivsalloc(ptr
) != 0)
223 JEMALLOC_P(free
)(ptr
);
225 size_t size
= szone
.size(zone
, ptr
);
227 (szone
.free
)(zone
, ptr
);
232 ozone_realloc(malloc_zone_t
*zone
, void *ptr
, size_t size
)
237 return (JEMALLOC_P(malloc
)(size
));
239 oldsize
= ivsalloc(ptr
);
241 return (JEMALLOC_P(realloc
)(ptr
, size
));
243 oldsize
= szone
.size(zone
, ptr
);
245 return (JEMALLOC_P(malloc
)(size
));
247 void *ret
= JEMALLOC_P(malloc
)(size
);
249 memcpy(ret
, ptr
, (oldsize
< size
) ? oldsize
:
251 (szone
.free
)(zone
, ptr
);
259 ozone_batch_malloc(malloc_zone_t
*zone
, size_t size
, void **results
,
260 unsigned num_requested
)
263 /* Don't bother implementing this interface, since it isn't required. */
268 ozone_batch_free(malloc_zone_t
*zone
, void **to_be_freed
, unsigned num
)
272 for (i
= 0; i
< num
; i
++)
273 ozone_free(zone
, to_be_freed
[i
]);
276 #if (JEMALLOC_ZONE_VERSION >= 6)
278 ozone_free_definite_size(malloc_zone_t
*zone
, void *ptr
, size_t size
)
281 if (ivsalloc(ptr
) != 0) {
282 assert(ivsalloc(ptr
) == size
);
283 JEMALLOC_P(free
)(ptr
);
285 assert(size
== szone
.size(zone
, ptr
));
286 szone
.free_definite_size(zone
, ptr
, size
);
292 ozone_force_lock(malloc_zone_t
*zone
)
295 /* jemalloc locking is taken care of by the normal jemalloc zone. */
296 szone
.introspect
->force_lock(zone
);
300 ozone_force_unlock(malloc_zone_t
*zone
)
303 /* jemalloc locking is taken care of by the normal jemalloc zone. */
304 szone
.introspect
->force_unlock(zone
);
308 * Overlay the default scalable zone (szone) such that existing allocations are
309 * drained, and further allocations come from jemalloc. This is necessary
310 * because Core Foundation directly accesses and uses the szone before the
311 * jemalloc library is even loaded.
314 szone2ozone(malloc_zone_t
*zone
)
318 * Stash a copy of the original szone so that we can call its
319 * functions as needed. Note that the internally, the szone stores its
320 * bookkeeping data structures immediately following the malloc_zone_t
321 * header, so when calling szone functions, we need to pass a pointer
322 * to the original zone structure.
324 memcpy(&szone
, zone
, sizeof(malloc_zone_t
));
326 zone
->size
= (void *)ozone_size
;
327 zone
->malloc
= (void *)zone_malloc
;
328 zone
->calloc
= (void *)zone_calloc
;
329 zone
->valloc
= (void *)zone_valloc
;
330 zone
->free
= (void *)ozone_free
;
331 zone
->realloc
= (void *)ozone_realloc
;
332 zone
->destroy
= (void *)zone_destroy
;
333 zone
->zone_name
= "jemalloc_ozone";
334 zone
->batch_malloc
= ozone_batch_malloc
;
335 zone
->batch_free
= ozone_batch_free
;
336 zone
->introspect
= &ozone_introspect
;
337 zone
->version
= JEMALLOC_ZONE_VERSION
;
338 #if (JEMALLOC_ZONE_VERSION >= 6)
339 zone
->memalign
= zone_memalign
;
340 zone
->free_definite_size
= ozone_free_definite_size
;
343 ozone_introspect
.enumerator
= NULL
;
344 ozone_introspect
.good_size
= (void *)zone_good_size
;
345 ozone_introspect
.check
= NULL
;
346 ozone_introspect
.print
= NULL
;
347 ozone_introspect
.log
= NULL
;
348 ozone_introspect
.force_lock
= (void *)ozone_force_lock
;
349 ozone_introspect
.force_unlock
= (void *)ozone_force_unlock
;
350 ozone_introspect
.statistics
= NULL
;
351 #if (JEMALLOC_ZONE_VERSION >= 6)
352 ozone_introspect
.zone_locked
= NULL
;