Skip to content

Commit e586330

Browse files
committed
Do not allow machine_memory_info data source instability
1 parent 17e40b0 commit e586330

3 files changed

Lines changed: 57 additions & 0 deletions

File tree

src/hotspot/share/gc/z/zAdaptiveHeap.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "logging/log.hpp"
3434
#include "runtime/atomicAccess.hpp"
3535
#include "runtime/globals_extension.hpp"
36+
#include "runtime/java.hpp"
3637
#include "runtime/os.hpp"
3738
#include "utilities/debug.hpp"
3839
#include "utilities/globalDefinitions.hpp"
@@ -45,6 +46,7 @@ bool ZAdaptiveHeap::_can_adapt;
4546
bool ZAdaptiveHeap::_initialized;
4647
bool ZAdaptiveHeap::_initialized_generation_data;
4748
ZAdaptiveHeap::ZIntensitySmoother ZAdaptiveHeap::_gc_intensities;
49+
ZBooleanStability ZAdaptiveHeap::_machine_memory_info_valid;
4850

4951
Atomic<double> ZAdaptiveHeap::_young_to_old_gc_time(0.0);
5052
double ZAdaptiveHeap::_accumulated_young_gc_time = 0.0;
@@ -57,6 +59,21 @@ static double calculate_progression(double availability, double from, double to)
5759
return 1.0 - (availability - to) / (from - to);
5860
}
5961

62+
bool ZBooleanStability::record_and_check_stability(bool observed) {
63+
const ValidityState observed_state = observed ? ValidityState::ObservedTrue : ValidityState::ObservedFalse;
64+
65+
ValidityState expected_state = _expected_state.load_relaxed();
66+
if (expected_state == ValidityState::Uninitialized) {
67+
expected_state = _expected_state.compare_exchange(ValidityState::Uninitialized, observed_state);
68+
if (expected_state == ValidityState::Uninitialized) {
69+
// This is the first observation, so nothing to compare against
70+
return true;
71+
}
72+
}
73+
74+
return expected_state == observed_state;
75+
}
76+
6077
void ZAdaptiveHeap::ZIntensitySmoother::initialize() {
6178
_lock = new ZLock();
6279
}
@@ -285,6 +302,13 @@ ZMemoryPressureMetrics ZAdaptiveHeap::memory_pressure_metrics() {
285302

286303
const ZMachineMemoryInfo machine_memory_info = ZAdaptiveHeap::machine_memory_info();
287304

305+
if (!_machine_memory_info_valid.record_and_check_stability(machine_memory_info._is_valid)) {
306+
log_warning(gc)("The data source for machine_memory_info is unstable (expected _is_valid to be %s, got %s). "
307+
"This behavior is unsupported for Automatic Heap Sizing. Please run without Automatic Heap Sizing using -XX:ZGCIntensity=0",
308+
BOOL_TO_STR(!machine_memory_info._is_valid), BOOL_TO_STR(machine_memory_info._is_valid));
309+
vm_exit(1);
310+
}
311+
288312
const physical_memory_size_type machine_max_memory = machine_memory_info._physical_memory;
289313

290314
const physical_memory_size_type machine_used_memory = machine_memory_info._is_valid

src/hotspot/share/gc/z/zAdaptiveHeap.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,23 @@ struct ZMachineMemoryInfo {
8686
bool _is_valid;
8787
};
8888

89+
struct ZBooleanStability {
90+
private:
91+
enum class ValidityState {
92+
Uninitialized,
93+
ObservedFalse,
94+
ObservedTrue,
95+
};
96+
97+
Atomic<ValidityState> _expected_state;
98+
99+
public:
100+
ZBooleanStability()
101+
: _expected_state(ValidityState::Uninitialized) {}
102+
103+
bool record_and_check_stability(bool observed);
104+
};
105+
89106
class ZAdaptiveHeap : public AllStatic {
90107
friend class ZAdaptiveHeapTest;
91108
private:
@@ -139,6 +156,7 @@ class ZAdaptiveHeap : public AllStatic {
139156
static ZGenerationOverhead _old_data;
140157
static Atomic<uint> _initial_young_worker_cap;
141158
static ZIntensitySmoother _gc_intensities;
159+
static ZBooleanStability _machine_memory_info_valid;
142160

143161
static ZCpuPressureMetrics cpu_pressure_metrics(ZGenerationId generation);
144162

test/hotspot/gtest/gc/z/test_zAdaptiveHeap.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,18 @@ TEST_F(ZAdaptiveHeapTest, test_mem_pressure) {
180180
}
181181
}
182182
}
183+
184+
TEST(ZAdaptiveHeap, test_boolean_stability) {
185+
// The stability state should latch onto the first observation it sees, and
186+
// then comapre any following observation against the first observation.
187+
188+
ZBooleanStability stability_false;
189+
EXPECT_TRUE(stability_false.record_and_check_stability(false));
190+
EXPECT_TRUE(stability_false.record_and_check_stability(false));
191+
EXPECT_FALSE(stability_false.record_and_check_stability(true));
192+
193+
ZBooleanStability stability_true;
194+
EXPECT_TRUE(stability_true.record_and_check_stability(true));
195+
EXPECT_TRUE(stability_true.record_and_check_stability(true));
196+
EXPECT_FALSE(stability_true.record_and_check_stability(false));
197+
}

0 commit comments

Comments
 (0)