Skip to content

Commit c71736e

Browse files
Gabriel Schulhofaddaleax
Gabriel Schulhof
authored andcommitted
src: unify Linux and FreeBSD large pages implem
dl_iterate_phdr(3) is also available for FreeBSD. This change adds the same trimming code for the start and end of the .text section as on Linux, making it work on FreeBSD, and removing the need for the additional FreeBSD-specific check. Manually tested on * https://www.osboxes.org/freebsd/#freebsd-12-1-vbox * https://www.osboxes.org/freebsd/#freebsd-11-vbox * test-digitalocean-freebsd11-x64-2 Signed-off-by: Gabriel Schulhof <[email protected]> PR-URL: #32534 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: David Carlier <[email protected]>
1 parent 06bff18 commit c71736e

File tree

2 files changed

+37
-75
lines changed

2 files changed

+37
-75
lines changed

node.gyp

+2-2
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@
322322
'target_name': 'node_text_start',
323323
'type': 'none',
324324
'conditions': [
325-
[ 'OS=="linux" and '
325+
[ 'OS in "linux freebsd" and '
326326
'target_arch=="x64"', {
327327
'type': 'static_library',
328328
'sources': [
@@ -511,7 +511,7 @@
511511
'src/node_snapshot_stub.cc'
512512
],
513513
}],
514-
[ 'OS=="linux" and '
514+
[ 'OS in "linux freebsd" and '
515515
'target_arch=="x64"', {
516516
'dependencies': [ 'node_text_start' ],
517517
'ldflags+': [

src/large_pages/node_large_page.cc

+35-73
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@
3030
#include "util.h"
3131
#include "uv.h"
3232

33+
#if defined(__linux__) || defined(__FreeBSD__)
34+
#include <string.h>
3335
#if defined(__linux__)
3436
#ifndef _GNU_SOURCE
3537
#define _GNU_SOURCE
36-
#endif
38+
#endif // ifndef _GNU_SOURCE
39+
#endif // defined(__linux__)
3740
#include <link.h>
38-
#endif
41+
#endif // defined(__linux__) || defined(__FreeBSD__)
42+
3943
#include <sys/types.h>
4044
#include <sys/mman.h>
4145
#if defined(__FreeBSD__)
@@ -73,15 +77,15 @@
7377
// Use madvise with MADV_HUGEPAGE to use Anonymous 2M Pages
7478
// If successful copy the code there and unmap the original region.
7579

76-
#if defined(__linux__)
80+
#if defined(__linux__) || defined(__FreeBSD__)
7781
extern "C" {
7882
// This symbol must be declared weak because this file becomes part of all
7983
// Node.js targets (like node_mksnapshot, node_mkcodecache, and cctest) and
8084
// those files do not supply the symbol.
8185
extern char __attribute__((weak)) __node_text_start;
8286
extern char __start_lpstub;
8387
} // extern "C"
84-
#endif // defined(__linux__)
88+
#endif // defined(__linux__) || defined(__FreeBSD__)
8589

8690
#endif // defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES
8791
namespace node {
@@ -121,19 +125,26 @@ inline uintptr_t hugepage_align_down(uintptr_t addr) {
121125
return ((addr) & ~((hps) - 1));
122126
}
123127

128+
#if defined(__linux__) || defined(__FreeBSD__)
129+
#if defined(__FreeBSD__)
130+
#ifndef ElfW
131+
#define ElfW(name) Elf_##name
132+
#endif // ifndef ElfW
133+
#endif // defined(__FreeBSD__)
134+
124135
struct dl_iterate_params {
125136
uintptr_t start;
126137
uintptr_t end;
127138
uintptr_t reference_sym;
139+
std::string exename;
128140
};
129141

130-
#if defined(__linux__)
131142
int FindMapping(struct dl_phdr_info* info, size_t, void* data) {
132-
if (info->dlpi_name[0] == 0) {
143+
auto dl_params = static_cast<dl_iterate_params*>(data);
144+
if (dl_params->exename == std::string(info->dlpi_name)) {
133145
for (int idx = 0; idx < info->dlpi_phnum; idx++) {
134146
const ElfW(Phdr)* phdr = &info->dlpi_phdr[idx];
135147
if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) {
136-
auto dl_params = static_cast<dl_iterate_params*>(data);
137148
uintptr_t start = info->dlpi_addr + phdr->p_vaddr;
138149
uintptr_t end = start + phdr->p_memsz;
139150

@@ -148,17 +159,30 @@ int FindMapping(struct dl_phdr_info* info, size_t, void* data) {
148159
}
149160
return 0;
150161
}
151-
#endif // defined(__linux__)
162+
#endif // defined(__linux__) || defined(__FreeBSD__)
152163

153164
struct text_region FindNodeTextRegion() {
154165
struct text_region nregion;
155166
nregion.found_text_region = false;
156-
#if defined(__linux__)
167+
#if defined(__linux__) || defined(__FreeBSD__)
157168
dl_iterate_params dl_params = {
158-
0, 0, reinterpret_cast<uintptr_t>(&__node_text_start)
169+
0, 0, reinterpret_cast<uintptr_t>(&__node_text_start), ""
159170
};
160171
uintptr_t lpstub_start = reinterpret_cast<uintptr_t>(&__start_lpstub);
161172

173+
#if defined(__FreeBSD__)
174+
// On FreeBSD we need the name of the binary, because `dl_iterate_phdr` does
175+
// not pass in an empty string as the `dlpi_name` of the binary but rather its
176+
// absolute path.
177+
{
178+
char selfexe[PATH_MAX];
179+
size_t count = sizeof(selfexe);
180+
if (uv_exepath(selfexe, &count))
181+
return nregion;
182+
dl_params.exename = std::string(selfexe, count);
183+
}
184+
#endif // defined(__FreeBSD__)
185+
162186
if (dl_iterate_phdr(FindMapping, &dl_params) == 1) {
163187
Debug("Hugepages info: start: %p - sym: %p - end: %p\n",
164188
reinterpret_cast<void*>(dl_params.start),
@@ -187,62 +211,6 @@ struct text_region FindNodeTextRegion() {
187211
}
188212
}
189213
}
190-
#elif defined(__FreeBSD__)
191-
std::string exename;
192-
{
193-
char selfexe[PATH_MAX];
194-
size_t count = sizeof(selfexe);
195-
if (uv_exepath(selfexe, &count))
196-
return nregion;
197-
198-
exename = std::string(selfexe, count);
199-
}
200-
201-
size_t numpg;
202-
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()};
203-
const size_t miblen = arraysize(mib);
204-
if (sysctl(mib, miblen, nullptr, &numpg, nullptr, 0) == -1) {
205-
return nregion;
206-
}
207-
208-
// Enough for struct kinfo_vmentry.
209-
numpg = numpg * 4 / 3;
210-
auto alg = std::vector<char>(numpg);
211-
212-
if (sysctl(mib, miblen, alg.data(), &numpg, nullptr, 0) == -1) {
213-
return nregion;
214-
}
215-
216-
char* start = alg.data();
217-
char* end = start + numpg;
218-
219-
while (start < end) {
220-
kinfo_vmentry* entry = reinterpret_cast<kinfo_vmentry*>(start);
221-
const size_t cursz = entry->kve_structsize;
222-
if (cursz == 0) {
223-
break;
224-
}
225-
226-
if (entry->kve_path[0] == '\0') {
227-
continue;
228-
}
229-
bool excmapping = ((entry->kve_protection & KVME_PROT_READ) &&
230-
(entry->kve_protection & KVME_PROT_EXEC));
231-
232-
if (!strcmp(exename.c_str(), entry->kve_path) && excmapping) {
233-
char* estart =
234-
reinterpret_cast<char*>(hugepage_align_up(entry->kve_start));
235-
char* eend =
236-
reinterpret_cast<char*>(hugepage_align_down(entry->kve_end));
237-
size_t size = eend - estart;
238-
nregion.found_text_region = true;
239-
nregion.from = estart;
240-
nregion.to = eend;
241-
nregion.total_hugepages = size / hps;
242-
break;
243-
}
244-
start += cursz;
245-
}
246214
#elif defined(__APPLE__)
247215
struct vm_region_submap_info_64 map;
248216
mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
@@ -349,13 +317,11 @@ MoveTextRegionToLargePages(const text_region& r) {
349317
PrintSystemError(errno);
350318
});
351319

352-
#if !defined (__FreeBSD__)
353320
// Allocate temporary region and back up the code we will re-map.
354321
nmem = mmap(nullptr, size,
355322
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
356323
if (nmem == MAP_FAILED) goto fail;
357324
memcpy(nmem, r.from, size);
358-
#endif
359325

360326
#if defined(__linux__)
361327
// We already know the original page is r-xp
@@ -374,6 +340,7 @@ MoveTextRegionToLargePages(const text_region& r) {
374340
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED |
375341
MAP_ALIGNED_SUPER, -1 , 0);
376342
if (tmem == MAP_FAILED) goto fail;
343+
memcpy(start, nmem, size);
377344
#elif defined(__APPLE__)
378345
// There is not enough room to reserve the mapping close
379346
// to the region address so we content to give a hint
@@ -420,11 +387,6 @@ int MapStaticCodeToLargePages() {
420387
if (r.found_text_region == false)
421388
return ENOENT;
422389

423-
#if defined(__FreeBSD__)
424-
if (r.from < reinterpret_cast<void*>(&MoveTextRegionToLargePages))
425-
return -1;
426-
#endif
427-
428390
return MoveTextRegionToLargePages(r);
429391
#else
430392
return ENOTSUP;

0 commit comments

Comments
 (0)