8272807: Permit use of memory concurrent with pretouch

Reviewed-by: shade, stuefe
This commit is contained in:
Kim Barrett 2022-02-09 06:53:09 +00:00
parent cb2f8caed2
commit 072e7b4da0
2 changed files with 27 additions and 10 deletions

View file

@ -1745,13 +1745,31 @@ void os::print_memory_mappings(outputStream* st) {
os::print_memory_mappings(nullptr, (size_t)-1, st);
}
// Pretouching must use a store, not just a load. On many OSes loads from
// fresh memory would be satisfied from a single mapped page containing all
// zeros. We need to store something to each page to get them backed by
// their own memory, which is the effect we want here. An atomic add of
// zero is used instead of a simple store, allowing the memory to be used
// while pretouch is in progress, rather than requiring users of the memory
// to wait until the entire range has been touched. This is technically
// a UB data race, but doesn't cause any problems for us.
void os::pretouch_memory(void* start, void* end, size_t page_size) {
for (volatile char *p = (char*)start; p < (char*)end; p += page_size) {
// Note: this must be a store, not a load. On many OSes loads from fresh
// memory would be satisfied from a single mapped page containing all zeros.
// We need to store something to each page to get them backed by their own
// memory, which is the effect we want here.
*p = 0;
assert(start <= end, "invalid range: " PTR_FORMAT " -> " PTR_FORMAT, p2i(start), p2i(end));
assert(is_power_of_2(page_size), "page size misaligned: %zu", page_size);
assert(page_size >= sizeof(int), "page size too small: %zu", page_size);
if (start < end) {
// We're doing concurrent-safe touch and memory state has page
// granularity, so we can touch anywhere in a page. Touch at the
// beginning of each page to simplify iteration.
char* cur = static_cast<char*>(align_down(start, page_size));
void* last = align_down(static_cast<char*>(end) - 1, page_size);
assert(cur <= last, "invariant");
// Iterate from first page through last (inclusive), being careful to
// avoid overflow if the last page abuts the end of the address range.
for ( ; true; cur += page_size) {
Atomic::add(reinterpret_cast<int*>(cur), 0, memory_order_relaxed);
if (cur >= last) break;
}
}
}