diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c index 0ff2c7e..cf76323 100644 --- a/src/backend/port/win32_shmem.c +++ b/src/backend/port/win32_shmem.c @@ -103,6 +103,33 @@ PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2) return true; } +/* + * Try to acquire SeLockMemoryPrivilege so we can use large pages if we + * haven't already. + */ +static bool +check_privilege(void) +{ + static bool first_time = true; + static bool result; + HANDLE hToken; + TOKEN_PRIVILEGES tp; + DWORD error; + + if (!first_time) + return result; + + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); + LookupPrivilegeValue(NULL, TEXT("SeLockMemoryPrivilege"), &tp.Privileges[0].Luid); + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + result = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0); + error = GetLastError(); + CloseHandle(hToken); + + first_time = false; + return result; +} /* * PGSharedMemoryCreate @@ -128,11 +155,6 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port, DWORD size_high; DWORD size_low; - if (huge_pages == HUGE_PAGES_ON) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("huge pages not supported on this platform"))); - /* Room for a header? */ Assert(size > MAXALIGN(sizeof(PGShmemHeader))); @@ -140,6 +162,15 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port, UsedShmemSegAddr = NULL; + if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY) + { + size_t hugepagesize = GetLargePageMinimum(); + + /* Round size up as appropriate. */ + if (size % hugepagesize != 0) + size += hugepagesize - (size % hugepagesize); + } + #ifdef _WIN64 size_high = size >> 32; #else @@ -161,12 +192,34 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port, */ SetLastError(0); - hmap = CreateFileMapping(INVALID_HANDLE_VALUE, /* Use the pagefile */ - NULL, /* Default security attrs */ - PAGE_READWRITE, /* Memory is Read/Write */ - size_high, /* Size Upper 32 Bits */ - size_low, /* Size Lower 32 bits */ - szShareMem); + if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY) + { + if (check_privilege()) + hmap = CreateFileMapping(INVALID_HANDLE_VALUE, /* Use the pagefile */ + NULL, /* Default security attrs */ + /* Memory is Read/Write and large */ + PAGE_READWRITE | SEC_COMMIT | SEC_LARGE_PAGES, + size_high, /* Size Upper 32 Bits */ + size_low, /* Size Lower 32 bits */ + szShareMem); + else if (huge_pages == HUGE_PAGES_ON) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("huge_pages = on, but cannot obtain SeLockMemoryPrivilege"))); + else + ereport(DEBUG1, + "huge_pages = try, cannot obtain SeLockMemoryPrivilege, falling back to huge_pages = off"); + } + + if (huge_pages != HUGE_PAGES_ON && !hmap) + { + hmap = CreateFileMapping(INVALID_HANDLE_VALUE, /* Use the pagefile */ + NULL, /* Default security attrs */ + PAGE_READWRITE, /* Memory is Read/Write */ + size_high, /* Size Upper 32 Bits */ + size_low, /* Size Lower 32 bits */ + szShareMem); + } if (!hmap) ereport(FATAL,