blob: 56b2ee422ab88f289d67339fed97ac21edf1a9a5 [file] [log] [blame]
Jason Evans4201af02010-01-24 02:53:40 -08001#define JEMALLOC_CHUNK_MMAP_C_
Jason Evans376b1522010-02-11 14:45:59 -08002#include "jemalloc/internal/jemalloc_internal.h"
Jason Evans4201af02010-01-24 02:53:40 -08003
4/******************************************************************************/
Mike Hommey666c5bf2012-04-18 18:29:43 +02005
Jason Evans4201af02010-01-24 02:53:40 -08006static void *
Jason Evans8fadb1a2015-08-04 10:49:46 -07007chunk_alloc_mmap_slow(size_t size, size_t alignment, bool *zero, bool *commit)
Jason Evans4201af02010-01-24 02:53:40 -08008{
Dmitry-Me78ae1ac2015-09-08 15:09:20 +03009 void *ret;
10 size_t alloc_size;
Jason Evans4201af02010-01-24 02:53:40 -080011
Jason Evans5ff709c2012-04-11 18:13:45 -070012 alloc_size = size + alignment - PAGE;
Jason Evans4201af02010-01-24 02:53:40 -080013 /* Beware size_t wrap-around. */
Jason Evans5ff709c2012-04-11 18:13:45 -070014 if (alloc_size < size)
Jason Evans4201af02010-01-24 02:53:40 -080015 return (NULL);
Mike Hommeya19e87f2012-04-21 21:27:46 -070016 do {
Dmitry-Me78ae1ac2015-09-08 15:09:20 +030017 void *pages;
18 size_t leadsize;
Mike Hommeya19e87f2012-04-21 21:27:46 -070019 pages = pages_map(NULL, alloc_size);
20 if (pages == NULL)
21 return (NULL);
22 leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) -
23 (uintptr_t)pages;
24 ret = pages_trim(pages, alloc_size, leadsize, size);
25 } while (ret == NULL);
Jason Evans4201af02010-01-24 02:53:40 -080026
Jason Evans8f0e0eb2012-04-21 13:33:48 -070027 assert(ret != NULL);
28 *zero = true;
Jason Evans03bf5b62015-08-12 10:26:54 -070029 if (!*commit)
30 *commit = pages_decommit(ret, size);
Jason Evans4201af02010-01-24 02:53:40 -080031 return (ret);
32}
33
Jason Evans5ff709c2012-04-11 18:13:45 -070034void *
Christopher Ferrise4294032016-03-02 14:33:02 -080035chunk_alloc_mmap(void *new_addr, size_t size, size_t alignment, bool *zero,
36 bool *commit)
Jason Evans4201af02010-01-24 02:53:40 -080037{
38 void *ret;
Jason Evansa8f8d752012-04-21 19:17:21 -070039 size_t offset;
Jason Evans4201af02010-01-24 02:53:40 -080040
41 /*
42 * Ideally, there would be a way to specify alignment to mmap() (like
43 * NetBSD has), but in the absence of such a feature, we have to work
44 * hard to efficiently create aligned mappings. The reliable, but
45 * slow method is to create a mapping that is over-sized, then trim the
Jason Evansde6fbdb2012-05-09 13:05:04 -070046 * excess. However, that always results in one or two calls to
Jason Evans4201af02010-01-24 02:53:40 -080047 * pages_unmap().
48 *
Jason Evansde6fbdb2012-05-09 13:05:04 -070049 * Optimistically try mapping precisely the right amount before falling
50 * back to the slow method, with the expectation that the optimistic
51 * approach works most of the time.
Jason Evans4201af02010-01-24 02:53:40 -080052 */
53
Jason Evansde6fbdb2012-05-09 13:05:04 -070054 assert(alignment != 0);
55 assert((alignment & chunksize_mask) == 0);
56
Christopher Ferrise4294032016-03-02 14:33:02 -080057 ret = pages_map(new_addr, size);
58 if (ret == NULL || ret == new_addr)
59 return (ret);
60 assert(new_addr == NULL);
Jason Evansa8f8d752012-04-21 19:17:21 -070061 offset = ALIGNMENT_ADDR2OFFSET(ret, alignment);
62 if (offset != 0) {
Jason Evansde6fbdb2012-05-09 13:05:04 -070063 pages_unmap(ret, size);
Jason Evans8fadb1a2015-08-04 10:49:46 -070064 return (chunk_alloc_mmap_slow(size, alignment, zero, commit));
Jason Evansa8f8d752012-04-21 19:17:21 -070065 }
Jason Evans4201af02010-01-24 02:53:40 -080066
Jason Evans8f0e0eb2012-04-21 13:33:48 -070067 assert(ret != NULL);
68 *zero = true;
Jason Evans03bf5b62015-08-12 10:26:54 -070069 if (!*commit)
70 *commit = pages_decommit(ret, size);
Jason Evans4201af02010-01-24 02:53:40 -080071 return (ret);
72}
73
Jason Evans7ca0fdf2012-04-12 20:20:58 -070074bool
Jason Evanse2deab72014-05-15 22:22:27 -070075chunk_dalloc_mmap(void *chunk, size_t size)
Jason Evans4201af02010-01-24 02:53:40 -080076{
77
Jason Evans7ca0fdf2012-04-12 20:20:58 -070078 if (config_munmap)
79 pages_unmap(chunk, size);
80
Jason Evans551ebc42014-10-03 10:16:09 -070081 return (!config_munmap);
Jason Evans4201af02010-01-24 02:53:40 -080082}