Skip to content

Commit 0bd38d4

Browse files
committed
Consistency in initialization logic
1 parent 17b5a92 commit 0bd38d4

File tree

9 files changed

+110
-89
lines changed

9 files changed

+110
-89
lines changed

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -227,14 +227,17 @@ void ZMemoryManager::register_callbacks(const Callbacks& callbacks) {
227227
_callbacks = callbacks;
228228
}
229229

230-
size_t ZMemoryManager::range_size() const {
230+
ZMemoryRange ZMemoryManager::total_range() const {
231231
ZLocker<ZLock> locker(&_lock);
232232

233233
if (_freelist.is_empty()) {
234-
return 0;
234+
return ZMemoryRange();
235235
}
236236

237-
return _freelist.last()->end() - _freelist.first()->start();
237+
const zoffset start = _freelist.first()->start();
238+
const size_t size = _freelist.last()->end() - start;
239+
240+
return ZMemoryRange(start, size);
238241
}
239242

240243
zoffset ZMemoryManager::peek_low_address() const {
@@ -282,24 +285,24 @@ ZMemoryRange ZMemoryManager::alloc_high_address(size_t size) {
282285
return ZMemoryRange();
283286
}
284287

285-
void ZMemoryManager::transfer_high_address(ZMemoryManager& other, size_t size) {
288+
void ZMemoryManager::transfer_low_address(ZMemoryManager& other, size_t size) {
286289
assert(other._freelist.is_empty(), "Should only be used for initializatiion");
287290

288291
ZLocker<ZLock> locker(&_lock);
289292
size_t to_move = size;
290293

291-
ZListReverseIterator<ZMemory> iter(&_freelist);
294+
ZListIterator<ZMemory> iter(&_freelist);
292295
for (ZMemory* area; iter.next(&area);) {
293296
if (area->size() <= to_move) {
294297
// Smaller than or equal to requested, remove from this freelist and
295298
// insert in other's freelist
296299
to_move -= area->size();
297300
_freelist.remove(area);
298-
other._freelist.insert_first(area);
301+
other._freelist.insert_last(area);
299302
} else {
300303
// Larger than requested, shrink area
301304
const zoffset_end end = area->end();
302-
shrink_from_back(area, to_move);
305+
shrink_from_front(area, to_move);
303306
other.free(zoffset(end - to_move), to_move);
304307
to_move = 0;
305308
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,14 @@ class ZMemoryManager {
103103

104104
void register_callbacks(const Callbacks& callbacks);
105105

106-
size_t range_size() const;
106+
ZMemoryRange total_range() const;
107107

108108
zoffset peek_low_address() const;
109109
ZMemoryRange alloc_low_address(size_t size);
110110
ZMemoryRange alloc_low_address_at_most(size_t size);
111111
ZMemoryRange alloc_high_address(size_t size);
112112

113-
void transfer_high_address(ZMemoryManager& other, size_t size);
113+
void transfer_low_address(ZMemoryManager& other, size_t size);
114114
int shuffle_memory_low_addresses(zoffset start, size_t size, ZArray<ZMemoryRange>* out);
115115
void shuffle_memory_low_addresses_contiguous(size_t size, ZArray<ZMemoryRange>* out);
116116

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ class ZNUMA : public AllStatic {
4242

4343
static uint32_t memory_id(uintptr_t addr);
4444

45+
static size_t calculate_share(uint32_t numa_id, size_t total);
46+
47+
template <typename Function>
48+
static void divide_resource(size_t resource, Function function);
49+
4550
static const char* to_string();
4651
};
4752

src/hotspot/share/gc/z/zNUMA.inline.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,30 @@
2626

2727
#include "gc/z/zNUMA.hpp"
2828

29+
#include "gc/z/zGlobals.hpp"
30+
#include "utilities/align.hpp"
31+
2932
inline bool ZNUMA::is_enabled() {
3033
return _enabled;
3134
}
3235

36+
inline size_t ZNUMA::calculate_share(uint32_t numa_id, size_t total) {
37+
const uint32_t num_nodes = count();
38+
const size_t base_share = align_down(total / num_nodes, ZGranuleSize);
39+
40+
const size_t extra_share_nodes = (total - base_share * num_nodes) / ZGranuleSize;
41+
if (numa_id < extra_share_nodes) {
42+
return base_share + ZGranuleSize;
43+
}
44+
45+
return base_share;
46+
}
47+
48+
template <typename Function>
49+
inline void ZNUMA::divide_resource(size_t total, Function function) {
50+
for (uint32_t numa_id = 0; numa_id < count(); numa_id++) {
51+
function(numa_id, calculate_share(numa_id, total));
52+
}
53+
}
54+
3355
#endif // SHARE_GC_Z_ZNUMA_INLINE_HPP

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

Lines changed: 38 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include "gc/z/zLock.inline.hpp"
3434
#include "gc/z/zMappedCache.hpp"
3535
#include "gc/z/zMemory.inline.hpp"
36-
#include "gc/z/zNUMA.hpp"
36+
#include "gc/z/zNUMA.inline.hpp"
3737
#include "gc/z/zPage.inline.hpp"
3838
#include "gc/z/zPageAge.hpp"
3939
#include "gc/z/zPageAllocator.inline.hpp"
@@ -361,18 +361,9 @@ ZPageAllocator::ZPageAllocator(size_t min_capacity,
361361
return;
362362
}
363363

364-
const int numa_nodes = ZNUMA::count();
365-
const size_t capacity_per_state = align_up(max_capacity / numa_nodes, ZGranuleSize);
366-
size_t capacity_left = max_capacity;
367-
368-
for (int numa_id = 0; numa_id < numa_nodes; numa_id++) {
369-
const size_t capacity = MIN2(capacity_per_state, capacity_left);
370-
capacity_left -= capacity;
371-
372-
ZCacheState& state = _states.get(numa_id);
373-
state.initialize(capacity);
374-
_physical.install_capacity(numa_id, zoffset(capacity_per_state * numa_id), capacity);
375-
}
364+
ZNUMA::divide_resource(max_capacity, [&](uint32_t numa_id, size_t capacity) {
365+
_states.get(numa_id).initialize(capacity);
366+
});
376367

377368
log_info_p(gc, init)("Min Capacity: %zuM", min_capacity / M);
378369
log_info_p(gc, init)("Initial Capacity: %zuM", initial_capacity / M);
@@ -438,48 +429,51 @@ class ZPreTouchTask : public ZTask {
438429
}
439430
};
440431

441-
bool ZPageAllocator::prime_cache(ZWorkers* workers, size_t size) {
442-
const int numa_nodes = ZNUMA::count();
443-
const size_t size_per_state = align_up(size / numa_nodes, ZGranuleSize);
444-
size_t size_left = size;
445-
446-
for (int numa_id = 0; numa_id < numa_nodes; numa_id++) {
447-
const size_t to_prime = MIN2(size_left, size_per_state);
448-
size_left -= to_prime;
449-
450-
if (to_prime == 0) {
451-
// Nothing more to prime, exit
452-
return true;
453-
}
432+
bool ZPageAllocator::prime_state_cache(ZWorkers* workers, int numa_id, size_t to_prime) {
433+
if (to_prime == 0) {
434+
return true;
435+
}
454436

455-
ZCacheState& state = _states.get(numa_id);
456-
ZMemoryRange vmem = _virtual.alloc(to_prime, numa_id, true /* force_low_address */);
437+
ZMemoryRange vmem = _virtual.alloc(to_prime, numa_id, true /* force_low_address */);
438+
ZCacheState& state = _states.get(numa_id);
457439

458-
// Increase capacity, allocate and commit physical memory
459-
state.increase_capacity(to_prime);
460-
_physical.alloc(_physical_mappings.get_addr(vmem.start()), to_prime, numa_id);
461-
if (!commit_physical(&vmem, numa_id)) {
462-
// This is a failure state. We do not cleanup the maybe partially committed memory.
463-
return false;
464-
}
440+
// Increase capacity, allocate and commit physical memory
441+
state.increase_capacity(to_prime);
442+
_physical.alloc(_physical_mappings.get_addr(vmem.start()), to_prime, numa_id);
443+
if (!commit_physical(&vmem, numa_id)) {
444+
// This is a failure state. We do not cleanup the maybe partially committed memory.
445+
return false;
446+
}
465447

466-
map_virtual_to_physical(vmem, numa_id);
448+
map_virtual_to_physical(vmem, numa_id);
467449

450+
if (ZNUMA::is_enabled()) {
468451
// Memory should have ended up on the desired NUMA id, if that's not the case, print error.
469452
int actual = ZNUMA::memory_id(untype(ZOffset::address(vmem.start())));
470453
if (actual != numa_id) {
471454
log_debug(gc, heap)("NUMA Mismatch (priming): desired %d, actual %d", numa_id, actual);
472455
}
456+
}
473457

474-
if (AlwaysPreTouch) {
475-
// Pre-touch memory
476-
ZPreTouchTask task(vmem.start(), vmem.end());
477-
workers->run_all(&task);
478-
}
458+
if (AlwaysPreTouch) {
459+
// Pre-touch memory
460+
ZPreTouchTask task(vmem.start(), vmem.end());
461+
workers->run_all(&task);
462+
}
479463

480-
// We don't have to take a lock here as no other threads will access the
481-
// mapped cache until we're finished.
482-
state._cache.insert_mapping(vmem);
464+
// We don't have to take a lock here as no other threads will access the
465+
// mapped cache until we're finished.
466+
state._cache.insert_mapping(vmem);
467+
468+
return true;
469+
}
470+
471+
bool ZPageAllocator::prime_cache(ZWorkers* workers, size_t size) {
472+
for (uint32_t numa_id = 0; numa_id < ZNUMA::count(); numa_id++) {
473+
const size_t to_prime = ZNUMA::calculate_share(numa_id, size);
474+
if (!prime_state_cache(workers, numa_id, to_prime)) {
475+
return false;
476+
}
483477
}
484478

485479
return true;

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ class ZPageAllocator {
108108
void notify_out_of_memory();
109109
void restart_gc() const;
110110

111+
bool prime_state_cache(ZWorkers* workers, int numa_id, size_t size);
112+
111113
public:
112114
ZPageAllocator(size_t min_capacity,
113115
size_t initial_capacity,

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,15 @@
4242
#include "utilities/powerOfTwo.hpp"
4343

4444
ZPhysicalMemoryManager::ZPhysicalMemoryManager(size_t max_capacity)
45-
: _backing(max_capacity) {}
45+
: _backing(max_capacity) {
46+
47+
// Install capacity into manager(s)
48+
size_t installed_capacity = 0;
49+
ZNUMA::divide_resource(max_capacity, [&](uint32_t numa_id, size_t capacity) {
50+
_managers.get(numa_id).free(zoffset(installed_capacity), capacity);
51+
installed_capacity += capacity;
52+
});
53+
}
4654

4755
bool ZPhysicalMemoryManager::is_initialized() const {
4856
return _backing.is_initialized();

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

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
#include "utilities/debug.hpp"
3636

3737
ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity)
38-
: _managers(),
38+
: _reserved_memory(),
39+
_managers(),
40+
_vmem_ranges(),
3941
_initialized(false) {
4042

4143
assert(max_capacity <= ZAddressOffsetMax, "Too large max_capacity");
@@ -44,14 +46,26 @@ ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity)
4446
pd_initialize_before_reserve();
4547

4648
// Reserve address space
47-
if (!reserve(max_capacity)) {
49+
const size_t reserved_total = reserve(max_capacity);
50+
if (reserved_total < max_capacity) {
4851
ZInitialize::error_d("Failed to reserve enough address space for Java heap");
4952
return;
5053
}
5154

5255
// Initialize platform specific parts after reserving address space
5356
pd_initialize_after_reserve();
5457

58+
// Install reserved memory into manager(s)
59+
ZNUMA::divide_resource(reserved_total, [&](int numa_id, size_t reserved) {
60+
ZMemoryManager& manager = _managers.get(numa_id);
61+
62+
// Transfer reserved memory
63+
_reserved_memory.transfer_low_address(manager, reserved);
64+
65+
// Store the range for the manager
66+
_vmem_ranges.set(manager.total_range(), numa_id);
67+
});
68+
5569
// Successfully initialized
5670
_initialized = true;
5771
}
@@ -151,9 +165,7 @@ bool ZVirtualMemoryManager::reserve_contiguous(zoffset start, size_t size) {
151165
// Register address views with native memory tracker
152166
ZNMT::reserve(addr, size);
153167

154-
// We put all the reserved memory inside the first manager and potentially
155-
// divide it when we've reserved all of the memory the user has requested.
156-
_managers.get(0).free(start, size);
168+
_reserved_memory.free(start, size);
157169

158170
return true;
159171
}
@@ -174,7 +186,7 @@ bool ZVirtualMemoryManager::reserve_contiguous(size_t size) {
174186
return false;
175187
}
176188

177-
bool ZVirtualMemoryManager::reserve(size_t max_capacity) {
189+
size_t ZVirtualMemoryManager::reserve(size_t max_capacity) {
178190
const size_t limit = MIN2(ZAddressOffsetMax, ZAddressSpaceLimit::heap());
179191
const size_t size = MIN2(max_capacity * ZVirtualToPhysicalRatio, limit);
180192
bool contiguous_reservation = false;
@@ -197,39 +209,14 @@ bool ZVirtualMemoryManager::reserve(size_t max_capacity) {
197209
};
198210

199211
const size_t reserved = do_reserve();
200-
initialize_managers(reserved);
201212

202213
log_info_p(gc, init)("Address Space Type: %s/%s/%s",
203214
(contiguous_reservation ? "Contiguous" : "Discontiguous"),
204215
(limit == ZAddressOffsetMax ? "Unrestricted" : "Restricted"),
205216
(reserved == size ? "Complete" : "Degraded"));
206217
log_info_p(gc, init)("Address Space Size: %zuM", reserved / M);
207218

208-
return reserved >= max_capacity;
209-
}
210-
211-
void ZVirtualMemoryManager::initialize_managers(size_t size) {
212-
// All reserved memory is initially stored in the manager with id 0. We need
213-
// to divide it equally among all the managers.
214-
ZMemoryManager& initial_manager = _managers.get(0);
215-
const int numa_nodes = ZNUMA::count();
216-
const size_t local_reservation = align_up(size / numa_nodes, ZGranuleSize);
217-
size_t reservation_left = size;
218-
219-
for (int numa_id = numa_nodes - 1; numa_id >= 0; numa_id--) {
220-
const size_t reservation = MIN2(local_reservation, reservation_left);
221-
reservation_left -= reservation;
222-
223-
ZMemoryManager& manager = _managers.get(numa_id);
224-
if (numa_id != 0) {
225-
initial_manager.transfer_high_address(manager, reservation);
226-
}
227-
228-
// Update the range
229-
const zoffset range_start = manager.peek_low_address();
230-
const size_t range_size = manager.range_size();
231-
_vmem_ranges.set(ZMemoryRange(range_start, range_size), numa_id);
232-
}
219+
return reserved;
233220
}
234221

235222
bool ZVirtualMemoryManager::is_initialized() const {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ class ZVirtualMemoryManager {
3535
private:
3636
static size_t calculate_min_range(size_t size);
3737

38+
ZMemoryManager _reserved_memory;
3839
ZPerNUMA<ZMemoryManager> _managers;
39-
ZPerNUMA<ZMemoryRange> _vmem_ranges;
40+
ZPerNUMA<ZMemoryRange> _vmem_ranges;
4041
bool _initialized;
4142

4243
// Platform specific implementation
@@ -49,10 +50,9 @@ class ZVirtualMemoryManager {
4950
bool reserve_contiguous(size_t size);
5051
size_t reserve_discontiguous(zoffset start, size_t size, size_t min_range);
5152
size_t reserve_discontiguous(size_t size);
52-
bool reserve(size_t max_capacity);
53+
size_t reserve(size_t max_capacity);
5354

5455
void set_vmem_range_for_manager(int numa_id);
55-
void initialize_managers(size_t size);
5656

5757
DEBUG_ONLY(size_t force_reserve_discontiguous(size_t size);)
5858

0 commit comments

Comments
 (0)