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/numa.h"
20 #include "hphp/util/portability.h"
21 #include <folly/Bits.h>
22 #include <sys/prctl.h>
25 HHVM_ATTRIBUTE_WEAK
extern void numa_init();
30 uint32_t numa_node_set
;
31 uint32_t numa_num_nodes
;
32 uint32_t numa_node_mask
;
33 std::vector
<bitmask
*> node_to_cpu_mask
;
34 bool use_numa
= false;
35 bool threads_bind_local
= false;
38 if (getenv("HHVM_DISABLE_NUMA")) {
41 // When linked dynamically numa_init() is called before JEMallocInitializer()
42 // numa_init is not exported by libnuma.so so it will be NULL
43 // however when linked statically numa_init() is not guaranteed to be called
44 // before JEMallocInitializer(), so call it here.
48 if (numa_available() < 0) return;
50 // set interleave for early code. we'll then force interleave for a few
51 // regions, and switch to local for the threads
52 numa_set_interleave_mask(numa_all_nodes_ptr
);
54 int max_node
= numa_max_node();
55 if (!max_node
|| max_node
>= 32) return;
58 bitmask
* run_nodes
= numa_get_run_node_mask();
59 bitmask
* mem_nodes
= numa_get_mems_allowed();
60 for (int i
= 0; i
<= max_node
; i
++) {
61 if (!numa_bitmask_isbitset(run_nodes
, i
) ||
62 !numa_bitmask_isbitset(mem_nodes
, i
)) {
63 // Only deal with the case of a contiguous set of nodes where we can
64 // run/allocate memory on each node.
68 numa_node_set
|= (uint32_t)1 << i
;
71 numa_bitmask_free(run_nodes
);
72 numa_bitmask_free(mem_nodes
);
74 if (!ret
|| numa_num_nodes
<= 1) return;
76 numa_node_mask
= folly::nextPowTwo(numa_num_nodes
) - 1;
79 int next_numa_node(std::atomic_int
& curr_node
) {
80 if (!use_numa
) return 0;
83 node
= curr_node
.fetch_add(1, std::memory_order_relaxed
);
84 node
&= numa_node_mask
;
85 } while (!((numa_node_set
>> node
) & 1));
89 void numa_interleave(void* start
, size_t size
) {
90 if (!use_numa
) return;
91 numa_interleave_memory(start
, size
, numa_all_nodes_ptr
);
94 void numa_local(void* start
, size_t size
) {
95 if (!use_numa
) return;
96 numa_setlocal_memory(start
, size
);
99 void numa_bind_to(void* start
, size_t size
, int node
) {
100 if (!use_numa
) return;
101 numa_tonode_memory(start
, size
, node
);