8255254: Split os::reserve_memory and os::map_memory_to_file interfaces
Reviewed-by: stefank, stuefe
This commit is contained in:
parent
dc85a3fe81
commit
acd0e2560c
src/hotspot
os
share
@ -2236,7 +2236,7 @@ bool os::can_execute_large_page_memory() {
|
||||
return false;
|
||||
}
|
||||
|
||||
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, int file_desc) {
|
||||
char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
|
||||
assert(file_desc >= 0, "file_desc is not valid");
|
||||
char* result = NULL;
|
||||
|
||||
|
@ -1905,7 +1905,7 @@ bool os::can_execute_large_page_memory() {
|
||||
return false;
|
||||
}
|
||||
|
||||
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, int file_desc) {
|
||||
char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
|
||||
assert(file_desc >= 0, "file_desc is not valid");
|
||||
char* result = pd_attempt_reserve_memory_at(requested_addr, bytes);
|
||||
if (result != NULL) {
|
||||
|
@ -4214,7 +4214,7 @@ bool os::can_execute_large_page_memory() {
|
||||
return UseTransparentHugePages || UseHugeTLBFS;
|
||||
}
|
||||
|
||||
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, int file_desc) {
|
||||
char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
|
||||
assert(file_desc >= 0, "file_desc is not valid");
|
||||
char* result = pd_attempt_reserve_memory_at(requested_addr, bytes);
|
||||
if (result != NULL) {
|
||||
|
@ -297,37 +297,18 @@ char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, in
|
||||
return map_memory_to_file(base, size, fd);
|
||||
}
|
||||
|
||||
// Multiple threads can race in this code, and can remap over each other with MAP_FIXED,
|
||||
// so on posix, unmap the section at the start and at the end of the chunk that we mapped
|
||||
// rather than unmapping and remapping the whole chunk to get requested alignment.
|
||||
char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {
|
||||
static size_t calculate_aligned_extra_size(size_t size, size_t alignment) {
|
||||
assert((alignment & (os::vm_allocation_granularity() - 1)) == 0,
|
||||
"Alignment must be a multiple of allocation granularity (page size)");
|
||||
assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned");
|
||||
|
||||
size_t extra_size = size + alignment;
|
||||
assert(extra_size >= size, "overflow, size is too large to allow alignment");
|
||||
return extra_size;
|
||||
}
|
||||
|
||||
char* extra_base;
|
||||
if (file_desc != -1) {
|
||||
// For file mapping, we do not call os:reserve_memory_with_fd since:
|
||||
// - we later chop away parts of the mapping using os::release_memory and that could fail if the
|
||||
// original mmap call had been tied to an fd.
|
||||
// - The memory API os::reserve_memory uses is an implementation detail. It may (and usually is)
|
||||
// mmap but it also may System V shared memory which cannot be uncommitted as a whole, so
|
||||
// chopping off and unmapping excess bits back and front (see below) would not work.
|
||||
extra_base = reserve_mmapped_memory(extra_size, NULL);
|
||||
if (extra_base != NULL) {
|
||||
MemTracker::record_virtual_memory_reserve((address)extra_base, extra_size, CALLER_PC);
|
||||
}
|
||||
} else {
|
||||
extra_base = os::reserve_memory(extra_size);
|
||||
}
|
||||
|
||||
if (extra_base == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// After a bigger chunk was mapped, unmaps start and end parts to get the requested alignment.
|
||||
static char* chop_extra_memory(size_t size, size_t alignment, char* extra_base, size_t extra_size) {
|
||||
// Do manual alignment
|
||||
char* aligned_base = align_up(extra_base, alignment);
|
||||
|
||||
@ -349,13 +330,39 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {
|
||||
os::release_memory(extra_base + begin_offset + size, end_offset);
|
||||
}
|
||||
|
||||
if (file_desc != -1) {
|
||||
// After we have an aligned address, we can replace anonymous mapping with file mapping
|
||||
if (replace_existing_mapping_with_file_mapping(aligned_base, size, file_desc) == NULL) {
|
||||
vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
|
||||
}
|
||||
MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC);
|
||||
return aligned_base;
|
||||
}
|
||||
|
||||
// Multiple threads can race in this code, and can remap over each other with MAP_FIXED,
|
||||
// so on posix, unmap the section at the start and at the end of the chunk that we mapped
|
||||
// rather than unmapping and remapping the whole chunk to get requested alignment.
|
||||
char* os::reserve_memory_aligned(size_t size, size_t alignment) {
|
||||
size_t extra_size = calculate_aligned_extra_size(size, alignment);
|
||||
char* extra_base = os::reserve_memory(extra_size);
|
||||
if (extra_base == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return chop_extra_memory(size, alignment, extra_base, extra_size);
|
||||
}
|
||||
|
||||
char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int file_desc) {
|
||||
size_t extra_size = calculate_aligned_extra_size(size, alignment);
|
||||
// For file mapping, we do not call os:map_memory_to_file(size,fd) since:
|
||||
// - we later chop away parts of the mapping using os::release_memory and that could fail if the
|
||||
// original mmap call had been tied to an fd.
|
||||
// - The memory API os::reserve_memory uses is an implementation detail. It may (and usually is)
|
||||
// mmap but it also may System V shared memory which cannot be uncommitted as a whole, so
|
||||
// chopping off and unmapping excess bits back and front (see below) would not work.
|
||||
char* extra_base = reserve_mmapped_memory(extra_size, NULL);
|
||||
if (extra_base == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
char* aligned_base = chop_extra_memory(size, alignment, extra_base, extra_size);
|
||||
// After we have an aligned address, we can replace anonymous mapping with file mapping
|
||||
if (replace_existing_mapping_with_file_mapping(aligned_base, size, file_desc) == NULL) {
|
||||
vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
|
||||
}
|
||||
MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC);
|
||||
return aligned_base;
|
||||
}
|
||||
|
||||
|
@ -3137,7 +3137,7 @@ void os::split_reserved_memory(char *base, size_t size, size_t split) {
|
||||
// Multiple threads can race in this code but it's not possible to unmap small sections of
|
||||
// virtual space to get requested alignment, like posix-like os's.
|
||||
// Windows prevents multiple thread from remapping over each other so this loop is thread-safe.
|
||||
char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {
|
||||
static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {
|
||||
assert((alignment & (os::vm_allocation_granularity() - 1)) == 0,
|
||||
"Alignment must be a multiple of allocation granularity (page size)");
|
||||
assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned");
|
||||
@ -3148,7 +3148,9 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {
|
||||
char* aligned_base = NULL;
|
||||
|
||||
do {
|
||||
char* extra_base = os::reserve_memory_with_fd(extra_size, file_desc);
|
||||
char* extra_base = file_desc != -1 ?
|
||||
os::map_memory_to_file(extra_size, file_desc) :
|
||||
os::reserve_memory(extra_size);
|
||||
if (extra_base == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -3161,13 +3163,23 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {
|
||||
os::release_memory(extra_base, extra_size);
|
||||
}
|
||||
|
||||
aligned_base = os::attempt_reserve_memory_at(aligned_base, size, file_desc);
|
||||
aligned_base = file_desc != -1 ?
|
||||
os::attempt_map_memory_to_file_at(aligned_base, size, file_desc) :
|
||||
os::attempt_reserve_memory_at(aligned_base, size);
|
||||
|
||||
} while (aligned_base == NULL);
|
||||
|
||||
return aligned_base;
|
||||
}
|
||||
|
||||
char* os::reserve_memory_aligned(size_t size, size_t alignment) {
|
||||
return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */);
|
||||
}
|
||||
|
||||
char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd) {
|
||||
return map_or_reserve_memory_aligned(size, alignment, fd);
|
||||
}
|
||||
|
||||
char* os::pd_reserve_memory(size_t bytes) {
|
||||
return pd_attempt_reserve_memory_at(NULL /* addr */, bytes);
|
||||
}
|
||||
@ -3205,7 +3217,7 @@ char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes) {
|
||||
return res;
|
||||
}
|
||||
|
||||
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, int file_desc) {
|
||||
char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
|
||||
assert(file_desc >= 0, "file_desc is not valid");
|
||||
return map_memory_to_file(requested_addr, bytes, file_desc);
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ static bool map_nvdimm_space(ReservedSpace rs) {
|
||||
return false;
|
||||
}
|
||||
// commit this memory in nv-dimm
|
||||
char* ret = os::attempt_reserve_memory_at(rs.base(), rs.size(), _backing_fd);
|
||||
char* ret = os::attempt_map_memory_to_file_at(rs.base(), rs.size(), _backing_fd);
|
||||
|
||||
if (ret != rs.base()) {
|
||||
if (ret != NULL) {
|
||||
|
@ -80,6 +80,30 @@ ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment,
|
||||
_executable = executable;
|
||||
}
|
||||
|
||||
// Helper method
|
||||
static char* attempt_map_or_reserve_memory_at(char* base, size_t size, int fd) {
|
||||
if (fd != -1) {
|
||||
return os::attempt_map_memory_to_file_at(base, size, fd);
|
||||
}
|
||||
return os::attempt_reserve_memory_at(base, size);
|
||||
}
|
||||
|
||||
// Helper method
|
||||
static char* map_or_reserve_memory(size_t size, int fd) {
|
||||
if (fd != -1) {
|
||||
return os::map_memory_to_file(size, fd);
|
||||
}
|
||||
return os::reserve_memory(size);
|
||||
}
|
||||
|
||||
// Helper method
|
||||
static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fd) {
|
||||
if (fd != -1) {
|
||||
return os::map_memory_to_file_aligned(size, alignment, fd);
|
||||
}
|
||||
return os::reserve_memory_aligned(size, alignment);
|
||||
}
|
||||
|
||||
// Helper method
|
||||
static void unmap_or_release_memory(char* base, size_t size, bool is_file_mapped) {
|
||||
if (is_file_mapped) {
|
||||
@ -188,13 +212,13 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
|
||||
// important. If available space is not detected, return NULL.
|
||||
|
||||
if (requested_address != 0) {
|
||||
base = os::attempt_reserve_memory_at(requested_address, size, _fd_for_heap);
|
||||
base = attempt_map_or_reserve_memory_at(requested_address, size, _fd_for_heap);
|
||||
if (failed_to_reserve_as_requested(base, requested_address, size, false, _fd_for_heap != -1)) {
|
||||
// OS ignored requested address. Try different address.
|
||||
base = NULL;
|
||||
}
|
||||
} else {
|
||||
base = os::reserve_memory_with_fd(size, _fd_for_heap);
|
||||
base = map_or_reserve_memory(size, _fd_for_heap);
|
||||
}
|
||||
|
||||
if (base == NULL) return;
|
||||
@ -206,7 +230,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
|
||||
|
||||
// Make sure that size is aligned
|
||||
size = align_up(size, alignment);
|
||||
base = os::reserve_memory_aligned(size, alignment, _fd_for_heap);
|
||||
base = map_or_reserve_memory_aligned(size, alignment, _fd_for_heap);
|
||||
|
||||
if (requested_address != 0 &&
|
||||
failed_to_reserve_as_requested(base, requested_address, size, false, _fd_for_heap != -1)) {
|
||||
@ -372,13 +396,13 @@ void ReservedHeapSpace::try_reserve_heap(size_t size,
|
||||
}
|
||||
|
||||
if (requested_address != 0) {
|
||||
base = os::attempt_reserve_memory_at(requested_address, size, _fd_for_heap);
|
||||
base = attempt_map_or_reserve_memory_at(requested_address, size, _fd_for_heap);
|
||||
} else {
|
||||
// Optimistically assume that the OSes returns an aligned base pointer.
|
||||
// When reserving a large address range, most OSes seem to align to at
|
||||
// least 64K.
|
||||
// If the returned memory is not aligned we will release and retry.
|
||||
base = os::reserve_memory_with_fd(size, _fd_for_heap);
|
||||
base = map_or_reserve_memory(size, _fd_for_heap);
|
||||
}
|
||||
}
|
||||
if (base == NULL) { return; }
|
||||
|
@ -1658,38 +1658,10 @@ char* os::reserve_memory(size_t bytes, MEMFLAGS flags) {
|
||||
return result;
|
||||
}
|
||||
|
||||
char* os::reserve_memory_with_fd(size_t bytes, int file_desc) {
|
||||
char* result;
|
||||
|
||||
if (file_desc != -1) {
|
||||
// Could have called pd_reserve_memory() followed by replace_existing_mapping_with_file_mapping(),
|
||||
// but AIX may use SHM in which case its more trouble to detach the segment and remap memory to the file.
|
||||
result = os::map_memory_to_file(NULL /* addr */, bytes, file_desc);
|
||||
if (result != NULL) {
|
||||
MemTracker::record_virtual_memory_reserve_and_commit(result, bytes, CALLER_PC);
|
||||
}
|
||||
} else {
|
||||
result = pd_reserve_memory(bytes);
|
||||
if (result != NULL) {
|
||||
MemTracker::record_virtual_memory_reserve(result, bytes, CALLER_PC);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char* os::attempt_reserve_memory_at(char* addr, size_t bytes, int file_desc) {
|
||||
char* result = NULL;
|
||||
if (file_desc != -1) {
|
||||
result = pd_attempt_reserve_memory_at(addr, bytes, file_desc);
|
||||
if (result != NULL) {
|
||||
MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC);
|
||||
}
|
||||
} else {
|
||||
result = pd_attempt_reserve_memory_at(addr, bytes);
|
||||
if (result != NULL) {
|
||||
MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
|
||||
}
|
||||
char* os::attempt_reserve_memory_at(char* addr, size_t bytes) {
|
||||
char* result = pd_attempt_reserve_memory_at(addr, bytes);
|
||||
if (result != NULL) {
|
||||
MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -1758,6 +1730,25 @@ void os::pretouch_memory(void* start, void* end, size_t page_size) {
|
||||
}
|
||||
}
|
||||
|
||||
char* os::map_memory_to_file(size_t bytes, int file_desc) {
|
||||
// Could have called pd_reserve_memory() followed by replace_existing_mapping_with_file_mapping(),
|
||||
// but AIX may use SHM in which case its more trouble to detach the segment and remap memory to the file.
|
||||
// On all current implementations NULL is interpreted as any available address.
|
||||
char* result = os::map_memory_to_file(NULL /* addr */, bytes, file_desc);
|
||||
if (result != NULL) {
|
||||
MemTracker::record_virtual_memory_reserve_and_commit(result, bytes, CALLER_PC);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char* os::attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc) {
|
||||
char* result = pd_attempt_map_memory_to_file_at(addr, bytes, file_desc);
|
||||
if (result != NULL) {
|
||||
MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
|
||||
char *addr, size_t bytes, bool read_only,
|
||||
bool allow_exec, MEMFLAGS flags) {
|
||||
|
@ -116,7 +116,6 @@ class os: AllStatic {
|
||||
static char* pd_reserve_memory(size_t bytes);
|
||||
|
||||
static char* pd_attempt_reserve_memory_at(char* addr, size_t bytes);
|
||||
static char* pd_attempt_reserve_memory_at(char* addr, size_t bytes, int file_desc);
|
||||
|
||||
static bool pd_commit_memory(char* addr, size_t bytes, bool executable);
|
||||
static bool pd_commit_memory(char* addr, size_t size, size_t alignment_hint,
|
||||
@ -131,6 +130,8 @@ class os: AllStatic {
|
||||
static bool pd_uncommit_memory(char* addr, size_t bytes);
|
||||
static bool pd_release_memory(char* addr, size_t bytes);
|
||||
|
||||
static char* pd_attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc);
|
||||
|
||||
static char* pd_map_memory(int fd, const char* file_name, size_t file_offset,
|
||||
char *addr, size_t bytes, bool read_only = false,
|
||||
bool allow_exec = false);
|
||||
@ -313,19 +314,14 @@ class os: AllStatic {
|
||||
static int vm_allocation_granularity();
|
||||
|
||||
// Reserves virtual memory.
|
||||
// alignment_hint - currently only used by AIX
|
||||
static char* reserve_memory(size_t bytes, MEMFLAGS flags = mtOther);
|
||||
|
||||
// Reserves virtual memory.
|
||||
// if file_desc != -1, also attaches the memory to the file.
|
||||
static char* reserve_memory_with_fd(size_t bytes, int file_desc);
|
||||
|
||||
// Reserves virtual memory that starts at an address that is aligned to 'alignment'.
|
||||
static char* reserve_memory_aligned(size_t size, size_t alignment, int file_desc = -1);
|
||||
static char* reserve_memory_aligned(size_t size, size_t alignment);
|
||||
|
||||
// Attempts to reserve the virtual memory at [addr, addr + bytes).
|
||||
// Does not overwrite existing mappings.
|
||||
static char* attempt_reserve_memory_at(char* addr, size_t bytes, int file_desc = -1);
|
||||
static char* attempt_reserve_memory_at(char* addr, size_t bytes);
|
||||
|
||||
// Split a reserved memory region [base, base+size) into two regions [base, base+split) and
|
||||
// [base+split, base+size).
|
||||
@ -370,7 +366,10 @@ class os: AllStatic {
|
||||
static int create_file_for_heap(const char* dir);
|
||||
// Map memory to the file referred by fd. This function is slightly different from map_memory()
|
||||
// and is added to be used for implementation of -XX:AllocateHeapAt
|
||||
static char* map_memory_to_file(size_t size, int fd);
|
||||
static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd);
|
||||
static char* map_memory_to_file(char* base, size_t size, int fd);
|
||||
static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd);
|
||||
// Replace existing reserved memory with file mapping
|
||||
static char* replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user