30
30
#if defined(__FreeBSD__)
31
31
#include < sys/sysctl.h>
32
32
#include < sys/user.h>
33
+ #elif defined(__APPLE__)
34
+ #include < mach/vm_map.h>
33
35
#endif
34
36
#include < unistd.h> // readlink
35
37
@@ -212,6 +214,42 @@ static struct text_region FindNodeTextRegion() {
212
214
}
213
215
start += cursz;
214
216
}
217
+ #elif defined(__APPLE__)
218
+ struct text_region nregion;
219
+ nregion.found_text_region = false ;
220
+ struct vm_region_submap_info_64 map;
221
+ mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
222
+ vm_address_t addr = 0UL ;
223
+ vm_size_t size = 0 ;
224
+ natural_t depth = 1 ;
225
+
226
+ while (true ) {
227
+ if (vm_region_recurse_64 (mach_task_self (), &addr, &size, &depth,
228
+ reinterpret_cast <vm_region_info_64_t >(&map),
229
+ &count) != KERN_SUCCESS) {
230
+ break ;
231
+ }
232
+
233
+ if (map.is_submap ) {
234
+ depth++;
235
+ } else {
236
+ char * start = reinterpret_cast <char *>(hugepage_align_up (addr));
237
+ char * end = reinterpret_cast <char *>(hugepage_align_down (addr+size));
238
+ size_t esize = end - start;
239
+
240
+ if (end > start && (map.protection & VM_PROT_READ) != 0 &&
241
+ (map.protection & VM_PROT_EXECUTE) != 0 ) {
242
+ nregion.found_text_region = true ;
243
+ nregion.from = start;
244
+ nregion.to = end;
245
+ nregion.total_hugepages = esize / hps;
246
+ break ;
247
+ }
248
+
249
+ addr += size;
250
+ size = 0 ;
251
+ }
252
+ }
215
253
#endif
216
254
return nregion;
217
255
}
@@ -267,11 +305,15 @@ static bool IsSuperPagesEnabled() {
267
305
// 2: This function should not call any function(s) that might be moved.
268
306
// a. map a new area and copy the original code there
269
307
// b. mmap using the start address with MAP_FIXED so we get exactly
270
- // the same virtual address
308
+ // the same virtual address (except on macOS).
271
309
// c. madvise with MADV_HUGE_PAGE
272
310
// d. If successful copy the code there and unmap the original region
273
311
int
312
+ #if !defined(__APPLE__)
274
313
__attribute__ ((__section__(" .lpstub" )))
314
+ #else
315
+ __attribute__ ((__section__(" __TEXT,__lpstub" )))
316
+ #endif
275
317
__attribute__ ((__aligned__(hps)))
276
318
__attribute__ ((__noinline__))
277
319
MoveTextRegionToLargePages (const text_region& r) {
@@ -289,6 +331,9 @@ MoveTextRegionToLargePages(const text_region& r) {
289
331
PrintSystemError (errno);
290
332
return -1 ;
291
333
}
334
+ OnScopeLeave munmap_on_return ([nmem, size]() {
335
+ if (-1 == munmap (nmem, size)) PrintSystemError (errno);
336
+ });
292
337
293
338
memcpy (nmem, r.from , size);
294
339
@@ -302,7 +347,6 @@ MoveTextRegionToLargePages(const text_region& r) {
302
347
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1 , 0 );
303
348
if (tmem == MAP_FAILED) {
304
349
PrintSystemError (errno);
305
- munmap (nmem, size);
306
350
return -1 ;
307
351
}
308
352
@@ -313,11 +357,6 @@ MoveTextRegionToLargePages(const text_region& r) {
313
357
if (ret == -1 ) {
314
358
PrintSystemError (errno);
315
359
}
316
- ret = munmap (nmem, size);
317
- if (ret == -1 ) {
318
- PrintSystemError (errno);
319
- }
320
-
321
360
return -1 ;
322
361
}
323
362
#elif defined(__FreeBSD__)
@@ -327,32 +366,46 @@ MoveTextRegionToLargePages(const text_region& r) {
327
366
MAP_ALIGNED_SUPER, -1 , 0 );
328
367
if (tmem == MAP_FAILED) {
329
368
PrintSystemError (errno);
330
- munmap (nmem, size);
331
369
return -1 ;
332
370
}
333
- #endif
334
-
335
- memcpy (start, nmem, size);
336
- ret = mprotect (start, size, PROT_READ | PROT_EXEC);
371
+ #elif defined(__APPLE__)
372
+ // There is not enough room to reserve the mapping close
373
+ // to the region address so we content to give a hint
374
+ // without forcing the new address being closed to.
375
+ // We explicitally gives all permission since we plan
376
+ // to write into it.
377
+ tmem = mmap (start, size,
378
+ PROT_READ | PROT_WRITE | PROT_EXEC,
379
+ MAP_PRIVATE | MAP_ANONYMOUS,
380
+ VM_FLAGS_SUPERPAGE_SIZE_2MB, 0 );
381
+ if (tmem == MAP_FAILED) {
382
+ PrintSystemError (errno);
383
+ return -1 ;
384
+ }
385
+ memcpy (tmem, nmem, size);
386
+ ret = mprotect (start, size, PROT_READ | PROT_WRITE | PROT_EXEC);
337
387
if (ret == -1 ) {
338
388
PrintSystemError (errno);
339
389
ret = munmap (tmem, size);
340
390
if (ret == -1 ) {
341
391
PrintSystemError (errno);
342
392
}
343
- ret = munmap (nmem, size);
344
- if (ret == -1 ) {
345
- PrintSystemError (errno);
346
- }
347
393
return -1 ;
348
394
}
395
+ memcpy (start, tmem, size);
396
+ #else
397
+ memcpy (start, nmem, size);
398
+ #endif
349
399
350
- // Release the old/temporary mapped region
351
- ret = munmap (nmem, size);
400
+ ret = mprotect (start, size, PROT_READ | PROT_EXEC);
352
401
if (ret == -1 ) {
353
402
PrintSystemError (errno);
403
+ ret = munmap (tmem, size);
404
+ if (ret == -1 ) {
405
+ PrintSystemError (errno);
406
+ }
407
+ return -1 ;
354
408
}
355
-
356
409
return ret;
357
410
}
358
411
@@ -369,16 +422,19 @@ int MapStaticCodeToLargePages() {
369
422
return MoveTextRegionToLargePages (r);
370
423
371
424
return -1 ;
372
- #elif defined(__FreeBSD__)
425
+ #elif defined(__FreeBSD__) || defined(__APPLE__)
373
426
return MoveTextRegionToLargePages (r);
374
427
#endif
375
428
}
376
429
377
430
bool IsLargePagesEnabled () {
378
431
#if defined(__linux__)
379
432
return IsTransparentHugePagesEnabled ();
380
- #else
433
+ #elif defined(__FreeBSD__)
381
434
return IsSuperPagesEnabled ();
435
+ #elif defined(__APPLE__)
436
+ // pse-36 flag is present in recent mac x64 products.
437
+ return true ;
382
438
#endif
383
439
}
384
440
0 commit comments