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:
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)
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
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
89101#include < string>
90102#include < fstream>
91103
92- #if defined(__linux__) || defined(__FreeBSD__)
104+ #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
93105extern " 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__))
337381MoveTextRegionToLargePages(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