1 #define JEMALLOC_PAGES_C_ 2 #include "jemalloc/internal/jemalloc_internal.h" 3 4 /******************************************************************************/ 5 6 void * 7 pages_map(void *addr, size_t size) 8 { 9 void *ret; 10 11 assert(size != 0); 12 13 #ifdef _WIN32 14 /* 15 * If VirtualAlloc can't allocate at the given address when one is 16 * given, it fails and returns NULL. 17 */ 18 ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, 19 PAGE_READWRITE); 20 #else 21 /* 22 * We don't use MAP_FIXED here, because it can cause the *replacement* 23 * of existing mappings, and we only want to create new mappings. 24 */ 25 ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 26 -1, 0); 27 assert(ret != NULL); 28 29 if (ret == MAP_FAILED) 30 ret = NULL; 31 else if (addr != NULL && ret != addr) { 32 /* 33 * We succeeded in mapping memory, but not in the right place. 34 */ 35 pages_unmap(ret, size); 36 ret = NULL; 37 } 38 #endif 39 assert(ret == NULL || (addr == NULL && ret != addr) 40 || (addr != NULL && ret == addr)); 41 return (ret); 42 } 43 44 void 45 pages_unmap(void *addr, size_t size) 46 { 47 48 #ifdef _WIN32 49 if (VirtualFree(addr, 0, MEM_RELEASE) == 0) 50 #else 51 if (munmap(addr, size) == -1) 52 #endif 53 { 54 char buf[BUFERROR_BUF]; 55 56 buferror(get_errno(), buf, sizeof(buf)); 57 malloc_printf("<jemalloc>: Error in " 58 #ifdef _WIN32 59 "VirtualFree" 60 #else 61 "munmap" 62 #endif 63 "(): %s\n", buf); 64 if (opt_abort) 65 abort(); 66 } 67 } 68 69 void * 70 pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size) 71 { 72 void *ret = (void *)((uintptr_t)addr + leadsize); 73 74 assert(alloc_size >= leadsize + size); 75 #ifdef _WIN32 76 { 77 void *new_addr; 78 79 pages_unmap(addr, alloc_size); 80 new_addr = pages_map(ret, size); 81 if (new_addr == ret) 82 return (ret); 83 if (new_addr) 84 pages_unmap(new_addr, size); 85 return (NULL); 86 } 87 #else 88 { 89 size_t trailsize = alloc_size - leadsize - size; 90 91 if (leadsize != 0) 92 pages_unmap(addr, leadsize); 93 if (trailsize != 0) 94 pages_unmap((void *)((uintptr_t)ret + size), trailsize); 95 return (ret); 96 } 97 #endif 98 } 99 100 static bool 101 pages_commit_impl(void *addr, size_t size, bool commit) 102 { 103 104 #ifndef _WIN32 105 /* 106 * The following decommit/commit implementation is functional, but 107 * always disabled because it doesn't add value beyong improved 108 * debugging (at the cost of extra system calls) on systems that 109 * overcommit. 110 */ 111 if (false) { 112 int prot = commit ? (PROT_READ | PROT_WRITE) : PROT_NONE; 113 void *result = mmap(addr, size, prot, MAP_PRIVATE | MAP_ANON | 114 MAP_FIXED, -1, 0); 115 if (result == MAP_FAILED) 116 return (true); 117 if (result != addr) { 118 /* 119 * We succeeded in mapping memory, but not in the right 120 * place. 121 */ 122 pages_unmap(result, size); 123 return (true); 124 } 125 return (false); 126 } 127 #endif 128 return (true); 129 } 130 131 bool 132 pages_commit(void *addr, size_t size) 133 { 134 135 return (pages_commit_impl(addr, size, true)); 136 } 137 138 bool 139 pages_decommit(void *addr, size_t size) 140 { 141 142 return (pages_commit_impl(addr, size, false)); 143 } 144 145 bool 146 pages_purge(void *addr, size_t size) 147 { 148 bool unzeroed; 149 150 #ifdef _WIN32 151 VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE); 152 unzeroed = true; 153 #elif defined(JEMALLOC_HAVE_MADVISE) 154 # ifdef JEMALLOC_PURGE_MADVISE_DONTNEED 155 # define JEMALLOC_MADV_PURGE MADV_DONTNEED 156 # define JEMALLOC_MADV_ZEROS true 157 # elif defined(JEMALLOC_PURGE_MADVISE_FREE) 158 # define JEMALLOC_MADV_PURGE MADV_FREE 159 # define JEMALLOC_MADV_ZEROS false 160 # else 161 # error "No madvise(2) flag defined for purging unused dirty pages." 162 # endif 163 int err = madvise(addr, size, JEMALLOC_MADV_PURGE); 164 unzeroed = (!JEMALLOC_MADV_ZEROS || err != 0); 165 # undef JEMALLOC_MADV_PURGE 166 # undef JEMALLOC_MADV_ZEROS 167 #else 168 /* Last resort no-op. */ 169 unzeroed = true; 170 #endif 171 return (unzeroed); 172 } 173 174