Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1cc4f53

Browse files
committed
Support huge pages on Windows
Add support for huge pages (called large pages on Windows) to theWindows build.This (probably) breaks compatibility with Windows versions prior toWindows 2003 or Windows Vista.Authors: Takayuki Tsunakawa and Thomas MunroReviewed by: Magnus Hagander, Amit Kapila
1 parent5c15a54 commit1cc4f53

File tree

4 files changed

+204
-22
lines changed

4 files changed

+204
-22
lines changed

‎doc/src/sgml/config.sgml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,14 +1369,26 @@ include_dir 'conf.d'
13691369
</para>
13701370

13711371
<para>
1372-
At present, this feature is supported only on Linux. The setting is
1373-
ignored on other systems when set to <literal>try</literal>.
1372+
At present, this feature is supported only on Linux and Windows. The
1373+
setting isignored on other systems when set to <literal>try</literal>.
13741374
</para>
13751375

13761376
<para>
13771377
The use of huge pages results in smaller page tables and less CPU time
1378-
spent on memory management, increasing performance. For more details,
1379-
see <xref linkend="linux-huge-pages"/>.
1378+
spent on memory management, increasing performance. For more details about
1379+
using huge pages on Linux, see <xref linkend="linux-huge-pages"/>.
1380+
</para>
1381+
1382+
<para>
1383+
Huge pages are known as large pages on Windows. To use them, you need to
1384+
assign the user right Lock Pages in Memory to the Windows user account
1385+
that runs <productname>PostgreSQL</productname>.
1386+
You can use Windows Group Policy tool (gpedit.msc) to assign the user right
1387+
Lock Pages in Memory.
1388+
To start the database server on the command prompt as a standalone process,
1389+
not as a Windows service, the command prompt must be run as an administrator
1390+
User Access Control (UAC) must be disabled. When the UAC is enabled, the normal
1391+
command prompt revokes the user right Lock Pages in Memory when started.
13801392
</para>
13811393

13821394
<para>

‎src/backend/port/win32_shmem.c

Lines changed: 117 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ HANDLEUsedShmemSegID = INVALID_HANDLE_VALUE;
2121
void*UsedShmemSegAddr=NULL;
2222
staticSizeUsedShmemSegSize=0;
2323

24+
staticboolEnableLockPagesPrivilege(intelevel);
2425
staticvoidpgwin32_SharedMemoryDelete(intstatus,DatumshmId);
2526

2627
/*
@@ -103,6 +104,66 @@ PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
103104
return true;
104105
}
105106

107+
/*
108+
* EnableLockPagesPrivilege
109+
*
110+
* Try to acquire SeLockMemoryPrivilege so we can use large pages.
111+
*/
112+
staticbool
113+
EnableLockPagesPrivilege(intelevel)
114+
{
115+
HANDLEhToken;
116+
TOKEN_PRIVILEGEStp;
117+
LUIDluid;
118+
119+
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES |TOKEN_QUERY,&hToken))
120+
{
121+
ereport(elevel,
122+
(errmsg("could not enable Lock Pages in Memory user right: error code %lu",GetLastError()),
123+
errdetail("Failed system call was %s.","OpenProcessToken")));
124+
return FALSE;
125+
}
126+
127+
if (!LookupPrivilegeValue(NULL,SE_LOCK_MEMORY_NAME,&luid))
128+
{
129+
ereport(elevel,
130+
(errmsg("could not enable Lock Pages in Memory user right: error code %lu",GetLastError()),
131+
errdetail("Failed system call was %s.","LookupPrivilegeValue")));
132+
CloseHandle(hToken);
133+
return FALSE;
134+
}
135+
tp.PrivilegeCount=1;
136+
tp.Privileges[0].Luid=luid;
137+
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
138+
139+
if (!AdjustTokenPrivileges(hToken, FALSE,&tp,0,NULL,NULL))
140+
{
141+
ereport(elevel,
142+
(errmsg("could not enable Lock Pages in Memory user right: error code %lu",GetLastError()),
143+
errdetail("Failed system call was %s.","AdjustTokenPrivileges")));
144+
CloseHandle(hToken);
145+
return FALSE;
146+
}
147+
148+
if (GetLastError()!=ERROR_SUCCESS)
149+
{
150+
if (GetLastError()==ERROR_NOT_ALL_ASSIGNED)
151+
ereport(elevel,
152+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
153+
errmsg("could not enable Lock Pages in Memory user right"),
154+
errhint("Assign Lock Pages in Memory user right to the Windows user account which runs PostgreSQL.")));
155+
else
156+
ereport(elevel,
157+
(errmsg("could not enable Lock Pages in Memory user right: error code %lu",GetLastError()),
158+
errdetail("Failed system call was %s.","AdjustTokenPrivileges")));
159+
CloseHandle(hToken);
160+
return FALSE;
161+
}
162+
163+
CloseHandle(hToken);
164+
165+
return TRUE;
166+
}
106167

107168
/*
108169
* PGSharedMemoryCreate
@@ -127,11 +188,9 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port,
127188
inti;
128189
DWORDsize_high;
129190
DWORDsize_low;
130-
131-
if (huge_pages==HUGE_PAGES_ON)
132-
ereport(ERROR,
133-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
134-
errmsg("huge pages not supported on this platform")));
191+
SIZE_TlargePageSize=0;
192+
Sizeorig_size=size;
193+
DWORDflProtect=PAGE_READWRITE;
135194

136195
/* Room for a header? */
137196
Assert(size>MAXALIGN(sizeof(PGShmemHeader)));
@@ -140,6 +199,35 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port,
140199

141200
UsedShmemSegAddr=NULL;
142201

202+
if (huge_pages==HUGE_PAGES_ON||huge_pages==HUGE_PAGES_TRY)
203+
{
204+
/* Does the processor support large pages? */
205+
largePageSize=GetLargePageMinimum();
206+
if (largePageSize==0)
207+
{
208+
ereport(huge_pages==HUGE_PAGES_ON ?FATAL :DEBUG1,
209+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
210+
errmsg("the processor does not support large pages")));
211+
ereport(DEBUG1,
212+
(errmsg("disabling huge pages")));
213+
}
214+
elseif (!EnableLockPagesPrivilege(huge_pages==HUGE_PAGES_ON ?FATAL :DEBUG1))
215+
{
216+
ereport(DEBUG1,
217+
(errmsg("disabling huge pages")));
218+
}
219+
else
220+
{
221+
/* Huge pages available and privilege enabled, so turn on */
222+
flProtect=PAGE_READWRITE |SEC_COMMIT |SEC_LARGE_PAGES;
223+
224+
/* Round size up as appropriate. */
225+
if (size %largePageSize!=0)
226+
size+=largePageSize- (size %largePageSize);
227+
}
228+
}
229+
230+
retry:
143231
#ifdef_WIN64
144232
size_high=size >>32;
145233
#else
@@ -163,16 +251,35 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port,
163251

164252
hmap=CreateFileMapping(INVALID_HANDLE_VALUE,/* Use the pagefile */
165253
NULL,/* Default security attrs */
166-
PAGE_READWRITE,/* Memory is Read/Write */
254+
flProtect,
167255
size_high,/* Size Upper 32 Bits*/
168256
size_low,/* Size Lower 32 bits */
169257
szShareMem);
170258

171259
if (!hmap)
172-
ereport(FATAL,
173-
(errmsg("could not create shared memory segment: error code %lu",GetLastError()),
174-
errdetail("Failed system call was CreateFileMapping(size=%zu, name=%s).",
175-
size,szShareMem)));
260+
{
261+
if (GetLastError()==ERROR_NO_SYSTEM_RESOURCES&&
262+
huge_pages==HUGE_PAGES_TRY&&
263+
(flProtect&SEC_LARGE_PAGES)!=0)
264+
{
265+
elog(DEBUG1,"CreateFileMapping(%zu) with SEC_LARGE_PAGES failed, "
266+
"huge pages disabled",
267+
size);
268+
269+
/*
270+
* Use the original size, not the rounded-up value, when falling back
271+
* to non-huge pages.
272+
*/
273+
size=orig_size;
274+
flProtect=PAGE_READWRITE;
275+
gotoretry;
276+
}
277+
else
278+
ereport(FATAL,
279+
(errmsg("could not create shared memory segment: error code %lu",GetLastError()),
280+
errdetail("Failed system call was CreateFileMapping(size=%zu, name=%s).",
281+
size,szShareMem)));
282+
}
176283

177284
/*
178285
* If the segment already existed, CreateFileMapping() will return a

‎src/backend/utils/misc/guc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3913,7 +3913,7 @@ static struct config_enum ConfigureNamesEnum[] =
39133913

39143914
{
39153915
{"huge_pages",PGC_POSTMASTER,RESOURCES_MEM,
3916-
gettext_noop("Use of huge pages on Linux."),
3916+
gettext_noop("Use of huge pages on Linux or Windows."),
39173917
NULL
39183918
},
39193919
&huge_pages,

‎src/bin/pg_ctl/pg_ctl.c

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ static void WINAPI pgwin32_ServiceHandler(DWORD);
144144
staticvoidWINAPIpgwin32_ServiceMain(DWORD,LPTSTR*);
145145
staticvoidpgwin32_doRunAsService(void);
146146
staticintCreateRestrictedProcess(char*cmd,PROCESS_INFORMATION*processInfo,boolas_service);
147+
staticPTOKEN_PRIVILEGESGetPrivilegesToDelete(HANDLEhToken);
147148
#endif
148149

149150
staticpgpid_tget_pgpid(boolis_status_request);
@@ -1623,11 +1624,6 @@ typedef BOOL (WINAPI * __SetInformationJobObject) (HANDLE, JOBOBJECTINFOCLASS, L
16231624
typedefBOOL (WINAPI*__AssignProcessToJobObject) (HANDLE,HANDLE);
16241625
typedefBOOL (WINAPI*__QueryInformationJobObject) (HANDLE,JOBOBJECTINFOCLASS,LPVOID,DWORD,LPDWORD);
16251626

1626-
/* Windows API define missing from some versions of MingW headers */
1627-
#ifndefDISABLE_MAX_PRIVILEGE
1628-
#defineDISABLE_MAX_PRIVILEGE0x1
1629-
#endif
1630-
16311627
/*
16321628
* Create a restricted token, a job object sandbox, and execute the specified
16331629
* process with it.
@@ -1650,6 +1646,7 @@ CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_ser
16501646
HANDLErestrictedToken;
16511647
SID_IDENTIFIER_AUTHORITYNtAuthority= {SECURITY_NT_AUTHORITY};
16521648
SID_AND_ATTRIBUTESdropSids[2];
1649+
PTOKEN_PRIVILEGESdelPrivs;
16531650

16541651
/* Functions loaded dynamically */
16551652
__CreateRestrictedToken_CreateRestrictedToken=NULL;
@@ -1708,14 +1705,21 @@ CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_ser
17081705
return0;
17091706
}
17101707

1708+
/* Get list of privileges to remove */
1709+
delPrivs=GetPrivilegesToDelete(origToken);
1710+
if (delPrivs==NULL)
1711+
/* Error message already printed */
1712+
return0;
1713+
17111714
b=_CreateRestrictedToken(origToken,
1712-
DISABLE_MAX_PRIVILEGE,
1715+
0,
17131716
sizeof(dropSids) /sizeof(dropSids[0]),
17141717
dropSids,
1715-
0,NULL,
1718+
delPrivs->PrivilegeCount,delPrivs->Privileges,
17161719
0,NULL,
17171720
&restrictedToken);
17181721

1722+
free(delPrivs);
17191723
FreeSid(dropSids[1].Sid);
17201724
FreeSid(dropSids[0].Sid);
17211725
CloseHandle(origToken);
@@ -1832,6 +1836,65 @@ CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_ser
18321836
*/
18331837
returnr;
18341838
}
1839+
1840+
/*
1841+
* Get a list of privileges to delete from the access token. We delete all privileges
1842+
* except SeLockMemoryPrivilege which is needed to use large pages, and
1843+
* SeChangeNotifyPrivilege which is enabled by default in DISABLE_MAX_PRIVILEGE.
1844+
*/
1845+
staticPTOKEN_PRIVILEGES
1846+
GetPrivilegesToDelete(HANDLEhToken)
1847+
{
1848+
inti,j;
1849+
DWORDlength;
1850+
PTOKEN_PRIVILEGEStokenPrivs;
1851+
LUIDluidLockPages;
1852+
LUIDluidChangeNotify;
1853+
1854+
if (!LookupPrivilegeValue(NULL,SE_LOCK_MEMORY_NAME,&luidLockPages)||
1855+
!LookupPrivilegeValue(NULL,SE_CHANGE_NOTIFY_NAME,&luidChangeNotify))
1856+
{
1857+
write_stderr(_("%s: could not get LUIDs for privileges: error code %lu\n"),
1858+
progname, (unsigned long)GetLastError());
1859+
returnNULL;
1860+
}
1861+
1862+
if (!GetTokenInformation(hToken,TokenPrivileges,NULL,0,&length)&&
1863+
GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
1864+
{
1865+
write_stderr(_("%s: could not get token information: error code %lu\n"),
1866+
progname, (unsigned long)GetLastError());
1867+
returnNULL;
1868+
}
1869+
1870+
tokenPrivs= (PTOKEN_PRIVILEGES)malloc(length);
1871+
if (tokenPrivs==NULL)
1872+
{
1873+
write_stderr(_("%s: out of memory\n"),progname);
1874+
returnNULL;
1875+
}
1876+
1877+
if (!GetTokenInformation(hToken,TokenPrivileges,tokenPrivs,length,&length))
1878+
{
1879+
write_stderr(_("%s: could not get token information: error code %lu\n"),
1880+
progname, (unsigned long)GetLastError());
1881+
free(tokenPrivs);
1882+
returnNULL;
1883+
}
1884+
1885+
for (i=0;i<tokenPrivs->PrivilegeCount;i++)
1886+
{
1887+
if (memcmp(&tokenPrivs->Privileges[i].Luid,&luidLockPages,sizeof(LUID))==0||
1888+
memcmp(&tokenPrivs->Privileges[i].Luid,&luidChangeNotify,sizeof(LUID))==0)
1889+
{
1890+
for (j=i;j<tokenPrivs->PrivilegeCount-1;j++)
1891+
tokenPrivs->Privileges[j]=tokenPrivs->Privileges[j+1];
1892+
tokenPrivs->PrivilegeCount--;
1893+
}
1894+
}
1895+
1896+
returntokenPrivs;
1897+
}
18351898
#endif/* WIN32 */
18361899

18371900
staticvoid

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp