Skip to content

zend alloc large page support for win(64) proposal. #8405

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion Zend/zend_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ static size_t _real_page_size = ZEND_MM_PAGE_SIZE;
# ifdef MAP_ALIGNED_SUPER
# define MAP_HUGETLB MAP_ALIGNED_SUPER
# endif
#else
static zend_long minlgsz = -1;
#endif

#ifndef REAL_PAGE_SIZE
Expand Down Expand Up @@ -452,7 +454,18 @@ static void *zend_mm_mmap_fixed(void *addr, size_t size)
static void *zend_mm_mmap(size_t size)
{
#ifdef _WIN32
void *ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
void *ptr;
#ifdef _WIN64
// For now enabling only for 64 bits, seems more costly than benefitial otherwise
// ZEND_MM_CHUNK_SIZE being the minimum large page size too.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure about this? Don't we need to check GetLargePageMinimum()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did in a small app, x86 64 supports 2MB and 1GB and GetLargePageMinimum returns the former.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but doesn't this depend on the processor? What if a processor doesn't support large pages at all, or requires a larger size than 2MiB (ZEND_MM_CHUNK_SIZE)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point I ll add a check.

if (zend_mm_use_huge_pages && minlgsz == ZEND_MM_CHUNK_SIZE && size == ZEND_MM_CHUNK_SIZE) {
ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE);
if (ptr != NULL) {
return ptr;
}
}
#endif
ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

if (ptr == NULL) {
#if ZEND_MM_ERROR
Expand Down Expand Up @@ -2901,6 +2914,35 @@ ZEND_API void start_memory_manager(void)
# elif defined(_SC_PAGE_SIZE)
REAL_PAGE_SIZE = sysconf(_SC_PAGE_SIZE);
# endif
#else
HANDLE token;
DWORD err;
BOOL r;
TOKEN_PRIVILEGES priv = {0};
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
stderr_last_error("Can't access process token");
return;
}

if (!LookupPrivilegeValueA(NULL, "SeLockMemoryPrivilege", &priv.Privileges[0].Luid)) {
CloseHandle(token);
stderr_last_error("Can't access privilege lookup");
return;
}

priv.PrivilegeCount = 1;
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

r = AdjustTokenPrivileges(token, FALSE, &priv, sizeof(priv), NULL, 0);
err = GetLastError();

if (!r || err != ERROR_SUCCESS) {
CloseHandle(token);
return;
}

CloseHandle(token);
minlgsz = (zend_long)GetLargePageMinimum();
#endif
}

Expand Down