Fix semdiff syntactic output
[hiphop-php.git] / hphp / util / numa.cpp
blob8fa62ac8160cdfd184ec37970a259fa11e9d2baf
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 #ifdef HAVE_NUMA
19 #include "hphp/util/numa.h"
20 #include "hphp/util/portability.h"
21 #include <folly/Bits.h>
22 #include <sys/prctl.h>
24 extern "C" {
25 HHVM_ATTRIBUTE_WEAK extern void numa_init();
28 namespace HPHP {
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;
37 void initNuma() {
38 if (getenv("HHVM_DISABLE_NUMA")) {
39 return;
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.
45 if (&numa_init) {
46 numa_init();
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;
57 bool ret = true;
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.
65 ret = false;
66 break;
68 numa_node_set |= (uint32_t)1 << i;
69 numa_num_nodes++;
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;
81 int node;
82 do {
83 node = curr_node.fetch_add(1, std::memory_order_relaxed);
84 node &= numa_node_mask;
85 } while (!((numa_node_set >> node) & 1));
86 return node;
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);
106 #endif