Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/services/lowMemoryDetector.hpp
41144 views
1
/*
2
* Copyright (c) 2003, 2021, 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_SERVICES_LOWMEMORYDETECTOR_HPP
26
#define SHARE_SERVICES_LOWMEMORYDETECTOR_HPP
27
28
#include "memory/allocation.hpp"
29
#include "oops/oopHandle.hpp"
30
#include "runtime/atomic.hpp"
31
#include "services/memoryPool.hpp"
32
#include "services/memoryService.hpp"
33
#include "services/memoryUsage.hpp"
34
35
// Low Memory Detection Support
36
// Two memory alarms in the JDK (we called them sensors).
37
// - Heap memory sensor
38
// - Non-heap memory sensor
39
// When the VM detects if the memory usage of a memory pool has reached
40
// or exceeded its threshold, it will trigger the sensor for the type
41
// of the memory pool (heap or nonheap or both).
42
//
43
// If threshold == -1, no low memory detection is supported and
44
// the threshold value is not allowed to be changed.
45
// If threshold == 0, no low memory detection is performed for
46
// that memory pool. The threshold can be set to any non-negative
47
// value.
48
//
49
// The default threshold of the Hotspot memory pools are:
50
// Eden space -1
51
// Survivor space 1 -1
52
// Survivor space 2 -1
53
// Old generation 0
54
// Perm generation 0
55
// CodeCache 0
56
//
57
// For heap memory, detection will be performed when GC finishes
58
// and also in the slow path allocation.
59
// For Code cache, detection will be performed in the allocation
60
// and deallocation.
61
//
62
// May need to deal with hysteresis effect.
63
//
64
// Memory detection code runs in the Notification thread or
65
// ServiceThread depending on UseNotificationThread flag.
66
67
class OopClosure;
68
class MemoryPool;
69
70
class ThresholdSupport : public CHeapObj<mtInternal> {
71
private:
72
bool _support_high_threshold;
73
bool _support_low_threshold;
74
size_t _high_threshold;
75
size_t _low_threshold;
76
public:
77
ThresholdSupport(bool support_high, bool support_low) {
78
_support_high_threshold = support_high;
79
_support_low_threshold = support_low;
80
_high_threshold = 0;
81
_low_threshold= 0;
82
}
83
84
size_t high_threshold() const { return _high_threshold; }
85
size_t low_threshold() const { return _low_threshold; }
86
bool is_high_threshold_supported() { return _support_high_threshold; }
87
bool is_low_threshold_supported() { return _support_low_threshold; }
88
89
bool is_high_threshold_crossed(MemoryUsage usage) {
90
if (_support_high_threshold && _high_threshold > 0) {
91
return (usage.used() >= _high_threshold);
92
}
93
return false;
94
}
95
bool is_low_threshold_crossed(MemoryUsage usage) {
96
if (_support_low_threshold && _low_threshold > 0) {
97
return (usage.used() < _low_threshold);
98
}
99
return false;
100
}
101
102
size_t set_high_threshold(size_t new_threshold) {
103
assert(_support_high_threshold, "can only be set if supported");
104
assert(new_threshold >= _low_threshold, "new_threshold must be >= _low_threshold");
105
size_t prev = _high_threshold;
106
_high_threshold = new_threshold;
107
return prev;
108
}
109
110
size_t set_low_threshold(size_t new_threshold) {
111
assert(_support_low_threshold, "can only be set if supported");
112
assert(new_threshold <= _high_threshold, "new_threshold must be <= _high_threshold");
113
size_t prev = _low_threshold;
114
_low_threshold = new_threshold;
115
return prev;
116
}
117
};
118
119
class SensorInfo : public CHeapObj<mtInternal> {
120
private:
121
OopHandle _sensor_obj;
122
bool _sensor_on;
123
size_t _sensor_count;
124
125
// before the actual sensor on flag and sensor count are set
126
// we maintain the number of pending triggers and clears.
127
// _pending_trigger_count means the number of pending triggers
128
// and the sensor count should be incremented by the same number.
129
130
int _pending_trigger_count;
131
132
// _pending_clear_count takes precedence if it's > 0 which
133
// indicates the resulting sensor will be off
134
// Sensor trigger requests will reset this clear count to
135
// indicate the resulting flag should be on.
136
137
int _pending_clear_count;
138
139
MemoryUsage _usage;
140
141
void clear(int count, TRAPS);
142
void trigger(int count, TRAPS);
143
public:
144
SensorInfo();
145
void set_sensor(instanceOop sensor);
146
147
bool has_pending_requests() {
148
return (_pending_trigger_count > 0 || _pending_clear_count > 0);
149
}
150
151
int pending_trigger_count() { return _pending_trigger_count; }
152
int pending_clear_count() { return _pending_clear_count; }
153
154
// When this method is used, the memory usage is monitored
155
// as a gauge attribute. High and low thresholds are designed
156
// to provide a hysteresis mechanism to avoid repeated triggering
157
// of notifications when the attribute value makes small oscillations
158
// around the high or low threshold value.
159
//
160
// The sensor will be triggered if:
161
// (1) the usage is crossing above the high threshold and
162
// the sensor is currently off and no pending
163
// trigger requests; or
164
// (2) the usage is crossing above the high threshold and
165
// the sensor will be off (i.e. sensor is currently on
166
// and has pending clear requests).
167
//
168
// Subsequent crossings of the high threshold value do not cause
169
// any triggers unless the usage becomes less than the low threshold.
170
//
171
// The sensor will be cleared if:
172
// (1) the usage is crossing below the low threshold and
173
// the sensor is currently on and no pending
174
// clear requests; or
175
// (2) the usage is crossing below the low threshold and
176
// the sensor will be on (i.e. sensor is currently off
177
// and has pending trigger requests).
178
//
179
// Subsequent crossings of the low threshold value do not cause
180
// any clears unless the usage becomes greater than or equal
181
// to the high threshold.
182
//
183
// If the current level is between high and low threshold, no change.
184
//
185
void set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold);
186
187
// When this method is used, the memory usage is monitored as a
188
// simple counter attribute. The sensor will be triggered
189
// whenever the usage is crossing the threshold to keep track
190
// of the number of times the VM detects such a condition occurs.
191
//
192
// The sensor will be triggered if:
193
// - the usage is crossing above the high threshold regardless
194
// of the current sensor state.
195
//
196
// The sensor will be cleared if:
197
// (1) the usage is crossing below the low threshold and
198
// the sensor is currently on; or
199
// (2) the usage is crossing below the low threshold and
200
// the sensor will be on (i.e. sensor is currently off
201
// and has pending trigger requests).
202
//
203
void set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold);
204
205
void process_pending_requests(TRAPS);
206
207
#ifndef PRODUCT
208
// printing on default output stream;
209
void print();
210
#endif // PRODUCT
211
};
212
213
class LowMemoryDetector : public AllStatic {
214
friend class ServiceThread;
215
friend class NotificationThread;
216
private:
217
// true if any collected heap has low memory detection enabled
218
static volatile bool _enabled_for_collected_pools;
219
220
static bool has_pending_requests();
221
static void process_sensor_changes(TRAPS);
222
223
public:
224
static void detect_low_memory();
225
static void detect_low_memory(MemoryPool* pool);
226
static void detect_after_gc_memory(MemoryPool* pool);
227
228
static bool is_enabled(MemoryPool* pool) {
229
// low memory detection is enabled for collected memory pools
230
// iff one of the collected memory pool has a sensor and the
231
// threshold set non-zero
232
if (pool->usage_sensor() == NULL) {
233
return false;
234
} else {
235
ThresholdSupport* threshold_support = pool->usage_threshold();
236
return (threshold_support->is_high_threshold_supported() ?
237
(threshold_support->high_threshold() > 0) : false);
238
}
239
}
240
241
// recompute enabled flag
242
static void recompute_enabled_for_collected_pools();
243
244
// low memory detection for collected memory pools.
245
static inline void detect_low_memory_for_collected_pools() {
246
// no-op if low memory detection not enabled
247
if (!_enabled_for_collected_pools) {
248
return;
249
}
250
int num_memory_pools = MemoryService::num_memory_pools();
251
for (int i=0; i<num_memory_pools; i++) {
252
MemoryPool* pool = MemoryService::get_memory_pool(i);
253
254
// if low memory detection is enabled then check if the
255
// current used exceeds the high threshold
256
if (pool->is_collected_pool() && is_enabled(pool)) {
257
size_t used = pool->used_in_bytes();
258
size_t high = pool->usage_threshold()->high_threshold();
259
if (used > high) {
260
detect_low_memory(pool);
261
}
262
}
263
}
264
}
265
};
266
267
#endif // SHARE_SERVICES_LOWMEMORYDETECTOR_HPP
268
269