pages.c revision 286866
1286866Sjasone#define JEMALLOC_PAGES_C_ 2286866Sjasone#include "jemalloc/internal/jemalloc_internal.h" 3286866Sjasone 4286866Sjasone/******************************************************************************/ 5286866Sjasone 6286866Sjasonevoid * 7286866Sjasonepages_map(void *addr, size_t size) 8286866Sjasone{ 9286866Sjasone void *ret; 10286866Sjasone 11286866Sjasone assert(size != 0); 12286866Sjasone 13286866Sjasone#ifdef _WIN32 14286866Sjasone /* 15286866Sjasone * If VirtualAlloc can't allocate at the given address when one is 16286866Sjasone * given, it fails and returns NULL. 17286866Sjasone */ 18286866Sjasone ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, 19286866Sjasone PAGE_READWRITE); 20286866Sjasone#else 21286866Sjasone /* 22286866Sjasone * We don't use MAP_FIXED here, because it can cause the *replacement* 23286866Sjasone * of existing mappings, and we only want to create new mappings. 24286866Sjasone */ 25286866Sjasone ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 26286866Sjasone -1, 0); 27286866Sjasone assert(ret != NULL); 28286866Sjasone 29286866Sjasone if (ret == MAP_FAILED) 30286866Sjasone ret = NULL; 31286866Sjasone else if (addr != NULL && ret != addr) { 32286866Sjasone /* 33286866Sjasone * We succeeded in mapping memory, but not in the right place. 34286866Sjasone */ 35286866Sjasone pages_unmap(ret, size); 36286866Sjasone ret = NULL; 37286866Sjasone } 38286866Sjasone#endif 39286866Sjasone assert(ret == NULL || (addr == NULL && ret != addr) 40286866Sjasone || (addr != NULL && ret == addr)); 41286866Sjasone return (ret); 42286866Sjasone} 43286866Sjasone 44286866Sjasonevoid 45286866Sjasonepages_unmap(void *addr, size_t size) 46286866Sjasone{ 47286866Sjasone 48286866Sjasone#ifdef _WIN32 49286866Sjasone if (VirtualFree(addr, 0, MEM_RELEASE) == 0) 50286866Sjasone#else 51286866Sjasone if (munmap(addr, size) == -1) 52286866Sjasone#endif 53286866Sjasone { 54286866Sjasone char buf[BUFERROR_BUF]; 55286866Sjasone 56286866Sjasone buferror(get_errno(), buf, sizeof(buf)); 57286866Sjasone malloc_printf("<jemalloc>: Error in " 58286866Sjasone#ifdef _WIN32 59286866Sjasone "VirtualFree" 60286866Sjasone#else 61286866Sjasone "munmap" 62286866Sjasone#endif 63286866Sjasone "(): %s\n", buf); 64286866Sjasone if (opt_abort) 65286866Sjasone abort(); 66286866Sjasone } 67286866Sjasone} 68286866Sjasone 69286866Sjasonevoid * 70286866Sjasonepages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size) 71286866Sjasone{ 72286866Sjasone void *ret = (void *)((uintptr_t)addr + leadsize); 73286866Sjasone 74286866Sjasone assert(alloc_size >= leadsize + size); 75286866Sjasone#ifdef _WIN32 76286866Sjasone { 77286866Sjasone void *new_addr; 78286866Sjasone 79286866Sjasone pages_unmap(addr, alloc_size); 80286866Sjasone new_addr = pages_map(ret, size); 81286866Sjasone if (new_addr == ret) 82286866Sjasone return (ret); 83286866Sjasone if (new_addr) 84286866Sjasone pages_unmap(new_addr, size); 85286866Sjasone return (NULL); 86286866Sjasone } 87286866Sjasone#else 88286866Sjasone { 89286866Sjasone size_t trailsize = alloc_size - leadsize - size; 90286866Sjasone 91286866Sjasone if (leadsize != 0) 92286866Sjasone pages_unmap(addr, leadsize); 93286866Sjasone if (trailsize != 0) 94286866Sjasone pages_unmap((void *)((uintptr_t)ret + size), trailsize); 95286866Sjasone return (ret); 96286866Sjasone } 97286866Sjasone#endif 98286866Sjasone} 99286866Sjasone 100286866Sjasonestatic bool 101286866Sjasonepages_commit_impl(void *addr, size_t size, bool commit) 102286866Sjasone{ 103286866Sjasone 104286866Sjasone#ifndef _WIN32 105286866Sjasone /* 106286866Sjasone * The following decommit/commit implementation is functional, but 107286866Sjasone * always disabled because it doesn't add value beyong improved 108286866Sjasone * debugging (at the cost of extra system calls) on systems that 109286866Sjasone * overcommit. 110286866Sjasone */ 111286866Sjasone if (false) { 112286866Sjasone int prot = commit ? (PROT_READ | PROT_WRITE) : PROT_NONE; 113286866Sjasone void *result = mmap(addr, size, prot, MAP_PRIVATE | MAP_ANON | 114286866Sjasone MAP_FIXED, -1, 0); 115286866Sjasone if (result == MAP_FAILED) 116286866Sjasone return (true); 117286866Sjasone if (result != addr) { 118286866Sjasone /* 119286866Sjasone * We succeeded in mapping memory, but not in the right 120286866Sjasone * place. 121286866Sjasone */ 122286866Sjasone pages_unmap(result, size); 123286866Sjasone return (true); 124286866Sjasone } 125286866Sjasone return (false); 126286866Sjasone } 127286866Sjasone#endif 128286866Sjasone return (true); 129286866Sjasone} 130286866Sjasone 131286866Sjasonebool 132286866Sjasonepages_commit(void *addr, size_t size) 133286866Sjasone{ 134286866Sjasone 135286866Sjasone return (pages_commit_impl(addr, size, true)); 136286866Sjasone} 137286866Sjasone 138286866Sjasonebool 139286866Sjasonepages_decommit(void *addr, size_t size) 140286866Sjasone{ 141286866Sjasone 142286866Sjasone return (pages_commit_impl(addr, size, false)); 143286866Sjasone} 144286866Sjasone 145286866Sjasonebool 146286866Sjasonepages_purge(void *addr, size_t size) 147286866Sjasone{ 148286866Sjasone bool unzeroed; 149286866Sjasone 150286866Sjasone#ifdef _WIN32 151286866Sjasone VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE); 152286866Sjasone unzeroed = true; 153286866Sjasone#elif defined(JEMALLOC_HAVE_MADVISE) 154286866Sjasone# ifdef JEMALLOC_PURGE_MADVISE_DONTNEED 155286866Sjasone# define JEMALLOC_MADV_PURGE MADV_DONTNEED 156286866Sjasone# define JEMALLOC_MADV_ZEROS true 157286866Sjasone# elif defined(JEMALLOC_PURGE_MADVISE_FREE) 158286866Sjasone# define JEMALLOC_MADV_PURGE MADV_FREE 159286866Sjasone# define JEMALLOC_MADV_ZEROS false 160286866Sjasone# else 161286866Sjasone# error "No madvise(2) flag defined for purging unused dirty pages." 162286866Sjasone# endif 163286866Sjasone int err = madvise(addr, size, JEMALLOC_MADV_PURGE); 164286866Sjasone unzeroed = (!JEMALLOC_MADV_ZEROS || err != 0); 165286866Sjasone# undef JEMALLOC_MADV_PURGE 166286866Sjasone# undef JEMALLOC_MADV_ZEROS 167286866Sjasone#else 168286866Sjasone /* Last resort no-op. */ 169286866Sjasone unzeroed = true; 170286866Sjasone#endif 171286866Sjasone return (unzeroed); 172286866Sjasone} 173286866Sjasone 174