[vm] Fix running under WSL 1

On WSL 1 trying to allocate memory close to the binary
by supplying a hint fails with ENOMEM for unclear reason.
Some reports suggest that this might be related to the
alignment of the hint but aligning it by 64Kb does not
make the issue go away in our experiments. Instead
just retry without any hint.

Fixes https://github.com/dart-lang/sdk/issues/54587

TEST=manually under WSL 1

Change-Id: I0adf997fbf76e470a57da00f5ce7a26bb50706f7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345802
Commit-Queue: Slava Egorov <vegorov@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
This commit is contained in:
Vyacheslav Egorov 2024-01-11 22:24:44 +00:00 committed by Commit Queue
parent b990bd213d
commit aaca6ce34a
5 changed files with 54 additions and 0 deletions

View file

@ -102,9 +102,21 @@ MappedMemory* File::Map(MapType type,
flags |= MAP_FIXED;
}
void* addr = mmap(hint, length, prot, flags, handle_->fd(), position);
// On WSL 1 trying to allocate memory close to the binary by supplying a hint
// fails with ENOMEM for unclear reason. Some reports suggest that this might
// be related to the alignment of the hint but aligning it by 64Kb does not
// make the issue go away in our experiments. Instead just retry without any
// hint.
if (addr == MAP_FAILED && hint != nullptr && start == nullptr &&
Utils::IsWindowsSubsystemForLinux()) {
addr = mmap(nullptr, length, prot, flags, handle_->fd(), position);
}
if (addr == MAP_FAILED) {
return nullptr;
}
return new MappedMemory(addr, length, /*should_unmap=*/start == nullptr);
}

View file

@ -57,6 +57,17 @@ VirtualMemory* VirtualMemory::Allocate(intptr_t size,
// generated code near the VM binary to avoid this.
void* hint = is_executable ? reinterpret_cast<void*>(&Allocate) : nullptr;
void* address = mmap(hint, size, prot, map_flags, -1, 0);
#if defined(DART_HOST_OS_LINUX)
// On WSL 1 trying to allocate memory close to the binary by supplying a hint
// fails with ENOMEM for unclear reason. Some reports suggest that this might
// be related to the alignment of the hint but aligning it by 64Kb does not
// make the issue go away in our experiments. Instead just retry without any
// hint.
if (address == MAP_FAILED && hint != nullptr &&
Utils::IsWindowsSubsystemForLinux()) {
address = mmap(nullptr, size, prot, map_flags, -1, 0);
}
#endif
if (address == MAP_FAILED) {
return nullptr;
}

View file

@ -672,6 +672,10 @@ class Utils {
// when it is no longer needed).
static void UnloadDynamicLibrary(void* library_handle,
char** error = nullptr);
#if defined(DART_HOST_OS_LINUX)
static bool IsWindowsSubsystemForLinux();
#endif
};
} // namespace dart

View file

@ -5,6 +5,8 @@
#include "platform/globals.h"
#if defined(DART_HOST_OS_LINUX)
#include <sys/utsname.h>
#include "platform/utils.h"
#include "platform/utils_linux.h"
@ -42,13 +44,26 @@ int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
int Utils::Close(int fildes) {
return close(fildes);
}
size_t Utils::Read(int filedes, void* buf, size_t nbyte) {
return read(filedes, buf, nbyte);
}
int Utils::Unlink(const char* path) {
return unlink(path);
}
bool Utils::IsWindowsSubsystemForLinux() {
struct utsname info;
if (uname(&info) != 0) {
return false; // Not sure.
}
// If info.release contains either Microsoft or microsoft then we are
// most likely running under WSL.
return strstr(info.release, "icrosoft") != nullptr;
}
} // namespace dart
#endif // defined(DART_HOST_OS_LINUX)

View file

@ -287,6 +287,18 @@ VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
}
void* address =
GenericMapAligned(hint, prot, size, alignment, allocated_size, map_flags);
#if defined(DART_HOST_OS_LINUX)
// On WSL 1 trying to allocate memory close to the binary by supplying a hint
// fails with ENOMEM for unclear reason. Some reports suggest that this might
// be related to the alignment of the hint but aligning it by 64Kb does not
// make the issue go away in our experiments. Instead just retry without any
// hint.
if (address == nullptr && hint != nullptr &&
Utils::IsWindowsSubsystemForLinux()) {
address = GenericMapAligned(nullptr, prot, size, alignment, allocated_size,
map_flags);
}
#endif
if (address == nullptr) {
return nullptr;
}