Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 36.4k
src: large page support for macOS#28977
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -30,6 +30,8 @@ | ||
| #if defined(__FreeBSD__) | ||
| #include <sys/sysctl.h> | ||
| #include <sys/user.h> | ||
| #elif defined(__APPLE__) | ||
| #include <mach/vm_map.h> | ||
| #endif | ||
| #include <unistd.h> // readlink | ||
| @@ -212,6 +214,42 @@ static struct text_region FindNodeTextRegion() { | ||
| } | ||
| start += cursz; | ||
| } | ||
| #elif defined(__APPLE__) | ||
| struct text_region nregion; | ||
| nregion.found_text_region = false; | ||
| struct vm_region_submap_info_64 map; | ||
| mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64; | ||
| vm_address_t addr = 0UL; | ||
| vm_size_t size = 0; | ||
| natural_t depth = 1; | ||
| while (true) { | ||
| if (vm_region_recurse_64(mach_task_self(), &addr, &size, &depth, | ||
| reinterpret_cast<vm_region_info_64_t>(&map), | ||
| &count) != KERN_SUCCESS) { | ||
| break; | ||
| } | ||
| if (map.is_submap) { | ||
| depth++; | ||
| } else { | ||
| char* start = reinterpret_cast<char*>(hugepage_align_up(addr)); | ||
| char* end = reinterpret_cast<char*>(hugepage_align_down(addr+size)); | ||
| size_t esize = end - start; | ||
| if (end > start && (map.protection & VM_PROT_READ) != 0 && | ||
| (map.protection & VM_PROT_EXECUTE) != 0) { | ||
| nregion.found_text_region = true; | ||
| nregion.from = start; | ||
| nregion.to = end; | ||
| nregion.total_hugepages = esize / hps; | ||
| break; | ||
| } | ||
| addr += size; | ||
| size = 0; | ||
| } | ||
| } | ||
| #endif | ||
| return nregion; | ||
| } | ||
| @@ -267,11 +305,15 @@ static bool IsSuperPagesEnabled() { | ||
| // 2: This function should not call any function(s) that might be moved. | ||
| // a. map a new area and copy the original code there | ||
| // b. mmap using the start address with MAP_FIXED so we get exactly | ||
| // the same virtual address | ||
| // the same virtual address (except on macOS). | ||
| // c. madvise with MADV_HUGE_PAGE | ||
| // d. If successful copy the code there and unmap the original region | ||
| int | ||
| #if !defined(__APPLE__) | ||
| __attribute__((__section__(".lpstub"))) | ||
| #else | ||
| __attribute__((__section__("__TEXT,__lpstub"))) | ||
| #endif | ||
| __attribute__((__aligned__(hps))) | ||
| __attribute__((__noinline__)) | ||
| MoveTextRegionToLargePages(const text_region& r) { | ||
| @@ -289,6 +331,9 @@ MoveTextRegionToLargePages(const text_region& r) { | ||
| PrintSystemError(errno); | ||
| return -1; | ||
| } | ||
| OnScopeLeave munmap_on_return([nmem, size]() { | ||
| if (-1 == munmap(nmem, size)) PrintSystemError(errno); | ||
| }); | ||
| memcpy(nmem, r.from, size); | ||
| @@ -302,7 +347,6 @@ MoveTextRegionToLargePages(const text_region& r) { | ||
| MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1 , 0); | ||
| if (tmem == MAP_FAILED) { | ||
| PrintSystemError(errno); | ||
| munmap(nmem, size); | ||
| return -1; | ||
| } | ||
| @@ -313,11 +357,6 @@ MoveTextRegionToLargePages(const text_region& r) { | ||
| if (ret == -1) { | ||
| PrintSystemError(errno); | ||
| } | ||
| ret = munmap(nmem, size); | ||
| if (ret == -1) { | ||
| PrintSystemError(errno); | ||
| } | ||
| return -1; | ||
| } | ||
| #elif defined(__FreeBSD__) | ||
| @@ -327,32 +366,46 @@ MoveTextRegionToLargePages(const text_region& r) { | ||
| MAP_ALIGNED_SUPER, -1 , 0); | ||
| if (tmem == MAP_FAILED) { | ||
| PrintSystemError(errno); | ||
| munmap(nmem, size); | ||
| return -1; | ||
| } | ||
| #endif | ||
| memcpy(start, nmem, size); | ||
| ret = mprotect(start, size, PROT_READ | PROT_EXEC); | ||
| #elif defined(__APPLE__) | ||
| // There is not enough room to reserve the mapping close | ||
| // to the region address so we content to give a hint | ||
| // without forcing the new address being closed to. | ||
| // We explicitally gives all permission since we plan | ||
| // to write into it. | ||
| tmem = mmap(start, size, | ||
| PROT_READ | PROT_WRITE | PROT_EXEC, | ||
| MAP_PRIVATE | MAP_ANONYMOUS, | ||
| VM_FLAGS_SUPERPAGE_SIZE_2MB, 0); | ||
| if (tmem == MAP_FAILED) { | ||
| PrintSystemError(errno); | ||
| return -1; | ||
| } | ||
| memcpy(tmem, nmem, size); | ||
| ret = mprotect(start, size, PROT_READ | PROT_WRITE | PROT_EXEC); | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain why this is necessary? It's already mapped rwx, isn't it? Should the mmap() call include Aside: since there are a lot of nmem = mmap(...);
OnScopeLeave munmap_on_return([nmem, size] () {
if (-1 == munmap(nmem, size)) PrintSystemError(errno);
});I guess you lose the ability to return an error from
| ||
| if (ret == -1) { | ||
| PrintSystemError(errno); | ||
| ret = munmap(tmem, size); | ||
| if (ret == -1) { | ||
| PrintSystemError(errno); | ||
| } | ||
| ret = munmap(nmem, size); | ||
| if (ret == -1) { | ||
| PrintSystemError(errno); | ||
| } | ||
| return -1; | ||
| } | ||
| memcpy(start, tmem, size); | ||
| #else | ||
| memcpy(start, nmem, size); | ||
| #endif | ||
| // Release the old/temporary mapped region | ||
| ret = munmap(nmem, size); | ||
| ret = mprotect(start, size, PROT_READ | PROT_EXEC); | ||
| if (ret == -1) { | ||
| PrintSystemError(errno); | ||
| ret = munmap(tmem, size); | ||
| if (ret == -1) { | ||
| PrintSystemError(errno); | ||
| } | ||
| return -1; | ||
| } | ||
| return ret; | ||
| } | ||
| @@ -369,16 +422,19 @@ int MapStaticCodeToLargePages() { | ||
| return MoveTextRegionToLargePages(r); | ||
| return -1; | ||
| #elif defined(__FreeBSD__) | ||
| #elif defined(__FreeBSD__) || defined(__APPLE__) | ||
| return MoveTextRegionToLargePages(r); | ||
| #endif | ||
| } | ||
| bool IsLargePagesEnabled() { | ||
| #if defined(__linux__) | ||
| return IsTransparentHugePagesEnabled(); | ||
| #else | ||
| #elif defined(__FreeBSD__) | ||
| return IsSuperPagesEnabled(); | ||
| #elif defined(__APPLE__) | ||
| // pse-36 flag is present in recent mac x64 products. | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How recent is recent? Node.js supports macOS 10.11 and up. ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then it is fine El Capitan is recent enough :) | ||
| return true; | ||
| #endif | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.