Skip to content

Commit 68c5d50

Browse files
committed
src: large pages support for illumos/solaris systems.
* Making sure using apis supported by both.
1 parent ac6ecd6 commit 68c5d50

File tree

2 files changed

+75
-10
lines changed

2 files changed

+75
-10
lines changed

node.gyp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@
336336
'target_name': 'node_text_start',
337337
'type': 'none',
338338
'conditions': [
339-
[ 'OS in "linux freebsd" and '
339+
[ 'OS in "linux freebsd solaris" and '
340340
'target_arch=="x64"', {
341341
'type': 'static_library',
342342
'sources': [
@@ -906,7 +906,7 @@
906906
'src/tls_wrap.h'
907907
],
908908
}],
909-
[ 'OS in "linux freebsd mac" and '
909+
[ 'OS in "linux freebsd mac solaris" and '
910910
'target_arch=="x64" and '
911911
'node_target_type=="executable"', {
912912
'defines': [ 'NODE_ENABLE_LARGE_CODE_PAGES=1' ],

src/large_pages/node_large_page.cc

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
// We use gcc attributes
4343
// (__section__) to put it outside the `.text` section,
4444
// (__aligned__) to align it at the 2M boundary, and
45-
// (__noline__) to not inline this function.
45+
// (__noinline__) to not inline this function.
4646
// b) `MoveTextRegionToLargePages` should not call any function(s) that might
4747
// be moved.
4848
// To move the .text section, perform the following steps:
@@ -55,6 +55,14 @@
5555
// be readable and executable.
5656
// * Unmap the temporary area.
5757

58+
#if defined(__sun)
59+
#ifdef _XOPEN_SOURCE
60+
#undef _XOPEN_SOURCE // to access older memory mapping api
61+
#endif
62+
typedef char* maptype;
63+
#else
64+
typedef void* maptype;
65+
#endif
5866
#include "node_large_page.h"
5967

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

66-
#if defined(__linux__) || defined(__FreeBSD__)
74+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
6775
#if defined(__linux__)
6876
#ifndef _GNU_SOURCE
6977
#define _GNU_SOURCE
@@ -72,14 +80,18 @@
7280
#include "uv.h" // uv_exepath
7381
#endif // defined(__linux__)
7482
#include <link.h>
75-
#endif // defined(__linux__) || defined(__FreeBSD__)
83+
#endif // defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
7684

7785
#include <sys/types.h>
7886
#include <sys/mman.h>
7987
#if defined(__FreeBSD__)
8088
#include <sys/sysctl.h>
8189
#elif defined(__APPLE__)
8290
#include <mach/vm_map.h>
91+
#elif defined(__sun)
92+
#define _STRUCTURED_PROC 1 // to get proper mapping types
93+
#include <sys/procfs.h> // pr*map structs
94+
#include <unistd.h>
8395
#endif
8496

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

92-
#if defined(__linux__) || defined(__FreeBSD__)
104+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
93105
extern "C" {
94106
// This symbol must be declared weak because this file becomes part of all
95107
// Node.js targets (like node_mksnapshot, node_mkcodecache, and cctest) and
@@ -251,6 +263,38 @@ struct text_region FindNodeTextRegion() {
251263
size = 0;
252264
}
253265
}
266+
#elif defined(__sun)
267+
auto size = 1 << 20;
268+
auto fd = open("/proc/self/map", O_RDONLY);
269+
270+
if (fd != -1) {
271+
ssize_t r;
272+
prmap_t* cur, * map;
273+
std::unique_ptr<char[]> pm = std::unique_ptr<char[]>(new char[size]);
274+
275+
while ((r = pread(fd, pm.get(), size, 0)) == size) {
276+
size <<= 1;
277+
pm.reset(new char[size]);
278+
}
279+
280+
close(fd);
281+
282+
map = reinterpret_cast<prmap_t*>(pm.get());
283+
for (cur = map; r > 0; cur++, r -= sizeof(prmap_t)) {
284+
auto estart = cur->pr_vaddr;
285+
auto eend = estart + cur->pr_size;
286+
char* start = reinterpret_cast<char*>(hugepage_align_up(estart));
287+
char* end = reinterpret_cast<char*>(hugepage_align_down(eend));
288+
289+
if (end > start && (cur->pr_mflags & MA_READ) != 0 &&
290+
(cur->pr_mflags & MA_EXEC) != 0) {
291+
nregion.found_text_region = true;
292+
nregion.from = start;
293+
nregion.to = end;
294+
break;
295+
}
296+
}
297+
}
254298
#endif
255299
Debug("Found %d huge pages\n", (nregion.to - nregion.from) / hps);
256300
return nregion;
@@ -294,12 +338,12 @@ class MemoryMapPointer {
294338
public:
295339
FORCE_INLINE explicit MemoryMapPointer() {}
296340
FORCE_INLINE bool operator==(void* rhs) const { return mem_ == rhs; }
297-
FORCE_INLINE void* mem() const { return mem_; }
341+
FORCE_INLINE maptype mem() const { return mem_; }
298342
MemoryMapPointer(const MemoryMapPointer&) = delete;
299343
MemoryMapPointer(MemoryMapPointer&&) = delete;
300344
void operator= (const MemoryMapPointer&) = delete;
301345
void operator= (const MemoryMapPointer&&) = delete;
302-
FORCE_INLINE void Reset(void* start,
346+
FORCE_INLINE void Reset(maptype start,
303347
size_t size,
304348
int prot,
305349
int flags,
@@ -321,7 +365,7 @@ class MemoryMapPointer {
321365

322366
private:
323367
size_t size_ = 0;
324-
void* mem_ = nullptr;
368+
maptype mem_ = nullptr;
325369
};
326370

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

343387
// Allocate a temporary region and back up the code we will re-map.
@@ -364,6 +408,25 @@ MoveTextRegionToLargePages(const text_region& r) {
364408
MAP_ALIGNED_SUPER);
365409
if (tmem.mem() == MAP_FAILED) goto fail;
366410
memcpy(start, nmem.mem(), size);
411+
#elif defined(__sun)
412+
// MAP_ALIGN takes start as a hint and is
413+
// therefore mutually exclusive with MAP_FIXED
414+
// We map, gives write permission.
415+
memcntl_mha mha;
416+
mha.mha_flags = 0;
417+
mha.mha_pagesize = hps;
418+
mha.mha_cmd = MHA_MAPSIZE_VA;
419+
tmem.Reset(start, size,
420+
PROT_READ | PROT_WRITE | PROT_EXEC,
421+
MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGN);
422+
if (tmem.mem() == MAP_FAILED) goto fail;
423+
memcpy(tmem.mem(), nmem.mem(), size);
424+
if (mprotect(start, size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
425+
goto fail;
426+
if (memcntl((caddr_t)tmem.mem(), size,
427+
MC_HAT_ADVISE, (caddr_t)&mha, 0, 0) == -1)
428+
goto fail;
429+
memcpy(start, tmem.mem(), size);
367430
#elif defined(__APPLE__)
368431
// There is not enough room to reserve the mapping close
369432
// to the region address so we content to give a hint
@@ -400,6 +463,8 @@ int MapStaticCodeToLargePages() {
400463
have_thp = IsTransparentHugePagesEnabled();
401464
#elif defined(__FreeBSD__)
402465
have_thp = IsSuperPagesEnabled();
466+
#elif defined(__sun)
467+
have_thp = true;
403468
#elif defined(__APPLE__)
404469
// pse-36 flag is present in recent mac x64 products.
405470
have_thp = true;

0 commit comments

Comments
 (0)