1*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_PAGES_C_
2*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_preamble.h"
3*1208bc7eSAndroid Build Coastguard Worker
4*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/pages.h"
5*1208bc7eSAndroid Build Coastguard Worker
6*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_internal_includes.h"
7*1208bc7eSAndroid Build Coastguard Worker
8*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/assert.h"
9*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/malloc_io.h"
10*1208bc7eSAndroid Build Coastguard Worker
11*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT
12*1208bc7eSAndroid Build Coastguard Worker #include <sys/sysctl.h>
13*1208bc7eSAndroid Build Coastguard Worker #ifdef __FreeBSD__
14*1208bc7eSAndroid Build Coastguard Worker #include <vm/vm_param.h>
15*1208bc7eSAndroid Build Coastguard Worker #endif
16*1208bc7eSAndroid Build Coastguard Worker #endif
17*1208bc7eSAndroid Build Coastguard Worker
18*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
19*1208bc7eSAndroid Build Coastguard Worker /* Defines/includes needed for special android code. */
20*1208bc7eSAndroid Build Coastguard Worker
21*1208bc7eSAndroid Build Coastguard Worker #if defined(__ANDROID__)
22*1208bc7eSAndroid Build Coastguard Worker #include <sys/prctl.h>
23*1208bc7eSAndroid Build Coastguard Worker #endif
24*1208bc7eSAndroid Build Coastguard Worker
25*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
26*1208bc7eSAndroid Build Coastguard Worker /* Data. */
27*1208bc7eSAndroid Build Coastguard Worker
28*1208bc7eSAndroid Build Coastguard Worker /* Actual operating system page size, detected during bootstrap, <= PAGE. */
29*1208bc7eSAndroid Build Coastguard Worker static size_t os_page;
30*1208bc7eSAndroid Build Coastguard Worker
31*1208bc7eSAndroid Build Coastguard Worker #ifndef _WIN32
32*1208bc7eSAndroid Build Coastguard Worker # define PAGES_PROT_COMMIT (PROT_READ | PROT_WRITE)
33*1208bc7eSAndroid Build Coastguard Worker # define PAGES_PROT_DECOMMIT (PROT_NONE)
34*1208bc7eSAndroid Build Coastguard Worker static int mmap_flags;
35*1208bc7eSAndroid Build Coastguard Worker #endif
36*1208bc7eSAndroid Build Coastguard Worker static bool os_overcommits;
37*1208bc7eSAndroid Build Coastguard Worker
38*1208bc7eSAndroid Build Coastguard Worker const char *thp_mode_names[] = {
39*1208bc7eSAndroid Build Coastguard Worker "default",
40*1208bc7eSAndroid Build Coastguard Worker "always",
41*1208bc7eSAndroid Build Coastguard Worker "never",
42*1208bc7eSAndroid Build Coastguard Worker "not supported"
43*1208bc7eSAndroid Build Coastguard Worker };
44*1208bc7eSAndroid Build Coastguard Worker thp_mode_t opt_thp = THP_MODE_DEFAULT;
45*1208bc7eSAndroid Build Coastguard Worker thp_mode_t init_system_thp_mode;
46*1208bc7eSAndroid Build Coastguard Worker
47*1208bc7eSAndroid Build Coastguard Worker /* Runtime support for lazy purge. Irrelevant when !pages_can_purge_lazy. */
48*1208bc7eSAndroid Build Coastguard Worker static bool pages_can_purge_lazy_runtime = true;
49*1208bc7eSAndroid Build Coastguard Worker
50*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
51*1208bc7eSAndroid Build Coastguard Worker /*
52*1208bc7eSAndroid Build Coastguard Worker * Function prototypes for static functions that are referenced prior to
53*1208bc7eSAndroid Build Coastguard Worker * definition.
54*1208bc7eSAndroid Build Coastguard Worker */
55*1208bc7eSAndroid Build Coastguard Worker
56*1208bc7eSAndroid Build Coastguard Worker static void os_pages_unmap(void *addr, size_t size);
57*1208bc7eSAndroid Build Coastguard Worker
58*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
59*1208bc7eSAndroid Build Coastguard Worker
60*1208bc7eSAndroid Build Coastguard Worker static void *
os_pages_map(void * addr,size_t size,size_t alignment,bool * commit)61*1208bc7eSAndroid Build Coastguard Worker os_pages_map(void *addr, size_t size, size_t alignment, bool *commit) {
62*1208bc7eSAndroid Build Coastguard Worker assert(ALIGNMENT_ADDR2BASE(addr, os_page) == addr);
63*1208bc7eSAndroid Build Coastguard Worker assert(ALIGNMENT_CEILING(size, os_page) == size);
64*1208bc7eSAndroid Build Coastguard Worker assert(size != 0);
65*1208bc7eSAndroid Build Coastguard Worker
66*1208bc7eSAndroid Build Coastguard Worker if (os_overcommits) {
67*1208bc7eSAndroid Build Coastguard Worker *commit = true;
68*1208bc7eSAndroid Build Coastguard Worker }
69*1208bc7eSAndroid Build Coastguard Worker
70*1208bc7eSAndroid Build Coastguard Worker void *ret;
71*1208bc7eSAndroid Build Coastguard Worker #ifdef _WIN32
72*1208bc7eSAndroid Build Coastguard Worker /*
73*1208bc7eSAndroid Build Coastguard Worker * If VirtualAlloc can't allocate at the given address when one is
74*1208bc7eSAndroid Build Coastguard Worker * given, it fails and returns NULL.
75*1208bc7eSAndroid Build Coastguard Worker */
76*1208bc7eSAndroid Build Coastguard Worker ret = VirtualAlloc(addr, size, MEM_RESERVE | (*commit ? MEM_COMMIT : 0),
77*1208bc7eSAndroid Build Coastguard Worker PAGE_READWRITE);
78*1208bc7eSAndroid Build Coastguard Worker #else
79*1208bc7eSAndroid Build Coastguard Worker /*
80*1208bc7eSAndroid Build Coastguard Worker * We don't use MAP_FIXED here, because it can cause the *replacement*
81*1208bc7eSAndroid Build Coastguard Worker * of existing mappings, and we only want to create new mappings.
82*1208bc7eSAndroid Build Coastguard Worker */
83*1208bc7eSAndroid Build Coastguard Worker {
84*1208bc7eSAndroid Build Coastguard Worker int prot = *commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT;
85*1208bc7eSAndroid Build Coastguard Worker
86*1208bc7eSAndroid Build Coastguard Worker ret = mmap(addr, size, prot, mmap_flags, -1, 0);
87*1208bc7eSAndroid Build Coastguard Worker }
88*1208bc7eSAndroid Build Coastguard Worker assert(ret != NULL);
89*1208bc7eSAndroid Build Coastguard Worker
90*1208bc7eSAndroid Build Coastguard Worker if (ret == MAP_FAILED) {
91*1208bc7eSAndroid Build Coastguard Worker ret = NULL;
92*1208bc7eSAndroid Build Coastguard Worker } else if (addr != NULL && ret != addr) {
93*1208bc7eSAndroid Build Coastguard Worker /*
94*1208bc7eSAndroid Build Coastguard Worker * We succeeded in mapping memory, but not in the right place.
95*1208bc7eSAndroid Build Coastguard Worker */
96*1208bc7eSAndroid Build Coastguard Worker os_pages_unmap(ret, size);
97*1208bc7eSAndroid Build Coastguard Worker ret = NULL;
98*1208bc7eSAndroid Build Coastguard Worker }
99*1208bc7eSAndroid Build Coastguard Worker #endif
100*1208bc7eSAndroid Build Coastguard Worker #if defined(__ANDROID__)
101*1208bc7eSAndroid Build Coastguard Worker if (ret != NULL) {
102*1208bc7eSAndroid Build Coastguard Worker /* Name this memory as being used by libc */
103*1208bc7eSAndroid Build Coastguard Worker prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ret, size,
104*1208bc7eSAndroid Build Coastguard Worker "libc_malloc");
105*1208bc7eSAndroid Build Coastguard Worker }
106*1208bc7eSAndroid Build Coastguard Worker #endif
107*1208bc7eSAndroid Build Coastguard Worker assert(ret == NULL || (addr == NULL && ret != addr) || (addr != NULL &&
108*1208bc7eSAndroid Build Coastguard Worker ret == addr));
109*1208bc7eSAndroid Build Coastguard Worker return ret;
110*1208bc7eSAndroid Build Coastguard Worker }
111*1208bc7eSAndroid Build Coastguard Worker
112*1208bc7eSAndroid Build Coastguard Worker static void *
os_pages_trim(void * addr,size_t alloc_size,size_t leadsize,size_t size,bool * commit)113*1208bc7eSAndroid Build Coastguard Worker os_pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size,
114*1208bc7eSAndroid Build Coastguard Worker bool *commit) {
115*1208bc7eSAndroid Build Coastguard Worker void *ret = (void *)((uintptr_t)addr + leadsize);
116*1208bc7eSAndroid Build Coastguard Worker
117*1208bc7eSAndroid Build Coastguard Worker assert(alloc_size >= leadsize + size);
118*1208bc7eSAndroid Build Coastguard Worker #ifdef _WIN32
119*1208bc7eSAndroid Build Coastguard Worker os_pages_unmap(addr, alloc_size);
120*1208bc7eSAndroid Build Coastguard Worker void *new_addr = os_pages_map(ret, size, PAGE, commit);
121*1208bc7eSAndroid Build Coastguard Worker if (new_addr == ret) {
122*1208bc7eSAndroid Build Coastguard Worker return ret;
123*1208bc7eSAndroid Build Coastguard Worker }
124*1208bc7eSAndroid Build Coastguard Worker if (new_addr != NULL) {
125*1208bc7eSAndroid Build Coastguard Worker os_pages_unmap(new_addr, size);
126*1208bc7eSAndroid Build Coastguard Worker }
127*1208bc7eSAndroid Build Coastguard Worker return NULL;
128*1208bc7eSAndroid Build Coastguard Worker #else
129*1208bc7eSAndroid Build Coastguard Worker size_t trailsize = alloc_size - leadsize - size;
130*1208bc7eSAndroid Build Coastguard Worker
131*1208bc7eSAndroid Build Coastguard Worker if (leadsize != 0) {
132*1208bc7eSAndroid Build Coastguard Worker os_pages_unmap(addr, leadsize);
133*1208bc7eSAndroid Build Coastguard Worker }
134*1208bc7eSAndroid Build Coastguard Worker if (trailsize != 0) {
135*1208bc7eSAndroid Build Coastguard Worker os_pages_unmap((void *)((uintptr_t)ret + size), trailsize);
136*1208bc7eSAndroid Build Coastguard Worker }
137*1208bc7eSAndroid Build Coastguard Worker return ret;
138*1208bc7eSAndroid Build Coastguard Worker #endif
139*1208bc7eSAndroid Build Coastguard Worker }
140*1208bc7eSAndroid Build Coastguard Worker
141*1208bc7eSAndroid Build Coastguard Worker static void
os_pages_unmap(void * addr,size_t size)142*1208bc7eSAndroid Build Coastguard Worker os_pages_unmap(void *addr, size_t size) {
143*1208bc7eSAndroid Build Coastguard Worker assert(ALIGNMENT_ADDR2BASE(addr, os_page) == addr);
144*1208bc7eSAndroid Build Coastguard Worker assert(ALIGNMENT_CEILING(size, os_page) == size);
145*1208bc7eSAndroid Build Coastguard Worker
146*1208bc7eSAndroid Build Coastguard Worker #ifdef _WIN32
147*1208bc7eSAndroid Build Coastguard Worker if (VirtualFree(addr, 0, MEM_RELEASE) == 0)
148*1208bc7eSAndroid Build Coastguard Worker #else
149*1208bc7eSAndroid Build Coastguard Worker if (munmap(addr, size) == -1)
150*1208bc7eSAndroid Build Coastguard Worker #endif
151*1208bc7eSAndroid Build Coastguard Worker {
152*1208bc7eSAndroid Build Coastguard Worker char buf[BUFERROR_BUF];
153*1208bc7eSAndroid Build Coastguard Worker
154*1208bc7eSAndroid Build Coastguard Worker buferror(get_errno(), buf, sizeof(buf));
155*1208bc7eSAndroid Build Coastguard Worker malloc_printf("<jemalloc>: Error in "
156*1208bc7eSAndroid Build Coastguard Worker #ifdef _WIN32
157*1208bc7eSAndroid Build Coastguard Worker "VirtualFree"
158*1208bc7eSAndroid Build Coastguard Worker #else
159*1208bc7eSAndroid Build Coastguard Worker "munmap"
160*1208bc7eSAndroid Build Coastguard Worker #endif
161*1208bc7eSAndroid Build Coastguard Worker "(): %s\n", buf);
162*1208bc7eSAndroid Build Coastguard Worker if (opt_abort) {
163*1208bc7eSAndroid Build Coastguard Worker abort();
164*1208bc7eSAndroid Build Coastguard Worker }
165*1208bc7eSAndroid Build Coastguard Worker }
166*1208bc7eSAndroid Build Coastguard Worker }
167*1208bc7eSAndroid Build Coastguard Worker
168*1208bc7eSAndroid Build Coastguard Worker static void *
pages_map_slow(size_t size,size_t alignment,bool * commit)169*1208bc7eSAndroid Build Coastguard Worker pages_map_slow(size_t size, size_t alignment, bool *commit) {
170*1208bc7eSAndroid Build Coastguard Worker size_t alloc_size = size + alignment - os_page;
171*1208bc7eSAndroid Build Coastguard Worker /* Beware size_t wrap-around. */
172*1208bc7eSAndroid Build Coastguard Worker if (alloc_size < size) {
173*1208bc7eSAndroid Build Coastguard Worker return NULL;
174*1208bc7eSAndroid Build Coastguard Worker }
175*1208bc7eSAndroid Build Coastguard Worker
176*1208bc7eSAndroid Build Coastguard Worker void *ret;
177*1208bc7eSAndroid Build Coastguard Worker do {
178*1208bc7eSAndroid Build Coastguard Worker void *pages = os_pages_map(NULL, alloc_size, alignment, commit);
179*1208bc7eSAndroid Build Coastguard Worker if (pages == NULL) {
180*1208bc7eSAndroid Build Coastguard Worker return NULL;
181*1208bc7eSAndroid Build Coastguard Worker }
182*1208bc7eSAndroid Build Coastguard Worker size_t leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment)
183*1208bc7eSAndroid Build Coastguard Worker - (uintptr_t)pages;
184*1208bc7eSAndroid Build Coastguard Worker ret = os_pages_trim(pages, alloc_size, leadsize, size, commit);
185*1208bc7eSAndroid Build Coastguard Worker } while (ret == NULL);
186*1208bc7eSAndroid Build Coastguard Worker
187*1208bc7eSAndroid Build Coastguard Worker assert(ret != NULL);
188*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_ADDR2BASE(ret) == ret);
189*1208bc7eSAndroid Build Coastguard Worker return ret;
190*1208bc7eSAndroid Build Coastguard Worker }
191*1208bc7eSAndroid Build Coastguard Worker
192*1208bc7eSAndroid Build Coastguard Worker void *
pages_map(void * addr,size_t size,size_t alignment,bool * commit)193*1208bc7eSAndroid Build Coastguard Worker pages_map(void *addr, size_t size, size_t alignment, bool *commit) {
194*1208bc7eSAndroid Build Coastguard Worker assert(alignment >= PAGE);
195*1208bc7eSAndroid Build Coastguard Worker assert(ALIGNMENT_ADDR2BASE(addr, alignment) == addr);
196*1208bc7eSAndroid Build Coastguard Worker
197*1208bc7eSAndroid Build Coastguard Worker /*
198*1208bc7eSAndroid Build Coastguard Worker * Ideally, there would be a way to specify alignment to mmap() (like
199*1208bc7eSAndroid Build Coastguard Worker * NetBSD has), but in the absence of such a feature, we have to work
200*1208bc7eSAndroid Build Coastguard Worker * hard to efficiently create aligned mappings. The reliable, but
201*1208bc7eSAndroid Build Coastguard Worker * slow method is to create a mapping that is over-sized, then trim the
202*1208bc7eSAndroid Build Coastguard Worker * excess. However, that always results in one or two calls to
203*1208bc7eSAndroid Build Coastguard Worker * os_pages_unmap(), and it can leave holes in the process's virtual
204*1208bc7eSAndroid Build Coastguard Worker * memory map if memory grows downward.
205*1208bc7eSAndroid Build Coastguard Worker *
206*1208bc7eSAndroid Build Coastguard Worker * Optimistically try mapping precisely the right amount before falling
207*1208bc7eSAndroid Build Coastguard Worker * back to the slow method, with the expectation that the optimistic
208*1208bc7eSAndroid Build Coastguard Worker * approach works most of the time.
209*1208bc7eSAndroid Build Coastguard Worker */
210*1208bc7eSAndroid Build Coastguard Worker
211*1208bc7eSAndroid Build Coastguard Worker void *ret = os_pages_map(addr, size, os_page, commit);
212*1208bc7eSAndroid Build Coastguard Worker if (ret == NULL || ret == addr) {
213*1208bc7eSAndroid Build Coastguard Worker return ret;
214*1208bc7eSAndroid Build Coastguard Worker }
215*1208bc7eSAndroid Build Coastguard Worker assert(addr == NULL);
216*1208bc7eSAndroid Build Coastguard Worker if (ALIGNMENT_ADDR2OFFSET(ret, alignment) != 0) {
217*1208bc7eSAndroid Build Coastguard Worker os_pages_unmap(ret, size);
218*1208bc7eSAndroid Build Coastguard Worker return pages_map_slow(size, alignment, commit);
219*1208bc7eSAndroid Build Coastguard Worker }
220*1208bc7eSAndroid Build Coastguard Worker
221*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_ADDR2BASE(ret) == ret);
222*1208bc7eSAndroid Build Coastguard Worker return ret;
223*1208bc7eSAndroid Build Coastguard Worker }
224*1208bc7eSAndroid Build Coastguard Worker
225*1208bc7eSAndroid Build Coastguard Worker void
pages_unmap(void * addr,size_t size)226*1208bc7eSAndroid Build Coastguard Worker pages_unmap(void *addr, size_t size) {
227*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_ADDR2BASE(addr) == addr);
228*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_CEILING(size) == size);
229*1208bc7eSAndroid Build Coastguard Worker
230*1208bc7eSAndroid Build Coastguard Worker os_pages_unmap(addr, size);
231*1208bc7eSAndroid Build Coastguard Worker }
232*1208bc7eSAndroid Build Coastguard Worker
233*1208bc7eSAndroid Build Coastguard Worker static bool
pages_commit_impl(void * addr,size_t size,bool commit)234*1208bc7eSAndroid Build Coastguard Worker pages_commit_impl(void *addr, size_t size, bool commit) {
235*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_ADDR2BASE(addr) == addr);
236*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_CEILING(size) == size);
237*1208bc7eSAndroid Build Coastguard Worker
238*1208bc7eSAndroid Build Coastguard Worker if (os_overcommits) {
239*1208bc7eSAndroid Build Coastguard Worker return true;
240*1208bc7eSAndroid Build Coastguard Worker }
241*1208bc7eSAndroid Build Coastguard Worker
242*1208bc7eSAndroid Build Coastguard Worker #ifdef _WIN32
243*1208bc7eSAndroid Build Coastguard Worker return (commit ? (addr != VirtualAlloc(addr, size, MEM_COMMIT,
244*1208bc7eSAndroid Build Coastguard Worker PAGE_READWRITE)) : (!VirtualFree(addr, size, MEM_DECOMMIT)));
245*1208bc7eSAndroid Build Coastguard Worker #else
246*1208bc7eSAndroid Build Coastguard Worker {
247*1208bc7eSAndroid Build Coastguard Worker int prot = commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT;
248*1208bc7eSAndroid Build Coastguard Worker void *result = mmap(addr, size, prot, mmap_flags | MAP_FIXED,
249*1208bc7eSAndroid Build Coastguard Worker -1, 0);
250*1208bc7eSAndroid Build Coastguard Worker if (result == MAP_FAILED) {
251*1208bc7eSAndroid Build Coastguard Worker return true;
252*1208bc7eSAndroid Build Coastguard Worker }
253*1208bc7eSAndroid Build Coastguard Worker if (result != addr) {
254*1208bc7eSAndroid Build Coastguard Worker /*
255*1208bc7eSAndroid Build Coastguard Worker * We succeeded in mapping memory, but not in the right
256*1208bc7eSAndroid Build Coastguard Worker * place.
257*1208bc7eSAndroid Build Coastguard Worker */
258*1208bc7eSAndroid Build Coastguard Worker os_pages_unmap(result, size);
259*1208bc7eSAndroid Build Coastguard Worker return true;
260*1208bc7eSAndroid Build Coastguard Worker }
261*1208bc7eSAndroid Build Coastguard Worker return false;
262*1208bc7eSAndroid Build Coastguard Worker }
263*1208bc7eSAndroid Build Coastguard Worker #endif
264*1208bc7eSAndroid Build Coastguard Worker }
265*1208bc7eSAndroid Build Coastguard Worker
266*1208bc7eSAndroid Build Coastguard Worker bool
pages_commit(void * addr,size_t size)267*1208bc7eSAndroid Build Coastguard Worker pages_commit(void *addr, size_t size) {
268*1208bc7eSAndroid Build Coastguard Worker return pages_commit_impl(addr, size, true);
269*1208bc7eSAndroid Build Coastguard Worker }
270*1208bc7eSAndroid Build Coastguard Worker
271*1208bc7eSAndroid Build Coastguard Worker bool
pages_decommit(void * addr,size_t size)272*1208bc7eSAndroid Build Coastguard Worker pages_decommit(void *addr, size_t size) {
273*1208bc7eSAndroid Build Coastguard Worker return pages_commit_impl(addr, size, false);
274*1208bc7eSAndroid Build Coastguard Worker }
275*1208bc7eSAndroid Build Coastguard Worker
276*1208bc7eSAndroid Build Coastguard Worker bool
pages_purge_lazy(void * addr,size_t size)277*1208bc7eSAndroid Build Coastguard Worker pages_purge_lazy(void *addr, size_t size) {
278*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_ADDR2BASE(addr) == addr);
279*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_CEILING(size) == size);
280*1208bc7eSAndroid Build Coastguard Worker
281*1208bc7eSAndroid Build Coastguard Worker if (!pages_can_purge_lazy) {
282*1208bc7eSAndroid Build Coastguard Worker return true;
283*1208bc7eSAndroid Build Coastguard Worker }
284*1208bc7eSAndroid Build Coastguard Worker if (!pages_can_purge_lazy_runtime) {
285*1208bc7eSAndroid Build Coastguard Worker /*
286*1208bc7eSAndroid Build Coastguard Worker * Built with lazy purge enabled, but detected it was not
287*1208bc7eSAndroid Build Coastguard Worker * supported on the current system.
288*1208bc7eSAndroid Build Coastguard Worker */
289*1208bc7eSAndroid Build Coastguard Worker return true;
290*1208bc7eSAndroid Build Coastguard Worker }
291*1208bc7eSAndroid Build Coastguard Worker
292*1208bc7eSAndroid Build Coastguard Worker #ifdef _WIN32
293*1208bc7eSAndroid Build Coastguard Worker VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE);
294*1208bc7eSAndroid Build Coastguard Worker return false;
295*1208bc7eSAndroid Build Coastguard Worker #elif defined(JEMALLOC_PURGE_MADVISE_FREE)
296*1208bc7eSAndroid Build Coastguard Worker return (madvise(addr, size,
297*1208bc7eSAndroid Build Coastguard Worker # ifdef MADV_FREE
298*1208bc7eSAndroid Build Coastguard Worker MADV_FREE
299*1208bc7eSAndroid Build Coastguard Worker # else
300*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_MADV_FREE
301*1208bc7eSAndroid Build Coastguard Worker # endif
302*1208bc7eSAndroid Build Coastguard Worker ) != 0);
303*1208bc7eSAndroid Build Coastguard Worker #elif defined(JEMALLOC_PURGE_MADVISE_DONTNEED) && \
304*1208bc7eSAndroid Build Coastguard Worker !defined(JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS)
305*1208bc7eSAndroid Build Coastguard Worker return (madvise(addr, size, MADV_DONTNEED) != 0);
306*1208bc7eSAndroid Build Coastguard Worker #else
307*1208bc7eSAndroid Build Coastguard Worker not_reached();
308*1208bc7eSAndroid Build Coastguard Worker #endif
309*1208bc7eSAndroid Build Coastguard Worker }
310*1208bc7eSAndroid Build Coastguard Worker
311*1208bc7eSAndroid Build Coastguard Worker bool
pages_purge_forced(void * addr,size_t size)312*1208bc7eSAndroid Build Coastguard Worker pages_purge_forced(void *addr, size_t size) {
313*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_ADDR2BASE(addr) == addr);
314*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_CEILING(size) == size);
315*1208bc7eSAndroid Build Coastguard Worker
316*1208bc7eSAndroid Build Coastguard Worker if (!pages_can_purge_forced) {
317*1208bc7eSAndroid Build Coastguard Worker return true;
318*1208bc7eSAndroid Build Coastguard Worker }
319*1208bc7eSAndroid Build Coastguard Worker
320*1208bc7eSAndroid Build Coastguard Worker #if defined(JEMALLOC_PURGE_MADVISE_DONTNEED) && \
321*1208bc7eSAndroid Build Coastguard Worker defined(JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS)
322*1208bc7eSAndroid Build Coastguard Worker return (madvise(addr, size, MADV_DONTNEED) != 0);
323*1208bc7eSAndroid Build Coastguard Worker #elif defined(JEMALLOC_MAPS_COALESCE)
324*1208bc7eSAndroid Build Coastguard Worker /* Try to overlay a new demand-zeroed mapping. */
325*1208bc7eSAndroid Build Coastguard Worker return pages_commit(addr, size);
326*1208bc7eSAndroid Build Coastguard Worker #else
327*1208bc7eSAndroid Build Coastguard Worker not_reached();
328*1208bc7eSAndroid Build Coastguard Worker #endif
329*1208bc7eSAndroid Build Coastguard Worker }
330*1208bc7eSAndroid Build Coastguard Worker
331*1208bc7eSAndroid Build Coastguard Worker static bool
pages_huge_impl(void * addr,size_t size,bool aligned)332*1208bc7eSAndroid Build Coastguard Worker pages_huge_impl(void *addr, size_t size, bool aligned) {
333*1208bc7eSAndroid Build Coastguard Worker if (aligned) {
334*1208bc7eSAndroid Build Coastguard Worker assert(HUGEPAGE_ADDR2BASE(addr) == addr);
335*1208bc7eSAndroid Build Coastguard Worker assert(HUGEPAGE_CEILING(size) == size);
336*1208bc7eSAndroid Build Coastguard Worker }
337*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_HAVE_MADVISE_HUGE
338*1208bc7eSAndroid Build Coastguard Worker return (madvise(addr, size, MADV_HUGEPAGE) != 0);
339*1208bc7eSAndroid Build Coastguard Worker #else
340*1208bc7eSAndroid Build Coastguard Worker return true;
341*1208bc7eSAndroid Build Coastguard Worker #endif
342*1208bc7eSAndroid Build Coastguard Worker }
343*1208bc7eSAndroid Build Coastguard Worker
344*1208bc7eSAndroid Build Coastguard Worker bool
pages_huge(void * addr,size_t size)345*1208bc7eSAndroid Build Coastguard Worker pages_huge(void *addr, size_t size) {
346*1208bc7eSAndroid Build Coastguard Worker return pages_huge_impl(addr, size, true);
347*1208bc7eSAndroid Build Coastguard Worker }
348*1208bc7eSAndroid Build Coastguard Worker
349*1208bc7eSAndroid Build Coastguard Worker static bool
pages_huge_unaligned(void * addr,size_t size)350*1208bc7eSAndroid Build Coastguard Worker pages_huge_unaligned(void *addr, size_t size) {
351*1208bc7eSAndroid Build Coastguard Worker return pages_huge_impl(addr, size, false);
352*1208bc7eSAndroid Build Coastguard Worker }
353*1208bc7eSAndroid Build Coastguard Worker
354*1208bc7eSAndroid Build Coastguard Worker static bool
pages_nohuge_impl(void * addr,size_t size,bool aligned)355*1208bc7eSAndroid Build Coastguard Worker pages_nohuge_impl(void *addr, size_t size, bool aligned) {
356*1208bc7eSAndroid Build Coastguard Worker if (aligned) {
357*1208bc7eSAndroid Build Coastguard Worker assert(HUGEPAGE_ADDR2BASE(addr) == addr);
358*1208bc7eSAndroid Build Coastguard Worker assert(HUGEPAGE_CEILING(size) == size);
359*1208bc7eSAndroid Build Coastguard Worker }
360*1208bc7eSAndroid Build Coastguard Worker
361*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_HAVE_MADVISE_HUGE
362*1208bc7eSAndroid Build Coastguard Worker return (madvise(addr, size, MADV_NOHUGEPAGE) != 0);
363*1208bc7eSAndroid Build Coastguard Worker #else
364*1208bc7eSAndroid Build Coastguard Worker return false;
365*1208bc7eSAndroid Build Coastguard Worker #endif
366*1208bc7eSAndroid Build Coastguard Worker }
367*1208bc7eSAndroid Build Coastguard Worker
368*1208bc7eSAndroid Build Coastguard Worker bool
pages_nohuge(void * addr,size_t size)369*1208bc7eSAndroid Build Coastguard Worker pages_nohuge(void *addr, size_t size) {
370*1208bc7eSAndroid Build Coastguard Worker return pages_nohuge_impl(addr, size, true);
371*1208bc7eSAndroid Build Coastguard Worker }
372*1208bc7eSAndroid Build Coastguard Worker
373*1208bc7eSAndroid Build Coastguard Worker static bool
pages_nohuge_unaligned(void * addr,size_t size)374*1208bc7eSAndroid Build Coastguard Worker pages_nohuge_unaligned(void *addr, size_t size) {
375*1208bc7eSAndroid Build Coastguard Worker return pages_nohuge_impl(addr, size, false);
376*1208bc7eSAndroid Build Coastguard Worker }
377*1208bc7eSAndroid Build Coastguard Worker
378*1208bc7eSAndroid Build Coastguard Worker bool
pages_dontdump(void * addr,size_t size)379*1208bc7eSAndroid Build Coastguard Worker pages_dontdump(void *addr, size_t size) {
380*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_ADDR2BASE(addr) == addr);
381*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_CEILING(size) == size);
382*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_MADVISE_DONTDUMP
383*1208bc7eSAndroid Build Coastguard Worker return madvise(addr, size, MADV_DONTDUMP) != 0;
384*1208bc7eSAndroid Build Coastguard Worker #else
385*1208bc7eSAndroid Build Coastguard Worker return false;
386*1208bc7eSAndroid Build Coastguard Worker #endif
387*1208bc7eSAndroid Build Coastguard Worker }
388*1208bc7eSAndroid Build Coastguard Worker
389*1208bc7eSAndroid Build Coastguard Worker bool
pages_dodump(void * addr,size_t size)390*1208bc7eSAndroid Build Coastguard Worker pages_dodump(void *addr, size_t size) {
391*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_ADDR2BASE(addr) == addr);
392*1208bc7eSAndroid Build Coastguard Worker assert(PAGE_CEILING(size) == size);
393*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_MADVISE_DONTDUMP
394*1208bc7eSAndroid Build Coastguard Worker return madvise(addr, size, MADV_DODUMP) != 0;
395*1208bc7eSAndroid Build Coastguard Worker #else
396*1208bc7eSAndroid Build Coastguard Worker return false;
397*1208bc7eSAndroid Build Coastguard Worker #endif
398*1208bc7eSAndroid Build Coastguard Worker }
399*1208bc7eSAndroid Build Coastguard Worker
400*1208bc7eSAndroid Build Coastguard Worker
401*1208bc7eSAndroid Build Coastguard Worker static size_t
os_page_detect(void)402*1208bc7eSAndroid Build Coastguard Worker os_page_detect(void) {
403*1208bc7eSAndroid Build Coastguard Worker #ifdef _WIN32
404*1208bc7eSAndroid Build Coastguard Worker SYSTEM_INFO si;
405*1208bc7eSAndroid Build Coastguard Worker GetSystemInfo(&si);
406*1208bc7eSAndroid Build Coastguard Worker return si.dwPageSize;
407*1208bc7eSAndroid Build Coastguard Worker #elif defined(__FreeBSD__)
408*1208bc7eSAndroid Build Coastguard Worker return getpagesize();
409*1208bc7eSAndroid Build Coastguard Worker #else
410*1208bc7eSAndroid Build Coastguard Worker long result = sysconf(_SC_PAGESIZE);
411*1208bc7eSAndroid Build Coastguard Worker if (result == -1) {
412*1208bc7eSAndroid Build Coastguard Worker return LG_PAGE;
413*1208bc7eSAndroid Build Coastguard Worker }
414*1208bc7eSAndroid Build Coastguard Worker return (size_t)result;
415*1208bc7eSAndroid Build Coastguard Worker #endif
416*1208bc7eSAndroid Build Coastguard Worker }
417*1208bc7eSAndroid Build Coastguard Worker
418*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT
419*1208bc7eSAndroid Build Coastguard Worker static bool
os_overcommits_sysctl(void)420*1208bc7eSAndroid Build Coastguard Worker os_overcommits_sysctl(void) {
421*1208bc7eSAndroid Build Coastguard Worker int vm_overcommit;
422*1208bc7eSAndroid Build Coastguard Worker size_t sz;
423*1208bc7eSAndroid Build Coastguard Worker
424*1208bc7eSAndroid Build Coastguard Worker sz = sizeof(vm_overcommit);
425*1208bc7eSAndroid Build Coastguard Worker #if defined(__FreeBSD__) && defined(VM_OVERCOMMIT)
426*1208bc7eSAndroid Build Coastguard Worker int mib[2];
427*1208bc7eSAndroid Build Coastguard Worker
428*1208bc7eSAndroid Build Coastguard Worker mib[0] = CTL_VM;
429*1208bc7eSAndroid Build Coastguard Worker mib[1] = VM_OVERCOMMIT;
430*1208bc7eSAndroid Build Coastguard Worker if (sysctl(mib, 2, &vm_overcommit, &sz, NULL, 0) != 0) {
431*1208bc7eSAndroid Build Coastguard Worker return false; /* Error. */
432*1208bc7eSAndroid Build Coastguard Worker }
433*1208bc7eSAndroid Build Coastguard Worker #else
434*1208bc7eSAndroid Build Coastguard Worker if (sysctlbyname("vm.overcommit", &vm_overcommit, &sz, NULL, 0) != 0) {
435*1208bc7eSAndroid Build Coastguard Worker return false; /* Error. */
436*1208bc7eSAndroid Build Coastguard Worker }
437*1208bc7eSAndroid Build Coastguard Worker #endif
438*1208bc7eSAndroid Build Coastguard Worker
439*1208bc7eSAndroid Build Coastguard Worker return ((vm_overcommit & 0x3) == 0);
440*1208bc7eSAndroid Build Coastguard Worker }
441*1208bc7eSAndroid Build Coastguard Worker #endif
442*1208bc7eSAndroid Build Coastguard Worker
443*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY
444*1208bc7eSAndroid Build Coastguard Worker /*
445*1208bc7eSAndroid Build Coastguard Worker * Use syscall(2) rather than {open,read,close}(2) when possible to avoid
446*1208bc7eSAndroid Build Coastguard Worker * reentry during bootstrapping if another library has interposed system call
447*1208bc7eSAndroid Build Coastguard Worker * wrappers.
448*1208bc7eSAndroid Build Coastguard Worker */
449*1208bc7eSAndroid Build Coastguard Worker static bool
os_overcommits_proc(void)450*1208bc7eSAndroid Build Coastguard Worker os_overcommits_proc(void) {
451*1208bc7eSAndroid Build Coastguard Worker int fd;
452*1208bc7eSAndroid Build Coastguard Worker char buf[1];
453*1208bc7eSAndroid Build Coastguard Worker
454*1208bc7eSAndroid Build Coastguard Worker #if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_open)
455*1208bc7eSAndroid Build Coastguard Worker #if defined(O_CLOEXEC)
456*1208bc7eSAndroid Build Coastguard Worker fd = (int)syscall(SYS_open, "/proc/sys/vm/overcommit_memory", O_RDONLY |
457*1208bc7eSAndroid Build Coastguard Worker O_CLOEXEC);
458*1208bc7eSAndroid Build Coastguard Worker #else
459*1208bc7eSAndroid Build Coastguard Worker fd = (int)syscall(SYS_open, "/proc/sys/vm/overcommit_memory", O_RDONLY);
460*1208bc7eSAndroid Build Coastguard Worker if (fd != -1) {
461*1208bc7eSAndroid Build Coastguard Worker fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
462*1208bc7eSAndroid Build Coastguard Worker }
463*1208bc7eSAndroid Build Coastguard Worker #endif
464*1208bc7eSAndroid Build Coastguard Worker #elif defined(JEMALLOC_USE_SYSCALL) && defined(SYS_openat)
465*1208bc7eSAndroid Build Coastguard Worker #if defined(O_CLOEXEC)
466*1208bc7eSAndroid Build Coastguard Worker fd = (int)syscall(SYS_openat,
467*1208bc7eSAndroid Build Coastguard Worker AT_FDCWD, "/proc/sys/vm/overcommit_memory", O_RDONLY | O_CLOEXEC);
468*1208bc7eSAndroid Build Coastguard Worker #else
469*1208bc7eSAndroid Build Coastguard Worker fd = (int)syscall(SYS_openat,
470*1208bc7eSAndroid Build Coastguard Worker AT_FDCWD, "/proc/sys/vm/overcommit_memory", O_RDONLY);
471*1208bc7eSAndroid Build Coastguard Worker if (fd != -1) {
472*1208bc7eSAndroid Build Coastguard Worker fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
473*1208bc7eSAndroid Build Coastguard Worker }
474*1208bc7eSAndroid Build Coastguard Worker #endif
475*1208bc7eSAndroid Build Coastguard Worker #else
476*1208bc7eSAndroid Build Coastguard Worker #if defined(O_CLOEXEC)
477*1208bc7eSAndroid Build Coastguard Worker fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY | O_CLOEXEC);
478*1208bc7eSAndroid Build Coastguard Worker #else
479*1208bc7eSAndroid Build Coastguard Worker fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY);
480*1208bc7eSAndroid Build Coastguard Worker if (fd != -1) {
481*1208bc7eSAndroid Build Coastguard Worker fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
482*1208bc7eSAndroid Build Coastguard Worker }
483*1208bc7eSAndroid Build Coastguard Worker #endif
484*1208bc7eSAndroid Build Coastguard Worker #endif
485*1208bc7eSAndroid Build Coastguard Worker
486*1208bc7eSAndroid Build Coastguard Worker if (fd == -1) {
487*1208bc7eSAndroid Build Coastguard Worker return false; /* Error. */
488*1208bc7eSAndroid Build Coastguard Worker }
489*1208bc7eSAndroid Build Coastguard Worker
490*1208bc7eSAndroid Build Coastguard Worker ssize_t nread = malloc_read_fd(fd, &buf, sizeof(buf));
491*1208bc7eSAndroid Build Coastguard Worker #if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_close)
492*1208bc7eSAndroid Build Coastguard Worker syscall(SYS_close, fd);
493*1208bc7eSAndroid Build Coastguard Worker #else
494*1208bc7eSAndroid Build Coastguard Worker close(fd);
495*1208bc7eSAndroid Build Coastguard Worker #endif
496*1208bc7eSAndroid Build Coastguard Worker
497*1208bc7eSAndroid Build Coastguard Worker if (nread < 1) {
498*1208bc7eSAndroid Build Coastguard Worker return false; /* Error. */
499*1208bc7eSAndroid Build Coastguard Worker }
500*1208bc7eSAndroid Build Coastguard Worker /*
501*1208bc7eSAndroid Build Coastguard Worker * /proc/sys/vm/overcommit_memory meanings:
502*1208bc7eSAndroid Build Coastguard Worker * 0: Heuristic overcommit.
503*1208bc7eSAndroid Build Coastguard Worker * 1: Always overcommit.
504*1208bc7eSAndroid Build Coastguard Worker * 2: Never overcommit.
505*1208bc7eSAndroid Build Coastguard Worker */
506*1208bc7eSAndroid Build Coastguard Worker return (buf[0] == '0' || buf[0] == '1');
507*1208bc7eSAndroid Build Coastguard Worker }
508*1208bc7eSAndroid Build Coastguard Worker #endif
509*1208bc7eSAndroid Build Coastguard Worker
510*1208bc7eSAndroid Build Coastguard Worker void
pages_set_thp_state(void * ptr,size_t size)511*1208bc7eSAndroid Build Coastguard Worker pages_set_thp_state (void *ptr, size_t size) {
512*1208bc7eSAndroid Build Coastguard Worker if (opt_thp == thp_mode_default || opt_thp == init_system_thp_mode) {
513*1208bc7eSAndroid Build Coastguard Worker return;
514*1208bc7eSAndroid Build Coastguard Worker }
515*1208bc7eSAndroid Build Coastguard Worker assert(opt_thp != thp_mode_not_supported &&
516*1208bc7eSAndroid Build Coastguard Worker init_system_thp_mode != thp_mode_not_supported);
517*1208bc7eSAndroid Build Coastguard Worker
518*1208bc7eSAndroid Build Coastguard Worker if (opt_thp == thp_mode_always
519*1208bc7eSAndroid Build Coastguard Worker && init_system_thp_mode != thp_mode_never) {
520*1208bc7eSAndroid Build Coastguard Worker assert(init_system_thp_mode == thp_mode_default);
521*1208bc7eSAndroid Build Coastguard Worker pages_huge_unaligned(ptr, size);
522*1208bc7eSAndroid Build Coastguard Worker } else if (opt_thp == thp_mode_never) {
523*1208bc7eSAndroid Build Coastguard Worker assert(init_system_thp_mode == thp_mode_default ||
524*1208bc7eSAndroid Build Coastguard Worker init_system_thp_mode == thp_mode_always);
525*1208bc7eSAndroid Build Coastguard Worker pages_nohuge_unaligned(ptr, size);
526*1208bc7eSAndroid Build Coastguard Worker }
527*1208bc7eSAndroid Build Coastguard Worker }
528*1208bc7eSAndroid Build Coastguard Worker
529*1208bc7eSAndroid Build Coastguard Worker static void
init_thp_state(void)530*1208bc7eSAndroid Build Coastguard Worker init_thp_state(void) {
531*1208bc7eSAndroid Build Coastguard Worker if (!have_madvise_huge) {
532*1208bc7eSAndroid Build Coastguard Worker if (metadata_thp_enabled() && opt_abort) {
533*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: no MADV_HUGEPAGE support\n");
534*1208bc7eSAndroid Build Coastguard Worker abort();
535*1208bc7eSAndroid Build Coastguard Worker }
536*1208bc7eSAndroid Build Coastguard Worker goto label_error;
537*1208bc7eSAndroid Build Coastguard Worker }
538*1208bc7eSAndroid Build Coastguard Worker
539*1208bc7eSAndroid Build Coastguard Worker static const char sys_state_madvise[] = "always [madvise] never\n";
540*1208bc7eSAndroid Build Coastguard Worker static const char sys_state_always[] = "[always] madvise never\n";
541*1208bc7eSAndroid Build Coastguard Worker static const char sys_state_never[] = "always madvise [never]\n";
542*1208bc7eSAndroid Build Coastguard Worker char buf[sizeof(sys_state_madvise)];
543*1208bc7eSAndroid Build Coastguard Worker
544*1208bc7eSAndroid Build Coastguard Worker #if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_open)
545*1208bc7eSAndroid Build Coastguard Worker int fd = (int)syscall(SYS_open,
546*1208bc7eSAndroid Build Coastguard Worker "/sys/kernel/mm/transparent_hugepage/enabled", O_RDONLY);
547*1208bc7eSAndroid Build Coastguard Worker #else
548*1208bc7eSAndroid Build Coastguard Worker int fd = open("/sys/kernel/mm/transparent_hugepage/enabled", O_RDONLY);
549*1208bc7eSAndroid Build Coastguard Worker #endif
550*1208bc7eSAndroid Build Coastguard Worker if (fd == -1) {
551*1208bc7eSAndroid Build Coastguard Worker goto label_error;
552*1208bc7eSAndroid Build Coastguard Worker }
553*1208bc7eSAndroid Build Coastguard Worker
554*1208bc7eSAndroid Build Coastguard Worker ssize_t nread = malloc_read_fd(fd, &buf, sizeof(buf));
555*1208bc7eSAndroid Build Coastguard Worker #if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_close)
556*1208bc7eSAndroid Build Coastguard Worker syscall(SYS_close, fd);
557*1208bc7eSAndroid Build Coastguard Worker #else
558*1208bc7eSAndroid Build Coastguard Worker close(fd);
559*1208bc7eSAndroid Build Coastguard Worker #endif
560*1208bc7eSAndroid Build Coastguard Worker
561*1208bc7eSAndroid Build Coastguard Worker if (strncmp(buf, sys_state_madvise, (size_t)nread) == 0) {
562*1208bc7eSAndroid Build Coastguard Worker init_system_thp_mode = thp_mode_default;
563*1208bc7eSAndroid Build Coastguard Worker } else if (strncmp(buf, sys_state_always, (size_t)nread) == 0) {
564*1208bc7eSAndroid Build Coastguard Worker init_system_thp_mode = thp_mode_always;
565*1208bc7eSAndroid Build Coastguard Worker } else if (strncmp(buf, sys_state_never, (size_t)nread) == 0) {
566*1208bc7eSAndroid Build Coastguard Worker init_system_thp_mode = thp_mode_never;
567*1208bc7eSAndroid Build Coastguard Worker } else {
568*1208bc7eSAndroid Build Coastguard Worker goto label_error;
569*1208bc7eSAndroid Build Coastguard Worker }
570*1208bc7eSAndroid Build Coastguard Worker return;
571*1208bc7eSAndroid Build Coastguard Worker label_error:
572*1208bc7eSAndroid Build Coastguard Worker opt_thp = init_system_thp_mode = thp_mode_not_supported;
573*1208bc7eSAndroid Build Coastguard Worker }
574*1208bc7eSAndroid Build Coastguard Worker
575*1208bc7eSAndroid Build Coastguard Worker bool
pages_boot(void)576*1208bc7eSAndroid Build Coastguard Worker pages_boot(void) {
577*1208bc7eSAndroid Build Coastguard Worker os_page = os_page_detect();
578*1208bc7eSAndroid Build Coastguard Worker if (os_page > PAGE) {
579*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Unsupported system page size\n");
580*1208bc7eSAndroid Build Coastguard Worker if (opt_abort) {
581*1208bc7eSAndroid Build Coastguard Worker abort();
582*1208bc7eSAndroid Build Coastguard Worker }
583*1208bc7eSAndroid Build Coastguard Worker return true;
584*1208bc7eSAndroid Build Coastguard Worker }
585*1208bc7eSAndroid Build Coastguard Worker
586*1208bc7eSAndroid Build Coastguard Worker #ifndef _WIN32
587*1208bc7eSAndroid Build Coastguard Worker mmap_flags = MAP_PRIVATE | MAP_ANON;
588*1208bc7eSAndroid Build Coastguard Worker #endif
589*1208bc7eSAndroid Build Coastguard Worker
590*1208bc7eSAndroid Build Coastguard Worker #if defined(__ANDROID__)
591*1208bc7eSAndroid Build Coastguard Worker /* Android always supports overcommits. */
592*1208bc7eSAndroid Build Coastguard Worker os_overcommits = true;
593*1208bc7eSAndroid Build Coastguard Worker #else /* __ANDROID__ */
594*1208bc7eSAndroid Build Coastguard Worker
595*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT
596*1208bc7eSAndroid Build Coastguard Worker os_overcommits = os_overcommits_sysctl();
597*1208bc7eSAndroid Build Coastguard Worker #elif defined(JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY)
598*1208bc7eSAndroid Build Coastguard Worker os_overcommits = os_overcommits_proc();
599*1208bc7eSAndroid Build Coastguard Worker # ifdef MAP_NORESERVE
600*1208bc7eSAndroid Build Coastguard Worker if (os_overcommits) {
601*1208bc7eSAndroid Build Coastguard Worker mmap_flags |= MAP_NORESERVE;
602*1208bc7eSAndroid Build Coastguard Worker }
603*1208bc7eSAndroid Build Coastguard Worker # endif
604*1208bc7eSAndroid Build Coastguard Worker #else
605*1208bc7eSAndroid Build Coastguard Worker os_overcommits = false;
606*1208bc7eSAndroid Build Coastguard Worker #endif
607*1208bc7eSAndroid Build Coastguard Worker
608*1208bc7eSAndroid Build Coastguard Worker #endif /* __ANDROID__ */
609*1208bc7eSAndroid Build Coastguard Worker
610*1208bc7eSAndroid Build Coastguard Worker init_thp_state();
611*1208bc7eSAndroid Build Coastguard Worker
612*1208bc7eSAndroid Build Coastguard Worker /* Detect lazy purge runtime support. */
613*1208bc7eSAndroid Build Coastguard Worker if (pages_can_purge_lazy) {
614*1208bc7eSAndroid Build Coastguard Worker bool committed = false;
615*1208bc7eSAndroid Build Coastguard Worker void *madv_free_page = os_pages_map(NULL, PAGE, PAGE, &committed);
616*1208bc7eSAndroid Build Coastguard Worker if (madv_free_page == NULL) {
617*1208bc7eSAndroid Build Coastguard Worker return true;
618*1208bc7eSAndroid Build Coastguard Worker }
619*1208bc7eSAndroid Build Coastguard Worker assert(pages_can_purge_lazy_runtime);
620*1208bc7eSAndroid Build Coastguard Worker if (pages_purge_lazy(madv_free_page, PAGE)) {
621*1208bc7eSAndroid Build Coastguard Worker pages_can_purge_lazy_runtime = false;
622*1208bc7eSAndroid Build Coastguard Worker }
623*1208bc7eSAndroid Build Coastguard Worker os_pages_unmap(madv_free_page, PAGE);
624*1208bc7eSAndroid Build Coastguard Worker }
625*1208bc7eSAndroid Build Coastguard Worker
626*1208bc7eSAndroid Build Coastguard Worker return false;
627*1208bc7eSAndroid Build Coastguard Worker }
628