Add sub-controls for Hack array compat runtime checks
[hiphop-php.git] / hphp / runtime / base / slab-manager.cpp
blob3ab33f63303e35947b9464d6e214e1d5bda8c3b2
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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 +----------------------------------------------------------------------+
17 #include "hphp/runtime/base/slab-manager.h"
19 #include "hphp/runtime/base/runtime-option.h"
20 #include "hphp/util/alloc.h"
21 #include "hphp/util/hugetlb.h"
22 #include "hphp/util/logger.h"
23 #include "hphp/util/numa.h"
25 #include <folly/portability/SysMman.h>
26 #include <vector>
28 namespace HPHP {
30 std::vector<SlabManager*> SlabManager::s_slabManagers;
32 void TaggedSlabList::addRange(void* ptr, std::size_t size) {
33 if (!ptr) return;
34 while (size >= kSlabSize) {
35 push_front(ptr, 0);
36 size -= kSlabSize;
37 ptr = reinterpret_cast<char*>(ptr) + kSlabSize;
41 void SlabManager::init() {
42 if (!s_slabManagers.empty()) return;
43 #ifdef HAVE_NUMA
44 unsigned max_node = numa_max_node();
45 #else
46 unsigned constexpr max_node = 0;
47 #endif
48 const unsigned numNodes = num_numa_nodes(); // number of NUMA node allowed
49 s_slabManagers.reserve(max_node + 1);
51 unsigned num1GPages = RuntimeOption::EvalNum1GPagesForSlabs;
52 unsigned num2MPages = RuntimeOption::EvalNum2MPagesForSlabs;
53 if (numNodes > 1) {
54 auto perNode1G = num1GPages / numNodes;
55 if (auto const excessive = num1GPages % numNodes) {
56 Logger::Warning("uneven distribution of %u 1G huge pages "
57 "(Eval.Num1GPagesForSlabs) to %u NUMA nodes, "
58 "excessive %u pages not used",
59 num1GPages, numNodes, excessive);
61 num1GPages = perNode1G;
62 auto perNode2M = num2MPages / numNodes;
63 if (auto const excessive = num2MPages % numNodes) {
64 Logger::Warning("uneven distribution of %u 2M huge pages "
65 "(Eval.Num1MPagesForSlabs) to %u NUMA nodes, "
66 "excessive %u pages not used",
67 num2MPages, numNodes, excessive);
69 num2MPages = perNode2M;
72 for (unsigned node = 0; node <= max_node; ++node) {
73 if (!numa_node_allowed(node)) {
74 s_slabManagers.push_back(nullptr);
75 continue;
77 constexpr auto kCacheLineSize = 64u;
78 static_assert(sizeof(SlabManager) <= kCacheLineSize, "");
79 auto ptr = mallocx_on_node(kCacheLineSize, node, kCacheLineSize); // leaked
80 auto slabManager = new (ptr) SlabManager;
81 s_slabManagers.push_back(slabManager);
82 unsigned actual1g = 0, actual2m = 0;
83 for (int i = 0; i < num1GPages; ++i) {
84 auto ptr = mmap_1g(nullptr, node);
85 if (!ptr) {
86 Logger::Warning("Insufficient 1G huge pages for slabs "
87 "on NUMA node %u, desired %u, actual %u",
88 node, num1GPages, actual1g);
89 break;
91 ++actual1g;
92 slabManager->addRange(ptr, size1g);
94 for (unsigned i = 0; i < num2MPages; ++i) {
95 auto ptr = mmap_2m(nullptr, PROT_READ | PROT_WRITE, node);
96 if (!ptr) {
97 Logger::Warning("Insufficient 2M huge pages for slabs "
98 "on NUMA node %u, desired %u, actual %u",
99 node, num2MPages, actual2m);
100 break;
102 ++actual2m;
103 slabManager->addRange(ptr, size2m);