blob: 73fc497afbbaddd6705baf44f67c1a9319bed522 [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 Evans05a9e4a2016-06-07 14:19:50 -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;
Jason Evansc2f970c2016-05-05 17:45:02 -070019 pages = pages_map(NULL, alloc_size, commit);
Mike Hommeya19e87f2012-04-21 21:27:46 -070020 if (pages == NULL)
21 return (NULL);
22 leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) -
23 (uintptr_t)pages;
Jason Evansc2f970c2016-05-05 17:45:02 -070024 ret = pages_trim(pages, alloc_size, leadsize, size, commit);
Mike Hommeya19e87f2012-04-21 21:27:46 -070025 } 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 Evans4201af02010-01-24 02:53:40 -080029 return (ret);
30}
31
Jason Evans5ff709c2012-04-11 18:13:45 -070032void *
Jason Evansc7a9a6c2016-02-24 17:18:44 -080033chunk_alloc_mmap(void *new_addr, size_t size, size_t alignment, bool *zero,
34 bool *commit)
Jason Evans4201af02010-01-24 02:53:40 -080035{
36 void *ret;
Jason Evansa8f8d752012-04-21 19:17:21 -070037 size_t offset;
Jason Evans4201af02010-01-24 02:53:40 -080038
39 /*
40 * Ideally, there would be a way to specify alignment to mmap() (like
41 * NetBSD has), but in the absence of such a feature, we have to work
42 * hard to efficiently create aligned mappings. The reliable, but
43 * slow method is to create a mapping that is over-sized, then trim the
Jason Evansde6fbdb2012-05-09 13:05:04 -070044 * excess. However, that always results in one or two calls to
Jason Evans4201af02010-01-24 02:53:40 -080045 * pages_unmap().
46 *
Jason Evansde6fbdb2012-05-09 13:05:04 -070047 * Optimistically try mapping precisely the right amount before falling
48 * back to the slow method, with the expectation that the optimistic
49 * approach works most of the time.
Jason Evans4201af02010-01-24 02:53:40 -080050 */
51
Jason Evansde6fbdb2012-05-09 13:05:04 -070052 assert(alignment != 0);
53 assert((alignment & chunksize_mask) == 0);
54
Jason Evansc2f970c2016-05-05 17:45:02 -070055 ret = pages_map(new_addr, size, commit);
Jason Evansc7a9a6c2016-02-24 17:18:44 -080056 if (ret == NULL || ret == new_addr)
57 return (ret);
58 assert(new_addr == NULL);
Jason Evansa8f8d752012-04-21 19:17:21 -070059 offset = ALIGNMENT_ADDR2OFFSET(ret, alignment);
60 if (offset != 0) {
Jason Evansde6fbdb2012-05-09 13:05:04 -070061 pages_unmap(ret, size);
Jason Evans8fadb1a2015-08-04 10:49:46 -070062 return (chunk_alloc_mmap_slow(size, alignment, zero, commit));
Jason Evansa8f8d752012-04-21 19:17:21 -070063 }
Jason Evans4201af02010-01-24 02:53:40 -080064
Jason Evans8f0e0eb2012-04-21 13:33:48 -070065 assert(ret != NULL);
66 *zero = true;
Jason Evans4201af02010-01-24 02:53:40 -080067 return (ret);
68}
69
Jason Evans7ca0fdf2012-04-12 20:20:58 -070070bool
Jason Evanse2deab72014-05-15 22:22:27 -070071chunk_dalloc_mmap(void *chunk, size_t size)
Jason Evans4201af02010-01-24 02:53:40 -080072{
73
Jason Evans7ca0fdf2012-04-12 20:20:58 -070074 if (config_munmap)
75 pages_unmap(chunk, size);
76
Jason Evans551ebc42014-10-03 10:16:09 -070077 return (!config_munmap);
Jason Evans4201af02010-01-24 02:53:40 -080078}