Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: large pages support for illumos/solaris systems. #34320

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions node.gyp
Original file line number Diff line number Diff line change
@@ -336,7 +336,7 @@
'target_name': 'node_text_start',
'type': 'none',
'conditions': [
[ 'OS in "linux freebsd" and '
[ 'OS in "linux freebsd solaris" and '
'target_arch=="x64"', {
'type': 'static_library',
'sources': [
@@ -906,7 +906,7 @@
'src/tls_wrap.h'
],
}],
[ 'OS in "linux freebsd mac" and '
[ 'OS in "linux freebsd mac solaris" and '
'target_arch=="x64" and '
'node_target_type=="executable"', {
'defines': [ 'NODE_ENABLE_LARGE_CODE_PAGES=1' ],
81 changes: 73 additions & 8 deletions src/large_pages/node_large_page.cc
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@
// We use gcc attributes
// (__section__) to put it outside the `.text` section,
// (__aligned__) to align it at the 2M boundary, and
// (__noline__) to not inline this function.
// (__noinline__) to not inline this function.
// b) `MoveTextRegionToLargePages` should not call any function(s) that might
// be moved.
// To move the .text section, perform the following steps:
@@ -55,6 +55,14 @@
// be readable and executable.
// * Unmap the temporary area.

#if defined(__sun)
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE // to access older memory mapping api
#endif
typedef char* maptype;
#else
typedef void* maptype;
#endif
#include "node_large_page.h"

#include <cerrno> // NOLINT(build/include)
@@ -63,7 +71,7 @@
#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES
#include "debug_utils-inl.h"

#if defined(__linux__) || defined(__FreeBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
#if defined(__linux__)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@@ -72,14 +80,18 @@
#include "uv.h" // uv_exepath
#endif // defined(__linux__)
#include <link.h>
#endif // defined(__linux__) || defined(__FreeBSD__)
#endif // defined(__linux__) || defined(__FreeBSD__) || defined(__sun)

#include <sys/types.h>
#include <sys/mman.h>
#if defined(__FreeBSD__)
#include <sys/sysctl.h>
#elif defined(__APPLE__)
#include <mach/vm_map.h>
#elif defined(__sun)
#define _STRUCTURED_PROC 1 // to get proper mapping types
#include <sys/procfs.h> // pr*map structs
#include <unistd.h>
#endif

#include <climits> // PATH_MAX
@@ -89,7 +101,7 @@
#include <string>
#include <fstream>

#if defined(__linux__) || defined(__FreeBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
extern "C" {
// This symbol must be declared weak because this file becomes part of all
// Node.js targets (like node_mksnapshot, node_mkcodecache, and cctest) and
@@ -251,6 +263,38 @@ struct text_region FindNodeTextRegion() {
size = 0;
}
}
#elif defined(__sun)
auto size = 1 << 20;
auto fd = open("/proc/self/map", O_RDONLY);

if (fd != -1) {
ssize_t r;
prmap_t* cur, * map;
std::unique_ptr<char[]> pm = std::unique_ptr<char[]>(new char[size]);

while ((r = pread(fd, pm.get(), size, 0)) == size) {
size <<= 1;
pm.reset(new char[size]);
}

close(fd);

map = reinterpret_cast<prmap_t*>(pm.get());
for (cur = map; r > 0; cur++, r -= sizeof(prmap_t)) {
auto estart = cur->pr_vaddr;
auto eend = estart + cur->pr_size;
char* start = reinterpret_cast<char*>(hugepage_align_up(estart));
char* end = reinterpret_cast<char*>(hugepage_align_down(eend));

if (end > start && (cur->pr_mflags & MA_READ) != 0 &&
(cur->pr_mflags & MA_EXEC) != 0) {
nregion.found_text_region = true;
nregion.from = start;
nregion.to = end;
break;
}
}
}
#endif
Debug("Found %d huge pages\n", (nregion.to - nregion.from) / hps);
return nregion;
@@ -294,12 +338,12 @@ class MemoryMapPointer {
public:
FORCE_INLINE explicit MemoryMapPointer() {}
FORCE_INLINE bool operator==(void* rhs) const { return mem_ == rhs; }
FORCE_INLINE void* mem() const { return mem_; }
FORCE_INLINE maptype mem() const { return mem_; }
MemoryMapPointer(const MemoryMapPointer&) = delete;
MemoryMapPointer(MemoryMapPointer&&) = delete;
void operator= (const MemoryMapPointer&) = delete;
void operator= (const MemoryMapPointer&&) = delete;
FORCE_INLINE void Reset(void* start,
FORCE_INLINE void Reset(maptype start,
size_t size,
int prot,
int flags,
@@ -321,7 +365,7 @@ class MemoryMapPointer {

private:
size_t size_ = 0;
void* mem_ = nullptr;
maptype mem_ = nullptr;
};

} // End of anonymous namespace
@@ -337,7 +381,7 @@ __attribute__((__noinline__))
MoveTextRegionToLargePages(const text_region& r) {
MemoryMapPointer nmem;
MemoryMapPointer tmem;
void* start = r.from;
maptype start = r.from;
size_t size = r.to - r.from;

// Allocate a temporary region and back up the code we will re-map.
@@ -364,6 +408,25 @@ MoveTextRegionToLargePages(const text_region& r) {
MAP_ALIGNED_SUPER);
if (tmem.mem() == MAP_FAILED) goto fail;
memcpy(start, nmem.mem(), size);
#elif defined(__sun)
// MAP_ALIGN takes start as a hint and is
// therefore mutually exclusive with MAP_FIXED
// We map, gives write permission.
memcntl_mha mha;
mha.mha_flags = 0;
mha.mha_pagesize = hps;
mha.mha_cmd = MHA_MAPSIZE_VA;
tmem.Reset(start, size,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGN);
if (tmem.mem() == MAP_FAILED) goto fail;
memcpy(tmem.mem(), nmem.mem(), size);
if (mprotect(start, size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
goto fail;
if (memcntl((caddr_t)tmem.mem(), size,
MC_HAT_ADVISE, (caddr_t)&mha, 0, 0) == -1)
goto fail;
memcpy(start, tmem.mem(), size);
#elif defined(__APPLE__)
// There is not enough room to reserve the mapping close
// to the region address so we content to give a hint
@@ -400,6 +463,8 @@ int MapStaticCodeToLargePages() {
have_thp = IsTransparentHugePagesEnabled();
#elif defined(__FreeBSD__)
have_thp = IsSuperPagesEnabled();
#elif defined(__sun)
have_thp = true;
#elif defined(__APPLE__)
// pse-36 flag is present in recent mac x64 products.
have_thp = true;