Skip to content

Commit

Permalink
src: include large pages source unconditionally
Browse files Browse the repository at this point in the history
Restrict the usage of the C preprocessor directive enabling large
pages support to the large pages implementation. This cleans up the
code in src/node.cc.

Backport-PR-URL: #32092
PR-URL: #31904
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
  • Loading branch information
Gabriel Schulhof authored and targos committed Apr 28, 2020
1 parent 5ea3d60 commit 809d8b5
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 39 deletions.
6 changes: 2 additions & 4 deletions node.gyp
Expand Up @@ -621,6 +621,8 @@
'src/histogram-inl.h',
'src/http_parser_adaptor.h',
'src/js_stream.h',
'src/large_pages/node_large_page.cc',
'src/large_pages/node_large_page.h'
'src/memory_tracker.h',
'src/memory_tracker-inl.h',
'src/module_wrap.h',
Expand Down Expand Up @@ -857,10 +859,6 @@
'target_arch=="x64" and '
'node_target_type=="executable"', {
'defines': [ 'NODE_ENABLE_LARGE_CODE_PAGES=1' ],
'sources': [
'src/large_pages/node_large_page.cc',
'src/large_pages/node_large_page.h'
],
}],
[ 'use_openssl_def==1', {
# TODO(bnoordhuis) Make all platforms export the same list of symbols.
Expand Down
69 changes: 53 additions & 16 deletions src/large_pages/node_large_page.cc
Expand Up @@ -21,6 +21,11 @@
// SPDX-License-Identifier: MIT

#include "node_large_page.h"

#include <cerrno> // NOLINT(build/include)

// Besides returning ENOTSUP at runtime we do nothing if this define is missing.
#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES
#include "util.h"
#include "uv.h"

Expand All @@ -35,7 +40,6 @@
#endif
#include <unistd.h> // readlink

#include <cerrno> // NOLINT(build/include)
#include <climits> // PATH_MAX
#include <clocale>
#include <csignal>
Expand Down Expand Up @@ -71,7 +75,11 @@ extern char __executable_start;
} // extern "C"
#endif // defined(__linux__)

#endif // defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES
namespace node {
#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES

namespace {

struct text_region {
char* from;
Expand Down Expand Up @@ -103,7 +111,7 @@ inline uintptr_t hugepage_align_down(uintptr_t addr) {
// 00400000-00452000 r-xp 00000000 08:02 173521 /usr/bin/dbus-daemon
// This is also handling the case where the first line is not the binary.

static struct text_region FindNodeTextRegion() {
struct text_region FindNodeTextRegion() {
struct text_region nregion;
nregion.found_text_region = false;
#if defined(__linux__)
Expand Down Expand Up @@ -263,7 +271,7 @@ static struct text_region FindNodeTextRegion() {
}

#if defined(__linux__)
static bool IsTransparentHugePagesEnabled() {
bool IsTransparentHugePagesEnabled() {
std::ifstream ifs;

ifs.open("/sys/kernel/mm/transparent_hugepage/enabled");
Expand Down Expand Up @@ -294,6 +302,8 @@ static bool IsSuperPagesEnabled() {
}
#endif

} // End of anonymous namespace

// Moving the text region to large pages. We need to be very careful.
// 1: This function itself should not be moved.
// We use a gcc attributes
Expand Down Expand Up @@ -408,32 +418,59 @@ MoveTextRegionToLargePages(const text_region& r) {
if (-1 == munmap(nmem, size)) PrintSystemError(errno);
return ret;
}
#endif // defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES

// This is the primary API called from main.
int MapStaticCodeToLargePages() {
#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES
bool have_thp = false;
#if defined(__linux__)
have_thp = IsTransparentHugePagesEnabled();
#elif defined(__FreeBSD__)
have_thp = IsSuperPagesEnabled();
#elif defined(__APPLE__)
// pse-36 flag is present in recent mac x64 products.
have_thp = true;
#endif
if (!have_thp)
return EACCES;

struct text_region r = FindNodeTextRegion();
if (r.found_text_region == false) {
PrintWarning("failed to find text region");
return -1;
}
if (r.found_text_region == false)
return ENOENT;

#if defined(__FreeBSD__)
if (r.from < reinterpret_cast<void*>(&MoveTextRegionToLargePages))
return -1;
#endif

return MoveTextRegionToLargePages(r);
#else
return ENOTSUP;
#endif
}

bool IsLargePagesEnabled() {
#if defined(__linux__)
return IsTransparentHugePagesEnabled();
#elif defined(__FreeBSD__)
return IsSuperPagesEnabled();
#elif defined(__APPLE__)
// pse-36 flag is present in recent mac x64 products.
return true;
#endif
const char* LargePagesError(int status) {
switch (status) {
case ENOTSUP:
return "Mapping to large pages is not supported.";

case EACCES:
return "Large pages are not enabled.";

case ENOENT:
return "failed to find text region";

case -1:
return "Mapping code to large pages failed. Reverting to default page "
"size.";

case 0:
return "OK";

default:
return "Unknown error";
}
}

} // namespace node
3 changes: 1 addition & 2 deletions src/large_pages/node_large_page.h
Expand Up @@ -25,10 +25,9 @@

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS


namespace node {
bool IsLargePagesEnabled();
int MapStaticCodeToLargePages();
const char* LargePagesError(int status);
} // namespace node

#endif // NODE_WANT_INTERNALS
Expand Down
20 changes: 3 additions & 17 deletions src/node.cc
Expand Up @@ -65,9 +65,7 @@
#include "inspector/worker_inspector.h" // ParentInspectorHandle
#endif

#ifdef NODE_ENABLE_LARGE_CODE_PAGES
#include "large_pages/node_large_page.h"
#endif

#ifdef NODE_REPORT
#include "node_report.h"
Expand Down Expand Up @@ -891,25 +889,13 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) {
}
}

#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES
if (per_process::cli_options->use_largepages == "on" ||
per_process::cli_options->use_largepages == "silent") {
if (node::IsLargePagesEnabled()) {
if (node::MapStaticCodeToLargePages() != 0 &&
per_process::cli_options->use_largepages != "silent") {
fprintf(stderr,
"Mapping code to large pages failed. Reverting to default page "
"size.\n");
}
} else if (per_process::cli_options->use_largepages != "silent") {
fprintf(stderr, "Large pages are not enabled.\n");
int result = node::MapStaticCodeToLargePages();
if (per_process::cli_options->use_largepages == "on" && result != 0) {
fprintf(stderr, "%s\n", node::LargePagesError(result));
}
}
#else
if (per_process::cli_options->use_largepages == "on") {
fprintf(stderr, "Mapping to large pages is not supported.\n");
}
#endif // NODE_ENABLE_LARGE_CODE_PAGES

if (per_process::cli_options->print_version) {
printf("%s\n", NODE_VERSION);
Expand Down

0 comments on commit 809d8b5

Please sign in to comment.