7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #include "precompiled.hpp" 25 #include "gc/shared/gcLogPrecious.hpp" 26 #include "gc/z/zAddress.inline.hpp" 27 #include "gc/z/zGlobals.hpp" 28 #include "gc/z/zLargePages.inline.hpp" 29 #include "gc/z/zNUMA.inline.hpp" 30 #include "gc/z/zPhysicalMemory.inline.hpp" 31 #include "logging/log.hpp" 32 #include "runtime/globals.hpp" 33 #include "runtime/globals_extension.hpp" 34 #include "runtime/init.hpp" 35 #include "runtime/os.hpp" 36 #include "services/memTracker.hpp" 37 #include "utilities/align.hpp" 38 #include "utilities/debug.hpp" 39 #include "utilities/globalDefinitions.hpp" 40 #include "utilities/powerOfTwo.hpp" 41 42 ZPhysicalMemory::ZPhysicalMemory() : 43 _nsegments_max(0), 44 _nsegments(0), 45 _segments(NULL) {} 46 47 ZPhysicalMemory::ZPhysicalMemory(const ZPhysicalMemorySegment& segment) : 48 _nsegments_max(0), 49 _nsegments(0), 50 _segments(NULL) { 51 add_segment(segment); 52 } 53 54 ZPhysicalMemory::ZPhysicalMemory(const ZPhysicalMemory& pmem) : 55 _nsegments_max(0), 56 _nsegments(0), 57 _segments(NULL) { 58 add_segments(pmem); 59 } 60 61 const ZPhysicalMemory& ZPhysicalMemory::operator=(const ZPhysicalMemory& pmem) { 62 remove_segments(); 63 add_segments(pmem); 64 return *this; 65 } 66 67 ZPhysicalMemory::~ZPhysicalMemory() { 68 remove_segments(); 69 } 70 71 size_t ZPhysicalMemory::size() const { 72 size_t size = 0; 73 74 for (uint32_t i = 0; i < _nsegments; i++) { 75 size += _segments[i].size(); 76 } 77 78 return size; 79 } 80 81 void ZPhysicalMemory::insert_segment(uint32_t index, uintptr_t start, size_t size, bool committed) { 82 assert(index <= _nsegments, "Invalid index"); 83 84 ZPhysicalMemorySegment* const from_segments = _segments; 85 86 if (_nsegments + 1 > _nsegments_max) { 87 // Resize array 88 _nsegments_max = round_up_power_of_2(_nsegments_max + 1); 89 _segments = new ZPhysicalMemorySegment[_nsegments_max]; 90 91 // Copy segments before index 92 for (uint32_t i = 0; i < index; i++) { 93 _segments[i] = from_segments[i]; 94 } 95 } 96 97 // Copy/Move segments after index 98 for (uint32_t i = _nsegments; i > index; i--) { 99 _segments[i] = from_segments[i - 1]; 100 } 101 102 // Insert new segment 103 _segments[index] = ZPhysicalMemorySegment(start, size, committed); 104 _nsegments++; 105 106 // Delete old array 107 if (from_segments != _segments) { 108 delete [] from_segments; 109 } 110 } 111 112 void ZPhysicalMemory::replace_segment(uint32_t index, uintptr_t start, size_t size, bool committed) { 113 assert(index < _nsegments, "Invalid index"); 114 _segments[index] = ZPhysicalMemorySegment(start, size, committed);; 115 } 116 117 void ZPhysicalMemory::remove_segment(uint32_t index) { 118 assert(index < _nsegments, "Invalid index"); 119 120 // Move segments after index 121 for (uint32_t i = index + 1; i < _nsegments; i++) { 122 _segments[i - 1] = _segments[i]; 123 } 124 125 _nsegments--; 126 } 127 128 void ZPhysicalMemory::add_segments(const ZPhysicalMemory& pmem) { 129 for (uint32_t i = 0; i < pmem.nsegments(); i++) { 130 add_segment(pmem.segment(i)); 131 } 132 } 133 134 void ZPhysicalMemory::remove_segments() { 135 delete [] _segments; 136 _segments = NULL; 137 _nsegments_max = 0; 138 _nsegments = 0; 139 } 140 141 static bool is_mergable(const ZPhysicalMemorySegment& before, const ZPhysicalMemorySegment& after) { 142 return before.end() == after.start() && before.is_committed() == after.is_committed(); 143 } 144 145 void ZPhysicalMemory::add_segment(const ZPhysicalMemorySegment& segment) { 146 // Insert segments in address order, merge segments when possible 147 for (uint32_t i = _nsegments; i > 0; i--) { 148 const uint32_t current = i - 1; 149 150 if (_segments[current].end() <= segment.start()) { 151 if (is_mergable(_segments[current], segment)) { 152 if (current + 1 < _nsegments && is_mergable(segment, _segments[current + 1])) { 153 // Merge with end of current segment and start of next segment 154 const size_t start = _segments[current].start(); 155 const size_t size = _segments[current].size() + segment.size() + _segments[current + 1].size(); 156 replace_segment(current, start, size, segment.is_committed()); 157 remove_segment(current + 1); 158 return; 159 } 160 161 // Merge with end of current segment 162 const size_t start = _segments[current].start(); 163 const size_t size = _segments[current].size() + segment.size(); 164 replace_segment(current, start, size, segment.is_committed()); 165 return; 166 } else if (current + 1 < _nsegments && is_mergable(segment, _segments[current + 1])) { 167 // Merge with start of next segment 168 const size_t start = segment.start(); 169 const size_t size = segment.size() + _segments[current + 1].size(); 170 replace_segment(current + 1, start, size, segment.is_committed()); 171 return; 172 } 173 174 // Insert after current segment 175 insert_segment(current + 1, segment.start(), segment.size(), segment.is_committed()); 176 return; 177 } 178 } 179 180 if (_nsegments > 0 && is_mergable(segment, _segments[0])) { 181 // Merge with start of first segment 182 const size_t start = segment.start(); 183 const size_t size = segment.size() + _segments[0].size(); 184 replace_segment(0, start, size, segment.is_committed()); 185 return; 186 } 187 188 // Insert before first segment 189 insert_segment(0, segment.start(), segment.size(), segment.is_committed()); 190 } 191 192 bool ZPhysicalMemory::commit_segment(uint32_t index, size_t size) { 193 assert(index < _nsegments, "Invalid index"); 194 assert(size <= _segments[index].size(), "Invalid size"); 195 assert(!_segments[index].is_committed(), "Invalid state"); 196 197 if (size == _segments[index].size()) { 198 // Completely committed 199 _segments[index].set_committed(true); 200 return true; 201 } 202 203 if (size > 0) { 204 // Partially committed, split segment 205 insert_segment(index + 1, _segments[index].start() + size, _segments[index].size() - size, false /* committed */); 206 replace_segment(index, _segments[index].start(), size, true /* committed */); 207 } 208 209 return false; 210 } 211 212 bool ZPhysicalMemory::uncommit_segment(uint32_t index, size_t size) { 213 assert(index < _nsegments, "Invalid index"); 214 assert(size <= _segments[index].size(), "Invalid size"); 215 assert(_segments[index].is_committed(), "Invalid state"); 216 217 if (size == _segments[index].size()) { 218 // Completely uncommitted 219 _segments[index].set_committed(false); 220 return true; 221 } 222 223 if (size > 0) { 224 // Partially uncommitted, split segment 225 insert_segment(index + 1, _segments[index].start() + size, _segments[index].size() - size, true /* committed */); 226 replace_segment(index, _segments[index].start(), size, false /* committed */); 227 } 228 229 return false; 230 } 231 232 ZPhysicalMemory ZPhysicalMemory::split(size_t size) { 233 ZPhysicalMemory pmem; 234 uint32_t nsegments = 0; 235 236 for (uint32_t i = 0; i < _nsegments; i++) { 237 const ZPhysicalMemorySegment& segment = _segments[i]; 238 if (pmem.size() < size) { 239 if (pmem.size() + segment.size() <= size) { 240 // Transfer segment 241 pmem.add_segment(segment); 242 } else { 243 // Split segment 244 const size_t split_size = size - pmem.size(); 245 pmem.add_segment(ZPhysicalMemorySegment(segment.start(), split_size, segment.is_committed())); 246 _segments[nsegments++] = ZPhysicalMemorySegment(segment.start() + split_size, segment.size() - split_size, segment.is_committed()); 247 } 248 } else { 249 // Keep segment 250 _segments[nsegments++] = segment; 251 } 252 } 253 254 _nsegments = nsegments; 255 256 return pmem; 257 } 258 259 ZPhysicalMemory ZPhysicalMemory::split_committed() { 260 ZPhysicalMemory pmem; 261 uint32_t nsegments = 0; 262 263 for (uint32_t i = 0; i < _nsegments; i++) { 264 const ZPhysicalMemorySegment& segment = _segments[i]; 265 if (segment.is_committed()) { 266 // Transfer segment 267 pmem.add_segment(segment); 268 } else { 269 // Keep segment 270 _segments[nsegments++] = segment; 271 } 272 } 273 274 _nsegments = nsegments; 275 276 return pmem; 277 } 278 279 ZPhysicalMemoryManager::ZPhysicalMemoryManager(size_t max_capacity) : 280 _backing(max_capacity) { 281 // Make the whole range free 282 _manager.free(0, max_capacity); 283 } 284 285 bool ZPhysicalMemoryManager::is_initialized() const { 286 return _backing.is_initialized(); 287 } 288 289 void ZPhysicalMemoryManager::warn_commit_limits(size_t max_capacity) const { 290 _backing.warn_commit_limits(max_capacity); 291 } 292 293 void ZPhysicalMemoryManager::try_enable_uncommit(size_t min_capacity, size_t max_capacity) { 294 assert(!is_init_completed(), "Invalid state"); 332 Tracker tracker(Tracker::uncommit); 333 tracker.record((address)addr, size); 334 } 335 } 336 337 void ZPhysicalMemoryManager::alloc(ZPhysicalMemory& pmem, size_t size) { 338 assert(is_aligned(size, ZGranuleSize), "Invalid size"); 339 340 // Allocate segments 341 while (size > 0) { 342 size_t allocated = 0; 343 const uintptr_t start = _manager.alloc_from_front_at_most(size, &allocated); 344 assert(start != UINTPTR_MAX, "Allocation should never fail"); 345 pmem.add_segment(ZPhysicalMemorySegment(start, allocated, false /* committed */)); 346 size -= allocated; 347 } 348 } 349 350 void ZPhysicalMemoryManager::free(const ZPhysicalMemory& pmem) { 351 // Free segments 352 for (uint32_t i = 0; i < pmem.nsegments(); i++) { 353 const ZPhysicalMemorySegment& segment = pmem.segment(i); 354 _manager.free(segment.start(), segment.size()); 355 } 356 } 357 358 bool ZPhysicalMemoryManager::commit(ZPhysicalMemory& pmem) { 359 // Commit segments 360 for (uint32_t i = 0; i < pmem.nsegments(); i++) { 361 const ZPhysicalMemorySegment& segment = pmem.segment(i); 362 if (segment.is_committed()) { 363 // Segment already committed 364 continue; 365 } 366 367 // Commit segment 368 const size_t committed = _backing.commit(segment.start(), segment.size()); 369 if (!pmem.commit_segment(i, committed)) { 370 // Failed or partially failed 371 return false; 372 } 373 } 374 375 // Success 376 return true; 377 } 378 379 bool ZPhysicalMemoryManager::uncommit(ZPhysicalMemory& pmem) { 380 // Commit segments 381 for (uint32_t i = 0; i < pmem.nsegments(); i++) { 382 const ZPhysicalMemorySegment& segment = pmem.segment(i); 383 if (!segment.is_committed()) { 384 // Segment already uncommitted 385 continue; 386 } 387 388 // Uncommit segment 389 const size_t uncommitted = _backing.uncommit(segment.start(), segment.size()); 390 if (!pmem.uncommit_segment(i, uncommitted)) { 391 // Failed or partially failed 392 return false; 393 } 394 } 395 396 // Success 397 return true; 398 } 399 400 void ZPhysicalMemoryManager::pretouch_view(uintptr_t addr, size_t size) const { 401 const size_t page_size = ZLargePages::is_explicit() ? ZGranuleSize : os::vm_page_size(); 402 os::pretouch_memory((void*)addr, (void*)(addr + size), page_size); 403 } 404 405 void ZPhysicalMemoryManager::map_view(uintptr_t addr, const ZPhysicalMemory& pmem) const { 406 size_t size = 0; 407 408 // Map segments 409 for (uint32_t i = 0; i < pmem.nsegments(); i++) { 410 const ZPhysicalMemorySegment& segment = pmem.segment(i); 411 _backing.map(addr + size, segment.size(), segment.start()); 412 size += segment.size(); 413 } 414 415 // Setup NUMA interleaving for large pages 416 if (ZNUMA::is_enabled() && ZLargePages::is_explicit()) { 417 // To get granule-level NUMA interleaving when using large pages, 418 // we simply let the kernel interleave the memory for us at page 419 // fault time. 420 os::numa_make_global((char*)addr, size); 421 } 422 } 423 424 void ZPhysicalMemoryManager::unmap_view(uintptr_t addr, size_t size) const { 425 _backing.unmap(addr, size); 426 } 427 428 void ZPhysicalMemoryManager::pretouch(uintptr_t offset, size_t size) const { 429 if (ZVerifyViews) { | 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #include "precompiled.hpp" 25 #include "gc/shared/gcLogPrecious.hpp" 26 #include "gc/z/zAddress.inline.hpp" 27 #include "gc/z/zArray.inline.hpp" 28 #include "gc/z/zGlobals.hpp" 29 #include "gc/z/zLargePages.inline.hpp" 30 #include "gc/z/zNUMA.inline.hpp" 31 #include "gc/z/zPhysicalMemory.inline.hpp" 32 #include "logging/log.hpp" 33 #include "runtime/globals.hpp" 34 #include "runtime/globals_extension.hpp" 35 #include "runtime/init.hpp" 36 #include "runtime/os.hpp" 37 #include "services/memTracker.hpp" 38 #include "utilities/align.hpp" 39 #include "utilities/debug.hpp" 40 #include "utilities/globalDefinitions.hpp" 41 #include "utilities/powerOfTwo.hpp" 42 43 ZPhysicalMemory::ZPhysicalMemory() : 44 _segments() {} 45 46 ZPhysicalMemory::ZPhysicalMemory(const ZPhysicalMemorySegment& segment) : 47 _segments() { 48 add_segment(segment); 49 } 50 51 ZPhysicalMemory::ZPhysicalMemory(const ZPhysicalMemory& pmem) : 52 _segments() { 53 add_segments(pmem); 54 } 55 56 const ZPhysicalMemory& ZPhysicalMemory::operator=(const ZPhysicalMemory& pmem) { 57 // Free segments 58 _segments.clear_and_deallocate(); 59 60 // Copy segments 61 add_segments(pmem); 62 63 return *this; 64 } 65 66 size_t ZPhysicalMemory::size() const { 67 size_t size = 0; 68 69 for (int i = 0; i < _segments.length(); i++) { 70 size += _segments.at(i).size(); 71 } 72 73 return size; 74 } 75 76 void ZPhysicalMemory::insert_segment(int index, uintptr_t start, size_t size, bool committed) { 77 _segments.insert_before(index, ZPhysicalMemorySegment(start, size, committed)); 78 } 79 80 void ZPhysicalMemory::replace_segment(int index, uintptr_t start, size_t size, bool committed) { 81 _segments.at_put(index, ZPhysicalMemorySegment(start, size, committed)); 82 } 83 84 void ZPhysicalMemory::remove_segment(int index) { 85 _segments.remove_at(index); 86 } 87 88 void ZPhysicalMemory::add_segments(const ZPhysicalMemory& pmem) { 89 for (int i = 0; i < pmem.nsegments(); i++) { 90 add_segment(pmem.segment(i)); 91 } 92 } 93 94 void ZPhysicalMemory::remove_segments() { 95 _segments.clear_and_deallocate(); 96 } 97 98 static bool is_mergable(const ZPhysicalMemorySegment& before, const ZPhysicalMemorySegment& after) { 99 return before.end() == after.start() && before.is_committed() == after.is_committed(); 100 } 101 102 void ZPhysicalMemory::add_segment(const ZPhysicalMemorySegment& segment) { 103 // Insert segments in address order, merge segments when possible 104 for (int i = _segments.length(); i > 0; i--) { 105 const int current = i - 1; 106 107 if (_segments.at(current).end() <= segment.start()) { 108 if (is_mergable(_segments.at(current), segment)) { 109 if (current + 1 < _segments.length() && is_mergable(segment, _segments.at(current + 1))) { 110 // Merge with end of current segment and start of next segment 111 const size_t start = _segments.at(current).start(); 112 const size_t size = _segments.at(current).size() + segment.size() + _segments.at(current + 1).size(); 113 replace_segment(current, start, size, segment.is_committed()); 114 remove_segment(current + 1); 115 return; 116 } 117 118 // Merge with end of current segment 119 const size_t start = _segments.at(current).start(); 120 const size_t size = _segments.at(current).size() + segment.size(); 121 replace_segment(current, start, size, segment.is_committed()); 122 return; 123 } else if (current + 1 < _segments.length() && is_mergable(segment, _segments.at(current + 1))) { 124 // Merge with start of next segment 125 const size_t start = segment.start(); 126 const size_t size = segment.size() + _segments.at(current + 1).size(); 127 replace_segment(current + 1, start, size, segment.is_committed()); 128 return; 129 } 130 131 // Insert after current segment 132 insert_segment(current + 1, segment.start(), segment.size(), segment.is_committed()); 133 return; 134 } 135 } 136 137 if (_segments.length() > 0 && is_mergable(segment, _segments.at(0))) { 138 // Merge with start of first segment 139 const size_t start = segment.start(); 140 const size_t size = segment.size() + _segments.at(0).size(); 141 replace_segment(0, start, size, segment.is_committed()); 142 return; 143 } 144 145 // Insert before first segment 146 insert_segment(0, segment.start(), segment.size(), segment.is_committed()); 147 } 148 149 bool ZPhysicalMemory::commit_segment(int index, size_t size) { 150 ZPhysicalMemorySegment& segment = _segments.at(index); 151 152 assert(size <= segment.size(), "Invalid size"); 153 assert(!segment.is_committed(), "Invalid state"); 154 155 if (size == segment.size()) { 156 // Completely committed 157 segment.set_committed(true); 158 return true; 159 } 160 161 if (size > 0) { 162 // Partially committed, split segment 163 insert_segment(index + 1, segment.start() + size, segment.size() - size, false /* committed */); 164 replace_segment(index, segment.start(), size, true /* committed */); 165 } 166 167 return false; 168 } 169 170 bool ZPhysicalMemory::uncommit_segment(int index, size_t size) { 171 ZPhysicalMemorySegment& segment = _segments.at(index); 172 173 assert(size <= segment.size(), "Invalid size"); 174 assert(segment.is_committed(), "Invalid state"); 175 176 if (size == segment.size()) { 177 // Completely uncommitted 178 segment.set_committed(false); 179 return true; 180 } 181 182 if (size > 0) { 183 // Partially uncommitted, split segment 184 insert_segment(index + 1, segment.start() + size, segment.size() - size, true /* committed */); 185 replace_segment(index, segment.start(), size, false /* committed */); 186 } 187 188 return false; 189 } 190 191 ZPhysicalMemory ZPhysicalMemory::split(size_t size) { 192 ZPhysicalMemory pmem; 193 int nsegments = 0; 194 195 for (int i = 0; i < _segments.length(); i++) { 196 const ZPhysicalMemorySegment& segment = _segments.at(i); 197 if (pmem.size() < size) { 198 if (pmem.size() + segment.size() <= size) { 199 // Transfer segment 200 pmem.add_segment(segment); 201 } else { 202 // Split segment 203 const size_t split_size = size - pmem.size(); 204 pmem.add_segment(ZPhysicalMemorySegment(segment.start(), split_size, segment.is_committed())); 205 _segments.at_put(nsegments++, ZPhysicalMemorySegment(segment.start() + split_size, segment.size() - split_size, segment.is_committed())); 206 } 207 } else { 208 // Keep segment 209 _segments.at_put(nsegments++, segment); 210 } 211 } 212 213 _segments.trunc_to(nsegments); 214 215 return pmem; 216 } 217 218 ZPhysicalMemory ZPhysicalMemory::split_committed() { 219 ZPhysicalMemory pmem; 220 int nsegments = 0; 221 222 for (int i = 0; i < _segments.length(); i++) { 223 const ZPhysicalMemorySegment& segment = _segments.at(i); 224 if (segment.is_committed()) { 225 // Transfer segment 226 pmem.add_segment(segment); 227 } else { 228 // Keep segment 229 _segments.at_put(nsegments++, segment); 230 } 231 } 232 233 _segments.trunc_to(nsegments); 234 235 return pmem; 236 } 237 238 ZPhysicalMemoryManager::ZPhysicalMemoryManager(size_t max_capacity) : 239 _backing(max_capacity) { 240 // Make the whole range free 241 _manager.free(0, max_capacity); 242 } 243 244 bool ZPhysicalMemoryManager::is_initialized() const { 245 return _backing.is_initialized(); 246 } 247 248 void ZPhysicalMemoryManager::warn_commit_limits(size_t max_capacity) const { 249 _backing.warn_commit_limits(max_capacity); 250 } 251 252 void ZPhysicalMemoryManager::try_enable_uncommit(size_t min_capacity, size_t max_capacity) { 253 assert(!is_init_completed(), "Invalid state"); 291 Tracker tracker(Tracker::uncommit); 292 tracker.record((address)addr, size); 293 } 294 } 295 296 void ZPhysicalMemoryManager::alloc(ZPhysicalMemory& pmem, size_t size) { 297 assert(is_aligned(size, ZGranuleSize), "Invalid size"); 298 299 // Allocate segments 300 while (size > 0) { 301 size_t allocated = 0; 302 const uintptr_t start = _manager.alloc_from_front_at_most(size, &allocated); 303 assert(start != UINTPTR_MAX, "Allocation should never fail"); 304 pmem.add_segment(ZPhysicalMemorySegment(start, allocated, false /* committed */)); 305 size -= allocated; 306 } 307 } 308 309 void ZPhysicalMemoryManager::free(const ZPhysicalMemory& pmem) { 310 // Free segments 311 for (int i = 0; i < pmem.nsegments(); i++) { 312 const ZPhysicalMemorySegment& segment = pmem.segment(i); 313 _manager.free(segment.start(), segment.size()); 314 } 315 } 316 317 bool ZPhysicalMemoryManager::commit(ZPhysicalMemory& pmem) { 318 // Commit segments 319 for (int i = 0; i < pmem.nsegments(); i++) { 320 const ZPhysicalMemorySegment& segment = pmem.segment(i); 321 if (segment.is_committed()) { 322 // Segment already committed 323 continue; 324 } 325 326 // Commit segment 327 const size_t committed = _backing.commit(segment.start(), segment.size()); 328 if (!pmem.commit_segment(i, committed)) { 329 // Failed or partially failed 330 return false; 331 } 332 } 333 334 // Success 335 return true; 336 } 337 338 bool ZPhysicalMemoryManager::uncommit(ZPhysicalMemory& pmem) { 339 // Commit segments 340 for (int i = 0; i < pmem.nsegments(); i++) { 341 const ZPhysicalMemorySegment& segment = pmem.segment(i); 342 if (!segment.is_committed()) { 343 // Segment already uncommitted 344 continue; 345 } 346 347 // Uncommit segment 348 const size_t uncommitted = _backing.uncommit(segment.start(), segment.size()); 349 if (!pmem.uncommit_segment(i, uncommitted)) { 350 // Failed or partially failed 351 return false; 352 } 353 } 354 355 // Success 356 return true; 357 } 358 359 void ZPhysicalMemoryManager::pretouch_view(uintptr_t addr, size_t size) const { 360 const size_t page_size = ZLargePages::is_explicit() ? ZGranuleSize : os::vm_page_size(); 361 os::pretouch_memory((void*)addr, (void*)(addr + size), page_size); 362 } 363 364 void ZPhysicalMemoryManager::map_view(uintptr_t addr, const ZPhysicalMemory& pmem) const { 365 size_t size = 0; 366 367 // Map segments 368 for (int i = 0; i < pmem.nsegments(); i++) { 369 const ZPhysicalMemorySegment& segment = pmem.segment(i); 370 _backing.map(addr + size, segment.size(), segment.start()); 371 size += segment.size(); 372 } 373 374 // Setup NUMA interleaving for large pages 375 if (ZNUMA::is_enabled() && ZLargePages::is_explicit()) { 376 // To get granule-level NUMA interleaving when using large pages, 377 // we simply let the kernel interleave the memory for us at page 378 // fault time. 379 os::numa_make_global((char*)addr, size); 380 } 381 } 382 383 void ZPhysicalMemoryManager::unmap_view(uintptr_t addr, size_t size) const { 384 _backing.unmap(addr, size); 385 } 386 387 void ZPhysicalMemoryManager::pretouch(uintptr_t offset, size_t size) const { 388 if (ZVerifyViews) { |