diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c index 6cf69411db..49b9fa0322 100644 --- a/src/backend/port/win32_shmem.c +++ b/src/backend/port/win32_shmem.c @@ -12,6 +12,8 @@ */ #include "postgres.h" +#include + #include "miscadmin.h" #include "storage/dsm.h" #include "storage/ipc.h" @@ -39,6 +41,17 @@ #define PROTECTIVE_REGION_SIZE (10 * WIN32_STACK_RLIMIT) void *ShmemProtectiveRegion = NULL; +/* + * FILE_MAP_LARGE_PAGES is needed for the support of huge pages, and + * it is only available since Windows 10.0.1703. PG_FILE_MAP_LARGE_PAGES + * saves its value at compile-time. + */ +#ifdef FILE_MAP_LARGE_PAGES +#define PG_FILE_MAP_LARGE_PAGES FILE_MAP_LARGE_PAGES +#else +#define PG_FILE_MAP_LARGE_PAGES 0 +#endif + HANDLE UsedShmemSegID = INVALID_HANDLE_VALUE; void *UsedShmemSegAddr = NULL; static Size UsedShmemSegSize = 0; @@ -216,6 +229,7 @@ PGSharedMemoryCreate(Size size, SIZE_T largePageSize = 0; Size orig_size = size; DWORD flProtect = PAGE_READWRITE; + DWORD desiredAccess; ShmemProtectiveRegion = VirtualAlloc(NULL, PROTECTIVE_REGION_SIZE, MEM_RESERVE, PAGE_NOACCESS); @@ -258,6 +272,22 @@ PGSharedMemoryCreate(Size size, } } + /* + * If this binary has been compiled without FILE_MAP_LARGE_PAGES + * available and huge pages are wanted, there is nothing do do + * if running on a version older than 10.0.1703 as this flag is a + * requirement to allow the use of huge pages. + */ + if (huge_pages == HUGE_PAGES_ON && + PG_FILE_MAP_LARGE_PAGES == 0 && + IsWindowsVersionOrGreater(10, 0, 1703)) + { + ereport(FATAL, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("the processor does not support large pages"), + errdetail("The code has been compiled without huge page support for this version of Windows."))); + } + retry: #ifdef _WIN64 size_high = size >> 32; @@ -353,12 +383,21 @@ retry: if (!CloseHandle(hmap)) elog(LOG, "could not close handle to shared memory: error code %lu", GetLastError()); + desiredAccess = FILE_MAP_WRITE | FILE_MAP_READ; + + /* + * Set large pages if wanted. FILE_MAP_LARGE_PAGES is needed when + * running at least Windows 10.0.1703. + */ + if ((flProtect & SEC_LARGE_PAGES) != 0 && + IsWindowsVersionOrGreater(10, 0, 1703)) + desiredAccess |= PG_FILE_MAP_LARGE_PAGES; /* * Get a pointer to the new shared memory segment. Map the whole segment * at once, and let the system decide on the initial address. */ - memAddress = MapViewOfFileEx(hmap2, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0, NULL); + memAddress = MapViewOfFileEx(hmap2, desiredAccess, 0, 0, 0, NULL); if (!memAddress) ereport(FATAL, (errmsg("could not create shared memory segment: error code %lu", GetLastError()),