30
30
#include " util.h"
31
31
#include " uv.h"
32
32
33
+ #if defined(__linux__) || defined(__FreeBSD__)
34
+ #include < string.h>
33
35
#if defined(__linux__)
34
36
#ifndef _GNU_SOURCE
35
37
#define _GNU_SOURCE
36
- #endif
38
+ #endif // ifndef _GNU_SOURCE
39
+ #endif // defined(__linux__)
37
40
#include < link.h>
38
- #endif
41
+ #endif // defined(__linux__) || defined(__FreeBSD__)
42
+
39
43
#include < sys/types.h>
40
44
#include < sys/mman.h>
41
45
#if defined(__FreeBSD__)
73
77
// Use madvise with MADV_HUGEPAGE to use Anonymous 2M Pages
74
78
// If successful copy the code there and unmap the original region.
75
79
76
- #if defined(__linux__)
80
+ #if defined(__linux__) || defined(__FreeBSD__)
77
81
extern " C" {
78
82
// This symbol must be declared weak because this file becomes part of all
79
83
// Node.js targets (like node_mksnapshot, node_mkcodecache, and cctest) and
80
84
// those files do not supply the symbol.
81
85
extern char __attribute__ ((weak)) __node_text_start;
82
86
extern char __start_lpstub;
83
87
} // extern "C"
84
- #endif // defined(__linux__)
88
+ #endif // defined(__linux__) || defined(__FreeBSD__)
85
89
86
90
#endif // defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES
87
91
namespace node {
@@ -121,19 +125,26 @@ inline uintptr_t hugepage_align_down(uintptr_t addr) {
121
125
return ((addr) & ~((hps) - 1 ));
122
126
}
123
127
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
+
124
135
struct dl_iterate_params {
125
136
uintptr_t start;
126
137
uintptr_t end;
127
138
uintptr_t reference_sym;
139
+ std::string exename;
128
140
};
129
141
130
- #if defined(__linux__)
131
142
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 )) {
133
145
for (int idx = 0 ; idx < info->dlpi_phnum ; idx++) {
134
146
const ElfW (Phdr)* phdr = &info->dlpi_phdr [idx];
135
147
if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) {
136
- auto dl_params = static_cast <dl_iterate_params*>(data);
137
148
uintptr_t start = info->dlpi_addr + phdr->p_vaddr ;
138
149
uintptr_t end = start + phdr->p_memsz ;
139
150
@@ -148,17 +159,30 @@ int FindMapping(struct dl_phdr_info* info, size_t, void* data) {
148
159
}
149
160
return 0 ;
150
161
}
151
- #endif // defined(__linux__)
162
+ #endif // defined(__linux__) || defined(__FreeBSD__)
152
163
153
164
struct text_region FindNodeTextRegion () {
154
165
struct text_region nregion;
155
166
nregion.found_text_region = false ;
156
- #if defined(__linux__)
167
+ #if defined(__linux__) || defined(__FreeBSD__)
157
168
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), " "
159
170
};
160
171
uintptr_t lpstub_start = reinterpret_cast <uintptr_t >(&__start_lpstub);
161
172
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
+
162
186
if (dl_iterate_phdr (FindMapping, &dl_params) == 1 ) {
163
187
Debug (" Hugepages info: start: %p - sym: %p - end: %p\n " ,
164
188
reinterpret_cast <void *>(dl_params.start ),
@@ -187,62 +211,6 @@ struct text_region FindNodeTextRegion() {
187
211
}
188
212
}
189
213
}
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
- }
246
214
#elif defined(__APPLE__)
247
215
struct vm_region_submap_info_64 map;
248
216
mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
@@ -349,13 +317,11 @@ MoveTextRegionToLargePages(const text_region& r) {
349
317
PrintSystemError (errno);
350
318
});
351
319
352
- #if !defined (__FreeBSD__)
353
320
// Allocate temporary region and back up the code we will re-map.
354
321
nmem = mmap (nullptr , size,
355
322
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1 , 0 );
356
323
if (nmem == MAP_FAILED) goto fail;
357
324
memcpy (nmem, r.from , size);
358
- #endif
359
325
360
326
#if defined(__linux__)
361
327
// We already know the original page is r-xp
@@ -374,6 +340,7 @@ MoveTextRegionToLargePages(const text_region& r) {
374
340
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED |
375
341
MAP_ALIGNED_SUPER, -1 , 0 );
376
342
if (tmem == MAP_FAILED) goto fail;
343
+ memcpy (start, nmem, size);
377
344
#elif defined(__APPLE__)
378
345
// There is not enough room to reserve the mapping close
379
346
// to the region address so we content to give a hint
@@ -420,11 +387,6 @@ int MapStaticCodeToLargePages() {
420
387
if (r.found_text_region == false )
421
388
return ENOENT;
422
389
423
- #if defined(__FreeBSD__)
424
- if (r.from < reinterpret_cast <void *>(&MoveTextRegionToLargePages))
425
- return -1 ;
426
- #endif
427
-
428
390
return MoveTextRegionToLargePages (r);
429
391
#else
430
392
return ENOTSUP;
0 commit comments