1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // http://www.canonware.com/download/jemalloc/jemalloc-latest/doc/jemalloc.html 18 19 #pragma once 20 21 #include <folly/CPortability.h> 22 #include <folly/portability/Config.h> 23 #include <folly/portability/Malloc.h> 24 25 #if defined(FOLLY_USE_JEMALLOC) && !FOLLY_SANITIZE 26 27 #include <folly/portability/SysMman.h> 28 29 #if (JEMALLOC_VERSION_MAJOR > 3) && defined(MADV_DONTDUMP) 30 #define FOLLY_JEMALLOC_NODUMP_ALLOCATOR_SUPPORTED 1 31 #if (JEMALLOC_VERSION_MAJOR == 4) 32 #define FOLLY_JEMALLOC_NODUMP_ALLOCATOR_CHUNK 33 #define JEMALLOC_CHUNK_OR_EXTENT chunk 34 #else 35 #define FOLLY_JEMALLOC_NODUMP_ALLOCATOR_EXTENT 36 #define JEMALLOC_CHUNK_OR_EXTENT extent 37 #endif 38 #endif 39 40 #endif // FOLLY_USE_JEMALLOC 41 42 #include <cstddef> 43 44 namespace folly { 45 46 /** 47 * An allocator which uses Jemalloc to create an dedicated arena to allocate 48 * memory from. The only special property set on the allocated memory is that 49 * the memory is not dump-able. 50 * 51 * This is done by setting MADV_DONTDUMP using the `madvise` system call. A 52 * custom hook installed which is called when allocating a new chunk / extent of 53 * memory. All it does is call the original jemalloc hook to allocate the 54 * memory and then set the advise on it before returning the pointer to the 55 * allocated memory. Jemalloc does not use allocated chunks / extents across 56 * different arenas, without `munmap`-ing them first, and the advises are not 57 * sticky i.e. they are unset if `munmap` is done. Also this arena can't be used 58 * by any other part of the code by just calling `malloc`. 59 * 60 * If target system doesn't support MADV_DONTDUMP or jemalloc doesn't support 61 * custom arena hook, JemallocNodumpAllocator would fall back to using malloc / 62 * free. Such behavior can be identified by using 63 * !defined(FOLLY_JEMALLOC_NODUMP_ALLOCATOR_SUPPORTED). 64 * 65 * Similarly, if binary isn't linked with jemalloc, the logic would fall back to 66 * malloc / free. 67 */ 68 class JemallocNodumpAllocator { 69 public: 70 enum class State { 71 ENABLED, 72 DISABLED, 73 }; 74 75 // To be used as IOBuf::FreeFunction, userData should be set to 76 // reinterpret_cast<void*>(getFlags()). 77 static void deallocate(void* p, void* userData); 78 79 explicit JemallocNodumpAllocator(State state = State::ENABLED); 80 81 void* allocate(size_t size); 82 void* reallocate(void* p, size_t size); 83 void deallocate(void* p, size_t = 0); 84 getArenaIndex()85 unsigned getArenaIndex() const { return arena_index_; } getFlags()86 int getFlags() const { return flags_; } 87 88 private: 89 #ifdef FOLLY_JEMALLOC_NODUMP_ALLOCATOR_SUPPORTED 90 #ifdef FOLLY_JEMALLOC_NODUMP_ALLOCATOR_CHUNK 91 static chunk_alloc_t* original_alloc_; 92 static void* alloc( 93 void* chunk, 94 #else 95 static extent_hooks_t extent_hooks_; 96 static extent_alloc_t* original_alloc_; 97 static void* alloc( 98 extent_hooks_t* extent, 99 void* new_addr, 100 #endif 101 size_t size, 102 size_t alignment, 103 bool* zero, 104 bool* commit, 105 unsigned arena_ind); 106 #endif // FOLLY_JEMALLOC_NODUMP_ALLOCATOR_SUPPORTED 107 108 bool extend_and_setup_arena(); 109 110 unsigned arena_index_{0}; 111 int flags_{0}; 112 }; 113 114 /** 115 * JemallocNodumpAllocator singleton. 116 */ 117 JemallocNodumpAllocator& globalJemallocNodumpAllocator(); 118 119 } // namespace folly 120