Skip to content

Commit 3804082

Browse files
roberttoyonagatstuefe
authored andcommitted
8346123: [REDO] NMT should not use ThreadCritical
Reviewed-by: dholmes, coleenp, stuefe
1 parent 1f0efc0 commit 3804082

19 files changed

+96
-49
lines changed

src/hotspot/os/posix/perfMemory_posix.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ static char* mmap_create_shared(size_t size) {
10861086
static void unmap_shared(char* addr, size_t bytes) {
10871087
int res;
10881088
if (MemTracker::enabled()) {
1089-
ThreadCritical tc;
1089+
MemTracker::NmtVirtualMemoryLocker nvml;
10901090
res = ::munmap(addr, bytes);
10911091
if (res == 0) {
10921092
MemTracker::record_virtual_memory_release((address)addr, bytes);

src/hotspot/os/windows/os_windows.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3639,10 +3639,7 @@ bool os::pd_release_memory(char* addr, size_t bytes) {
36393639
// Handle mapping error. We assert in debug, unconditionally print a warning in release.
36403640
if (err != nullptr) {
36413641
log_warning(os)("bad release: [" PTR_FORMAT "-" PTR_FORMAT "): %s", p2i(start), p2i(end), err);
3642-
#ifdef ASSERT
3643-
os::print_memory_mappings((char*)start, bytes, tty);
36443642
assert(false, "bad release: [" PTR_FORMAT "-" PTR_FORMAT "): %s", p2i(start), p2i(end), err);
3645-
#endif
36463643
return false;
36473644
}
36483645
// Free this range

src/hotspot/os/windows/perfMemory_windows.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1803,7 +1803,7 @@ void PerfMemory::detach(char* addr, size_t bytes) {
18031803

18041804
if (MemTracker::enabled()) {
18051805
// it does not go through os api, the operation has to record from here
1806-
ThreadCritical tc;
1806+
MemTracker::NmtVirtualMemoryLocker nvml;
18071807
remove_file_mapping(addr);
18081808
MemTracker::record_virtual_memory_release((address)addr, bytes);
18091809
} else {

src/hotspot/share/nmt/memBaseline.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ void MemBaseline::baseline_summary() {
141141
MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
142142
VirtualMemorySummary::snapshot(&_virtual_memory_snapshot);
143143
{
144-
MemoryFileTracker::Instance::Locker lock;
144+
MemTracker::NmtVirtualMemoryLocker nvml;
145145
MemoryFileTracker::Instance::summary_snapshot(&_virtual_memory_snapshot);
146146
}
147147

src/hotspot/share/nmt/memReporter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "nmt/mallocTracker.hpp"
2929
#include "nmt/memTag.hpp"
3030
#include "nmt/memReporter.hpp"
31+
#include "nmt/memTracker.hpp"
3132
#include "nmt/memoryFileTracker.hpp"
3233
#include "nmt/threadStackTracker.hpp"
3334
#include "nmt/virtualMemoryTracker.hpp"
@@ -465,7 +466,7 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion*
465466
void MemDetailReporter::report_memory_file_allocations() {
466467
stringStream st;
467468
{
468-
MemoryFileTracker::Instance::Locker lock;
469+
MemTracker::NmtVirtualMemoryLocker nvml;
469470
MemoryFileTracker::Instance::print_all_reports_on(&st, scale());
470471
}
471472
output()->print_raw(st.freeze());

src/hotspot/share/nmt/memTracker.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown;
5252

5353
MemBaseline MemTracker::_baseline;
5454

55+
bool MemTracker::NmtVirtualMemoryLocker::_safe_to_use;
56+
5557
void MemTracker::initialize() {
5658
bool rc = true;
5759
assert(_tracking_level == NMT_unknown, "only call once");

src/hotspot/share/nmt/memTracker.hpp

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#include "nmt/threadStackTracker.hpp"
3232
#include "nmt/virtualMemoryTracker.hpp"
3333
#include "runtime/mutexLocker.hpp"
34-
#include "runtime/threadCritical.hpp"
3534
#include "utilities/debug.hpp"
3635
#include "utilities/nativeCallStack.hpp"
3736

@@ -62,6 +61,12 @@ class MemTracker : AllStatic {
6261
return _tracking_level != NMT_unknown;
6362
}
6463

64+
// This may be called on a detached thread during VM init, so we should check that first.
65+
static inline void assert_locked() {
66+
assert(!NmtVirtualMemoryLocker::is_safe_to_use() || NmtVirtualMemory_lock->owned_by_self(),
67+
"should have acquired NmtVirtualMemory_lock");
68+
}
69+
6570
static inline NMT_TrackingLevel tracking_level() {
6671
return _tracking_level;
6772
}
@@ -125,7 +130,7 @@ class MemTracker : AllStatic {
125130
assert_post_init();
126131
if (!enabled()) return;
127132
if (addr != nullptr) {
128-
ThreadCritical tc;
133+
NmtVirtualMemoryLocker nvml;
129134
VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, mem_tag);
130135
}
131136
}
@@ -151,7 +156,7 @@ class MemTracker : AllStatic {
151156
assert_post_init();
152157
if (!enabled()) return;
153158
if (addr != nullptr) {
154-
ThreadCritical tc;
159+
NmtVirtualMemoryLocker nvml;
155160
VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, mem_tag);
156161
VirtualMemoryTracker::add_committed_region((address)addr, size, stack);
157162
}
@@ -162,23 +167,23 @@ class MemTracker : AllStatic {
162167
assert_post_init();
163168
if (!enabled()) return;
164169
if (addr != nullptr) {
165-
ThreadCritical tc;
170+
NmtVirtualMemoryLocker nvml;
166171
VirtualMemoryTracker::add_committed_region((address)addr, size, stack);
167172
}
168173
}
169174

170175
static inline MemoryFileTracker::MemoryFile* register_file(const char* descriptive_name) {
171176
assert_post_init();
172177
if (!enabled()) return nullptr;
173-
MemoryFileTracker::Instance::Locker lock;
178+
NmtVirtualMemoryLocker nvml;
174179
return MemoryFileTracker::Instance::make_file(descriptive_name);
175180
}
176181

177182
static inline void remove_file(MemoryFileTracker::MemoryFile* file) {
178183
assert_post_init();
179184
if (!enabled()) return;
180185
assert(file != nullptr, "must be");
181-
MemoryFileTracker::Instance::Locker lock;
186+
NmtVirtualMemoryLocker nvml;
182187
MemoryFileTracker::Instance::free_file(file);
183188
}
184189

@@ -187,7 +192,7 @@ class MemTracker : AllStatic {
187192
assert_post_init();
188193
if (!enabled()) return;
189194
assert(file != nullptr, "must be");
190-
MemoryFileTracker::Instance::Locker lock;
195+
NmtVirtualMemoryLocker nvml;
191196
MemoryFileTracker::Instance::allocate_memory(file, offset, size, stack, mem_tag);
192197
}
193198

@@ -196,7 +201,7 @@ class MemTracker : AllStatic {
196201
assert_post_init();
197202
if (!enabled()) return;
198203
assert(file != nullptr, "must be");
199-
MemoryFileTracker::Instance::Locker lock;
204+
NmtVirtualMemoryLocker nvml;
200205
MemoryFileTracker::Instance::free_memory(file, offset, size);
201206
}
202207

@@ -210,7 +215,7 @@ class MemTracker : AllStatic {
210215
assert_post_init();
211216
if (!enabled()) return;
212217
if (addr != nullptr) {
213-
ThreadCritical tc;
218+
NmtVirtualMemoryLocker nvml;
214219
VirtualMemoryTracker::split_reserved_region((address)addr, size, split, mem_tag, split_tag);
215220
}
216221
}
@@ -219,7 +224,7 @@ class MemTracker : AllStatic {
219224
assert_post_init();
220225
if (!enabled()) return;
221226
if (addr != nullptr) {
222-
ThreadCritical tc;
227+
NmtVirtualMemoryLocker nvml;
223228
VirtualMemoryTracker::set_reserved_region_type((address)addr, mem_tag);
224229
}
225230
}
@@ -269,6 +274,39 @@ class MemTracker : AllStatic {
269274
// and return true; false if not found.
270275
static bool print_containing_region(const void* p, outputStream* out);
271276

277+
/*
278+
* NmtVirtualMemoryLocker is similar to MutexLocker but can be used during VM init before mutexes are ready or
279+
* current thread has been assigned. Performs no action during VM init.
280+
*
281+
* Unlike malloc, NMT requires locking for virtual memory operations. This is because it must synchronize the usage
282+
* of global data structures used for modelling the effect of virtual memory operations.
283+
* It is important that locking is used such that the actual OS memory operations (mmap) are done atomically with the
284+
* corresponding NMT accounting (updating the internal model). Currently, this is not the case in all situations
285+
* (see JDK-8341491), but this should be changed in the future.
286+
*
287+
* An issue with using Mutex is that NMT is used early during VM initialization before mutexes are initialized
288+
* and current thread is attached. Mutexes do not work under those conditions, so we must use a flag to avoid
289+
* attempting to lock until initialization is finished. Lack of synchronization here should not be a problem since it
290+
* is single threaded at that point in time anyway.
291+
*/
292+
class NmtVirtualMemoryLocker: StackObj {
293+
// Returns true if it is safe to start using this locker.
294+
static bool _safe_to_use;
295+
ConditionalMutexLocker _cml;
296+
297+
public:
298+
NmtVirtualMemoryLocker(): _cml(NmtVirtualMemory_lock, _safe_to_use, Mutex::_no_safepoint_check_flag){}
299+
300+
static inline bool is_safe_to_use() {
301+
return _safe_to_use;
302+
}
303+
304+
// Set in Threads::create_vm once threads and mutexes have been initialized.
305+
static inline void set_safe_to_use() {
306+
_safe_to_use = true;
307+
}
308+
};
309+
272310
private:
273311
static void report(bool summary_only, outputStream* output, size_t scale);
274312

@@ -277,8 +315,6 @@ class MemTracker : AllStatic {
277315
static NMT_TrackingLevel _tracking_level;
278316
// Stored baseline
279317
static MemBaseline _baseline;
280-
// Query lock
281-
static Mutex* _query_lock;
282318
};
283319

284320
#endif // SHARE_NMT_MEMTRACKER_HPP

src/hotspot/share/nmt/memoryFileTracker.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,11 @@
2929
#include "nmt/nmtCommon.hpp"
3030
#include "nmt/nmtNativeCallStackStorage.hpp"
3131
#include "nmt/vmatree.hpp"
32-
#include "runtime/mutex.hpp"
3332
#include "utilities/growableArray.hpp"
3433
#include "utilities/nativeCallStack.hpp"
3534
#include "utilities/ostream.hpp"
3635

3736
MemoryFileTracker* MemoryFileTracker::Instance::_tracker = nullptr;
38-
PlatformMutex* MemoryFileTracker::Instance::_mutex = nullptr;
3937

4038
MemoryFileTracker::MemoryFileTracker(bool is_detailed_mode)
4139
: _stack_storage(is_detailed_mode), _files() {}
@@ -132,7 +130,6 @@ bool MemoryFileTracker::Instance::initialize(NMT_TrackingLevel tracking_level) {
132130
_tracker = static_cast<MemoryFileTracker*>(os::malloc(sizeof(MemoryFileTracker), mtNMT));
133131
if (_tracker == nullptr) return false;
134132
new (_tracker) MemoryFileTracker(tracking_level == NMT_TrackingLevel::NMT_detail);
135-
_mutex = new PlatformMutex();
136133
return true;
137134
}
138135

@@ -189,11 +186,3 @@ void MemoryFileTracker::summary_snapshot(VirtualMemorySnapshot* snapshot) const
189186
void MemoryFileTracker::Instance::summary_snapshot(VirtualMemorySnapshot* snapshot) {
190187
_tracker->summary_snapshot(snapshot);
191188
}
192-
193-
MemoryFileTracker::Instance::Locker::Locker() {
194-
MemoryFileTracker::Instance::_mutex->lock();
195-
}
196-
197-
MemoryFileTracker::Instance::Locker::~Locker() {
198-
MemoryFileTracker::Instance::_mutex->unlock();
199-
}

src/hotspot/share/nmt/memoryFileTracker.hpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include "nmt/nmtNativeCallStackStorage.hpp"
3131
#include "nmt/virtualMemoryTracker.hpp"
3232
#include "nmt/vmatree.hpp"
33-
#include "runtime/mutex.hpp"
3433
#include "runtime/os.inline.hpp"
3534
#include "utilities/growableArray.hpp"
3635
#include "utilities/nativeCallStack.hpp"
@@ -93,14 +92,8 @@ class MemoryFileTracker {
9392

9493
class Instance : public AllStatic {
9594
static MemoryFileTracker* _tracker;
96-
static PlatformMutex* _mutex;
9795

9896
public:
99-
class Locker : public StackObj {
100-
public:
101-
Locker();
102-
~Locker();
103-
};
10497

10598
static bool initialize(NMT_TrackingLevel tracking_level);
10699

src/hotspot/share/nmt/nmtUsage.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "precompiled.hpp"
2626
#include "nmt/mallocTracker.hpp"
2727
#include "nmt/memoryFileTracker.hpp"
28+
#include "nmt/memTracker.hpp"
2829
#include "nmt/nmtCommon.hpp"
2930
#include "nmt/nmtUsage.hpp"
3031
#include "nmt/threadStackTracker.hpp"
@@ -94,7 +95,7 @@ void NMTUsage::update_vm_usage() {
9495

9596
{ // MemoryFileTracker addition
9697
using MFT = MemoryFileTracker::Instance;
97-
MFT::Locker lock;
98+
MemTracker::NmtVirtualMemoryLocker nvml;
9899
MFT::iterate_summary([&](MemTag tag, const VirtualMemory* vm) {
99100
int i = NMTUtil::tag_to_index(tag);
100101
_vm_by_type[i].committed += vm->committed();

0 commit comments

Comments
 (0)