1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_VM_GC_G1_NUMA_HPP 26 #define SHARE_VM_GC_G1_NUMA_HPP 27 28 #include "gc/g1/g1NUMAStats.hpp" 29 #include "gc/g1/heapRegion.hpp" 30 #include "memory/allocation.hpp" 31 #include "runtime/os.hpp" 32 33 class LogStream; 34 35 class G1NUMA: public CHeapObj<mtGC> { 36 // Mapping of available node ids to 0-based index which can be used for 37 // fast resource management. I.e. for every node id provides a unique value in 38 // the range from [0, {# of nodes-1}]. 39 // For invalid node id, return UnknownNodeIndex. 40 uint* _node_id_to_index_map; 41 // Length of _num_active_node_ids_id to index map. 42 int _len_node_id_to_index_map; 43 44 // Current active node ids. 45 int* _node_ids; 46 // Total number of node ids. 47 uint _num_active_node_ids; 48 49 // HeapRegion size 50 size_t _region_size; 51 // Necessary when touching memory. 52 size_t _page_size; 53 54 // Stores statistic data. 55 G1NUMAStats* _stats; 56 57 size_t region_size() const; 58 size_t page_size() const; 59 60 // Returns node index of the given node id. 61 // Precondition: node_id is an active node id. 62 inline uint index_of_node_id(int node_id) const; 63 64 // Creates node id and node index mapping table of _node_id_to_index_map. 65 void init_node_id_to_index_map(const int* node_ids, uint num_node_ids); 66 67 static G1NUMA* _inst; 68 69 G1NUMA(); 70 void initialize(bool use_numa); 71 void initialize_without_numa(); 72 73 public: 74 static const uint UnknownNodeIndex = UINT_MAX; 75 static const uint AnyNodeIndex = UnknownNodeIndex - 1; 76 77 static G1NUMA* numa() { return _inst; } 78 79 static G1NUMA* create(); 80 81 ~G1NUMA(); 82 83 // Sets heap region size and page size after those values 84 // are determined at G1CollectedHeap::initialize(). 85 void set_region_info(size_t region_size, size_t page_size); 86 87 // Returns active memory node count. 88 uint num_active_nodes() const; 89 90 bool is_enabled() const; 91 92 int numa_id(int index) const; 93 94 // Returns memory node ids 95 const int* node_ids() const; 96 97 // Returns node index of current calling thread. 98 uint index_of_current_thread() const; 99 100 // Returns the preferred index for the given HeapRegion index. 101 // This assumes that HeapRegions are evenly spit, so we can decide preferred index 102 // with the given HeapRegion index. 103 // Result is less than num_active_nodes(). 104 uint preferred_node_index_for_index(uint region_index) const; 105 106 // Retrieves node index of the given address. 107 // Result is less than num_active_nodes() or is UnknownNodeIndex. 108 // Should not be used if the given address is not yet faulted in, i.e. free HeapRegion or 109 // AlwaysPreTouch disabled case, because previous request of numa_make_local() 110 // will not be honored. The return node index will be node index of the calling process. 111 // Precondition: address is in reserved range for heap. 112 uint index_of_address(HeapWord* address) const; 113 114 // If AlwaysPreTouch is enabled, return actual node index via system call. 115 // If disabled, return preferred node index of the given heap region. 116 uint index_for_region(HeapRegion* hr) const; 117 118 // Requests the given memory area to be located at the given node index. 119 void request_memory_on_node(void* aligned_address, size_t size_in_bytes, uint region_index); 120 121 // Returns maximum search depth which is used to limit heap region search iterations. 122 // The number of active nodes, page size and heap region size are considered. 123 uint max_search_depth() const; 124 125 // Update the given phase of requested and allocated node index. 126 void update_statistics(G1NUMAStats::NodeDataItems phase, uint requested_node_index, uint allocated_node_index); 127 128 // Copy all allocated statistics of the given phase and requested node. 129 // Precondition: allocated_stat should have same length of active nodes. 130 void copy_statistics(G1NUMAStats::NodeDataItems phase, uint requested_node_index, size_t* allocated_stat); 131 132 // Print all statistics. 133 void print() const; 134 }; 135 136 class NodeIndexCheckClosure : public HeapRegionClosure { 137 G1NUMA* _numa; 138 // Records matched count of each node. 139 uint* _matched; 140 // Records total count of each node. 141 uint* _total; 142 LogStream* _ls; 143 144 public: 145 NodeIndexCheckClosure(G1NUMA* numa, LogStream* ls); 146 ~NodeIndexCheckClosure(); 147 148 bool do_heap_region(HeapRegion* hr); 149 }; 150 151 #endif // SHARE_VM_GC_G1_NUMA_HPP