@@ -2831,6 +2831,16 @@ void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec,
2831
2831
#define MADV_HUGEPAGE 14
2832
2832
#endif
2833
2833
2834
+ // Note that the value for MAP_FIXED_NOREPLACE differs between architectures, but all architectures
2835
+ // supported by OpenJDK share the same flag value.
2836
+ #define MAP_FIXED_NOREPLACE_value 0x100000
2837
+ #ifndef MAP_FIXED_NOREPLACE
2838
+ #define MAP_FIXED_NOREPLACE MAP_FIXED_NOREPLACE_value
2839
+ #else
2840
+ // Sanity-check our assumed default value if we build with a new enough libc.
2841
+ static_assert (MAP_FIXED_NOREPLACE == MAP_FIXED_NOREPLACE_value);
2842
+ #endif
2843
+
2834
2844
int os::Linux::commit_memory_impl (char * addr, size_t size,
2835
2845
size_t alignment_hint, bool exec) {
2836
2846
int err = os::Linux::commit_memory_impl (addr, size, exec);
@@ -3471,8 +3481,23 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) {
3471
3481
// may not start from the requested address. Unlike Linux mmap(), this
3472
3482
// function returns null to indicate failure.
3473
3483
static char * anon_mmap (char * requested_addr, size_t bytes) {
3474
- // MAP_FIXED is intentionally left out, to leave existing mappings intact.
3475
- const int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS;
3484
+ // If a requested address was given:
3485
+ //
3486
+ // The POSIX-conforming way is to *omit* MAP_FIXED. This will leave existing mappings intact.
3487
+ // If the requested mapping area is blocked by a pre-existing mapping, the kernel will map
3488
+ // somewhere else. On Linux, that alternative address appears to have no relation to the
3489
+ // requested address.
3490
+ // Unfortunately, this is not what we need - if we requested a specific address, we'd want
3491
+ // to map there and nowhere else. Therefore we will unmap the block again, which means we
3492
+ // just executed a needless mmap->munmap cycle.
3493
+ // Since Linux 4.17, the kernel offers MAP_FIXED_NOREPLACE. With this flag, if a pre-
3494
+ // existing mapping exists, the kernel will not map at an alternative point but instead
3495
+ // return an error. We can therefore save that unnecessary mmap-munmap cycle.
3496
+ //
3497
+ // Backward compatibility: Older kernels will ignore the unknown flag; so mmap will behave
3498
+ // as in mode (a).
3499
+ const int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS |
3500
+ ((requested_addr != nullptr ) ? MAP_FIXED_NOREPLACE : 0 );
3476
3501
3477
3502
// Map reserved/uncommitted pages PROT_NONE so we fail early if we
3478
3503
// touch an uncommitted page. Otherwise, the read/write might
@@ -4212,6 +4237,7 @@ char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool
4212
4237
4213
4238
if (addr != nullptr ) {
4214
4239
// mmap() is successful but it fails to reserve at the requested address
4240
+ log_trace (os, map)(" Kernel rejected " PTR_FORMAT " , offered " PTR_FORMAT " ." , p2i (requested_addr), p2i (addr));
4215
4241
anon_munmap (addr, bytes);
4216
4242
}
4217
4243
0 commit comments