/* * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #include "precompiled.hpp" #include "gc/g1/heapRegionType.hpp" #include "gc/g1/g1MemoryNodeManager.hpp" #include "gc/g1/g1NUMA.inline.hpp" G1MemoryNodeManager* G1MemoryNodeManager::_inst = NULL; class G1MemoryMultiNodeManager : public G1MemoryNodeManager { G1NUMA* _numa; public: // The given numa instance will be deleted by the destructor. G1MemoryMultiNodeManager(G1NUMA* numa); ~G1MemoryMultiNodeManager(); virtual void set_page_size(size_t page_size); virtual uint num_active_nodes() const; virtual const int* node_ids() const; virtual uint index_of_current_thread() const; virtual uint valid_node_index(uint node_index) const; virtual bool is_valid_node_index(uint node_index) const; virtual uint index_of_address(HeapWord* addr) const; }; G1MemoryNodeManager* G1MemoryNodeManager::create() { guarantee(_inst == NULL, "Should be called once."); // Use multi node manager: // 1. If UseNUMA is enabled // 2. If there are more than 1 active numa nodes. // Doesn't support multi node manager for Solaris. if (UseNUMA SOLARIS_ONLY(&& false)) { // Create G1NUMA to check current active numa nodes. G1NUMA* numa = new G1NUMA(); if (numa != NULL) { numa->initialize(); if (numa->num_active_numa_ids() > 1) { G1NUMA::set_numa(numa); _inst = new G1MemoryMultiNodeManager(numa); return _inst; } delete numa; } } _inst = new G1MemoryNodeManager(); return _inst; } G1MemoryMultiNodeManager::G1MemoryMultiNodeManager(G1NUMA* numa) : _numa(numa) { } G1MemoryMultiNodeManager::~G1MemoryMultiNodeManager() { delete _numa; } void G1MemoryMultiNodeManager::set_page_size(size_t page_size) { _numa->set_page_size(page_size); } uint G1MemoryMultiNodeManager::num_active_nodes() const { return _numa->num_active_numa_ids(); } const int* G1MemoryMultiNodeManager::node_ids() const { return _numa->numa_ids(); } uint G1MemoryMultiNodeManager::index_of_current_thread() const { int node_id = os::numa_get_group_id(); return _numa->index_of_numa_id(node_id); } uint G1MemoryMultiNodeManager::valid_node_index(uint node_index) const { if (!_numa->is_valid_numa_index(node_index)) { node_index = _numa->next_numa_index(); } return node_index; } bool G1MemoryMultiNodeManager::is_valid_node_index(uint node_index) const { return _numa->is_valid_numa_index(node_index); } uint G1MemoryMultiNodeManager::index_of_address(HeapWord* addr) const { return _numa->index_of_address(addr); }