REDACTED-rig/src/Mem_win.cpp
2018-03-18 22:48:46 +01:00

207 lines
4.9 KiB
C++

/* 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 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2016-2018 XMRig <https://github.com/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/>.
*/
#include <winsock2.h>
#include <windows.h>
#include <ntsecapi.h>
#include <tchar.h>
#ifdef __GNUC__
# include <mm_malloc.h>
#else
# include <malloc.h>
#endif
#include "log/Log.h"
#include "crypto/CryptoNight.h"
#include "Mem.h"
#include "Options.h"
#include "xmrig.h"
/*****************************************************************
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
*/
static BOOL SetLockPagesPrivilege()
{
HANDLE token;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) != TRUE)
{
return FALSE;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE)
{
return FALSE;
}
BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, NULL, NULL);
if(rc != TRUE || GetLastError() != ERROR_SUCCESS)
{
return FALSE;
}
CloseHandle(token);
return TRUE;
}
static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string)
{
LSA_UNICODE_STRING lsaString;
DWORD dwLen = (DWORD) wcslen((WCHAR*)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)
{
LOG_NOTICE("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();
}
bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
{
m_algo = algo;
m_threads = threads;
m_doubleHash = doubleHash;
const int ratio = (doubleHash && algo != xmrig::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
m_size = MONERO_MEMORY * (threads * ratio + 1);
if(!enabled)
{
m_memory = static_cast<uint8_t*>(_mm_malloc(m_size, 16));
return true;
}
if(TrySetLockPagesPrivilege())
{
m_flags |= HugepagesAvailable;
}
m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, m_size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES,
PAGE_READWRITE));
if(!m_memory)
{
m_memory = static_cast<uint8_t*>(_mm_malloc(m_size, 16));
}
else
{
m_flags |= HugepagesEnabled;
}
return true;
}
void Mem::release()
{
if(m_flags & HugepagesEnabled)
{
VirtualFree(m_memory, 0, MEM_RELEASE);
}
else
{
_mm_free(m_memory);
}
}