1*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_C_
2*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_preamble.h"
3*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_internal_includes.h"
4*1208bc7eSAndroid Build Coastguard Worker
5*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/assert.h"
6*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/atomic.h"
7*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/ctl.h"
8*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/extent_dss.h"
9*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/extent_mmap.h"
10*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_internal_types.h"
11*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/log.h"
12*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/malloc_io.h"
13*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/mutex.h"
14*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/rtree.h"
15*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/size_classes.h"
16*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/spin.h"
17*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/sz.h"
18*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/ticker.h"
19*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/util.h"
20*1208bc7eSAndroid Build Coastguard Worker
21*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
22*1208bc7eSAndroid Build Coastguard Worker /* Data. */
23*1208bc7eSAndroid Build Coastguard Worker
24*1208bc7eSAndroid Build Coastguard Worker /* Runtime configuration options. */
25*1208bc7eSAndroid Build Coastguard Worker const char *je_malloc_conf
26*1208bc7eSAndroid Build Coastguard Worker #ifndef _WIN32
27*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(weak)
28*1208bc7eSAndroid Build Coastguard Worker #endif
29*1208bc7eSAndroid Build Coastguard Worker ;
30*1208bc7eSAndroid Build Coastguard Worker bool opt_abort =
31*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_DEBUG
32*1208bc7eSAndroid Build Coastguard Worker true
33*1208bc7eSAndroid Build Coastguard Worker #else
34*1208bc7eSAndroid Build Coastguard Worker false
35*1208bc7eSAndroid Build Coastguard Worker #endif
36*1208bc7eSAndroid Build Coastguard Worker ;
37*1208bc7eSAndroid Build Coastguard Worker bool opt_abort_conf =
38*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_DEBUG
39*1208bc7eSAndroid Build Coastguard Worker true
40*1208bc7eSAndroid Build Coastguard Worker #else
41*1208bc7eSAndroid Build Coastguard Worker false
42*1208bc7eSAndroid Build Coastguard Worker #endif
43*1208bc7eSAndroid Build Coastguard Worker ;
44*1208bc7eSAndroid Build Coastguard Worker const char *opt_junk =
45*1208bc7eSAndroid Build Coastguard Worker #if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))
46*1208bc7eSAndroid Build Coastguard Worker "true"
47*1208bc7eSAndroid Build Coastguard Worker #else
48*1208bc7eSAndroid Build Coastguard Worker "false"
49*1208bc7eSAndroid Build Coastguard Worker #endif
50*1208bc7eSAndroid Build Coastguard Worker ;
51*1208bc7eSAndroid Build Coastguard Worker bool opt_junk_alloc =
52*1208bc7eSAndroid Build Coastguard Worker #if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))
53*1208bc7eSAndroid Build Coastguard Worker true
54*1208bc7eSAndroid Build Coastguard Worker #else
55*1208bc7eSAndroid Build Coastguard Worker false
56*1208bc7eSAndroid Build Coastguard Worker #endif
57*1208bc7eSAndroid Build Coastguard Worker ;
58*1208bc7eSAndroid Build Coastguard Worker bool opt_junk_free =
59*1208bc7eSAndroid Build Coastguard Worker #if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))
60*1208bc7eSAndroid Build Coastguard Worker true
61*1208bc7eSAndroid Build Coastguard Worker #else
62*1208bc7eSAndroid Build Coastguard Worker false
63*1208bc7eSAndroid Build Coastguard Worker #endif
64*1208bc7eSAndroid Build Coastguard Worker ;
65*1208bc7eSAndroid Build Coastguard Worker
66*1208bc7eSAndroid Build Coastguard Worker bool opt_utrace = false;
67*1208bc7eSAndroid Build Coastguard Worker bool opt_xmalloc = false;
68*1208bc7eSAndroid Build Coastguard Worker bool opt_zero = false;
69*1208bc7eSAndroid Build Coastguard Worker unsigned opt_narenas = 0;
70*1208bc7eSAndroid Build Coastguard Worker
71*1208bc7eSAndroid Build Coastguard Worker unsigned ncpus;
72*1208bc7eSAndroid Build Coastguard Worker
73*1208bc7eSAndroid Build Coastguard Worker /* Protects arenas initialization. */
74*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_t arenas_lock;
75*1208bc7eSAndroid Build Coastguard Worker /*
76*1208bc7eSAndroid Build Coastguard Worker * Arenas that are used to service external requests. Not all elements of the
77*1208bc7eSAndroid Build Coastguard Worker * arenas array are necessarily used; arenas are created lazily as needed.
78*1208bc7eSAndroid Build Coastguard Worker *
79*1208bc7eSAndroid Build Coastguard Worker * arenas[0..narenas_auto) are used for automatic multiplexing of threads and
80*1208bc7eSAndroid Build Coastguard Worker * arenas. arenas[narenas_auto..narenas_total) are only used if the application
81*1208bc7eSAndroid Build Coastguard Worker * takes some action to create them and allocate from them.
82*1208bc7eSAndroid Build Coastguard Worker *
83*1208bc7eSAndroid Build Coastguard Worker * Points to an arena_t.
84*1208bc7eSAndroid Build Coastguard Worker */
85*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALIGNED(CACHELINE)
86*1208bc7eSAndroid Build Coastguard Worker atomic_p_t arenas[MALLOCX_ARENA_LIMIT];
87*1208bc7eSAndroid Build Coastguard Worker static atomic_u_t narenas_total; /* Use narenas_total_*(). */
88*1208bc7eSAndroid Build Coastguard Worker static arena_t *a0; /* arenas[0]; read-only after initialization. */
89*1208bc7eSAndroid Build Coastguard Worker unsigned narenas_auto; /* Read-only after initialization. */
90*1208bc7eSAndroid Build Coastguard Worker
91*1208bc7eSAndroid Build Coastguard Worker typedef enum {
92*1208bc7eSAndroid Build Coastguard Worker malloc_init_uninitialized = 3,
93*1208bc7eSAndroid Build Coastguard Worker malloc_init_a0_initialized = 2,
94*1208bc7eSAndroid Build Coastguard Worker malloc_init_recursible = 1,
95*1208bc7eSAndroid Build Coastguard Worker malloc_init_initialized = 0 /* Common case --> jnz. */
96*1208bc7eSAndroid Build Coastguard Worker } malloc_init_t;
97*1208bc7eSAndroid Build Coastguard Worker static malloc_init_t malloc_init_state = malloc_init_uninitialized;
98*1208bc7eSAndroid Build Coastguard Worker
99*1208bc7eSAndroid Build Coastguard Worker /* False should be the common case. Set to true to trigger initialization. */
100*1208bc7eSAndroid Build Coastguard Worker bool malloc_slow = true;
101*1208bc7eSAndroid Build Coastguard Worker
102*1208bc7eSAndroid Build Coastguard Worker /* When malloc_slow is true, set the corresponding bits for sanity check. */
103*1208bc7eSAndroid Build Coastguard Worker enum {
104*1208bc7eSAndroid Build Coastguard Worker flag_opt_junk_alloc = (1U),
105*1208bc7eSAndroid Build Coastguard Worker flag_opt_junk_free = (1U << 1),
106*1208bc7eSAndroid Build Coastguard Worker flag_opt_zero = (1U << 2),
107*1208bc7eSAndroid Build Coastguard Worker flag_opt_utrace = (1U << 3),
108*1208bc7eSAndroid Build Coastguard Worker flag_opt_xmalloc = (1U << 4)
109*1208bc7eSAndroid Build Coastguard Worker };
110*1208bc7eSAndroid Build Coastguard Worker static uint8_t malloc_slow_flags;
111*1208bc7eSAndroid Build Coastguard Worker
112*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_THREADED_INIT
113*1208bc7eSAndroid Build Coastguard Worker /* Used to let the initializing thread recursively allocate. */
114*1208bc7eSAndroid Build Coastguard Worker # define NO_INITIALIZER ((pthread_t)0)
115*1208bc7eSAndroid Build Coastguard Worker # define INITIALIZER pthread_self()
116*1208bc7eSAndroid Build Coastguard Worker # define IS_INITIALIZER (malloc_initializer == pthread_self())
117*1208bc7eSAndroid Build Coastguard Worker static pthread_t malloc_initializer = NO_INITIALIZER;
118*1208bc7eSAndroid Build Coastguard Worker #else
119*1208bc7eSAndroid Build Coastguard Worker # define NO_INITIALIZER false
120*1208bc7eSAndroid Build Coastguard Worker # define INITIALIZER true
121*1208bc7eSAndroid Build Coastguard Worker # define IS_INITIALIZER malloc_initializer
122*1208bc7eSAndroid Build Coastguard Worker static bool malloc_initializer = NO_INITIALIZER;
123*1208bc7eSAndroid Build Coastguard Worker #endif
124*1208bc7eSAndroid Build Coastguard Worker
125*1208bc7eSAndroid Build Coastguard Worker /* Used to avoid initialization races. */
126*1208bc7eSAndroid Build Coastguard Worker #ifdef _WIN32
127*1208bc7eSAndroid Build Coastguard Worker #if _WIN32_WINNT >= 0x0600
128*1208bc7eSAndroid Build Coastguard Worker static malloc_mutex_t init_lock = SRWLOCK_INIT;
129*1208bc7eSAndroid Build Coastguard Worker #else
130*1208bc7eSAndroid Build Coastguard Worker static malloc_mutex_t init_lock;
131*1208bc7eSAndroid Build Coastguard Worker static bool init_lock_initialized = false;
132*1208bc7eSAndroid Build Coastguard Worker
JEMALLOC_ATTR(constructor)133*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(constructor)
134*1208bc7eSAndroid Build Coastguard Worker static void WINAPI
135*1208bc7eSAndroid Build Coastguard Worker _init_init_lock(void) {
136*1208bc7eSAndroid Build Coastguard Worker /*
137*1208bc7eSAndroid Build Coastguard Worker * If another constructor in the same binary is using mallctl to e.g.
138*1208bc7eSAndroid Build Coastguard Worker * set up extent hooks, it may end up running before this one, and
139*1208bc7eSAndroid Build Coastguard Worker * malloc_init_hard will crash trying to lock the uninitialized lock. So
140*1208bc7eSAndroid Build Coastguard Worker * we force an initialization of the lock in malloc_init_hard as well.
141*1208bc7eSAndroid Build Coastguard Worker * We don't try to care about atomicity of the accessed to the
142*1208bc7eSAndroid Build Coastguard Worker * init_lock_initialized boolean, since it really only matters early in
143*1208bc7eSAndroid Build Coastguard Worker * the process creation, before any separate thread normally starts
144*1208bc7eSAndroid Build Coastguard Worker * doing anything.
145*1208bc7eSAndroid Build Coastguard Worker */
146*1208bc7eSAndroid Build Coastguard Worker if (!init_lock_initialized) {
147*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_init(&init_lock, "init", WITNESS_RANK_INIT,
148*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_rank_exclusive);
149*1208bc7eSAndroid Build Coastguard Worker }
150*1208bc7eSAndroid Build Coastguard Worker init_lock_initialized = true;
151*1208bc7eSAndroid Build Coastguard Worker }
152*1208bc7eSAndroid Build Coastguard Worker
153*1208bc7eSAndroid Build Coastguard Worker #ifdef _MSC_VER
154*1208bc7eSAndroid Build Coastguard Worker # pragma section(".CRT$XCU", read)
155*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_SECTION(".CRT$XCU") JEMALLOC_ATTR(used)
156*1208bc7eSAndroid Build Coastguard Worker static const void (WINAPI *init_init_lock)(void) = _init_init_lock;
157*1208bc7eSAndroid Build Coastguard Worker #endif
158*1208bc7eSAndroid Build Coastguard Worker #endif
159*1208bc7eSAndroid Build Coastguard Worker #else
160*1208bc7eSAndroid Build Coastguard Worker static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER;
161*1208bc7eSAndroid Build Coastguard Worker #endif
162*1208bc7eSAndroid Build Coastguard Worker
163*1208bc7eSAndroid Build Coastguard Worker typedef struct {
164*1208bc7eSAndroid Build Coastguard Worker void *p; /* Input pointer (as in realloc(p, s)). */
165*1208bc7eSAndroid Build Coastguard Worker size_t s; /* Request size. */
166*1208bc7eSAndroid Build Coastguard Worker void *r; /* Result pointer. */
167*1208bc7eSAndroid Build Coastguard Worker } malloc_utrace_t;
168*1208bc7eSAndroid Build Coastguard Worker
169*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_UTRACE
170*1208bc7eSAndroid Build Coastguard Worker # define UTRACE(a, b, c) do { \
171*1208bc7eSAndroid Build Coastguard Worker if (unlikely(opt_utrace)) { \
172*1208bc7eSAndroid Build Coastguard Worker int utrace_serrno = errno; \
173*1208bc7eSAndroid Build Coastguard Worker malloc_utrace_t ut; \
174*1208bc7eSAndroid Build Coastguard Worker ut.p = (a); \
175*1208bc7eSAndroid Build Coastguard Worker ut.s = (b); \
176*1208bc7eSAndroid Build Coastguard Worker ut.r = (c); \
177*1208bc7eSAndroid Build Coastguard Worker utrace(&ut, sizeof(ut)); \
178*1208bc7eSAndroid Build Coastguard Worker errno = utrace_serrno; \
179*1208bc7eSAndroid Build Coastguard Worker } \
180*1208bc7eSAndroid Build Coastguard Worker } while (0)
181*1208bc7eSAndroid Build Coastguard Worker #else
182*1208bc7eSAndroid Build Coastguard Worker # define UTRACE(a, b, c)
183*1208bc7eSAndroid Build Coastguard Worker #endif
184*1208bc7eSAndroid Build Coastguard Worker
185*1208bc7eSAndroid Build Coastguard Worker /* Whether encountered any invalid config options. */
186*1208bc7eSAndroid Build Coastguard Worker static bool had_conf_error = false;
187*1208bc7eSAndroid Build Coastguard Worker
188*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
189*1208bc7eSAndroid Build Coastguard Worker /*
190*1208bc7eSAndroid Build Coastguard Worker * Function prototypes for static functions that are referenced prior to
191*1208bc7eSAndroid Build Coastguard Worker * definition.
192*1208bc7eSAndroid Build Coastguard Worker */
193*1208bc7eSAndroid Build Coastguard Worker
194*1208bc7eSAndroid Build Coastguard Worker static bool malloc_init_hard_a0(void);
195*1208bc7eSAndroid Build Coastguard Worker static bool malloc_init_hard(void);
196*1208bc7eSAndroid Build Coastguard Worker
197*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
198*1208bc7eSAndroid Build Coastguard Worker /*
199*1208bc7eSAndroid Build Coastguard Worker * Begin miscellaneous support functions.
200*1208bc7eSAndroid Build Coastguard Worker */
201*1208bc7eSAndroid Build Coastguard Worker
202*1208bc7eSAndroid Build Coastguard Worker bool
malloc_initialized(void)203*1208bc7eSAndroid Build Coastguard Worker malloc_initialized(void) {
204*1208bc7eSAndroid Build Coastguard Worker return (malloc_init_state == malloc_init_initialized);
205*1208bc7eSAndroid Build Coastguard Worker }
206*1208bc7eSAndroid Build Coastguard Worker
207*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE bool
malloc_init_a0(void)208*1208bc7eSAndroid Build Coastguard Worker malloc_init_a0(void) {
209*1208bc7eSAndroid Build Coastguard Worker if (unlikely(malloc_init_state == malloc_init_uninitialized)) {
210*1208bc7eSAndroid Build Coastguard Worker return malloc_init_hard_a0();
211*1208bc7eSAndroid Build Coastguard Worker }
212*1208bc7eSAndroid Build Coastguard Worker return false;
213*1208bc7eSAndroid Build Coastguard Worker }
214*1208bc7eSAndroid Build Coastguard Worker
215*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE bool
malloc_init(void)216*1208bc7eSAndroid Build Coastguard Worker malloc_init(void) {
217*1208bc7eSAndroid Build Coastguard Worker if (unlikely(!malloc_initialized()) && malloc_init_hard()) {
218*1208bc7eSAndroid Build Coastguard Worker return true;
219*1208bc7eSAndroid Build Coastguard Worker }
220*1208bc7eSAndroid Build Coastguard Worker return false;
221*1208bc7eSAndroid Build Coastguard Worker }
222*1208bc7eSAndroid Build Coastguard Worker
223*1208bc7eSAndroid Build Coastguard Worker /*
224*1208bc7eSAndroid Build Coastguard Worker * The a0*() functions are used instead of i{d,}alloc() in situations that
225*1208bc7eSAndroid Build Coastguard Worker * cannot tolerate TLS variable access.
226*1208bc7eSAndroid Build Coastguard Worker */
227*1208bc7eSAndroid Build Coastguard Worker
228*1208bc7eSAndroid Build Coastguard Worker static void *
a0ialloc(size_t size,bool zero,bool is_internal)229*1208bc7eSAndroid Build Coastguard Worker a0ialloc(size_t size, bool zero, bool is_internal) {
230*1208bc7eSAndroid Build Coastguard Worker if (unlikely(malloc_init_a0())) {
231*1208bc7eSAndroid Build Coastguard Worker return NULL;
232*1208bc7eSAndroid Build Coastguard Worker }
233*1208bc7eSAndroid Build Coastguard Worker
234*1208bc7eSAndroid Build Coastguard Worker return iallocztm(TSDN_NULL, size, sz_size2index(size), zero, NULL,
235*1208bc7eSAndroid Build Coastguard Worker is_internal, arena_get(TSDN_NULL, 0, true), true);
236*1208bc7eSAndroid Build Coastguard Worker }
237*1208bc7eSAndroid Build Coastguard Worker
238*1208bc7eSAndroid Build Coastguard Worker static void
a0idalloc(void * ptr,bool is_internal)239*1208bc7eSAndroid Build Coastguard Worker a0idalloc(void *ptr, bool is_internal) {
240*1208bc7eSAndroid Build Coastguard Worker idalloctm(TSDN_NULL, ptr, NULL, NULL, is_internal, true);
241*1208bc7eSAndroid Build Coastguard Worker }
242*1208bc7eSAndroid Build Coastguard Worker
243*1208bc7eSAndroid Build Coastguard Worker void *
a0malloc(size_t size)244*1208bc7eSAndroid Build Coastguard Worker a0malloc(size_t size) {
245*1208bc7eSAndroid Build Coastguard Worker return a0ialloc(size, false, true);
246*1208bc7eSAndroid Build Coastguard Worker }
247*1208bc7eSAndroid Build Coastguard Worker
248*1208bc7eSAndroid Build Coastguard Worker void
a0dalloc(void * ptr)249*1208bc7eSAndroid Build Coastguard Worker a0dalloc(void *ptr) {
250*1208bc7eSAndroid Build Coastguard Worker a0idalloc(ptr, true);
251*1208bc7eSAndroid Build Coastguard Worker }
252*1208bc7eSAndroid Build Coastguard Worker
253*1208bc7eSAndroid Build Coastguard Worker /*
254*1208bc7eSAndroid Build Coastguard Worker * FreeBSD's libc uses the bootstrap_*() functions in bootstrap-senstive
255*1208bc7eSAndroid Build Coastguard Worker * situations that cannot tolerate TLS variable access (TLS allocation and very
256*1208bc7eSAndroid Build Coastguard Worker * early internal data structure initialization).
257*1208bc7eSAndroid Build Coastguard Worker */
258*1208bc7eSAndroid Build Coastguard Worker
259*1208bc7eSAndroid Build Coastguard Worker void *
bootstrap_malloc(size_t size)260*1208bc7eSAndroid Build Coastguard Worker bootstrap_malloc(size_t size) {
261*1208bc7eSAndroid Build Coastguard Worker if (unlikely(size == 0)) {
262*1208bc7eSAndroid Build Coastguard Worker size = 1;
263*1208bc7eSAndroid Build Coastguard Worker }
264*1208bc7eSAndroid Build Coastguard Worker
265*1208bc7eSAndroid Build Coastguard Worker return a0ialloc(size, false, false);
266*1208bc7eSAndroid Build Coastguard Worker }
267*1208bc7eSAndroid Build Coastguard Worker
268*1208bc7eSAndroid Build Coastguard Worker void *
bootstrap_calloc(size_t num,size_t size)269*1208bc7eSAndroid Build Coastguard Worker bootstrap_calloc(size_t num, size_t size) {
270*1208bc7eSAndroid Build Coastguard Worker size_t num_size;
271*1208bc7eSAndroid Build Coastguard Worker
272*1208bc7eSAndroid Build Coastguard Worker num_size = num * size;
273*1208bc7eSAndroid Build Coastguard Worker if (unlikely(num_size == 0)) {
274*1208bc7eSAndroid Build Coastguard Worker assert(num == 0 || size == 0);
275*1208bc7eSAndroid Build Coastguard Worker num_size = 1;
276*1208bc7eSAndroid Build Coastguard Worker }
277*1208bc7eSAndroid Build Coastguard Worker
278*1208bc7eSAndroid Build Coastguard Worker return a0ialloc(num_size, true, false);
279*1208bc7eSAndroid Build Coastguard Worker }
280*1208bc7eSAndroid Build Coastguard Worker
281*1208bc7eSAndroid Build Coastguard Worker void
bootstrap_free(void * ptr)282*1208bc7eSAndroid Build Coastguard Worker bootstrap_free(void *ptr) {
283*1208bc7eSAndroid Build Coastguard Worker if (unlikely(ptr == NULL)) {
284*1208bc7eSAndroid Build Coastguard Worker return;
285*1208bc7eSAndroid Build Coastguard Worker }
286*1208bc7eSAndroid Build Coastguard Worker
287*1208bc7eSAndroid Build Coastguard Worker a0idalloc(ptr, false);
288*1208bc7eSAndroid Build Coastguard Worker }
289*1208bc7eSAndroid Build Coastguard Worker
290*1208bc7eSAndroid Build Coastguard Worker void
arena_set(unsigned ind,arena_t * arena)291*1208bc7eSAndroid Build Coastguard Worker arena_set(unsigned ind, arena_t *arena) {
292*1208bc7eSAndroid Build Coastguard Worker atomic_store_p(&arenas[ind], arena, ATOMIC_RELEASE);
293*1208bc7eSAndroid Build Coastguard Worker }
294*1208bc7eSAndroid Build Coastguard Worker
295*1208bc7eSAndroid Build Coastguard Worker static void
narenas_total_set(unsigned narenas)296*1208bc7eSAndroid Build Coastguard Worker narenas_total_set(unsigned narenas) {
297*1208bc7eSAndroid Build Coastguard Worker atomic_store_u(&narenas_total, narenas, ATOMIC_RELEASE);
298*1208bc7eSAndroid Build Coastguard Worker }
299*1208bc7eSAndroid Build Coastguard Worker
300*1208bc7eSAndroid Build Coastguard Worker static void
narenas_total_inc(void)301*1208bc7eSAndroid Build Coastguard Worker narenas_total_inc(void) {
302*1208bc7eSAndroid Build Coastguard Worker atomic_fetch_add_u(&narenas_total, 1, ATOMIC_RELEASE);
303*1208bc7eSAndroid Build Coastguard Worker }
304*1208bc7eSAndroid Build Coastguard Worker
305*1208bc7eSAndroid Build Coastguard Worker unsigned
narenas_total_get(void)306*1208bc7eSAndroid Build Coastguard Worker narenas_total_get(void) {
307*1208bc7eSAndroid Build Coastguard Worker return atomic_load_u(&narenas_total, ATOMIC_ACQUIRE);
308*1208bc7eSAndroid Build Coastguard Worker }
309*1208bc7eSAndroid Build Coastguard Worker
310*1208bc7eSAndroid Build Coastguard Worker /* Create a new arena and insert it into the arenas array at index ind. */
311*1208bc7eSAndroid Build Coastguard Worker static arena_t *
arena_init_locked(tsdn_t * tsdn,unsigned ind,extent_hooks_t * extent_hooks)312*1208bc7eSAndroid Build Coastguard Worker arena_init_locked(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
313*1208bc7eSAndroid Build Coastguard Worker arena_t *arena;
314*1208bc7eSAndroid Build Coastguard Worker
315*1208bc7eSAndroid Build Coastguard Worker assert(ind <= narenas_total_get());
316*1208bc7eSAndroid Build Coastguard Worker if (ind >= MALLOCX_ARENA_LIMIT) {
317*1208bc7eSAndroid Build Coastguard Worker return NULL;
318*1208bc7eSAndroid Build Coastguard Worker }
319*1208bc7eSAndroid Build Coastguard Worker if (ind == narenas_total_get()) {
320*1208bc7eSAndroid Build Coastguard Worker narenas_total_inc();
321*1208bc7eSAndroid Build Coastguard Worker }
322*1208bc7eSAndroid Build Coastguard Worker
323*1208bc7eSAndroid Build Coastguard Worker /*
324*1208bc7eSAndroid Build Coastguard Worker * Another thread may have already initialized arenas[ind] if it's an
325*1208bc7eSAndroid Build Coastguard Worker * auto arena.
326*1208bc7eSAndroid Build Coastguard Worker */
327*1208bc7eSAndroid Build Coastguard Worker arena = arena_get(tsdn, ind, false);
328*1208bc7eSAndroid Build Coastguard Worker if (arena != NULL) {
329*1208bc7eSAndroid Build Coastguard Worker assert(ind < narenas_auto);
330*1208bc7eSAndroid Build Coastguard Worker return arena;
331*1208bc7eSAndroid Build Coastguard Worker }
332*1208bc7eSAndroid Build Coastguard Worker
333*1208bc7eSAndroid Build Coastguard Worker /* Actually initialize the arena. */
334*1208bc7eSAndroid Build Coastguard Worker arena = arena_new(tsdn, ind, extent_hooks);
335*1208bc7eSAndroid Build Coastguard Worker
336*1208bc7eSAndroid Build Coastguard Worker return arena;
337*1208bc7eSAndroid Build Coastguard Worker }
338*1208bc7eSAndroid Build Coastguard Worker
339*1208bc7eSAndroid Build Coastguard Worker static void
arena_new_create_background_thread(tsdn_t * tsdn,unsigned ind)340*1208bc7eSAndroid Build Coastguard Worker arena_new_create_background_thread(tsdn_t *tsdn, unsigned ind) {
341*1208bc7eSAndroid Build Coastguard Worker if (ind == 0) {
342*1208bc7eSAndroid Build Coastguard Worker return;
343*1208bc7eSAndroid Build Coastguard Worker }
344*1208bc7eSAndroid Build Coastguard Worker if (have_background_thread) {
345*1208bc7eSAndroid Build Coastguard Worker bool err;
346*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(tsdn, &background_thread_lock);
347*1208bc7eSAndroid Build Coastguard Worker err = background_thread_create(tsdn_tsd(tsdn), ind);
348*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsdn, &background_thread_lock);
349*1208bc7eSAndroid Build Coastguard Worker if (err) {
350*1208bc7eSAndroid Build Coastguard Worker malloc_printf("<jemalloc>: error in background thread "
351*1208bc7eSAndroid Build Coastguard Worker "creation for arena %u. Abort.\n", ind);
352*1208bc7eSAndroid Build Coastguard Worker abort();
353*1208bc7eSAndroid Build Coastguard Worker }
354*1208bc7eSAndroid Build Coastguard Worker }
355*1208bc7eSAndroid Build Coastguard Worker }
356*1208bc7eSAndroid Build Coastguard Worker
357*1208bc7eSAndroid Build Coastguard Worker arena_t *
arena_init(tsdn_t * tsdn,unsigned ind,extent_hooks_t * extent_hooks)358*1208bc7eSAndroid Build Coastguard Worker arena_init(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
359*1208bc7eSAndroid Build Coastguard Worker arena_t *arena;
360*1208bc7eSAndroid Build Coastguard Worker
361*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(tsdn, &arenas_lock);
362*1208bc7eSAndroid Build Coastguard Worker arena = arena_init_locked(tsdn, ind, extent_hooks);
363*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsdn, &arenas_lock);
364*1208bc7eSAndroid Build Coastguard Worker
365*1208bc7eSAndroid Build Coastguard Worker arena_new_create_background_thread(tsdn, ind);
366*1208bc7eSAndroid Build Coastguard Worker
367*1208bc7eSAndroid Build Coastguard Worker return arena;
368*1208bc7eSAndroid Build Coastguard Worker }
369*1208bc7eSAndroid Build Coastguard Worker
370*1208bc7eSAndroid Build Coastguard Worker static void
arena_bind(tsd_t * tsd,unsigned ind,bool internal)371*1208bc7eSAndroid Build Coastguard Worker arena_bind(tsd_t *tsd, unsigned ind, bool internal) {
372*1208bc7eSAndroid Build Coastguard Worker arena_t *arena = arena_get(tsd_tsdn(tsd), ind, false);
373*1208bc7eSAndroid Build Coastguard Worker arena_nthreads_inc(arena, internal);
374*1208bc7eSAndroid Build Coastguard Worker
375*1208bc7eSAndroid Build Coastguard Worker if (internal) {
376*1208bc7eSAndroid Build Coastguard Worker tsd_iarena_set(tsd, arena);
377*1208bc7eSAndroid Build Coastguard Worker } else {
378*1208bc7eSAndroid Build Coastguard Worker tsd_arena_set(tsd, arena);
379*1208bc7eSAndroid Build Coastguard Worker }
380*1208bc7eSAndroid Build Coastguard Worker }
381*1208bc7eSAndroid Build Coastguard Worker
382*1208bc7eSAndroid Build Coastguard Worker void
arena_migrate(tsd_t * tsd,unsigned oldind,unsigned newind)383*1208bc7eSAndroid Build Coastguard Worker arena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind) {
384*1208bc7eSAndroid Build Coastguard Worker arena_t *oldarena, *newarena;
385*1208bc7eSAndroid Build Coastguard Worker
386*1208bc7eSAndroid Build Coastguard Worker oldarena = arena_get(tsd_tsdn(tsd), oldind, false);
387*1208bc7eSAndroid Build Coastguard Worker newarena = arena_get(tsd_tsdn(tsd), newind, false);
388*1208bc7eSAndroid Build Coastguard Worker arena_nthreads_dec(oldarena, false);
389*1208bc7eSAndroid Build Coastguard Worker arena_nthreads_inc(newarena, false);
390*1208bc7eSAndroid Build Coastguard Worker tsd_arena_set(tsd, newarena);
391*1208bc7eSAndroid Build Coastguard Worker }
392*1208bc7eSAndroid Build Coastguard Worker
393*1208bc7eSAndroid Build Coastguard Worker static void
arena_unbind(tsd_t * tsd,unsigned ind,bool internal)394*1208bc7eSAndroid Build Coastguard Worker arena_unbind(tsd_t *tsd, unsigned ind, bool internal) {
395*1208bc7eSAndroid Build Coastguard Worker arena_t *arena;
396*1208bc7eSAndroid Build Coastguard Worker
397*1208bc7eSAndroid Build Coastguard Worker arena = arena_get(tsd_tsdn(tsd), ind, false);
398*1208bc7eSAndroid Build Coastguard Worker arena_nthreads_dec(arena, internal);
399*1208bc7eSAndroid Build Coastguard Worker
400*1208bc7eSAndroid Build Coastguard Worker if (internal) {
401*1208bc7eSAndroid Build Coastguard Worker tsd_iarena_set(tsd, NULL);
402*1208bc7eSAndroid Build Coastguard Worker } else {
403*1208bc7eSAndroid Build Coastguard Worker tsd_arena_set(tsd, NULL);
404*1208bc7eSAndroid Build Coastguard Worker }
405*1208bc7eSAndroid Build Coastguard Worker }
406*1208bc7eSAndroid Build Coastguard Worker
407*1208bc7eSAndroid Build Coastguard Worker arena_tdata_t *
arena_tdata_get_hard(tsd_t * tsd,unsigned ind)408*1208bc7eSAndroid Build Coastguard Worker arena_tdata_get_hard(tsd_t *tsd, unsigned ind) {
409*1208bc7eSAndroid Build Coastguard Worker arena_tdata_t *tdata, *arenas_tdata_old;
410*1208bc7eSAndroid Build Coastguard Worker arena_tdata_t *arenas_tdata = tsd_arenas_tdata_get(tsd);
411*1208bc7eSAndroid Build Coastguard Worker unsigned narenas_tdata_old, i;
412*1208bc7eSAndroid Build Coastguard Worker unsigned narenas_tdata = tsd_narenas_tdata_get(tsd);
413*1208bc7eSAndroid Build Coastguard Worker unsigned narenas_actual = narenas_total_get();
414*1208bc7eSAndroid Build Coastguard Worker
415*1208bc7eSAndroid Build Coastguard Worker /*
416*1208bc7eSAndroid Build Coastguard Worker * Dissociate old tdata array (and set up for deallocation upon return)
417*1208bc7eSAndroid Build Coastguard Worker * if it's too small.
418*1208bc7eSAndroid Build Coastguard Worker */
419*1208bc7eSAndroid Build Coastguard Worker if (arenas_tdata != NULL && narenas_tdata < narenas_actual) {
420*1208bc7eSAndroid Build Coastguard Worker arenas_tdata_old = arenas_tdata;
421*1208bc7eSAndroid Build Coastguard Worker narenas_tdata_old = narenas_tdata;
422*1208bc7eSAndroid Build Coastguard Worker arenas_tdata = NULL;
423*1208bc7eSAndroid Build Coastguard Worker narenas_tdata = 0;
424*1208bc7eSAndroid Build Coastguard Worker tsd_arenas_tdata_set(tsd, arenas_tdata);
425*1208bc7eSAndroid Build Coastguard Worker tsd_narenas_tdata_set(tsd, narenas_tdata);
426*1208bc7eSAndroid Build Coastguard Worker } else {
427*1208bc7eSAndroid Build Coastguard Worker arenas_tdata_old = NULL;
428*1208bc7eSAndroid Build Coastguard Worker narenas_tdata_old = 0;
429*1208bc7eSAndroid Build Coastguard Worker }
430*1208bc7eSAndroid Build Coastguard Worker
431*1208bc7eSAndroid Build Coastguard Worker /* Allocate tdata array if it's missing. */
432*1208bc7eSAndroid Build Coastguard Worker if (arenas_tdata == NULL) {
433*1208bc7eSAndroid Build Coastguard Worker bool *arenas_tdata_bypassp = tsd_arenas_tdata_bypassp_get(tsd);
434*1208bc7eSAndroid Build Coastguard Worker narenas_tdata = (ind < narenas_actual) ? narenas_actual : ind+1;
435*1208bc7eSAndroid Build Coastguard Worker
436*1208bc7eSAndroid Build Coastguard Worker if (tsd_nominal(tsd) && !*arenas_tdata_bypassp) {
437*1208bc7eSAndroid Build Coastguard Worker *arenas_tdata_bypassp = true;
438*1208bc7eSAndroid Build Coastguard Worker arenas_tdata = (arena_tdata_t *)a0malloc(
439*1208bc7eSAndroid Build Coastguard Worker sizeof(arena_tdata_t) * narenas_tdata);
440*1208bc7eSAndroid Build Coastguard Worker *arenas_tdata_bypassp = false;
441*1208bc7eSAndroid Build Coastguard Worker }
442*1208bc7eSAndroid Build Coastguard Worker if (arenas_tdata == NULL) {
443*1208bc7eSAndroid Build Coastguard Worker tdata = NULL;
444*1208bc7eSAndroid Build Coastguard Worker goto label_return;
445*1208bc7eSAndroid Build Coastguard Worker }
446*1208bc7eSAndroid Build Coastguard Worker assert(tsd_nominal(tsd) && !*arenas_tdata_bypassp);
447*1208bc7eSAndroid Build Coastguard Worker tsd_arenas_tdata_set(tsd, arenas_tdata);
448*1208bc7eSAndroid Build Coastguard Worker tsd_narenas_tdata_set(tsd, narenas_tdata);
449*1208bc7eSAndroid Build Coastguard Worker }
450*1208bc7eSAndroid Build Coastguard Worker
451*1208bc7eSAndroid Build Coastguard Worker /*
452*1208bc7eSAndroid Build Coastguard Worker * Copy to tdata array. It's possible that the actual number of arenas
453*1208bc7eSAndroid Build Coastguard Worker * has increased since narenas_total_get() was called above, but that
454*1208bc7eSAndroid Build Coastguard Worker * causes no correctness issues unless two threads concurrently execute
455*1208bc7eSAndroid Build Coastguard Worker * the arenas.create mallctl, which we trust mallctl synchronization to
456*1208bc7eSAndroid Build Coastguard Worker * prevent.
457*1208bc7eSAndroid Build Coastguard Worker */
458*1208bc7eSAndroid Build Coastguard Worker
459*1208bc7eSAndroid Build Coastguard Worker /* Copy/initialize tickers. */
460*1208bc7eSAndroid Build Coastguard Worker for (i = 0; i < narenas_actual; i++) {
461*1208bc7eSAndroid Build Coastguard Worker if (i < narenas_tdata_old) {
462*1208bc7eSAndroid Build Coastguard Worker ticker_copy(&arenas_tdata[i].decay_ticker,
463*1208bc7eSAndroid Build Coastguard Worker &arenas_tdata_old[i].decay_ticker);
464*1208bc7eSAndroid Build Coastguard Worker } else {
465*1208bc7eSAndroid Build Coastguard Worker ticker_init(&arenas_tdata[i].decay_ticker,
466*1208bc7eSAndroid Build Coastguard Worker DECAY_NTICKS_PER_UPDATE);
467*1208bc7eSAndroid Build Coastguard Worker }
468*1208bc7eSAndroid Build Coastguard Worker }
469*1208bc7eSAndroid Build Coastguard Worker if (narenas_tdata > narenas_actual) {
470*1208bc7eSAndroid Build Coastguard Worker memset(&arenas_tdata[narenas_actual], 0, sizeof(arena_tdata_t)
471*1208bc7eSAndroid Build Coastguard Worker * (narenas_tdata - narenas_actual));
472*1208bc7eSAndroid Build Coastguard Worker }
473*1208bc7eSAndroid Build Coastguard Worker
474*1208bc7eSAndroid Build Coastguard Worker /* Read the refreshed tdata array. */
475*1208bc7eSAndroid Build Coastguard Worker tdata = &arenas_tdata[ind];
476*1208bc7eSAndroid Build Coastguard Worker label_return:
477*1208bc7eSAndroid Build Coastguard Worker if (arenas_tdata_old != NULL) {
478*1208bc7eSAndroid Build Coastguard Worker a0dalloc(arenas_tdata_old);
479*1208bc7eSAndroid Build Coastguard Worker }
480*1208bc7eSAndroid Build Coastguard Worker return tdata;
481*1208bc7eSAndroid Build Coastguard Worker }
482*1208bc7eSAndroid Build Coastguard Worker
483*1208bc7eSAndroid Build Coastguard Worker /* Slow path, called only by arena_choose(). */
484*1208bc7eSAndroid Build Coastguard Worker arena_t *
arena_choose_hard(tsd_t * tsd,bool internal)485*1208bc7eSAndroid Build Coastguard Worker arena_choose_hard(tsd_t *tsd, bool internal) {
486*1208bc7eSAndroid Build Coastguard Worker arena_t *ret JEMALLOC_CC_SILENCE_INIT(NULL);
487*1208bc7eSAndroid Build Coastguard Worker
488*1208bc7eSAndroid Build Coastguard Worker if (have_percpu_arena && PERCPU_ARENA_ENABLED(opt_percpu_arena)) {
489*1208bc7eSAndroid Build Coastguard Worker unsigned choose = percpu_arena_choose();
490*1208bc7eSAndroid Build Coastguard Worker ret = arena_get(tsd_tsdn(tsd), choose, true);
491*1208bc7eSAndroid Build Coastguard Worker assert(ret != NULL);
492*1208bc7eSAndroid Build Coastguard Worker arena_bind(tsd, arena_ind_get(ret), false);
493*1208bc7eSAndroid Build Coastguard Worker arena_bind(tsd, arena_ind_get(ret), true);
494*1208bc7eSAndroid Build Coastguard Worker
495*1208bc7eSAndroid Build Coastguard Worker return ret;
496*1208bc7eSAndroid Build Coastguard Worker }
497*1208bc7eSAndroid Build Coastguard Worker
498*1208bc7eSAndroid Build Coastguard Worker if (narenas_auto > 1) {
499*1208bc7eSAndroid Build Coastguard Worker unsigned i, j, choose[2], first_null;
500*1208bc7eSAndroid Build Coastguard Worker bool is_new_arena[2];
501*1208bc7eSAndroid Build Coastguard Worker
502*1208bc7eSAndroid Build Coastguard Worker /*
503*1208bc7eSAndroid Build Coastguard Worker * Determine binding for both non-internal and internal
504*1208bc7eSAndroid Build Coastguard Worker * allocation.
505*1208bc7eSAndroid Build Coastguard Worker *
506*1208bc7eSAndroid Build Coastguard Worker * choose[0]: For application allocation.
507*1208bc7eSAndroid Build Coastguard Worker * choose[1]: For internal metadata allocation.
508*1208bc7eSAndroid Build Coastguard Worker */
509*1208bc7eSAndroid Build Coastguard Worker
510*1208bc7eSAndroid Build Coastguard Worker for (j = 0; j < 2; j++) {
511*1208bc7eSAndroid Build Coastguard Worker choose[j] = 0;
512*1208bc7eSAndroid Build Coastguard Worker is_new_arena[j] = false;
513*1208bc7eSAndroid Build Coastguard Worker }
514*1208bc7eSAndroid Build Coastguard Worker
515*1208bc7eSAndroid Build Coastguard Worker first_null = narenas_auto;
516*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(tsd_tsdn(tsd), &arenas_lock);
517*1208bc7eSAndroid Build Coastguard Worker assert(arena_get(tsd_tsdn(tsd), 0, false) != NULL);
518*1208bc7eSAndroid Build Coastguard Worker for (i = 1; i < narenas_auto; i++) {
519*1208bc7eSAndroid Build Coastguard Worker if (arena_get(tsd_tsdn(tsd), i, false) != NULL) {
520*1208bc7eSAndroid Build Coastguard Worker /*
521*1208bc7eSAndroid Build Coastguard Worker * Choose the first arena that has the lowest
522*1208bc7eSAndroid Build Coastguard Worker * number of threads assigned to it.
523*1208bc7eSAndroid Build Coastguard Worker */
524*1208bc7eSAndroid Build Coastguard Worker for (j = 0; j < 2; j++) {
525*1208bc7eSAndroid Build Coastguard Worker if (arena_nthreads_get(arena_get(
526*1208bc7eSAndroid Build Coastguard Worker tsd_tsdn(tsd), i, false), !!j) <
527*1208bc7eSAndroid Build Coastguard Worker arena_nthreads_get(arena_get(
528*1208bc7eSAndroid Build Coastguard Worker tsd_tsdn(tsd), choose[j], false),
529*1208bc7eSAndroid Build Coastguard Worker !!j)) {
530*1208bc7eSAndroid Build Coastguard Worker choose[j] = i;
531*1208bc7eSAndroid Build Coastguard Worker }
532*1208bc7eSAndroid Build Coastguard Worker }
533*1208bc7eSAndroid Build Coastguard Worker } else if (first_null == narenas_auto) {
534*1208bc7eSAndroid Build Coastguard Worker /*
535*1208bc7eSAndroid Build Coastguard Worker * Record the index of the first uninitialized
536*1208bc7eSAndroid Build Coastguard Worker * arena, in case all extant arenas are in use.
537*1208bc7eSAndroid Build Coastguard Worker *
538*1208bc7eSAndroid Build Coastguard Worker * NB: It is possible for there to be
539*1208bc7eSAndroid Build Coastguard Worker * discontinuities in terms of initialized
540*1208bc7eSAndroid Build Coastguard Worker * versus uninitialized arenas, due to the
541*1208bc7eSAndroid Build Coastguard Worker * "thread.arena" mallctl.
542*1208bc7eSAndroid Build Coastguard Worker */
543*1208bc7eSAndroid Build Coastguard Worker first_null = i;
544*1208bc7eSAndroid Build Coastguard Worker }
545*1208bc7eSAndroid Build Coastguard Worker }
546*1208bc7eSAndroid Build Coastguard Worker
547*1208bc7eSAndroid Build Coastguard Worker for (j = 0; j < 2; j++) {
548*1208bc7eSAndroid Build Coastguard Worker if (arena_nthreads_get(arena_get(tsd_tsdn(tsd),
549*1208bc7eSAndroid Build Coastguard Worker choose[j], false), !!j) == 0 || first_null ==
550*1208bc7eSAndroid Build Coastguard Worker narenas_auto) {
551*1208bc7eSAndroid Build Coastguard Worker /*
552*1208bc7eSAndroid Build Coastguard Worker * Use an unloaded arena, or the least loaded
553*1208bc7eSAndroid Build Coastguard Worker * arena if all arenas are already initialized.
554*1208bc7eSAndroid Build Coastguard Worker */
555*1208bc7eSAndroid Build Coastguard Worker if (!!j == internal) {
556*1208bc7eSAndroid Build Coastguard Worker ret = arena_get(tsd_tsdn(tsd),
557*1208bc7eSAndroid Build Coastguard Worker choose[j], false);
558*1208bc7eSAndroid Build Coastguard Worker }
559*1208bc7eSAndroid Build Coastguard Worker } else {
560*1208bc7eSAndroid Build Coastguard Worker arena_t *arena;
561*1208bc7eSAndroid Build Coastguard Worker
562*1208bc7eSAndroid Build Coastguard Worker /* Initialize a new arena. */
563*1208bc7eSAndroid Build Coastguard Worker choose[j] = first_null;
564*1208bc7eSAndroid Build Coastguard Worker arena = arena_init_locked(tsd_tsdn(tsd),
565*1208bc7eSAndroid Build Coastguard Worker choose[j],
566*1208bc7eSAndroid Build Coastguard Worker (extent_hooks_t *)&extent_hooks_default);
567*1208bc7eSAndroid Build Coastguard Worker if (arena == NULL) {
568*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsd_tsdn(tsd),
569*1208bc7eSAndroid Build Coastguard Worker &arenas_lock);
570*1208bc7eSAndroid Build Coastguard Worker return NULL;
571*1208bc7eSAndroid Build Coastguard Worker }
572*1208bc7eSAndroid Build Coastguard Worker is_new_arena[j] = true;
573*1208bc7eSAndroid Build Coastguard Worker if (!!j == internal) {
574*1208bc7eSAndroid Build Coastguard Worker ret = arena;
575*1208bc7eSAndroid Build Coastguard Worker }
576*1208bc7eSAndroid Build Coastguard Worker }
577*1208bc7eSAndroid Build Coastguard Worker arena_bind(tsd, choose[j], !!j);
578*1208bc7eSAndroid Build Coastguard Worker }
579*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsd_tsdn(tsd), &arenas_lock);
580*1208bc7eSAndroid Build Coastguard Worker
581*1208bc7eSAndroid Build Coastguard Worker for (j = 0; j < 2; j++) {
582*1208bc7eSAndroid Build Coastguard Worker if (is_new_arena[j]) {
583*1208bc7eSAndroid Build Coastguard Worker assert(choose[j] > 0);
584*1208bc7eSAndroid Build Coastguard Worker arena_new_create_background_thread(
585*1208bc7eSAndroid Build Coastguard Worker tsd_tsdn(tsd), choose[j]);
586*1208bc7eSAndroid Build Coastguard Worker }
587*1208bc7eSAndroid Build Coastguard Worker }
588*1208bc7eSAndroid Build Coastguard Worker
589*1208bc7eSAndroid Build Coastguard Worker } else {
590*1208bc7eSAndroid Build Coastguard Worker ret = arena_get(tsd_tsdn(tsd), 0, false);
591*1208bc7eSAndroid Build Coastguard Worker arena_bind(tsd, 0, false);
592*1208bc7eSAndroid Build Coastguard Worker arena_bind(tsd, 0, true);
593*1208bc7eSAndroid Build Coastguard Worker }
594*1208bc7eSAndroid Build Coastguard Worker
595*1208bc7eSAndroid Build Coastguard Worker return ret;
596*1208bc7eSAndroid Build Coastguard Worker }
597*1208bc7eSAndroid Build Coastguard Worker
598*1208bc7eSAndroid Build Coastguard Worker void
iarena_cleanup(tsd_t * tsd)599*1208bc7eSAndroid Build Coastguard Worker iarena_cleanup(tsd_t *tsd) {
600*1208bc7eSAndroid Build Coastguard Worker arena_t *iarena;
601*1208bc7eSAndroid Build Coastguard Worker
602*1208bc7eSAndroid Build Coastguard Worker iarena = tsd_iarena_get(tsd);
603*1208bc7eSAndroid Build Coastguard Worker if (iarena != NULL) {
604*1208bc7eSAndroid Build Coastguard Worker arena_unbind(tsd, arena_ind_get(iarena), true);
605*1208bc7eSAndroid Build Coastguard Worker }
606*1208bc7eSAndroid Build Coastguard Worker }
607*1208bc7eSAndroid Build Coastguard Worker
608*1208bc7eSAndroid Build Coastguard Worker void
arena_cleanup(tsd_t * tsd)609*1208bc7eSAndroid Build Coastguard Worker arena_cleanup(tsd_t *tsd) {
610*1208bc7eSAndroid Build Coastguard Worker arena_t *arena;
611*1208bc7eSAndroid Build Coastguard Worker
612*1208bc7eSAndroid Build Coastguard Worker arena = tsd_arena_get(tsd);
613*1208bc7eSAndroid Build Coastguard Worker if (arena != NULL) {
614*1208bc7eSAndroid Build Coastguard Worker arena_unbind(tsd, arena_ind_get(arena), false);
615*1208bc7eSAndroid Build Coastguard Worker }
616*1208bc7eSAndroid Build Coastguard Worker }
617*1208bc7eSAndroid Build Coastguard Worker
618*1208bc7eSAndroid Build Coastguard Worker void
arenas_tdata_cleanup(tsd_t * tsd)619*1208bc7eSAndroid Build Coastguard Worker arenas_tdata_cleanup(tsd_t *tsd) {
620*1208bc7eSAndroid Build Coastguard Worker arena_tdata_t *arenas_tdata;
621*1208bc7eSAndroid Build Coastguard Worker
622*1208bc7eSAndroid Build Coastguard Worker /* Prevent tsd->arenas_tdata from being (re)created. */
623*1208bc7eSAndroid Build Coastguard Worker *tsd_arenas_tdata_bypassp_get(tsd) = true;
624*1208bc7eSAndroid Build Coastguard Worker
625*1208bc7eSAndroid Build Coastguard Worker arenas_tdata = tsd_arenas_tdata_get(tsd);
626*1208bc7eSAndroid Build Coastguard Worker if (arenas_tdata != NULL) {
627*1208bc7eSAndroid Build Coastguard Worker tsd_arenas_tdata_set(tsd, NULL);
628*1208bc7eSAndroid Build Coastguard Worker a0dalloc(arenas_tdata);
629*1208bc7eSAndroid Build Coastguard Worker }
630*1208bc7eSAndroid Build Coastguard Worker }
631*1208bc7eSAndroid Build Coastguard Worker
632*1208bc7eSAndroid Build Coastguard Worker static void
stats_print_atexit(void)633*1208bc7eSAndroid Build Coastguard Worker stats_print_atexit(void) {
634*1208bc7eSAndroid Build Coastguard Worker #if defined(ANDROID_ENABLE_TCACHE)
635*1208bc7eSAndroid Build Coastguard Worker if (config_stats) {
636*1208bc7eSAndroid Build Coastguard Worker tsdn_t *tsdn;
637*1208bc7eSAndroid Build Coastguard Worker unsigned narenas, i;
638*1208bc7eSAndroid Build Coastguard Worker
639*1208bc7eSAndroid Build Coastguard Worker tsdn = tsdn_fetch();
640*1208bc7eSAndroid Build Coastguard Worker
641*1208bc7eSAndroid Build Coastguard Worker /*
642*1208bc7eSAndroid Build Coastguard Worker * Merge stats from extant threads. This is racy, since
643*1208bc7eSAndroid Build Coastguard Worker * individual threads do not lock when recording tcache stats
644*1208bc7eSAndroid Build Coastguard Worker * events. As a consequence, the final stats may be slightly
645*1208bc7eSAndroid Build Coastguard Worker * out of date by the time they are reported, if other threads
646*1208bc7eSAndroid Build Coastguard Worker * continue to allocate.
647*1208bc7eSAndroid Build Coastguard Worker */
648*1208bc7eSAndroid Build Coastguard Worker for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
649*1208bc7eSAndroid Build Coastguard Worker arena_t *arena = arena_get(tsdn, i, false);
650*1208bc7eSAndroid Build Coastguard Worker if (arena != NULL) {
651*1208bc7eSAndroid Build Coastguard Worker tcache_t *tcache;
652*1208bc7eSAndroid Build Coastguard Worker
653*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(tsdn, &arena->tcache_ql_mtx);
654*1208bc7eSAndroid Build Coastguard Worker ql_foreach(tcache, &arena->tcache_ql, link) {
655*1208bc7eSAndroid Build Coastguard Worker tcache_stats_merge(tsdn, tcache, arena);
656*1208bc7eSAndroid Build Coastguard Worker }
657*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsdn,
658*1208bc7eSAndroid Build Coastguard Worker &arena->tcache_ql_mtx);
659*1208bc7eSAndroid Build Coastguard Worker }
660*1208bc7eSAndroid Build Coastguard Worker }
661*1208bc7eSAndroid Build Coastguard Worker }
662*1208bc7eSAndroid Build Coastguard Worker #endif
663*1208bc7eSAndroid Build Coastguard Worker je_malloc_stats_print(NULL, NULL, opt_stats_print_opts);
664*1208bc7eSAndroid Build Coastguard Worker }
665*1208bc7eSAndroid Build Coastguard Worker
666*1208bc7eSAndroid Build Coastguard Worker /*
667*1208bc7eSAndroid Build Coastguard Worker * Ensure that we don't hold any locks upon entry to or exit from allocator
668*1208bc7eSAndroid Build Coastguard Worker * code (in a "broad" sense that doesn't count a reentrant allocation as an
669*1208bc7eSAndroid Build Coastguard Worker * entrance or exit).
670*1208bc7eSAndroid Build Coastguard Worker */
671*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void
check_entry_exit_locking(tsdn_t * tsdn)672*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn_t *tsdn) {
673*1208bc7eSAndroid Build Coastguard Worker if (!config_debug) {
674*1208bc7eSAndroid Build Coastguard Worker return;
675*1208bc7eSAndroid Build Coastguard Worker }
676*1208bc7eSAndroid Build Coastguard Worker if (tsdn_null(tsdn)) {
677*1208bc7eSAndroid Build Coastguard Worker return;
678*1208bc7eSAndroid Build Coastguard Worker }
679*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd = tsdn_tsd(tsdn);
680*1208bc7eSAndroid Build Coastguard Worker /*
681*1208bc7eSAndroid Build Coastguard Worker * It's possible we hold locks at entry/exit if we're in a nested
682*1208bc7eSAndroid Build Coastguard Worker * allocation.
683*1208bc7eSAndroid Build Coastguard Worker */
684*1208bc7eSAndroid Build Coastguard Worker int8_t reentrancy_level = tsd_reentrancy_level_get(tsd);
685*1208bc7eSAndroid Build Coastguard Worker if (reentrancy_level != 0) {
686*1208bc7eSAndroid Build Coastguard Worker return;
687*1208bc7eSAndroid Build Coastguard Worker }
688*1208bc7eSAndroid Build Coastguard Worker witness_assert_lockless(tsdn_witness_tsdp_get(tsdn));
689*1208bc7eSAndroid Build Coastguard Worker }
690*1208bc7eSAndroid Build Coastguard Worker
691*1208bc7eSAndroid Build Coastguard Worker /*
692*1208bc7eSAndroid Build Coastguard Worker * End miscellaneous support functions.
693*1208bc7eSAndroid Build Coastguard Worker */
694*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
695*1208bc7eSAndroid Build Coastguard Worker /*
696*1208bc7eSAndroid Build Coastguard Worker * Begin initialization functions.
697*1208bc7eSAndroid Build Coastguard Worker */
698*1208bc7eSAndroid Build Coastguard Worker
699*1208bc7eSAndroid Build Coastguard Worker static char *
jemalloc_secure_getenv(const char * name)700*1208bc7eSAndroid Build Coastguard Worker jemalloc_secure_getenv(const char *name) {
701*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_HAVE_SECURE_GETENV
702*1208bc7eSAndroid Build Coastguard Worker return secure_getenv(name);
703*1208bc7eSAndroid Build Coastguard Worker #else
704*1208bc7eSAndroid Build Coastguard Worker # ifdef JEMALLOC_HAVE_ISSETUGID
705*1208bc7eSAndroid Build Coastguard Worker if (issetugid() != 0) {
706*1208bc7eSAndroid Build Coastguard Worker return NULL;
707*1208bc7eSAndroid Build Coastguard Worker }
708*1208bc7eSAndroid Build Coastguard Worker # endif
709*1208bc7eSAndroid Build Coastguard Worker return getenv(name);
710*1208bc7eSAndroid Build Coastguard Worker #endif
711*1208bc7eSAndroid Build Coastguard Worker }
712*1208bc7eSAndroid Build Coastguard Worker
713*1208bc7eSAndroid Build Coastguard Worker static unsigned
malloc_ncpus(void)714*1208bc7eSAndroid Build Coastguard Worker malloc_ncpus(void) {
715*1208bc7eSAndroid Build Coastguard Worker long result;
716*1208bc7eSAndroid Build Coastguard Worker
717*1208bc7eSAndroid Build Coastguard Worker #ifdef _WIN32
718*1208bc7eSAndroid Build Coastguard Worker SYSTEM_INFO si;
719*1208bc7eSAndroid Build Coastguard Worker GetSystemInfo(&si);
720*1208bc7eSAndroid Build Coastguard Worker result = si.dwNumberOfProcessors;
721*1208bc7eSAndroid Build Coastguard Worker #elif defined(JEMALLOC_GLIBC_MALLOC_HOOK) && defined(CPU_COUNT)
722*1208bc7eSAndroid Build Coastguard Worker /*
723*1208bc7eSAndroid Build Coastguard Worker * glibc >= 2.6 has the CPU_COUNT macro.
724*1208bc7eSAndroid Build Coastguard Worker *
725*1208bc7eSAndroid Build Coastguard Worker * glibc's sysconf() uses isspace(). glibc allocates for the first time
726*1208bc7eSAndroid Build Coastguard Worker * *before* setting up the isspace tables. Therefore we need a
727*1208bc7eSAndroid Build Coastguard Worker * different method to get the number of CPUs.
728*1208bc7eSAndroid Build Coastguard Worker */
729*1208bc7eSAndroid Build Coastguard Worker {
730*1208bc7eSAndroid Build Coastguard Worker cpu_set_t set;
731*1208bc7eSAndroid Build Coastguard Worker
732*1208bc7eSAndroid Build Coastguard Worker pthread_getaffinity_np(pthread_self(), sizeof(set), &set);
733*1208bc7eSAndroid Build Coastguard Worker result = CPU_COUNT(&set);
734*1208bc7eSAndroid Build Coastguard Worker }
735*1208bc7eSAndroid Build Coastguard Worker #else
736*1208bc7eSAndroid Build Coastguard Worker result = sysconf(_SC_NPROCESSORS_ONLN);
737*1208bc7eSAndroid Build Coastguard Worker #endif
738*1208bc7eSAndroid Build Coastguard Worker return ((result == -1) ? 1 : (unsigned)result);
739*1208bc7eSAndroid Build Coastguard Worker }
740*1208bc7eSAndroid Build Coastguard Worker
741*1208bc7eSAndroid Build Coastguard Worker static void
init_opt_stats_print_opts(const char * v,size_t vlen)742*1208bc7eSAndroid Build Coastguard Worker init_opt_stats_print_opts(const char *v, size_t vlen) {
743*1208bc7eSAndroid Build Coastguard Worker size_t opts_len = strlen(opt_stats_print_opts);
744*1208bc7eSAndroid Build Coastguard Worker assert(opts_len <= stats_print_tot_num_options);
745*1208bc7eSAndroid Build Coastguard Worker
746*1208bc7eSAndroid Build Coastguard Worker for (size_t i = 0; i < vlen; i++) {
747*1208bc7eSAndroid Build Coastguard Worker switch (v[i]) {
748*1208bc7eSAndroid Build Coastguard Worker #define OPTION(o, v, d, s) case o: break;
749*1208bc7eSAndroid Build Coastguard Worker STATS_PRINT_OPTIONS
750*1208bc7eSAndroid Build Coastguard Worker #undef OPTION
751*1208bc7eSAndroid Build Coastguard Worker default: continue;
752*1208bc7eSAndroid Build Coastguard Worker }
753*1208bc7eSAndroid Build Coastguard Worker
754*1208bc7eSAndroid Build Coastguard Worker if (strchr(opt_stats_print_opts, v[i]) != NULL) {
755*1208bc7eSAndroid Build Coastguard Worker /* Ignore repeated. */
756*1208bc7eSAndroid Build Coastguard Worker continue;
757*1208bc7eSAndroid Build Coastguard Worker }
758*1208bc7eSAndroid Build Coastguard Worker
759*1208bc7eSAndroid Build Coastguard Worker opt_stats_print_opts[opts_len++] = v[i];
760*1208bc7eSAndroid Build Coastguard Worker opt_stats_print_opts[opts_len] = '\0';
761*1208bc7eSAndroid Build Coastguard Worker assert(opts_len <= stats_print_tot_num_options);
762*1208bc7eSAndroid Build Coastguard Worker }
763*1208bc7eSAndroid Build Coastguard Worker assert(opts_len == strlen(opt_stats_print_opts));
764*1208bc7eSAndroid Build Coastguard Worker }
765*1208bc7eSAndroid Build Coastguard Worker
766*1208bc7eSAndroid Build Coastguard Worker static bool
malloc_conf_next(char const ** opts_p,char const ** k_p,size_t * klen_p,char const ** v_p,size_t * vlen_p)767*1208bc7eSAndroid Build Coastguard Worker malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p,
768*1208bc7eSAndroid Build Coastguard Worker char const **v_p, size_t *vlen_p) {
769*1208bc7eSAndroid Build Coastguard Worker bool accept;
770*1208bc7eSAndroid Build Coastguard Worker const char *opts = *opts_p;
771*1208bc7eSAndroid Build Coastguard Worker
772*1208bc7eSAndroid Build Coastguard Worker *k_p = opts;
773*1208bc7eSAndroid Build Coastguard Worker
774*1208bc7eSAndroid Build Coastguard Worker for (accept = false; !accept;) {
775*1208bc7eSAndroid Build Coastguard Worker switch (*opts) {
776*1208bc7eSAndroid Build Coastguard Worker case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
777*1208bc7eSAndroid Build Coastguard Worker case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
778*1208bc7eSAndroid Build Coastguard Worker case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
779*1208bc7eSAndroid Build Coastguard Worker case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
780*1208bc7eSAndroid Build Coastguard Worker case 'Y': case 'Z':
781*1208bc7eSAndroid Build Coastguard Worker case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
782*1208bc7eSAndroid Build Coastguard Worker case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
783*1208bc7eSAndroid Build Coastguard Worker case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
784*1208bc7eSAndroid Build Coastguard Worker case 's': case 't': case 'u': case 'v': case 'w': case 'x':
785*1208bc7eSAndroid Build Coastguard Worker case 'y': case 'z':
786*1208bc7eSAndroid Build Coastguard Worker case '0': case '1': case '2': case '3': case '4': case '5':
787*1208bc7eSAndroid Build Coastguard Worker case '6': case '7': case '8': case '9':
788*1208bc7eSAndroid Build Coastguard Worker case '_':
789*1208bc7eSAndroid Build Coastguard Worker opts++;
790*1208bc7eSAndroid Build Coastguard Worker break;
791*1208bc7eSAndroid Build Coastguard Worker case ':':
792*1208bc7eSAndroid Build Coastguard Worker opts++;
793*1208bc7eSAndroid Build Coastguard Worker *klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p;
794*1208bc7eSAndroid Build Coastguard Worker *v_p = opts;
795*1208bc7eSAndroid Build Coastguard Worker accept = true;
796*1208bc7eSAndroid Build Coastguard Worker break;
797*1208bc7eSAndroid Build Coastguard Worker case '\0':
798*1208bc7eSAndroid Build Coastguard Worker if (opts != *opts_p) {
799*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Conf string ends "
800*1208bc7eSAndroid Build Coastguard Worker "with key\n");
801*1208bc7eSAndroid Build Coastguard Worker }
802*1208bc7eSAndroid Build Coastguard Worker return true;
803*1208bc7eSAndroid Build Coastguard Worker default:
804*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Malformed conf string\n");
805*1208bc7eSAndroid Build Coastguard Worker return true;
806*1208bc7eSAndroid Build Coastguard Worker }
807*1208bc7eSAndroid Build Coastguard Worker }
808*1208bc7eSAndroid Build Coastguard Worker
809*1208bc7eSAndroid Build Coastguard Worker for (accept = false; !accept;) {
810*1208bc7eSAndroid Build Coastguard Worker switch (*opts) {
811*1208bc7eSAndroid Build Coastguard Worker case ',':
812*1208bc7eSAndroid Build Coastguard Worker opts++;
813*1208bc7eSAndroid Build Coastguard Worker /*
814*1208bc7eSAndroid Build Coastguard Worker * Look ahead one character here, because the next time
815*1208bc7eSAndroid Build Coastguard Worker * this function is called, it will assume that end of
816*1208bc7eSAndroid Build Coastguard Worker * input has been cleanly reached if no input remains,
817*1208bc7eSAndroid Build Coastguard Worker * but we have optimistically already consumed the
818*1208bc7eSAndroid Build Coastguard Worker * comma if one exists.
819*1208bc7eSAndroid Build Coastguard Worker */
820*1208bc7eSAndroid Build Coastguard Worker if (*opts == '\0') {
821*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Conf string ends "
822*1208bc7eSAndroid Build Coastguard Worker "with comma\n");
823*1208bc7eSAndroid Build Coastguard Worker }
824*1208bc7eSAndroid Build Coastguard Worker *vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p;
825*1208bc7eSAndroid Build Coastguard Worker accept = true;
826*1208bc7eSAndroid Build Coastguard Worker break;
827*1208bc7eSAndroid Build Coastguard Worker case '\0':
828*1208bc7eSAndroid Build Coastguard Worker *vlen_p = (uintptr_t)opts - (uintptr_t)*v_p;
829*1208bc7eSAndroid Build Coastguard Worker accept = true;
830*1208bc7eSAndroid Build Coastguard Worker break;
831*1208bc7eSAndroid Build Coastguard Worker default:
832*1208bc7eSAndroid Build Coastguard Worker opts++;
833*1208bc7eSAndroid Build Coastguard Worker break;
834*1208bc7eSAndroid Build Coastguard Worker }
835*1208bc7eSAndroid Build Coastguard Worker }
836*1208bc7eSAndroid Build Coastguard Worker
837*1208bc7eSAndroid Build Coastguard Worker *opts_p = opts;
838*1208bc7eSAndroid Build Coastguard Worker return false;
839*1208bc7eSAndroid Build Coastguard Worker }
840*1208bc7eSAndroid Build Coastguard Worker
841*1208bc7eSAndroid Build Coastguard Worker static void
malloc_abort_invalid_conf(void)842*1208bc7eSAndroid Build Coastguard Worker malloc_abort_invalid_conf(void) {
843*1208bc7eSAndroid Build Coastguard Worker assert(opt_abort_conf);
844*1208bc7eSAndroid Build Coastguard Worker malloc_printf("<jemalloc>: Abort (abort_conf:true) on invalid conf "
845*1208bc7eSAndroid Build Coastguard Worker "value (see above).\n");
846*1208bc7eSAndroid Build Coastguard Worker abort();
847*1208bc7eSAndroid Build Coastguard Worker }
848*1208bc7eSAndroid Build Coastguard Worker
849*1208bc7eSAndroid Build Coastguard Worker static void
malloc_conf_error(const char * msg,const char * k,size_t klen,const char * v,size_t vlen)850*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v,
851*1208bc7eSAndroid Build Coastguard Worker size_t vlen) {
852*1208bc7eSAndroid Build Coastguard Worker malloc_printf("<jemalloc>: %s: %.*s:%.*s\n", msg, (int)klen, k,
853*1208bc7eSAndroid Build Coastguard Worker (int)vlen, v);
854*1208bc7eSAndroid Build Coastguard Worker /* If abort_conf is set, error out after processing all options. */
855*1208bc7eSAndroid Build Coastguard Worker had_conf_error = true;
856*1208bc7eSAndroid Build Coastguard Worker }
857*1208bc7eSAndroid Build Coastguard Worker
858*1208bc7eSAndroid Build Coastguard Worker static void
malloc_slow_flag_init(void)859*1208bc7eSAndroid Build Coastguard Worker malloc_slow_flag_init(void) {
860*1208bc7eSAndroid Build Coastguard Worker /*
861*1208bc7eSAndroid Build Coastguard Worker * Combine the runtime options into malloc_slow for fast path. Called
862*1208bc7eSAndroid Build Coastguard Worker * after processing all the options.
863*1208bc7eSAndroid Build Coastguard Worker */
864*1208bc7eSAndroid Build Coastguard Worker malloc_slow_flags |= (opt_junk_alloc ? flag_opt_junk_alloc : 0)
865*1208bc7eSAndroid Build Coastguard Worker | (opt_junk_free ? flag_opt_junk_free : 0)
866*1208bc7eSAndroid Build Coastguard Worker | (opt_zero ? flag_opt_zero : 0)
867*1208bc7eSAndroid Build Coastguard Worker | (opt_utrace ? flag_opt_utrace : 0)
868*1208bc7eSAndroid Build Coastguard Worker | (opt_xmalloc ? flag_opt_xmalloc : 0);
869*1208bc7eSAndroid Build Coastguard Worker
870*1208bc7eSAndroid Build Coastguard Worker malloc_slow = (malloc_slow_flags != 0);
871*1208bc7eSAndroid Build Coastguard Worker }
872*1208bc7eSAndroid Build Coastguard Worker
873*1208bc7eSAndroid Build Coastguard Worker static void
malloc_conf_init(void)874*1208bc7eSAndroid Build Coastguard Worker malloc_conf_init(void) {
875*1208bc7eSAndroid Build Coastguard Worker unsigned i;
876*1208bc7eSAndroid Build Coastguard Worker char buf[PATH_MAX + 1];
877*1208bc7eSAndroid Build Coastguard Worker const char *opts, *k, *v;
878*1208bc7eSAndroid Build Coastguard Worker size_t klen, vlen;
879*1208bc7eSAndroid Build Coastguard Worker
880*1208bc7eSAndroid Build Coastguard Worker #if defined(__BIONIC__)
881*1208bc7eSAndroid Build Coastguard Worker /* For Android, do not look at files nor environment variables for
882*1208bc7eSAndroid Build Coastguard Worker * config data.
883*1208bc7eSAndroid Build Coastguard Worker */
884*1208bc7eSAndroid Build Coastguard Worker for (i = 0; i < 2; i++) {
885*1208bc7eSAndroid Build Coastguard Worker #else
886*1208bc7eSAndroid Build Coastguard Worker for (i = 0; i < 4; i++) {
887*1208bc7eSAndroid Build Coastguard Worker #endif
888*1208bc7eSAndroid Build Coastguard Worker /* Get runtime configuration. */
889*1208bc7eSAndroid Build Coastguard Worker switch (i) {
890*1208bc7eSAndroid Build Coastguard Worker case 0:
891*1208bc7eSAndroid Build Coastguard Worker opts = config_malloc_conf;
892*1208bc7eSAndroid Build Coastguard Worker break;
893*1208bc7eSAndroid Build Coastguard Worker case 1:
894*1208bc7eSAndroid Build Coastguard Worker if (je_malloc_conf != NULL) {
895*1208bc7eSAndroid Build Coastguard Worker /*
896*1208bc7eSAndroid Build Coastguard Worker * Use options that were compiled into the
897*1208bc7eSAndroid Build Coastguard Worker * program.
898*1208bc7eSAndroid Build Coastguard Worker */
899*1208bc7eSAndroid Build Coastguard Worker opts = je_malloc_conf;
900*1208bc7eSAndroid Build Coastguard Worker } else {
901*1208bc7eSAndroid Build Coastguard Worker /* No configuration specified. */
902*1208bc7eSAndroid Build Coastguard Worker buf[0] = '\0';
903*1208bc7eSAndroid Build Coastguard Worker opts = buf;
904*1208bc7eSAndroid Build Coastguard Worker }
905*1208bc7eSAndroid Build Coastguard Worker break;
906*1208bc7eSAndroid Build Coastguard Worker case 2: {
907*1208bc7eSAndroid Build Coastguard Worker ssize_t linklen = 0;
908*1208bc7eSAndroid Build Coastguard Worker #ifndef _WIN32
909*1208bc7eSAndroid Build Coastguard Worker int saved_errno = errno;
910*1208bc7eSAndroid Build Coastguard Worker const char *linkname =
911*1208bc7eSAndroid Build Coastguard Worker # ifdef JEMALLOC_PREFIX
912*1208bc7eSAndroid Build Coastguard Worker "/etc/"JEMALLOC_PREFIX"malloc.conf"
913*1208bc7eSAndroid Build Coastguard Worker # else
914*1208bc7eSAndroid Build Coastguard Worker "/etc/malloc.conf"
915*1208bc7eSAndroid Build Coastguard Worker # endif
916*1208bc7eSAndroid Build Coastguard Worker ;
917*1208bc7eSAndroid Build Coastguard Worker
918*1208bc7eSAndroid Build Coastguard Worker /*
919*1208bc7eSAndroid Build Coastguard Worker * Try to use the contents of the "/etc/malloc.conf"
920*1208bc7eSAndroid Build Coastguard Worker * symbolic link's name.
921*1208bc7eSAndroid Build Coastguard Worker */
922*1208bc7eSAndroid Build Coastguard Worker linklen = readlink(linkname, buf, sizeof(buf) - 1);
923*1208bc7eSAndroid Build Coastguard Worker if (linklen == -1) {
924*1208bc7eSAndroid Build Coastguard Worker /* No configuration specified. */
925*1208bc7eSAndroid Build Coastguard Worker linklen = 0;
926*1208bc7eSAndroid Build Coastguard Worker /* Restore errno. */
927*1208bc7eSAndroid Build Coastguard Worker set_errno(saved_errno);
928*1208bc7eSAndroid Build Coastguard Worker }
929*1208bc7eSAndroid Build Coastguard Worker #endif
930*1208bc7eSAndroid Build Coastguard Worker buf[linklen] = '\0';
931*1208bc7eSAndroid Build Coastguard Worker opts = buf;
932*1208bc7eSAndroid Build Coastguard Worker break;
933*1208bc7eSAndroid Build Coastguard Worker } case 3: {
934*1208bc7eSAndroid Build Coastguard Worker const char *envname =
935*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_PREFIX
936*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_CPREFIX"MALLOC_CONF"
937*1208bc7eSAndroid Build Coastguard Worker #else
938*1208bc7eSAndroid Build Coastguard Worker "MALLOC_CONF"
939*1208bc7eSAndroid Build Coastguard Worker #endif
940*1208bc7eSAndroid Build Coastguard Worker ;
941*1208bc7eSAndroid Build Coastguard Worker
942*1208bc7eSAndroid Build Coastguard Worker if ((opts = jemalloc_secure_getenv(envname)) != NULL) {
943*1208bc7eSAndroid Build Coastguard Worker /*
944*1208bc7eSAndroid Build Coastguard Worker * Do nothing; opts is already initialized to
945*1208bc7eSAndroid Build Coastguard Worker * the value of the MALLOC_CONF environment
946*1208bc7eSAndroid Build Coastguard Worker * variable.
947*1208bc7eSAndroid Build Coastguard Worker */
948*1208bc7eSAndroid Build Coastguard Worker } else {
949*1208bc7eSAndroid Build Coastguard Worker /* No configuration specified. */
950*1208bc7eSAndroid Build Coastguard Worker buf[0] = '\0';
951*1208bc7eSAndroid Build Coastguard Worker opts = buf;
952*1208bc7eSAndroid Build Coastguard Worker }
953*1208bc7eSAndroid Build Coastguard Worker break;
954*1208bc7eSAndroid Build Coastguard Worker } default:
955*1208bc7eSAndroid Build Coastguard Worker not_reached();
956*1208bc7eSAndroid Build Coastguard Worker buf[0] = '\0';
957*1208bc7eSAndroid Build Coastguard Worker opts = buf;
958*1208bc7eSAndroid Build Coastguard Worker }
959*1208bc7eSAndroid Build Coastguard Worker
960*1208bc7eSAndroid Build Coastguard Worker while (*opts != '\0' && !malloc_conf_next(&opts, &k, &klen, &v,
961*1208bc7eSAndroid Build Coastguard Worker &vlen)) {
962*1208bc7eSAndroid Build Coastguard Worker #define CONF_MATCH(n) \
963*1208bc7eSAndroid Build Coastguard Worker (sizeof(n)-1 == klen && strncmp(n, k, klen) == 0)
964*1208bc7eSAndroid Build Coastguard Worker #define CONF_MATCH_VALUE(n) \
965*1208bc7eSAndroid Build Coastguard Worker (sizeof(n)-1 == vlen && strncmp(n, v, vlen) == 0)
966*1208bc7eSAndroid Build Coastguard Worker #define CONF_HANDLE_BOOL(o, n) \
967*1208bc7eSAndroid Build Coastguard Worker if (CONF_MATCH(n)) { \
968*1208bc7eSAndroid Build Coastguard Worker if (CONF_MATCH_VALUE("true")) { \
969*1208bc7eSAndroid Build Coastguard Worker o = true; \
970*1208bc7eSAndroid Build Coastguard Worker } else if (CONF_MATCH_VALUE("false")) { \
971*1208bc7eSAndroid Build Coastguard Worker o = false; \
972*1208bc7eSAndroid Build Coastguard Worker } else { \
973*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error( \
974*1208bc7eSAndroid Build Coastguard Worker "Invalid conf value", \
975*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen); \
976*1208bc7eSAndroid Build Coastguard Worker } \
977*1208bc7eSAndroid Build Coastguard Worker continue; \
978*1208bc7eSAndroid Build Coastguard Worker }
979*1208bc7eSAndroid Build Coastguard Worker #define CONF_MIN_no(um, min) false
980*1208bc7eSAndroid Build Coastguard Worker #define CONF_MIN_yes(um, min) ((um) < (min))
981*1208bc7eSAndroid Build Coastguard Worker #define CONF_MAX_no(um, max) false
982*1208bc7eSAndroid Build Coastguard Worker #define CONF_MAX_yes(um, max) ((um) > (max))
983*1208bc7eSAndroid Build Coastguard Worker #define CONF_HANDLE_T_U(t, o, n, min, max, check_min, check_max, clip) \
984*1208bc7eSAndroid Build Coastguard Worker if (CONF_MATCH(n)) { \
985*1208bc7eSAndroid Build Coastguard Worker uintmax_t um; \
986*1208bc7eSAndroid Build Coastguard Worker char *end; \
987*1208bc7eSAndroid Build Coastguard Worker \
988*1208bc7eSAndroid Build Coastguard Worker set_errno(0); \
989*1208bc7eSAndroid Build Coastguard Worker um = malloc_strtoumax(v, &end, 0); \
990*1208bc7eSAndroid Build Coastguard Worker if (get_errno() != 0 || (uintptr_t)end -\
991*1208bc7eSAndroid Build Coastguard Worker (uintptr_t)v != vlen) { \
992*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error( \
993*1208bc7eSAndroid Build Coastguard Worker "Invalid conf value", \
994*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen); \
995*1208bc7eSAndroid Build Coastguard Worker } else if (clip) { \
996*1208bc7eSAndroid Build Coastguard Worker if (CONF_MIN_##check_min(um, \
997*1208bc7eSAndroid Build Coastguard Worker (t)(min))) { \
998*1208bc7eSAndroid Build Coastguard Worker o = (t)(min); \
999*1208bc7eSAndroid Build Coastguard Worker } else if ( \
1000*1208bc7eSAndroid Build Coastguard Worker CONF_MAX_##check_max(um, \
1001*1208bc7eSAndroid Build Coastguard Worker (t)(max))) { \
1002*1208bc7eSAndroid Build Coastguard Worker o = (t)(max); \
1003*1208bc7eSAndroid Build Coastguard Worker } else { \
1004*1208bc7eSAndroid Build Coastguard Worker o = (t)um; \
1005*1208bc7eSAndroid Build Coastguard Worker } \
1006*1208bc7eSAndroid Build Coastguard Worker } else { \
1007*1208bc7eSAndroid Build Coastguard Worker if (CONF_MIN_##check_min(um, \
1008*1208bc7eSAndroid Build Coastguard Worker (t)(min)) || \
1009*1208bc7eSAndroid Build Coastguard Worker CONF_MAX_##check_max(um, \
1010*1208bc7eSAndroid Build Coastguard Worker (t)(max))) { \
1011*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error( \
1012*1208bc7eSAndroid Build Coastguard Worker "Out-of-range " \
1013*1208bc7eSAndroid Build Coastguard Worker "conf value", \
1014*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen); \
1015*1208bc7eSAndroid Build Coastguard Worker } else { \
1016*1208bc7eSAndroid Build Coastguard Worker o = (t)um; \
1017*1208bc7eSAndroid Build Coastguard Worker } \
1018*1208bc7eSAndroid Build Coastguard Worker } \
1019*1208bc7eSAndroid Build Coastguard Worker continue; \
1020*1208bc7eSAndroid Build Coastguard Worker }
1021*1208bc7eSAndroid Build Coastguard Worker #define CONF_HANDLE_UNSIGNED(o, n, min, max, check_min, check_max, \
1022*1208bc7eSAndroid Build Coastguard Worker clip) \
1023*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_T_U(unsigned, o, n, min, max, \
1024*1208bc7eSAndroid Build Coastguard Worker check_min, check_max, clip)
1025*1208bc7eSAndroid Build Coastguard Worker #define CONF_HANDLE_SIZE_T(o, n, min, max, check_min, check_max, clip) \
1026*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_T_U(size_t, o, n, min, max, \
1027*1208bc7eSAndroid Build Coastguard Worker check_min, check_max, clip)
1028*1208bc7eSAndroid Build Coastguard Worker #define CONF_HANDLE_SSIZE_T(o, n, min, max) \
1029*1208bc7eSAndroid Build Coastguard Worker if (CONF_MATCH(n)) { \
1030*1208bc7eSAndroid Build Coastguard Worker long l; \
1031*1208bc7eSAndroid Build Coastguard Worker char *end; \
1032*1208bc7eSAndroid Build Coastguard Worker \
1033*1208bc7eSAndroid Build Coastguard Worker set_errno(0); \
1034*1208bc7eSAndroid Build Coastguard Worker l = strtol(v, &end, 0); \
1035*1208bc7eSAndroid Build Coastguard Worker if (get_errno() != 0 || (uintptr_t)end -\
1036*1208bc7eSAndroid Build Coastguard Worker (uintptr_t)v != vlen) { \
1037*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error( \
1038*1208bc7eSAndroid Build Coastguard Worker "Invalid conf value", \
1039*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen); \
1040*1208bc7eSAndroid Build Coastguard Worker } else if (l < (ssize_t)(min) || l > \
1041*1208bc7eSAndroid Build Coastguard Worker (ssize_t)(max)) { \
1042*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error( \
1043*1208bc7eSAndroid Build Coastguard Worker "Out-of-range conf value", \
1044*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen); \
1045*1208bc7eSAndroid Build Coastguard Worker } else { \
1046*1208bc7eSAndroid Build Coastguard Worker o = l; \
1047*1208bc7eSAndroid Build Coastguard Worker } \
1048*1208bc7eSAndroid Build Coastguard Worker continue; \
1049*1208bc7eSAndroid Build Coastguard Worker }
1050*1208bc7eSAndroid Build Coastguard Worker #define CONF_HANDLE_CHAR_P(o, n, d) \
1051*1208bc7eSAndroid Build Coastguard Worker if (CONF_MATCH(n)) { \
1052*1208bc7eSAndroid Build Coastguard Worker size_t cpylen = (vlen <= \
1053*1208bc7eSAndroid Build Coastguard Worker sizeof(o)-1) ? vlen : \
1054*1208bc7eSAndroid Build Coastguard Worker sizeof(o)-1; \
1055*1208bc7eSAndroid Build Coastguard Worker strncpy(o, v, cpylen); \
1056*1208bc7eSAndroid Build Coastguard Worker o[cpylen] = '\0'; \
1057*1208bc7eSAndroid Build Coastguard Worker continue; \
1058*1208bc7eSAndroid Build Coastguard Worker }
1059*1208bc7eSAndroid Build Coastguard Worker
1060*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_abort, "abort")
1061*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_abort_conf, "abort_conf")
1062*1208bc7eSAndroid Build Coastguard Worker if (strncmp("metadata_thp", k, klen) == 0) {
1063*1208bc7eSAndroid Build Coastguard Worker int i;
1064*1208bc7eSAndroid Build Coastguard Worker bool match = false;
1065*1208bc7eSAndroid Build Coastguard Worker for (i = 0; i < metadata_thp_mode_limit; i++) {
1066*1208bc7eSAndroid Build Coastguard Worker if (strncmp(metadata_thp_mode_names[i],
1067*1208bc7eSAndroid Build Coastguard Worker v, vlen) == 0) {
1068*1208bc7eSAndroid Build Coastguard Worker opt_metadata_thp = i;
1069*1208bc7eSAndroid Build Coastguard Worker match = true;
1070*1208bc7eSAndroid Build Coastguard Worker break;
1071*1208bc7eSAndroid Build Coastguard Worker }
1072*1208bc7eSAndroid Build Coastguard Worker }
1073*1208bc7eSAndroid Build Coastguard Worker if (!match) {
1074*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error("Invalid conf value",
1075*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen);
1076*1208bc7eSAndroid Build Coastguard Worker }
1077*1208bc7eSAndroid Build Coastguard Worker continue;
1078*1208bc7eSAndroid Build Coastguard Worker }
1079*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_retain, "retain")
1080*1208bc7eSAndroid Build Coastguard Worker if (strncmp("dss", k, klen) == 0) {
1081*1208bc7eSAndroid Build Coastguard Worker int i;
1082*1208bc7eSAndroid Build Coastguard Worker bool match = false;
1083*1208bc7eSAndroid Build Coastguard Worker for (i = 0; i < dss_prec_limit; i++) {
1084*1208bc7eSAndroid Build Coastguard Worker if (strncmp(dss_prec_names[i], v, vlen)
1085*1208bc7eSAndroid Build Coastguard Worker == 0) {
1086*1208bc7eSAndroid Build Coastguard Worker if (extent_dss_prec_set(i)) {
1087*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error(
1088*1208bc7eSAndroid Build Coastguard Worker "Error setting dss",
1089*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen);
1090*1208bc7eSAndroid Build Coastguard Worker } else {
1091*1208bc7eSAndroid Build Coastguard Worker opt_dss =
1092*1208bc7eSAndroid Build Coastguard Worker dss_prec_names[i];
1093*1208bc7eSAndroid Build Coastguard Worker match = true;
1094*1208bc7eSAndroid Build Coastguard Worker break;
1095*1208bc7eSAndroid Build Coastguard Worker }
1096*1208bc7eSAndroid Build Coastguard Worker }
1097*1208bc7eSAndroid Build Coastguard Worker }
1098*1208bc7eSAndroid Build Coastguard Worker if (!match) {
1099*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error("Invalid conf value",
1100*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen);
1101*1208bc7eSAndroid Build Coastguard Worker }
1102*1208bc7eSAndroid Build Coastguard Worker continue;
1103*1208bc7eSAndroid Build Coastguard Worker }
1104*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_UNSIGNED(opt_narenas, "narenas", 1,
1105*1208bc7eSAndroid Build Coastguard Worker UINT_MAX, yes, no, false)
1106*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_SSIZE_T(opt_dirty_decay_ms,
1107*1208bc7eSAndroid Build Coastguard Worker "dirty_decay_ms", -1, NSTIME_SEC_MAX * KQU(1000) <
1108*1208bc7eSAndroid Build Coastguard Worker QU(SSIZE_MAX) ? NSTIME_SEC_MAX * KQU(1000) :
1109*1208bc7eSAndroid Build Coastguard Worker SSIZE_MAX);
1110*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_SSIZE_T(opt_muzzy_decay_ms,
1111*1208bc7eSAndroid Build Coastguard Worker "muzzy_decay_ms", -1, NSTIME_SEC_MAX * KQU(1000) <
1112*1208bc7eSAndroid Build Coastguard Worker QU(SSIZE_MAX) ? NSTIME_SEC_MAX * KQU(1000) :
1113*1208bc7eSAndroid Build Coastguard Worker SSIZE_MAX);
1114*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_stats_print, "stats_print")
1115*1208bc7eSAndroid Build Coastguard Worker if (CONF_MATCH("stats_print_opts")) {
1116*1208bc7eSAndroid Build Coastguard Worker init_opt_stats_print_opts(v, vlen);
1117*1208bc7eSAndroid Build Coastguard Worker continue;
1118*1208bc7eSAndroid Build Coastguard Worker }
1119*1208bc7eSAndroid Build Coastguard Worker if (config_fill) {
1120*1208bc7eSAndroid Build Coastguard Worker if (CONF_MATCH("junk")) {
1121*1208bc7eSAndroid Build Coastguard Worker if (CONF_MATCH_VALUE("true")) {
1122*1208bc7eSAndroid Build Coastguard Worker opt_junk = "true";
1123*1208bc7eSAndroid Build Coastguard Worker opt_junk_alloc = opt_junk_free =
1124*1208bc7eSAndroid Build Coastguard Worker true;
1125*1208bc7eSAndroid Build Coastguard Worker } else if (CONF_MATCH_VALUE("false")) {
1126*1208bc7eSAndroid Build Coastguard Worker opt_junk = "false";
1127*1208bc7eSAndroid Build Coastguard Worker opt_junk_alloc = opt_junk_free =
1128*1208bc7eSAndroid Build Coastguard Worker false;
1129*1208bc7eSAndroid Build Coastguard Worker } else if (CONF_MATCH_VALUE("alloc")) {
1130*1208bc7eSAndroid Build Coastguard Worker opt_junk = "alloc";
1131*1208bc7eSAndroid Build Coastguard Worker opt_junk_alloc = true;
1132*1208bc7eSAndroid Build Coastguard Worker opt_junk_free = false;
1133*1208bc7eSAndroid Build Coastguard Worker } else if (CONF_MATCH_VALUE("free")) {
1134*1208bc7eSAndroid Build Coastguard Worker opt_junk = "free";
1135*1208bc7eSAndroid Build Coastguard Worker opt_junk_alloc = false;
1136*1208bc7eSAndroid Build Coastguard Worker opt_junk_free = true;
1137*1208bc7eSAndroid Build Coastguard Worker } else {
1138*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error(
1139*1208bc7eSAndroid Build Coastguard Worker "Invalid conf value", k,
1140*1208bc7eSAndroid Build Coastguard Worker klen, v, vlen);
1141*1208bc7eSAndroid Build Coastguard Worker }
1142*1208bc7eSAndroid Build Coastguard Worker continue;
1143*1208bc7eSAndroid Build Coastguard Worker }
1144*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_zero, "zero")
1145*1208bc7eSAndroid Build Coastguard Worker }
1146*1208bc7eSAndroid Build Coastguard Worker if (config_utrace) {
1147*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_utrace, "utrace")
1148*1208bc7eSAndroid Build Coastguard Worker }
1149*1208bc7eSAndroid Build Coastguard Worker if (config_xmalloc) {
1150*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_xmalloc, "xmalloc")
1151*1208bc7eSAndroid Build Coastguard Worker }
1152*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_tcache, "tcache")
1153*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_SIZE_T(opt_lg_extent_max_active_fit,
1154*1208bc7eSAndroid Build Coastguard Worker "lg_extent_max_active_fit", 0,
1155*1208bc7eSAndroid Build Coastguard Worker (sizeof(size_t) << 3), yes, yes, false)
1156*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_SSIZE_T(opt_lg_tcache_max, "lg_tcache_max",
1157*1208bc7eSAndroid Build Coastguard Worker -1, (sizeof(size_t) << 3) - 1)
1158*1208bc7eSAndroid Build Coastguard Worker if (strncmp("percpu_arena", k, klen) == 0) {
1159*1208bc7eSAndroid Build Coastguard Worker bool match = false;
1160*1208bc7eSAndroid Build Coastguard Worker for (int i = percpu_arena_mode_names_base; i <
1161*1208bc7eSAndroid Build Coastguard Worker percpu_arena_mode_names_limit; i++) {
1162*1208bc7eSAndroid Build Coastguard Worker if (strncmp(percpu_arena_mode_names[i],
1163*1208bc7eSAndroid Build Coastguard Worker v, vlen) == 0) {
1164*1208bc7eSAndroid Build Coastguard Worker if (!have_percpu_arena) {
1165*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error(
1166*1208bc7eSAndroid Build Coastguard Worker "No getcpu support",
1167*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen);
1168*1208bc7eSAndroid Build Coastguard Worker }
1169*1208bc7eSAndroid Build Coastguard Worker opt_percpu_arena = i;
1170*1208bc7eSAndroid Build Coastguard Worker match = true;
1171*1208bc7eSAndroid Build Coastguard Worker break;
1172*1208bc7eSAndroid Build Coastguard Worker }
1173*1208bc7eSAndroid Build Coastguard Worker }
1174*1208bc7eSAndroid Build Coastguard Worker if (!match) {
1175*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error("Invalid conf value",
1176*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen);
1177*1208bc7eSAndroid Build Coastguard Worker }
1178*1208bc7eSAndroid Build Coastguard Worker continue;
1179*1208bc7eSAndroid Build Coastguard Worker }
1180*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_background_thread,
1181*1208bc7eSAndroid Build Coastguard Worker "background_thread");
1182*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_SIZE_T(opt_max_background_threads,
1183*1208bc7eSAndroid Build Coastguard Worker "max_background_threads", 1,
1184*1208bc7eSAndroid Build Coastguard Worker opt_max_background_threads, yes, yes,
1185*1208bc7eSAndroid Build Coastguard Worker true);
1186*1208bc7eSAndroid Build Coastguard Worker if (config_prof) {
1187*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_prof, "prof")
1188*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_CHAR_P(opt_prof_prefix,
1189*1208bc7eSAndroid Build Coastguard Worker "prof_prefix", "jeprof")
1190*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_prof_active, "prof_active")
1191*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_prof_thread_active_init,
1192*1208bc7eSAndroid Build Coastguard Worker "prof_thread_active_init")
1193*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_SIZE_T(opt_lg_prof_sample,
1194*1208bc7eSAndroid Build Coastguard Worker "lg_prof_sample", 0, (sizeof(uint64_t) << 3)
1195*1208bc7eSAndroid Build Coastguard Worker - 1, no, yes, true)
1196*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum")
1197*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_SSIZE_T(opt_lg_prof_interval,
1198*1208bc7eSAndroid Build Coastguard Worker "lg_prof_interval", -1,
1199*1208bc7eSAndroid Build Coastguard Worker (sizeof(uint64_t) << 3) - 1)
1200*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump")
1201*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_prof_final, "prof_final")
1202*1208bc7eSAndroid Build Coastguard Worker CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak")
1203*1208bc7eSAndroid Build Coastguard Worker }
1204*1208bc7eSAndroid Build Coastguard Worker if (config_log) {
1205*1208bc7eSAndroid Build Coastguard Worker if (CONF_MATCH("log")) {
1206*1208bc7eSAndroid Build Coastguard Worker size_t cpylen = (
1207*1208bc7eSAndroid Build Coastguard Worker vlen <= sizeof(log_var_names) ?
1208*1208bc7eSAndroid Build Coastguard Worker vlen : sizeof(log_var_names) - 1);
1209*1208bc7eSAndroid Build Coastguard Worker strncpy(log_var_names, v, cpylen);
1210*1208bc7eSAndroid Build Coastguard Worker log_var_names[cpylen] = '\0';
1211*1208bc7eSAndroid Build Coastguard Worker continue;
1212*1208bc7eSAndroid Build Coastguard Worker }
1213*1208bc7eSAndroid Build Coastguard Worker }
1214*1208bc7eSAndroid Build Coastguard Worker if (CONF_MATCH("thp")) {
1215*1208bc7eSAndroid Build Coastguard Worker bool match = false;
1216*1208bc7eSAndroid Build Coastguard Worker for (int i = 0; i < thp_mode_names_limit; i++) {
1217*1208bc7eSAndroid Build Coastguard Worker if (strncmp(thp_mode_names[i],v, vlen)
1218*1208bc7eSAndroid Build Coastguard Worker == 0) {
1219*1208bc7eSAndroid Build Coastguard Worker if (!have_madvise_huge) {
1220*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error(
1221*1208bc7eSAndroid Build Coastguard Worker "No THP support",
1222*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen);
1223*1208bc7eSAndroid Build Coastguard Worker }
1224*1208bc7eSAndroid Build Coastguard Worker opt_thp = i;
1225*1208bc7eSAndroid Build Coastguard Worker match = true;
1226*1208bc7eSAndroid Build Coastguard Worker break;
1227*1208bc7eSAndroid Build Coastguard Worker }
1228*1208bc7eSAndroid Build Coastguard Worker }
1229*1208bc7eSAndroid Build Coastguard Worker if (!match) {
1230*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error("Invalid conf value",
1231*1208bc7eSAndroid Build Coastguard Worker k, klen, v, vlen);
1232*1208bc7eSAndroid Build Coastguard Worker }
1233*1208bc7eSAndroid Build Coastguard Worker continue;
1234*1208bc7eSAndroid Build Coastguard Worker }
1235*1208bc7eSAndroid Build Coastguard Worker malloc_conf_error("Invalid conf pair", k, klen, v,
1236*1208bc7eSAndroid Build Coastguard Worker vlen);
1237*1208bc7eSAndroid Build Coastguard Worker #undef CONF_MATCH
1238*1208bc7eSAndroid Build Coastguard Worker #undef CONF_MATCH_VALUE
1239*1208bc7eSAndroid Build Coastguard Worker #undef CONF_HANDLE_BOOL
1240*1208bc7eSAndroid Build Coastguard Worker #undef CONF_MIN_no
1241*1208bc7eSAndroid Build Coastguard Worker #undef CONF_MIN_yes
1242*1208bc7eSAndroid Build Coastguard Worker #undef CONF_MAX_no
1243*1208bc7eSAndroid Build Coastguard Worker #undef CONF_MAX_yes
1244*1208bc7eSAndroid Build Coastguard Worker #undef CONF_HANDLE_T_U
1245*1208bc7eSAndroid Build Coastguard Worker #undef CONF_HANDLE_UNSIGNED
1246*1208bc7eSAndroid Build Coastguard Worker #undef CONF_HANDLE_SIZE_T
1247*1208bc7eSAndroid Build Coastguard Worker #undef CONF_HANDLE_SSIZE_T
1248*1208bc7eSAndroid Build Coastguard Worker #undef CONF_HANDLE_CHAR_P
1249*1208bc7eSAndroid Build Coastguard Worker }
1250*1208bc7eSAndroid Build Coastguard Worker if (opt_abort_conf && had_conf_error) {
1251*1208bc7eSAndroid Build Coastguard Worker malloc_abort_invalid_conf();
1252*1208bc7eSAndroid Build Coastguard Worker }
1253*1208bc7eSAndroid Build Coastguard Worker }
1254*1208bc7eSAndroid Build Coastguard Worker atomic_store_b(&log_init_done, true, ATOMIC_RELEASE);
1255*1208bc7eSAndroid Build Coastguard Worker }
1256*1208bc7eSAndroid Build Coastguard Worker
1257*1208bc7eSAndroid Build Coastguard Worker static bool
1258*1208bc7eSAndroid Build Coastguard Worker malloc_init_hard_needed(void) {
1259*1208bc7eSAndroid Build Coastguard Worker if (malloc_initialized() || (IS_INITIALIZER && malloc_init_state ==
1260*1208bc7eSAndroid Build Coastguard Worker malloc_init_recursible)) {
1261*1208bc7eSAndroid Build Coastguard Worker /*
1262*1208bc7eSAndroid Build Coastguard Worker * Another thread initialized the allocator before this one
1263*1208bc7eSAndroid Build Coastguard Worker * acquired init_lock, or this thread is the initializing
1264*1208bc7eSAndroid Build Coastguard Worker * thread, and it is recursively allocating.
1265*1208bc7eSAndroid Build Coastguard Worker */
1266*1208bc7eSAndroid Build Coastguard Worker return false;
1267*1208bc7eSAndroid Build Coastguard Worker }
1268*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_THREADED_INIT
1269*1208bc7eSAndroid Build Coastguard Worker if (malloc_initializer != NO_INITIALIZER && !IS_INITIALIZER) {
1270*1208bc7eSAndroid Build Coastguard Worker /* Busy-wait until the initializing thread completes. */
1271*1208bc7eSAndroid Build Coastguard Worker spin_t spinner = SPIN_INITIALIZER;
1272*1208bc7eSAndroid Build Coastguard Worker do {
1273*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(TSDN_NULL, &init_lock);
1274*1208bc7eSAndroid Build Coastguard Worker spin_adaptive(&spinner);
1275*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(TSDN_NULL, &init_lock);
1276*1208bc7eSAndroid Build Coastguard Worker } while (!malloc_initialized());
1277*1208bc7eSAndroid Build Coastguard Worker return false;
1278*1208bc7eSAndroid Build Coastguard Worker }
1279*1208bc7eSAndroid Build Coastguard Worker #endif
1280*1208bc7eSAndroid Build Coastguard Worker return true;
1281*1208bc7eSAndroid Build Coastguard Worker }
1282*1208bc7eSAndroid Build Coastguard Worker
1283*1208bc7eSAndroid Build Coastguard Worker static bool
1284*1208bc7eSAndroid Build Coastguard Worker malloc_init_hard_a0_locked() {
1285*1208bc7eSAndroid Build Coastguard Worker malloc_initializer = INITIALIZER;
1286*1208bc7eSAndroid Build Coastguard Worker
1287*1208bc7eSAndroid Build Coastguard Worker if (config_prof) {
1288*1208bc7eSAndroid Build Coastguard Worker prof_boot0();
1289*1208bc7eSAndroid Build Coastguard Worker }
1290*1208bc7eSAndroid Build Coastguard Worker malloc_conf_init();
1291*1208bc7eSAndroid Build Coastguard Worker if (opt_stats_print) {
1292*1208bc7eSAndroid Build Coastguard Worker /* Print statistics at exit. */
1293*1208bc7eSAndroid Build Coastguard Worker if (atexit(stats_print_atexit) != 0) {
1294*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Error in atexit()\n");
1295*1208bc7eSAndroid Build Coastguard Worker if (opt_abort) {
1296*1208bc7eSAndroid Build Coastguard Worker abort();
1297*1208bc7eSAndroid Build Coastguard Worker }
1298*1208bc7eSAndroid Build Coastguard Worker }
1299*1208bc7eSAndroid Build Coastguard Worker }
1300*1208bc7eSAndroid Build Coastguard Worker if (pages_boot()) {
1301*1208bc7eSAndroid Build Coastguard Worker return true;
1302*1208bc7eSAndroid Build Coastguard Worker }
1303*1208bc7eSAndroid Build Coastguard Worker if (base_boot(TSDN_NULL)) {
1304*1208bc7eSAndroid Build Coastguard Worker return true;
1305*1208bc7eSAndroid Build Coastguard Worker }
1306*1208bc7eSAndroid Build Coastguard Worker if (extent_boot()) {
1307*1208bc7eSAndroid Build Coastguard Worker return true;
1308*1208bc7eSAndroid Build Coastguard Worker }
1309*1208bc7eSAndroid Build Coastguard Worker if (ctl_boot()) {
1310*1208bc7eSAndroid Build Coastguard Worker return true;
1311*1208bc7eSAndroid Build Coastguard Worker }
1312*1208bc7eSAndroid Build Coastguard Worker if (config_prof) {
1313*1208bc7eSAndroid Build Coastguard Worker prof_boot1();
1314*1208bc7eSAndroid Build Coastguard Worker }
1315*1208bc7eSAndroid Build Coastguard Worker arena_boot();
1316*1208bc7eSAndroid Build Coastguard Worker if (tcache_boot(TSDN_NULL)) {
1317*1208bc7eSAndroid Build Coastguard Worker return true;
1318*1208bc7eSAndroid Build Coastguard Worker }
1319*1208bc7eSAndroid Build Coastguard Worker if (malloc_mutex_init(&arenas_lock, "arenas", WITNESS_RANK_ARENAS,
1320*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_rank_exclusive)) {
1321*1208bc7eSAndroid Build Coastguard Worker return true;
1322*1208bc7eSAndroid Build Coastguard Worker }
1323*1208bc7eSAndroid Build Coastguard Worker /*
1324*1208bc7eSAndroid Build Coastguard Worker * Create enough scaffolding to allow recursive allocation in
1325*1208bc7eSAndroid Build Coastguard Worker * malloc_ncpus().
1326*1208bc7eSAndroid Build Coastguard Worker */
1327*1208bc7eSAndroid Build Coastguard Worker narenas_auto = 1;
1328*1208bc7eSAndroid Build Coastguard Worker memset(arenas, 0, sizeof(arena_t *) * narenas_auto);
1329*1208bc7eSAndroid Build Coastguard Worker /*
1330*1208bc7eSAndroid Build Coastguard Worker * Initialize one arena here. The rest are lazily created in
1331*1208bc7eSAndroid Build Coastguard Worker * arena_choose_hard().
1332*1208bc7eSAndroid Build Coastguard Worker */
1333*1208bc7eSAndroid Build Coastguard Worker if (arena_init(TSDN_NULL, 0, (extent_hooks_t *)&extent_hooks_default)
1334*1208bc7eSAndroid Build Coastguard Worker == NULL) {
1335*1208bc7eSAndroid Build Coastguard Worker return true;
1336*1208bc7eSAndroid Build Coastguard Worker }
1337*1208bc7eSAndroid Build Coastguard Worker a0 = arena_get(TSDN_NULL, 0, false);
1338*1208bc7eSAndroid Build Coastguard Worker malloc_init_state = malloc_init_a0_initialized;
1339*1208bc7eSAndroid Build Coastguard Worker
1340*1208bc7eSAndroid Build Coastguard Worker return false;
1341*1208bc7eSAndroid Build Coastguard Worker }
1342*1208bc7eSAndroid Build Coastguard Worker
1343*1208bc7eSAndroid Build Coastguard Worker static bool
1344*1208bc7eSAndroid Build Coastguard Worker malloc_init_hard_a0(void) {
1345*1208bc7eSAndroid Build Coastguard Worker bool ret;
1346*1208bc7eSAndroid Build Coastguard Worker
1347*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(TSDN_NULL, &init_lock);
1348*1208bc7eSAndroid Build Coastguard Worker ret = malloc_init_hard_a0_locked();
1349*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(TSDN_NULL, &init_lock);
1350*1208bc7eSAndroid Build Coastguard Worker return ret;
1351*1208bc7eSAndroid Build Coastguard Worker }
1352*1208bc7eSAndroid Build Coastguard Worker
1353*1208bc7eSAndroid Build Coastguard Worker /* Initialize data structures which may trigger recursive allocation. */
1354*1208bc7eSAndroid Build Coastguard Worker static bool
1355*1208bc7eSAndroid Build Coastguard Worker malloc_init_hard_recursible(void) {
1356*1208bc7eSAndroid Build Coastguard Worker malloc_init_state = malloc_init_recursible;
1357*1208bc7eSAndroid Build Coastguard Worker
1358*1208bc7eSAndroid Build Coastguard Worker #if defined(__BIONIC__) && defined(ANDROID_NUM_ARENAS)
1359*1208bc7eSAndroid Build Coastguard Worker /* Hardcode since this value won't be used. */
1360*1208bc7eSAndroid Build Coastguard Worker ncpus = 2;
1361*1208bc7eSAndroid Build Coastguard Worker #else
1362*1208bc7eSAndroid Build Coastguard Worker ncpus = malloc_ncpus();
1363*1208bc7eSAndroid Build Coastguard Worker #endif
1364*1208bc7eSAndroid Build Coastguard Worker
1365*1208bc7eSAndroid Build Coastguard Worker #if (defined(JEMALLOC_HAVE_PTHREAD_ATFORK) && !defined(JEMALLOC_MUTEX_INIT_CB) \
1366*1208bc7eSAndroid Build Coastguard Worker && !defined(JEMALLOC_ZONE) && !defined(_WIN32) && \
1367*1208bc7eSAndroid Build Coastguard Worker !defined(__native_client__))
1368*1208bc7eSAndroid Build Coastguard Worker /* LinuxThreads' pthread_atfork() allocates. */
1369*1208bc7eSAndroid Build Coastguard Worker if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,
1370*1208bc7eSAndroid Build Coastguard Worker jemalloc_postfork_child) != 0) {
1371*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Error in pthread_atfork()\n");
1372*1208bc7eSAndroid Build Coastguard Worker if (opt_abort) {
1373*1208bc7eSAndroid Build Coastguard Worker abort();
1374*1208bc7eSAndroid Build Coastguard Worker }
1375*1208bc7eSAndroid Build Coastguard Worker return true;
1376*1208bc7eSAndroid Build Coastguard Worker }
1377*1208bc7eSAndroid Build Coastguard Worker #endif
1378*1208bc7eSAndroid Build Coastguard Worker
1379*1208bc7eSAndroid Build Coastguard Worker if (background_thread_boot0()) {
1380*1208bc7eSAndroid Build Coastguard Worker return true;
1381*1208bc7eSAndroid Build Coastguard Worker }
1382*1208bc7eSAndroid Build Coastguard Worker
1383*1208bc7eSAndroid Build Coastguard Worker return false;
1384*1208bc7eSAndroid Build Coastguard Worker }
1385*1208bc7eSAndroid Build Coastguard Worker
1386*1208bc7eSAndroid Build Coastguard Worker static unsigned
1387*1208bc7eSAndroid Build Coastguard Worker malloc_narenas_default(void) {
1388*1208bc7eSAndroid Build Coastguard Worker #if defined(ANDROID_NUM_ARENAS)
1389*1208bc7eSAndroid Build Coastguard Worker return ANDROID_NUM_ARENAS;
1390*1208bc7eSAndroid Build Coastguard Worker #else
1391*1208bc7eSAndroid Build Coastguard Worker assert(ncpus > 0);
1392*1208bc7eSAndroid Build Coastguard Worker /*
1393*1208bc7eSAndroid Build Coastguard Worker * For SMP systems, create more than one arena per CPU by
1394*1208bc7eSAndroid Build Coastguard Worker * default.
1395*1208bc7eSAndroid Build Coastguard Worker */
1396*1208bc7eSAndroid Build Coastguard Worker if (ncpus > 1) {
1397*1208bc7eSAndroid Build Coastguard Worker return ncpus << 2;
1398*1208bc7eSAndroid Build Coastguard Worker } else {
1399*1208bc7eSAndroid Build Coastguard Worker return 1;
1400*1208bc7eSAndroid Build Coastguard Worker }
1401*1208bc7eSAndroid Build Coastguard Worker #endif
1402*1208bc7eSAndroid Build Coastguard Worker }
1403*1208bc7eSAndroid Build Coastguard Worker
1404*1208bc7eSAndroid Build Coastguard Worker static percpu_arena_mode_t
1405*1208bc7eSAndroid Build Coastguard Worker percpu_arena_as_initialized(percpu_arena_mode_t mode) {
1406*1208bc7eSAndroid Build Coastguard Worker assert(!malloc_initialized());
1407*1208bc7eSAndroid Build Coastguard Worker assert(mode <= percpu_arena_disabled);
1408*1208bc7eSAndroid Build Coastguard Worker
1409*1208bc7eSAndroid Build Coastguard Worker if (mode != percpu_arena_disabled) {
1410*1208bc7eSAndroid Build Coastguard Worker mode += percpu_arena_mode_enabled_base;
1411*1208bc7eSAndroid Build Coastguard Worker }
1412*1208bc7eSAndroid Build Coastguard Worker
1413*1208bc7eSAndroid Build Coastguard Worker return mode;
1414*1208bc7eSAndroid Build Coastguard Worker }
1415*1208bc7eSAndroid Build Coastguard Worker
1416*1208bc7eSAndroid Build Coastguard Worker static bool
1417*1208bc7eSAndroid Build Coastguard Worker malloc_init_narenas(void) {
1418*1208bc7eSAndroid Build Coastguard Worker assert(ncpus > 0);
1419*1208bc7eSAndroid Build Coastguard Worker
1420*1208bc7eSAndroid Build Coastguard Worker if (opt_percpu_arena != percpu_arena_disabled) {
1421*1208bc7eSAndroid Build Coastguard Worker if (!have_percpu_arena || malloc_getcpu() < 0) {
1422*1208bc7eSAndroid Build Coastguard Worker opt_percpu_arena = percpu_arena_disabled;
1423*1208bc7eSAndroid Build Coastguard Worker malloc_printf("<jemalloc>: perCPU arena getcpu() not "
1424*1208bc7eSAndroid Build Coastguard Worker "available. Setting narenas to %u.\n", opt_narenas ?
1425*1208bc7eSAndroid Build Coastguard Worker opt_narenas : malloc_narenas_default());
1426*1208bc7eSAndroid Build Coastguard Worker if (opt_abort) {
1427*1208bc7eSAndroid Build Coastguard Worker abort();
1428*1208bc7eSAndroid Build Coastguard Worker }
1429*1208bc7eSAndroid Build Coastguard Worker } else {
1430*1208bc7eSAndroid Build Coastguard Worker if (ncpus >= MALLOCX_ARENA_LIMIT) {
1431*1208bc7eSAndroid Build Coastguard Worker malloc_printf("<jemalloc>: narenas w/ percpu"
1432*1208bc7eSAndroid Build Coastguard Worker "arena beyond limit (%d)\n", ncpus);
1433*1208bc7eSAndroid Build Coastguard Worker if (opt_abort) {
1434*1208bc7eSAndroid Build Coastguard Worker abort();
1435*1208bc7eSAndroid Build Coastguard Worker }
1436*1208bc7eSAndroid Build Coastguard Worker return true;
1437*1208bc7eSAndroid Build Coastguard Worker }
1438*1208bc7eSAndroid Build Coastguard Worker /* NB: opt_percpu_arena isn't fully initialized yet. */
1439*1208bc7eSAndroid Build Coastguard Worker if (percpu_arena_as_initialized(opt_percpu_arena) ==
1440*1208bc7eSAndroid Build Coastguard Worker per_phycpu_arena && ncpus % 2 != 0) {
1441*1208bc7eSAndroid Build Coastguard Worker malloc_printf("<jemalloc>: invalid "
1442*1208bc7eSAndroid Build Coastguard Worker "configuration -- per physical CPU arena "
1443*1208bc7eSAndroid Build Coastguard Worker "with odd number (%u) of CPUs (no hyper "
1444*1208bc7eSAndroid Build Coastguard Worker "threading?).\n", ncpus);
1445*1208bc7eSAndroid Build Coastguard Worker if (opt_abort)
1446*1208bc7eSAndroid Build Coastguard Worker abort();
1447*1208bc7eSAndroid Build Coastguard Worker }
1448*1208bc7eSAndroid Build Coastguard Worker unsigned n = percpu_arena_ind_limit(
1449*1208bc7eSAndroid Build Coastguard Worker percpu_arena_as_initialized(opt_percpu_arena));
1450*1208bc7eSAndroid Build Coastguard Worker if (opt_narenas < n) {
1451*1208bc7eSAndroid Build Coastguard Worker /*
1452*1208bc7eSAndroid Build Coastguard Worker * If narenas is specified with percpu_arena
1453*1208bc7eSAndroid Build Coastguard Worker * enabled, actual narenas is set as the greater
1454*1208bc7eSAndroid Build Coastguard Worker * of the two. percpu_arena_choose will be free
1455*1208bc7eSAndroid Build Coastguard Worker * to use any of the arenas based on CPU
1456*1208bc7eSAndroid Build Coastguard Worker * id. This is conservative (at a small cost)
1457*1208bc7eSAndroid Build Coastguard Worker * but ensures correctness.
1458*1208bc7eSAndroid Build Coastguard Worker *
1459*1208bc7eSAndroid Build Coastguard Worker * If for some reason the ncpus determined at
1460*1208bc7eSAndroid Build Coastguard Worker * boot is not the actual number (e.g. because
1461*1208bc7eSAndroid Build Coastguard Worker * of affinity setting from numactl), reserving
1462*1208bc7eSAndroid Build Coastguard Worker * narenas this way provides a workaround for
1463*1208bc7eSAndroid Build Coastguard Worker * percpu_arena.
1464*1208bc7eSAndroid Build Coastguard Worker */
1465*1208bc7eSAndroid Build Coastguard Worker opt_narenas = n;
1466*1208bc7eSAndroid Build Coastguard Worker }
1467*1208bc7eSAndroid Build Coastguard Worker }
1468*1208bc7eSAndroid Build Coastguard Worker }
1469*1208bc7eSAndroid Build Coastguard Worker if (opt_narenas == 0) {
1470*1208bc7eSAndroid Build Coastguard Worker opt_narenas = malloc_narenas_default();
1471*1208bc7eSAndroid Build Coastguard Worker }
1472*1208bc7eSAndroid Build Coastguard Worker assert(opt_narenas > 0);
1473*1208bc7eSAndroid Build Coastguard Worker
1474*1208bc7eSAndroid Build Coastguard Worker narenas_auto = opt_narenas;
1475*1208bc7eSAndroid Build Coastguard Worker /*
1476*1208bc7eSAndroid Build Coastguard Worker * Limit the number of arenas to the indexing range of MALLOCX_ARENA().
1477*1208bc7eSAndroid Build Coastguard Worker */
1478*1208bc7eSAndroid Build Coastguard Worker if (narenas_auto >= MALLOCX_ARENA_LIMIT) {
1479*1208bc7eSAndroid Build Coastguard Worker narenas_auto = MALLOCX_ARENA_LIMIT - 1;
1480*1208bc7eSAndroid Build Coastguard Worker malloc_printf("<jemalloc>: Reducing narenas to limit (%d)\n",
1481*1208bc7eSAndroid Build Coastguard Worker narenas_auto);
1482*1208bc7eSAndroid Build Coastguard Worker }
1483*1208bc7eSAndroid Build Coastguard Worker narenas_total_set(narenas_auto);
1484*1208bc7eSAndroid Build Coastguard Worker
1485*1208bc7eSAndroid Build Coastguard Worker return false;
1486*1208bc7eSAndroid Build Coastguard Worker }
1487*1208bc7eSAndroid Build Coastguard Worker
1488*1208bc7eSAndroid Build Coastguard Worker static void
1489*1208bc7eSAndroid Build Coastguard Worker malloc_init_percpu(void) {
1490*1208bc7eSAndroid Build Coastguard Worker opt_percpu_arena = percpu_arena_as_initialized(opt_percpu_arena);
1491*1208bc7eSAndroid Build Coastguard Worker }
1492*1208bc7eSAndroid Build Coastguard Worker
1493*1208bc7eSAndroid Build Coastguard Worker static bool
1494*1208bc7eSAndroid Build Coastguard Worker malloc_init_hard_finish(void) {
1495*1208bc7eSAndroid Build Coastguard Worker if (malloc_mutex_boot()) {
1496*1208bc7eSAndroid Build Coastguard Worker return true;
1497*1208bc7eSAndroid Build Coastguard Worker }
1498*1208bc7eSAndroid Build Coastguard Worker
1499*1208bc7eSAndroid Build Coastguard Worker malloc_init_state = malloc_init_initialized;
1500*1208bc7eSAndroid Build Coastguard Worker malloc_slow_flag_init();
1501*1208bc7eSAndroid Build Coastguard Worker
1502*1208bc7eSAndroid Build Coastguard Worker return false;
1503*1208bc7eSAndroid Build Coastguard Worker }
1504*1208bc7eSAndroid Build Coastguard Worker
1505*1208bc7eSAndroid Build Coastguard Worker static void
1506*1208bc7eSAndroid Build Coastguard Worker malloc_init_hard_cleanup(tsdn_t *tsdn, bool reentrancy_set) {
1507*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_assert_owner(tsdn, &init_lock);
1508*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsdn, &init_lock);
1509*1208bc7eSAndroid Build Coastguard Worker if (reentrancy_set) {
1510*1208bc7eSAndroid Build Coastguard Worker assert(!tsdn_null(tsdn));
1511*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd = tsdn_tsd(tsdn);
1512*1208bc7eSAndroid Build Coastguard Worker assert(tsd_reentrancy_level_get(tsd) > 0);
1513*1208bc7eSAndroid Build Coastguard Worker post_reentrancy(tsd);
1514*1208bc7eSAndroid Build Coastguard Worker }
1515*1208bc7eSAndroid Build Coastguard Worker }
1516*1208bc7eSAndroid Build Coastguard Worker
1517*1208bc7eSAndroid Build Coastguard Worker static bool
1518*1208bc7eSAndroid Build Coastguard Worker malloc_init_hard(void) {
1519*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd;
1520*1208bc7eSAndroid Build Coastguard Worker
1521*1208bc7eSAndroid Build Coastguard Worker #if defined(_WIN32) && _WIN32_WINNT < 0x0600
1522*1208bc7eSAndroid Build Coastguard Worker _init_init_lock();
1523*1208bc7eSAndroid Build Coastguard Worker #endif
1524*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(TSDN_NULL, &init_lock);
1525*1208bc7eSAndroid Build Coastguard Worker
1526*1208bc7eSAndroid Build Coastguard Worker #define UNLOCK_RETURN(tsdn, ret, reentrancy) \
1527*1208bc7eSAndroid Build Coastguard Worker malloc_init_hard_cleanup(tsdn, reentrancy); \
1528*1208bc7eSAndroid Build Coastguard Worker return ret;
1529*1208bc7eSAndroid Build Coastguard Worker
1530*1208bc7eSAndroid Build Coastguard Worker if (!malloc_init_hard_needed()) {
1531*1208bc7eSAndroid Build Coastguard Worker UNLOCK_RETURN(TSDN_NULL, false, false)
1532*1208bc7eSAndroid Build Coastguard Worker }
1533*1208bc7eSAndroid Build Coastguard Worker
1534*1208bc7eSAndroid Build Coastguard Worker if (malloc_init_state != malloc_init_a0_initialized &&
1535*1208bc7eSAndroid Build Coastguard Worker malloc_init_hard_a0_locked()) {
1536*1208bc7eSAndroid Build Coastguard Worker UNLOCK_RETURN(TSDN_NULL, true, false)
1537*1208bc7eSAndroid Build Coastguard Worker }
1538*1208bc7eSAndroid Build Coastguard Worker
1539*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(TSDN_NULL, &init_lock);
1540*1208bc7eSAndroid Build Coastguard Worker /* Recursive allocation relies on functional tsd. */
1541*1208bc7eSAndroid Build Coastguard Worker tsd = malloc_tsd_boot0();
1542*1208bc7eSAndroid Build Coastguard Worker if (tsd == NULL) {
1543*1208bc7eSAndroid Build Coastguard Worker return true;
1544*1208bc7eSAndroid Build Coastguard Worker }
1545*1208bc7eSAndroid Build Coastguard Worker if (malloc_init_hard_recursible()) {
1546*1208bc7eSAndroid Build Coastguard Worker return true;
1547*1208bc7eSAndroid Build Coastguard Worker }
1548*1208bc7eSAndroid Build Coastguard Worker
1549*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(tsd_tsdn(tsd), &init_lock);
1550*1208bc7eSAndroid Build Coastguard Worker /* Set reentrancy level to 1 during init. */
1551*1208bc7eSAndroid Build Coastguard Worker pre_reentrancy(tsd, NULL);
1552*1208bc7eSAndroid Build Coastguard Worker /* Initialize narenas before prof_boot2 (for allocation). */
1553*1208bc7eSAndroid Build Coastguard Worker if (malloc_init_narenas() || background_thread_boot1(tsd_tsdn(tsd))) {
1554*1208bc7eSAndroid Build Coastguard Worker UNLOCK_RETURN(tsd_tsdn(tsd), true, true)
1555*1208bc7eSAndroid Build Coastguard Worker }
1556*1208bc7eSAndroid Build Coastguard Worker if (config_prof && prof_boot2(tsd)) {
1557*1208bc7eSAndroid Build Coastguard Worker UNLOCK_RETURN(tsd_tsdn(tsd), true, true)
1558*1208bc7eSAndroid Build Coastguard Worker }
1559*1208bc7eSAndroid Build Coastguard Worker
1560*1208bc7eSAndroid Build Coastguard Worker malloc_init_percpu();
1561*1208bc7eSAndroid Build Coastguard Worker
1562*1208bc7eSAndroid Build Coastguard Worker if (malloc_init_hard_finish()) {
1563*1208bc7eSAndroid Build Coastguard Worker UNLOCK_RETURN(tsd_tsdn(tsd), true, true)
1564*1208bc7eSAndroid Build Coastguard Worker }
1565*1208bc7eSAndroid Build Coastguard Worker post_reentrancy(tsd);
1566*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsd_tsdn(tsd), &init_lock);
1567*1208bc7eSAndroid Build Coastguard Worker
1568*1208bc7eSAndroid Build Coastguard Worker witness_assert_lockless(witness_tsd_tsdn(
1569*1208bc7eSAndroid Build Coastguard Worker tsd_witness_tsdp_get_unsafe(tsd)));
1570*1208bc7eSAndroid Build Coastguard Worker malloc_tsd_boot1();
1571*1208bc7eSAndroid Build Coastguard Worker /* Update TSD after tsd_boot1. */
1572*1208bc7eSAndroid Build Coastguard Worker tsd = tsd_fetch();
1573*1208bc7eSAndroid Build Coastguard Worker if (opt_background_thread) {
1574*1208bc7eSAndroid Build Coastguard Worker assert(have_background_thread);
1575*1208bc7eSAndroid Build Coastguard Worker /*
1576*1208bc7eSAndroid Build Coastguard Worker * Need to finish init & unlock first before creating background
1577*1208bc7eSAndroid Build Coastguard Worker * threads (pthread_create depends on malloc). ctl_init (which
1578*1208bc7eSAndroid Build Coastguard Worker * sets isthreaded) needs to be called without holding any lock.
1579*1208bc7eSAndroid Build Coastguard Worker */
1580*1208bc7eSAndroid Build Coastguard Worker background_thread_ctl_init(tsd_tsdn(tsd));
1581*1208bc7eSAndroid Build Coastguard Worker
1582*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock);
1583*1208bc7eSAndroid Build Coastguard Worker bool err = background_thread_create(tsd, 0);
1584*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock);
1585*1208bc7eSAndroid Build Coastguard Worker if (err) {
1586*1208bc7eSAndroid Build Coastguard Worker return true;
1587*1208bc7eSAndroid Build Coastguard Worker }
1588*1208bc7eSAndroid Build Coastguard Worker }
1589*1208bc7eSAndroid Build Coastguard Worker #undef UNLOCK_RETURN
1590*1208bc7eSAndroid Build Coastguard Worker return false;
1591*1208bc7eSAndroid Build Coastguard Worker }
1592*1208bc7eSAndroid Build Coastguard Worker
1593*1208bc7eSAndroid Build Coastguard Worker /*
1594*1208bc7eSAndroid Build Coastguard Worker * End initialization functions.
1595*1208bc7eSAndroid Build Coastguard Worker */
1596*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
1597*1208bc7eSAndroid Build Coastguard Worker /*
1598*1208bc7eSAndroid Build Coastguard Worker * Begin allocation-path internal functions and data structures.
1599*1208bc7eSAndroid Build Coastguard Worker */
1600*1208bc7eSAndroid Build Coastguard Worker
1601*1208bc7eSAndroid Build Coastguard Worker /*
1602*1208bc7eSAndroid Build Coastguard Worker * Settings determined by the documented behavior of the allocation functions.
1603*1208bc7eSAndroid Build Coastguard Worker */
1604*1208bc7eSAndroid Build Coastguard Worker typedef struct static_opts_s static_opts_t;
1605*1208bc7eSAndroid Build Coastguard Worker struct static_opts_s {
1606*1208bc7eSAndroid Build Coastguard Worker /* Whether or not allocation size may overflow. */
1607*1208bc7eSAndroid Build Coastguard Worker bool may_overflow;
1608*1208bc7eSAndroid Build Coastguard Worker /* Whether or not allocations of size 0 should be treated as size 1. */
1609*1208bc7eSAndroid Build Coastguard Worker bool bump_empty_alloc;
1610*1208bc7eSAndroid Build Coastguard Worker /*
1611*1208bc7eSAndroid Build Coastguard Worker * Whether to assert that allocations are not of size 0 (after any
1612*1208bc7eSAndroid Build Coastguard Worker * bumping).
1613*1208bc7eSAndroid Build Coastguard Worker */
1614*1208bc7eSAndroid Build Coastguard Worker bool assert_nonempty_alloc;
1615*1208bc7eSAndroid Build Coastguard Worker
1616*1208bc7eSAndroid Build Coastguard Worker /*
1617*1208bc7eSAndroid Build Coastguard Worker * Whether or not to modify the 'result' argument to malloc in case of
1618*1208bc7eSAndroid Build Coastguard Worker * error.
1619*1208bc7eSAndroid Build Coastguard Worker */
1620*1208bc7eSAndroid Build Coastguard Worker bool null_out_result_on_error;
1621*1208bc7eSAndroid Build Coastguard Worker /* Whether to set errno when we encounter an error condition. */
1622*1208bc7eSAndroid Build Coastguard Worker bool set_errno_on_error;
1623*1208bc7eSAndroid Build Coastguard Worker
1624*1208bc7eSAndroid Build Coastguard Worker /*
1625*1208bc7eSAndroid Build Coastguard Worker * The minimum valid alignment for functions requesting aligned storage.
1626*1208bc7eSAndroid Build Coastguard Worker */
1627*1208bc7eSAndroid Build Coastguard Worker size_t min_alignment;
1628*1208bc7eSAndroid Build Coastguard Worker
1629*1208bc7eSAndroid Build Coastguard Worker /* The error string to use if we oom. */
1630*1208bc7eSAndroid Build Coastguard Worker const char *oom_string;
1631*1208bc7eSAndroid Build Coastguard Worker /* The error string to use if the passed-in alignment is invalid. */
1632*1208bc7eSAndroid Build Coastguard Worker const char *invalid_alignment_string;
1633*1208bc7eSAndroid Build Coastguard Worker
1634*1208bc7eSAndroid Build Coastguard Worker /*
1635*1208bc7eSAndroid Build Coastguard Worker * False if we're configured to skip some time-consuming operations.
1636*1208bc7eSAndroid Build Coastguard Worker *
1637*1208bc7eSAndroid Build Coastguard Worker * This isn't really a malloc "behavior", but it acts as a useful
1638*1208bc7eSAndroid Build Coastguard Worker * summary of several other static (or at least, static after program
1639*1208bc7eSAndroid Build Coastguard Worker * initialization) options.
1640*1208bc7eSAndroid Build Coastguard Worker */
1641*1208bc7eSAndroid Build Coastguard Worker bool slow;
1642*1208bc7eSAndroid Build Coastguard Worker };
1643*1208bc7eSAndroid Build Coastguard Worker
1644*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void
1645*1208bc7eSAndroid Build Coastguard Worker static_opts_init(static_opts_t *static_opts) {
1646*1208bc7eSAndroid Build Coastguard Worker static_opts->may_overflow = false;
1647*1208bc7eSAndroid Build Coastguard Worker static_opts->bump_empty_alloc = false;
1648*1208bc7eSAndroid Build Coastguard Worker static_opts->assert_nonempty_alloc = false;
1649*1208bc7eSAndroid Build Coastguard Worker static_opts->null_out_result_on_error = false;
1650*1208bc7eSAndroid Build Coastguard Worker static_opts->set_errno_on_error = false;
1651*1208bc7eSAndroid Build Coastguard Worker static_opts->min_alignment = 0;
1652*1208bc7eSAndroid Build Coastguard Worker static_opts->oom_string = "";
1653*1208bc7eSAndroid Build Coastguard Worker static_opts->invalid_alignment_string = "";
1654*1208bc7eSAndroid Build Coastguard Worker static_opts->slow = false;
1655*1208bc7eSAndroid Build Coastguard Worker }
1656*1208bc7eSAndroid Build Coastguard Worker
1657*1208bc7eSAndroid Build Coastguard Worker /*
1658*1208bc7eSAndroid Build Coastguard Worker * These correspond to the macros in jemalloc/jemalloc_macros.h. Broadly, we
1659*1208bc7eSAndroid Build Coastguard Worker * should have one constant here per magic value there. Note however that the
1660*1208bc7eSAndroid Build Coastguard Worker * representations need not be related.
1661*1208bc7eSAndroid Build Coastguard Worker */
1662*1208bc7eSAndroid Build Coastguard Worker #define TCACHE_IND_NONE ((unsigned)-1)
1663*1208bc7eSAndroid Build Coastguard Worker #define TCACHE_IND_AUTOMATIC ((unsigned)-2)
1664*1208bc7eSAndroid Build Coastguard Worker #define ARENA_IND_AUTOMATIC ((unsigned)-1)
1665*1208bc7eSAndroid Build Coastguard Worker
1666*1208bc7eSAndroid Build Coastguard Worker typedef struct dynamic_opts_s dynamic_opts_t;
1667*1208bc7eSAndroid Build Coastguard Worker struct dynamic_opts_s {
1668*1208bc7eSAndroid Build Coastguard Worker void **result;
1669*1208bc7eSAndroid Build Coastguard Worker size_t num_items;
1670*1208bc7eSAndroid Build Coastguard Worker size_t item_size;
1671*1208bc7eSAndroid Build Coastguard Worker size_t alignment;
1672*1208bc7eSAndroid Build Coastguard Worker bool zero;
1673*1208bc7eSAndroid Build Coastguard Worker unsigned tcache_ind;
1674*1208bc7eSAndroid Build Coastguard Worker unsigned arena_ind;
1675*1208bc7eSAndroid Build Coastguard Worker };
1676*1208bc7eSAndroid Build Coastguard Worker
1677*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void
1678*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_init(dynamic_opts_t *dynamic_opts) {
1679*1208bc7eSAndroid Build Coastguard Worker dynamic_opts->result = NULL;
1680*1208bc7eSAndroid Build Coastguard Worker dynamic_opts->num_items = 0;
1681*1208bc7eSAndroid Build Coastguard Worker dynamic_opts->item_size = 0;
1682*1208bc7eSAndroid Build Coastguard Worker dynamic_opts->alignment = 0;
1683*1208bc7eSAndroid Build Coastguard Worker dynamic_opts->zero = false;
1684*1208bc7eSAndroid Build Coastguard Worker dynamic_opts->tcache_ind = TCACHE_IND_AUTOMATIC;
1685*1208bc7eSAndroid Build Coastguard Worker dynamic_opts->arena_ind = ARENA_IND_AUTOMATIC;
1686*1208bc7eSAndroid Build Coastguard Worker }
1687*1208bc7eSAndroid Build Coastguard Worker
1688*1208bc7eSAndroid Build Coastguard Worker /* ind is ignored if dopts->alignment > 0. */
1689*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void *
1690*1208bc7eSAndroid Build Coastguard Worker imalloc_no_sample(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd,
1691*1208bc7eSAndroid Build Coastguard Worker size_t size, size_t usize, szind_t ind) {
1692*1208bc7eSAndroid Build Coastguard Worker tcache_t *tcache;
1693*1208bc7eSAndroid Build Coastguard Worker arena_t *arena;
1694*1208bc7eSAndroid Build Coastguard Worker
1695*1208bc7eSAndroid Build Coastguard Worker /* Fill in the tcache. */
1696*1208bc7eSAndroid Build Coastguard Worker if (dopts->tcache_ind == TCACHE_IND_AUTOMATIC) {
1697*1208bc7eSAndroid Build Coastguard Worker if (likely(!sopts->slow)) {
1698*1208bc7eSAndroid Build Coastguard Worker /* Getting tcache ptr unconditionally. */
1699*1208bc7eSAndroid Build Coastguard Worker tcache = tsd_tcachep_get(tsd);
1700*1208bc7eSAndroid Build Coastguard Worker assert(tcache == tcache_get(tsd));
1701*1208bc7eSAndroid Build Coastguard Worker } else {
1702*1208bc7eSAndroid Build Coastguard Worker tcache = tcache_get(tsd);
1703*1208bc7eSAndroid Build Coastguard Worker }
1704*1208bc7eSAndroid Build Coastguard Worker } else if (dopts->tcache_ind == TCACHE_IND_NONE) {
1705*1208bc7eSAndroid Build Coastguard Worker tcache = NULL;
1706*1208bc7eSAndroid Build Coastguard Worker } else {
1707*1208bc7eSAndroid Build Coastguard Worker tcache = tcaches_get(tsd, dopts->tcache_ind);
1708*1208bc7eSAndroid Build Coastguard Worker }
1709*1208bc7eSAndroid Build Coastguard Worker
1710*1208bc7eSAndroid Build Coastguard Worker /* Fill in the arena. */
1711*1208bc7eSAndroid Build Coastguard Worker if (dopts->arena_ind == ARENA_IND_AUTOMATIC) {
1712*1208bc7eSAndroid Build Coastguard Worker /*
1713*1208bc7eSAndroid Build Coastguard Worker * In case of automatic arena management, we defer arena
1714*1208bc7eSAndroid Build Coastguard Worker * computation until as late as we can, hoping to fill the
1715*1208bc7eSAndroid Build Coastguard Worker * allocation out of the tcache.
1716*1208bc7eSAndroid Build Coastguard Worker */
1717*1208bc7eSAndroid Build Coastguard Worker arena = NULL;
1718*1208bc7eSAndroid Build Coastguard Worker } else {
1719*1208bc7eSAndroid Build Coastguard Worker arena = arena_get(tsd_tsdn(tsd), dopts->arena_ind, true);
1720*1208bc7eSAndroid Build Coastguard Worker }
1721*1208bc7eSAndroid Build Coastguard Worker
1722*1208bc7eSAndroid Build Coastguard Worker if (unlikely(dopts->alignment != 0)) {
1723*1208bc7eSAndroid Build Coastguard Worker return ipalloct(tsd_tsdn(tsd), usize, dopts->alignment,
1724*1208bc7eSAndroid Build Coastguard Worker dopts->zero, tcache, arena);
1725*1208bc7eSAndroid Build Coastguard Worker }
1726*1208bc7eSAndroid Build Coastguard Worker
1727*1208bc7eSAndroid Build Coastguard Worker return iallocztm(tsd_tsdn(tsd), size, ind, dopts->zero, tcache, false,
1728*1208bc7eSAndroid Build Coastguard Worker arena, sopts->slow);
1729*1208bc7eSAndroid Build Coastguard Worker }
1730*1208bc7eSAndroid Build Coastguard Worker
1731*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void *
1732*1208bc7eSAndroid Build Coastguard Worker imalloc_sample(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd,
1733*1208bc7eSAndroid Build Coastguard Worker size_t usize, szind_t ind) {
1734*1208bc7eSAndroid Build Coastguard Worker void *ret;
1735*1208bc7eSAndroid Build Coastguard Worker
1736*1208bc7eSAndroid Build Coastguard Worker /*
1737*1208bc7eSAndroid Build Coastguard Worker * For small allocations, sampling bumps the usize. If so, we allocate
1738*1208bc7eSAndroid Build Coastguard Worker * from the ind_large bucket.
1739*1208bc7eSAndroid Build Coastguard Worker */
1740*1208bc7eSAndroid Build Coastguard Worker szind_t ind_large;
1741*1208bc7eSAndroid Build Coastguard Worker size_t bumped_usize = usize;
1742*1208bc7eSAndroid Build Coastguard Worker
1743*1208bc7eSAndroid Build Coastguard Worker if (usize <= SMALL_MAXCLASS) {
1744*1208bc7eSAndroid Build Coastguard Worker assert(((dopts->alignment == 0) ? sz_s2u(LARGE_MINCLASS) :
1745*1208bc7eSAndroid Build Coastguard Worker sz_sa2u(LARGE_MINCLASS, dopts->alignment))
1746*1208bc7eSAndroid Build Coastguard Worker == LARGE_MINCLASS);
1747*1208bc7eSAndroid Build Coastguard Worker ind_large = sz_size2index(LARGE_MINCLASS);
1748*1208bc7eSAndroid Build Coastguard Worker bumped_usize = sz_s2u(LARGE_MINCLASS);
1749*1208bc7eSAndroid Build Coastguard Worker ret = imalloc_no_sample(sopts, dopts, tsd, bumped_usize,
1750*1208bc7eSAndroid Build Coastguard Worker bumped_usize, ind_large);
1751*1208bc7eSAndroid Build Coastguard Worker if (unlikely(ret == NULL)) {
1752*1208bc7eSAndroid Build Coastguard Worker return NULL;
1753*1208bc7eSAndroid Build Coastguard Worker }
1754*1208bc7eSAndroid Build Coastguard Worker arena_prof_promote(tsd_tsdn(tsd), ret, usize);
1755*1208bc7eSAndroid Build Coastguard Worker } else {
1756*1208bc7eSAndroid Build Coastguard Worker ret = imalloc_no_sample(sopts, dopts, tsd, usize, usize, ind);
1757*1208bc7eSAndroid Build Coastguard Worker }
1758*1208bc7eSAndroid Build Coastguard Worker
1759*1208bc7eSAndroid Build Coastguard Worker return ret;
1760*1208bc7eSAndroid Build Coastguard Worker }
1761*1208bc7eSAndroid Build Coastguard Worker
1762*1208bc7eSAndroid Build Coastguard Worker /*
1763*1208bc7eSAndroid Build Coastguard Worker * Returns true if the allocation will overflow, and false otherwise. Sets
1764*1208bc7eSAndroid Build Coastguard Worker * *size to the product either way.
1765*1208bc7eSAndroid Build Coastguard Worker */
1766*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE bool
1767*1208bc7eSAndroid Build Coastguard Worker compute_size_with_overflow(bool may_overflow, dynamic_opts_t *dopts,
1768*1208bc7eSAndroid Build Coastguard Worker size_t *size) {
1769*1208bc7eSAndroid Build Coastguard Worker /*
1770*1208bc7eSAndroid Build Coastguard Worker * This function is just num_items * item_size, except that we may have
1771*1208bc7eSAndroid Build Coastguard Worker * to check for overflow.
1772*1208bc7eSAndroid Build Coastguard Worker */
1773*1208bc7eSAndroid Build Coastguard Worker
1774*1208bc7eSAndroid Build Coastguard Worker if (!may_overflow) {
1775*1208bc7eSAndroid Build Coastguard Worker assert(dopts->num_items == 1);
1776*1208bc7eSAndroid Build Coastguard Worker *size = dopts->item_size;
1777*1208bc7eSAndroid Build Coastguard Worker return false;
1778*1208bc7eSAndroid Build Coastguard Worker }
1779*1208bc7eSAndroid Build Coastguard Worker
1780*1208bc7eSAndroid Build Coastguard Worker /* A size_t with its high-half bits all set to 1. */
1781*1208bc7eSAndroid Build Coastguard Worker static const size_t high_bits = SIZE_T_MAX << (sizeof(size_t) * 8 / 2);
1782*1208bc7eSAndroid Build Coastguard Worker
1783*1208bc7eSAndroid Build Coastguard Worker *size = dopts->item_size * dopts->num_items;
1784*1208bc7eSAndroid Build Coastguard Worker
1785*1208bc7eSAndroid Build Coastguard Worker if (unlikely(*size == 0)) {
1786*1208bc7eSAndroid Build Coastguard Worker return (dopts->num_items != 0 && dopts->item_size != 0);
1787*1208bc7eSAndroid Build Coastguard Worker }
1788*1208bc7eSAndroid Build Coastguard Worker
1789*1208bc7eSAndroid Build Coastguard Worker /*
1790*1208bc7eSAndroid Build Coastguard Worker * We got a non-zero size, but we don't know if we overflowed to get
1791*1208bc7eSAndroid Build Coastguard Worker * there. To avoid having to do a divide, we'll be clever and note that
1792*1208bc7eSAndroid Build Coastguard Worker * if both A and B can be represented in N/2 bits, then their product
1793*1208bc7eSAndroid Build Coastguard Worker * can be represented in N bits (without the possibility of overflow).
1794*1208bc7eSAndroid Build Coastguard Worker */
1795*1208bc7eSAndroid Build Coastguard Worker if (likely((high_bits & (dopts->num_items | dopts->item_size)) == 0)) {
1796*1208bc7eSAndroid Build Coastguard Worker return false;
1797*1208bc7eSAndroid Build Coastguard Worker }
1798*1208bc7eSAndroid Build Coastguard Worker if (likely(*size / dopts->item_size == dopts->num_items)) {
1799*1208bc7eSAndroid Build Coastguard Worker return false;
1800*1208bc7eSAndroid Build Coastguard Worker }
1801*1208bc7eSAndroid Build Coastguard Worker return true;
1802*1208bc7eSAndroid Build Coastguard Worker }
1803*1208bc7eSAndroid Build Coastguard Worker
1804*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE int
1805*1208bc7eSAndroid Build Coastguard Worker imalloc_body(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd) {
1806*1208bc7eSAndroid Build Coastguard Worker /* Where the actual allocated memory will live. */
1807*1208bc7eSAndroid Build Coastguard Worker void *allocation = NULL;
1808*1208bc7eSAndroid Build Coastguard Worker /* Filled in by compute_size_with_overflow below. */
1809*1208bc7eSAndroid Build Coastguard Worker size_t size = 0;
1810*1208bc7eSAndroid Build Coastguard Worker /*
1811*1208bc7eSAndroid Build Coastguard Worker * For unaligned allocations, we need only ind. For aligned
1812*1208bc7eSAndroid Build Coastguard Worker * allocations, or in case of stats or profiling we need usize.
1813*1208bc7eSAndroid Build Coastguard Worker *
1814*1208bc7eSAndroid Build Coastguard Worker * These are actually dead stores, in that their values are reset before
1815*1208bc7eSAndroid Build Coastguard Worker * any branch on their value is taken. Sometimes though, it's
1816*1208bc7eSAndroid Build Coastguard Worker * convenient to pass them as arguments before this point. To avoid
1817*1208bc7eSAndroid Build Coastguard Worker * undefined behavior then, we initialize them with dummy stores.
1818*1208bc7eSAndroid Build Coastguard Worker */
1819*1208bc7eSAndroid Build Coastguard Worker szind_t ind = 0;
1820*1208bc7eSAndroid Build Coastguard Worker size_t usize = 0;
1821*1208bc7eSAndroid Build Coastguard Worker
1822*1208bc7eSAndroid Build Coastguard Worker /* Reentrancy is only checked on slow path. */
1823*1208bc7eSAndroid Build Coastguard Worker int8_t reentrancy_level;
1824*1208bc7eSAndroid Build Coastguard Worker
1825*1208bc7eSAndroid Build Coastguard Worker /* Compute the amount of memory the user wants. */
1826*1208bc7eSAndroid Build Coastguard Worker if (unlikely(compute_size_with_overflow(sopts->may_overflow, dopts,
1827*1208bc7eSAndroid Build Coastguard Worker &size))) {
1828*1208bc7eSAndroid Build Coastguard Worker goto label_oom;
1829*1208bc7eSAndroid Build Coastguard Worker }
1830*1208bc7eSAndroid Build Coastguard Worker
1831*1208bc7eSAndroid Build Coastguard Worker /* Validate the user input. */
1832*1208bc7eSAndroid Build Coastguard Worker if (sopts->bump_empty_alloc) {
1833*1208bc7eSAndroid Build Coastguard Worker if (unlikely(size == 0)) {
1834*1208bc7eSAndroid Build Coastguard Worker size = 1;
1835*1208bc7eSAndroid Build Coastguard Worker }
1836*1208bc7eSAndroid Build Coastguard Worker }
1837*1208bc7eSAndroid Build Coastguard Worker
1838*1208bc7eSAndroid Build Coastguard Worker if (sopts->assert_nonempty_alloc) {
1839*1208bc7eSAndroid Build Coastguard Worker assert (size != 0);
1840*1208bc7eSAndroid Build Coastguard Worker }
1841*1208bc7eSAndroid Build Coastguard Worker
1842*1208bc7eSAndroid Build Coastguard Worker if (unlikely(dopts->alignment < sopts->min_alignment
1843*1208bc7eSAndroid Build Coastguard Worker || (dopts->alignment & (dopts->alignment - 1)) != 0)) {
1844*1208bc7eSAndroid Build Coastguard Worker goto label_invalid_alignment;
1845*1208bc7eSAndroid Build Coastguard Worker }
1846*1208bc7eSAndroid Build Coastguard Worker
1847*1208bc7eSAndroid Build Coastguard Worker /* This is the beginning of the "core" algorithm. */
1848*1208bc7eSAndroid Build Coastguard Worker
1849*1208bc7eSAndroid Build Coastguard Worker if (dopts->alignment == 0) {
1850*1208bc7eSAndroid Build Coastguard Worker ind = sz_size2index(size);
1851*1208bc7eSAndroid Build Coastguard Worker if (unlikely(ind >= NSIZES)) {
1852*1208bc7eSAndroid Build Coastguard Worker goto label_oom;
1853*1208bc7eSAndroid Build Coastguard Worker }
1854*1208bc7eSAndroid Build Coastguard Worker if (config_stats || (config_prof && opt_prof)) {
1855*1208bc7eSAndroid Build Coastguard Worker usize = sz_index2size(ind);
1856*1208bc7eSAndroid Build Coastguard Worker assert(usize > 0 && usize <= LARGE_MAXCLASS);
1857*1208bc7eSAndroid Build Coastguard Worker }
1858*1208bc7eSAndroid Build Coastguard Worker } else {
1859*1208bc7eSAndroid Build Coastguard Worker usize = sz_sa2u(size, dopts->alignment);
1860*1208bc7eSAndroid Build Coastguard Worker if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) {
1861*1208bc7eSAndroid Build Coastguard Worker goto label_oom;
1862*1208bc7eSAndroid Build Coastguard Worker }
1863*1208bc7eSAndroid Build Coastguard Worker }
1864*1208bc7eSAndroid Build Coastguard Worker
1865*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
1866*1208bc7eSAndroid Build Coastguard Worker
1867*1208bc7eSAndroid Build Coastguard Worker /*
1868*1208bc7eSAndroid Build Coastguard Worker * If we need to handle reentrancy, we can do it out of a
1869*1208bc7eSAndroid Build Coastguard Worker * known-initialized arena (i.e. arena 0).
1870*1208bc7eSAndroid Build Coastguard Worker */
1871*1208bc7eSAndroid Build Coastguard Worker reentrancy_level = tsd_reentrancy_level_get(tsd);
1872*1208bc7eSAndroid Build Coastguard Worker if (sopts->slow && unlikely(reentrancy_level > 0)) {
1873*1208bc7eSAndroid Build Coastguard Worker /*
1874*1208bc7eSAndroid Build Coastguard Worker * We should never specify particular arenas or tcaches from
1875*1208bc7eSAndroid Build Coastguard Worker * within our internal allocations.
1876*1208bc7eSAndroid Build Coastguard Worker */
1877*1208bc7eSAndroid Build Coastguard Worker assert(dopts->tcache_ind == TCACHE_IND_AUTOMATIC ||
1878*1208bc7eSAndroid Build Coastguard Worker dopts->tcache_ind == TCACHE_IND_NONE);
1879*1208bc7eSAndroid Build Coastguard Worker assert(dopts->arena_ind == ARENA_IND_AUTOMATIC);
1880*1208bc7eSAndroid Build Coastguard Worker dopts->tcache_ind = TCACHE_IND_NONE;
1881*1208bc7eSAndroid Build Coastguard Worker /* We know that arena 0 has already been initialized. */
1882*1208bc7eSAndroid Build Coastguard Worker dopts->arena_ind = 0;
1883*1208bc7eSAndroid Build Coastguard Worker }
1884*1208bc7eSAndroid Build Coastguard Worker
1885*1208bc7eSAndroid Build Coastguard Worker /* If profiling is on, get our profiling context. */
1886*1208bc7eSAndroid Build Coastguard Worker if (config_prof && opt_prof) {
1887*1208bc7eSAndroid Build Coastguard Worker /*
1888*1208bc7eSAndroid Build Coastguard Worker * Note that if we're going down this path, usize must have been
1889*1208bc7eSAndroid Build Coastguard Worker * initialized in the previous if statement.
1890*1208bc7eSAndroid Build Coastguard Worker */
1891*1208bc7eSAndroid Build Coastguard Worker prof_tctx_t *tctx = prof_alloc_prep(
1892*1208bc7eSAndroid Build Coastguard Worker tsd, usize, prof_active_get_unlocked(), true);
1893*1208bc7eSAndroid Build Coastguard Worker
1894*1208bc7eSAndroid Build Coastguard Worker alloc_ctx_t alloc_ctx;
1895*1208bc7eSAndroid Build Coastguard Worker if (likely((uintptr_t)tctx == (uintptr_t)1U)) {
1896*1208bc7eSAndroid Build Coastguard Worker alloc_ctx.slab = (usize <= SMALL_MAXCLASS);
1897*1208bc7eSAndroid Build Coastguard Worker allocation = imalloc_no_sample(
1898*1208bc7eSAndroid Build Coastguard Worker sopts, dopts, tsd, usize, usize, ind);
1899*1208bc7eSAndroid Build Coastguard Worker } else if ((uintptr_t)tctx > (uintptr_t)1U) {
1900*1208bc7eSAndroid Build Coastguard Worker /*
1901*1208bc7eSAndroid Build Coastguard Worker * Note that ind might still be 0 here. This is fine;
1902*1208bc7eSAndroid Build Coastguard Worker * imalloc_sample ignores ind if dopts->alignment > 0.
1903*1208bc7eSAndroid Build Coastguard Worker */
1904*1208bc7eSAndroid Build Coastguard Worker allocation = imalloc_sample(
1905*1208bc7eSAndroid Build Coastguard Worker sopts, dopts, tsd, usize, ind);
1906*1208bc7eSAndroid Build Coastguard Worker alloc_ctx.slab = false;
1907*1208bc7eSAndroid Build Coastguard Worker } else {
1908*1208bc7eSAndroid Build Coastguard Worker allocation = NULL;
1909*1208bc7eSAndroid Build Coastguard Worker }
1910*1208bc7eSAndroid Build Coastguard Worker
1911*1208bc7eSAndroid Build Coastguard Worker if (unlikely(allocation == NULL)) {
1912*1208bc7eSAndroid Build Coastguard Worker prof_alloc_rollback(tsd, tctx, true);
1913*1208bc7eSAndroid Build Coastguard Worker goto label_oom;
1914*1208bc7eSAndroid Build Coastguard Worker }
1915*1208bc7eSAndroid Build Coastguard Worker prof_malloc(tsd_tsdn(tsd), allocation, usize, &alloc_ctx, tctx);
1916*1208bc7eSAndroid Build Coastguard Worker } else {
1917*1208bc7eSAndroid Build Coastguard Worker /*
1918*1208bc7eSAndroid Build Coastguard Worker * If dopts->alignment > 0, then ind is still 0, but usize was
1919*1208bc7eSAndroid Build Coastguard Worker * computed in the previous if statement. Down the positive
1920*1208bc7eSAndroid Build Coastguard Worker * alignment path, imalloc_no_sample ignores ind and size
1921*1208bc7eSAndroid Build Coastguard Worker * (relying only on usize).
1922*1208bc7eSAndroid Build Coastguard Worker */
1923*1208bc7eSAndroid Build Coastguard Worker allocation = imalloc_no_sample(sopts, dopts, tsd, size, usize,
1924*1208bc7eSAndroid Build Coastguard Worker ind);
1925*1208bc7eSAndroid Build Coastguard Worker if (unlikely(allocation == NULL)) {
1926*1208bc7eSAndroid Build Coastguard Worker goto label_oom;
1927*1208bc7eSAndroid Build Coastguard Worker }
1928*1208bc7eSAndroid Build Coastguard Worker }
1929*1208bc7eSAndroid Build Coastguard Worker
1930*1208bc7eSAndroid Build Coastguard Worker /*
1931*1208bc7eSAndroid Build Coastguard Worker * Allocation has been done at this point. We still have some
1932*1208bc7eSAndroid Build Coastguard Worker * post-allocation work to do though.
1933*1208bc7eSAndroid Build Coastguard Worker */
1934*1208bc7eSAndroid Build Coastguard Worker assert(dopts->alignment == 0
1935*1208bc7eSAndroid Build Coastguard Worker || ((uintptr_t)allocation & (dopts->alignment - 1)) == ZU(0));
1936*1208bc7eSAndroid Build Coastguard Worker
1937*1208bc7eSAndroid Build Coastguard Worker if (config_stats) {
1938*1208bc7eSAndroid Build Coastguard Worker assert(usize == isalloc(tsd_tsdn(tsd), allocation));
1939*1208bc7eSAndroid Build Coastguard Worker *tsd_thread_allocatedp_get(tsd) += usize;
1940*1208bc7eSAndroid Build Coastguard Worker }
1941*1208bc7eSAndroid Build Coastguard Worker
1942*1208bc7eSAndroid Build Coastguard Worker if (sopts->slow) {
1943*1208bc7eSAndroid Build Coastguard Worker UTRACE(0, size, allocation);
1944*1208bc7eSAndroid Build Coastguard Worker }
1945*1208bc7eSAndroid Build Coastguard Worker
1946*1208bc7eSAndroid Build Coastguard Worker /* Success! */
1947*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
1948*1208bc7eSAndroid Build Coastguard Worker *dopts->result = allocation;
1949*1208bc7eSAndroid Build Coastguard Worker return 0;
1950*1208bc7eSAndroid Build Coastguard Worker
1951*1208bc7eSAndroid Build Coastguard Worker label_oom:
1952*1208bc7eSAndroid Build Coastguard Worker if (unlikely(sopts->slow) && config_xmalloc && unlikely(opt_xmalloc)) {
1953*1208bc7eSAndroid Build Coastguard Worker malloc_write(sopts->oom_string);
1954*1208bc7eSAndroid Build Coastguard Worker abort();
1955*1208bc7eSAndroid Build Coastguard Worker }
1956*1208bc7eSAndroid Build Coastguard Worker
1957*1208bc7eSAndroid Build Coastguard Worker if (sopts->slow) {
1958*1208bc7eSAndroid Build Coastguard Worker UTRACE(NULL, size, NULL);
1959*1208bc7eSAndroid Build Coastguard Worker }
1960*1208bc7eSAndroid Build Coastguard Worker
1961*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
1962*1208bc7eSAndroid Build Coastguard Worker
1963*1208bc7eSAndroid Build Coastguard Worker if (sopts->set_errno_on_error) {
1964*1208bc7eSAndroid Build Coastguard Worker set_errno(ENOMEM);
1965*1208bc7eSAndroid Build Coastguard Worker }
1966*1208bc7eSAndroid Build Coastguard Worker
1967*1208bc7eSAndroid Build Coastguard Worker if (sopts->null_out_result_on_error) {
1968*1208bc7eSAndroid Build Coastguard Worker *dopts->result = NULL;
1969*1208bc7eSAndroid Build Coastguard Worker }
1970*1208bc7eSAndroid Build Coastguard Worker
1971*1208bc7eSAndroid Build Coastguard Worker return ENOMEM;
1972*1208bc7eSAndroid Build Coastguard Worker
1973*1208bc7eSAndroid Build Coastguard Worker /*
1974*1208bc7eSAndroid Build Coastguard Worker * This label is only jumped to by one goto; we move it out of line
1975*1208bc7eSAndroid Build Coastguard Worker * anyways to avoid obscuring the non-error paths, and for symmetry with
1976*1208bc7eSAndroid Build Coastguard Worker * the oom case.
1977*1208bc7eSAndroid Build Coastguard Worker */
1978*1208bc7eSAndroid Build Coastguard Worker label_invalid_alignment:
1979*1208bc7eSAndroid Build Coastguard Worker if (config_xmalloc && unlikely(opt_xmalloc)) {
1980*1208bc7eSAndroid Build Coastguard Worker malloc_write(sopts->invalid_alignment_string);
1981*1208bc7eSAndroid Build Coastguard Worker abort();
1982*1208bc7eSAndroid Build Coastguard Worker }
1983*1208bc7eSAndroid Build Coastguard Worker
1984*1208bc7eSAndroid Build Coastguard Worker if (sopts->set_errno_on_error) {
1985*1208bc7eSAndroid Build Coastguard Worker set_errno(EINVAL);
1986*1208bc7eSAndroid Build Coastguard Worker }
1987*1208bc7eSAndroid Build Coastguard Worker
1988*1208bc7eSAndroid Build Coastguard Worker if (sopts->slow) {
1989*1208bc7eSAndroid Build Coastguard Worker UTRACE(NULL, size, NULL);
1990*1208bc7eSAndroid Build Coastguard Worker }
1991*1208bc7eSAndroid Build Coastguard Worker
1992*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
1993*1208bc7eSAndroid Build Coastguard Worker
1994*1208bc7eSAndroid Build Coastguard Worker if (sopts->null_out_result_on_error) {
1995*1208bc7eSAndroid Build Coastguard Worker *dopts->result = NULL;
1996*1208bc7eSAndroid Build Coastguard Worker }
1997*1208bc7eSAndroid Build Coastguard Worker
1998*1208bc7eSAndroid Build Coastguard Worker return EINVAL;
1999*1208bc7eSAndroid Build Coastguard Worker }
2000*1208bc7eSAndroid Build Coastguard Worker
2001*1208bc7eSAndroid Build Coastguard Worker /* Returns the errno-style error code of the allocation. */
2002*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE int
2003*1208bc7eSAndroid Build Coastguard Worker imalloc(static_opts_t *sopts, dynamic_opts_t *dopts) {
2004*1208bc7eSAndroid Build Coastguard Worker if (unlikely(!malloc_initialized()) && unlikely(malloc_init())) {
2005*1208bc7eSAndroid Build Coastguard Worker if (config_xmalloc && unlikely(opt_xmalloc)) {
2006*1208bc7eSAndroid Build Coastguard Worker malloc_write(sopts->oom_string);
2007*1208bc7eSAndroid Build Coastguard Worker abort();
2008*1208bc7eSAndroid Build Coastguard Worker }
2009*1208bc7eSAndroid Build Coastguard Worker UTRACE(NULL, dopts->num_items * dopts->item_size, NULL);
2010*1208bc7eSAndroid Build Coastguard Worker set_errno(ENOMEM);
2011*1208bc7eSAndroid Build Coastguard Worker *dopts->result = NULL;
2012*1208bc7eSAndroid Build Coastguard Worker
2013*1208bc7eSAndroid Build Coastguard Worker return ENOMEM;
2014*1208bc7eSAndroid Build Coastguard Worker }
2015*1208bc7eSAndroid Build Coastguard Worker
2016*1208bc7eSAndroid Build Coastguard Worker /* We always need the tsd. Let's grab it right away. */
2017*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd = tsd_fetch();
2018*1208bc7eSAndroid Build Coastguard Worker assert(tsd);
2019*1208bc7eSAndroid Build Coastguard Worker if (likely(tsd_fast(tsd))) {
2020*1208bc7eSAndroid Build Coastguard Worker /* Fast and common path. */
2021*1208bc7eSAndroid Build Coastguard Worker tsd_assert_fast(tsd);
2022*1208bc7eSAndroid Build Coastguard Worker sopts->slow = false;
2023*1208bc7eSAndroid Build Coastguard Worker return imalloc_body(sopts, dopts, tsd);
2024*1208bc7eSAndroid Build Coastguard Worker } else {
2025*1208bc7eSAndroid Build Coastguard Worker sopts->slow = true;
2026*1208bc7eSAndroid Build Coastguard Worker return imalloc_body(sopts, dopts, tsd);
2027*1208bc7eSAndroid Build Coastguard Worker }
2028*1208bc7eSAndroid Build Coastguard Worker }
2029*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
2030*1208bc7eSAndroid Build Coastguard Worker /*
2031*1208bc7eSAndroid Build Coastguard Worker * Begin malloc(3)-compatible functions.
2032*1208bc7eSAndroid Build Coastguard Worker */
2033*1208bc7eSAndroid Build Coastguard Worker
2034*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2035*1208bc7eSAndroid Build Coastguard Worker void JEMALLOC_NOTHROW *
2036*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1)
2037*1208bc7eSAndroid Build Coastguard Worker je_malloc(size_t size) {
2038*1208bc7eSAndroid Build Coastguard Worker void *ret;
2039*1208bc7eSAndroid Build Coastguard Worker static_opts_t sopts;
2040*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_t dopts;
2041*1208bc7eSAndroid Build Coastguard Worker
2042*1208bc7eSAndroid Build Coastguard Worker LOG("core.malloc.entry", "size: %zu", size);
2043*1208bc7eSAndroid Build Coastguard Worker
2044*1208bc7eSAndroid Build Coastguard Worker static_opts_init(&sopts);
2045*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_init(&dopts);
2046*1208bc7eSAndroid Build Coastguard Worker
2047*1208bc7eSAndroid Build Coastguard Worker sopts.bump_empty_alloc = true;
2048*1208bc7eSAndroid Build Coastguard Worker sopts.null_out_result_on_error = true;
2049*1208bc7eSAndroid Build Coastguard Worker sopts.set_errno_on_error = true;
2050*1208bc7eSAndroid Build Coastguard Worker sopts.oom_string = "<jemalloc>: Error in malloc(): out of memory\n";
2051*1208bc7eSAndroid Build Coastguard Worker
2052*1208bc7eSAndroid Build Coastguard Worker dopts.result = &ret;
2053*1208bc7eSAndroid Build Coastguard Worker dopts.num_items = 1;
2054*1208bc7eSAndroid Build Coastguard Worker dopts.item_size = size;
2055*1208bc7eSAndroid Build Coastguard Worker
2056*1208bc7eSAndroid Build Coastguard Worker imalloc(&sopts, &dopts);
2057*1208bc7eSAndroid Build Coastguard Worker
2058*1208bc7eSAndroid Build Coastguard Worker LOG("core.malloc.exit", "result: %p", ret);
2059*1208bc7eSAndroid Build Coastguard Worker
2060*1208bc7eSAndroid Build Coastguard Worker return ret;
2061*1208bc7eSAndroid Build Coastguard Worker }
2062*1208bc7eSAndroid Build Coastguard Worker
2063*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT int JEMALLOC_NOTHROW
2064*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(nonnull(1))
2065*1208bc7eSAndroid Build Coastguard Worker je_posix_memalign(void **memptr, size_t alignment, size_t size) {
2066*1208bc7eSAndroid Build Coastguard Worker int ret;
2067*1208bc7eSAndroid Build Coastguard Worker static_opts_t sopts;
2068*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_t dopts;
2069*1208bc7eSAndroid Build Coastguard Worker
2070*1208bc7eSAndroid Build Coastguard Worker LOG("core.posix_memalign.entry", "mem ptr: %p, alignment: %zu, "
2071*1208bc7eSAndroid Build Coastguard Worker "size: %zu", memptr, alignment, size);
2072*1208bc7eSAndroid Build Coastguard Worker
2073*1208bc7eSAndroid Build Coastguard Worker static_opts_init(&sopts);
2074*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_init(&dopts);
2075*1208bc7eSAndroid Build Coastguard Worker
2076*1208bc7eSAndroid Build Coastguard Worker sopts.bump_empty_alloc = true;
2077*1208bc7eSAndroid Build Coastguard Worker sopts.min_alignment = sizeof(void *);
2078*1208bc7eSAndroid Build Coastguard Worker sopts.oom_string =
2079*1208bc7eSAndroid Build Coastguard Worker "<jemalloc>: Error allocating aligned memory: out of memory\n";
2080*1208bc7eSAndroid Build Coastguard Worker sopts.invalid_alignment_string =
2081*1208bc7eSAndroid Build Coastguard Worker "<jemalloc>: Error allocating aligned memory: invalid alignment\n";
2082*1208bc7eSAndroid Build Coastguard Worker
2083*1208bc7eSAndroid Build Coastguard Worker dopts.result = memptr;
2084*1208bc7eSAndroid Build Coastguard Worker dopts.num_items = 1;
2085*1208bc7eSAndroid Build Coastguard Worker dopts.item_size = size;
2086*1208bc7eSAndroid Build Coastguard Worker dopts.alignment = alignment;
2087*1208bc7eSAndroid Build Coastguard Worker
2088*1208bc7eSAndroid Build Coastguard Worker ret = imalloc(&sopts, &dopts);
2089*1208bc7eSAndroid Build Coastguard Worker
2090*1208bc7eSAndroid Build Coastguard Worker LOG("core.posix_memalign.exit", "result: %d, alloc ptr: %p", ret,
2091*1208bc7eSAndroid Build Coastguard Worker *memptr);
2092*1208bc7eSAndroid Build Coastguard Worker
2093*1208bc7eSAndroid Build Coastguard Worker return ret;
2094*1208bc7eSAndroid Build Coastguard Worker }
2095*1208bc7eSAndroid Build Coastguard Worker
2096*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2097*1208bc7eSAndroid Build Coastguard Worker void JEMALLOC_NOTHROW *
2098*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(2)
2099*1208bc7eSAndroid Build Coastguard Worker je_aligned_alloc(size_t alignment, size_t size) {
2100*1208bc7eSAndroid Build Coastguard Worker void *ret;
2101*1208bc7eSAndroid Build Coastguard Worker
2102*1208bc7eSAndroid Build Coastguard Worker static_opts_t sopts;
2103*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_t dopts;
2104*1208bc7eSAndroid Build Coastguard Worker
2105*1208bc7eSAndroid Build Coastguard Worker LOG("core.aligned_alloc.entry", "alignment: %zu, size: %zu\n",
2106*1208bc7eSAndroid Build Coastguard Worker alignment, size);
2107*1208bc7eSAndroid Build Coastguard Worker
2108*1208bc7eSAndroid Build Coastguard Worker static_opts_init(&sopts);
2109*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_init(&dopts);
2110*1208bc7eSAndroid Build Coastguard Worker
2111*1208bc7eSAndroid Build Coastguard Worker sopts.bump_empty_alloc = true;
2112*1208bc7eSAndroid Build Coastguard Worker sopts.null_out_result_on_error = true;
2113*1208bc7eSAndroid Build Coastguard Worker sopts.set_errno_on_error = true;
2114*1208bc7eSAndroid Build Coastguard Worker sopts.min_alignment = 1;
2115*1208bc7eSAndroid Build Coastguard Worker sopts.oom_string =
2116*1208bc7eSAndroid Build Coastguard Worker "<jemalloc>: Error allocating aligned memory: out of memory\n";
2117*1208bc7eSAndroid Build Coastguard Worker sopts.invalid_alignment_string =
2118*1208bc7eSAndroid Build Coastguard Worker "<jemalloc>: Error allocating aligned memory: invalid alignment\n";
2119*1208bc7eSAndroid Build Coastguard Worker
2120*1208bc7eSAndroid Build Coastguard Worker dopts.result = &ret;
2121*1208bc7eSAndroid Build Coastguard Worker dopts.num_items = 1;
2122*1208bc7eSAndroid Build Coastguard Worker dopts.item_size = size;
2123*1208bc7eSAndroid Build Coastguard Worker dopts.alignment = alignment;
2124*1208bc7eSAndroid Build Coastguard Worker
2125*1208bc7eSAndroid Build Coastguard Worker imalloc(&sopts, &dopts);
2126*1208bc7eSAndroid Build Coastguard Worker
2127*1208bc7eSAndroid Build Coastguard Worker LOG("core.aligned_alloc.exit", "result: %p", ret);
2128*1208bc7eSAndroid Build Coastguard Worker
2129*1208bc7eSAndroid Build Coastguard Worker return ret;
2130*1208bc7eSAndroid Build Coastguard Worker }
2131*1208bc7eSAndroid Build Coastguard Worker
2132*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2133*1208bc7eSAndroid Build Coastguard Worker void JEMALLOC_NOTHROW *
2134*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2)
2135*1208bc7eSAndroid Build Coastguard Worker je_calloc(size_t num, size_t size) {
2136*1208bc7eSAndroid Build Coastguard Worker void *ret;
2137*1208bc7eSAndroid Build Coastguard Worker static_opts_t sopts;
2138*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_t dopts;
2139*1208bc7eSAndroid Build Coastguard Worker
2140*1208bc7eSAndroid Build Coastguard Worker LOG("core.calloc.entry", "num: %zu, size: %zu\n", num, size);
2141*1208bc7eSAndroid Build Coastguard Worker
2142*1208bc7eSAndroid Build Coastguard Worker static_opts_init(&sopts);
2143*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_init(&dopts);
2144*1208bc7eSAndroid Build Coastguard Worker
2145*1208bc7eSAndroid Build Coastguard Worker sopts.may_overflow = true;
2146*1208bc7eSAndroid Build Coastguard Worker sopts.bump_empty_alloc = true;
2147*1208bc7eSAndroid Build Coastguard Worker sopts.null_out_result_on_error = true;
2148*1208bc7eSAndroid Build Coastguard Worker sopts.set_errno_on_error = true;
2149*1208bc7eSAndroid Build Coastguard Worker sopts.oom_string = "<jemalloc>: Error in calloc(): out of memory\n";
2150*1208bc7eSAndroid Build Coastguard Worker
2151*1208bc7eSAndroid Build Coastguard Worker dopts.result = &ret;
2152*1208bc7eSAndroid Build Coastguard Worker dopts.num_items = num;
2153*1208bc7eSAndroid Build Coastguard Worker dopts.item_size = size;
2154*1208bc7eSAndroid Build Coastguard Worker dopts.zero = true;
2155*1208bc7eSAndroid Build Coastguard Worker
2156*1208bc7eSAndroid Build Coastguard Worker imalloc(&sopts, &dopts);
2157*1208bc7eSAndroid Build Coastguard Worker
2158*1208bc7eSAndroid Build Coastguard Worker LOG("core.calloc.exit", "result: %p", ret);
2159*1208bc7eSAndroid Build Coastguard Worker
2160*1208bc7eSAndroid Build Coastguard Worker return ret;
2161*1208bc7eSAndroid Build Coastguard Worker }
2162*1208bc7eSAndroid Build Coastguard Worker
2163*1208bc7eSAndroid Build Coastguard Worker static void *
2164*1208bc7eSAndroid Build Coastguard Worker irealloc_prof_sample(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize,
2165*1208bc7eSAndroid Build Coastguard Worker prof_tctx_t *tctx) {
2166*1208bc7eSAndroid Build Coastguard Worker void *p;
2167*1208bc7eSAndroid Build Coastguard Worker
2168*1208bc7eSAndroid Build Coastguard Worker if (tctx == NULL) {
2169*1208bc7eSAndroid Build Coastguard Worker return NULL;
2170*1208bc7eSAndroid Build Coastguard Worker }
2171*1208bc7eSAndroid Build Coastguard Worker if (usize <= SMALL_MAXCLASS) {
2172*1208bc7eSAndroid Build Coastguard Worker p = iralloc(tsd, old_ptr, old_usize, LARGE_MINCLASS, 0, false);
2173*1208bc7eSAndroid Build Coastguard Worker if (p == NULL) {
2174*1208bc7eSAndroid Build Coastguard Worker return NULL;
2175*1208bc7eSAndroid Build Coastguard Worker }
2176*1208bc7eSAndroid Build Coastguard Worker arena_prof_promote(tsd_tsdn(tsd), p, usize);
2177*1208bc7eSAndroid Build Coastguard Worker } else {
2178*1208bc7eSAndroid Build Coastguard Worker p = iralloc(tsd, old_ptr, old_usize, usize, 0, false);
2179*1208bc7eSAndroid Build Coastguard Worker }
2180*1208bc7eSAndroid Build Coastguard Worker
2181*1208bc7eSAndroid Build Coastguard Worker return p;
2182*1208bc7eSAndroid Build Coastguard Worker }
2183*1208bc7eSAndroid Build Coastguard Worker
2184*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void *
2185*1208bc7eSAndroid Build Coastguard Worker irealloc_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize,
2186*1208bc7eSAndroid Build Coastguard Worker alloc_ctx_t *alloc_ctx) {
2187*1208bc7eSAndroid Build Coastguard Worker void *p;
2188*1208bc7eSAndroid Build Coastguard Worker bool prof_active;
2189*1208bc7eSAndroid Build Coastguard Worker prof_tctx_t *old_tctx, *tctx;
2190*1208bc7eSAndroid Build Coastguard Worker
2191*1208bc7eSAndroid Build Coastguard Worker prof_active = prof_active_get_unlocked();
2192*1208bc7eSAndroid Build Coastguard Worker old_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr, alloc_ctx);
2193*1208bc7eSAndroid Build Coastguard Worker tctx = prof_alloc_prep(tsd, usize, prof_active, true);
2194*1208bc7eSAndroid Build Coastguard Worker if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {
2195*1208bc7eSAndroid Build Coastguard Worker p = irealloc_prof_sample(tsd, old_ptr, old_usize, usize, tctx);
2196*1208bc7eSAndroid Build Coastguard Worker } else {
2197*1208bc7eSAndroid Build Coastguard Worker p = iralloc(tsd, old_ptr, old_usize, usize, 0, false);
2198*1208bc7eSAndroid Build Coastguard Worker }
2199*1208bc7eSAndroid Build Coastguard Worker if (unlikely(p == NULL)) {
2200*1208bc7eSAndroid Build Coastguard Worker prof_alloc_rollback(tsd, tctx, true);
2201*1208bc7eSAndroid Build Coastguard Worker return NULL;
2202*1208bc7eSAndroid Build Coastguard Worker }
2203*1208bc7eSAndroid Build Coastguard Worker prof_realloc(tsd, p, usize, tctx, prof_active, true, old_ptr, old_usize,
2204*1208bc7eSAndroid Build Coastguard Worker old_tctx);
2205*1208bc7eSAndroid Build Coastguard Worker
2206*1208bc7eSAndroid Build Coastguard Worker return p;
2207*1208bc7eSAndroid Build Coastguard Worker }
2208*1208bc7eSAndroid Build Coastguard Worker
2209*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void
2210*1208bc7eSAndroid Build Coastguard Worker ifree(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path) {
2211*1208bc7eSAndroid Build Coastguard Worker if (!slow_path) {
2212*1208bc7eSAndroid Build Coastguard Worker tsd_assert_fast(tsd);
2213*1208bc7eSAndroid Build Coastguard Worker }
2214*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2215*1208bc7eSAndroid Build Coastguard Worker if (tsd_reentrancy_level_get(tsd) != 0) {
2216*1208bc7eSAndroid Build Coastguard Worker assert(slow_path);
2217*1208bc7eSAndroid Build Coastguard Worker }
2218*1208bc7eSAndroid Build Coastguard Worker
2219*1208bc7eSAndroid Build Coastguard Worker assert(ptr != NULL);
2220*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized() || IS_INITIALIZER);
2221*1208bc7eSAndroid Build Coastguard Worker
2222*1208bc7eSAndroid Build Coastguard Worker alloc_ctx_t alloc_ctx;
2223*1208bc7eSAndroid Build Coastguard Worker rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd);
2224*1208bc7eSAndroid Build Coastguard Worker rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx,
2225*1208bc7eSAndroid Build Coastguard Worker (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab);
2226*1208bc7eSAndroid Build Coastguard Worker assert(alloc_ctx.szind != NSIZES);
2227*1208bc7eSAndroid Build Coastguard Worker
2228*1208bc7eSAndroid Build Coastguard Worker size_t usize;
2229*1208bc7eSAndroid Build Coastguard Worker if (config_prof && opt_prof) {
2230*1208bc7eSAndroid Build Coastguard Worker usize = sz_index2size(alloc_ctx.szind);
2231*1208bc7eSAndroid Build Coastguard Worker prof_free(tsd, ptr, usize, &alloc_ctx);
2232*1208bc7eSAndroid Build Coastguard Worker } else if (config_stats) {
2233*1208bc7eSAndroid Build Coastguard Worker usize = sz_index2size(alloc_ctx.szind);
2234*1208bc7eSAndroid Build Coastguard Worker }
2235*1208bc7eSAndroid Build Coastguard Worker if (config_stats) {
2236*1208bc7eSAndroid Build Coastguard Worker *tsd_thread_deallocatedp_get(tsd) += usize;
2237*1208bc7eSAndroid Build Coastguard Worker }
2238*1208bc7eSAndroid Build Coastguard Worker
2239*1208bc7eSAndroid Build Coastguard Worker if (likely(!slow_path)) {
2240*1208bc7eSAndroid Build Coastguard Worker idalloctm(tsd_tsdn(tsd), ptr, tcache, &alloc_ctx, false,
2241*1208bc7eSAndroid Build Coastguard Worker false);
2242*1208bc7eSAndroid Build Coastguard Worker } else {
2243*1208bc7eSAndroid Build Coastguard Worker idalloctm(tsd_tsdn(tsd), ptr, tcache, &alloc_ctx, false,
2244*1208bc7eSAndroid Build Coastguard Worker true);
2245*1208bc7eSAndroid Build Coastguard Worker }
2246*1208bc7eSAndroid Build Coastguard Worker }
2247*1208bc7eSAndroid Build Coastguard Worker
2248*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void
2249*1208bc7eSAndroid Build Coastguard Worker isfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache, bool slow_path) {
2250*1208bc7eSAndroid Build Coastguard Worker if (!slow_path) {
2251*1208bc7eSAndroid Build Coastguard Worker tsd_assert_fast(tsd);
2252*1208bc7eSAndroid Build Coastguard Worker }
2253*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2254*1208bc7eSAndroid Build Coastguard Worker if (tsd_reentrancy_level_get(tsd) != 0) {
2255*1208bc7eSAndroid Build Coastguard Worker assert(slow_path);
2256*1208bc7eSAndroid Build Coastguard Worker }
2257*1208bc7eSAndroid Build Coastguard Worker
2258*1208bc7eSAndroid Build Coastguard Worker assert(ptr != NULL);
2259*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized() || IS_INITIALIZER);
2260*1208bc7eSAndroid Build Coastguard Worker
2261*1208bc7eSAndroid Build Coastguard Worker alloc_ctx_t alloc_ctx, *ctx;
2262*1208bc7eSAndroid Build Coastguard Worker if (!config_cache_oblivious && ((uintptr_t)ptr & PAGE_MASK) != 0) {
2263*1208bc7eSAndroid Build Coastguard Worker /*
2264*1208bc7eSAndroid Build Coastguard Worker * When cache_oblivious is disabled and ptr is not page aligned,
2265*1208bc7eSAndroid Build Coastguard Worker * the allocation was not sampled -- usize can be used to
2266*1208bc7eSAndroid Build Coastguard Worker * determine szind directly.
2267*1208bc7eSAndroid Build Coastguard Worker */
2268*1208bc7eSAndroid Build Coastguard Worker alloc_ctx.szind = sz_size2index(usize);
2269*1208bc7eSAndroid Build Coastguard Worker alloc_ctx.slab = true;
2270*1208bc7eSAndroid Build Coastguard Worker ctx = &alloc_ctx;
2271*1208bc7eSAndroid Build Coastguard Worker if (config_debug) {
2272*1208bc7eSAndroid Build Coastguard Worker alloc_ctx_t dbg_ctx;
2273*1208bc7eSAndroid Build Coastguard Worker rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd);
2274*1208bc7eSAndroid Build Coastguard Worker rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree,
2275*1208bc7eSAndroid Build Coastguard Worker rtree_ctx, (uintptr_t)ptr, true, &dbg_ctx.szind,
2276*1208bc7eSAndroid Build Coastguard Worker &dbg_ctx.slab);
2277*1208bc7eSAndroid Build Coastguard Worker assert(dbg_ctx.szind == alloc_ctx.szind);
2278*1208bc7eSAndroid Build Coastguard Worker assert(dbg_ctx.slab == alloc_ctx.slab);
2279*1208bc7eSAndroid Build Coastguard Worker }
2280*1208bc7eSAndroid Build Coastguard Worker } else if (config_prof && opt_prof) {
2281*1208bc7eSAndroid Build Coastguard Worker rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd);
2282*1208bc7eSAndroid Build Coastguard Worker rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx,
2283*1208bc7eSAndroid Build Coastguard Worker (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab);
2284*1208bc7eSAndroid Build Coastguard Worker assert(alloc_ctx.szind == sz_size2index(usize));
2285*1208bc7eSAndroid Build Coastguard Worker ctx = &alloc_ctx;
2286*1208bc7eSAndroid Build Coastguard Worker } else {
2287*1208bc7eSAndroid Build Coastguard Worker ctx = NULL;
2288*1208bc7eSAndroid Build Coastguard Worker }
2289*1208bc7eSAndroid Build Coastguard Worker
2290*1208bc7eSAndroid Build Coastguard Worker if (config_prof && opt_prof) {
2291*1208bc7eSAndroid Build Coastguard Worker prof_free(tsd, ptr, usize, ctx);
2292*1208bc7eSAndroid Build Coastguard Worker }
2293*1208bc7eSAndroid Build Coastguard Worker if (config_stats) {
2294*1208bc7eSAndroid Build Coastguard Worker *tsd_thread_deallocatedp_get(tsd) += usize;
2295*1208bc7eSAndroid Build Coastguard Worker }
2296*1208bc7eSAndroid Build Coastguard Worker
2297*1208bc7eSAndroid Build Coastguard Worker if (likely(!slow_path)) {
2298*1208bc7eSAndroid Build Coastguard Worker isdalloct(tsd_tsdn(tsd), ptr, usize, tcache, ctx, false);
2299*1208bc7eSAndroid Build Coastguard Worker } else {
2300*1208bc7eSAndroid Build Coastguard Worker isdalloct(tsd_tsdn(tsd), ptr, usize, tcache, ctx, true);
2301*1208bc7eSAndroid Build Coastguard Worker }
2302*1208bc7eSAndroid Build Coastguard Worker }
2303*1208bc7eSAndroid Build Coastguard Worker
2304*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2305*1208bc7eSAndroid Build Coastguard Worker void JEMALLOC_NOTHROW *
2306*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALLOC_SIZE(2)
2307*1208bc7eSAndroid Build Coastguard Worker je_realloc(void *ptr, size_t size) {
2308*1208bc7eSAndroid Build Coastguard Worker void *ret;
2309*1208bc7eSAndroid Build Coastguard Worker tsdn_t *tsdn JEMALLOC_CC_SILENCE_INIT(NULL);
2310*1208bc7eSAndroid Build Coastguard Worker size_t usize JEMALLOC_CC_SILENCE_INIT(0);
2311*1208bc7eSAndroid Build Coastguard Worker size_t old_usize = 0;
2312*1208bc7eSAndroid Build Coastguard Worker
2313*1208bc7eSAndroid Build Coastguard Worker LOG("core.realloc.entry", "ptr: %p, size: %zu\n", ptr, size);
2314*1208bc7eSAndroid Build Coastguard Worker
2315*1208bc7eSAndroid Build Coastguard Worker if (unlikely(size == 0)) {
2316*1208bc7eSAndroid Build Coastguard Worker if (ptr != NULL) {
2317*1208bc7eSAndroid Build Coastguard Worker /* realloc(ptr, 0) is equivalent to free(ptr). */
2318*1208bc7eSAndroid Build Coastguard Worker UTRACE(ptr, 0, 0);
2319*1208bc7eSAndroid Build Coastguard Worker tcache_t *tcache;
2320*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd = tsd_fetch();
2321*1208bc7eSAndroid Build Coastguard Worker if (tsd_reentrancy_level_get(tsd) == 0) {
2322*1208bc7eSAndroid Build Coastguard Worker tcache = tcache_get(tsd);
2323*1208bc7eSAndroid Build Coastguard Worker } else {
2324*1208bc7eSAndroid Build Coastguard Worker tcache = NULL;
2325*1208bc7eSAndroid Build Coastguard Worker }
2326*1208bc7eSAndroid Build Coastguard Worker ifree(tsd, ptr, tcache, true);
2327*1208bc7eSAndroid Build Coastguard Worker
2328*1208bc7eSAndroid Build Coastguard Worker LOG("core.realloc.exit", "result: %p", NULL);
2329*1208bc7eSAndroid Build Coastguard Worker return NULL;
2330*1208bc7eSAndroid Build Coastguard Worker }
2331*1208bc7eSAndroid Build Coastguard Worker size = 1;
2332*1208bc7eSAndroid Build Coastguard Worker }
2333*1208bc7eSAndroid Build Coastguard Worker
2334*1208bc7eSAndroid Build Coastguard Worker if (likely(ptr != NULL)) {
2335*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized() || IS_INITIALIZER);
2336*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd = tsd_fetch();
2337*1208bc7eSAndroid Build Coastguard Worker
2338*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2339*1208bc7eSAndroid Build Coastguard Worker
2340*1208bc7eSAndroid Build Coastguard Worker alloc_ctx_t alloc_ctx;
2341*1208bc7eSAndroid Build Coastguard Worker rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd);
2342*1208bc7eSAndroid Build Coastguard Worker rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx,
2343*1208bc7eSAndroid Build Coastguard Worker (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab);
2344*1208bc7eSAndroid Build Coastguard Worker assert(alloc_ctx.szind != NSIZES);
2345*1208bc7eSAndroid Build Coastguard Worker old_usize = sz_index2size(alloc_ctx.szind);
2346*1208bc7eSAndroid Build Coastguard Worker assert(old_usize == isalloc(tsd_tsdn(tsd), ptr));
2347*1208bc7eSAndroid Build Coastguard Worker if (config_prof && opt_prof) {
2348*1208bc7eSAndroid Build Coastguard Worker usize = sz_s2u(size);
2349*1208bc7eSAndroid Build Coastguard Worker ret = unlikely(usize == 0 || usize > LARGE_MAXCLASS) ?
2350*1208bc7eSAndroid Build Coastguard Worker NULL : irealloc_prof(tsd, ptr, old_usize, usize,
2351*1208bc7eSAndroid Build Coastguard Worker &alloc_ctx);
2352*1208bc7eSAndroid Build Coastguard Worker } else {
2353*1208bc7eSAndroid Build Coastguard Worker if (config_stats) {
2354*1208bc7eSAndroid Build Coastguard Worker usize = sz_s2u(size);
2355*1208bc7eSAndroid Build Coastguard Worker }
2356*1208bc7eSAndroid Build Coastguard Worker ret = iralloc(tsd, ptr, old_usize, size, 0, false);
2357*1208bc7eSAndroid Build Coastguard Worker }
2358*1208bc7eSAndroid Build Coastguard Worker tsdn = tsd_tsdn(tsd);
2359*1208bc7eSAndroid Build Coastguard Worker } else {
2360*1208bc7eSAndroid Build Coastguard Worker /* realloc(NULL, size) is equivalent to malloc(size). */
2361*1208bc7eSAndroid Build Coastguard Worker void *ret = je_malloc(size);
2362*1208bc7eSAndroid Build Coastguard Worker LOG("core.realloc.exit", "result: %p", ret);
2363*1208bc7eSAndroid Build Coastguard Worker return ret;
2364*1208bc7eSAndroid Build Coastguard Worker }
2365*1208bc7eSAndroid Build Coastguard Worker
2366*1208bc7eSAndroid Build Coastguard Worker if (unlikely(ret == NULL)) {
2367*1208bc7eSAndroid Build Coastguard Worker if (config_xmalloc && unlikely(opt_xmalloc)) {
2368*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Error in realloc(): "
2369*1208bc7eSAndroid Build Coastguard Worker "out of memory\n");
2370*1208bc7eSAndroid Build Coastguard Worker abort();
2371*1208bc7eSAndroid Build Coastguard Worker }
2372*1208bc7eSAndroid Build Coastguard Worker set_errno(ENOMEM);
2373*1208bc7eSAndroid Build Coastguard Worker }
2374*1208bc7eSAndroid Build Coastguard Worker if (config_stats && likely(ret != NULL)) {
2375*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd;
2376*1208bc7eSAndroid Build Coastguard Worker
2377*1208bc7eSAndroid Build Coastguard Worker assert(usize == isalloc(tsdn, ret));
2378*1208bc7eSAndroid Build Coastguard Worker tsd = tsdn_tsd(tsdn);
2379*1208bc7eSAndroid Build Coastguard Worker *tsd_thread_allocatedp_get(tsd) += usize;
2380*1208bc7eSAndroid Build Coastguard Worker *tsd_thread_deallocatedp_get(tsd) += old_usize;
2381*1208bc7eSAndroid Build Coastguard Worker }
2382*1208bc7eSAndroid Build Coastguard Worker UTRACE(ptr, size, ret);
2383*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
2384*1208bc7eSAndroid Build Coastguard Worker
2385*1208bc7eSAndroid Build Coastguard Worker LOG("core.realloc.exit", "result: %p", ret);
2386*1208bc7eSAndroid Build Coastguard Worker return ret;
2387*1208bc7eSAndroid Build Coastguard Worker }
2388*1208bc7eSAndroid Build Coastguard Worker
2389*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void JEMALLOC_NOTHROW
2390*1208bc7eSAndroid Build Coastguard Worker je_free(void *ptr) {
2391*1208bc7eSAndroid Build Coastguard Worker LOG("core.free.entry", "ptr: %p", ptr);
2392*1208bc7eSAndroid Build Coastguard Worker
2393*1208bc7eSAndroid Build Coastguard Worker UTRACE(ptr, 0, 0);
2394*1208bc7eSAndroid Build Coastguard Worker if (likely(ptr != NULL)) {
2395*1208bc7eSAndroid Build Coastguard Worker /*
2396*1208bc7eSAndroid Build Coastguard Worker * We avoid setting up tsd fully (e.g. tcache, arena binding)
2397*1208bc7eSAndroid Build Coastguard Worker * based on only free() calls -- other activities trigger the
2398*1208bc7eSAndroid Build Coastguard Worker * minimal to full transition. This is because free() may
2399*1208bc7eSAndroid Build Coastguard Worker * happen during thread shutdown after tls deallocation: if a
2400*1208bc7eSAndroid Build Coastguard Worker * thread never had any malloc activities until then, a
2401*1208bc7eSAndroid Build Coastguard Worker * fully-setup tsd won't be destructed properly.
2402*1208bc7eSAndroid Build Coastguard Worker */
2403*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd = tsd_fetch_min();
2404*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2405*1208bc7eSAndroid Build Coastguard Worker
2406*1208bc7eSAndroid Build Coastguard Worker tcache_t *tcache;
2407*1208bc7eSAndroid Build Coastguard Worker if (likely(tsd_fast(tsd))) {
2408*1208bc7eSAndroid Build Coastguard Worker tsd_assert_fast(tsd);
2409*1208bc7eSAndroid Build Coastguard Worker /* Unconditionally get tcache ptr on fast path. */
2410*1208bc7eSAndroid Build Coastguard Worker tcache = tsd_tcachep_get(tsd);
2411*1208bc7eSAndroid Build Coastguard Worker ifree(tsd, ptr, tcache, false);
2412*1208bc7eSAndroid Build Coastguard Worker } else {
2413*1208bc7eSAndroid Build Coastguard Worker if (likely(tsd_reentrancy_level_get(tsd) == 0)) {
2414*1208bc7eSAndroid Build Coastguard Worker tcache = tcache_get(tsd);
2415*1208bc7eSAndroid Build Coastguard Worker } else {
2416*1208bc7eSAndroid Build Coastguard Worker tcache = NULL;
2417*1208bc7eSAndroid Build Coastguard Worker }
2418*1208bc7eSAndroid Build Coastguard Worker ifree(tsd, ptr, tcache, true);
2419*1208bc7eSAndroid Build Coastguard Worker }
2420*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2421*1208bc7eSAndroid Build Coastguard Worker }
2422*1208bc7eSAndroid Build Coastguard Worker LOG("core.free.exit", "");
2423*1208bc7eSAndroid Build Coastguard Worker }
2424*1208bc7eSAndroid Build Coastguard Worker
2425*1208bc7eSAndroid Build Coastguard Worker /*
2426*1208bc7eSAndroid Build Coastguard Worker * End malloc(3)-compatible functions.
2427*1208bc7eSAndroid Build Coastguard Worker */
2428*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
2429*1208bc7eSAndroid Build Coastguard Worker /*
2430*1208bc7eSAndroid Build Coastguard Worker * Begin non-standard override functions.
2431*1208bc7eSAndroid Build Coastguard Worker */
2432*1208bc7eSAndroid Build Coastguard Worker
2433*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_OVERRIDE_MEMALIGN
2434*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2435*1208bc7eSAndroid Build Coastguard Worker void JEMALLOC_NOTHROW *
2436*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(malloc)
2437*1208bc7eSAndroid Build Coastguard Worker je_memalign(size_t alignment, size_t size) {
2438*1208bc7eSAndroid Build Coastguard Worker void *ret;
2439*1208bc7eSAndroid Build Coastguard Worker static_opts_t sopts;
2440*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_t dopts;
2441*1208bc7eSAndroid Build Coastguard Worker
2442*1208bc7eSAndroid Build Coastguard Worker LOG("core.memalign.entry", "alignment: %zu, size: %zu\n", alignment,
2443*1208bc7eSAndroid Build Coastguard Worker size);
2444*1208bc7eSAndroid Build Coastguard Worker
2445*1208bc7eSAndroid Build Coastguard Worker static_opts_init(&sopts);
2446*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_init(&dopts);
2447*1208bc7eSAndroid Build Coastguard Worker
2448*1208bc7eSAndroid Build Coastguard Worker sopts.bump_empty_alloc = true;
2449*1208bc7eSAndroid Build Coastguard Worker sopts.min_alignment = 1;
2450*1208bc7eSAndroid Build Coastguard Worker sopts.oom_string =
2451*1208bc7eSAndroid Build Coastguard Worker "<jemalloc>: Error allocating aligned memory: out of memory\n";
2452*1208bc7eSAndroid Build Coastguard Worker sopts.invalid_alignment_string =
2453*1208bc7eSAndroid Build Coastguard Worker "<jemalloc>: Error allocating aligned memory: invalid alignment\n";
2454*1208bc7eSAndroid Build Coastguard Worker sopts.null_out_result_on_error = true;
2455*1208bc7eSAndroid Build Coastguard Worker
2456*1208bc7eSAndroid Build Coastguard Worker dopts.result = &ret;
2457*1208bc7eSAndroid Build Coastguard Worker dopts.num_items = 1;
2458*1208bc7eSAndroid Build Coastguard Worker dopts.item_size = size;
2459*1208bc7eSAndroid Build Coastguard Worker dopts.alignment = alignment;
2460*1208bc7eSAndroid Build Coastguard Worker
2461*1208bc7eSAndroid Build Coastguard Worker imalloc(&sopts, &dopts);
2462*1208bc7eSAndroid Build Coastguard Worker
2463*1208bc7eSAndroid Build Coastguard Worker LOG("core.memalign.exit", "result: %p", ret);
2464*1208bc7eSAndroid Build Coastguard Worker return ret;
2465*1208bc7eSAndroid Build Coastguard Worker }
2466*1208bc7eSAndroid Build Coastguard Worker #endif
2467*1208bc7eSAndroid Build Coastguard Worker
2468*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_OVERRIDE_VALLOC
2469*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2470*1208bc7eSAndroid Build Coastguard Worker void JEMALLOC_NOTHROW *
2471*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(malloc)
2472*1208bc7eSAndroid Build Coastguard Worker je_valloc(size_t size) {
2473*1208bc7eSAndroid Build Coastguard Worker void *ret;
2474*1208bc7eSAndroid Build Coastguard Worker
2475*1208bc7eSAndroid Build Coastguard Worker static_opts_t sopts;
2476*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_t dopts;
2477*1208bc7eSAndroid Build Coastguard Worker
2478*1208bc7eSAndroid Build Coastguard Worker LOG("core.valloc.entry", "size: %zu\n", size);
2479*1208bc7eSAndroid Build Coastguard Worker
2480*1208bc7eSAndroid Build Coastguard Worker static_opts_init(&sopts);
2481*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_init(&dopts);
2482*1208bc7eSAndroid Build Coastguard Worker
2483*1208bc7eSAndroid Build Coastguard Worker sopts.bump_empty_alloc = true;
2484*1208bc7eSAndroid Build Coastguard Worker sopts.null_out_result_on_error = true;
2485*1208bc7eSAndroid Build Coastguard Worker sopts.min_alignment = PAGE;
2486*1208bc7eSAndroid Build Coastguard Worker sopts.oom_string =
2487*1208bc7eSAndroid Build Coastguard Worker "<jemalloc>: Error allocating aligned memory: out of memory\n";
2488*1208bc7eSAndroid Build Coastguard Worker sopts.invalid_alignment_string =
2489*1208bc7eSAndroid Build Coastguard Worker "<jemalloc>: Error allocating aligned memory: invalid alignment\n";
2490*1208bc7eSAndroid Build Coastguard Worker
2491*1208bc7eSAndroid Build Coastguard Worker dopts.result = &ret;
2492*1208bc7eSAndroid Build Coastguard Worker dopts.num_items = 1;
2493*1208bc7eSAndroid Build Coastguard Worker dopts.item_size = size;
2494*1208bc7eSAndroid Build Coastguard Worker dopts.alignment = PAGE;
2495*1208bc7eSAndroid Build Coastguard Worker
2496*1208bc7eSAndroid Build Coastguard Worker imalloc(&sopts, &dopts);
2497*1208bc7eSAndroid Build Coastguard Worker
2498*1208bc7eSAndroid Build Coastguard Worker LOG("core.valloc.exit", "result: %p\n", ret);
2499*1208bc7eSAndroid Build Coastguard Worker return ret;
2500*1208bc7eSAndroid Build Coastguard Worker }
2501*1208bc7eSAndroid Build Coastguard Worker #endif
2502*1208bc7eSAndroid Build Coastguard Worker
2503*1208bc7eSAndroid Build Coastguard Worker #if defined(JEMALLOC_IS_MALLOC) && defined(JEMALLOC_GLIBC_MALLOC_HOOK)
2504*1208bc7eSAndroid Build Coastguard Worker /*
2505*1208bc7eSAndroid Build Coastguard Worker * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible
2506*1208bc7eSAndroid Build Coastguard Worker * to inconsistently reference libc's malloc(3)-compatible functions
2507*1208bc7eSAndroid Build Coastguard Worker * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541).
2508*1208bc7eSAndroid Build Coastguard Worker *
2509*1208bc7eSAndroid Build Coastguard Worker * These definitions interpose hooks in glibc. The functions are actually
2510*1208bc7eSAndroid Build Coastguard Worker * passed an extra argument for the caller return address, which will be
2511*1208bc7eSAndroid Build Coastguard Worker * ignored.
2512*1208bc7eSAndroid Build Coastguard Worker */
2513*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void (*__free_hook)(void *ptr) = je_free;
2514*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void *(*__malloc_hook)(size_t size) = je_malloc;
2515*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc;
2516*1208bc7eSAndroid Build Coastguard Worker # ifdef JEMALLOC_GLIBC_MEMALIGN_HOOK
2517*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) =
2518*1208bc7eSAndroid Build Coastguard Worker je_memalign;
2519*1208bc7eSAndroid Build Coastguard Worker # endif
2520*1208bc7eSAndroid Build Coastguard Worker
2521*1208bc7eSAndroid Build Coastguard Worker # ifdef CPU_COUNT
2522*1208bc7eSAndroid Build Coastguard Worker /*
2523*1208bc7eSAndroid Build Coastguard Worker * To enable static linking with glibc, the libc specific malloc interface must
2524*1208bc7eSAndroid Build Coastguard Worker * be implemented also, so none of glibc's malloc.o functions are added to the
2525*1208bc7eSAndroid Build Coastguard Worker * link.
2526*1208bc7eSAndroid Build Coastguard Worker */
2527*1208bc7eSAndroid Build Coastguard Worker # define ALIAS(je_fn) __attribute__((alias (#je_fn), used))
2528*1208bc7eSAndroid Build Coastguard Worker /* To force macro expansion of je_ prefix before stringification. */
2529*1208bc7eSAndroid Build Coastguard Worker # define PREALIAS(je_fn) ALIAS(je_fn)
2530*1208bc7eSAndroid Build Coastguard Worker # ifdef JEMALLOC_OVERRIDE___LIBC_CALLOC
2531*1208bc7eSAndroid Build Coastguard Worker void *__libc_calloc(size_t n, size_t size) PREALIAS(je_calloc);
2532*1208bc7eSAndroid Build Coastguard Worker # endif
2533*1208bc7eSAndroid Build Coastguard Worker # ifdef JEMALLOC_OVERRIDE___LIBC_FREE
2534*1208bc7eSAndroid Build Coastguard Worker void __libc_free(void* ptr) PREALIAS(je_free);
2535*1208bc7eSAndroid Build Coastguard Worker # endif
2536*1208bc7eSAndroid Build Coastguard Worker # ifdef JEMALLOC_OVERRIDE___LIBC_MALLOC
2537*1208bc7eSAndroid Build Coastguard Worker void *__libc_malloc(size_t size) PREALIAS(je_malloc);
2538*1208bc7eSAndroid Build Coastguard Worker # endif
2539*1208bc7eSAndroid Build Coastguard Worker # ifdef JEMALLOC_OVERRIDE___LIBC_MEMALIGN
2540*1208bc7eSAndroid Build Coastguard Worker void *__libc_memalign(size_t align, size_t s) PREALIAS(je_memalign);
2541*1208bc7eSAndroid Build Coastguard Worker # endif
2542*1208bc7eSAndroid Build Coastguard Worker # ifdef JEMALLOC_OVERRIDE___LIBC_REALLOC
2543*1208bc7eSAndroid Build Coastguard Worker void *__libc_realloc(void* ptr, size_t size) PREALIAS(je_realloc);
2544*1208bc7eSAndroid Build Coastguard Worker # endif
2545*1208bc7eSAndroid Build Coastguard Worker # ifdef JEMALLOC_OVERRIDE___LIBC_VALLOC
2546*1208bc7eSAndroid Build Coastguard Worker void *__libc_valloc(size_t size) PREALIAS(je_valloc);
2547*1208bc7eSAndroid Build Coastguard Worker # endif
2548*1208bc7eSAndroid Build Coastguard Worker # ifdef JEMALLOC_OVERRIDE___POSIX_MEMALIGN
2549*1208bc7eSAndroid Build Coastguard Worker int __posix_memalign(void** r, size_t a, size_t s) PREALIAS(je_posix_memalign);
2550*1208bc7eSAndroid Build Coastguard Worker # endif
2551*1208bc7eSAndroid Build Coastguard Worker # undef PREALIAS
2552*1208bc7eSAndroid Build Coastguard Worker # undef ALIAS
2553*1208bc7eSAndroid Build Coastguard Worker # endif
2554*1208bc7eSAndroid Build Coastguard Worker #endif
2555*1208bc7eSAndroid Build Coastguard Worker
2556*1208bc7eSAndroid Build Coastguard Worker /*
2557*1208bc7eSAndroid Build Coastguard Worker * End non-standard override functions.
2558*1208bc7eSAndroid Build Coastguard Worker */
2559*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
2560*1208bc7eSAndroid Build Coastguard Worker /*
2561*1208bc7eSAndroid Build Coastguard Worker * Begin non-standard functions.
2562*1208bc7eSAndroid Build Coastguard Worker */
2563*1208bc7eSAndroid Build Coastguard Worker
2564*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2565*1208bc7eSAndroid Build Coastguard Worker void JEMALLOC_NOTHROW *
2566*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1)
2567*1208bc7eSAndroid Build Coastguard Worker je_mallocx(size_t size, int flags) {
2568*1208bc7eSAndroid Build Coastguard Worker void *ret;
2569*1208bc7eSAndroid Build Coastguard Worker static_opts_t sopts;
2570*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_t dopts;
2571*1208bc7eSAndroid Build Coastguard Worker
2572*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallocx.entry", "size: %zu, flags: %d", size, flags);
2573*1208bc7eSAndroid Build Coastguard Worker
2574*1208bc7eSAndroid Build Coastguard Worker static_opts_init(&sopts);
2575*1208bc7eSAndroid Build Coastguard Worker dynamic_opts_init(&dopts);
2576*1208bc7eSAndroid Build Coastguard Worker
2577*1208bc7eSAndroid Build Coastguard Worker sopts.assert_nonempty_alloc = true;
2578*1208bc7eSAndroid Build Coastguard Worker sopts.null_out_result_on_error = true;
2579*1208bc7eSAndroid Build Coastguard Worker sopts.oom_string = "<jemalloc>: Error in mallocx(): out of memory\n";
2580*1208bc7eSAndroid Build Coastguard Worker
2581*1208bc7eSAndroid Build Coastguard Worker dopts.result = &ret;
2582*1208bc7eSAndroid Build Coastguard Worker dopts.num_items = 1;
2583*1208bc7eSAndroid Build Coastguard Worker dopts.item_size = size;
2584*1208bc7eSAndroid Build Coastguard Worker if (unlikely(flags != 0)) {
2585*1208bc7eSAndroid Build Coastguard Worker if ((flags & MALLOCX_LG_ALIGN_MASK) != 0) {
2586*1208bc7eSAndroid Build Coastguard Worker dopts.alignment = MALLOCX_ALIGN_GET_SPECIFIED(flags);
2587*1208bc7eSAndroid Build Coastguard Worker }
2588*1208bc7eSAndroid Build Coastguard Worker
2589*1208bc7eSAndroid Build Coastguard Worker dopts.zero = MALLOCX_ZERO_GET(flags);
2590*1208bc7eSAndroid Build Coastguard Worker
2591*1208bc7eSAndroid Build Coastguard Worker if ((flags & MALLOCX_TCACHE_MASK) != 0) {
2592*1208bc7eSAndroid Build Coastguard Worker if ((flags & MALLOCX_TCACHE_MASK)
2593*1208bc7eSAndroid Build Coastguard Worker == MALLOCX_TCACHE_NONE) {
2594*1208bc7eSAndroid Build Coastguard Worker dopts.tcache_ind = TCACHE_IND_NONE;
2595*1208bc7eSAndroid Build Coastguard Worker } else {
2596*1208bc7eSAndroid Build Coastguard Worker dopts.tcache_ind = MALLOCX_TCACHE_GET(flags);
2597*1208bc7eSAndroid Build Coastguard Worker }
2598*1208bc7eSAndroid Build Coastguard Worker } else {
2599*1208bc7eSAndroid Build Coastguard Worker dopts.tcache_ind = TCACHE_IND_AUTOMATIC;
2600*1208bc7eSAndroid Build Coastguard Worker }
2601*1208bc7eSAndroid Build Coastguard Worker
2602*1208bc7eSAndroid Build Coastguard Worker if ((flags & MALLOCX_ARENA_MASK) != 0)
2603*1208bc7eSAndroid Build Coastguard Worker dopts.arena_ind = MALLOCX_ARENA_GET(flags);
2604*1208bc7eSAndroid Build Coastguard Worker }
2605*1208bc7eSAndroid Build Coastguard Worker
2606*1208bc7eSAndroid Build Coastguard Worker imalloc(&sopts, &dopts);
2607*1208bc7eSAndroid Build Coastguard Worker
2608*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallocx.exit", "result: %p", ret);
2609*1208bc7eSAndroid Build Coastguard Worker return ret;
2610*1208bc7eSAndroid Build Coastguard Worker }
2611*1208bc7eSAndroid Build Coastguard Worker
2612*1208bc7eSAndroid Build Coastguard Worker static void *
2613*1208bc7eSAndroid Build Coastguard Worker irallocx_prof_sample(tsdn_t *tsdn, void *old_ptr, size_t old_usize,
2614*1208bc7eSAndroid Build Coastguard Worker size_t usize, size_t alignment, bool zero, tcache_t *tcache, arena_t *arena,
2615*1208bc7eSAndroid Build Coastguard Worker prof_tctx_t *tctx) {
2616*1208bc7eSAndroid Build Coastguard Worker void *p;
2617*1208bc7eSAndroid Build Coastguard Worker
2618*1208bc7eSAndroid Build Coastguard Worker if (tctx == NULL) {
2619*1208bc7eSAndroid Build Coastguard Worker return NULL;
2620*1208bc7eSAndroid Build Coastguard Worker }
2621*1208bc7eSAndroid Build Coastguard Worker if (usize <= SMALL_MAXCLASS) {
2622*1208bc7eSAndroid Build Coastguard Worker p = iralloct(tsdn, old_ptr, old_usize, LARGE_MINCLASS,
2623*1208bc7eSAndroid Build Coastguard Worker alignment, zero, tcache, arena);
2624*1208bc7eSAndroid Build Coastguard Worker if (p == NULL) {
2625*1208bc7eSAndroid Build Coastguard Worker return NULL;
2626*1208bc7eSAndroid Build Coastguard Worker }
2627*1208bc7eSAndroid Build Coastguard Worker arena_prof_promote(tsdn, p, usize);
2628*1208bc7eSAndroid Build Coastguard Worker } else {
2629*1208bc7eSAndroid Build Coastguard Worker p = iralloct(tsdn, old_ptr, old_usize, usize, alignment, zero,
2630*1208bc7eSAndroid Build Coastguard Worker tcache, arena);
2631*1208bc7eSAndroid Build Coastguard Worker }
2632*1208bc7eSAndroid Build Coastguard Worker
2633*1208bc7eSAndroid Build Coastguard Worker return p;
2634*1208bc7eSAndroid Build Coastguard Worker }
2635*1208bc7eSAndroid Build Coastguard Worker
2636*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void *
2637*1208bc7eSAndroid Build Coastguard Worker irallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size,
2638*1208bc7eSAndroid Build Coastguard Worker size_t alignment, size_t *usize, bool zero, tcache_t *tcache,
2639*1208bc7eSAndroid Build Coastguard Worker arena_t *arena, alloc_ctx_t *alloc_ctx) {
2640*1208bc7eSAndroid Build Coastguard Worker void *p;
2641*1208bc7eSAndroid Build Coastguard Worker bool prof_active;
2642*1208bc7eSAndroid Build Coastguard Worker prof_tctx_t *old_tctx, *tctx;
2643*1208bc7eSAndroid Build Coastguard Worker
2644*1208bc7eSAndroid Build Coastguard Worker prof_active = prof_active_get_unlocked();
2645*1208bc7eSAndroid Build Coastguard Worker old_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr, alloc_ctx);
2646*1208bc7eSAndroid Build Coastguard Worker tctx = prof_alloc_prep(tsd, *usize, prof_active, false);
2647*1208bc7eSAndroid Build Coastguard Worker if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {
2648*1208bc7eSAndroid Build Coastguard Worker p = irallocx_prof_sample(tsd_tsdn(tsd), old_ptr, old_usize,
2649*1208bc7eSAndroid Build Coastguard Worker *usize, alignment, zero, tcache, arena, tctx);
2650*1208bc7eSAndroid Build Coastguard Worker } else {
2651*1208bc7eSAndroid Build Coastguard Worker p = iralloct(tsd_tsdn(tsd), old_ptr, old_usize, size, alignment,
2652*1208bc7eSAndroid Build Coastguard Worker zero, tcache, arena);
2653*1208bc7eSAndroid Build Coastguard Worker }
2654*1208bc7eSAndroid Build Coastguard Worker if (unlikely(p == NULL)) {
2655*1208bc7eSAndroid Build Coastguard Worker prof_alloc_rollback(tsd, tctx, false);
2656*1208bc7eSAndroid Build Coastguard Worker return NULL;
2657*1208bc7eSAndroid Build Coastguard Worker }
2658*1208bc7eSAndroid Build Coastguard Worker
2659*1208bc7eSAndroid Build Coastguard Worker if (p == old_ptr && alignment != 0) {
2660*1208bc7eSAndroid Build Coastguard Worker /*
2661*1208bc7eSAndroid Build Coastguard Worker * The allocation did not move, so it is possible that the size
2662*1208bc7eSAndroid Build Coastguard Worker * class is smaller than would guarantee the requested
2663*1208bc7eSAndroid Build Coastguard Worker * alignment, and that the alignment constraint was
2664*1208bc7eSAndroid Build Coastguard Worker * serendipitously satisfied. Additionally, old_usize may not
2665*1208bc7eSAndroid Build Coastguard Worker * be the same as the current usize because of in-place large
2666*1208bc7eSAndroid Build Coastguard Worker * reallocation. Therefore, query the actual value of usize.
2667*1208bc7eSAndroid Build Coastguard Worker */
2668*1208bc7eSAndroid Build Coastguard Worker *usize = isalloc(tsd_tsdn(tsd), p);
2669*1208bc7eSAndroid Build Coastguard Worker }
2670*1208bc7eSAndroid Build Coastguard Worker prof_realloc(tsd, p, *usize, tctx, prof_active, false, old_ptr,
2671*1208bc7eSAndroid Build Coastguard Worker old_usize, old_tctx);
2672*1208bc7eSAndroid Build Coastguard Worker
2673*1208bc7eSAndroid Build Coastguard Worker return p;
2674*1208bc7eSAndroid Build Coastguard Worker }
2675*1208bc7eSAndroid Build Coastguard Worker
2676*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2677*1208bc7eSAndroid Build Coastguard Worker void JEMALLOC_NOTHROW *
2678*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALLOC_SIZE(2)
2679*1208bc7eSAndroid Build Coastguard Worker je_rallocx(void *ptr, size_t size, int flags) {
2680*1208bc7eSAndroid Build Coastguard Worker void *p;
2681*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd;
2682*1208bc7eSAndroid Build Coastguard Worker size_t usize;
2683*1208bc7eSAndroid Build Coastguard Worker size_t old_usize;
2684*1208bc7eSAndroid Build Coastguard Worker size_t alignment = MALLOCX_ALIGN_GET(flags);
2685*1208bc7eSAndroid Build Coastguard Worker bool zero = flags & MALLOCX_ZERO;
2686*1208bc7eSAndroid Build Coastguard Worker arena_t *arena;
2687*1208bc7eSAndroid Build Coastguard Worker tcache_t *tcache;
2688*1208bc7eSAndroid Build Coastguard Worker
2689*1208bc7eSAndroid Build Coastguard Worker LOG("core.rallocx.entry", "ptr: %p, size: %zu, flags: %d", ptr,
2690*1208bc7eSAndroid Build Coastguard Worker size, flags);
2691*1208bc7eSAndroid Build Coastguard Worker
2692*1208bc7eSAndroid Build Coastguard Worker
2693*1208bc7eSAndroid Build Coastguard Worker assert(ptr != NULL);
2694*1208bc7eSAndroid Build Coastguard Worker assert(size != 0);
2695*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized() || IS_INITIALIZER);
2696*1208bc7eSAndroid Build Coastguard Worker tsd = tsd_fetch();
2697*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2698*1208bc7eSAndroid Build Coastguard Worker
2699*1208bc7eSAndroid Build Coastguard Worker if (unlikely((flags & MALLOCX_ARENA_MASK) != 0)) {
2700*1208bc7eSAndroid Build Coastguard Worker unsigned arena_ind = MALLOCX_ARENA_GET(flags);
2701*1208bc7eSAndroid Build Coastguard Worker arena = arena_get(tsd_tsdn(tsd), arena_ind, true);
2702*1208bc7eSAndroid Build Coastguard Worker if (unlikely(arena == NULL)) {
2703*1208bc7eSAndroid Build Coastguard Worker goto label_oom;
2704*1208bc7eSAndroid Build Coastguard Worker }
2705*1208bc7eSAndroid Build Coastguard Worker } else {
2706*1208bc7eSAndroid Build Coastguard Worker arena = NULL;
2707*1208bc7eSAndroid Build Coastguard Worker }
2708*1208bc7eSAndroid Build Coastguard Worker
2709*1208bc7eSAndroid Build Coastguard Worker if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {
2710*1208bc7eSAndroid Build Coastguard Worker if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE) {
2711*1208bc7eSAndroid Build Coastguard Worker tcache = NULL;
2712*1208bc7eSAndroid Build Coastguard Worker } else {
2713*1208bc7eSAndroid Build Coastguard Worker tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));
2714*1208bc7eSAndroid Build Coastguard Worker }
2715*1208bc7eSAndroid Build Coastguard Worker } else {
2716*1208bc7eSAndroid Build Coastguard Worker tcache = tcache_get(tsd);
2717*1208bc7eSAndroid Build Coastguard Worker }
2718*1208bc7eSAndroid Build Coastguard Worker
2719*1208bc7eSAndroid Build Coastguard Worker alloc_ctx_t alloc_ctx;
2720*1208bc7eSAndroid Build Coastguard Worker rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd);
2721*1208bc7eSAndroid Build Coastguard Worker rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx,
2722*1208bc7eSAndroid Build Coastguard Worker (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab);
2723*1208bc7eSAndroid Build Coastguard Worker assert(alloc_ctx.szind != NSIZES);
2724*1208bc7eSAndroid Build Coastguard Worker old_usize = sz_index2size(alloc_ctx.szind);
2725*1208bc7eSAndroid Build Coastguard Worker assert(old_usize == isalloc(tsd_tsdn(tsd), ptr));
2726*1208bc7eSAndroid Build Coastguard Worker if (config_prof && opt_prof) {
2727*1208bc7eSAndroid Build Coastguard Worker usize = (alignment == 0) ?
2728*1208bc7eSAndroid Build Coastguard Worker sz_s2u(size) : sz_sa2u(size, alignment);
2729*1208bc7eSAndroid Build Coastguard Worker if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) {
2730*1208bc7eSAndroid Build Coastguard Worker goto label_oom;
2731*1208bc7eSAndroid Build Coastguard Worker }
2732*1208bc7eSAndroid Build Coastguard Worker p = irallocx_prof(tsd, ptr, old_usize, size, alignment, &usize,
2733*1208bc7eSAndroid Build Coastguard Worker zero, tcache, arena, &alloc_ctx);
2734*1208bc7eSAndroid Build Coastguard Worker if (unlikely(p == NULL)) {
2735*1208bc7eSAndroid Build Coastguard Worker goto label_oom;
2736*1208bc7eSAndroid Build Coastguard Worker }
2737*1208bc7eSAndroid Build Coastguard Worker } else {
2738*1208bc7eSAndroid Build Coastguard Worker p = iralloct(tsd_tsdn(tsd), ptr, old_usize, size, alignment,
2739*1208bc7eSAndroid Build Coastguard Worker zero, tcache, arena);
2740*1208bc7eSAndroid Build Coastguard Worker if (unlikely(p == NULL)) {
2741*1208bc7eSAndroid Build Coastguard Worker goto label_oom;
2742*1208bc7eSAndroid Build Coastguard Worker }
2743*1208bc7eSAndroid Build Coastguard Worker if (config_stats) {
2744*1208bc7eSAndroid Build Coastguard Worker usize = isalloc(tsd_tsdn(tsd), p);
2745*1208bc7eSAndroid Build Coastguard Worker }
2746*1208bc7eSAndroid Build Coastguard Worker }
2747*1208bc7eSAndroid Build Coastguard Worker assert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0));
2748*1208bc7eSAndroid Build Coastguard Worker
2749*1208bc7eSAndroid Build Coastguard Worker if (config_stats) {
2750*1208bc7eSAndroid Build Coastguard Worker *tsd_thread_allocatedp_get(tsd) += usize;
2751*1208bc7eSAndroid Build Coastguard Worker *tsd_thread_deallocatedp_get(tsd) += old_usize;
2752*1208bc7eSAndroid Build Coastguard Worker }
2753*1208bc7eSAndroid Build Coastguard Worker UTRACE(ptr, size, p);
2754*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2755*1208bc7eSAndroid Build Coastguard Worker
2756*1208bc7eSAndroid Build Coastguard Worker LOG("core.rallocx.exit", "result: %p", p);
2757*1208bc7eSAndroid Build Coastguard Worker return p;
2758*1208bc7eSAndroid Build Coastguard Worker label_oom:
2759*1208bc7eSAndroid Build Coastguard Worker if (config_xmalloc && unlikely(opt_xmalloc)) {
2760*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Error in rallocx(): out of memory\n");
2761*1208bc7eSAndroid Build Coastguard Worker abort();
2762*1208bc7eSAndroid Build Coastguard Worker }
2763*1208bc7eSAndroid Build Coastguard Worker UTRACE(ptr, size, 0);
2764*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2765*1208bc7eSAndroid Build Coastguard Worker
2766*1208bc7eSAndroid Build Coastguard Worker LOG("core.rallocx.exit", "result: %p", NULL);
2767*1208bc7eSAndroid Build Coastguard Worker return NULL;
2768*1208bc7eSAndroid Build Coastguard Worker }
2769*1208bc7eSAndroid Build Coastguard Worker
2770*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE size_t
2771*1208bc7eSAndroid Build Coastguard Worker ixallocx_helper(tsdn_t *tsdn, void *ptr, size_t old_usize, size_t size,
2772*1208bc7eSAndroid Build Coastguard Worker size_t extra, size_t alignment, bool zero) {
2773*1208bc7eSAndroid Build Coastguard Worker size_t usize;
2774*1208bc7eSAndroid Build Coastguard Worker
2775*1208bc7eSAndroid Build Coastguard Worker if (ixalloc(tsdn, ptr, old_usize, size, extra, alignment, zero)) {
2776*1208bc7eSAndroid Build Coastguard Worker return old_usize;
2777*1208bc7eSAndroid Build Coastguard Worker }
2778*1208bc7eSAndroid Build Coastguard Worker usize = isalloc(tsdn, ptr);
2779*1208bc7eSAndroid Build Coastguard Worker
2780*1208bc7eSAndroid Build Coastguard Worker return usize;
2781*1208bc7eSAndroid Build Coastguard Worker }
2782*1208bc7eSAndroid Build Coastguard Worker
2783*1208bc7eSAndroid Build Coastguard Worker static size_t
2784*1208bc7eSAndroid Build Coastguard Worker ixallocx_prof_sample(tsdn_t *tsdn, void *ptr, size_t old_usize, size_t size,
2785*1208bc7eSAndroid Build Coastguard Worker size_t extra, size_t alignment, bool zero, prof_tctx_t *tctx) {
2786*1208bc7eSAndroid Build Coastguard Worker size_t usize;
2787*1208bc7eSAndroid Build Coastguard Worker
2788*1208bc7eSAndroid Build Coastguard Worker if (tctx == NULL) {
2789*1208bc7eSAndroid Build Coastguard Worker return old_usize;
2790*1208bc7eSAndroid Build Coastguard Worker }
2791*1208bc7eSAndroid Build Coastguard Worker usize = ixallocx_helper(tsdn, ptr, old_usize, size, extra, alignment,
2792*1208bc7eSAndroid Build Coastguard Worker zero);
2793*1208bc7eSAndroid Build Coastguard Worker
2794*1208bc7eSAndroid Build Coastguard Worker return usize;
2795*1208bc7eSAndroid Build Coastguard Worker }
2796*1208bc7eSAndroid Build Coastguard Worker
2797*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE size_t
2798*1208bc7eSAndroid Build Coastguard Worker ixallocx_prof(tsd_t *tsd, void *ptr, size_t old_usize, size_t size,
2799*1208bc7eSAndroid Build Coastguard Worker size_t extra, size_t alignment, bool zero, alloc_ctx_t *alloc_ctx) {
2800*1208bc7eSAndroid Build Coastguard Worker size_t usize_max, usize;
2801*1208bc7eSAndroid Build Coastguard Worker bool prof_active;
2802*1208bc7eSAndroid Build Coastguard Worker prof_tctx_t *old_tctx, *tctx;
2803*1208bc7eSAndroid Build Coastguard Worker
2804*1208bc7eSAndroid Build Coastguard Worker prof_active = prof_active_get_unlocked();
2805*1208bc7eSAndroid Build Coastguard Worker old_tctx = prof_tctx_get(tsd_tsdn(tsd), ptr, alloc_ctx);
2806*1208bc7eSAndroid Build Coastguard Worker /*
2807*1208bc7eSAndroid Build Coastguard Worker * usize isn't knowable before ixalloc() returns when extra is non-zero.
2808*1208bc7eSAndroid Build Coastguard Worker * Therefore, compute its maximum possible value and use that in
2809*1208bc7eSAndroid Build Coastguard Worker * prof_alloc_prep() to decide whether to capture a backtrace.
2810*1208bc7eSAndroid Build Coastguard Worker * prof_realloc() will use the actual usize to decide whether to sample.
2811*1208bc7eSAndroid Build Coastguard Worker */
2812*1208bc7eSAndroid Build Coastguard Worker if (alignment == 0) {
2813*1208bc7eSAndroid Build Coastguard Worker usize_max = sz_s2u(size+extra);
2814*1208bc7eSAndroid Build Coastguard Worker assert(usize_max > 0 && usize_max <= LARGE_MAXCLASS);
2815*1208bc7eSAndroid Build Coastguard Worker } else {
2816*1208bc7eSAndroid Build Coastguard Worker usize_max = sz_sa2u(size+extra, alignment);
2817*1208bc7eSAndroid Build Coastguard Worker if (unlikely(usize_max == 0 || usize_max > LARGE_MAXCLASS)) {
2818*1208bc7eSAndroid Build Coastguard Worker /*
2819*1208bc7eSAndroid Build Coastguard Worker * usize_max is out of range, and chances are that
2820*1208bc7eSAndroid Build Coastguard Worker * allocation will fail, but use the maximum possible
2821*1208bc7eSAndroid Build Coastguard Worker * value and carry on with prof_alloc_prep(), just in
2822*1208bc7eSAndroid Build Coastguard Worker * case allocation succeeds.
2823*1208bc7eSAndroid Build Coastguard Worker */
2824*1208bc7eSAndroid Build Coastguard Worker usize_max = LARGE_MAXCLASS;
2825*1208bc7eSAndroid Build Coastguard Worker }
2826*1208bc7eSAndroid Build Coastguard Worker }
2827*1208bc7eSAndroid Build Coastguard Worker tctx = prof_alloc_prep(tsd, usize_max, prof_active, false);
2828*1208bc7eSAndroid Build Coastguard Worker
2829*1208bc7eSAndroid Build Coastguard Worker if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {
2830*1208bc7eSAndroid Build Coastguard Worker usize = ixallocx_prof_sample(tsd_tsdn(tsd), ptr, old_usize,
2831*1208bc7eSAndroid Build Coastguard Worker size, extra, alignment, zero, tctx);
2832*1208bc7eSAndroid Build Coastguard Worker } else {
2833*1208bc7eSAndroid Build Coastguard Worker usize = ixallocx_helper(tsd_tsdn(tsd), ptr, old_usize, size,
2834*1208bc7eSAndroid Build Coastguard Worker extra, alignment, zero);
2835*1208bc7eSAndroid Build Coastguard Worker }
2836*1208bc7eSAndroid Build Coastguard Worker if (usize == old_usize) {
2837*1208bc7eSAndroid Build Coastguard Worker prof_alloc_rollback(tsd, tctx, false);
2838*1208bc7eSAndroid Build Coastguard Worker return usize;
2839*1208bc7eSAndroid Build Coastguard Worker }
2840*1208bc7eSAndroid Build Coastguard Worker prof_realloc(tsd, ptr, usize, tctx, prof_active, false, ptr, old_usize,
2841*1208bc7eSAndroid Build Coastguard Worker old_tctx);
2842*1208bc7eSAndroid Build Coastguard Worker
2843*1208bc7eSAndroid Build Coastguard Worker return usize;
2844*1208bc7eSAndroid Build Coastguard Worker }
2845*1208bc7eSAndroid Build Coastguard Worker
2846*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW
2847*1208bc7eSAndroid Build Coastguard Worker je_xallocx(void *ptr, size_t size, size_t extra, int flags) {
2848*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd;
2849*1208bc7eSAndroid Build Coastguard Worker size_t usize, old_usize;
2850*1208bc7eSAndroid Build Coastguard Worker size_t alignment = MALLOCX_ALIGN_GET(flags);
2851*1208bc7eSAndroid Build Coastguard Worker bool zero = flags & MALLOCX_ZERO;
2852*1208bc7eSAndroid Build Coastguard Worker
2853*1208bc7eSAndroid Build Coastguard Worker LOG("core.xallocx.entry", "ptr: %p, size: %zu, extra: %zu, "
2854*1208bc7eSAndroid Build Coastguard Worker "flags: %d", ptr, size, extra, flags);
2855*1208bc7eSAndroid Build Coastguard Worker
2856*1208bc7eSAndroid Build Coastguard Worker assert(ptr != NULL);
2857*1208bc7eSAndroid Build Coastguard Worker assert(size != 0);
2858*1208bc7eSAndroid Build Coastguard Worker assert(SIZE_T_MAX - size >= extra);
2859*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized() || IS_INITIALIZER);
2860*1208bc7eSAndroid Build Coastguard Worker tsd = tsd_fetch();
2861*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2862*1208bc7eSAndroid Build Coastguard Worker
2863*1208bc7eSAndroid Build Coastguard Worker alloc_ctx_t alloc_ctx;
2864*1208bc7eSAndroid Build Coastguard Worker rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd);
2865*1208bc7eSAndroid Build Coastguard Worker rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx,
2866*1208bc7eSAndroid Build Coastguard Worker (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab);
2867*1208bc7eSAndroid Build Coastguard Worker assert(alloc_ctx.szind != NSIZES);
2868*1208bc7eSAndroid Build Coastguard Worker old_usize = sz_index2size(alloc_ctx.szind);
2869*1208bc7eSAndroid Build Coastguard Worker assert(old_usize == isalloc(tsd_tsdn(tsd), ptr));
2870*1208bc7eSAndroid Build Coastguard Worker /*
2871*1208bc7eSAndroid Build Coastguard Worker * The API explicitly absolves itself of protecting against (size +
2872*1208bc7eSAndroid Build Coastguard Worker * extra) numerical overflow, but we may need to clamp extra to avoid
2873*1208bc7eSAndroid Build Coastguard Worker * exceeding LARGE_MAXCLASS.
2874*1208bc7eSAndroid Build Coastguard Worker *
2875*1208bc7eSAndroid Build Coastguard Worker * Ordinarily, size limit checking is handled deeper down, but here we
2876*1208bc7eSAndroid Build Coastguard Worker * have to check as part of (size + extra) clamping, since we need the
2877*1208bc7eSAndroid Build Coastguard Worker * clamped value in the above helper functions.
2878*1208bc7eSAndroid Build Coastguard Worker */
2879*1208bc7eSAndroid Build Coastguard Worker if (unlikely(size > LARGE_MAXCLASS)) {
2880*1208bc7eSAndroid Build Coastguard Worker usize = old_usize;
2881*1208bc7eSAndroid Build Coastguard Worker goto label_not_resized;
2882*1208bc7eSAndroid Build Coastguard Worker }
2883*1208bc7eSAndroid Build Coastguard Worker if (unlikely(LARGE_MAXCLASS - size < extra)) {
2884*1208bc7eSAndroid Build Coastguard Worker extra = LARGE_MAXCLASS - size;
2885*1208bc7eSAndroid Build Coastguard Worker }
2886*1208bc7eSAndroid Build Coastguard Worker
2887*1208bc7eSAndroid Build Coastguard Worker if (config_prof && opt_prof) {
2888*1208bc7eSAndroid Build Coastguard Worker usize = ixallocx_prof(tsd, ptr, old_usize, size, extra,
2889*1208bc7eSAndroid Build Coastguard Worker alignment, zero, &alloc_ctx);
2890*1208bc7eSAndroid Build Coastguard Worker } else {
2891*1208bc7eSAndroid Build Coastguard Worker usize = ixallocx_helper(tsd_tsdn(tsd), ptr, old_usize, size,
2892*1208bc7eSAndroid Build Coastguard Worker extra, alignment, zero);
2893*1208bc7eSAndroid Build Coastguard Worker }
2894*1208bc7eSAndroid Build Coastguard Worker if (unlikely(usize == old_usize)) {
2895*1208bc7eSAndroid Build Coastguard Worker goto label_not_resized;
2896*1208bc7eSAndroid Build Coastguard Worker }
2897*1208bc7eSAndroid Build Coastguard Worker
2898*1208bc7eSAndroid Build Coastguard Worker if (config_stats) {
2899*1208bc7eSAndroid Build Coastguard Worker *tsd_thread_allocatedp_get(tsd) += usize;
2900*1208bc7eSAndroid Build Coastguard Worker *tsd_thread_deallocatedp_get(tsd) += old_usize;
2901*1208bc7eSAndroid Build Coastguard Worker }
2902*1208bc7eSAndroid Build Coastguard Worker label_not_resized:
2903*1208bc7eSAndroid Build Coastguard Worker UTRACE(ptr, size, ptr);
2904*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2905*1208bc7eSAndroid Build Coastguard Worker
2906*1208bc7eSAndroid Build Coastguard Worker LOG("core.xallocx.exit", "result: %zu", usize);
2907*1208bc7eSAndroid Build Coastguard Worker return usize;
2908*1208bc7eSAndroid Build Coastguard Worker }
2909*1208bc7eSAndroid Build Coastguard Worker
2910*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW
2911*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(pure)
2912*1208bc7eSAndroid Build Coastguard Worker je_sallocx(const void *ptr, UNUSED int flags) {
2913*1208bc7eSAndroid Build Coastguard Worker size_t usize;
2914*1208bc7eSAndroid Build Coastguard Worker tsdn_t *tsdn;
2915*1208bc7eSAndroid Build Coastguard Worker
2916*1208bc7eSAndroid Build Coastguard Worker LOG("core.sallocx.entry", "ptr: %p, flags: %d", ptr, flags);
2917*1208bc7eSAndroid Build Coastguard Worker
2918*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized() || IS_INITIALIZER);
2919*1208bc7eSAndroid Build Coastguard Worker assert(ptr != NULL);
2920*1208bc7eSAndroid Build Coastguard Worker
2921*1208bc7eSAndroid Build Coastguard Worker tsdn = tsdn_fetch();
2922*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
2923*1208bc7eSAndroid Build Coastguard Worker
2924*1208bc7eSAndroid Build Coastguard Worker if (config_debug || force_ivsalloc) {
2925*1208bc7eSAndroid Build Coastguard Worker usize = ivsalloc(tsdn, ptr);
2926*1208bc7eSAndroid Build Coastguard Worker assert(force_ivsalloc || usize != 0);
2927*1208bc7eSAndroid Build Coastguard Worker } else {
2928*1208bc7eSAndroid Build Coastguard Worker usize = isalloc(tsdn, ptr);
2929*1208bc7eSAndroid Build Coastguard Worker }
2930*1208bc7eSAndroid Build Coastguard Worker
2931*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
2932*1208bc7eSAndroid Build Coastguard Worker
2933*1208bc7eSAndroid Build Coastguard Worker LOG("core.sallocx.exit", "result: %zu", usize);
2934*1208bc7eSAndroid Build Coastguard Worker return usize;
2935*1208bc7eSAndroid Build Coastguard Worker }
2936*1208bc7eSAndroid Build Coastguard Worker
2937*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void JEMALLOC_NOTHROW
2938*1208bc7eSAndroid Build Coastguard Worker je_dallocx(void *ptr, int flags) {
2939*1208bc7eSAndroid Build Coastguard Worker LOG("core.dallocx.entry", "ptr: %p, flags: %d", ptr, flags);
2940*1208bc7eSAndroid Build Coastguard Worker
2941*1208bc7eSAndroid Build Coastguard Worker assert(ptr != NULL);
2942*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized() || IS_INITIALIZER);
2943*1208bc7eSAndroid Build Coastguard Worker
2944*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd = tsd_fetch();
2945*1208bc7eSAndroid Build Coastguard Worker bool fast = tsd_fast(tsd);
2946*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2947*1208bc7eSAndroid Build Coastguard Worker
2948*1208bc7eSAndroid Build Coastguard Worker tcache_t *tcache;
2949*1208bc7eSAndroid Build Coastguard Worker if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {
2950*1208bc7eSAndroid Build Coastguard Worker /* Not allowed to be reentrant and specify a custom tcache. */
2951*1208bc7eSAndroid Build Coastguard Worker assert(tsd_reentrancy_level_get(tsd) == 0);
2952*1208bc7eSAndroid Build Coastguard Worker if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE) {
2953*1208bc7eSAndroid Build Coastguard Worker tcache = NULL;
2954*1208bc7eSAndroid Build Coastguard Worker } else {
2955*1208bc7eSAndroid Build Coastguard Worker tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));
2956*1208bc7eSAndroid Build Coastguard Worker }
2957*1208bc7eSAndroid Build Coastguard Worker } else {
2958*1208bc7eSAndroid Build Coastguard Worker if (likely(fast)) {
2959*1208bc7eSAndroid Build Coastguard Worker tcache = tsd_tcachep_get(tsd);
2960*1208bc7eSAndroid Build Coastguard Worker assert(tcache == tcache_get(tsd));
2961*1208bc7eSAndroid Build Coastguard Worker } else {
2962*1208bc7eSAndroid Build Coastguard Worker if (likely(tsd_reentrancy_level_get(tsd) == 0)) {
2963*1208bc7eSAndroid Build Coastguard Worker tcache = tcache_get(tsd);
2964*1208bc7eSAndroid Build Coastguard Worker } else {
2965*1208bc7eSAndroid Build Coastguard Worker tcache = NULL;
2966*1208bc7eSAndroid Build Coastguard Worker }
2967*1208bc7eSAndroid Build Coastguard Worker }
2968*1208bc7eSAndroid Build Coastguard Worker }
2969*1208bc7eSAndroid Build Coastguard Worker
2970*1208bc7eSAndroid Build Coastguard Worker UTRACE(ptr, 0, 0);
2971*1208bc7eSAndroid Build Coastguard Worker if (likely(fast)) {
2972*1208bc7eSAndroid Build Coastguard Worker tsd_assert_fast(tsd);
2973*1208bc7eSAndroid Build Coastguard Worker ifree(tsd, ptr, tcache, false);
2974*1208bc7eSAndroid Build Coastguard Worker } else {
2975*1208bc7eSAndroid Build Coastguard Worker ifree(tsd, ptr, tcache, true);
2976*1208bc7eSAndroid Build Coastguard Worker }
2977*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
2978*1208bc7eSAndroid Build Coastguard Worker
2979*1208bc7eSAndroid Build Coastguard Worker LOG("core.dallocx.exit", "");
2980*1208bc7eSAndroid Build Coastguard Worker }
2981*1208bc7eSAndroid Build Coastguard Worker
2982*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE size_t
2983*1208bc7eSAndroid Build Coastguard Worker inallocx(tsdn_t *tsdn, size_t size, int flags) {
2984*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
2985*1208bc7eSAndroid Build Coastguard Worker
2986*1208bc7eSAndroid Build Coastguard Worker size_t usize;
2987*1208bc7eSAndroid Build Coastguard Worker if (likely((flags & MALLOCX_LG_ALIGN_MASK) == 0)) {
2988*1208bc7eSAndroid Build Coastguard Worker usize = sz_s2u(size);
2989*1208bc7eSAndroid Build Coastguard Worker } else {
2990*1208bc7eSAndroid Build Coastguard Worker usize = sz_sa2u(size, MALLOCX_ALIGN_GET_SPECIFIED(flags));
2991*1208bc7eSAndroid Build Coastguard Worker }
2992*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
2993*1208bc7eSAndroid Build Coastguard Worker return usize;
2994*1208bc7eSAndroid Build Coastguard Worker }
2995*1208bc7eSAndroid Build Coastguard Worker
2996*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void JEMALLOC_NOTHROW
2997*1208bc7eSAndroid Build Coastguard Worker je_sdallocx(void *ptr, size_t size, int flags) {
2998*1208bc7eSAndroid Build Coastguard Worker assert(ptr != NULL);
2999*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized() || IS_INITIALIZER);
3000*1208bc7eSAndroid Build Coastguard Worker
3001*1208bc7eSAndroid Build Coastguard Worker LOG("core.sdallocx.entry", "ptr: %p, size: %zu, flags: %d", ptr,
3002*1208bc7eSAndroid Build Coastguard Worker size, flags);
3003*1208bc7eSAndroid Build Coastguard Worker
3004*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd = tsd_fetch();
3005*1208bc7eSAndroid Build Coastguard Worker bool fast = tsd_fast(tsd);
3006*1208bc7eSAndroid Build Coastguard Worker size_t usize = inallocx(tsd_tsdn(tsd), size, flags);
3007*1208bc7eSAndroid Build Coastguard Worker assert(usize == isalloc(tsd_tsdn(tsd), ptr));
3008*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
3009*1208bc7eSAndroid Build Coastguard Worker
3010*1208bc7eSAndroid Build Coastguard Worker tcache_t *tcache;
3011*1208bc7eSAndroid Build Coastguard Worker if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {
3012*1208bc7eSAndroid Build Coastguard Worker /* Not allowed to be reentrant and specify a custom tcache. */
3013*1208bc7eSAndroid Build Coastguard Worker assert(tsd_reentrancy_level_get(tsd) == 0);
3014*1208bc7eSAndroid Build Coastguard Worker if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE) {
3015*1208bc7eSAndroid Build Coastguard Worker tcache = NULL;
3016*1208bc7eSAndroid Build Coastguard Worker } else {
3017*1208bc7eSAndroid Build Coastguard Worker tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));
3018*1208bc7eSAndroid Build Coastguard Worker }
3019*1208bc7eSAndroid Build Coastguard Worker } else {
3020*1208bc7eSAndroid Build Coastguard Worker if (likely(fast)) {
3021*1208bc7eSAndroid Build Coastguard Worker tcache = tsd_tcachep_get(tsd);
3022*1208bc7eSAndroid Build Coastguard Worker assert(tcache == tcache_get(tsd));
3023*1208bc7eSAndroid Build Coastguard Worker } else {
3024*1208bc7eSAndroid Build Coastguard Worker if (likely(tsd_reentrancy_level_get(tsd) == 0)) {
3025*1208bc7eSAndroid Build Coastguard Worker tcache = tcache_get(tsd);
3026*1208bc7eSAndroid Build Coastguard Worker } else {
3027*1208bc7eSAndroid Build Coastguard Worker tcache = NULL;
3028*1208bc7eSAndroid Build Coastguard Worker }
3029*1208bc7eSAndroid Build Coastguard Worker }
3030*1208bc7eSAndroid Build Coastguard Worker }
3031*1208bc7eSAndroid Build Coastguard Worker
3032*1208bc7eSAndroid Build Coastguard Worker UTRACE(ptr, 0, 0);
3033*1208bc7eSAndroid Build Coastguard Worker if (likely(fast)) {
3034*1208bc7eSAndroid Build Coastguard Worker tsd_assert_fast(tsd);
3035*1208bc7eSAndroid Build Coastguard Worker isfree(tsd, ptr, usize, tcache, false);
3036*1208bc7eSAndroid Build Coastguard Worker } else {
3037*1208bc7eSAndroid Build Coastguard Worker isfree(tsd, ptr, usize, tcache, true);
3038*1208bc7eSAndroid Build Coastguard Worker }
3039*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
3040*1208bc7eSAndroid Build Coastguard Worker
3041*1208bc7eSAndroid Build Coastguard Worker LOG("core.sdallocx.exit", "");
3042*1208bc7eSAndroid Build Coastguard Worker }
3043*1208bc7eSAndroid Build Coastguard Worker
3044*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW
3045*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(pure)
3046*1208bc7eSAndroid Build Coastguard Worker je_nallocx(size_t size, int flags) {
3047*1208bc7eSAndroid Build Coastguard Worker size_t usize;
3048*1208bc7eSAndroid Build Coastguard Worker tsdn_t *tsdn;
3049*1208bc7eSAndroid Build Coastguard Worker
3050*1208bc7eSAndroid Build Coastguard Worker assert(size != 0);
3051*1208bc7eSAndroid Build Coastguard Worker
3052*1208bc7eSAndroid Build Coastguard Worker if (unlikely(malloc_init())) {
3053*1208bc7eSAndroid Build Coastguard Worker LOG("core.nallocx.exit", "result: %zu", ZU(0));
3054*1208bc7eSAndroid Build Coastguard Worker return 0;
3055*1208bc7eSAndroid Build Coastguard Worker }
3056*1208bc7eSAndroid Build Coastguard Worker
3057*1208bc7eSAndroid Build Coastguard Worker tsdn = tsdn_fetch();
3058*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
3059*1208bc7eSAndroid Build Coastguard Worker
3060*1208bc7eSAndroid Build Coastguard Worker usize = inallocx(tsdn, size, flags);
3061*1208bc7eSAndroid Build Coastguard Worker if (unlikely(usize > LARGE_MAXCLASS)) {
3062*1208bc7eSAndroid Build Coastguard Worker LOG("core.nallocx.exit", "result: %zu", ZU(0));
3063*1208bc7eSAndroid Build Coastguard Worker return 0;
3064*1208bc7eSAndroid Build Coastguard Worker }
3065*1208bc7eSAndroid Build Coastguard Worker
3066*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
3067*1208bc7eSAndroid Build Coastguard Worker LOG("core.nallocx.exit", "result: %zu", usize);
3068*1208bc7eSAndroid Build Coastguard Worker return usize;
3069*1208bc7eSAndroid Build Coastguard Worker }
3070*1208bc7eSAndroid Build Coastguard Worker
3071*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT int JEMALLOC_NOTHROW
3072*1208bc7eSAndroid Build Coastguard Worker je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp,
3073*1208bc7eSAndroid Build Coastguard Worker size_t newlen) {
3074*1208bc7eSAndroid Build Coastguard Worker int ret;
3075*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd;
3076*1208bc7eSAndroid Build Coastguard Worker
3077*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallctl.entry", "name: %s", name);
3078*1208bc7eSAndroid Build Coastguard Worker
3079*1208bc7eSAndroid Build Coastguard Worker if (unlikely(malloc_init())) {
3080*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallctl.exit", "result: %d", EAGAIN);
3081*1208bc7eSAndroid Build Coastguard Worker return EAGAIN;
3082*1208bc7eSAndroid Build Coastguard Worker }
3083*1208bc7eSAndroid Build Coastguard Worker
3084*1208bc7eSAndroid Build Coastguard Worker tsd = tsd_fetch();
3085*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
3086*1208bc7eSAndroid Build Coastguard Worker ret = ctl_byname(tsd, name, oldp, oldlenp, newp, newlen);
3087*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
3088*1208bc7eSAndroid Build Coastguard Worker
3089*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallctl.exit", "result: %d", ret);
3090*1208bc7eSAndroid Build Coastguard Worker return ret;
3091*1208bc7eSAndroid Build Coastguard Worker }
3092*1208bc7eSAndroid Build Coastguard Worker
3093*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT int JEMALLOC_NOTHROW
3094*1208bc7eSAndroid Build Coastguard Worker je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp) {
3095*1208bc7eSAndroid Build Coastguard Worker int ret;
3096*1208bc7eSAndroid Build Coastguard Worker
3097*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallctlnametomib.entry", "name: %s", name);
3098*1208bc7eSAndroid Build Coastguard Worker
3099*1208bc7eSAndroid Build Coastguard Worker if (unlikely(malloc_init())) {
3100*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallctlnametomib.exit", "result: %d", EAGAIN);
3101*1208bc7eSAndroid Build Coastguard Worker return EAGAIN;
3102*1208bc7eSAndroid Build Coastguard Worker }
3103*1208bc7eSAndroid Build Coastguard Worker
3104*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd = tsd_fetch();
3105*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
3106*1208bc7eSAndroid Build Coastguard Worker ret = ctl_nametomib(tsd, name, mibp, miblenp);
3107*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
3108*1208bc7eSAndroid Build Coastguard Worker
3109*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallctlnametomib.exit", "result: %d", ret);
3110*1208bc7eSAndroid Build Coastguard Worker return ret;
3111*1208bc7eSAndroid Build Coastguard Worker }
3112*1208bc7eSAndroid Build Coastguard Worker
3113*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT int JEMALLOC_NOTHROW
3114*1208bc7eSAndroid Build Coastguard Worker je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
3115*1208bc7eSAndroid Build Coastguard Worker void *newp, size_t newlen) {
3116*1208bc7eSAndroid Build Coastguard Worker int ret;
3117*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd;
3118*1208bc7eSAndroid Build Coastguard Worker
3119*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallctlbymib.entry", "");
3120*1208bc7eSAndroid Build Coastguard Worker
3121*1208bc7eSAndroid Build Coastguard Worker if (unlikely(malloc_init())) {
3122*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallctlbymib.exit", "result: %d", EAGAIN);
3123*1208bc7eSAndroid Build Coastguard Worker return EAGAIN;
3124*1208bc7eSAndroid Build Coastguard Worker }
3125*1208bc7eSAndroid Build Coastguard Worker
3126*1208bc7eSAndroid Build Coastguard Worker tsd = tsd_fetch();
3127*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
3128*1208bc7eSAndroid Build Coastguard Worker ret = ctl_bymib(tsd, mib, miblen, oldp, oldlenp, newp, newlen);
3129*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsd_tsdn(tsd));
3130*1208bc7eSAndroid Build Coastguard Worker LOG("core.mallctlbymib.exit", "result: %d", ret);
3131*1208bc7eSAndroid Build Coastguard Worker return ret;
3132*1208bc7eSAndroid Build Coastguard Worker }
3133*1208bc7eSAndroid Build Coastguard Worker
3134*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void JEMALLOC_NOTHROW
3135*1208bc7eSAndroid Build Coastguard Worker je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
3136*1208bc7eSAndroid Build Coastguard Worker const char *opts) {
3137*1208bc7eSAndroid Build Coastguard Worker tsdn_t *tsdn;
3138*1208bc7eSAndroid Build Coastguard Worker
3139*1208bc7eSAndroid Build Coastguard Worker LOG("core.malloc_stats_print.entry", "");
3140*1208bc7eSAndroid Build Coastguard Worker
3141*1208bc7eSAndroid Build Coastguard Worker tsdn = tsdn_fetch();
3142*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
3143*1208bc7eSAndroid Build Coastguard Worker stats_print(write_cb, cbopaque, opts);
3144*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
3145*1208bc7eSAndroid Build Coastguard Worker LOG("core.malloc_stats_print.exit", "");
3146*1208bc7eSAndroid Build Coastguard Worker }
3147*1208bc7eSAndroid Build Coastguard Worker
3148*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW
3149*1208bc7eSAndroid Build Coastguard Worker je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) {
3150*1208bc7eSAndroid Build Coastguard Worker size_t ret;
3151*1208bc7eSAndroid Build Coastguard Worker tsdn_t *tsdn;
3152*1208bc7eSAndroid Build Coastguard Worker
3153*1208bc7eSAndroid Build Coastguard Worker LOG("core.malloc_usable_size.entry", "ptr: %p", ptr);
3154*1208bc7eSAndroid Build Coastguard Worker
3155*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized() || IS_INITIALIZER);
3156*1208bc7eSAndroid Build Coastguard Worker
3157*1208bc7eSAndroid Build Coastguard Worker tsdn = tsdn_fetch();
3158*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
3159*1208bc7eSAndroid Build Coastguard Worker
3160*1208bc7eSAndroid Build Coastguard Worker if (unlikely(ptr == NULL)) {
3161*1208bc7eSAndroid Build Coastguard Worker ret = 0;
3162*1208bc7eSAndroid Build Coastguard Worker } else {
3163*1208bc7eSAndroid Build Coastguard Worker if (config_debug || force_ivsalloc) {
3164*1208bc7eSAndroid Build Coastguard Worker ret = ivsalloc(tsdn, ptr);
3165*1208bc7eSAndroid Build Coastguard Worker assert(force_ivsalloc || ret != 0);
3166*1208bc7eSAndroid Build Coastguard Worker } else {
3167*1208bc7eSAndroid Build Coastguard Worker ret = isalloc(tsdn, ptr);
3168*1208bc7eSAndroid Build Coastguard Worker }
3169*1208bc7eSAndroid Build Coastguard Worker }
3170*1208bc7eSAndroid Build Coastguard Worker
3171*1208bc7eSAndroid Build Coastguard Worker check_entry_exit_locking(tsdn);
3172*1208bc7eSAndroid Build Coastguard Worker LOG("core.malloc_usable_size.exit", "result: %zu", ret);
3173*1208bc7eSAndroid Build Coastguard Worker return ret;
3174*1208bc7eSAndroid Build Coastguard Worker }
3175*1208bc7eSAndroid Build Coastguard Worker
3176*1208bc7eSAndroid Build Coastguard Worker /*
3177*1208bc7eSAndroid Build Coastguard Worker * End non-standard functions.
3178*1208bc7eSAndroid Build Coastguard Worker */
3179*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
3180*1208bc7eSAndroid Build Coastguard Worker /*
3181*1208bc7eSAndroid Build Coastguard Worker * The following functions are used by threading libraries for protection of
3182*1208bc7eSAndroid Build Coastguard Worker * malloc during fork().
3183*1208bc7eSAndroid Build Coastguard Worker */
3184*1208bc7eSAndroid Build Coastguard Worker
3185*1208bc7eSAndroid Build Coastguard Worker /*
3186*1208bc7eSAndroid Build Coastguard Worker * If an application creates a thread before doing any allocation in the main
3187*1208bc7eSAndroid Build Coastguard Worker * thread, then calls fork(2) in the main thread followed by memory allocation
3188*1208bc7eSAndroid Build Coastguard Worker * in the child process, a race can occur that results in deadlock within the
3189*1208bc7eSAndroid Build Coastguard Worker * child: the main thread may have forked while the created thread had
3190*1208bc7eSAndroid Build Coastguard Worker * partially initialized the allocator. Ordinarily jemalloc prevents
3191*1208bc7eSAndroid Build Coastguard Worker * fork/malloc races via the following functions it registers during
3192*1208bc7eSAndroid Build Coastguard Worker * initialization using pthread_atfork(), but of course that does no good if
3193*1208bc7eSAndroid Build Coastguard Worker * the allocator isn't fully initialized at fork time. The following library
3194*1208bc7eSAndroid Build Coastguard Worker * constructor is a partial solution to this problem. It may still be possible
3195*1208bc7eSAndroid Build Coastguard Worker * to trigger the deadlock described above, but doing so would involve forking
3196*1208bc7eSAndroid Build Coastguard Worker * via a library constructor that runs before jemalloc's runs.
3197*1208bc7eSAndroid Build Coastguard Worker */
3198*1208bc7eSAndroid Build Coastguard Worker #ifndef JEMALLOC_JET
3199*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ATTR(constructor)
3200*1208bc7eSAndroid Build Coastguard Worker static void
3201*1208bc7eSAndroid Build Coastguard Worker jemalloc_constructor(void) {
3202*1208bc7eSAndroid Build Coastguard Worker malloc_init();
3203*1208bc7eSAndroid Build Coastguard Worker }
3204*1208bc7eSAndroid Build Coastguard Worker #endif
3205*1208bc7eSAndroid Build Coastguard Worker
3206*1208bc7eSAndroid Build Coastguard Worker #ifndef JEMALLOC_MUTEX_INIT_CB
3207*1208bc7eSAndroid Build Coastguard Worker void
3208*1208bc7eSAndroid Build Coastguard Worker jemalloc_prefork(void)
3209*1208bc7eSAndroid Build Coastguard Worker #else
3210*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void
3211*1208bc7eSAndroid Build Coastguard Worker _malloc_prefork(void)
3212*1208bc7eSAndroid Build Coastguard Worker #endif
3213*1208bc7eSAndroid Build Coastguard Worker {
3214*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd;
3215*1208bc7eSAndroid Build Coastguard Worker unsigned i, j, narenas;
3216*1208bc7eSAndroid Build Coastguard Worker arena_t *arena;
3217*1208bc7eSAndroid Build Coastguard Worker
3218*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_MUTEX_INIT_CB
3219*1208bc7eSAndroid Build Coastguard Worker if (!malloc_initialized()) {
3220*1208bc7eSAndroid Build Coastguard Worker return;
3221*1208bc7eSAndroid Build Coastguard Worker }
3222*1208bc7eSAndroid Build Coastguard Worker #endif
3223*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized());
3224*1208bc7eSAndroid Build Coastguard Worker
3225*1208bc7eSAndroid Build Coastguard Worker tsd = tsd_fetch();
3226*1208bc7eSAndroid Build Coastguard Worker
3227*1208bc7eSAndroid Build Coastguard Worker narenas = narenas_total_get();
3228*1208bc7eSAndroid Build Coastguard Worker
3229*1208bc7eSAndroid Build Coastguard Worker witness_prefork(tsd_witness_tsdp_get(tsd));
3230*1208bc7eSAndroid Build Coastguard Worker /* Acquire all mutexes in a safe order. */
3231*1208bc7eSAndroid Build Coastguard Worker ctl_prefork(tsd_tsdn(tsd));
3232*1208bc7eSAndroid Build Coastguard Worker tcache_prefork(tsd_tsdn(tsd));
3233*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_prefork(tsd_tsdn(tsd), &arenas_lock);
3234*1208bc7eSAndroid Build Coastguard Worker if (have_background_thread) {
3235*1208bc7eSAndroid Build Coastguard Worker background_thread_prefork0(tsd_tsdn(tsd));
3236*1208bc7eSAndroid Build Coastguard Worker }
3237*1208bc7eSAndroid Build Coastguard Worker prof_prefork0(tsd_tsdn(tsd));
3238*1208bc7eSAndroid Build Coastguard Worker if (have_background_thread) {
3239*1208bc7eSAndroid Build Coastguard Worker background_thread_prefork1(tsd_tsdn(tsd));
3240*1208bc7eSAndroid Build Coastguard Worker }
3241*1208bc7eSAndroid Build Coastguard Worker /* Break arena prefork into stages to preserve lock order. */
3242*1208bc7eSAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
3243*1208bc7eSAndroid Build Coastguard Worker for (j = 0; j < narenas; j++) {
3244*1208bc7eSAndroid Build Coastguard Worker if ((arena = arena_get(tsd_tsdn(tsd), j, false)) !=
3245*1208bc7eSAndroid Build Coastguard Worker NULL) {
3246*1208bc7eSAndroid Build Coastguard Worker switch (i) {
3247*1208bc7eSAndroid Build Coastguard Worker case 0:
3248*1208bc7eSAndroid Build Coastguard Worker arena_prefork0(tsd_tsdn(tsd), arena);
3249*1208bc7eSAndroid Build Coastguard Worker break;
3250*1208bc7eSAndroid Build Coastguard Worker case 1:
3251*1208bc7eSAndroid Build Coastguard Worker arena_prefork1(tsd_tsdn(tsd), arena);
3252*1208bc7eSAndroid Build Coastguard Worker break;
3253*1208bc7eSAndroid Build Coastguard Worker case 2:
3254*1208bc7eSAndroid Build Coastguard Worker arena_prefork2(tsd_tsdn(tsd), arena);
3255*1208bc7eSAndroid Build Coastguard Worker break;
3256*1208bc7eSAndroid Build Coastguard Worker case 3:
3257*1208bc7eSAndroid Build Coastguard Worker arena_prefork3(tsd_tsdn(tsd), arena);
3258*1208bc7eSAndroid Build Coastguard Worker break;
3259*1208bc7eSAndroid Build Coastguard Worker case 4:
3260*1208bc7eSAndroid Build Coastguard Worker arena_prefork4(tsd_tsdn(tsd), arena);
3261*1208bc7eSAndroid Build Coastguard Worker break;
3262*1208bc7eSAndroid Build Coastguard Worker case 5:
3263*1208bc7eSAndroid Build Coastguard Worker arena_prefork5(tsd_tsdn(tsd), arena);
3264*1208bc7eSAndroid Build Coastguard Worker break;
3265*1208bc7eSAndroid Build Coastguard Worker case 6:
3266*1208bc7eSAndroid Build Coastguard Worker arena_prefork6(tsd_tsdn(tsd), arena);
3267*1208bc7eSAndroid Build Coastguard Worker break;
3268*1208bc7eSAndroid Build Coastguard Worker case 7:
3269*1208bc7eSAndroid Build Coastguard Worker arena_prefork7(tsd_tsdn(tsd), arena);
3270*1208bc7eSAndroid Build Coastguard Worker break;
3271*1208bc7eSAndroid Build Coastguard Worker default: not_reached();
3272*1208bc7eSAndroid Build Coastguard Worker }
3273*1208bc7eSAndroid Build Coastguard Worker }
3274*1208bc7eSAndroid Build Coastguard Worker }
3275*1208bc7eSAndroid Build Coastguard Worker }
3276*1208bc7eSAndroid Build Coastguard Worker prof_prefork1(tsd_tsdn(tsd));
3277*1208bc7eSAndroid Build Coastguard Worker }
3278*1208bc7eSAndroid Build Coastguard Worker
3279*1208bc7eSAndroid Build Coastguard Worker #ifndef JEMALLOC_MUTEX_INIT_CB
3280*1208bc7eSAndroid Build Coastguard Worker void
3281*1208bc7eSAndroid Build Coastguard Worker jemalloc_postfork_parent(void)
3282*1208bc7eSAndroid Build Coastguard Worker #else
3283*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void
3284*1208bc7eSAndroid Build Coastguard Worker _malloc_postfork(void)
3285*1208bc7eSAndroid Build Coastguard Worker #endif
3286*1208bc7eSAndroid Build Coastguard Worker {
3287*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd;
3288*1208bc7eSAndroid Build Coastguard Worker unsigned i, narenas;
3289*1208bc7eSAndroid Build Coastguard Worker
3290*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_MUTEX_INIT_CB
3291*1208bc7eSAndroid Build Coastguard Worker if (!malloc_initialized()) {
3292*1208bc7eSAndroid Build Coastguard Worker return;
3293*1208bc7eSAndroid Build Coastguard Worker }
3294*1208bc7eSAndroid Build Coastguard Worker #endif
3295*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized());
3296*1208bc7eSAndroid Build Coastguard Worker
3297*1208bc7eSAndroid Build Coastguard Worker tsd = tsd_fetch();
3298*1208bc7eSAndroid Build Coastguard Worker
3299*1208bc7eSAndroid Build Coastguard Worker witness_postfork_parent(tsd_witness_tsdp_get(tsd));
3300*1208bc7eSAndroid Build Coastguard Worker /* Release all mutexes, now that fork() has completed. */
3301*1208bc7eSAndroid Build Coastguard Worker for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
3302*1208bc7eSAndroid Build Coastguard Worker arena_t *arena;
3303*1208bc7eSAndroid Build Coastguard Worker
3304*1208bc7eSAndroid Build Coastguard Worker if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL) {
3305*1208bc7eSAndroid Build Coastguard Worker arena_postfork_parent(tsd_tsdn(tsd), arena);
3306*1208bc7eSAndroid Build Coastguard Worker }
3307*1208bc7eSAndroid Build Coastguard Worker }
3308*1208bc7eSAndroid Build Coastguard Worker prof_postfork_parent(tsd_tsdn(tsd));
3309*1208bc7eSAndroid Build Coastguard Worker if (have_background_thread) {
3310*1208bc7eSAndroid Build Coastguard Worker background_thread_postfork_parent(tsd_tsdn(tsd));
3311*1208bc7eSAndroid Build Coastguard Worker }
3312*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_postfork_parent(tsd_tsdn(tsd), &arenas_lock);
3313*1208bc7eSAndroid Build Coastguard Worker tcache_postfork_parent(tsd_tsdn(tsd));
3314*1208bc7eSAndroid Build Coastguard Worker ctl_postfork_parent(tsd_tsdn(tsd));
3315*1208bc7eSAndroid Build Coastguard Worker }
3316*1208bc7eSAndroid Build Coastguard Worker
3317*1208bc7eSAndroid Build Coastguard Worker void
3318*1208bc7eSAndroid Build Coastguard Worker jemalloc_postfork_child(void) {
3319*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd;
3320*1208bc7eSAndroid Build Coastguard Worker unsigned i, narenas;
3321*1208bc7eSAndroid Build Coastguard Worker
3322*1208bc7eSAndroid Build Coastguard Worker assert(malloc_initialized());
3323*1208bc7eSAndroid Build Coastguard Worker
3324*1208bc7eSAndroid Build Coastguard Worker tsd = tsd_fetch();
3325*1208bc7eSAndroid Build Coastguard Worker
3326*1208bc7eSAndroid Build Coastguard Worker witness_postfork_child(tsd_witness_tsdp_get(tsd));
3327*1208bc7eSAndroid Build Coastguard Worker extent_postfork_child(tsd_tsdn(tsd));
3328*1208bc7eSAndroid Build Coastguard Worker /* Release all mutexes, now that fork() has completed. */
3329*1208bc7eSAndroid Build Coastguard Worker for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
3330*1208bc7eSAndroid Build Coastguard Worker arena_t *arena;
3331*1208bc7eSAndroid Build Coastguard Worker
3332*1208bc7eSAndroid Build Coastguard Worker if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL) {
3333*1208bc7eSAndroid Build Coastguard Worker arena_postfork_child(tsd_tsdn(tsd), arena);
3334*1208bc7eSAndroid Build Coastguard Worker }
3335*1208bc7eSAndroid Build Coastguard Worker }
3336*1208bc7eSAndroid Build Coastguard Worker prof_postfork_child(tsd_tsdn(tsd));
3337*1208bc7eSAndroid Build Coastguard Worker if (have_background_thread) {
3338*1208bc7eSAndroid Build Coastguard Worker background_thread_postfork_child(tsd_tsdn(tsd));
3339*1208bc7eSAndroid Build Coastguard Worker }
3340*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_postfork_child(tsd_tsdn(tsd), &arenas_lock);
3341*1208bc7eSAndroid Build Coastguard Worker tcache_postfork_child(tsd_tsdn(tsd));
3342*1208bc7eSAndroid Build Coastguard Worker ctl_postfork_child(tsd_tsdn(tsd));
3343*1208bc7eSAndroid Build Coastguard Worker }
3344*1208bc7eSAndroid Build Coastguard Worker
3345*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
3346*1208bc7eSAndroid Build Coastguard Worker
3347*1208bc7eSAndroid Build Coastguard Worker #if defined(__BIONIC__) && !defined(JEMALLOC_JET)
3348*1208bc7eSAndroid Build Coastguard Worker #include "android_je_iterate.c"
3349*1208bc7eSAndroid Build Coastguard Worker #include "android_je_mallinfo.c"
3350*1208bc7eSAndroid Build Coastguard Worker #include "android_je_stats.c"
3351*1208bc7eSAndroid Build Coastguard Worker #endif
3352