8245203: ZGC: Don't track size in ZPhysicalMemoryBacking

Reviewed-by: eosterlund, stefank
This commit is contained in:
Per Lidén 2020-06-09 11:01:09 +02:00
parent 82e3640eb1
commit 4d8189b265
9 changed files with 33 additions and 113 deletions

View File

@ -73,13 +73,12 @@ static ZErrno mremap(uintptr_t from_addr, uintptr_t to_addr, size_t size) {
return (res == KERN_SUCCESS) ? ZErrno(0) : ZErrno(EINVAL); return (res == KERN_SUCCESS) ? ZErrno(0) : ZErrno(EINVAL);
} }
ZPhysicalMemoryBacking::ZPhysicalMemoryBacking() : ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity) :
_base(0), _base(0),
_size(0),
_initialized(false) { _initialized(false) {
// Reserve address space for backing memory // Reserve address space for backing memory
_base = (uintptr_t)os::reserve_memory(MaxHeapSize); _base = (uintptr_t)os::reserve_memory(max_capacity);
if (_base == 0) { if (_base == 0) {
// Failed // Failed
log_error_pd(gc)("Failed to reserve address space for backing memory"); log_error_pd(gc)("Failed to reserve address space for backing memory");
@ -98,10 +97,6 @@ void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const {
// Does nothing // Does nothing
} }
size_t ZPhysicalMemoryBacking::size() const {
return _size;
}
bool ZPhysicalMemoryBacking::commit_inner(size_t offset, size_t length) { bool ZPhysicalMemoryBacking::commit_inner(size_t offset, size_t length) {
assert(is_aligned(offset, os::vm_page_size()), "Invalid offset"); assert(is_aligned(offset, os::vm_page_size()), "Invalid offset");
assert(is_aligned(length, os::vm_page_size()), "Invalid length"); assert(is_aligned(length, os::vm_page_size()), "Invalid length");
@ -117,12 +112,6 @@ bool ZPhysicalMemoryBacking::commit_inner(size_t offset, size_t length) {
return false; return false;
} }
const size_t end = offset + length;
if (end > _size) {
// Record new size
_size = end;
}
// Success // Success
return true; return true;
} }

View File

@ -27,20 +27,17 @@
class ZPhysicalMemoryBacking { class ZPhysicalMemoryBacking {
private: private:
uintptr_t _base; uintptr_t _base;
size_t _size;
bool _initialized; bool _initialized;
bool commit_inner(size_t offset, size_t length); bool commit_inner(size_t offset, size_t length);
public: public:
ZPhysicalMemoryBacking(); ZPhysicalMemoryBacking(size_t max_capacity);
bool is_initialized() const; bool is_initialized() const;
void warn_commit_limits(size_t max) const; void warn_commit_limits(size_t max) const;
size_t size() const;
size_t commit(size_t offset, size_t length); size_t commit(size_t offset, size_t length);
size_t uncommit(size_t offset, size_t length); size_t uncommit(size_t offset, size_t length);

View File

@ -113,9 +113,8 @@ static const char* z_preferred_hugetlbfs_mountpoints[] = {
static int z_fallocate_hugetlbfs_attempts = 3; static int z_fallocate_hugetlbfs_attempts = 3;
static bool z_fallocate_supported = true; static bool z_fallocate_supported = true;
ZPhysicalMemoryBacking::ZPhysicalMemoryBacking() : ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity) :
_fd(-1), _fd(-1),
_size(0),
_filesystem(0), _filesystem(0),
_block_size(0), _block_size(0),
_available(0), _available(0),
@ -127,6 +126,15 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking() :
return; return;
} }
// Truncate backing file
while (ftruncate(_fd, max_capacity) == -1) {
if (errno != EINTR) {
ZErrno err;
log_error_p(gc)("Failed to truncate backing file (%s)", err.to_string());
return;
}
}
// Get filesystem statistics // Get filesystem statistics
struct statfs buf; struct statfs buf;
if (fstatfs(_fd, &buf) == -1) { if (fstatfs(_fd, &buf) == -1) {
@ -362,10 +370,6 @@ void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const {
warn_max_map_count(max); warn_max_map_count(max);
} }
size_t ZPhysicalMemoryBacking::size() const {
return _size;
}
bool ZPhysicalMemoryBacking::is_tmpfs() const { bool ZPhysicalMemoryBacking::is_tmpfs() const {
return _filesystem == TMPFS_MAGIC; return _filesystem == TMPFS_MAGIC;
} }
@ -380,18 +384,6 @@ bool ZPhysicalMemoryBacking::tmpfs_supports_transparent_huge_pages() const {
return access(ZFILENAME_SHMEM_ENABLED, R_OK) == 0; return access(ZFILENAME_SHMEM_ENABLED, R_OK) == 0;
} }
ZErrno ZPhysicalMemoryBacking::fallocate_compat_ftruncate(size_t size) const {
while (ftruncate(_fd, size) == -1) {
if (errno != EINTR) {
// Failed
return errno;
}
}
// Success
return 0;
}
ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_hugetlbfs(size_t offset, size_t length, bool touch) const { ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_hugetlbfs(size_t offset, size_t length, bool touch) const {
// On hugetlbfs, mapping a file segment will fail immediately, without // On hugetlbfs, mapping a file segment will fail immediately, without
// the need to touch the mapped pages first, if there aren't enough huge // the need to touch the mapped pages first, if there aren't enough huge
@ -490,41 +482,13 @@ ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_compat(size_t offset, size_t
// since Linux 4.3. When fallocate(2) is not supported we emulate it using // since Linux 4.3. When fallocate(2) is not supported we emulate it using
// mmap/munmap (for hugetlbfs and tmpfs with transparent huge pages) or pwrite // mmap/munmap (for hugetlbfs and tmpfs with transparent huge pages) or pwrite
// (for tmpfs without transparent huge pages and other filesystem types). // (for tmpfs without transparent huge pages and other filesystem types).
if (ZLargePages::is_explicit()) {
const size_t end = offset + length; return fallocate_compat_mmap_hugetlbfs(offset, length, false /* touch */);
if (end > _size) { } else if (ZLargePages::is_transparent()) {
// Increase file size return fallocate_compat_mmap_tmpfs(offset, length);
const ZErrno err = fallocate_compat_ftruncate(end); } else {
if (err) { return fallocate_compat_pwrite(offset, length);
// Failed
return err;
}
} }
// Allocate backing memory
const ZErrno err = ZLargePages::is_explicit()
? fallocate_compat_mmap_hugetlbfs(offset, length, false /* touch */)
: (ZLargePages::is_transparent()
? fallocate_compat_mmap_tmpfs(offset, length)
: fallocate_compat_pwrite(offset, length));
if (err) {
if (end > _size) {
// Restore file size
fallocate_compat_ftruncate(_size);
}
// Failed
return err;
}
if (end > _size) {
// Record new file size
_size = end;
}
// Success
return 0;
} }
ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_syscall(size_t offset, size_t length) { ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_syscall(size_t offset, size_t length) {
@ -535,12 +499,6 @@ ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_syscall(size_t offset, size_t
return errno; return errno;
} }
const size_t end = offset + length;
if (end > _size) {
// Record new file size
_size = end;
}
// Success // Success
return 0; return 0;
} }

View File

@ -46,7 +46,6 @@ private:
bool is_hugetlbfs() const; bool is_hugetlbfs() const;
bool tmpfs_supports_transparent_huge_pages() const; bool tmpfs_supports_transparent_huge_pages() const;
ZErrno fallocate_compat_ftruncate(size_t size) const;
ZErrno fallocate_compat_mmap_hugetlbfs(size_t offset, size_t length, bool touch) const; ZErrno fallocate_compat_mmap_hugetlbfs(size_t offset, size_t length, bool touch) const;
ZErrno fallocate_compat_mmap_tmpfs(size_t offset, size_t length) const; ZErrno fallocate_compat_mmap_tmpfs(size_t offset, size_t length) const;
ZErrno fallocate_compat_pwrite(size_t offset, size_t length) const; ZErrno fallocate_compat_pwrite(size_t offset, size_t length) const;
@ -62,14 +61,12 @@ private:
size_t commit_default(size_t offset, size_t length); size_t commit_default(size_t offset, size_t length);
public: public:
ZPhysicalMemoryBacking(); ZPhysicalMemoryBacking(size_t max_capacity);
bool is_initialized() const; bool is_initialized() const;
void warn_commit_limits(size_t max) const; void warn_commit_limits(size_t max) const;
size_t size() const;
size_t commit(size_t offset, size_t length); size_t commit(size_t offset, size_t length);
size_t uncommit(size_t offset, size_t length); size_t uncommit(size_t offset, size_t length);

View File

@ -35,9 +35,8 @@
// committing and uncommitting, each ZGranuleSize'd chunk is mapped to // committing and uncommitting, each ZGranuleSize'd chunk is mapped to
// a separate paging file mapping. // a separate paging file mapping.
ZPhysicalMemoryBacking::ZPhysicalMemoryBacking() : ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity) :
_handles(MaxHeapSize), _handles(max_capacity) {}
_size(0) {}
bool ZPhysicalMemoryBacking::is_initialized() const { bool ZPhysicalMemoryBacking::is_initialized() const {
return true; return true;
@ -47,10 +46,6 @@ void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const {
// Does nothing // Does nothing
} }
size_t ZPhysicalMemoryBacking::size() const {
return _size;
}
HANDLE ZPhysicalMemoryBacking::get_handle(uintptr_t offset) const { HANDLE ZPhysicalMemoryBacking::get_handle(uintptr_t offset) const {
HANDLE const handle = _handles.get(offset); HANDLE const handle = _handles.get(offset);
assert(handle != 0, "Should be set"); assert(handle != 0, "Should be set");
@ -95,15 +90,7 @@ size_t ZPhysicalMemoryBacking::commit(size_t offset, size_t length) {
log_trace(gc, heap)("Committing memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)", log_trace(gc, heap)("Committing memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",
offset / M, (offset + length) / M, length / M); offset / M, (offset + length) / M, length / M);
const size_t committed = commit_from_paging_file(offset, length); return commit_from_paging_file(offset, length);
const size_t end = offset + committed;
if (end > _size) {
// Update size
_size = end;
}
return committed;
} }
size_t ZPhysicalMemoryBacking::uncommit(size_t offset, size_t length) { size_t ZPhysicalMemoryBacking::uncommit(size_t offset, size_t length) {

View File

@ -31,7 +31,6 @@
class ZPhysicalMemoryBacking { class ZPhysicalMemoryBacking {
private: private:
ZGranuleMap<HANDLE> _handles; ZGranuleMap<HANDLE> _handles;
size_t _size;
HANDLE get_handle(uintptr_t offset) const; HANDLE get_handle(uintptr_t offset) const;
void put_handle(uintptr_t offset, HANDLE handle); void put_handle(uintptr_t offset, HANDLE handle);
@ -41,14 +40,12 @@ private:
size_t uncommit_from_paging_file(size_t offset, size_t size); size_t uncommit_from_paging_file(size_t offset, size_t size);
public: public:
ZPhysicalMemoryBacking(); ZPhysicalMemoryBacking(size_t max_capacity);
bool is_initialized() const; bool is_initialized() const;
void warn_commit_limits(size_t max) const; void warn_commit_limits(size_t max) const;
size_t size() const;
size_t commit(size_t offset, size_t length); size_t commit(size_t offset, size_t length);
size_t uncommit(size_t offset, size_t length); size_t uncommit(size_t offset, size_t length);

View File

@ -106,7 +106,7 @@ ZPageAllocator::ZPageAllocator(ZWorkers* workers,
size_t max_reserve) : size_t max_reserve) :
_lock(), _lock(),
_virtual(max_capacity), _virtual(max_capacity),
_physical(), _physical(max_capacity),
_cache(), _cache(),
_min_capacity(min_capacity), _min_capacity(min_capacity),
_max_capacity(max_capacity), _max_capacity(max_capacity),

View File

@ -135,6 +135,12 @@ ZPhysicalMemory ZPhysicalMemory::split(size_t size) {
return pmem; return pmem;
} }
ZPhysicalMemoryManager::ZPhysicalMemoryManager(size_t max_capacity) :
_backing(max_capacity) {
// Register everything as uncommitted
_uncommitted.free(0, max_capacity);
}
bool ZPhysicalMemoryManager::is_initialized() const { bool ZPhysicalMemoryManager::is_initialized() const {
return _backing.is_initialized(); return _backing.is_initialized();
} }
@ -145,7 +151,6 @@ void ZPhysicalMemoryManager::warn_commit_limits(size_t max) const {
bool ZPhysicalMemoryManager::supports_uncommit() { bool ZPhysicalMemoryManager::supports_uncommit() {
assert(!is_init_completed(), "Invalid state"); assert(!is_init_completed(), "Invalid state");
assert(_backing.size() >= ZGranuleSize, "Invalid size");
// Test if uncommit is supported by uncommitting and then re-committing a granule // Test if uncommit is supported by uncommitting and then re-committing a granule
return commit(uncommit(ZGranuleSize)) == ZGranuleSize; return commit(uncommit(ZGranuleSize)) == ZGranuleSize;
@ -194,18 +199,6 @@ size_t ZPhysicalMemoryManager::commit(size_t size) {
} }
} }
// Expand backing memory
if (committed < size) {
const size_t remaining = size - committed;
const uintptr_t start = _backing.size();
const size_t expanded = _backing.commit(start, remaining);
if (expanded > 0) {
// Successful or partialy successful
_committed.free(start, expanded);
committed += expanded;
}
}
return committed; return committed;
} }

View File

@ -78,6 +78,8 @@ private:
void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const;
public: public:
ZPhysicalMemoryManager(size_t max_capacity);
bool is_initialized() const; bool is_initialized() const;
void warn_commit_limits(size_t max) const; void warn_commit_limits(size_t max) const;