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 #include "precompiled.hpp"
  26 #include "gc/g1/heapRegionType.hpp"
  27 #include "gc/g1/g1MemoryNodeManager.hpp"
  28 #include "gc/g1/g1NUMA.inline.hpp"
  29 
  30 G1MemoryNodeManager* G1MemoryNodeManager::_inst = NULL;
  31 
  32 class G1MemoryMultiNodeManager : public G1MemoryNodeManager {
  33   G1NUMA*      _numa;
  34 
  35 public:
  36   // The given numa instance will be deleted by the destructor.
  37   G1MemoryMultiNodeManager(G1NUMA* numa);
  38   ~G1MemoryMultiNodeManager();
  39 
  40   virtual void set_page_size(size_t page_size);
  41 
  42   virtual uint num_active_nodes() const;
  43 
  44   virtual const int* node_ids() const;
  45 
  46   virtual uint index_of_current_thread() const;
  47 
  48   virtual uint valid_node_index(uint node_index) const;
  49 
  50   virtual bool is_valid_node_index(uint node_index) const;
  51 
  52   virtual uint index_of_address(HeapWord* addr) const;
  53 };
  54 
  55 G1MemoryNodeManager* G1MemoryNodeManager::create() {
  56   guarantee(_inst == NULL, "Should be called once.");
  57 
  58   // Use multi node manager:
  59   //   1. If UseNUMA is enabled
  60   //   2. If there are more than 1 active numa nodes.
  61   // Doesn't support multi node manager for Solaris.
  62   if (UseNUMA SOLARIS_ONLY(&& false)) {
  63     // Create G1NUMA to check current active numa nodes.
  64     G1NUMA* numa = new G1NUMA();
  65 
  66     if (numa != NULL) {
  67       numa->initialize();
  68 
  69       if (numa->num_active_numa_ids() > 1) {
  70         G1NUMA::set_numa(numa);
  71         _inst = new G1MemoryMultiNodeManager(numa);
  72         return _inst;
  73       }
  74 
  75       delete numa;
  76     }
  77   }
  78 
  79   _inst = new G1MemoryNodeManager();
  80 
  81   return _inst;
  82 }
  83 
  84 G1MemoryMultiNodeManager::G1MemoryMultiNodeManager(G1NUMA* numa) : _numa(numa) { }
  85 
  86 G1MemoryMultiNodeManager::~G1MemoryMultiNodeManager() {
  87   delete _numa;
  88 }
  89 
  90 void G1MemoryMultiNodeManager::set_page_size(size_t page_size) {
  91   _numa->set_page_size(page_size);
  92 }
  93 
  94 uint G1MemoryMultiNodeManager::num_active_nodes() const {
  95   return _numa->num_active_numa_ids();
  96 }
  97 
  98 const int* G1MemoryMultiNodeManager::node_ids() const {
  99   return _numa->numa_ids();
 100 }
 101 
 102 uint G1MemoryMultiNodeManager::index_of_current_thread() const {
 103   int node_id = os::numa_get_group_id();
 104   return _numa->index_of_numa_id(node_id);
 105 }
 106 
 107 uint G1MemoryMultiNodeManager::valid_node_index(uint node_index) const {
 108   if (!_numa->is_valid_numa_index(node_index)) {
 109     node_index = _numa->next_numa_index();
 110   }
 111   return node_index;
 112 }
 113 
 114 bool G1MemoryMultiNodeManager::is_valid_node_index(uint node_index) const {
 115   return _numa->is_valid_numa_index(node_index);
 116 }
 117 
 118 uint G1MemoryMultiNodeManager::index_of_address(HeapWord* addr) const {
 119   return _numa->index_of_address(addr);
 120 }