6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
6723229: NUMA allocator: assert(lgrp_num > 0, "There should be at least one locality group")
Summary: The fix takes care of the assertion triggered during TLAB resizing after reconfiguration. Also it now handles a defect in the topology graph, in which a single leaf node doesn't have memory.
Reviewed-by: jmasa
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Jul 14 04:12:47 2008 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Jul 17 10:26:33 2008 -0700
@@ -2658,6 +2658,12 @@
top += r;
cur++;
}
+ if (bottom == 0) {
+ // Handle a situation, when the OS reports no memory available.
+ // Assume UMA architecture.
+ ids[0] = 0;
+ return 1;
+ }
return bottom;
}
--- a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp Mon Jul 14 04:12:47 2008 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp Thu Jul 17 10:26:33 2008 -0700
@@ -58,6 +58,12 @@
_average(0.0), _sample_count(0), _weight(weight), _last_sample(0.0) {
}
+ void clear() {
+ _average = 0;
+ _sample_count = 0;
+ _last_sample = 0;
+ }
+
// Accessors
float average() const { return _average; }
unsigned weight() const { return _weight; }
@@ -115,6 +121,12 @@
float deviation() const { return _deviation; }
unsigned padding() const { return _padding; }
+ void clear() {
+ AdaptiveWeightedAverage::clear();
+ _padded_avg = 0;
+ _deviation = 0;
+ }
+
// Override
void sample(float new_sample);
};
--- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Mon Jul 14 04:12:47 2008 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Thu Jul 17 10:26:33 2008 -0700
@@ -141,7 +141,20 @@
size_t MutableNUMASpace::tlab_capacity(Thread *thr) const {
guarantee(thr != NULL, "No thread");
int lgrp_id = thr->lgrp_id();
- assert(lgrp_id != -1, "No lgrp_id set");
+ if (lgrp_id == -1) {
+ // This case can occur after the topology of the system has
+ // changed. Thread can change their location, the new home
+ // group will be determined during the first allocation
+ // attempt. For now we can safely assume that all spaces
+ // have equal size because the whole space will be reinitialized.
+ if (lgrp_spaces()->length() > 0) {
+ return capacity_in_bytes() / lgrp_spaces()->length();
+ } else {
+ assert(false, "There should be at least one locality group");
+ return 0;
+ }
+ }
+ // That's the normal case, where we know the locality group of the thread.
int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
if (i == -1) {
return 0;
@@ -150,9 +163,17 @@
}
size_t MutableNUMASpace::unsafe_max_tlab_alloc(Thread *thr) const {
+ // Please see the comments for tlab_capacity().
guarantee(thr != NULL, "No thread");
int lgrp_id = thr->lgrp_id();
- assert(lgrp_id != -1, "No lgrp_id set");
+ if (lgrp_id == -1) {
+ if (lgrp_spaces()->length() > 0) {
+ return free_in_bytes() / lgrp_spaces()->length();
+ } else {
+ assert(false, "There should be at least one locality group");
+ return 0;
+ }
+ }
int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
if (i == -1) {
return 0;
@@ -250,10 +271,15 @@
void MutableNUMASpace::update() {
if (update_layout(false)) {
// If the topology has changed, make all chunks zero-sized.
+ // And clear the alloc-rate statistics.
+ // In future we may want to handle this more gracefully in order
+ // to avoid the reallocation of the pages as much as possible.
for (int i = 0; i < lgrp_spaces()->length(); i++) {
- MutableSpace *s = lgrp_spaces()->at(i)->space();
+ LGRPSpace *ls = lgrp_spaces()->at(i);
+ MutableSpace *s = ls->space();
s->set_end(s->bottom());
s->set_top(s->bottom());
+ ls->clear_alloc_rate();
}
// A NUMA space is never mangled
initialize(region(),
--- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Mon Jul 14 04:12:47 2008 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Thu Jul 17 10:26:33 2008 -0700
@@ -112,6 +112,7 @@
int lgrp_id() const { return _lgrp_id; }
MutableSpace* space() const { return _space; }
AdaptiveWeightedAverage* alloc_rate() const { return _alloc_rate; }
+ void clear_alloc_rate() { _alloc_rate->clear(); }
SpaceStats* space_stats() { return &_space_stats; }
void clear_space_stats() { _space_stats = SpaceStats(); }