/* * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// Used to manually signal a mapper to handle a set of regions as committed. // Setting the 'zero_filled' parameter to false signals the mapper that the // regions have not been cleared by the OS and that they need to be clear // explicitly. void G1RegionToSpaceMapper::signal_mapping_changed(uint start_idx, size_t num_regions) {
fire_on_commit(start_idx, num_regions, false);
}
// G1RegionToSpaceMapper implementation where the region granularity is larger than // or the same as the commit granularity. // Basically, the space corresponding to one region region spans several OS pages. class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper { private:
size_t _pages_per_region;
// G1RegionToSpaceMapper implementation where the region granularity is smaller // than the commit granularity. // Basically, the contents of one OS page span several regions. class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper {
size_t _regions_per_page; // Lock to prevent bitmap updates and the actual underlying // commit to get out of order. This can happen in the cases // where one thread is expanding the heap during a humongous // allocation and at the same time the service thread is // doing uncommit. These operations will not operate on the // same regions, but they might operate on regions sharing // an underlying OS page. So we need to make sure that both // those resources are in sync: // - G1RegionToSpaceMapper::_region_commit_map; // - G1PageBasedVirtualSpace::_committed (_storage.commit())
Mutex _lock;
bool is_page_committed(size_t page_idx) {
size_t region = page_idx * _regions_per_page;
size_t region_limit = region + _regions_per_page; // Committed if there is a bit set in the range. return _region_commit_map.get_next_one_offset(region, region_limit) != region_limit;
}
virtualvoid commit_regions(uint start_idx, size_t num_regions, WorkerThreads* pretouch_workers) {
uint region_limit = (uint)(start_idx + num_regions);
assert(num_regions > 0, "Must commit at least one region");
assert(_region_commit_map.get_next_one_offset(start_idx, region_limit) == region_limit, "Should be no committed regions in the range [%u, %u)", start_idx, region_limit);
// Concurrent operations might operate on regions sharing the same // underlying OS page. See lock declaration for more details.
{
MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag); for (size_t page = start_page; page <= end_page; page++) { if (!is_page_committed(page)) { // Page not committed. if (num_committed == 0) {
first_committed = page;
}
num_committed++;
if (!_storage.commit(page, 1)) { // Found dirty region during commit.
all_zero_filled = false;
}
// Move memory to correct NUMA node for the heap.
numa_request_on_node(page);
} else { // Page already committed.
all_zero_filled = false;
}
}
// Update the commit map for the given range. Not using the par_set_range // since updates to _region_commit_map for this mapper is protected by _lock.
_region_commit_map.set_range(start_idx, region_limit, BitMap::unknown_range);
}
virtualvoid uncommit_regions(uint start_idx, size_t num_regions) {
uint region_limit = (uint)(start_idx + num_regions);
assert(num_regions > 0, "Must uncommit at least one region");
assert(_region_commit_map.get_next_zero_offset(start_idx, region_limit) == region_limit, "Should only be committed regions in the range [%u, %u)", start_idx, region_limit);
// Concurrent operations might operate on regions sharing the same // underlying OS page. See lock declaration for more details.
MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag); // Clear commit map for the given range. Not using the par_clear_range since // updates to _region_commit_map for this mapper is protected by _lock.
_region_commit_map.clear_range(start_idx, region_limit, BitMap::unknown_range);
for (size_t page = start_page; page <= end_page; page++) { // We know all pages were committed before clearing the map. If the // the page is still marked as committed after the clear we should // not uncommit it. if (!is_page_committed(page)) {
_storage.uncommit(page, 1);
}
}
}
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.