1 #define JEMALLOC_PAGES_C_
2 #include "jemalloc/internal/jemalloc_internal.h"
4 #ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT
5 #include <sys/sysctl.h>
8 /******************************************************************************/
12 # define PAGES_PROT_COMMIT (PROT_READ | PROT_WRITE)
13 # define PAGES_PROT_DECOMMIT (PROT_NONE)
14 static int mmap_flags;
16 static bool os_overcommits;
18 /******************************************************************************/
21 pages_map(void *addr, size_t size, bool *commit)
32 * If VirtualAlloc can't allocate at the given address when one is
33 * given, it fails and returns NULL.
35 ret = VirtualAlloc(addr, size, MEM_RESERVE | (*commit ? MEM_COMMIT : 0),
39 * We don't use MAP_FIXED here, because it can cause the *replacement*
40 * of existing mappings, and we only want to create new mappings.
43 int prot = *commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT;
45 ret = mmap(addr, size, prot, mmap_flags, -1, 0);
49 if (ret == MAP_FAILED)
51 else if (addr != NULL && ret != addr) {
53 * We succeeded in mapping memory, but not in the right place.
55 pages_unmap(ret, size);
59 assert(ret == NULL || (addr == NULL && ret != addr)
60 || (addr != NULL && ret == addr));
65 pages_unmap(void *addr, size_t size)
69 if (VirtualFree(addr, 0, MEM_RELEASE) == 0)
71 if (munmap(addr, size) == -1)
74 char buf[BUFERROR_BUF];
76 buferror(get_errno(), buf, sizeof(buf));
77 malloc_printf("<jemalloc>: Error in "
90 pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size,
93 void *ret = (void *)((uintptr_t)addr + leadsize);
95 assert(alloc_size >= leadsize + size);
100 pages_unmap(addr, alloc_size);
101 new_addr = pages_map(ret, size, commit);
105 pages_unmap(new_addr, size);
110 size_t trailsize = alloc_size - leadsize - size;
113 pages_unmap(addr, leadsize);
115 pages_unmap((void *)((uintptr_t)ret + size), trailsize);
122 pages_commit_impl(void *addr, size_t size, bool commit)
129 return (commit ? (addr != VirtualAlloc(addr, size, MEM_COMMIT,
130 PAGE_READWRITE)) : (!VirtualFree(addr, size, MEM_DECOMMIT)));
133 int prot = commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT;
134 void *result = mmap(addr, size, prot, mmap_flags | MAP_FIXED,
136 if (result == MAP_FAILED)
138 if (result != addr) {
140 * We succeeded in mapping memory, but not in the right
143 pages_unmap(result, size);
152 pages_commit(void *addr, size_t size)
155 return (pages_commit_impl(addr, size, true));
159 pages_decommit(void *addr, size_t size)
162 return (pages_commit_impl(addr, size, false));
166 pages_purge(void *addr, size_t size)
171 VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE);
173 #elif defined(JEMALLOC_HAVE_MADVISE)
174 # ifdef JEMALLOC_PURGE_MADVISE_DONTNEED
175 # define JEMALLOC_MADV_PURGE MADV_DONTNEED
176 # define JEMALLOC_MADV_ZEROS true
177 # elif defined(JEMALLOC_PURGE_MADVISE_FREE)
178 # define JEMALLOC_MADV_PURGE MADV_FREE
179 # define JEMALLOC_MADV_ZEROS false
181 # error "No madvise(2) flag defined for purging unused dirty pages."
183 int err = madvise(addr, size, JEMALLOC_MADV_PURGE);
184 unzeroed = (!JEMALLOC_MADV_ZEROS || err != 0);
185 # undef JEMALLOC_MADV_PURGE
186 # undef JEMALLOC_MADV_ZEROS
188 /* Last resort no-op. */
194 #ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT
196 os_overcommits_sysctl(void)
201 sz = sizeof(vm_overcommit);
202 if (sysctlbyname("vm.overcommit", &vm_overcommit, &sz, NULL, 0) != 0)
203 return (false); /* Error. */
205 return ((vm_overcommit & 0x3) == 0);
209 #ifdef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY
211 os_overcommits_proc(void)
217 fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY);
219 return (false); /* Error. */
221 nread = read(fd, &buf, sizeof(buf));
223 return (false); /* Error. */
225 * /proc/sys/vm/overcommit_memory meanings:
226 * 0: Heuristic overcommit.
227 * 1: Always overcommit.
228 * 2: Never overcommit.
230 return (buf[0] == '0' || buf[0] == '1');
239 mmap_flags = MAP_PRIVATE | MAP_ANON;
242 #ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT
243 os_overcommits = os_overcommits_sysctl();
244 #elif defined(JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY)
245 os_overcommits = os_overcommits_proc();
246 # ifdef MAP_NORESERVE
248 mmap_flags |= MAP_NORESERVE;
251 os_overcommits = false;