xmrig/src/Mem_win.cpp

172 lines
4.7 KiB
C++
Raw Normal View History

2017-04-15 06:02:08 +00:00
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2017-04-21 08:56:11 +00:00
2017-04-15 06:02:08 +00:00
2017-06-09 12:09:21 +00:00
#include <winsock2.h>
2017-04-15 06:02:08 +00:00
#include <windows.h>
#include <ntsecapi.h>
#include <tchar.h>
2017-04-15 06:02:08 +00:00
2017-06-09 12:09:21 +00:00
#include "Mem.h"
#include "Console.h"
#include "Options.h"
2017-04-15 06:02:08 +00:00
/*****************************************************************
SetLockPagesPrivilege: a function to obtain or
release the privilege of locking physical pages.
Inputs:
HANDLE hProcess: Handle for the process for which the
privilege is needed
BOOL bEnable: Enable (TRUE) or disable?
Return value: TRUE indicates success, FALSE failure.
*****************************************************************/
/**
* AWE Example: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366531(v=vs.85).aspx
* Creating a File Mapping Using Large Pages: https://msdn.microsoft.com/en-us/library/aa366543(VS.85).aspx
*/
2017-05-04 11:18:14 +00:00
static BOOL SetLockPagesPrivilege() {
HANDLE token;
2017-04-15 06:02:08 +00:00
2017-05-04 11:18:14 +00:00
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) != TRUE) {
2017-04-15 06:02:08 +00:00
return FALSE;
}
2017-05-04 11:18:14 +00:00
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
2017-04-15 06:02:08 +00:00
2017-05-04 11:18:14 +00:00
if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE) {
2017-04-15 06:02:08 +00:00
return FALSE;
}
2017-05-04 11:18:14 +00:00
BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, NULL, NULL);
if (rc != TRUE || GetLastError() != ERROR_SUCCESS) {
2017-04-15 06:02:08 +00:00
return FALSE;
}
2017-05-04 11:18:14 +00:00
CloseHandle(token);
2017-04-15 06:02:08 +00:00
return TRUE;
}
static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) {
LSA_UNICODE_STRING lsaString;
DWORD dwLen = 0;
dwLen = wcslen(string);
lsaString.Buffer = (LPWSTR) string;
lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR));
lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR));
return lsaString;
}
static BOOL ObtainLockPagesPrivilege() {
HANDLE token;
PTOKEN_USER user = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) {
DWORD size = 0;
GetTokenInformation(token, TokenUser, NULL, 0, &size);
if (size) {
user = (PTOKEN_USER) LocalAlloc(LPTR, size);
}
GetTokenInformation(token, TokenUser, user, size, &size);
CloseHandle(token);
}
if (!user) {
return FALSE;
}
LSA_HANDLE handle;
LSA_OBJECT_ATTRIBUTES attributes;
ZeroMemory(&attributes, sizeof(attributes));
BOOL result = FALSE;
if (LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0) {
LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME));
if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) {
2017-06-09 12:09:21 +00:00
LOG_DEBUG("Huge pages support was successfully enabled, but reboot required to use it");
result = TRUE;
}
LsaClose(handle);
}
LocalFree(user);
return result;
}
static BOOL TrySetLockPagesPrivilege() {
if (SetLockPagesPrivilege()) {
return TRUE;
}
return ObtainLockPagesPrivilege() && SetLockPagesPrivilege();
}
2017-06-09 12:09:21 +00:00
bool Mem::allocate(int algo, int threads, bool doubleHash)
{
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1);
2017-04-15 06:02:08 +00:00
if (TrySetLockPagesPrivilege()) {
2017-06-09 12:09:21 +00:00
m_flags |= HUGEPAGES_AVAILABLE;
2017-04-15 06:02:08 +00:00
}
2017-06-09 12:09:21 +00:00
m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE));
if (!m_memory) {
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
2017-04-15 06:02:08 +00:00
}
else {
2017-06-09 12:09:21 +00:00
m_flags |= HUGEPAGES_ENABLED;
2017-04-15 06:02:08 +00:00
}
2017-06-09 12:09:21 +00:00
return true;
2017-04-15 06:02:08 +00:00
}
2017-06-09 12:09:21 +00:00
void Mem::release()
{
if (m_flags & HUGEPAGES_ENABLED) {
VirtualFree(m_memory, 0, MEM_RELEASE);
2017-04-15 06:02:08 +00:00
}
else {
2017-06-09 12:09:21 +00:00
_mm_free(m_memory);
2017-04-15 06:02:08 +00:00
}
}