2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
19 #include "hphp/util/address-range.h"
20 #include "hphp/util/alloc-defs.h"
21 #include "hphp/util/alloc.h"
25 #if USE_JEMALLOC_EXTENT_HOOKS
29 extern bool g_useTHPUponHugeTLBFailure
;
33 // Interface for all mappers. It also includes data about page limit (for huge
34 // page mappers) and NUMA support.
37 // State is shared between multiple mappers and multiple threads.
38 explicit RangeMapper(RangeState
& state
, uint32_t maxHugePages
= 0,
39 uint32_t numaMask
= 0, short nextNode
= 0)
41 , m_maxHugePages(maxHugePages
)
42 , m_interleaveMask(numaMask
)
43 , m_nextNode(nextNode
) {}
45 virtual ~RangeMapper() = default;
47 // Form a linked list of mappers for the same range.
48 static void append(RangeMapper
**& ptail
, RangeMapper
* next
) {
49 assert((*ptail
) == nullptr); // always keep track of the tail.
51 ptail
= &(next
->m_fallback
);
52 assert((*ptail
) == nullptr); // next already has fallback?
59 RangeState
& getRangeState() {
63 void setMaxPages(uint32_t maxHugePages
) {
64 m_maxHugePages
= maxHugePages
;
69 if (addMappingImpl()) return true;
70 // Some hugepage mappers start with zero page budget. Don't fail
71 // permanently if they didn't work in the beginning.
72 if (m_maxHugePages
) m_failed
= true;
77 void* alloc(size_t size
, size_t align
) {
79 auto const d
= direction();
81 if (m_state
.trivial(size
, align
, d
)) {
82 if (auto r
= m_state
.tryAlloc(size
, align
, d
)) return r
;
84 if (m_state
.infeasible(size
, align
, d
)) return nullptr;
85 } while (addMapping());
87 if (m_fallback
) return m_fallback
->alloc(size
, align
);
92 virtual bool addMappingImpl() = 0;
93 virtual Direction
direction() const = 0;
97 uint32_t m_maxHugePages
{0};
98 uint32_t m_currHugePages
{0};
99 uint32_t m_interleaveMask
; // 0 indicates no NUMA
101 bool m_failed
{false};
102 RangeMapper
* m_fallback
{nullptr};
106 struct Bump1GMapper
: public RangeMapper
{
108 template<typename
... Args
>
109 explicit Bump1GMapper(Args
&&... args
)
110 : RangeMapper(std::forward
<Args
>(args
)...) {}
113 Direction
direction() const override
{ return Direction::LowToHigh
; }
114 bool addMappingImpl() override
;
118 struct Bump2MMapper
: public RangeMapper
{
120 template<typename
... Args
>
121 explicit Bump2MMapper(Args
&&... args
)
122 : RangeMapper(std::forward
<Args
>(args
)...) {}
125 Direction
direction() const override
{ return Direction::LowToHigh
; }
126 bool addMappingImpl() override
;
130 template<Direction D
= Direction::LowToHigh
>
131 struct BumpNormalMapper
: public RangeMapper
{
133 template<typename
... Args
>
134 explicit BumpNormalMapper(Args
&&... args
)
135 : RangeMapper(std::forward
<Args
>(args
)...) {}
138 Direction
direction() const override
{ return D
; }
139 bool addMappingImpl() override
;
142 // Create mappings backed by a file
143 struct BumpFileMapper
: public RangeMapper
{
145 template<typename
... Args
>
146 explicit BumpFileMapper(Args
&&... args
)
147 : RangeMapper(std::forward
<Args
>(args
)...) {
148 m_failed
= true; // disabled initially
153 bool setDirectory(const char* dir
);
156 Direction
direction() const override
{ return Direction::LowToHigh
; }
157 bool addMappingImpl() override
;
160 // PATH_MAX feels like a waste of memory, so use something smaller and make it
161 // configurable at build time.
163 #define TMPDIRMAXLEN 80
165 char m_dirName
[TMPDIRMAXLEN
]{};
169 // A mapper that is used when other mappers all fail. To avoid crashing, this
170 // could allocate from some emergency buffer, and initiate a graceful shutdown.
171 // The range passed in should be pre-mapped.
172 struct BumpEmergencyMapper
: public RangeMapper
{
174 using ExitFun
= std::function
<void()>;
175 template<typename
... Args
>
176 explicit BumpEmergencyMapper(ExitFun
&& exitFn
, Args
&&... args
)
177 : RangeMapper(std::forward
<Args
>(args
)...)
180 Direction
direction() const override
{ return Direction::LowToHigh
; }
181 bool addMappingImpl() override
;
183 // The exit function to call when we start using the emergency mapping.