Merge branch 'feature-per-pool-algo' into evo

This commit is contained in:
XMRig 2019-07-20 05:28:56 +07:00
commit 31ca1a1b6f
160 changed files with 6628 additions and 5176 deletions

View file

@ -18,40 +18,30 @@ option(WITH_EMBEDDED_CONFIG "Enable internal embedded JSON config" OFF)
include (CheckIncludeFile)
include (cmake/cpu.cmake)
include (src/base/base.cmake)
include (src/backend/backend.cmake)
set(HEADERS
"${HEADERS_BASE}"
"${HEADERS_BASE_HTTP}"
"${HEADERS_BACKEND}"
src/api/interfaces/IApiListener.h
src/App.h
src/common/cpu/Cpu.h
src/common/crypto/keccak.h
src/common/interfaces/ICpuInfo.h
src/common/Platform.h
src/common/xmrig.h
src/core/config/Config_default.h
src/core/config/Config_platform.h
src/core/config/Config.h
src/core/config/ConfigTransform.h
src/core/config/usage.h
src/core/Controller.h
src/interfaces/IJobResultListener.h
src/interfaces/IThread.h
src/interfaces/IWorker.h
src/Mem.h
src/core/Miner.h
src/net/interfaces/IJobResultListener.h
src/net/JobResult.h
src/net/JobResults.h
src/net/Network.h
src/net/NetworkState.h
src/net/strategies/DonateStrategy.h
src/Summary.h
src/version.h
src/workers/CpuThread.h
src/workers/Hashrate.h
src/workers/MultiWorker.h
src/workers/ThreadHandle.h
src/workers/Worker.h
src/workers/Workers.h
)
set(HEADERS_CRYPTO
@ -60,7 +50,9 @@ set(HEADERS_CRYPTO
src/crypto/cn/c_groestl.h
src/crypto/cn/c_jh.h
src/crypto/cn/c_skein.h
src/crypto/cn/CryptoNight_constants.h
src/crypto/cn/CnAlgo.h
src/crypto/cn/CnCtx.h
src/crypto/cn/CnHash.h
src/crypto/cn/CryptoNight_monero.h
src/crypto/cn/CryptoNight_test.h
src/crypto/cn/CryptoNight.h
@ -69,6 +61,8 @@ set(HEADERS_CRYPTO
src/crypto/cn/skein_port.h
src/crypto/cn/soft_aes.h
src/crypto/common/Algorithm.h
src/crypto/common/keccak.h
src/crypto/common/Nonce.h
src/crypto/common/portable/mm_malloc.h
src/crypto/common/VirtualMemory.h
)
@ -82,32 +76,30 @@ endif()
set(SOURCES
"${SOURCES_BASE}"
"${SOURCES_BASE_HTTP}"
"${SOURCES_BACKEND}"
src/App.cpp
src/common/crypto/keccak.cpp
src/common/Platform.cpp
src/core/config/Config.cpp
src/core/config/ConfigTransform.cpp
src/core/Controller.cpp
src/Mem.cpp
src/core/Miner.cpp
src/net/JobResults.cpp
src/net/Network.cpp
src/net/NetworkState.cpp
src/net/strategies/DonateStrategy.cpp
src/Summary.cpp
src/workers/CpuThread.cpp
src/workers/Hashrate.cpp
src/workers/MultiWorker.cpp
src/workers/ThreadHandle.cpp
src/workers/Worker.cpp
src/workers/Workers.cpp
src/xmrig.cpp
)
set(SOURCES_CRYPTO
src/crypto/cn/c_groestl.c
src/crypto/cn/c_blake256.c
src/crypto/cn/c_groestl.c
src/crypto/cn/c_jh.c
src/crypto/cn/c_skein.c
src/crypto/cn/CnCtx.cpp
src/crypto/cn/CnHash.cpp
src/crypto/common/Algorithm.cpp
src/crypto/common/keccak.cpp
src/crypto/common/Nonce.cpp
)
if (WIN32)
@ -115,8 +107,6 @@ if (WIN32)
"${SOURCES_OS}"
res/app.rc
src/App_win.cpp
src/common/Platform_win.cpp
src/Mem_win.cpp
src/crypto/common/VirtualMemory_win.cpp
)
@ -126,16 +116,12 @@ elseif (APPLE)
set(SOURCES_OS
"${SOURCES_OS}"
src/App_unix.cpp
src/common/Platform_mac.cpp
src/Mem_unix.cpp
src/crypto/common/VirtualMemory_unix.cpp
)
else()
set(SOURCES_OS
"${SOURCES_OS}"
src/App_unix.cpp
src/common/Platform_unix.cpp
src/Mem_unix.cpp
src/crypto/common/VirtualMemory_unix.cpp
)
@ -166,24 +152,34 @@ if (WITH_RANDOMX)
set(SOURCES_CRYPTO
"${SOURCES_CRYPTO}"
src/crypto/randomx/aes_hash.cpp
src/crypto/randomx/allocator.cpp
src/crypto/randomx/argon2_core.c
src/crypto/randomx/argon2_ref.c
src/crypto/randomx/blake2_generator.cpp
src/crypto/randomx/blake2/blake2b.c
src/crypto/randomx/bytecode_machine.cpp
src/crypto/randomx/dataset.cpp
src/crypto/randomx/soft_aes.cpp
src/crypto/randomx/virtual_memory.cpp
src/crypto/randomx/vm_interpreted.cpp
src/crypto/randomx/allocator.cpp
src/crypto/randomx/instructions_portable.cpp
src/crypto/randomx/randomx.cpp
src/crypto/randomx/reciprocal.c
src/crypto/randomx/soft_aes.cpp
src/crypto/randomx/superscalar.cpp
src/crypto/randomx/virtual_machine.cpp
src/crypto/randomx/virtual_memory.cpp
src/crypto/randomx/vm_compiled_light.cpp
src/crypto/randomx/vm_compiled.cpp
src/crypto/randomx/vm_interpreted_light.cpp
src/crypto/randomx/argon2_core.c
src/crypto/randomx/blake2_generator.cpp
src/crypto/randomx/instructions_portable.cpp
src/crypto/randomx/reciprocal.c
src/crypto/randomx/virtual_machine.cpp
src/crypto/randomx/vm_compiled_light.cpp
src/crypto/randomx/blake2/blake2b.c
src/crypto/randomx/vm_interpreted.cpp
src/crypto/rx/Rx.cpp
src/crypto/rx/Rx.h
src/crypto/rx/RxAlgo.cpp
src/crypto/rx/RxAlgo.h
src/crypto/rx/RxCache.cpp
src/crypto/rx/RxCache.h
src/crypto/rx/RxDataset.cpp
src/crypto/rx/RxDataset.h
src/crypto/rx/RxVm.cpp
src/crypto/rx/RxVm.h
)
if (NOT ARCH_ID)
set(ARCH_ID ${CMAKE_HOST_SYSTEM_PROCESSOR})
@ -208,23 +204,6 @@ endif()
include(cmake/flags.cmake)
if (WITH_LIBCPUID)
add_subdirectory(src/3rdparty/libcpuid)
include_directories(src/3rdparty/libcpuid)
set(CPUID_LIB cpuid)
set(SOURCES_CPUID src/core/cpu/AdvancedCpuInfo.h src/core/cpu/AdvancedCpuInfo.cpp src/core/cpu/Cpu.cpp)
else()
add_definitions(/DXMRIG_NO_LIBCPUID)
set(SOURCES_CPUID src/common/cpu/BasicCpuInfo.h src/common/cpu/Cpu.cpp)
if (XMRIG_ARM)
set(SOURCES_CPUID ${SOURCES_CPUID} src/common/cpu/BasicCpuInfo_arm.cpp)
else()
set(SOURCES_CPUID ${SOURCES_CPUID} src/common/cpu/BasicCpuInfo.cpp)
endif()
endif()
include(cmake/OpenSSL.cmake)
include(cmake/asm.cmake)
include(cmake/cn-gpu.cmake)
@ -256,8 +235,6 @@ if (WITH_HTTP)
src/api/requests/ApiRequest.h
src/api/requests/HttpApiRequest.cpp
src/api/requests/HttpApiRequest.h
src/api/v1/ApiRouter.cpp
src/api/v1/ApiRouter.h
)
else()
set(HTTP_SOURCES "")

View file

@ -36,10 +36,17 @@ if (WITH_ASM AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
endif()
add_library(${XMRIG_ASM_LIBRARY} STATIC ${XMRIG_ASM_FILES})
set(XMRIG_ASM_SOURCES src/crypto/cn/Asm.h src/crypto/cn/Asm.cpp src/crypto/cn/r/CryptonightR_gen.cpp)
set(XMRIG_ASM_SOURCES
src/crypto/common/Assembly.h
src/crypto/common/Assembly.cpp
src/crypto/cn/r/CryptonightR_gen.cpp
)
set_property(TARGET ${XMRIG_ASM_LIBRARY} PROPERTY LINKER_LANGUAGE C)
add_definitions(/DXMRIG_FEATURE_ASM)
else()
set(XMRIG_ASM_SOURCES "")
set(XMRIG_ASM_LIBRARY "")
add_definitions(/DXMRIG_NO_ASM)
remove_definitions(/DXMRIG_FEATURE_ASM)
endif()

View file

@ -61,7 +61,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-exceptions -fno-rtti -Wno-missing-braces")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexceptions -fno-rtti -Wno-missing-braces")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
if (XMRIG_ARMv8)

View file

@ -6,7 +6,7 @@
* 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 2018 SChernykh <https://github.com/SChernykh>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
@ -30,18 +30,17 @@
#include "api/Api.h"
#include "App.h"
#include "backend/cpu/Cpu.h"
#include "base/io/Console.h"
#include "base/io/log/Log.h"
#include "base/kernel/Signals.h"
#include "common/cpu/Cpu.h"
#include "common/Platform.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "Mem.h"
#include "core/Miner.h"
#include "crypto/common/VirtualMemory.h"
#include "net/Network.h"
#include "Summary.h"
#include "version.h"
#include "workers/Workers.h"
xmrig::App::App(Process *process) :
@ -77,7 +76,7 @@ int xmrig::App::exec()
background();
Mem::init(m_controller->config()->isHugePages());
VirtualMemory::init(m_controller->config()->cpu().isHugePages());
Summary::print(m_controller);
@ -87,8 +86,6 @@ int xmrig::App::exec()
return 0;
}
Workers::start(m_controller);
m_controller->start();
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
@ -103,23 +100,17 @@ void xmrig::App::onConsoleCommand(char command)
switch (command) {
case 'h':
case 'H':
Workers::printHashrate(true);
m_controller->miner()->printHashrate(true);
break;
case 'p':
case 'P':
if (Workers::isEnabled()) {
LOG_INFO(YELLOW_BOLD("paused") ", press " MAGENTA_BOLD("r") " to resume");
Workers::setEnabled(false);
}
m_controller->miner()->setEnabled(false);
break;
case 'r':
case 'R':
if (!Workers::isEnabled()) {
LOG_INFO(GREEN_BOLD("resumed"));
Workers::setEnabled(true);
}
m_controller->miner()->setEnabled(true);
break;
case 3:
@ -163,6 +154,5 @@ void xmrig::App::close()
m_console->stop();
m_controller->stop();
Workers::stop();
Log::destroy();
}

View file

@ -1,186 +0,0 @@
/* 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 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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>
#include "base/io/log/Log.h"
#include "common/xmrig.h"
#include "crypto/common/portable/mm_malloc.h"
#include "crypto/common/VirtualMemory.h"
#include "crypto/cn/CryptoNight_constants.h"
#include "crypto/cn/CryptoNight.h"
#include "Mem.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(nullptr, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE) {
return FALSE;
}
BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, nullptr, nullptr);
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(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 = nullptr;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) {
DWORD size = 0;
GetTokenInformation(token, TokenUser, nullptr, 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(nullptr, &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();
}
void Mem::init(bool enabled)
{
m_enabled = enabled;
if (enabled && TrySetLockPagesPrivilege()) {
m_flags |= HugepagesAvailable;
}
}
void Mem::allocate(MemInfo &info, bool enabled)
{
info.hugePages = 0;
if (!enabled) {
info.memory = static_cast<uint8_t*>(_mm_malloc(info.size, 4096));
return;
}
info.memory = static_cast<uint8_t*>(xmrig::VirtualMemory::allocateLargePagesMemory(info.size));
if (info.memory) {
info.hugePages = info.pages;
return;
}
allocate(info, false);
}
void Mem::release(MemInfo &info)
{
if (info.hugePages) {
xmrig::VirtualMemory::freeLargePagesMemory(info.memory, info.size);
}
else {
_mm_free(info.memory);
}
}

View file

@ -28,18 +28,18 @@
#include <uv.h>
#include "backend/cpu/Cpu.h"
#include "base/io/log/Log.h"
#include "base/net/stratum/Pool.h"
#include "common/cpu/Cpu.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "crypto/cn/Asm.h"
#include "Mem.h"
#include "crypto/common/Assembly.h"
#include "crypto/common/VirtualMemory.h"
#include "Summary.h"
#include "version.h"
#ifndef XMRIG_NO_ASM
#ifdef XMRIG_FEATURE_ASM
static const char *coloredAsmNames[] = {
RED_BOLD("none"),
"auto",
@ -49,7 +49,7 @@ static const char *coloredAsmNames[] = {
};
inline static const char *asmName(xmrig::Assembly assembly)
inline static const char *asmName(xmrig::Assembly::Id assembly)
{
return coloredAsmNames[assembly];
}
@ -59,7 +59,7 @@ inline static const char *asmName(xmrig::Assembly assembly)
static void print_memory(xmrig::Config *) {
# ifdef _WIN32
xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s",
"HUGE PAGES", Mem::isHugepagesAvailable() ? GREEN_BOLD("available") : RED_BOLD("unavailable"));
"HUGE PAGES", xmrig::VirtualMemory::isHugepagesAvailable() ? GREEN_BOLD("available") : RED_BOLD("unavailable"));
# endif
}
@ -76,7 +76,7 @@ static void print_cpu(xmrig::Config *)
Cpu::info()->hasAES() ? GREEN_BOLD_S : RED_BOLD_S "-",
Cpu::info()->hasAVX2() ? GREEN_BOLD_S : RED_BOLD_S "-"
);
# ifndef XMRIG_NO_LIBCPUID
# ifdef XMRIG_FEATURE_LIBCPUID
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%.1f MB/%.1f MB"), "CPU L2/L3", Cpu::info()->L2() / 1024.0, Cpu::info()->L3() / 1024.0);
# endif
}
@ -84,40 +84,20 @@ static void print_cpu(xmrig::Config *)
static void print_threads(xmrig::Config *config)
{
if (config->threadsMode() != xmrig::Config::Advanced) {
char buf[32] = { 0 };
if (config->affinity() != -1L) {
snprintf(buf, sizeof buf, ", affinity=0x%" PRIX64, config->affinity());
}
xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, av=%d, %sdonate=%d%%") WHITE_BOLD("%s"),
"THREADS",
config->threadsCount(),
config->algorithm().shortName(),
config->algoVariant(),
config->pools().donateLevel() == 0 ? RED_BOLD_S : "",
config->pools().donateLevel(),
buf
);
}
else {
xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, %sdonate=%d%%"),
"THREADS",
config->threadsCount(),
config->algorithm().shortName(),
xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s%d%%"),
"DONATE",
config->pools().donateLevel() == 0 ? RED_BOLD_S : "",
config->pools().donateLevel()
);
}
# ifndef XMRIG_NO_ASM
if (config->assembly() == xmrig::ASM_AUTO) {
# ifdef XMRIG_FEATURE_ASM
if (config->cpu().assembly() == xmrig::Assembly::AUTO) {
const xmrig::Assembly assembly = xmrig::Cpu::info()->assembly();
xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13sauto:%s"), "ASSEMBLY", asmName(assembly));
}
else {
xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s"), "ASSEMBLY", asmName(config->assembly()));
xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s"), "ASSEMBLY", asmName(config->cpu().assembly()));
}
# endif
}

View file

@ -35,13 +35,13 @@
#include "api/Api.h"
#include "api/interfaces/IApiListener.h"
#include "api/requests/HttpApiRequest.h"
#include "api/v1/ApiRouter.h"
#include "base/kernel/Base.h"
#include "base/tools/Buffer.h"
#include "base/tools/Chrono.h"
#include "common/crypto/keccak.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "crypto/common/Algorithm.h"
#include "crypto/common/keccak.h"
#include "version.h"
@ -60,16 +60,11 @@ xmrig::Api::Api(Base *base) :
base->addListener(this);
genId(base->config()->apiId());
m_v1 = new ApiRouter(base);
addListener(m_v1);
}
xmrig::Api::~Api()
{
delete m_v1;
# ifdef XMRIG_FEATURE_HTTP
delete m_httpd;
# endif
@ -119,13 +114,31 @@ void xmrig::Api::exec(IApiRequest &request)
{
using namespace rapidjson;
if (request.method() == IApiRequest::METHOD_GET && (request.url() == "/1/summary" || request.url() == "/api.json")) {
if (request.type() == IApiRequest::REQ_SUMMARY) {
auto &allocator = request.doc().GetAllocator();
request.accept();
request.reply().AddMember("id", StringRef(m_id), allocator);
request.reply().AddMember("worker_id", StringRef(m_workerId), allocator);
request.reply().AddMember("uptime", (Chrono::steadyMSecs() - m_timestamp) / 1000, allocator);
Value features(kArrayType);
# ifdef XMRIG_FEATURE_API
features.PushBack("api", allocator);
# endif
# ifdef XMRIG_FEATURE_ASM
features.PushBack("asm", allocator);
# endif
# ifdef XMRIG_FEATURE_HTTP
features.PushBack("http", allocator);
# endif
# ifdef XMRIG_FEATURE_LIBCPUID
features.PushBack("cpuid", allocator);
# endif
# ifdef XMRIG_FEATURE_TLS
features.PushBack("tls", allocator);
# endif
request.reply().AddMember("features", features, allocator);
}
for (IApiListener *listener : m_listeners) {

View file

@ -36,7 +36,6 @@
namespace xmrig {
class ApiRouter;
class Base;
class Httpd;
class HttpData;
@ -67,7 +66,6 @@ private:
void genId(const String &id);
void genWorkerId(const String &id);
ApiRouter *m_v1;
Base *m_base;
char m_id[32];
char m_workerId[128];

View file

@ -35,7 +35,9 @@ class IApiListener
public:
virtual ~IApiListener() = default;
# ifdef XMRIG_FEATURE_API
virtual void onRequest(IApiRequest &request) = 0;
# endif
};

View file

@ -4,7 +4,9 @@
* 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-2018 XMRig <support@xmrig.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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
@ -50,6 +52,12 @@ public:
};
enum RequestType {
REQ_UNKNOWN,
REQ_SUMMARY
};
virtual ~IApiRequest() = default;
virtual bool isDone() const = 0;
@ -57,9 +65,11 @@ public:
virtual bool isRestricted() const = 0;
virtual const rapidjson::Value &json() const = 0;
virtual const String &url() const = 0;
virtual int version() const = 0;
virtual Method method() const = 0;
virtual rapidjson::Document &doc() = 0;
virtual rapidjson::Value &reply() = 0;
virtual RequestType type() const = 0;
virtual Source source() const = 0;
virtual void accept() = 0;
virtual void done(int status) = 0;

View file

@ -28,8 +28,7 @@
xmrig::ApiRequest::ApiRequest(Source source, bool restricted) :
m_restricted(restricted),
m_source(source),
m_state(STATE_NEW)
m_source(source)
{
}

View file

@ -43,10 +43,15 @@ protected:
inline bool isDone() const override { return m_state == STATE_DONE; }
inline bool isNew() const override { return m_state == STATE_NEW; }
inline bool isRestricted() const override { return m_restricted; }
inline int version() const override { return m_version; }
inline RequestType type() const override { return m_type; }
inline Source source() const override { return m_source; }
inline void accept() override { m_state = STATE_ACCEPTED; }
inline void done(int) override { m_state = STATE_DONE; }
int m_version = 1;
RequestType m_type = REQ_UNKNOWN;
private:
enum State {
STATE_NEW,
@ -56,7 +61,7 @@ private:
bool m_restricted;
Source m_source;
State m_state;
State m_state = STATE_NEW;
};

View file

@ -35,6 +35,17 @@ xmrig::HttpApiRequest::HttpApiRequest(const HttpData &req, bool restricted) :
m_res(req.id()),
m_url(req.url.c_str())
{
if (method() == METHOD_GET) {
if (url() == "/1/summary" || url() == "/2/summary" || url() == "/api.json") {
m_type = REQ_SUMMARY;
}
}
if (url().size() > 4) {
if (memcmp(url().data(), "/2/", 3) == 0) {
m_version = 2;
}
}
}

View file

@ -1,179 +0,0 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 <math.h>
#include <string.h>
#include <uv.h>
#include "api/interfaces/IApiRequest.h"
#include "api/v1/ApiRouter.h"
#include "base/kernel/Base.h"
#include "common/cpu/Cpu.h"
#include "common/Platform.h"
#include "core/config/Config.h"
#include "interfaces/IThread.h"
#include "rapidjson/document.h"
#include "version.h"
#include "workers/Hashrate.h"
#include "workers/Workers.h"
static inline rapidjson::Value normalize(double d)
{
using namespace rapidjson;
if (!isnormal(d)) {
return Value(kNullType);
}
return Value(floor(d * 100.0) / 100.0);
}
xmrig::ApiRouter::ApiRouter(Base *base) :
m_base(base)
{
}
xmrig::ApiRouter::~ApiRouter()
{
}
void xmrig::ApiRouter::onRequest(IApiRequest &request)
{
if (request.method() == IApiRequest::METHOD_GET) {
if (request.url() == "/1/summary" || request.url() == "/api.json") {
request.accept();
getMiner(request.reply(), request.doc());
getHashrate(request.reply(), request.doc());
}
else if (request.url() == "/1/threads") {
request.accept();
getThreads(request.reply(), request.doc());
}
else if (request.url() == "/1/config") {
if (request.isRestricted()) {
return request.done(403);
}
request.accept();
m_base->config()->getJSON(request.doc());
}
}
else if (request.method() == IApiRequest::METHOD_PUT || request.method() == IApiRequest::METHOD_POST) {
if (request.url() == "/1/config") {
request.accept();
if (!m_base->reload(request.json())) {
return request.done(400);
}
request.done(204);
}
}
}
void xmrig::ApiRouter::getHashrate(rapidjson::Value &reply, rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value hashrate(kObjectType);
Value total(kArrayType);
Value threads(kArrayType);
const Hashrate *hr = Workers::hashrate();
total.PushBack(normalize(hr->calc(Hashrate::ShortInterval)), allocator);
total.PushBack(normalize(hr->calc(Hashrate::MediumInterval)), allocator);
total.PushBack(normalize(hr->calc(Hashrate::LargeInterval)), allocator);
for (size_t i = 0; i < Workers::threads(); i++) {
Value thread(kArrayType);
thread.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
thread.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
thread.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
threads.PushBack(thread, allocator);
}
hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", normalize(hr->highest()), allocator);
hashrate.AddMember("threads", threads, allocator);
reply.AddMember("hashrate", hashrate, allocator);
}
void xmrig::ApiRouter::getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value cpu(kObjectType);
cpu.AddMember("brand", StringRef(Cpu::info()->brand()), allocator);
cpu.AddMember("aes", Cpu::info()->hasAES(), allocator);
cpu.AddMember("x64", Cpu::info()->isX64(), allocator);
cpu.AddMember("sockets", Cpu::info()->sockets(), allocator);
reply.AddMember("version", APP_VERSION, allocator);
reply.AddMember("kind", APP_KIND, allocator);
reply.AddMember("ua", StringRef(Platform::userAgent()), allocator);
reply.AddMember("cpu", cpu, allocator);
reply.AddMember("hugepages", Workers::hugePages() > 0, allocator);
reply.AddMember("donate_level", m_base->config()->pools().donateLevel(), allocator);
}
void xmrig::ApiRouter::getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
const Hashrate *hr = Workers::hashrate();
Workers::threadsSummary(doc);
const std::vector<IThread *> &threads = m_base->config()->threads();
Value list(kArrayType);
size_t i = 0;
for (const xmrig::IThread *thread : threads) {
Value value = thread->toAPI(doc);
Value hashrate(kArrayType);
hashrate.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
hashrate.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
hashrate.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
i++;
value.AddMember("hashrate", hashrate, allocator);
list.PushBack(value, allocator);
}
reply.AddMember("threads", list, allocator);
}

13
src/backend/backend.cmake Normal file
View file

@ -0,0 +1,13 @@
include (src/backend/cpu/cpu.cmake)
include (src/backend/common/common.cmake)
set(HEADERS_BACKEND
"${HEADERS_BACKEND_COMMON}"
"${HEADERS_BACKEND_CPU}"
)
set(SOURCES_BACKEND
"${SOURCES_BACKEND_COMMON}"
"${SOURCES_BACKEND_CPU}"
)

View file

@ -24,22 +24,20 @@
#include <assert.h>
#include <chrono>
#include <math.h>
#include <cmath>
#include <memory.h>
#include <stdio.h>
#include "base/io/log/Log.h"
#include "backend/common/Hashrate.h"
#include "base/tools/Chrono.h"
#include "base/tools/Handle.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "workers/Hashrate.h"
#include "rapidjson/document.h"
inline static const char *format(double h, char *buf, size_t size)
{
if (isnormal(h)) {
if (std::isnormal(h)) {
snprintf(buf, size, "%03.1f", h);
return buf;
}
@ -48,10 +46,9 @@ inline static const char *format(double h, char *buf, size_t size)
}
Hashrate::Hashrate(size_t threads, xmrig::Controller *controller) :
xmrig::Hashrate::Hashrate(size_t threads) :
m_highest(0.0),
m_threads(threads),
m_timer(nullptr)
m_threads(threads)
{
m_counts = new uint64_t*[threads];
m_timestamps = new uint64_t*[threads];
@ -62,27 +59,30 @@ Hashrate::Hashrate(size_t threads, xmrig::Controller *controller) :
m_timestamps[i] = new uint64_t[kBucketSize]();
m_top[i] = 0;
}
const int printTime = controller->config()->printTime();
if (printTime > 0) {
m_timer = new uv_timer_t;
uv_timer_init(uv_default_loop(), m_timer);
m_timer->data = this;
uv_timer_start(m_timer, Hashrate::onReport, (printTime + 4) * 1000, printTime * 1000);
}
}
double Hashrate::calc(size_t ms) const
xmrig::Hashrate::~Hashrate()
{
for (size_t i = 0; i < m_threads; i++) {
delete [] m_counts[i];
delete [] m_timestamps[i];
}
delete [] m_counts;
delete [] m_timestamps;
delete [] m_top;
}
double xmrig::Hashrate::calc(size_t ms) const
{
double result = 0.0;
double data;
for (size_t i = 0; i < m_threads; ++i) {
data = calc(i, ms);
if (isnormal(data)) {
if (std::isnormal(data)) {
result += data;
}
}
@ -91,16 +91,13 @@ double Hashrate::calc(size_t ms) const
}
double Hashrate::calc(size_t threadId, size_t ms) const
double xmrig::Hashrate::calc(size_t threadId, size_t ms) const
{
assert(threadId < m_threads);
if (threadId >= m_threads) {
return nan("");
}
using namespace std::chrono;
const uint64_t now = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
uint64_t earliestHashCount = 0;
uint64_t earliestStamp = 0;
uint64_t lastestStamp = 0;
@ -119,7 +116,7 @@ double Hashrate::calc(size_t threadId, size_t ms) const
lastestHashCnt = m_counts[threadId][idx];
}
if (now - m_timestamps[threadId][idx] > ms) {
if (xmrig::Chrono::highResolutionMSecs() - m_timestamps[threadId][idx] > ms) {
haveFullSet = true;
break;
}
@ -136,16 +133,14 @@ double Hashrate::calc(size_t threadId, size_t ms) const
return nan("");
}
double hashes, time;
hashes = (double) lastestHashCnt - earliestHashCount;
time = (double) lastestStamp - earliestStamp;
time /= 1000.0;
const double hashes = static_cast<double>(lastestHashCnt - earliestHashCount);
const double time = static_cast<double>(lastestStamp - earliestStamp) / 1000.0;
return hashes / time;
}
void Hashrate::add(size_t threadId, uint64_t count, uint64_t timestamp)
void xmrig::Hashrate::add(size_t threadId, uint64_t count, uint64_t timestamp)
{
const size_t top = m_top[threadId];
m_counts[threadId][top] = count;
@ -155,45 +150,28 @@ void Hashrate::add(size_t threadId, uint64_t count, uint64_t timestamp)
}
void Hashrate::print() const
{
char num1[8] = { 0 };
char num2[8] = { 0 };
char num3[8] = { 0 };
char num4[8] = { 0 };
LOG_INFO(WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("H/s") " max " CYAN_BOLD("%s H/s"),
format(calc(ShortInterval), num1, sizeof(num1)),
format(calc(MediumInterval), num2, sizeof(num2)),
format(calc(LargeInterval), num3, sizeof(num3)),
format(m_highest, num4, sizeof(num4))
);
}
void Hashrate::stop()
{
xmrig::Handle::close(m_timer);
m_timer = nullptr;
}
void Hashrate::updateHighest()
void xmrig::Hashrate::updateHighest()
{
double highest = calc(ShortInterval);
if (isnormal(highest) && highest > m_highest) {
if (std::isnormal(highest) && highest > m_highest) {
m_highest = highest;
}
}
const char *Hashrate::format(double h, char *buf, size_t size)
const char *xmrig::Hashrate::format(double h, char *buf, size_t size)
{
return ::format(h, buf, size);
}
void Hashrate::onReport(uv_timer_t *handle)
rapidjson::Value xmrig::Hashrate::normalize(double d)
{
static_cast<Hashrate*>(handle->data)->print();
using namespace rapidjson;
if (!std::isnormal(d)) {
return Value(kNullType);
}
return Value(floor(d * 100.0) / 100.0);
}

View file

@ -26,13 +26,14 @@
#define XMRIG_HASHRATE_H
#include <stddef.h>
#include <stdint.h>
#include <uv.h>
#include "rapidjson/fwd.h"
namespace xmrig {
class Controller;
}
class Hashrate
@ -44,22 +45,20 @@ public:
LargeInterval = 900000
};
Hashrate(size_t threads, xmrig::Controller *controller);
Hashrate(size_t threads);
~Hashrate();
double calc(size_t ms) const;
double calc(size_t threadId, size_t ms) const;
void add(size_t threadId, uint64_t count, uint64_t timestamp);
void print() const;
void stop();
void updateHighest();
inline double highest() const { return m_highest; }
inline size_t threads() const { return m_threads; }
static const char *format(double h, char *buf, size_t size);
static rapidjson::Value normalize(double d);
private:
static void onReport(uv_timer_t *handle);
constexpr static size_t kBucketSize = 2 << 11;
constexpr static size_t kBucketMask = kBucketSize - 1;
@ -68,8 +67,10 @@ private:
uint32_t* m_top;
uint64_t** m_counts;
uint64_t** m_timestamps;
uv_timer_t *m_timer;
};
} // namespace xmrig
#endif /* XMRIG_HASHRATE_H */

View file

@ -0,0 +1,67 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_THREAD_H
#define XMRIG_THREAD_H
#include <uv.h>
#include "backend/common/interfaces/IWorker.h"
namespace xmrig {
class IBackend;
template<class T>
class Thread
{
public:
inline Thread(IBackend *backend, size_t index, const T &config) : m_index(index), m_config(config), m_backend(backend) {}
inline ~Thread() { uv_thread_join(&m_thread); delete m_worker; }
inline const T &config() const { return m_config; }
inline IBackend *backend() const { return m_backend; }
inline IWorker *worker() const { return m_worker; }
inline size_t index() const { return m_index; }
inline void setWorker(IWorker *worker) { m_worker = worker; }
inline void start(void (*callback) (void *)) { uv_thread_create(&m_thread, callback, this); }
private:
const size_t m_index = 0;
const T m_config;
IBackend *m_backend;
IWorker *m_worker = nullptr;
uv_thread_t m_thread;
};
} // namespace xmrig
#endif /* XMRIG_THREAD_H */

View file

@ -0,0 +1,164 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 "backend/common/Threads.h"
#include "backend/cpu/CpuThread.h"
#include "rapidjson/document.h"
namespace xmrig {
static const char *kAsterisk = "*";
} // namespace xmrig
template <class T>
const std::vector<T> &xmrig::Threads<T>::get(const String &profileName) const
{
static std::vector<T> empty;
if (profileName.isNull() || !has(profileName)) {
return empty;
}
return m_profiles.at(profileName);
}
template <class T>
size_t xmrig::Threads<T>::read(const rapidjson::Value &value)
{
using namespace rapidjson;
for (auto &member : value.GetObject()) {
if (member.value.IsArray()) {
std::vector<T> threads;
for (auto &v : member.value.GetArray()) {
T thread(v);
if (thread.isValid()) {
threads.push_back(std::move(thread));
}
}
if (!threads.empty()) {
move(member.name.GetString(), std::move(threads));
}
continue;
}
const Algorithm algo(member.name.GetString());
if (!algo.isValid()) {
continue;
}
if (member.value.IsBool() && member.value.IsFalse()) {
disable(algo);
continue;
}
if (member.value.IsString()) {
if (has(member.value.GetString())) {
m_aliases.insert({ algo, member.value.GetString() });
}
else {
m_disabled.insert(algo);
}
}
}
return m_profiles.size();
}
template <class T>
xmrig::String xmrig::Threads<T>::profileName(const Algorithm &algorithm, bool strict) const
{
if (isDisabled(algorithm)) {
return String();
}
const String name = algorithm.shortName();
if (has(name)) {
return name;
}
if (m_aliases.count(algorithm) > 0) {
return m_aliases.at(algorithm);
}
if (strict) {
return String();
}
if (name.contains("/")) {
const String base = name.split('/').at(0);
if (has(base)) {
return base;
}
}
if (has(kAsterisk)) {
return kAsterisk;
}
return String();
}
template <class T>
void xmrig::Threads<T>::toJSON(rapidjson::Value &out, rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
for (const auto &kv : m_profiles) {
Value arr(kArrayType);
for (const T &thread : kv.second) {
arr.PushBack(thread.toJSON(doc), allocator);
}
out.AddMember(kv.first.toJSON(), arr, allocator);
}
for (const Algorithm &algo : m_disabled) {
out.AddMember(StringRef(algo.shortName()), false, allocator);
}
for (const auto &kv : m_aliases) {
out.AddMember(StringRef(kv.first.shortName()), kv.second.toJSON(), allocator);
}
}
namespace xmrig {
template class Threads<CpuThread>;
} // namespace xmrig

View file

@ -0,0 +1,67 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_THREADS_H
#define XMRIG_THREADS_H
#include <map>
#include <set>
#include "base/tools/String.h"
#include "crypto/common/Algorithm.h"
#include "rapidjson/fwd.h"
namespace xmrig {
template <class T>
class Threads
{
public:
inline bool has(const char *profile) const { return m_profiles.count(profile) > 0; }
inline bool isDisabled(const Algorithm &algo) const { return m_disabled.count(algo) > 0 || algo == Algorithm::RX_0; }
inline bool isExist(const Algorithm &algo) const { return isDisabled(algo) || m_aliases.count(algo) > 0 || has(algo.shortName()); }
inline const std::vector<T> &get(const Algorithm &algo, bool strict = false) const { return get(profileName(algo, strict)); }
inline void disable(const Algorithm &algo) { m_disabled.insert(algo); }
inline void move(const char *profile, std::vector<T> &&threads) { m_profiles.insert({ profile, threads }); }
const std::vector<T> &get(const String &profileName) const;
size_t read(const rapidjson::Value &value);
String profileName(const Algorithm &algorithm, bool strict = false) const;
void toJSON(rapidjson::Value &out, rapidjson::Document &doc) const;
private:
std::map<Algorithm, String> m_aliases;
std::map<String, std::vector<T> > m_profiles;
std::set<Algorithm> m_disabled;
};
} /* namespace xmrig */
#endif /* XMRIG_THREADS_H */

View file

@ -23,52 +23,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_MEM_H
#define XMRIG_MEM_H
#include "backend/common/Worker.h"
#include "base/kernel/Platform.h"
#include "base/tools/Chrono.h"
#include <stddef.h>
#include <stdint.h>
#include "common/xmrig.h"
struct cryptonight_ctx;
struct MemInfo
xmrig::Worker::Worker(size_t id, int64_t affinity, int priority) :
m_id(id),
m_hashCount(0),
m_timestamp(0),
m_count(0)
{
alignas(16) uint8_t *memory = nullptr;
size_t hugePages = 0;
size_t pages = 0;
size_t size = 0;
};
Platform::trySetThreadAffinity(affinity);
Platform::setThreadPriority(priority);
}
class Mem
void xmrig::Worker::storeStats()
{
public:
enum Flags {
HugepagesAvailable = 1,
HugepagesEnabled = 2,
Lock = 4
};
static MemInfo create(cryptonight_ctx **ctx, xmrig::Algo algorithm, size_t count);
static void init(bool enabled);
static void release(cryptonight_ctx **ctx, size_t count, MemInfo &info);
static inline bool isHugepagesAvailable() { return (m_flags & HugepagesAvailable) != 0; }
private:
static void allocate(MemInfo &info, bool enabled);
static void release(MemInfo &info);
static int m_flags;
static bool m_enabled;
};
#endif /* XMRIG_MEM_H */
m_hashCount.store(m_count, std::memory_order_relaxed);
m_timestamp.store(Chrono::highResolutionMSecs(), std::memory_order_relaxed);
}

View file

@ -5,7 +5,9 @@
* 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 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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
@ -29,24 +31,18 @@
#include <stdint.h>
#include "interfaces/IWorker.h"
#include "Mem.h"
class ThreadHandle;
#include "backend/common/interfaces/IWorker.h"
namespace xmrig {
class CpuThread;
}
class Worker : public IWorker
{
public:
Worker(ThreadHandle *handle);
Worker(size_t id, int64_t affinity, int priority);
inline const MemInfo &memory() const { return m_memory; }
inline const VirtualMemory *memory() const override { return nullptr; }
inline size_t id() const override { return m_id; }
inline uint64_t hashCount() const override { return m_hashCount.load(std::memory_order_relaxed); }
inline uint64_t timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); }
@ -55,15 +51,13 @@ protected:
void storeStats();
const size_t m_id;
const size_t m_totalWays;
const uint32_t m_offset;
MemInfo m_memory;
std::atomic<uint64_t> m_hashCount;
std::atomic<uint64_t> m_timestamp;
uint64_t m_count;
uint64_t m_sequence;
xmrig::CpuThread *m_thread;
};
} // namespace xmrig
#endif /* XMRIG_WORKER_H */

View file

@ -0,0 +1,142 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_WORKERJOB_H
#define XMRIG_WORKERJOB_H
#include <string.h>
#include "base/net/stratum/Job.h"
#include "crypto/common/Nonce.h"
namespace xmrig {
template<size_t N>
class WorkerJob
{
public:
inline const Job &currentJob() const { return m_jobs[index()]; }
inline uint32_t *nonce(size_t i = 0) { return reinterpret_cast<uint32_t*>(blob() + (i * currentJob().size()) + 39); }
inline uint64_t sequence() const { return m_sequence; }
inline uint8_t *blob() { return m_blobs[index()]; }
inline uint8_t index() const { return m_index; }
inline void add(const Job &job, uint64_t sequence, uint32_t reserveCount)
{
m_sequence = sequence;
if (currentJob() == job) {
return;
}
if (index() == 1 && job.index() == 0 && job == m_jobs[0]) {
return;
}
save(job, reserveCount);
}
inline void nextRound(uint32_t reserveCount)
{
m_rounds[index()]++;
if ((m_rounds[index()] % reserveCount) == 0) {
for (size_t i = 0; i < N; ++i) {
*nonce(i) = Nonce::next(index(), *nonce(i), reserveCount, currentJob().isNicehash());
}
}
else {
for (size_t i = 0; i < N; ++i) {
*nonce(i) += 1;
}
}
}
private:
inline void save(const Job &job, uint32_t reserveCount)
{
m_index = job.index();
const size_t size = job.size();
m_jobs[index()] = job;
m_rounds[index()] = 0;
for (size_t i = 0; i < N; ++i) {
memcpy(m_blobs[index()] + (i * size), job.blob(), size);
*nonce(i) = Nonce::next(index(), *nonce(i), reserveCount, job.isNicehash());
}
}
alignas(16) uint8_t m_blobs[2][Job::kMaxBlobSize * N];
Job m_jobs[2];
uint32_t m_rounds[2] = { 0, 0 };
uint64_t m_sequence = 0;
uint8_t m_index = 0;
};
template<>
inline uint32_t *xmrig::WorkerJob<1>::nonce(size_t)
{
return reinterpret_cast<uint32_t*>(blob() + 39);
}
template<>
inline void xmrig::WorkerJob<1>::nextRound(uint32_t reserveCount)
{
m_rounds[index()]++;
if ((m_rounds[index()] % reserveCount) == 0) {
*nonce() = Nonce::next(index(), *nonce(), reserveCount, currentJob().isNicehash());
}
else {
*nonce() += 1;
}
}
template<>
inline void xmrig::WorkerJob<1>::save(const Job &job, uint32_t reserveCount)
{
m_index = job.index();
m_jobs[index()] = job;
m_rounds[index()] = 0;
memcpy(blob(), job.blob(), job.size());
*nonce() = Nonce::next(index(), *nonce(), reserveCount, currentJob().isNicehash());
}
} // namespace xmrig
#endif /* XMRIG_WORKERJOB_H */

View file

@ -0,0 +1,192 @@
/* 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 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 "backend/common/Hashrate.h"
#include "backend/common/interfaces/IBackend.h"
#include "backend/common/Workers.h"
#include "backend/cpu/CpuWorker.h"
#include "base/io/log/Log.h"
namespace xmrig {
class WorkersPrivate
{
public:
inline WorkersPrivate()
{
}
inline ~WorkersPrivate()
{
delete hashrate;
}
Hashrate *hashrate = nullptr;
IBackend *backend = nullptr;
};
} // namespace xmrig
template<class T>
xmrig::Workers<T>::Workers() :
d_ptr(new WorkersPrivate())
{
}
template<class T>
xmrig::Workers<T>::~Workers()
{
delete d_ptr;
}
template<class T>
const xmrig::Hashrate *xmrig::Workers<T>::hashrate() const
{
return d_ptr->hashrate;
}
template<class T>
void xmrig::Workers<T>::setBackend(IBackend *backend)
{
d_ptr->backend = backend;
}
template<class T>
void xmrig::Workers<T>::start(const std::vector<T> &data)
{
for (const T &item : data) {
m_workers.push_back(new Thread<T>(d_ptr->backend, m_workers.size(), item));
}
d_ptr->hashrate = new Hashrate(m_workers.size());
for (Thread<T> *worker : m_workers) {
worker->start(Workers<T>::onReady);
}
}
template<class T>
void xmrig::Workers<T>::stop()
{
Nonce::stop(T::backend());
for (Thread<T> *worker : m_workers) {
delete worker;
}
m_workers.clear();
Nonce::touch(T::backend());
delete d_ptr->hashrate;
d_ptr->hashrate = nullptr;
}
template<class T>
void xmrig::Workers<T>::tick(uint64_t)
{
if (!d_ptr->hashrate) {
return;
}
for (Thread<T> *handle : m_workers) {
if (!handle->worker()) {
return;
}
d_ptr->hashrate->add(handle->index(), handle->worker()->hashCount(), handle->worker()->timestamp());
}
d_ptr->hashrate->updateHighest();
}
template<class T>
void xmrig::Workers<T>::onReady(void *)
{
}
namespace xmrig {
template<>
void xmrig::Workers<CpuLaunchData>::onReady(void *arg)
{
auto handle = static_cast<Thread<CpuLaunchData>* >(arg);
IWorker *worker = nullptr;
switch (handle->config().intensity) {
case 1:
worker = new CpuWorker<1>(handle->index(), handle->config());
break;
case 2:
worker = new CpuWorker<2>(handle->index(), handle->config());
break;
case 3:
worker = new CpuWorker<3>(handle->index(), handle->config());
break;
case 4:
worker = new CpuWorker<4>(handle->index(), handle->config());
break;
case 5:
worker = new CpuWorker<5>(handle->index(), handle->config());
break;
}
handle->setWorker(worker);
if (!worker->selfTest()) {
LOG_ERR("thread %zu error: \"hash self-test failed\".", handle->worker()->id());
return;
}
handle->backend()->start(worker);
}
template class Workers<CpuLaunchData>;
} // namespace xmrig

View file

@ -5,6 +5,7 @@
* 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 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
@ -22,42 +23,50 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_APIROUTER_H
#define XMRIG_APIROUTER_H
#ifndef XMRIG_WORKERS_H
#define XMRIG_WORKERS_H
#include "api/interfaces/IApiListener.h"
#include "rapidjson/fwd.h"
class Hashrate;
#include "backend/common/Thread.h"
#include "backend/cpu/CpuLaunchData.h"
namespace xmrig {
class Base;
class Hashrate;
class WorkersPrivate;
class ApiRouter : public xmrig::IApiListener
template<class T>
class Workers
{
public:
ApiRouter(Base *base);
~ApiRouter() override;
Workers();
~Workers();
protected:
void onRequest(IApiRequest &request) override;
const Hashrate *hashrate() const;
void setBackend(IBackend *backend);
void start(const std::vector<T> &data);
void stop();
void tick(uint64_t ticks);
private:
void getHashrate(rapidjson::Value &reply, rapidjson::Document &doc) const;
void getMiner(rapidjson::Value &reply, rapidjson::Document &doc) const;
void getThreads(rapidjson::Value &reply, rapidjson::Document &doc) const;
static void onReady(void *arg);
Base *m_base;
std::vector<Thread<T> *> m_workers;
WorkersPrivate *d_ptr;
};
template<>
void Workers<CpuLaunchData>::onReady(void *arg);
extern template class Workers<CpuLaunchData>;
} // namespace xmrig
#endif /* XMRIG_APIROUTER_H */
#endif /* XMRIG_WORKERS_H */

View file

@ -0,0 +1,18 @@
set(HEADERS_BACKEND_COMMON
src/backend/common/interfaces/IBackend.h
src/backend/common/interfaces/IThread.h
src/backend/common/interfaces/IWorker.h
src/backend/common/Hashrate.h
src/backend/common/Thread.h
src/backend/common/Threads.h
src/backend/common/Worker.h
src/backend/common/Workers.h
src/backend/common/WorkerJob.h
)
set(SOURCES_BACKEND_COMMON
src/backend/common/Hashrate.cpp
src/backend/common/Threads.cpp
src/backend/common/Worker.cpp
src/backend/common/Workers.cpp
)

View file

@ -0,0 +1,70 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_IBACKEND_H
#define XMRIG_IBACKEND_H
#include <stdint.h>
#include "rapidjson/fwd.h"
namespace xmrig {
class Algorithm;
class Hashrate;
class IWorker;
class Job;
class String;
class IBackend
{
public:
virtual ~IBackend() = default;
virtual bool isEnabled() const = 0;
virtual bool isEnabled(const Algorithm &algorithm) const = 0;
virtual const Hashrate *hashrate() const = 0;
virtual const String &profileName() const = 0;
virtual const String &type() const = 0;
virtual void printHashrate(bool details) = 0;
virtual void setJob(const Job &job) = 0;
virtual void start(IWorker *worker) = 0;
virtual void stop() = 0;
virtual void tick(uint64_t ticks) = 0;
# ifdef XMRIG_FEATURE_API
virtual rapidjson::Value toJSON(rapidjson::Document &doc) const = 0;
# endif
};
} // namespace xmrig
#endif // XMRIG_IBACKEND_H

View file

@ -27,7 +27,7 @@
#include <stdint.h>
#include "common/xmrig.h"
#include "crypto/common/Algorithm.h"
#include "rapidjson/fwd.h"
@ -53,7 +53,7 @@ public:
virtual ~IThread() = default;
virtual Algo algorithm() const = 0;
virtual Algorithm algorithm() const = 0;
virtual int priority() const = 0;
virtual int64_t affinity() const = 0;
virtual Multiway multiway() const = 0;

View file

@ -27,6 +27,13 @@
#include <stdint.h>
#include <stddef.h>
namespace xmrig {
class VirtualMemory;
class IWorker
@ -35,6 +42,7 @@ public:
virtual ~IWorker() = default;
virtual bool selfTest() = 0;
virtual const VirtualMemory *memory() const = 0;
virtual size_t id() const = 0;
virtual uint64_t hashCount() const = 0;
virtual uint64_t timestamp() const = 0;
@ -42,4 +50,7 @@ public:
};
} // namespace xmrig
#endif // XMRIG_IWORKER_H

View file

@ -4,8 +4,9 @@
* 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>
*
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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
@ -25,11 +26,13 @@
#include <assert.h>
#include "common/cpu/Cpu.h"
#include "backend/cpu/Cpu.h"
#ifndef XMRIG_NO_LIBCPUID
# include "core/cpu/AdvancedCpuInfo.h"
#ifdef XMRIG_FEATURE_LIBCPUID
# include "backend/cpu/platform/AdvancedCpuInfo.h"
#else
# include "backend/cpu/platform/BasicCpuInfo.h"
#endif
@ -48,7 +51,11 @@ void xmrig::Cpu::init()
{
assert(cpuInfo == nullptr);
# ifdef XMRIG_FEATURE_LIBCPUID
cpuInfo = new AdvancedCpuInfo();
# else
cpuInfo = new BasicCpuInfo();
# endif
}

View file

@ -5,7 +5,8 @@
* 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 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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
@ -25,7 +26,7 @@
#define XMRIG_CPU_H
#include "common/interfaces/ICpuInfo.h"
#include "backend/cpu/interfaces/ICpuInfo.h"
namespace xmrig {
@ -37,6 +38,8 @@ public:
static ICpuInfo *info();
static void init();
static void release();
inline static Assembly::Id assembly(Assembly::Id hint) { return hint == Assembly::AUTO ? Cpu::info()->assembly() : hint; }
};

View file

@ -0,0 +1,343 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 <uv.h>
#include "backend/common/Hashrate.h"
#include "backend/common/interfaces/IWorker.h"
#include "backend/common/Workers.h"
#include "backend/cpu/Cpu.h"
#include "backend/cpu/CpuBackend.h"
#include "base/io/log/Log.h"
#include "base/net/stratum/Job.h"
#include "base/tools/Chrono.h"
#include "base/tools/String.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "crypto/common/VirtualMemory.h"
#include "crypto/rx/Rx.h"
#include "crypto/rx/RxDataset.h"
#include "rapidjson/document.h"
namespace xmrig {
extern template class Threads<CpuThread>;
static const String kType = "cpu";
struct LaunchStatus
{
public:
inline void reset()
{
hugePages = 0;
memory = 0;
pages = 0;
started = 0;
threads = 0;
ways = 0;
ts = Chrono::steadyMSecs();
}
size_t hugePages = 0;
size_t memory = 0;
size_t pages = 0;
size_t started = 0;
size_t threads = 0;
size_t ways = 0;
uint64_t ts = 0;
};
class CpuBackendPrivate
{
public:
inline CpuBackendPrivate(Controller *controller) :
controller(controller)
{
uv_mutex_init(&mutex);
}
inline ~CpuBackendPrivate()
{
uv_mutex_destroy(&mutex);
}
inline void start()
{
LOG_INFO(GREEN_BOLD("CPU") " use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"),
profileName.data(),
threads.size(),
algo.memory() / 1024
);
workers.stop();
status.reset();
status.memory = algo.memory();
status.threads = threads.size();
for (const CpuLaunchData &data : threads) {
status.ways += static_cast<size_t>(data.intensity);
}
workers.start(threads);
}
Algorithm algo;
Controller *controller;
LaunchStatus status;
std::vector<CpuLaunchData> threads;
String profileName;
uv_mutex_t mutex;
Workers<CpuLaunchData> workers;
};
} // namespace xmrig
xmrig::CpuBackend::CpuBackend(Controller *controller) :
d_ptr(new CpuBackendPrivate(controller))
{
d_ptr->workers.setBackend(this);
}
xmrig::CpuBackend::~CpuBackend()
{
delete d_ptr;
}
bool xmrig::CpuBackend::isEnabled() const
{
return d_ptr->controller->config()->cpu().isEnabled();
}
bool xmrig::CpuBackend::isEnabled(const Algorithm &algorithm) const
{
return !d_ptr->controller->config()->cpu().threads().get(algorithm).empty();
}
const xmrig::Hashrate *xmrig::CpuBackend::hashrate() const
{
return d_ptr->workers.hashrate();
}
const xmrig::String &xmrig::CpuBackend::profileName() const
{
return d_ptr->profileName;
}
const xmrig::String &xmrig::CpuBackend::type() const
{
return kType;
}
void xmrig::CpuBackend::printHashrate(bool details)
{
if (!details || !hashrate()) {
return;
}
char num[8 * 3] = { 0 };
Log::print(WHITE_BOLD_S "| CPU THREAD | AFFINITY | 10s H/s | 60s H/s | 15m H/s |");
size_t i = 0;
for (const CpuLaunchData &data : d_ptr->threads) {
Log::print("| %13zu | %8" PRId64 " | %7s | %7s | %7s |",
i,
data.affinity,
Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval), num, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval), num + 8, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3)
);
i++;
}
}
void xmrig::CpuBackend::setJob(const Job &job)
{
if (!isEnabled()) {
d_ptr->workers.stop();
d_ptr->threads.clear();
return;
}
const CpuConfig &cpu = d_ptr->controller->config()->cpu();
std::vector<CpuLaunchData> threads = cpu.get(d_ptr->controller->miner(), job.algorithm());
if (d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) {
return;
}
d_ptr->algo = job.algorithm();
d_ptr->profileName = cpu.threads().profileName(job.algorithm());
if (d_ptr->profileName.isNull() || threads.empty()) {
d_ptr->workers.stop();
LOG_WARN(YELLOW_BOLD_S "CPU disabled, no suitable configuration for algo %s", job.algorithm().shortName());
return;
}
d_ptr->threads = std::move(threads);
d_ptr->start();
}
void xmrig::CpuBackend::start(IWorker *worker)
{
uv_mutex_lock(&d_ptr->mutex);
const auto pages = worker->memory()->hugePages();
d_ptr->status.started++;
d_ptr->status.hugePages += pages.first;
d_ptr->status.pages += pages.second;
if (d_ptr->status.started == d_ptr->status.threads) {
const double percent = d_ptr->status.hugePages == 0 ? 0.0 : static_cast<double>(d_ptr->status.hugePages) / d_ptr->status.pages * 100.0;
const size_t memory = d_ptr->status.ways * d_ptr->status.memory / 1024;
LOG_INFO(GREEN_BOLD("CPU READY") " threads " CYAN_BOLD("%zu(%zu)") " huge pages %s%zu/%zu %1.0f%%\x1B[0m memory " CYAN_BOLD("%zu KB") BLACK_BOLD(" (%" PRIu64 " ms)"),
d_ptr->status.threads, d_ptr->status.ways,
(d_ptr->status.hugePages == d_ptr->status.pages ? GREEN_BOLD_S : (d_ptr->status.hugePages == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
d_ptr->status.hugePages, d_ptr->status.pages, percent, memory,
Chrono::steadyMSecs() - d_ptr->status.ts
);
}
uv_mutex_unlock(&d_ptr->mutex);
worker->start();
}
void xmrig::CpuBackend::stop()
{
d_ptr->workers.stop();
}
void xmrig::CpuBackend::tick(uint64_t ticks)
{
d_ptr->workers.tick(ticks);
}
#ifdef XMRIG_FEATURE_API
rapidjson::Value xmrig::CpuBackend::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
const CpuConfig &cpu = d_ptr->controller->config()->cpu();
Value out(kObjectType);
out.AddMember("type", type().toJSON(), allocator);
out.AddMember("enabled", isEnabled(), allocator);
out.AddMember("algo", d_ptr->algo.toJSON(), allocator);
out.AddMember("profile", profileName().toJSON(), allocator);
out.AddMember("hw-aes", cpu.isHwAES(), allocator);
out.AddMember("priority", cpu.priority(), allocator);
# ifdef XMRIG_FEATURE_ASM
const Assembly assembly = Cpu::assembly(cpu.assembly());
out.AddMember("asm", assembly.toJSON(), allocator);
# else
out.AddMember("asm", false, allocator);
# endif
uv_mutex_lock(&d_ptr->mutex);
uint64_t pages[2] = { d_ptr->status.hugePages, d_ptr->status.pages };
const size_t ways = d_ptr->status.ways;
uv_mutex_unlock(&d_ptr->mutex);
# ifdef XMRIG_ALGO_RANDOMX
if (d_ptr->algo.family() == Algorithm::RANDOM_X) {
RxDataset *dataset = Rx::dataset();
if (dataset) {
const auto rxPages = dataset->hugePages();
pages[0] += rxPages.first;
pages[1] += rxPages.second;
}
}
# endif
rapidjson::Value hugepages(rapidjson::kArrayType);
hugepages.PushBack(pages[0], allocator);
hugepages.PushBack(pages[1], allocator);
out.AddMember("hugepages", hugepages, allocator);
out.AddMember("memory", static_cast<uint64_t>(d_ptr->algo.isValid() ? (ways * d_ptr->algo.memory()) : 0), allocator);
if (d_ptr->threads.empty() || !hashrate()) {
return out;
}
Value threads(kArrayType);
const Hashrate *hr = hashrate();
size_t i = 0;
for (const CpuLaunchData &data : d_ptr->threads) {
Value thread(kObjectType);
thread.AddMember("intensity", data.intensity, allocator);
thread.AddMember("affinity", data.affinity, allocator);
thread.AddMember("av", data.av(), allocator);
Value hashrate(kArrayType);
hashrate.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
hashrate.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
hashrate.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
i++;
thread.AddMember("hashrate", hashrate, allocator);
threads.PushBack(thread, allocator);
}
out.AddMember("threads", threads, allocator);
return out;
}
#endif

View file

@ -22,42 +22,49 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_THREADHANDLE_H
#define XMRIG_THREADHANDLE_H
#ifndef XMRIG_CPUBACKEND_H
#define XMRIG_CPUBACKEND_H
#include <assert.h>
#include <stdint.h>
#include <uv.h>
#include "backend/common/interfaces/IBackend.h"
#include "interfaces/IThread.h"
namespace xmrig {
class IWorker;
class Controller;
class CpuBackendPrivate;
class Miner;
class ThreadHandle
class CpuBackend : public IBackend
{
public:
ThreadHandle(xmrig::IThread *config, uint32_t offset, size_t totalWays);
void join();
void start(void (*callback) (void *));
CpuBackend(Controller *controller);
~CpuBackend() override;
inline IWorker *worker() const { return m_worker; }
inline size_t threadId() const { return m_config->index(); }
inline size_t totalWays() const { return m_totalWays; }
inline uint32_t offset() const { return m_offset; }
inline void setWorker(IWorker *worker) { assert(worker != nullptr); m_worker = worker; }
inline xmrig::IThread *config() const { return m_config; }
protected:
bool isEnabled() const override;
bool isEnabled(const Algorithm &algorithm) const override;
const Hashrate *hashrate() const override;
const String &profileName() const override;
const String &type() const override;
void printHashrate(bool details) override;
void setJob(const Job &job) override;
void start(IWorker *worker) override;
void stop() override;
void tick(uint64_t ticks) override;
# ifdef XMRIG_FEATURE_API
rapidjson::Value toJSON(rapidjson::Document &doc) const override;
# endif
private:
IWorker *m_worker;
size_t m_totalWays;
uint32_t m_offset;
uv_thread_t m_thread;
xmrig::IThread *m_config;
CpuBackendPrivate *d_ptr;
};
#endif /* XMRIG_THREADHANDLE_H */
} /* namespace xmrig */
#endif /* XMRIG_CPUBACKEND_H */

View file

@ -0,0 +1,187 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 "backend/cpu/Cpu.h"
#include "backend/cpu/CpuConfig.h"
#include "base/io/json/Json.h"
#include "rapidjson/document.h"
namespace xmrig {
static const char *kCn = "cn";
static const char *kEnabled = "enabled";
static const char *kHugePages = "huge-pages";
static const char *kHwAes = "hw-aes";
static const char *kPriority = "priority";
#ifdef XMRIG_FEATURE_ASM
static const char *kAsm = "asm";
#endif
#ifdef XMRIG_ALGO_CN_GPU
static const char *kCnGPU = "cn/gpu";
#endif
#ifdef XMRIG_ALGO_CN_LITE
static const char *kCnLite = "cn-lite";
#endif
#ifdef XMRIG_ALGO_CN_HEAVY
static const char *kCnHeavy = "cn-heavy";
#endif
#ifdef XMRIG_ALGO_CN_PICO
static const char *kCnPico = "cn-pico";
#endif
#ifdef XMRIG_ALGO_RANDOMX
static const char *kRx = "rx";
static const char *kRxWOW = "rx/wow";
#endif
extern template class Threads<CpuThread>;
}
xmrig::CpuConfig::CpuConfig()
{
}
bool xmrig::CpuConfig::isHwAES() const
{
return (m_aes == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aes) == AES_HW;
}
rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value obj(kObjectType);
obj.AddMember(StringRef(kEnabled), m_enabled, allocator);
obj.AddMember(StringRef(kHugePages), m_hugePages, allocator);
obj.AddMember(StringRef(kHwAes), m_aes == AES_AUTO ? Value(kNullType) : Value(m_aes == AES_HW), allocator);
obj.AddMember(StringRef(kPriority), priority() != -1 ? Value(priority()) : Value(kNullType), allocator);
# ifdef XMRIG_FEATURE_ASM
obj.AddMember(StringRef(kAsm), m_assembly.toJSON(), allocator);
# endif
m_threads.toJSON(obj, doc);
return obj;
}
std::vector<xmrig::CpuLaunchData> xmrig::CpuConfig::get(const Miner *miner, const Algorithm &algorithm) const
{
std::vector<CpuLaunchData> out;
const std::vector<CpuThread> &threads = m_threads.get(algorithm);
if (threads.empty()) {
return out;
}
out.reserve(threads.size());
for (const CpuThread &thread : threads) {
out.push_back(CpuLaunchData(miner, algorithm, *this, thread));
}
return out;
}
void xmrig::CpuConfig::read(const rapidjson::Value &value)
{
if (value.IsObject()) {
m_enabled = Json::getBool(value, kEnabled, m_enabled);
m_hugePages = Json::getBool(value, kHugePages, m_hugePages);
setAesMode(Json::getValue(value, kHwAes));
setPriority(Json::getInt(value, kPriority, -1));
# ifdef XMRIG_FEATURE_ASM
m_assembly = Json::getValue(value, kAsm);
# endif
if (!m_threads.read(value)) {
generate();
}
}
else if (value.IsBool() && value.IsFalse()) {
m_enabled = false;
}
else {
generate();
}
}
void xmrig::CpuConfig::generate()
{
m_shouldSave = true;
m_threads.disable(Algorithm::CN_0);
m_threads.move(kCn, Cpu::info()->threads(Algorithm::CN_0));
# ifdef XMRIG_ALGO_CN_GPU
m_threads.move(kCnGPU, Cpu::info()->threads(Algorithm::CN_GPU));
# endif
# ifdef XMRIG_ALGO_CN_LITE
m_threads.disable(Algorithm::CN_LITE_0);
m_threads.move(kCnLite, Cpu::info()->threads(Algorithm::CN_LITE_1));
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
m_threads.move(kCnHeavy, Cpu::info()->threads(Algorithm::CN_HEAVY_0));
# endif
# ifdef XMRIG_ALGO_CN_PICO
m_threads.move(kCnPico, Cpu::info()->threads(Algorithm::CN_PICO_0));
# endif
# ifdef XMRIG_ALGO_RANDOMX
m_threads.move(kRx, Cpu::info()->threads(Algorithm::RX_0));
m_threads.move(kRxWOW, Cpu::info()->threads(Algorithm::RX_WOW));
# endif
}
void xmrig::CpuConfig::setAesMode(const rapidjson::Value &aesMode)
{
if (aesMode.IsBool()) {
m_aes = aesMode.GetBool() ? AES_HW : AES_SOFT;
}
else {
m_aes = AES_AUTO;
}
}

View file

@ -0,0 +1,80 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_CPUCONFIG_H
#define XMRIG_CPUCONFIG_H
#include "backend/common/Threads.h"
#include "backend/cpu/CpuLaunchData.h"
#include "backend/cpu/CpuThread.h"
#include "crypto/common/Assembly.h"
namespace xmrig {
class CpuConfig
{
public:
enum AesMode {
AES_AUTO,
AES_HW,
AES_SOFT
};
CpuConfig();
bool isHwAES() const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
std::vector<CpuLaunchData> get(const Miner *miner, const Algorithm &algorithm) const;
void read(const rapidjson::Value &value);
inline bool isEnabled() const { return m_enabled; }
inline bool isHugePages() const { return m_hugePages; }
inline bool isShouldSave() const { return m_shouldSave; }
inline const Assembly &assembly() const { return m_assembly; }
inline const Threads<CpuThread> &threads() const { return m_threads; }
inline int priority() const { return m_priority; }
private:
void generate();
void setAesMode(const rapidjson::Value &aesMode);
inline void setPriority(int priority) { m_priority = (priority >= -1 && priority <= 5) ? priority : -1; }
AesMode m_aes = AES_AUTO;
Assembly m_assembly;
bool m_enabled = true;
bool m_hugePages = true;
bool m_shouldSave = false;
int m_priority = -1;
Threads<CpuThread> m_threads;
};
} /* namespace xmrig */
#endif /* XMRIG_CPUCONFIG_H */

View file

@ -24,66 +24,41 @@
*/
#include <stdlib.h>
#include <sys/mman.h>
#include "backend/cpu/CpuLaunchData.h"
#include "backend/cpu/CpuConfig.h"
#include "base/io/log/Log.h"
#include "common/xmrig.h"
#include "crypto/common/portable/mm_malloc.h"
#include "crypto/common/VirtualMemory.h"
#include "crypto/cn/CryptoNight.h"
#include "Mem.h"
#if defined(__APPLE__)
# include <mach/vm_statistics.h>
#endif
void Mem::init(bool enabled)
xmrig::CpuLaunchData::CpuLaunchData(const Miner *miner, const Algorithm &algorithm, const CpuConfig &config, const CpuThread &thread) :
algorithm(algorithm),
assembly(config.assembly()),
hugePages(config.isHugePages()),
hwAES(config.isHwAES()),
intensity(thread.intensity()),
priority(config.priority()),
affinity(thread.affinity()),
miner(miner)
{
m_enabled = enabled;
}
void Mem::allocate(MemInfo &info, bool enabled)
bool xmrig::CpuLaunchData::isEqual(const CpuLaunchData &other) const
{
info.hugePages = 0;
if (!enabled) {
info.memory = static_cast<uint8_t*>(_mm_malloc(info.size, 4096));
return;
}
info.memory = static_cast<uint8_t*>(xmrig::VirtualMemory::allocateLargePagesMemory(info.size));
if (!info.memory) {
return allocate(info, false);;
}
info.hugePages = info.pages;
if (madvise(info.memory, info.size, MADV_RANDOM | MADV_WILLNEED) != 0) {
LOG_ERR("madvise failed");
}
if (mlock(info.memory, info.size) == 0) {
m_flags |= Lock;
}
return (algorithm.memory() == other.algorithm.memory()
&& assembly == other.assembly
&& hugePages == other.hugePages
&& hwAES == other.hwAES
&& intensity == other.intensity
&& priority == other.priority
&& affinity == other.affinity
);
}
void Mem::release(MemInfo &info)
xmrig::CnHash::AlgoVariant xmrig::CpuLaunchData::av() const
{
if (info.hugePages) {
if (m_flags & Lock) {
munlock(info.memory, info.size);
if (intensity <= 2) {
return static_cast<CnHash::AlgoVariant>(!hwAES ? (intensity + 2) : intensity);
}
xmrig::VirtualMemory::freeLargePagesMemory(info.memory, info.size);
}
else {
_mm_free(info.memory);
}
return static_cast<CnHash::AlgoVariant>(!hwAES ? (intensity + 5) : (intensity + 2));
}

View file

@ -0,0 +1,71 @@
/* 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 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_CPULAUNCHDATA_H
#define XMRIG_CPULAUNCHDATA_H
#include "crypto/cn/CnHash.h"
#include "crypto/common/Algorithm.h"
#include "crypto/common/Assembly.h"
#include "crypto/common/Nonce.h"
namespace xmrig {
class CpuConfig;
class CpuThread;
class Miner;
class CpuLaunchData
{
public:
CpuLaunchData(const Miner *miner, const Algorithm &algorithm, const CpuConfig &config, const CpuThread &thread);
bool isEqual(const CpuLaunchData &other) const;
CnHash::AlgoVariant av() const;
inline constexpr static Nonce::Backend backend() { return Nonce::CPU; }
inline bool operator!=(const CpuLaunchData &other) const { return !isEqual(other); }
inline bool operator==(const CpuLaunchData &other) const { return isEqual(other); }
const Algorithm algorithm;
const Assembly assembly;
const bool hugePages;
const bool hwAES;
const int intensity;
const int priority;
const int64_t affinity;
const Miner *miner;
};
} // namespace xmrig
#endif /* XMRIG_CPULAUNCHDATA_H */

View file

@ -0,0 +1,71 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 "backend/cpu/CpuThread.h"
#include "base/io/json/Json.h"
#include "rapidjson/document.h"
namespace xmrig {
static const char *kAffinity = "affinity";
static const char *kIntensity = "intensity";
}
xmrig::CpuThread::CpuThread(const rapidjson::Value &value)
{
if (value.IsObject()) {
m_intensity = Json::getInt(value, kIntensity, -1);
m_affinity = Json::getInt(value, kAffinity, -1);
}
else if (value.IsInt()) {
m_intensity = 1;
m_affinity = value.GetInt();
}
}
rapidjson::Value xmrig::CpuThread::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
if (intensity() > 1) {
auto &allocator = doc.GetAllocator();
Value obj(kObjectType);
obj.AddMember(StringRef(kIntensity), m_intensity, allocator);
obj.AddMember(StringRef(kAffinity), m_affinity, allocator);
return obj;
}
return Value(m_affinity);
}

View file

@ -0,0 +1,67 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_CPUTHREADCONFIG_H
#define XMRIG_CPUTHREADCONFIG_H
#include <vector>
#include "rapidjson/fwd.h"
namespace xmrig {
class CpuThread
{
public:
inline constexpr CpuThread(int intensity = 1, int64_t affinity = -1) : m_intensity(intensity), m_affinity(affinity) {}
CpuThread(const rapidjson::Value &value);
inline bool isEqual(const CpuThread &other) const { return other.m_affinity == m_affinity && other.m_intensity == m_intensity; }
inline bool isValid() const { return m_intensity >= 1 && m_intensity <= 5; }
inline int intensity() const { return m_intensity; }
inline int64_t affinity() const { return m_affinity; }
inline bool operator!=(const CpuThread &other) const { return !isEqual(other); }
inline bool operator==(const CpuThread &other) const { return isEqual(other); }
rapidjson::Value toJSON(rapidjson::Document &doc) const;
private:
int m_intensity = -1;
int64_t m_affinity = -1;
};
typedef std::vector<CpuThread> CpuThreads;
} /* namespace xmrig */
#endif /* XMRIG_CPUTHREADCONFIG_H */

View file

@ -0,0 +1,307 @@
/* 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 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 <thread>
#include "backend/cpu/CpuWorker.h"
#include "core/Miner.h"
#include "crypto/cn/CnCtx.h"
#include "crypto/cn/CryptoNight_test.h"
#include "crypto/common/Nonce.h"
#include "crypto/common/VirtualMemory.h"
#include "crypto/rx/Rx.h"
#include "crypto/rx/RxVm.h"
#include "net/JobResults.h"
#ifdef XMRIG_ALGO_RANDOMX
# include "crypto/randomx/randomx.h"
#endif
namespace xmrig {
static constexpr uint32_t kReserveCount = 4096;
} // namespace xmrig
template<size_t N>
xmrig::CpuWorker<N>::CpuWorker(size_t index, const CpuLaunchData &data) :
Worker(index, data.affinity, data.priority),
m_algorithm(data.algorithm),
m_assembly(data.assembly),
m_hwAES(data.hwAES),
m_av(data.av()),
m_miner(data.miner),
m_ctx()
{
m_memory = new VirtualMemory(m_algorithm.memory() * N, data.hugePages);
}
template<size_t N>
xmrig::CpuWorker<N>::~CpuWorker()
{
CnCtx::release(m_ctx, N);
delete m_memory;
# ifdef XMRIG_ALGO_RANDOMX
delete m_vm;
# endif
}
#ifdef XMRIG_ALGO_RANDOMX
template<size_t N>
void xmrig::CpuWorker<N>::allocateRandomX_VM()
{
if (!m_vm) {
RxDataset *dataset = Rx::dataset(m_job.currentJob().seedHash(), m_job.currentJob().algorithm());
m_vm = new RxVm(dataset, m_memory->scratchpad(), !m_hwAES);
}
}
#endif
template<size_t N>
bool xmrig::CpuWorker<N>::selfTest()
{
# ifdef XMRIG_ALGO_RANDOMX
if (m_algorithm.family() == Algorithm::RANDOM_X) {
return true;
}
# endif
allocateCnCtx();
if (m_algorithm.family() == Algorithm::CN) {
const bool rc = verify(Algorithm::CN_0, test_output_v0) &&
verify(Algorithm::CN_1, test_output_v1) &&
verify(Algorithm::CN_2, test_output_v2) &&
verify(Algorithm::CN_FAST, test_output_msr) &&
verify(Algorithm::CN_XAO, test_output_xao) &&
verify(Algorithm::CN_RTO, test_output_rto) &&
verify(Algorithm::CN_HALF, test_output_half) &&
verify2(Algorithm::CN_WOW, test_output_wow) &&
verify2(Algorithm::CN_R, test_output_r) &&
verify(Algorithm::CN_RWZ, test_output_rwz) &&
verify(Algorithm::CN_ZLS, test_output_zls) &&
verify(Algorithm::CN_DOUBLE, test_output_double);
# ifdef XMRIG_ALGO_CN_GPU
if (!rc || N > 1) {
return rc;
}
return verify(Algorithm::CN_GPU, test_output_gpu);
# else
return rc;
# endif
}
# ifdef XMRIG_ALGO_CN_LITE
if (m_algorithm.family() == Algorithm::CN_LITE) {
return verify(Algorithm::CN_LITE_0, test_output_v0_lite) &&
verify(Algorithm::CN_LITE_1, test_output_v1_lite);
}
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
if (m_algorithm.family() == Algorithm::CN_HEAVY) {
return verify(Algorithm::CN_HEAVY_0, test_output_v0_heavy) &&
verify(Algorithm::CN_HEAVY_XHV, test_output_xhv_heavy) &&
verify(Algorithm::CN_HEAVY_TUBE, test_output_tube_heavy);
}
# endif
# ifdef XMRIG_ALGO_CN_PICO
if (m_algorithm.family() == Algorithm::CN_PICO) {
return verify(Algorithm::CN_PICO_0, test_output_pico_trtl);
}
# endif
return false;
}
template<size_t N>
void xmrig::CpuWorker<N>::start()
{
while (Nonce::sequence(Nonce::CPU) > 0) {
if (Nonce::isPaused()) {
do {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
while (Nonce::isPaused() && Nonce::sequence(Nonce::CPU) > 0);
if (Nonce::sequence(Nonce::CPU) == 0) {
break;
}
consumeJob();
}
while (!Nonce::isOutdated(Nonce::CPU, m_job.sequence())) {
if ((m_count & 0x7) == 0) {
storeStats();
}
const Job &job = m_job.currentJob();
if (job.algorithm().memory() != m_algorithm.memory()) {
break;
}
# ifdef XMRIG_ALGO_RANDOMX
if (job.algorithm().family() == Algorithm::RANDOM_X) {
randomx_calculate_hash(m_vm->get(), m_job.blob(), job.size(), m_hash);
}
else
# endif
{
fn(job.algorithm())(m_job.blob(), job.size(), m_hash, m_ctx, job.height());
}
for (size_t i = 0; i < N; ++i) {
if (*reinterpret_cast<uint64_t*>(m_hash + (i * 32) + 24) < job.target()) {
JobResults::submit(JobResult(job, *m_job.nonce(i), m_hash + (i * 32)));
}
}
m_job.nextRound(kReserveCount);
m_count += N;
std::this_thread::yield();
}
consumeJob();
}
}
template<size_t N>
bool xmrig::CpuWorker<N>::verify(const Algorithm &algorithm, const uint8_t *referenceValue)
{
cn_hash_fun func = fn(algorithm);
if (!func) {
return false;
}
func(test_input, 76, m_hash, m_ctx, 0);
return memcmp(m_hash, referenceValue, sizeof m_hash) == 0;
}
template<size_t N>
bool xmrig::CpuWorker<N>::verify2(const Algorithm &algorithm, const uint8_t *referenceValue)
{
cn_hash_fun func = fn(algorithm);
if (!func) {
return false;
}
for (size_t i = 0; i < (sizeof(cn_r_test_input) / sizeof(cn_r_test_input[0])); ++i) {
const size_t size = cn_r_test_input[i].size;
for (size_t k = 0; k < N; ++k) {
memcpy(m_job.blob() + (k * size), cn_r_test_input[i].data, size);
}
func(m_job.blob(), size, m_hash, m_ctx, cn_r_test_input[i].height);
for (size_t k = 0; k < N; ++k) {
if (memcmp(m_hash + k * 32, referenceValue + i * 32, sizeof m_hash / N) != 0) {
return false;
}
}
}
return true;
}
namespace xmrig {
template<>
bool CpuWorker<1>::verify2(const Algorithm &algorithm, const uint8_t *referenceValue)
{
cn_hash_fun func = fn(algorithm);
if (!func) {
return false;
}
for (size_t i = 0; i < (sizeof(cn_r_test_input) / sizeof(cn_r_test_input[0])); ++i) {
func(cn_r_test_input[i].data, cn_r_test_input[i].size, m_hash, m_ctx, cn_r_test_input[i].height);
if (memcmp(m_hash, referenceValue + i * 32, sizeof m_hash) != 0) {
return false;
}
}
return true;
}
} // namespace xmrig
template<size_t N>
void xmrig::CpuWorker<N>::allocateCnCtx()
{
if (m_ctx[0] == nullptr) {
CnCtx::create(m_ctx, m_memory->scratchpad(), m_algorithm.memory(), N);
}
}
template<size_t N>
void xmrig::CpuWorker<N>::consumeJob()
{
m_job.add(m_miner->job(), Nonce::sequence(Nonce::CPU), kReserveCount);
# ifdef XMRIG_ALGO_RANDOMX
if (m_job.currentJob().algorithm().family() == Algorithm::RANDOM_X) {
allocateRandomX_VM();
}
else
# endif
{
allocateCnCtx();
}
}
namespace xmrig {
template class CpuWorker<1>;
template class CpuWorker<2>;
template class CpuWorker<3>;
template class CpuWorker<4>;
template class CpuWorker<5>;
} // namespace xmrig

View file

@ -23,67 +23,76 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_MULTIWORKER_H
#define XMRIG_MULTIWORKER_H
#ifdef XMRIG_ALGO_RANDOMX
# include <randomx.h>
#endif
#ifndef XMRIG_CPUWORKER_H
#define XMRIG_CPUWORKER_H
#include "backend/common/Worker.h"
#include "backend/common/WorkerJob.h"
#include "backend/cpu/CpuLaunchData.h"
#include "base/net/stratum/Job.h"
#include "Mem.h"
#include "net/JobResult.h"
#include "workers/Worker.h"
class Handle;
namespace xmrig {
class RxVm;
template<size_t N>
class MultiWorker : public Worker
class CpuWorker : public Worker
{
public:
MultiWorker(ThreadHandle *handle);
~MultiWorker();
CpuWorker(size_t index, const CpuLaunchData &data);
~CpuWorker() override;
protected:
bool selfTest() override;
void start() override;
inline const VirtualMemory *memory() const override { return m_memory; }
private:
inline cn_hash_fun fn(const Algorithm &algorithm) const { return CnHash::fn(algorithm, m_av, m_assembly); }
# ifdef XMRIG_ALGO_RANDOMX
void allocateRandomX_VM();
# endif
bool resume(const xmrig::Job &job);
bool verify(xmrig::Variant variant, const uint8_t *referenceValue);
bool verify2(xmrig::Variant variant, const uint8_t *referenceValue);
bool verify(const Algorithm &algorithm, const uint8_t *referenceValue);
bool verify2(const Algorithm &algorithm, const uint8_t *referenceValue);
void allocateCnCtx();
void consumeJob();
void save(const xmrig::Job &job);
inline uint32_t *nonce(size_t index)
{
return reinterpret_cast<uint32_t*>(m_state.blob + (index * m_state.job.size()) + 39);
}
struct State
{
alignas(16) uint8_t blob[xmrig::Job::kMaxBlobSize * N];
xmrig::Job job;
};
const Algorithm m_algorithm;
const Assembly m_assembly;
const bool m_hwAES;
const CnHash::AlgoVariant m_av;
const Miner *m_miner;
cryptonight_ctx *m_ctx[N];
State m_pausedState;
State m_state;
uint8_t m_hash[N * 32];
VirtualMemory *m_memory = nullptr;
WorkerJob<N> m_job;
# ifdef XMRIG_ALGO_RANDOMX
randomx_vm *m_rx_vm = nullptr;
RxVm *m_vm = nullptr;
# endif
};
#endif /* XMRIG_MULTIWORKER_H */
template<>
bool CpuWorker<1>::verify2(const Algorithm &algorithm, const uint8_t *referenceValue);
extern template class CpuWorker<1>;
extern template class CpuWorker<2>;
extern template class CpuWorker<3>;
extern template class CpuWorker<4>;
extern template class CpuWorker<5>;
} // namespace xmrig
#endif /* XMRIG_CPUWORKER_H */

37
src/backend/cpu/cpu.cmake Normal file
View file

@ -0,0 +1,37 @@
set(HEADERS_BACKEND_CPU
src/backend/cpu/Cpu.h
src/backend/cpu/CpuBackend.h
src/backend/cpu/CpuConfig.h
src/backend/cpu/CpuLaunchData.cpp
src/backend/cpu/CpuThread.h
src/backend/cpu/CpuWorker.h
src/backend/cpu/interfaces/ICpuInfo.h
)
set(SOURCES_BACKEND_CPU
src/backend/cpu/Cpu.cpp
src/backend/cpu/CpuBackend.cpp
src/backend/cpu/CpuConfig.cpp
src/backend/cpu/CpuLaunchData.h
src/backend/cpu/CpuThread.cpp
src/backend/cpu/CpuWorker.cpp
)
if (WITH_LIBCPUID)
add_subdirectory(src/3rdparty/libcpuid)
include_directories(src/3rdparty/libcpuid)
add_definitions(/DXMRIG_FEATURE_LIBCPUID)
set(CPUID_LIB cpuid)
set(SOURCES_CPUID src/backend/cpu/platform/AdvancedCpuInfo.h src/backend/cpu/platform/AdvancedCpuInfo.cpp src/backend/cpu/Cpu.cpp)
else()
remove_definitions(/DXMRIG_FEATURE_LIBCPUID)
set(SOURCES_CPUID src/backend/cpu/platform/BasicCpuInfo.h src/backend/cpu/Cpu.cpp)
if (XMRIG_ARM)
set(SOURCES_CPUID ${SOURCES_CPUID} src/backend/cpu/platform/BasicCpuInfo_arm.cpp)
else()
set(SOURCES_CPUID ${SOURCES_CPUID} src/backend/cpu/platform/BasicCpuInfo.cpp)
endif()
endif()

View file

@ -26,11 +26,9 @@
#define XMRIG_CPUINFO_H
#include <stddef.h>
#include <stdint.h>
#include "common/xmrig.h"
#include "backend/cpu/CpuThread.h"
#include "crypto/common/Assembly.h"
#include "crypto/common/Algorithm.h"
namespace xmrig {
@ -39,21 +37,26 @@ namespace xmrig {
class ICpuInfo
{
public:
virtual ~ICpuInfo() {}
virtual ~ICpuInfo() = default;
# if defined(__x86_64__) || defined(_M_AMD64) || defined (__arm64__) || defined (__aarch64__)
inline constexpr static bool isX64() { return true; }
# else
inline constexpr static bool isX64() { return false; }
# endif
virtual Assembly::Id assembly() const = 0;
virtual bool hasAES() const = 0;
virtual bool hasAVX2() const = 0;
virtual bool isSupported() const = 0;
virtual bool isX64() const = 0;
virtual const char *brand() const = 0;
virtual int32_t cores() const = 0;
virtual int32_t L2() const = 0;
virtual int32_t L3() const = 0;
virtual int32_t nodes() const = 0;
virtual int32_t sockets() const = 0;
virtual int32_t threads() const = 0;
virtual size_t optimalThreadsCount(size_t memSize, int maxCpuUsage) const = 0;
virtual xmrig::Assembly assembly() const = 0;
virtual CpuThreads threads(const Algorithm &algorithm) const = 0;
virtual size_t cores() const = 0;
virtual size_t L2() const = 0;
virtual size_t L3() const = 0;
virtual size_t nodes() const = 0;
virtual size_t sockets() const = 0;
virtual size_t threads() const = 0;
};

View file

@ -22,66 +22,57 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <assert.h>
#include <libcpuid.h>
#include <math.h>
#include <string.h>
#include "core/cpu/AdvancedCpuInfo.h"
#include "backend/cpu/platform/AdvancedCpuInfo.h"
xmrig::AdvancedCpuInfo::AdvancedCpuInfo() :
m_assembly(ASM_NONE),
m_aes(false),
m_avx2(false),
m_L2_exclusive(false),
m_brand(),
m_cores(0),
m_L2(0),
m_L3(0),
m_sockets(1),
m_threads(0)
m_brand()
{
struct cpu_raw_data_t raw = { 0 };
struct cpu_id_t data = { 0 };
struct cpu_raw_data_t raw = {};
struct cpu_id_t data = {};
cpuid_get_raw_data(&raw);
cpu_identify(&raw, &data);
strncpy(m_brand, data.brand_str, sizeof(m_brand));
m_threads = data.total_logical_cpus;
m_sockets = threads() / data.num_logical_cpus;
if (m_sockets == 0) {
m_sockets = 1;
}
m_threads = static_cast<size_t>(data.total_logical_cpus);
m_sockets = std::max<size_t>(threads() / static_cast<size_t>(data.num_logical_cpus), 1);
m_cores = static_cast<size_t>(data.num_cores) * m_sockets;
m_L3 = data.l3_cache > 0 ? static_cast<size_t>(data.l3_cache) * m_sockets : 0;
m_cores = data.num_cores * m_sockets;
m_L3 = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0;
const size_t l2 = static_cast<size_t>(data.l2_cache);
// Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97
if (data.vendor == VENDOR_AMD && data.ext_family >= 0x15 && data.ext_family < 0x17) {
m_L2 = data.l2_cache * (cores() / 2) * m_sockets;
m_L2 = l2 * (cores() / 2) * m_sockets;
m_L2_exclusive = true;
}
// Workaround for Intel Pentium Dual-Core, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue
// These processors have L2 cache shared by 2 cores.
else if (data.vendor == VENDOR_INTEL && data.ext_family == 0x06 && (data.ext_model == 0x0E || data.ext_model == 0x0F || data.ext_model == 0x17)) {
int l2_count_per_socket = cores() > 1 ? cores() / 2 : 1;
m_L2 = data.l2_cache > 0 ? data.l2_cache * l2_count_per_socket * m_sockets : 0;
size_t l2_count_per_socket = cores() > 1 ? cores() / 2 : 1;
m_L2 = data.l2_cache > 0 ? l2 * l2_count_per_socket * m_sockets : 0;
}
else{
m_L2 = data.l2_cache > 0 ? data.l2_cache * cores() * m_sockets : 0;
m_L2 = data.l2_cache > 0 ? l2 * cores() * m_sockets : 0;
}
if (data.flags[CPU_FEATURE_AES]) {
m_aes = true;
if (data.vendor == VENDOR_AMD) {
m_assembly = (data.ext_family >= 23) ? ASM_RYZEN : ASM_BULLDOZER;
m_assembly = (data.ext_family >= 23) ? Assembly::RYZEN : Assembly::BULLDOZER;
}
else if (data.vendor == VENDOR_INTEL) {
m_assembly = ASM_INTEL;
m_assembly = Assembly::INTEL;
}
}
@ -89,13 +80,21 @@ xmrig::AdvancedCpuInfo::AdvancedCpuInfo() :
}
size_t xmrig::AdvancedCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsage) const
xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm) const
{
if (threads() == 1) {
return 1;
return CpuThreads(1);
}
# ifdef XMRIG_ALGO_CN_GPU
if (algorithm == Algorithm::CN_GPU) {
return CpuThreads(threads());
}
# endif
size_t cache = 0;
size_t count = 0;
if (m_L3) {
cache = m_L2_exclusive ? (m_L2 + m_L3) : m_L3;
}
@ -103,12 +102,14 @@ size_t xmrig::AdvancedCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsa
cache = m_L2;
}
size_t count = 0;
if (cache) {
count = cache / memSize;
cache *= 1024;
const size_t memory = algorithm.memory();
assert(memory > 0);
if (cache % memSize >= memSize / 2) {
count = cache / memory;
if (cache % memory >= memory / 2) {
count++;
}
}
@ -116,13 +117,5 @@ size_t xmrig::AdvancedCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsa
count = threads() / 2;
}
if (count > (size_t) threads()) {
count = threads();
}
if (((float) count / threads() * 100) > maxCpuUsage) {
count = (int) ceil((float) threads() * (maxCpuUsage / 100.0));
}
return count < 1 ? 1 : count;
return CpuThreads(std::max<size_t>(std::min<size_t>(count, threads()), 1));
}

View file

@ -26,7 +26,7 @@
#define XMRIG_ADVANCEDCPUINFO_H
#include "common/interfaces/ICpuInfo.h"
#include "backend/cpu/interfaces/ICpuInfo.h"
namespace xmrig {
@ -38,37 +38,31 @@ public:
AdvancedCpuInfo();
protected:
size_t optimalThreadsCount(size_t memSize, int maxCpuUsage) const override;
CpuThreads threads(const Algorithm &algorithm) const override;
inline Assembly assembly() const override { return m_assembly; }
inline Assembly::Id assembly() const override { return m_assembly; }
inline bool hasAES() const override { return m_aes; }
inline bool hasAVX2() const override { return m_avx2; }
inline bool isSupported() const override { return true; }
inline const char *brand() const override { return m_brand; }
inline int32_t cores() const override { return m_cores; }
inline int32_t L2() const override { return m_L2; }
inline int32_t L3() const override { return m_L3; }
inline int32_t nodes() const override { return -1; }
inline int32_t sockets() const override { return m_sockets; }
inline int32_t threads() const override { return m_threads; }
# if defined(__x86_64__) || defined(_M_AMD64)
inline bool isX64() const override { return true; }
# else
inline bool isX64() const override { return false; }
# endif
inline size_t cores() const override { return m_cores; }
inline size_t L2() const override { return m_L2; }
inline size_t L3() const override { return m_L3; }
inline size_t nodes() const override { return 0; }
inline size_t sockets() const override { return m_sockets; }
inline size_t threads() const override { return m_threads; }
private:
Assembly m_assembly;
bool m_aes;
bool m_avx2;
bool m_L2_exclusive;
bool m_aes = false;
bool m_avx2 = false;
bool m_L2_exclusive = false;
char m_brand[64];
int32_t m_cores;
int32_t m_L2;
int32_t m_L3;
int32_t m_sockets;
int32_t m_threads;
size_t m_cores = 0;
size_t m_L2 = 0;
size_t m_L3 = 0;
size_t m_sockets = 1;
size_t m_threads = 0;
};

View file

@ -22,6 +22,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <string.h>
#include <thread>
@ -45,7 +46,8 @@
#endif
#include "common/cpu/BasicCpuInfo.h"
#include "backend/cpu/platform/BasicCpuInfo.h"
#include "crypto/common/Assembly.h"
#define VENDOR_ID (0)
@ -121,15 +123,15 @@ static inline bool has_ossave()
xmrig::BasicCpuInfo::BasicCpuInfo() :
m_assembly(ASM_NONE),
m_assembly(Assembly::NONE),
m_aes(has_aes_ni()),
m_avx2(has_avx2() && has_ossave()),
m_brand(),
m_avx2(has_avx2() && has_ossave()),
m_threads(std::thread::hardware_concurrency())
{
cpu_brand_string(m_brand);
# ifndef XMRIG_NO_ASM
# ifdef XMRIG_FEATURE_ASM
if (hasAES()) {
char vendor[13] = { 0 };
int32_t data[4] = { 0 };
@ -141,19 +143,35 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
memcpy(vendor + 8, &data[2], 4);
if (memcmp(vendor, "GenuineIntel", 12) == 0) {
m_assembly = ASM_INTEL;
m_assembly = Assembly::INTEL;
}
else if (memcmp(vendor, "AuthenticAMD", 12) == 0) {
m_assembly = ASM_RYZEN;
m_assembly = Assembly::RYZEN;
}
}
# endif
}
size_t xmrig::BasicCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsage) const
xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm) const
{
const size_t count = threads() / 2;
return count < 1 ? 1 : count;
if (threads() == 1) {
return CpuThreads(1);
}
# ifdef XMRIG_ALGO_CN_GPU
if (algorithm == Algorithm::CN_GPU) {
return CpuThreads(threads());
}
# endif
if (algorithm.family() == Algorithm::CN_LITE || algorithm.family() == Algorithm::CN_PICO) {
return CpuThreads(threads());
}
if (algorithm.family() == Algorithm::CN_HEAVY) {
return CpuThreads(std::max<size_t>(threads() / 4, 1));
}
return CpuThreads(std::max<size_t>(threads() / 2, 1));
}

View file

@ -26,7 +26,7 @@
#define XMRIG_BASICCPUINFO_H
#include "common/interfaces/ICpuInfo.h"
#include "backend/cpu/interfaces/ICpuInfo.h"
namespace xmrig {
@ -38,32 +38,26 @@ public:
BasicCpuInfo();
protected:
size_t optimalThreadsCount(size_t memSize, int maxCpuUsage) const override;
CpuThreads threads(const Algorithm &algorithm) const override;
inline Assembly assembly() const override { return m_assembly; }
inline Assembly::Id assembly() const override { return m_assembly; }
inline bool hasAES() const override { return m_aes; }
inline bool hasAVX2() const override { return m_avx2; }
inline bool isSupported() const override { return true; }
inline const char *brand() const override { return m_brand; }
inline int32_t cores() const override { return -1; }
inline int32_t L2() const override { return -1; }
inline int32_t L3() const override { return -1; }
inline int32_t nodes() const override { return -1; }
inline int32_t sockets() const override { return 1; }
inline int32_t threads() const override { return m_threads; }
# if defined(__x86_64__) || defined(_M_AMD64) || defined (__arm64__) || defined (__aarch64__)
inline bool isX64() const override { return true; }
# else
inline bool isX64() const override { return false; }
# endif
inline size_t cores() const override { return 0; }
inline size_t L2() const override { return 0; }
inline size_t L3() const override { return 0; }
inline size_t nodes() const override { return 0; }
inline size_t sockets() const override { return 1; }
inline size_t threads() const override { return m_threads; }
private:
Assembly m_assembly;
bool m_aes;
bool m_avx2;
char m_brand[64];
int32_t m_threads;
char m_brand[64 + 6];
const bool m_avx2;
const size_t m_threads;
};

View file

@ -32,13 +32,13 @@
#endif
#include "common/cpu/BasicCpuInfo.h"
#include "backend/cpu/platform/BasicCpuInfo.h"
xmrig::BasicCpuInfo::BasicCpuInfo() :
m_aes(false),
m_avx2(false),
m_brand(),
m_avx2(false),
m_threads(std::thread::hardware_concurrency())
{
# ifdef XMRIG_ARMv8
@ -57,7 +57,7 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
}
size_t xmrig::BasicCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsage) const
xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm) const
{
return threads();
return CpuThreads(threads());
}

View file

@ -26,6 +26,7 @@ set(HEADERS_BASE
src/base/kernel/interfaces/IStrategyListener.h
src/base/kernel/interfaces/ITimerListener.h
src/base/kernel/interfaces/IWatcherListener.h
src/base/kernel/Platform.h
src/base/kernel/Process.h
src/base/kernel/Signals.h
src/base/net/dns/Dns.h
@ -63,6 +64,7 @@ set(SOURCES_BASE
src/base/kernel/config/BaseConfig.cpp
src/base/kernel/config/BaseTransform.cpp
src/base/kernel/Entry.cpp
src/base/kernel/Platform.cpp
src/base/kernel/Process.cpp
src/base/kernel/Signals.cpp
src/base/net/dns/Dns.cpp
@ -83,9 +85,20 @@ set(SOURCES_BASE
if (WIN32)
set(SOURCES_OS src/base/io/json/Json_win.cpp)
set(SOURCES_OS
src/base/io/json/Json_win.cpp
src/base/kernel/Platform_win.cpp
)
elseif (APPLE)
set(SOURCES_OS
src/base/io/json/Json_unix.cpp
src/base/kernel/Platform_mac.cpp
)
else()
set(SOURCES_OS src/base/io/json/Json_unix.cpp)
set(SOURCES_OS
src/base/io/json/Json_unix.cpp
src/base/kernel//Platform_unix.cpp
)
endif()
@ -133,5 +146,3 @@ else()
remove_definitions(/DXMRIG_FEATURE_HTTP)
remove_definitions(/DXMRIG_FEATURE_API)
endif()
add_definitions(/DXMRIG_DEPRECATED)

View file

@ -81,6 +81,11 @@ private:
#define WHITE_S CSI "0;37m" // another name for LT.GRAY
#define WHITE_BOLD_S CSI "1;37m" // actually white
#define BLUE_BG_S CSI "44m"
#define BLUE_BG_BOLD_S CSI "44;1m"
#define MAGENTA_BG_S CSI "45m"
#define MAGENTA_BG_BOLD_S CSI "45;1m"
//color wrappings
#define BLACK(x) BLACK_S x CLEAR
#define BLACK_BOLD(x) BLACK_BOLD_S x CLEAR
@ -99,6 +104,11 @@ private:
#define WHITE(x) WHITE_S x CLEAR
#define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR
#define BLUE_BG(x) BLUE_BG_S x CLEAR
#define BLUE_BG_BOLD(x) BLUE_BG_BOLD_S x CLEAR
#define MAGENTA_BG(x) MAGENTA_BG_S x CLEAR
#define MAGENTA_BG_BOLD(x) MAGENTA_BG_BOLD_S x CLEAR
#define LOG_EMERG(x, ...) xmrig::Log::print(xmrig::Log::EMERG, x, ##__VA_ARGS__)
#define LOG_ALERT(x, ...) xmrig::Log::print(xmrig::Log::ALERT, x, ##__VA_ARGS__)

View file

@ -35,8 +35,8 @@
#include "base/io/Watcher.h"
#include "base/kernel/Base.h"
#include "base/kernel/interfaces/IBaseListener.h"
#include "base/kernel/Platform.h"
#include "base/kernel/Process.h"
#include "common/Platform.h"
#include "core/config/Config.h"
#include "core/config/ConfigTransform.h"
@ -48,6 +48,7 @@
#ifdef XMRIG_FEATURE_API
# include "api/Api.h"
# include "api/interfaces/IApiRequest.h"
#endif
@ -167,12 +168,13 @@ int xmrig::Base::init()
# ifdef XMRIG_FEATURE_API
d_ptr->api = new Api(this);
d_ptr->api->addListener(this);
# endif
Platform::init(config()->userAgent());
# ifndef XMRIG_PROXY_PROJECT
Platform::setProcessPriority(config()->priority());
Platform::setProcessPriority(config()->cpu().priority());
# endif
if (!config()->isBackground()) {
@ -288,3 +290,31 @@ void xmrig::Base::onFileChanged(const String &fileName)
d_ptr->replace(config);
}
#ifdef XMRIG_FEATURE_API
void xmrig::Base::onRequest(IApiRequest &request)
{
if (request.method() == IApiRequest::METHOD_GET) {
if (request.url() == "/1/config") {
if (request.isRestricted()) {
return request.done(403);
}
request.accept();
config()->getJSON(request.doc());
}
}
else if (request.method() == IApiRequest::METHOD_PUT || request.method() == IApiRequest::METHOD_POST) {
if (request.url() == "/1/config") {
request.accept();
if (!reload(request.json())) {
return request.done(400);
}
request.done(204);
}
}
}
#endif

View file

@ -26,6 +26,7 @@
#define XMRIG_BASE_H
#include "api/interfaces/IApiListener.h"
#include "base/kernel/interfaces/IConfigListener.h"
#include "base/kernel/interfaces/IWatcherListener.h"
#include "rapidjson/fwd.h"
@ -35,13 +36,13 @@ namespace xmrig {
class Api;
class Config;
class BasePrivate;
class Config;
class IBaseListener;
class Process;
class Base : public IWatcherListener
class Base : public IWatcherListener, public IApiListener
{
public:
Base(Process *process);
@ -60,6 +61,10 @@ public:
protected:
void onFileChanged(const String &fileName) override;
# ifdef XMRIG_FEATURE_API
void onRequest(IApiRequest &request) override;
# endif
private:
BasePrivate *d_ptr;
};

View file

@ -35,6 +35,15 @@
class Platform
{
public:
static inline bool trySetThreadAffinity(int64_t cpu_id)
{
if (cpu_id < 0) {
return false;
}
return setThreadAffinity(static_cast<uint64_t>(cpu_id));
}
static bool setThreadAffinity(uint64_t cpu_id);
static uint32_t setTimerResolution(uint32_t resolution);
static void init(const char *userAgent);

View file

@ -60,14 +60,7 @@
#include "version.h"
xmrig::BaseConfig::BaseConfig() :
m_algorithm(CRYPTONIGHT, VARIANT_AUTO),
m_autoSave(true),
m_background(false),
m_dryRun(false),
m_syslog(false),
m_upgrade(false),
m_watch(true)
xmrig::BaseConfig::BaseConfig()
{
}
@ -146,33 +139,8 @@ bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName)
m_apiWorkerId = Json::getString(api, "worker-id");
}
# ifdef XMRIG_DEPRECATED
if (api.IsObject() && api.HasMember("port")) {
m_upgrade = true;
m_http.load(api);
m_http.setEnabled(Json::getUint(api, "port") > 0);
m_http.setHost("0.0.0.0");
}
else {
m_http.load(reader.getObject("http"));
}
# else
m_http.load(chain.getObject("http"));
# endif
m_algorithm.parseAlgorithm(reader.getString("algo", "cn"));
m_pools.load(reader.getArray("pools"));
m_pools.setDonateLevel(reader.getInt("donate-level", kDefaultDonateLevel));
m_pools.setProxyDonate(reader.getInt("donate-over-proxy", Pools::PROXY_DONATE_AUTO));
m_pools.setRetries(reader.getInt("retries"));
m_pools.setRetryPause(reader.getInt("retry-pause"));
if (!m_algorithm.isValid()) {
return false;
}
m_pools.adjust(m_algorithm);
m_pools.load(reader);
return m_pools.active() > 0;
}

View file

@ -29,7 +29,6 @@
#include "base/kernel/interfaces/IConfig.h"
#include "base/net/http/Http.h"
#include "base/net/stratum/Pools.h"
#include "common/xmrig.h"
struct option;
@ -59,7 +58,6 @@ public:
inline uint32_t printTime() const { return m_printTime; }
inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); }
inline const Algorithm &algorithm() const override { return m_algorithm; }
inline const String &fileName() const override { return m_fileName; }
inline void setFileName(const char *fileName) override { m_fileName = fileName; }
@ -69,13 +67,12 @@ public:
void printVersions();
protected:
Algorithm m_algorithm;
bool m_autoSave;
bool m_background;
bool m_dryRun;
bool m_syslog;
bool m_upgrade;
bool m_watch;
bool m_autoSave = true;
bool m_background = false;
bool m_dryRun = false;
bool m_syslog = false;
bool m_upgrade = false;
bool m_watch = true;
Http m_http;
Pools m_pools;
String m_apiId;

View file

@ -44,6 +44,7 @@
namespace xmrig
{
static const char *kAlgo = "algo";
static const char *kApi = "api";
static const char *kHttp = "http";
static const char *kPools = "pools";
@ -87,15 +88,38 @@ void xmrig::BaseTransform::load(JsonChain &chain, Process *process, IConfigTrans
LOG_WARN("%s: unsupported non-option argument '%s'", argv[0], argv[optind]);
}
transform.finalize(doc);
chain.add(std::move(doc));
}
void xmrig::BaseTransform::finalize(rapidjson::Document &doc)
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
if (m_algorithm.isValid() && doc.HasMember(kPools)) {
auto &pools = doc[kPools];
for (Value &pool : pools.GetArray()) {
if (!pool.HasMember(kAlgo)) {
pool.AddMember(StringRef(kAlgo), m_algorithm.toJSON(), allocator);
}
}
}
}
void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const char *arg)
{
switch (key) {
case IConfig::AlgorithmKey: /* --algo */
return set(doc, "algo", arg);
if (!doc.HasMember(kPools)) {
m_algorithm = arg;
}
else {
return add(doc, kPools, kAlgo, arg);
}
break;
case IConfig::UserpassKey: /* --userpass */
{
@ -128,19 +152,9 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
case IConfig::FingerprintKey: /* --tls-fingerprint */
return add(doc, kPools, "tls-fingerprint", arg);
case IConfig::VariantKey: /* --variant */
return add(doc, kPools, "variant", arg);
case IConfig::LogFileKey: /* --log-file */
return set(doc, "log-file", arg);
# ifdef XMRIG_DEPRECATED
case IConfig::ApiAccessTokenKey: /* --api-access-token */
fputs("option \"--api-access-token\" deprecated, use \"--http-access-token\" instead.\n", stderr);
fflush(stdout);
return set(doc, kHttp, "access-token", arg);
# endif
case IConfig::HttpAccessTokenKey: /* --http-access-token */
return set(doc, kHttp, "access-token", arg);
@ -162,9 +176,6 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
case IConfig::HttpPort: /* --http-port */
case IConfig::DonateLevelKey: /* --donate-level */
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
# ifdef XMRIG_DEPRECATED
case IConfig::ApiPort: /* --api-port */
# endif
return transformUint64(doc, key, static_cast<uint64_t>(strtol(arg, nullptr, 10)));
case IConfig::BackgroundKey: /* --background */
@ -179,10 +190,6 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
case IConfig::ColorKey: /* --no-color */
case IConfig::HttpRestrictedKey: /* --http-no-restricted */
# ifdef XMRIG_DEPRECATED
case IConfig::ApiRestrictedKey: /* --api-no-restricted */
case IConfig::ApiIPv6Key: /* --api-ipv6 */
# endif
return transformBoolean(doc, key, false);
default:
@ -217,16 +224,6 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b
case IConfig::ColorKey: /* --no-color */
return set(doc, "colors", enable);
# ifdef XMRIG_DEPRECATED
case IConfig::ApiIPv6Key: /* --api-ipv6 */
break;
case IConfig::ApiRestrictedKey: /* --api-no-restricted */
fputs("option \"--api-no-restricted\" deprecated, use \"--http-no-restricted\" instead.\n", stderr);
fflush(stdout);
return set(doc, kHttp, "restricted", enable);
# endif
case IConfig::HttpRestrictedKey: /* --http-no-restricted */
return set(doc, kHttp, "restricted", enable);
@ -257,13 +254,6 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui
case IConfig::ProxyDonateKey: /* --donate-over-proxy */
return set(doc, "donate-over-proxy", arg);
# ifdef XMRIG_DEPRECATED
case IConfig::ApiPort: /* --api-port */
fputs("option \"--api-port\" deprecated, use \"--http-port\" instead.\n", stderr);
fflush(stdout);
return set(doc, kHttp, "port", arg);
# endif
case IConfig::HttpPort: /* --http-port */
return set(doc, kHttp, "port", arg);

View file

@ -49,6 +49,7 @@ public:
static void load(JsonChain &chain, Process *process, IConfigTransform &transform);
protected:
void finalize(rapidjson::Document &doc) override;
void transform(rapidjson::Document &doc, int key, const char *arg) override;
@ -96,6 +97,9 @@ protected:
}
}
protected:
Algorithm m_algorithm;
private:
void transformBoolean(rapidjson::Document &doc, int key, bool enable);

View file

@ -35,6 +35,7 @@
namespace xmrig {
class Algorithm;
class IClient;
class Job;
class SubmitResult;
@ -50,6 +51,7 @@ public:
virtual void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params) = 0;
virtual void onLoginSuccess(IClient *client) = 0;
virtual void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) = 0;
virtual void onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok) = 0;
};

View file

@ -65,7 +65,6 @@ public:
UserAgentKey = 1008,
UserKey = 'u',
UserpassKey = 'O',
VariantKey = 1010,
VerboseKey = 1100,
TlsKey = 1013,
FingerprintKey = 1014,
@ -73,13 +72,6 @@ public:
DaemonKey = 1018,
DaemonPollKey = 1019,
# ifdef XMRIG_DEPRECATED
ApiPort = 4000,
ApiAccessTokenKey = 4001,
ApiIPv6Key = 4003,
ApiRestrictedKey = 4004,
# endif
// xmrig common
CPUPriorityKey = 1021,
NicehashKey = 1006,
@ -90,8 +82,6 @@ public:
CPUAffinityKey = 1020,
DryRunKey = 5000,
HugePagesKey = 1009,
MaxCPUUsageKey = 1004,
SafeKey = 1005,
ThreadsKey = 't',
// HardwareAESKey = 1011,
AssemblyKey = 1015,
@ -144,7 +134,6 @@ public:
virtual bool isWatch() const = 0;
virtual bool read(const IJsonReader &reader, const char *fileName) = 0;
virtual bool save() = 0;
virtual const Algorithm &algorithm() const = 0;
virtual const String &fileName() const = 0;
virtual void getJSON(rapidjson::Document &doc) const = 0;
virtual void setFileName(const char *fileName) = 0;

View file

@ -42,6 +42,7 @@ class IConfigTransform
public:
virtual ~IConfigTransform() = default;
virtual void finalize(rapidjson::Document &doc) = 0;
virtual void transform(rapidjson::Document &doc, int key, const char *arg) = 0;
};

View file

@ -26,12 +26,13 @@
#define XMRIG_ISTRATEGYLISTENER_H
#include <stdint.h>
#include "rapidjson/fwd.h"
namespace xmrig {
class Algorithm;
class IClient;
class IStrategy;
class Job;
@ -45,8 +46,10 @@ public:
virtual void onActive(IStrategy *strategy, IClient *client) = 0;
virtual void onJob(IStrategy *strategy, IClient *client, const Job &job) = 0;
virtual void onLogin(IStrategy *strategy, IClient *client, rapidjson::Document &doc, rapidjson::Value &params) = 0;
virtual void onPause(IStrategy *strategy) = 0;
virtual void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) = 0;
virtual void onVerifyAlgorithm(IStrategy *strategy, const IClient *client, const Algorithm &algorithm, bool *ok) = 0;
};

View file

@ -29,10 +29,10 @@
#include "3rdparty/http-parser/http_parser.h"
#include "base/io/log/Log.h"
#include "base/kernel/Platform.h"
#include "base/net/dns/Dns.h"
#include "base/net/http/HttpClient.h"
#include "base/tools/Baton.h"
#include "common/Platform.h"
namespace xmrig {

View file

@ -162,7 +162,7 @@ int64_t xmrig::Client::submit(const JobResult &result)
Buffer::toHex(reinterpret_cast<const char*>(&result.nonce), 4, nonce);
nonce[8] = '\0';
Buffer::toHex(result.result, 32, data);
Buffer::toHex(result.result(), 32, data);
data[64] = '\0';
# endif
@ -313,7 +313,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value &params, int *code)
return false;
}
Job job(m_id, has<EXT_NICEHASH>(), m_pool.algorithm(), m_rpcId);
Job job(has<EXT_NICEHASH>(), m_pool.algorithm(), m_rpcId);
if (!job.setId(params["job_id"].GetString())) {
*code = 3;
@ -330,25 +330,15 @@ bool xmrig::Client::parseJob(const rapidjson::Value &params, int *code)
return false;
}
if (params.HasMember("algo")) {
job.setAlgorithm(params["algo"].GetString());
}
if (params.HasMember("variant")) {
const rapidjson::Value &variant = params["variant"];
if (variant.IsInt()) {
job.setVariant(variant.GetInt());
}
else if (variant.IsString()){
job.setVariant(variant.GetString());
}
const char *algo = Json::getString(params, "algo");
if (algo) {
job.setAlgorithm(algo);
}
job.setSeedHash(Json::getString(params, "seed_hash"));
job.setHeight(Json::getUint64(params, "height"));
if (!verifyAlgorithm(job.algorithm())) {
if (!verifyAlgorithm(job.algorithm(), algo)) {
*code = 6;
close();
@ -426,32 +416,26 @@ bool xmrig::Client::send(BIO *bio)
}
bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm) const
bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm, const char *algo) const
{
# ifdef XMRIG_PROXY_PROJECT
if (m_pool.algorithm().variant() == VARIANT_AUTO || m_id == -1) {
return true;
}
# endif
if (m_pool.isCompatible(algorithm)) {
return true;
}
if (isQuiet()) {
return false;
}
if (algorithm.isValid()) {
LOG_ERR("Incompatible algorithm \"%s\" detected, reconnect", algorithm.name());
}
else {
LOG_ERR("Unknown/unsupported algorithm detected, reconnect");
if (!algorithm.isValid()) {
if (!isQuiet()) {
LOG_ERR("[%s] Unknown/unsupported algorithm \"%s\" detected, reconnect", url(), algo);
}
return false;
}
bool ok = true;
m_listener->onVerifyAlgorithm(this, algorithm, &ok);
if (!ok && !isQuiet()) {
LOG_ERR("[%s] Incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algorithm.shortName());
}
return ok;
}
int xmrig::Client::resolve(const String &host)
{
@ -586,19 +570,6 @@ void xmrig::Client::login()
params.AddMember("rigid", m_pool.rigId().toJSON(), allocator);
}
# ifdef XMRIG_PROXY_PROJECT
if (m_pool.algorithm().variant() != xmrig::VARIANT_AUTO)
# endif
{
Value algo(kArrayType);
for (const auto &a : m_pool.algorithms()) {
algo.PushBack(StringRef(a.shortName()), allocator);
}
params.AddMember("algo", algo, allocator);
}
m_listener->onLogin(this, doc, params);
JsonRequest::create(doc, 1, "login", params);

View file

@ -92,7 +92,7 @@ private:
bool parseJob(const rapidjson::Value &params, int *code);
bool parseLogin(const rapidjson::Value &result, int *code);
bool send(BIO *bio);
bool verifyAlgorithm(const Algorithm &algorithm) const;
bool verifyAlgorithm(const Algorithm &algorithm, const char *algo) const;
int resolve(const String &host);
int64_t send(const rapidjson::Document &doc);
int64_t send(size_t size);

View file

@ -212,7 +212,7 @@ bool xmrig::DaemonClient::isOutdated(uint64_t height, const char *hash) const
bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
{
Job job(m_id, false, m_pool.algorithm(), String());
Job job(false, m_pool.algorithm(), String());
String blocktemplate = Json::getString(params, kBlocktemplateBlob);
if (blocktemplate.isNull() || !job.setBlob(Json::getString(params, "blockhashing_blob"))) {

View file

@ -34,31 +34,16 @@
xmrig::Job::Job() :
m_autoVariant(false),
m_nicehash(false),
m_poolId(-2),
m_threadId(-1),
m_size(0),
m_diff(0),
m_height(0),
m_target(0),
m_blob(),
m_seedHash()
{
}
xmrig::Job::Job(int poolId, bool nicehash, const Algorithm &algorithm, const String &clientId) :
xmrig::Job::Job(bool nicehash, const Algorithm &algorithm, const String &clientId) :
m_algorithm(algorithm),
m_autoVariant(algorithm.variant() == VARIANT_AUTO),
m_nicehash(nicehash),
m_poolId(poolId),
m_threadId(-1),
m_size(0),
m_clientId(clientId),
m_diff(0),
m_height(0),
m_target(0),
m_blob(),
m_seedHash()
{
@ -100,10 +85,6 @@ bool xmrig::Job::setBlob(const char *blob)
m_nicehash = true;
}
if (m_autoVariant) {
m_algorithm.setVariant(variant());
}
# ifdef XMRIG_PROXY_PROJECT
memset(m_rawBlob, 0, sizeof(m_rawBlob));
memcpy(m_rawBlob, blob, m_size * 2);
@ -169,16 +150,6 @@ bool xmrig::Job::setTarget(const char *target)
}
void xmrig::Job::setAlgorithm(const char *algo)
{
m_algorithm.parseAlgorithm(algo);
if (m_algorithm.variant() == xmrig::VARIANT_AUTO) {
m_algorithm.setVariant(variant());
}
}
void xmrig::Job::setDiff(uint64_t diff)
{
m_diff = diff;
@ -189,23 +160,3 @@ void xmrig::Job::setDiff(uint64_t diff)
m_rawTarget[16] = '\0';
# endif
}
xmrig::Variant xmrig::Job::variant() const
{
switch (m_algorithm.algo()) {
case CRYPTONIGHT:
return (m_blob[0] >= 10) ? VARIANT_4 : ((m_blob[0] >= 8) ? VARIANT_2 : VARIANT_1);
case CRYPTONIGHT_LITE:
return VARIANT_1;
case CRYPTONIGHT_HEAVY:
return VARIANT_0;
default:
break;
}
return m_algorithm.variant();
}

View file

@ -47,14 +47,13 @@ public:
static constexpr const size_t kMaxBlobSize = 128;
Job();
Job(int poolId, bool nicehash, const Algorithm &algorithm, const String &clientId);
Job(bool nicehash, const Algorithm &algorithm, const String &clientId);
~Job();
bool isEqual(const Job &other) const;
bool setBlob(const char *blob);
bool setSeedHash(const char *hash);
bool setTarget(const char *target);
void setAlgorithm(const char *algo);
void setDiff(uint64_t diff);
inline bool isNicehash() const { return m_nicehash; }
@ -66,21 +65,18 @@ public:
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(m_blob + 39); }
inline const uint8_t *blob() const { return m_blob; }
inline const uint8_t *seedHash() const { return m_seedHash; }
inline int poolId() const { return m_poolId; }
inline int threadId() const { return m_threadId; }
inline size_t size() const { return m_size; }
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
inline uint64_t diff() const { return m_diff; }
inline uint64_t height() const { return m_height; }
inline uint64_t target() const { return m_target; }
inline uint8_t fixedByte() const { return *(m_blob + 42); }
inline uint8_t index() const { return m_index; }
inline void reset() { m_size = 0; m_diff = 0; }
inline void setAlgorithm(const char *algo) { m_algorithm = algo; }
inline void setClientId(const String &id) { m_clientId = id; }
inline void setHeight(uint64_t height) { m_height = height; }
inline void setPoolId(int poolId) { m_poolId = poolId; }
inline void setThreadId(int threadId) { m_threadId = threadId; }
inline void setVariant(const char *variant) { m_algorithm.parseVariant(variant); }
inline void setVariant(int variant) { m_algorithm.parseVariant(variant); }
inline void setIndex(uint8_t index) { m_index = index; }
# ifdef XMRIG_PROXY_PROJECT
inline char *rawBlob() { return m_rawBlob; }
@ -96,20 +92,16 @@ public:
inline bool operator!=(const Job &other) const { return !isEqual(other); }
private:
Variant variant() const;
Algorithm m_algorithm;
bool m_autoVariant;
bool m_nicehash;
int m_poolId;
int m_threadId;
size_t m_size;
bool m_nicehash = false;
size_t m_size = 0;
String m_clientId;
String m_id;
uint64_t m_diff;
uint64_t m_height;
uint64_t m_target;
uint64_t m_diff = 0;
uint64_t m_height = 0;
uint64_t m_target = 0;
uint8_t m_blob[kMaxBlobSize];
uint8_t m_index = 0;
uint8_t m_seedHash[32];
# ifdef XMRIG_PROXY_PROJECT

View file

@ -47,6 +47,7 @@
namespace xmrig {
static const char *kAlgo = "algo";
static const char *kDaemon = "daemon";
static const char *kDaemonPollInterval = "daemon-poll-interval";
static const char *kEnabled = "enabled";
@ -58,7 +59,6 @@ static const char *kRigId = "rig-id";
static const char *kTls = "tls";
static const char *kUrl = "url";
static const char *kUser = "user";
static const char *kVariant = "variant";
const String Pool::kDefaultPassword = "x";
const String Pool::kDefaultUser = "x";
@ -119,6 +119,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
m_rigId = Json::getString(object, kRigId);
m_fingerprint = Json::getString(object, kFingerprint);
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
m_algorithm = Json::getString(object, kAlgo);
m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true));
m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash));
@ -132,15 +133,6 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
else if (keepalive.IsBool()) {
setKeepAlive(keepalive.GetBool());
}
const rapidjson::Value &variant = Json::getValue(object, kVariant);
if (variant.IsString()) {
algorithm().parseVariant(variant.GetString());
}
else if (variant.IsInt()) {
algorithm().parseVariant(variant.GetInt());
}
}
@ -166,28 +158,6 @@ xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char
}
bool xmrig::Pool::isCompatible(const Algorithm &algorithm) const
{
if (m_algorithms.empty()) {
return true;
}
for (const auto &a : m_algorithms) {
if (algorithm == a) {
return true;
}
}
# ifdef XMRIG_PROXY_PROJECT
if (m_algorithm.algo() == xmrig::CRYPTONIGHT && algorithm.algo() == xmrig::CRYPTONIGHT) {
return m_algorithm.variant() == xmrig::VARIANT_RWZ || m_algorithm.variant() == xmrig::VARIANT_ZLS;
}
# endif
return false;
}
bool xmrig::Pool::isEnabled() const
{
# ifndef XMRIG_FEATURE_TLS
@ -202,7 +172,11 @@ bool xmrig::Pool::isEnabled() const
}
# endif
return m_flags.test(FLAG_ENABLED) && isValid() && algorithm().isValid();
if (isDaemon() && !algorithm().isValid()) {
return false;
}
return m_flags.test(FLAG_ENABLED) && isValid();
}
@ -218,7 +192,8 @@ bool xmrig::Pool::isEqual(const Pool &other) const
&& m_rigId == other.m_rigId
&& m_url == other.m_url
&& m_user == other.m_user
&& m_pollInterval == other.m_pollInterval);
&& m_pollInterval == other.m_pollInterval
);
}
@ -289,8 +264,11 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
Value obj(kObjectType);
obj.AddMember(StringRef(kAlgo), m_algorithm.toJSON(), allocator);
obj.AddMember(StringRef(kUrl), m_url.toJSON(), allocator);
obj.AddMember(StringRef(kUser), m_user.toJSON(), allocator);
if (!isDaemon()) {
obj.AddMember(StringRef(kPass), m_password.toJSON(), allocator);
obj.AddMember(StringRef(kRigId), m_rigId.toJSON(), allocator);
@ -304,56 +282,21 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
else {
obj.AddMember(StringRef(kKeepalive), m_keepAlive, allocator);
}
switch (m_algorithm.variant()) {
case VARIANT_AUTO:
case VARIANT_0:
case VARIANT_1:
obj.AddMember(StringRef(kVariant), m_algorithm.variant(), allocator);
break;
case VARIANT_2:
obj.AddMember(StringRef(kVariant), 2, allocator);
break;
default:
obj.AddMember(StringRef(kVariant), StringRef(m_algorithm.variantName()), allocator);
break;
}
obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator);
obj.AddMember(StringRef(kTls), isTLS(), allocator);
obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator);
obj.AddMember(StringRef(kDaemon), m_flags.test(FLAG_DAEMON), allocator);
if (isDaemon()) {
obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator);
}
return obj;
}
void xmrig::Pool::adjust(const Algorithm &algorithm)
{
if (!isValid()) {
return;
}
if (!m_algorithm.isValid()) {
m_algorithm.setAlgo(algorithm.algo());
adjustVariant(algorithm.variant());
}
rebuild();
}
void xmrig::Pool::setAlgo(const xmrig::Algorithm &algorithm)
{
m_algorithm = algorithm;
rebuild();
}
#ifdef APP_DEBUG
void xmrig::Pool::print() const
{
@ -391,134 +334,3 @@ bool xmrig::Pool::parseIPv6(const char *addr)
return true;
}
void xmrig::Pool::addVariant(xmrig::Variant variant)
{
const xmrig::Algorithm algorithm(m_algorithm.algo(), variant);
if (!algorithm.isValid() || m_algorithm == algorithm) {
return;
}
m_algorithms.push_back(algorithm);
}
void xmrig::Pool::adjustVariant(const xmrig::Variant variantHint)
{
# ifndef XMRIG_PROXY_PROJECT
using namespace xmrig;
if (m_host.contains(".nicehash.com")) {
m_flags.set(FLAG_NICEHASH, true);
m_keepAlive = false;
bool valid = true;
switch (m_port) {
case 3355:
case 33355:
valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonight.");
m_algorithm.setVariant(VARIANT_0);
break;
case 3363:
case 33363:
valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonightv7.");
m_algorithm.setVariant(VARIANT_1);
break;
case 3364:
valid = m_algorithm.algo() == CRYPTONIGHT_HEAVY && m_host.contains("cryptonightheavy.");
m_algorithm.setVariant(VARIANT_0);
break;
case 3367:
case 33367:
valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonightv8.");
m_algorithm.setVariant(VARIANT_2);
break;
default:
break;
}
if (!valid) {
m_algorithm.setAlgo(INVALID_ALGO);
}
m_flags.set(FLAG_TLS, m_port > 33000);
return;
}
if (m_host.contains(".minergate.com")) {
m_keepAlive = false;
bool valid = true;
m_algorithm.setVariant(VARIANT_1);
if (m_host.contains("xmr.pool.")) {
valid = m_algorithm.algo() == CRYPTONIGHT;
m_algorithm.setVariant(m_port == 45700 ? VARIANT_AUTO : VARIANT_0);
}
else if (m_host.contains("aeon.pool.") && m_port == 45690) {
valid = m_algorithm.algo() == CRYPTONIGHT_LITE;
m_algorithm.setVariant(VARIANT_1);
}
if (!valid) {
m_algorithm.setAlgo(INVALID_ALGO);
}
return;
}
if (variantHint != VARIANT_AUTO) {
m_algorithm.setVariant(variantHint);
return;
}
if (m_algorithm.variant() != VARIANT_AUTO) {
return;
}
if (m_algorithm.algo() == CRYPTONIGHT_HEAVY) {
m_algorithm.setVariant(VARIANT_0);
}
else if (m_algorithm.algo() == CRYPTONIGHT_LITE) {
m_algorithm.setVariant(VARIANT_1);
}
# endif
}
void xmrig::Pool::rebuild()
{
m_algorithms.clear();
if (!m_algorithm.isValid()) {
return;
}
m_algorithms.push_back(m_algorithm);
# ifndef XMRIG_PROXY_PROJECT
addVariant(VARIANT_4);
addVariant(VARIANT_WOW);
addVariant(VARIANT_2);
addVariant(VARIANT_1);
addVariant(VARIANT_0);
addVariant(VARIANT_HALF);
addVariant(VARIANT_XTL);
addVariant(VARIANT_TUBE);
addVariant(VARIANT_MSR);
addVariant(VARIANT_XHV);
addVariant(VARIANT_XAO);
addVariant(VARIANT_RTO);
addVariant(VARIANT_GPU);
addVariant(VARIANT_RWZ);
addVariant(VARIANT_ZLS);
addVariant(VARIANT_DOUBLE);
addVariant(VARIANT_RX_WOW);
addVariant(VARIANT_RX_LOKI);
addVariant(VARIANT_AUTO);
# endif
}

View file

@ -69,13 +69,11 @@ public:
bool tls = false
);
inline Algorithm &algorithm() { return m_algorithm; }
inline bool isDaemon() const { return m_flags.test(FLAG_DAEMON); }
inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); }
inline bool isTLS() const { return m_flags.test(FLAG_TLS); }
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
inline const Algorithm &algorithm() const { return m_algorithm; }
inline const Algorithms &algorithms() const { return m_algorithms; }
inline const String &fingerprint() const { return m_fingerprint; }
inline const String &host() const { return m_host; }
inline const String &password() const { return !m_password.isNull() ? m_password : kDefaultPassword; }
@ -85,6 +83,7 @@ public:
inline int keepAlive() const { return m_keepAlive; }
inline uint16_t port() const { return m_port; }
inline uint64_t pollInterval() const { return m_pollInterval; }
inline void setAlgo(const Algorithm &algorithm) { m_algorithm = algorithm; }
inline void setPassword(const String &password) { m_password = password; }
inline void setRigId(const String &rigId) { m_rigId = rigId; }
inline void setUser(const String &user) { m_user = user; }
@ -92,13 +91,10 @@ public:
inline bool operator!=(const Pool &other) const { return !isEqual(other); }
inline bool operator==(const Pool &other) const { return isEqual(other); }
bool isCompatible(const Algorithm &algorithm) const;
bool isEnabled() const;
bool isEqual(const Pool &other) const;
bool parse(const char *url);
rapidjson::Value toJSON(rapidjson::Document &doc) const;
void adjust(const Algorithm &algorithm);
void setAlgo(const Algorithm &algorithm);
# ifdef APP_DEBUG
void print() const;
@ -109,12 +105,8 @@ private:
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
bool parseIPv6(const char *addr);
void addVariant(Variant variant);
void adjustVariant(const Variant variantHint);
void rebuild();
Algorithm m_algorithm;
Algorithms m_algorithms;
int m_keepAlive;
std::bitset<FLAG_MAX> m_flags;
String m_fingerprint;

View file

@ -24,6 +24,7 @@
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/IJsonReader.h"
#include "base/net/stratum/Pools.h"
#include "base/net/stratum/strategies/FailoverStrategy.h"
#include "base/net/stratum/strategies/SinglePoolStrategy.h"
@ -103,18 +104,11 @@ size_t xmrig::Pools::active() const
}
void xmrig::Pools::adjust(const Algorithm &algorithm)
{
for (Pool &pool : m_data) {
pool.adjust(algorithm);
}
}
void xmrig::Pools::load(const rapidjson::Value &pools)
void xmrig::Pools::load(const IJsonReader &reader)
{
m_data.clear();
const rapidjson::Value &pools = reader.getArray("pools");
if (!pools.IsArray()) {
return;
}
@ -129,6 +123,11 @@ void xmrig::Pools::load(const rapidjson::Value &pools)
m_data.push_back(std::move(pool));
}
}
setDonateLevel(reader.getInt("donate-level", kDefaultDonateLevel));
setProxyDonate(reader.getInt("donate-over-proxy", PROXY_DONATE_AUTO));
setRetries(reader.getInt("retries"));
setRetryPause(reader.getInt("retry-pause"));
}
@ -136,11 +135,11 @@ void xmrig::Pools::print() const
{
size_t i = 1;
for (const Pool &pool : m_data) {
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " variant " WHITE_BOLD("%s"),
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " algo " WHITE_BOLD("%s"),
i,
(pool.isEnabled() ? (pool.isTLS() ? 32 : 36) : 31),
pool.url().data(),
pool.algorithm().variantName()
pool.algorithm().isValid() ? pool.algorithm().shortName() : "auto"
);
i++;

View file

@ -35,6 +35,7 @@
namespace xmrig {
class IJsonReader;
class IStrategy;
class IStrategyListener;
@ -63,15 +64,15 @@ public:
IStrategy *createStrategy(IStrategyListener *listener) const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
size_t active() const;
void adjust(const Algorithm &algorithm);
void load(const rapidjson::Value &pools);
void load(const IJsonReader &reader);
void print() const;
private:
void setDonateLevel(int level);
void setProxyDonate(int value);
void setRetries(int retries);
void setRetryPause(int retryPause);
private:
int m_donateLevel;
int m_retries;
int m_retryPause;

View file

@ -24,9 +24,9 @@
#include "base/kernel/interfaces/IStrategyListener.h"
#include "base/kernel/Platform.h"
#include "base/net/stratum/Client.h"
#include "base/net/stratum/strategies/FailoverStrategy.h"
#include "common/Platform.h"
#ifdef XMRIG_FEATURE_HTTP
@ -113,7 +113,7 @@ void xmrig::FailoverStrategy::resume()
}
void xmrig::FailoverStrategy::setAlgo(const xmrig::Algorithm &algo)
void xmrig::FailoverStrategy::setAlgo(const Algorithm &algo)
{
for (IClient *client : m_pools) {
client->setAlgo(algo);
@ -163,6 +163,12 @@ void xmrig::FailoverStrategy::onClose(IClient *client, int failures)
}
void xmrig::FailoverStrategy::onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params)
{
m_listener->onLogin(this, client, doc, params);
}
void xmrig::FailoverStrategy::onJobReceived(IClient *client, const Job &job, const rapidjson::Value &)
{
if (m_active == client->id()) {
@ -196,3 +202,9 @@ void xmrig::FailoverStrategy::onResultAccepted(IClient *client, const SubmitResu
{
m_listener->onResultAccepted(this, client, result, error);
}
void xmrig::FailoverStrategy::onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok)
{
m_listener->onVerifyAlgorithm(this, client, algorithm, ok);
}

View file

@ -53,7 +53,6 @@ public:
protected:
inline bool isActive() const override { return m_active >= 0; }
inline IClient *client() const override { return isActive() ? active() : m_pools[m_index]; }
inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {}
int64_t submit(const JobResult &result) override;
void connect() override;
@ -64,8 +63,10 @@ protected:
void onClose(IClient *client, int failures) override;
void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &params) override;
void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params) override;
void onLoginSuccess(IClient *client) override;
void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override;
void onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok) override;
private:
inline IClient *active() const { return m_pools[static_cast<size_t>(m_active)]; }

View file

@ -24,9 +24,9 @@
#include "base/kernel/interfaces/IStrategyListener.h"
#include "base/kernel/Platform.h"
#include "base/net/stratum/Client.h"
#include "base/net/stratum/strategies/SinglePoolStrategy.h"
#include "common/Platform.h"
#ifdef XMRIG_FEATURE_HTTP
@ -84,7 +84,7 @@ void xmrig::SinglePoolStrategy::resume()
}
void xmrig::SinglePoolStrategy::setAlgo(const xmrig::Algorithm &algo)
void xmrig::SinglePoolStrategy::setAlgo(const Algorithm &algo)
{
m_client->setAlgo(algo);
}
@ -119,6 +119,12 @@ void xmrig::SinglePoolStrategy::onJobReceived(IClient *client, const Job &job, c
}
void xmrig::SinglePoolStrategy::onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params)
{
m_listener->onLogin(this, client, doc, params);
}
void xmrig::SinglePoolStrategy::onLoginSuccess(IClient *client)
{
m_active = true;
@ -130,3 +136,9 @@ void xmrig::SinglePoolStrategy::onResultAccepted(IClient *client, const SubmitRe
{
m_listener->onResultAccepted(this, client, result, error);
}
void xmrig::SinglePoolStrategy::onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok)
{
m_listener->onVerifyAlgorithm(this, client, algorithm, ok);
}

View file

@ -47,7 +47,6 @@ public:
protected:
inline bool isActive() const override { return m_active; }
inline IClient *client() const override { return m_client; }
inline void onLogin(IClient *, rapidjson::Document &, rapidjson::Value &) override {}
int64_t submit(const JobResult &result) override;
void connect() override;
@ -58,8 +57,10 @@ protected:
void onClose(IClient *client, int failures) override;
void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &params) override;
void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value &params) override;
void onLoginSuccess(IClient *client) override;
void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override;
void onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok) override;
private:
bool m_active;

View file

@ -35,6 +35,14 @@ namespace xmrig {
class Chrono
{
public:
static inline uint64_t highResolutionMSecs()
{
using namespace std::chrono;
return static_cast<uint64_t>(time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count());
}
static inline uint64_t steadyMSecs()
{
using namespace std::chrono;

View file

@ -1,57 +0,0 @@
/* 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/>.
*/
#include <assert.h>
#include "common/cpu/BasicCpuInfo.h"
#include "common/cpu/Cpu.h"
static xmrig::ICpuInfo *cpuInfo = nullptr;
xmrig::ICpuInfo *xmrig::Cpu::info()
{
assert(cpuInfo != nullptr);
return cpuInfo;
}
void xmrig::Cpu::init()
{
assert(cpuInfo == nullptr);
cpuInfo = new BasicCpuInfo();
}
void xmrig::Cpu::release()
{
assert(cpuInfo != nullptr);
delete cpuInfo;
cpuInfo = nullptr;
}

View file

@ -1,124 +0,0 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_XMRIG_H
#define XMRIG_XMRIG_H
namespace xmrig
{
enum Algo {
INVALID_ALGO = -1,
CRYPTONIGHT, /* CryptoNight (2 MB) */
CRYPTONIGHT_LITE, /* CryptoNight (1 MB) */
CRYPTONIGHT_HEAVY, /* CryptoNight (4 MB) */
CRYPTONIGHT_PICO, /* CryptoNight (256 KB) */
RANDOM_X, /* RandomX */
ALGO_MAX
};
//--av=1 For CPUs with hardware AES.
//--av=2 Lower power mode (double hash) of 1.
//--av=3 Software AES implementation.
//--av=4 Lower power mode (double hash) of 3.
enum AlgoVariant {
AV_AUTO, // --av=0 Automatic mode.
AV_SINGLE, // --av=1 Single hash mode
AV_DOUBLE, // --av=2 Double hash mode
AV_SINGLE_SOFT, // --av=3 Single hash mode (Software AES)
AV_DOUBLE_SOFT, // --av=4 Double hash mode (Software AES)
AV_TRIPLE, // --av=5 Triple hash mode
AV_QUAD, // --av=6 Quard hash mode
AV_PENTA, // --av=7 Penta hash mode
AV_TRIPLE_SOFT, // --av=8 Triple hash mode (Software AES)
AV_QUAD_SOFT, // --av=9 Quard hash mode (Software AES)
AV_PENTA_SOFT, // --av=10 Penta hash mode (Software AES)
AV_MAX
};
enum Variant {
VARIANT_AUTO = -1, // Autodetect
VARIANT_0 = 0, // Original CryptoNight or CryptoNight-Heavy
VARIANT_1 = 1, // CryptoNight variant 1 also known as Monero7 and CryptoNightV7
VARIANT_TUBE = 2, // Modified CryptoNight-Heavy (TUBE only)
VARIANT_XTL = 3, // Modified CryptoNight variant 1 (Stellite only)
VARIANT_MSR = 4, // Modified CryptoNight variant 1 (Masari only)
VARIANT_XHV = 5, // Modified CryptoNight-Heavy (Haven Protocol only)
VARIANT_XAO = 6, // Modified CryptoNight variant 0 (Alloy only)
VARIANT_RTO = 7, // Modified CryptoNight variant 1 (Arto only)
VARIANT_2 = 8, // CryptoNight variant 2
VARIANT_HALF = 9, // CryptoNight variant 2 with half iterations (Masari/Stellite)
VARIANT_TRTL = 10, // CryptoNight Turtle (TRTL)
VARIANT_GPU = 11, // CryptoNight-GPU (Ryo)
VARIANT_WOW = 12, // CryptoNightR (Wownero)
VARIANT_4 = 13, // CryptoNightR (Monero's variant 4)
VARIANT_RWZ = 14, // CryptoNight variant 2 with 3/4 iterations and reversed shuffle operation (Graft)
VARIANT_ZLS = 15, // CryptoNight variant 2 with 3/4 iterations (Zelerius)
VARIANT_DOUBLE = 16, // CryptoNight variant 2 with double iterations (X-CASH)
VARIANT_RX_WOW = 17, // RandomX (Wownero)
VARIANT_RX_LOKI = 18, // RandomX (Loki)
VARIANT_MAX
};
enum AlgoVerify {
VERIFY_HW_AES = 1,
VERIFY_SOFT_AES = 2
};
enum AesMode {
AES_AUTO,
AES_HW,
AES_SOFT
};
enum OclVendor {
OCL_VENDOR_UNKNOWN = -2,
OCL_VENDOR_MANUAL = -1,
OCL_VENDOR_AMD = 0,
OCL_VENDOR_NVIDIA = 1,
OCL_VENDOR_INTEL = 2
};
enum Assembly {
ASM_NONE,
ASM_AUTO,
ASM_INTEL,
ASM_RYZEN,
ASM_BULLDOZER,
ASM_MAX
};
} /* namespace xmrig */
#endif /* XMRIG_XMRIG_H */

View file

@ -26,15 +26,14 @@
#include <assert.h>
#include "common/cpu/Cpu.h"
#include "common/Platform.h"
#include "backend/cpu/Cpu.h"
#include "core/Controller.h"
#include "core/Miner.h"
#include "net/Network.h"
xmrig::Controller::Controller(Process *process) :
Base(process),
m_network(nullptr)
Base(process)
{
}
@ -69,6 +68,8 @@ void xmrig::Controller::start()
{
Base::start();
m_miner = new Miner(this);
network()->connect();
}
@ -79,6 +80,19 @@ void xmrig::Controller::stop()
delete m_network;
m_network = nullptr;
m_miner->stop();
delete m_miner;
m_miner = nullptr;
}
xmrig::Miner *xmrig::Controller::miner() const
{
assert(m_miner != nullptr);
return m_miner;
}

View file

@ -32,6 +32,8 @@
namespace xmrig {
class Job;
class Miner;
class Network;
@ -46,10 +48,12 @@ public:
void start() override;
void stop() override;
Miner *miner() const;
Network *network() const;
private:
Network *m_network;
Miner *m_miner = nullptr;
Network *m_network = nullptr;
};

442
src/core/Miner.cpp Normal file
View file

@ -0,0 +1,442 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 <algorithm>
#include <uv.h>
#include "backend/common/Hashrate.h"
#include "backend/cpu/Cpu.h"
#include "backend/cpu/CpuBackend.h"
#include "base/io/log/Log.h"
#include "base/kernel/Platform.h"
#include "base/net/stratum/Job.h"
#include "base/tools/Timer.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "core/Miner.h"
#include "crypto/common/Nonce.h"
#include "rapidjson/document.h"
#include "version.h"
#ifdef XMRIG_FEATURE_API
# include "api/Api.h"
# include "api/interfaces/IApiRequest.h"
#endif
namespace xmrig {
class MinerPrivate
{
public:
inline MinerPrivate(Controller *controller) : controller(controller)
{
uv_rwlock_init(&rwlock);
}
inline ~MinerPrivate()
{
uv_rwlock_destroy(&rwlock);
delete timer;
for (IBackend *backend : backends) {
delete backend;
}
}
bool isEnabled(const Algorithm &algorithm) const
{
for (IBackend *backend : backends) {
if (backend->isEnabled(algorithm)) {
return true;
}
}
return false;
}
inline void rebuild()
{
algorithms.clear();
for (int i = 0; i < Algorithm::MAX; ++i) {
const Algorithm algo(static_cast<Algorithm::Id>(i));
if (isEnabled(algo)) {
algorithms.push_back(algo);
}
}
}
inline void handleJobChange(bool reset)
{
active = true;
for (IBackend *backend : backends) {
backend->setJob(job);
}
if (reset) {
Nonce::reset(job.index());
}
else {
Nonce::touch();
}
if (enabled) {
Nonce::pause(false);;
}
if (ticks == 0) {
ticks++;
timer->start(500, 500);
}
}
# ifdef XMRIG_FEATURE_API
void getMiner(rapidjson::Value &reply, rapidjson::Document &doc, int version) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value cpu(kObjectType);
cpu.AddMember("brand", StringRef(Cpu::info()->brand()), allocator);
cpu.AddMember("aes", Cpu::info()->hasAES(), allocator);
cpu.AddMember("x64", Cpu::info()->isX64(), allocator);
cpu.AddMember("sockets", static_cast<uint64_t>(Cpu::info()->sockets()), allocator);
reply.AddMember("version", APP_VERSION, allocator);
reply.AddMember("kind", APP_KIND, allocator);
reply.AddMember("ua", StringRef(Platform::userAgent()), allocator);
reply.AddMember("cpu", cpu, allocator);
if (version == 1) {
reply.AddMember("hugepages", false, allocator);
}
reply.AddMember("donate_level", controller->config()->pools().donateLevel(), allocator);
Value algo(kArrayType);
for (const Algorithm &a : algorithms) {
algo.PushBack(StringRef(a.shortName()), allocator);
}
reply.AddMember("algorithms", algo, allocator);
}
void getHashrate(rapidjson::Value &reply, rapidjson::Document &doc, int version) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value hashrate(kObjectType);
Value total(kArrayType);
Value threads(kArrayType);
double t[3] = { 0.0 };
for (IBackend *backend : backends) {
const Hashrate *hr = backend->hashrate();
if (!hr) {
continue;
}
t[0] += hr->calc(Hashrate::ShortInterval);
t[1] += hr->calc(Hashrate::MediumInterval);
t[2] += hr->calc(Hashrate::LargeInterval);
if (version > 1) {
continue;
}
for (size_t i = 0; i < hr->threads(); i++) {
Value thread(kArrayType);
thread.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
thread.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
thread.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
threads.PushBack(thread, allocator);
}
}
total.PushBack(Hashrate::normalize(t[0]), allocator);
total.PushBack(Hashrate::normalize(t[1]), allocator);
total.PushBack(Hashrate::normalize(t[2]), allocator);
hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", Hashrate::normalize(maxHashrate), allocator);
if (version == 1) {
hashrate.AddMember("threads", threads, allocator);
}
reply.AddMember("hashrate", hashrate, allocator);
}
void getBackends(rapidjson::Value &reply, rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
reply.SetArray();
for (IBackend *backend : backends) {
reply.PushBack(backend->toJSON(doc), allocator);
}
}
# endif
Algorithms algorithms;
bool active = false;
bool enabled = true;
Controller *controller;
double maxHashrate = 0.0;
Job job;
std::vector<IBackend *> backends;
String userJobId;
Timer *timer = nullptr;
uint64_t ticks = 0;
uv_rwlock_t rwlock;
};
} // namespace xmrig
xmrig::Miner::Miner(Controller *controller)
: d_ptr(new MinerPrivate(controller))
{
controller->addListener(this);
# ifdef XMRIG_FEATURE_API
controller->api()->addListener(this);
# endif
d_ptr->timer = new Timer(this);
d_ptr->backends.push_back(new CpuBackend(controller));
d_ptr->rebuild();
}
xmrig::Miner::~Miner()
{
delete d_ptr;
}
bool xmrig::Miner::isEnabled() const
{
return d_ptr->enabled;
}
bool xmrig::Miner::isEnabled(const Algorithm &algorithm) const
{
return std::find(d_ptr->algorithms.begin(), d_ptr->algorithms.end(), algorithm) != d_ptr->algorithms.end();
}
const xmrig::Algorithms &xmrig::Miner::algorithms() const
{
return d_ptr->algorithms;
}
const std::vector<xmrig::IBackend *> &xmrig::Miner::backends() const
{
return d_ptr->backends;
}
xmrig::Job xmrig::Miner::job() const
{
uv_rwlock_rdlock(&d_ptr->rwlock);
Job job = d_ptr->job;
uv_rwlock_rdunlock(&d_ptr->rwlock);
return job;
}
void xmrig::Miner::pause()
{
d_ptr->active = false;
Nonce::pause(true);
Nonce::touch();
}
void xmrig::Miner::printHashrate(bool details)
{
char num[8 * 4] = { 0 };
double speed[3] = { 0.0 };
for (IBackend *backend : d_ptr->backends) {
const Hashrate *hashrate = backend->hashrate();
if (hashrate) {
speed[0] += hashrate->calc(Hashrate::ShortInterval);
speed[1] += hashrate->calc(Hashrate::MediumInterval);
speed[2] += hashrate->calc(Hashrate::LargeInterval);
}
backend->printHashrate(details);
}
LOG_INFO(WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("H/s") " max " CYAN_BOLD("%s H/s"),
Hashrate::format(speed[0], num, sizeof(num) / 4),
Hashrate::format(speed[1], num + 8, sizeof(num) / 4),
Hashrate::format(speed[2], num + 8 * 2, sizeof(num) / 4 ),
Hashrate::format(d_ptr->maxHashrate, num + 8 * 3, sizeof(num) / 4)
);
}
void xmrig::Miner::setEnabled(bool enabled)
{
if (d_ptr->enabled == enabled) {
return;
}
d_ptr->enabled = enabled;
if (enabled) {
LOG_INFO(GREEN_BOLD("resumed"));
}
else {
LOG_INFO(YELLOW_BOLD("paused") ", press " MAGENTA_BG_BOLD(" r ") " to resume");
}
if (!d_ptr->active) {
return;
}
Nonce::pause(!enabled);
Nonce::touch();
}
void xmrig::Miner::setJob(const Job &job, bool donate)
{
uv_rwlock_wrlock(&d_ptr->rwlock);
const uint8_t index = donate ? 1 : 0;
const bool reset = !(d_ptr->job.index() == 1 && index == 0 && d_ptr->userJobId == job.id());
d_ptr->job = job;
d_ptr->job.setIndex(index);
if (index == 0) {
d_ptr->userJobId = job.id();
}
uv_rwlock_wrunlock(&d_ptr->rwlock);
d_ptr->handleJobChange(reset);
}
void xmrig::Miner::stop()
{
Nonce::stop();
for (IBackend *backend : d_ptr->backends) {
backend->stop();
}
}
void xmrig::Miner::onConfigChanged(Config *config, Config *previousConfig)
{
d_ptr->rebuild();
if (config->pools() != previousConfig->pools() && config->pools().active() > 0) {
return;
}
const Job job = this->job();
for (IBackend *backend : d_ptr->backends) {
backend->setJob(job);
}
}
void xmrig::Miner::onTimer(const Timer *)
{
double maxHashrate = 0.0;
for (IBackend *backend : d_ptr->backends) {
backend->tick(d_ptr->ticks);
if (backend->hashrate()) {
maxHashrate += backend->hashrate()->calc(Hashrate::ShortInterval);
}
}
d_ptr->maxHashrate = std::max(d_ptr->maxHashrate, maxHashrate);
if ((d_ptr->ticks % (d_ptr->controller->config()->printTime() * 2)) == 0) {
printHashrate(false);
}
d_ptr->ticks++;
}
#ifdef XMRIG_FEATURE_API
void xmrig::Miner::onRequest(IApiRequest &request)
{
if (request.method() == IApiRequest::METHOD_GET) {
if (request.type() == IApiRequest::REQ_SUMMARY) {
request.accept();
d_ptr->getMiner(request.reply(), request.doc(), request.version());
d_ptr->getHashrate(request.reply(), request.doc(), request.version());
}
else if (request.url() == "/2/backends") {
request.accept();
d_ptr->getBackends(request.reply(), request.doc());
}
}
}
#endif

80
src/core/Miner.h Normal file
View file

@ -0,0 +1,80 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_MINER_H
#define XMRIG_MINER_H
#include <vector>
#include "api/interfaces/IApiListener.h"
#include "base/kernel/interfaces/IBaseListener.h"
#include "base/kernel/interfaces/ITimerListener.h"
#include "crypto/common/Algorithm.h"
namespace xmrig {
class Controller;
class Job;
class MinerPrivate;
class IBackend;
class Miner : public ITimerListener, public IBaseListener, public IApiListener
{
public:
Miner(Controller *controller);
~Miner() override;
bool isEnabled() const;
bool isEnabled(const Algorithm &algorithm) const;
const Algorithms &algorithms() const;
const std::vector<IBackend *> &backends() const;
Job job() const;
void pause();
void printHashrate(bool details);
void setEnabled(bool enabled);
void setJob(const Job &job, bool donate);
void stop();
protected:
void onConfigChanged(Config *config, Config *previousConfig) override;
void onTimer(const Timer *timer) override;
# ifdef XMRIG_FEATURE_API
void onRequest(IApiRequest &request) override;
# endif
private:
MinerPrivate *d_ptr;
};
} // namespace xmrig
#endif /* XMRIG_MINER_H */

View file

@ -28,60 +28,30 @@
#include <inttypes.h>
#include "backend/cpu/Cpu.h"
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/IJsonReader.h"
#include "common/cpu/Cpu.h"
#include "core/config/Config.h"
#include "crypto/cn/Asm.h"
#include "crypto/cn/CryptoNight_constants.h"
#include "crypto/common/Assembly.h"
#include "rapidjson/document.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/prettywriter.h"
#include "workers/CpuThread.h"
static char affinity_tmp[20] = { 0 };
xmrig::Config::Config() :
m_aesMode(AES_AUTO),
m_algoVariant(AV_AUTO),
m_assembly(ASM_AUTO),
m_hugePages(true),
m_safe(false),
m_shouldSave(false),
m_maxCpuUsage(100),
m_priority(-1)
xmrig::Config::Config() : BaseConfig()
{
}
bool xmrig::Config::isHwAES() const
{
return (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_HW;
}
bool xmrig::Config::read(const IJsonReader &reader, const char *fileName)
{
if (!BaseConfig::read(reader, fileName)) {
return false;
}
m_hugePages = reader.getBool("huge-pages", true);
m_safe = reader.getBool("safe");
m_cpu.read(reader.getValue("cpu"));
setAesMode(reader.getValue("hw-aes"));
setAlgoVariant(reader.getInt("av"));
setMaxCpuUsage(reader.getInt("max-cpu-usage", 100));
setPriority(reader.getInt("cpu-priority", -1));
setThreads(reader.getValue("threads"));
# ifndef XMRIG_NO_ASM
setAssembly(reader.getValue("asm"));
# endif
return finalize();
return true;
}
@ -93,200 +63,24 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
auto &allocator = doc.GetAllocator();
doc.AddMember("algo", StringRef(algorithm().name()), allocator);
Value api(kObjectType);
api.AddMember("id", m_apiId.toJSON(), allocator);
api.AddMember("worker-id", m_apiWorkerId.toJSON(), allocator);
doc.AddMember("api", api, allocator);
doc.AddMember("http", m_http.toJSON(doc), allocator);
# ifndef XMRIG_NO_ASM
doc.AddMember("asm", Asm::toJSON(m_assembly), allocator);
# endif
doc.AddMember("autosave", isAutoSave(), allocator);
doc.AddMember("av", algoVariant(), allocator);
doc.AddMember("background", isBackground(), allocator);
doc.AddMember("colors", Log::colors, allocator);
if (affinity() != -1L) {
snprintf(affinity_tmp, sizeof(affinity_tmp) - 1, "0x%" PRIX64, affinity());
doc.AddMember("cpu-affinity", StringRef(affinity_tmp), allocator);
}
else {
doc.AddMember("cpu-affinity", kNullType, allocator);
}
doc.AddMember("cpu-priority", priority() != -1 ? Value(priority()) : Value(kNullType), allocator);
doc.AddMember("cpu", m_cpu.toJSON(doc), allocator);
doc.AddMember("donate-level", m_pools.donateLevel(), allocator);
doc.AddMember("donate-over-proxy", m_pools.proxyDonate(), allocator);
doc.AddMember("huge-pages", isHugePages(), allocator);
doc.AddMember("hw-aes", m_aesMode == AES_AUTO ? Value(kNullType) : Value(m_aesMode == AES_HW), allocator);
doc.AddMember("http", m_http.toJSON(doc), allocator);
doc.AddMember("log-file", m_logFile.toJSON(), allocator);
doc.AddMember("max-cpu-usage", m_maxCpuUsage, allocator);
doc.AddMember("pools", m_pools.toJSON(doc), allocator);
doc.AddMember("print-time", printTime(), allocator);
doc.AddMember("retries", m_pools.retries(), allocator);
doc.AddMember("retry-pause", m_pools.retryPause(), allocator);
doc.AddMember("safe", m_safe, allocator);
if (threadsMode() != Simple) {
Value threads(kArrayType);
for (const IThread *thread : m_threads.list) {
threads.PushBack(thread->toConfig(doc), allocator);
}
doc.AddMember("threads", threads, allocator);
}
else {
doc.AddMember("threads", threadsCount(), allocator);
}
doc.AddMember("user-agent", m_userAgent.toJSON(), allocator);
doc.AddMember("syslog", isSyslog(), allocator);
doc.AddMember("user-agent", m_userAgent.toJSON(), allocator);
doc.AddMember("watch", m_watch, allocator);
}
bool xmrig::Config::finalize()
{
if (!m_threads.cpu.empty()) {
m_threads.mode = Advanced;
for (size_t i = 0; i < m_threads.cpu.size(); ++i) {
m_threads.list.push_back(CpuThread::createFromData(i, m_algorithm.algo(), m_threads.cpu[i], m_priority, !isHwAES()));
}
return true;
}
const AlgoVariant av = getAlgoVariant();
m_threads.mode = m_threads.count ? Simple : Automatic;
const Variant v = m_algorithm.variant();
const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo(), v) / 1024;
if (!m_threads.count) {
m_threads.count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage);
}
else if (m_safe) {
const size_t count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage);
if (m_threads.count > count) {
m_threads.count = count;
}
}
for (size_t i = 0; i < m_threads.count; ++i) {
m_threads.list.push_back(CpuThread::createFromAV(i, m_algorithm.algo(), av, m_threads.mask, m_priority, m_assembly));
}
m_shouldSave = m_threads.mode == Automatic;
return true;
}
void xmrig::Config::setAesMode(const rapidjson::Value &aesMode)
{
if (aesMode.IsBool()) {
m_aesMode = aesMode.GetBool() ? AES_HW : AES_SOFT;
}
}
void xmrig::Config::setAlgoVariant(int av)
{
if (av >= AV_AUTO && av < AV_MAX) {
m_algoVariant = static_cast<AlgoVariant>(av);
}
}
void xmrig::Config::setMaxCpuUsage(int max)
{
if (max > 0 && max <= 100) {
m_maxCpuUsage = max;
}
}
void xmrig::Config::setPriority(int priority)
{
if (priority >= 0 && priority <= 5) {
m_priority = priority;
}
}
void xmrig::Config::setThreads(const rapidjson::Value &threads)
{
if (threads.IsArray()) {
m_threads.cpu.clear();
for (const rapidjson::Value &value : threads.GetArray()) {
if (!value.IsObject()) {
continue;
}
if (value.HasMember("low_power_mode")) {
auto data = CpuThread::parse(value);
if (data.valid) {
m_threads.cpu.push_back(std::move(data));
}
}
}
}
else if (threads.IsUint()) {
const unsigned count = threads.GetUint();
if (count < 1024) {
m_threads.count = count;
}
}
}
xmrig::AlgoVariant xmrig::Config::getAlgoVariant() const
{
# ifdef XMRIG_ALGO_CN_LITE
if (m_algorithm.algo() == xmrig::CRYPTONIGHT_LITE) {
return getAlgoVariantLite();
}
# endif
if (m_algoVariant <= AV_AUTO || m_algoVariant >= AV_MAX) {
return Cpu::info()->hasAES() ? AV_SINGLE : AV_SINGLE_SOFT;
}
if (m_safe && !Cpu::info()->hasAES() && m_algoVariant <= AV_DOUBLE) {
return static_cast<AlgoVariant>(m_algoVariant + 2);
}
return m_algoVariant;
}
#ifdef XMRIG_ALGO_CN_LITE
xmrig::AlgoVariant xmrig::Config::getAlgoVariantLite() const
{
if (m_algoVariant <= AV_AUTO || m_algoVariant >= AV_MAX) {
return Cpu::info()->hasAES() ? AV_DOUBLE : AV_DOUBLE_SOFT;
}
if (m_safe && !Cpu::info()->hasAES() && m_algoVariant <= AV_DOUBLE) {
return static_cast<AlgoVariant>(m_algoVariant + 2);
}
return m_algoVariant;
}
#endif
#ifndef XMRIG_NO_ASM
void xmrig::Config::setAssembly(const rapidjson::Value &assembly)
{
m_assembly = Asm::parse(assembly);
}
#endif

View file

@ -5,7 +5,8 @@
* 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 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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
@ -26,103 +27,37 @@
#include <stdint.h>
#include <vector>
#include "backend/cpu/CpuConfig.h"
#include "base/kernel/config/BaseConfig.h"
#include "common/xmrig.h"
#include "rapidjson/fwd.h"
#include "workers/CpuThread.h"
namespace xmrig {
class ConfigLoader;
class IThread;
class IConfigListener;
class Process;
/**
* @brief The Config class
*
* Options with dynamic reload:
* colors
* debug
* verbose
* custom-diff (only for new connections)
* api/worker-id
* pools/
*/
class Config : public BaseConfig
{
public:
enum ThreadsMode {
Automatic,
Simple,
Advanced
};
Config();
bool isHwAES() const;
bool read(const IJsonReader &reader, const char *fileName) override;
void getJSON(rapidjson::Document &doc) const override;
inline AlgoVariant algoVariant() const { return m_algoVariant; }
inline Assembly assembly() const { return m_assembly; }
inline bool isHugePages() const { return m_hugePages; }
inline bool isShouldSave() const { return (m_shouldSave || m_upgrade) && isAutoSave(); }
inline const std::vector<IThread *> &threads() const { return m_threads.list; }
inline int priority() const { return m_priority; }
inline int threadsCount() const { return static_cast<int>(m_threads.list.size()); }
inline int64_t affinity() const { return m_threads.mask; }
inline ThreadsMode threadsMode() const { return m_threads.mode; }
inline bool isShouldSave() const { return (m_shouldSave || m_upgrade || m_cpu.isShouldSave()) && isAutoSave(); }
inline const CpuConfig &cpu() const { return m_cpu; }
private:
bool finalize();
void setAesMode(const rapidjson::Value &aesMode);
void setAlgoVariant(int av);
void setMaxCpuUsage(int max);
void setPriority(int priority);
void setThreads(const rapidjson::Value &threads);
AlgoVariant getAlgoVariant() const;
# ifdef XMRIG_ALGO_CN_LITE
AlgoVariant getAlgoVariantLite() const;
# endif
# ifndef XMRIG_NO_ASM
void setAssembly(const rapidjson::Value &assembly);
# endif
struct Threads
{
inline Threads() : mask(-1L), count(0), mode(Automatic) {}
int64_t mask;
size_t count;
std::vector<CpuThread::Data> cpu;
std::vector<IThread *> list;
ThreadsMode mode;
};
AesMode m_aesMode;
AlgoVariant m_algoVariant;
Assembly m_assembly;
bool m_hugePages;
bool m_safe;
bool m_shouldSave;
int m_maxCpuUsage;
int m_priority;
Threads m_threads;
bool m_shouldSave = false;
CpuConfig m_cpu;
};
} /* namespace xmrig */
#endif /* XMRIG_CONFIG_H */

View file

@ -23,27 +23,189 @@
*/
#include "core/config/ConfigTransform.h"
#include "base/kernel/interfaces/IConfig.h"
#include "core/config/ConfigTransform.h"
#include "crypto/cn/CnHash.h"
xmrig::ConfigTransform::ConfigTransform()
namespace xmrig
{
static const char *kAffinity = "affinity";
static const char *kAsterisk = "*";
static const char *kCpu = "cpu";
static const char *kIntensity = "intensity";
static inline uint64_t intensity(uint64_t av)
{
switch (av) {
case CnHash::AV_SINGLE:
case CnHash::AV_SINGLE_SOFT:
return 1;
case CnHash::AV_DOUBLE_SOFT:
case CnHash::AV_DOUBLE:
return 2;
case CnHash::AV_TRIPLE_SOFT:
case CnHash::AV_TRIPLE:
return 3;
case CnHash::AV_QUAD_SOFT:
case CnHash::AV_QUAD:
return 4;
case CnHash::AV_PENTA_SOFT:
case CnHash::AV_PENTA:
return 5;
default:
break;
}
return 1;
}
static inline bool isHwAes(uint64_t av)
{
return av == CnHash::AV_SINGLE || av == CnHash::AV_DOUBLE || (av > CnHash::AV_DOUBLE_SOFT && av < CnHash::AV_TRIPLE_SOFT);
}
static inline int64_t affinity(uint64_t index, int64_t affinity)
{
if (affinity == -1L) {
return -1L;
}
size_t idx = 0;
for (size_t i = 0; i < 64; i++) {
if (!(static_cast<uint64_t>(affinity) & (1ULL << i))) {
continue;
}
if (idx == index) {
return static_cast<int64_t>(i);
}
idx++;
}
return -1L;
}
}
xmrig::ConfigTransform::ConfigTransform() : BaseTransform()
{
}
void xmrig::ConfigTransform::finalize(rapidjson::Document &doc)
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
BaseTransform::finalize(doc);
if (m_threads) {
if (!doc.HasMember(kCpu)) {
doc.AddMember(StringRef(kCpu), Value(kObjectType), allocator);
}
Value threads(kArrayType);
if (m_intensity > 1) {
for (uint64_t i = 0; i < m_threads; ++i) {
Value thread(kObjectType);
thread.AddMember(StringRef(kIntensity), m_intensity, allocator);
thread.AddMember(StringRef(kAffinity), affinity(i, m_affinity), allocator);
threads.PushBack(thread, doc.GetAllocator());
}
}
else {
for (uint64_t i = 0; i < m_threads; ++i) {
threads.PushBack(affinity(i, m_affinity), doc.GetAllocator());
}
}
doc[kCpu].AddMember(StringRef(kAsterisk), threads, doc.GetAllocator());
}
}
void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const char *arg)
{
BaseTransform::transform(doc, key, arg);
switch (key) {
case IConfig::AVKey: /* --av */
case IConfig::CPUPriorityKey: /* --cpu-priority */
case IConfig::ThreadsKey: /* --threads */
return transformUint64(doc, key, static_cast<uint64_t>(strtol(arg, nullptr, 10)));
case IConfig::HugePagesKey: /* --no-huge-pages */
return transformBoolean(doc, key, false);
case IConfig::CPUAffinityKey: /* --cpu-affinity */
{
const char *p = strstr(arg, "0x");
return transformUint64(doc, key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10));
}
# ifndef XMRIG_NO_ASM
case IConfig::AssemblyKey: /* --asm */
return set(doc, kCpu, "asm", arg);
# endif
default:
break;
}
}
void xmrig::ConfigTransform::transformBoolean(rapidjson::Document &doc, int key, bool enable)
{
switch (key) {
case IConfig::HugePagesKey: /* --no-huge-pages */
return set(doc, kCpu, "huge-pages", enable);
default:
break;
}
}
void xmrig::ConfigTransform::transformUint64(rapidjson::Document &doc, int key, uint64_t arg)
{
using namespace rapidjson;
switch (key) {
case IConfig::CPUAffinityKey: /* --cpu-affinity */
m_affinity = static_cast<int64_t>(arg);
break;
case IConfig::ThreadsKey: /* --threads */
m_threads = arg;
break;
case IConfig::AVKey: /* --av */
m_intensity = intensity(arg);
set(doc, kCpu, "hw-aes", isHwAes(arg));
break;
case IConfig::CPUPriorityKey: /* --cpu-priority */
return set(doc, kCpu, "priority", arg);
default:
break;
}
}

View file

@ -5,7 +5,8 @@
* 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 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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
@ -37,11 +38,16 @@ public:
ConfigTransform();
protected:
void finalize(rapidjson::Document &doc) override;
void transform(rapidjson::Document &doc, int key, const char *arg) override;
private:
void transformBoolean(rapidjson::Document &doc, int key, bool enable);
void transformUint64(rapidjson::Document &doc, int key, uint64_t arg);
int64_t m_affinity = -1;
uint64_t m_intensity = 1;
uint64_t m_threads = 0;
};

View file

@ -62,16 +62,13 @@ static const option options[] = {
{ "dry-run", 0, nullptr, IConfig::DryRunKey },
{ "keepalive", 0, nullptr, IConfig::KeepAliveKey },
{ "log-file", 1, nullptr, IConfig::LogFileKey },
{ "max-cpu-usage", 1, nullptr, IConfig::MaxCPUUsageKey },
{ "nicehash", 0, nullptr, IConfig::NicehashKey },
{ "no-color", 0, nullptr, IConfig::ColorKey },
{ "no-huge-pages", 0, nullptr, IConfig::HugePagesKey },
{ "variant", 1, nullptr, IConfig::VariantKey },
{ "pass", 1, nullptr, IConfig::PasswordKey },
{ "print-time", 1, nullptr, IConfig::PrintTimeKey },
{ "retries", 1, nullptr, IConfig::RetriesKey },
{ "retry-pause", 1, nullptr, IConfig::RetryPauseKey },
{ "safe", 0, nullptr, IConfig::SafeKey },
{ "syslog", 0, nullptr, IConfig::SyslogKey },
{ "threads", 1, nullptr, IConfig::ThreadsKey },
{ "url", 1, nullptr, IConfig::UrlKey },
@ -84,39 +81,6 @@ static const option options[] = {
{ "asm", 1, nullptr, IConfig::AssemblyKey },
{ "daemon", 0, nullptr, IConfig::DaemonKey },
{ "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey },
# ifdef XMRIG_DEPRECATED
{ "api-port", 1, nullptr, IConfig::ApiPort },
{ "api-access-token", 1, nullptr, IConfig::ApiAccessTokenKey },
{ "api-no-restricted", 0, nullptr, IConfig::ApiRestrictedKey },
{ "api-ipv6", 0, nullptr, IConfig::ApiIPv6Key },
# endif
{ nullptr, 0, nullptr, 0 }
};
static struct option const config_options[] = {
{ "algo", 1, nullptr, IConfig::AlgorithmKey },
{ "av", 1, nullptr, IConfig::AVKey },
{ "background", 0, nullptr, IConfig::BackgroundKey },
{ "colors", 0, nullptr, IConfig::ColorKey },
{ "cpu-affinity", 1, nullptr, IConfig::CPUAffinityKey },
{ "cpu-priority", 1, nullptr, IConfig::CPUPriorityKey },
{ "donate-level", 1, nullptr, IConfig::DonateLevelKey },
{ "donate-over-proxy", 1, nullptr, IConfig::ProxyDonateKey },
{ "dry-run", 0, nullptr, IConfig::DryRunKey },
{ "huge-pages", 0, nullptr, IConfig::HugePagesKey },
{ "log-file", 1, nullptr, IConfig::LogFileKey },
{ "max-cpu-usage", 1, nullptr, IConfig::MaxCPUUsageKey },
{ "print-time", 1, nullptr, IConfig::PrintTimeKey },
{ "retries", 1, nullptr, IConfig::RetriesKey },
{ "retry-pause", 1, nullptr, IConfig::RetryPauseKey },
{ "safe", 0, nullptr, IConfig::SafeKey },
{ "syslog", 0, nullptr, IConfig::SyslogKey },
{ "threads", 1, nullptr, IConfig::ThreadsKey },
{ "user-agent", 1, nullptr, IConfig::UserAgentKey },
{ "asm", 1, nullptr, IConfig::AssemblyKey },
{ nullptr, 0, nullptr, 0 }
};

View file

@ -36,18 +36,28 @@ static char const usage[] = "\
Usage: " APP_ID " [OPTIONS]\n\
Options:\n\
-a, --algo=ALGO specify the algorithm to use\n\
cryptonight\n"
cn/r, cn/2, cn/1, cn/0, cn/double, cn/half, cn/fast,\n\
cn/rwz, cn/zls, cn/xao, cn/rto"
#ifdef XMRIG_ALGO_CN_GPU
", cn/gpu,\n"
#else
",\n"
#endif
#ifdef XMRIG_ALGO_CN_LITE
"\
cryptonight-lite\n"
cn-lite/1,\n"
#endif
#ifdef XMRIG_ALGO_CN_HEAVY
"\
cryptonight-heavy\n"
cn-heavy/xhv, cn-heavy/tube, cn-heavy/0,\n"
#endif
#ifdef XMRIG_ALGO_CN_PICO
"\
cryptonight-pico\n"
cn-pico,\n"
#endif
#ifdef XMRIG_ALGO_RANDOMX
"\
rx/wow, rx/loki\n"
#endif
"\
-o, --url=URL URL of mining server\n\
@ -76,7 +86,6 @@ Options:\n\
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
--no-huge-pages disable huge pages support\n\
--no-color disable colored output\n\
--variant algorithm PoW variant\n\
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
--user-agent set custom user-agent string for pool\n\
-B, --background run the miner in the background\n\
@ -87,8 +96,6 @@ Options:\n\
-S, --syslog use system log for output messages\n"
# endif
"\
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default: 100)\n\
--safe safe adjust threads and av settings for current CPU\n\
--asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer.\n\
--print-time=N print hashrate report every N seconds\n"
#ifdef XMRIG_FEATURE_HTTP

222
src/crypto/cn/CnAlgo.h Normal file
View file

@ -0,0 +1,222 @@
/* 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-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_CN_ALGO_H
#define XMRIG_CN_ALGO_H
#include <stddef.h>
#include <stdint.h>
#include "crypto/common/Algorithm.h"
namespace xmrig
{
template<Algorithm::Id ALGO = Algorithm::INVALID>
class CnAlgo
{
public:
constexpr inline CnAlgo()
{
static_assert(ALGO != Algorithm::INVALID && m_memory[ALGO] > 0, "invalid CRYPTONIGHT algorithm");
static_assert(sizeof(m_memory) / sizeof(m_memory)[0] == Algorithm::MAX, "memory table size mismatch");
static_assert(sizeof(m_iterations) / sizeof(m_iterations)[0] == Algorithm::MAX, "iterations table size mismatch");
static_assert(sizeof(m_base) / sizeof(m_base)[0] == Algorithm::MAX, "iterations table size mismatch");
}
constexpr inline Algorithm::Id base() const { return m_base[ALGO]; }
constexpr inline bool isHeavy() const { return memory() == CN_MEMORY * 2; }
constexpr inline bool isR() const { return ALGO == Algorithm::CN_R || ALGO == Algorithm::CN_WOW; }
constexpr inline size_t memory() const { return m_memory[ALGO]; }
constexpr inline uint32_t iterations() const { return m_iterations[ALGO]; }
constexpr inline uint32_t mask() const { return ((memory() - 1) / 16) * 16; }
inline static size_t memory(Algorithm::Id algo)
{
switch (Algorithm::family(algo)) {
case Algorithm::CN:
return CN_MEMORY;
case Algorithm::CN_LITE:
return CN_MEMORY / 2;
case Algorithm::CN_HEAVY:
return CN_MEMORY * 2;
case Algorithm::CN_PICO:
return CN_MEMORY / 8;
default:
break;
}
return 0;
}
inline static uint32_t mask(Algorithm::Id algo)
{
# ifdef XMRIG_ALGO_CN_GPU
if (algo == Algorithm::CN_GPU) {
return 0x1FFFC0;
}
# endif
# ifdef XMRIG_ALGO_CN_PICO
if (algo == Algorithm::CN_PICO_0) {
return 0x1FFF0;
}
# endif
return ((memory(algo) - 1) / 16) * 16;
}
private:
constexpr const static size_t CN_MEMORY = 0x200000;
constexpr const static uint32_t CN_ITER = 0x80000;
constexpr const static size_t m_memory[] = {
CN_MEMORY, // CN_0
CN_MEMORY, // CN_1
CN_MEMORY, // CN_2
CN_MEMORY, // CN_R
CN_MEMORY, // CN_WOW
CN_MEMORY, // CN_FAST
CN_MEMORY, // CN_HALF
CN_MEMORY, // CN_XAO
CN_MEMORY, // CN_RTO
CN_MEMORY, // CN_RWZ
CN_MEMORY, // CN_ZLS
CN_MEMORY, // CN_DOUBLE
# ifdef XMRIG_ALGO_CN_GPU
CN_MEMORY, // CN_GPU
# endif
# ifdef XMRIG_ALGO_CN_LITE
CN_MEMORY / 2, // CN_LITE_0
CN_MEMORY / 2, // CN_LITE_1
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
CN_MEMORY * 2, // CN_HEAVY_0
CN_MEMORY * 2, // CN_HEAVY_TUBE
CN_MEMORY * 2, // CN_HEAVY_XHV
# endif
# ifdef XMRIG_ALGO_CN_PICO
CN_MEMORY / 8, // CN_PICO_0
# endif
# ifdef XMRIG_ALGO_RANDOMX
0, // RX_0
0, // RX_WOW
0, // RX_LOKI
# endif
};
constexpr const static uint32_t m_iterations[] = {
CN_ITER, // CN_0
CN_ITER, // CN_1
CN_ITER, // CN_2
CN_ITER, // CN_R
CN_ITER, // CN_WOW
CN_ITER / 2, // CN_FAST
CN_ITER / 2, // CN_HALF
CN_ITER * 2, // CN_XAO
CN_ITER, // CN_RTO
0x60000, // CN_RWZ
0x60000, // CN_ZLS
CN_ITER * 2, // CN_DOUBLE
# ifdef XMRIG_ALGO_CN_GPU
0xC000, // CN_GPU
# endif
# ifdef XMRIG_ALGO_CN_LITE
CN_ITER / 2, // CN_LITE_0
CN_ITER / 2, // CN_LITE_1
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
CN_ITER / 2, // CN_HEAVY_0
CN_ITER / 2, // CN_HEAVY_TUBE
CN_ITER / 2, // CN_HEAVY_XHV
# endif
# ifdef XMRIG_ALGO_CN_PICO
CN_ITER / 8, // CN_PICO_0
# endif
# ifdef XMRIG_ALGO_RANDOMX
0, // RX_0
0, // RX_WOW
0, // RX_LOKI
# endif
};
constexpr const static Algorithm::Id m_base[] = {
Algorithm::CN_0, // CN_0
Algorithm::CN_1, // CN_1
Algorithm::CN_2, // CN_2
Algorithm::CN_2, // CN_R
Algorithm::CN_2, // CN_WOW
Algorithm::CN_1, // CN_FAST
Algorithm::CN_2, // CN_HALF
Algorithm::CN_0, // CN_XAO
Algorithm::CN_1, // CN_RTO
Algorithm::CN_2, // CN_RWZ
Algorithm::CN_2, // CN_ZLS
Algorithm::CN_2, // CN_DOUBLE
# ifdef XMRIG_ALGO_CN_GPU
Algorithm::CN_GPU, // CN_GPU
# endif
# ifdef XMRIG_ALGO_CN_LITE
Algorithm::CN_0, // CN_LITE_0
Algorithm::CN_1, // CN_LITE_1
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
Algorithm::CN_0, // CN_HEAVY_0
Algorithm::CN_1, // CN_HEAVY_TUBE
Algorithm::CN_0, // CN_HEAVY_XHV
# endif
# ifdef XMRIG_ALGO_CN_PICO
Algorithm::CN_2, // CN_PICO_0,
# endif
# ifdef XMRIG_ALGO_RANDOMX
Algorithm::INVALID, // RX_0
Algorithm::INVALID, // RX_WOW
Algorithm::INVALID, // RX_LOKI
# endif
};
};
#ifdef XMRIG_ALGO_CN_GPU
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_GPU>::mask() const { return 0x1FFFC0; }
#endif
#ifdef XMRIG_ALGO_CN_PICO
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_PICO_0>::mask() const { return 0x1FFF0; }
#endif
} /* namespace xmrig */
#endif /* XMRIG_CN_ALGO_H */

View file

@ -4,7 +4,7 @@
* 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 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
@ -23,59 +23,38 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <limits>
#include "crypto/cn/CryptoNight_constants.h"
#include "crypto/cn/CnCtx.h"
#include "crypto/cn/CryptoNight.h"
#include "crypto/common/Algorithm.h"
#include "crypto/common/portable/mm_malloc.h"
#include "crypto/common/VirtualMemory.h"
#include "Mem.h"
bool Mem::m_enabled = true;
int Mem::m_flags = 0;
MemInfo Mem::create(cryptonight_ctx **ctx, xmrig::Algo algorithm, size_t count)
void xmrig::CnCtx::create(cryptonight_ctx **ctx, uint8_t *memory, size_t size, size_t count)
{
using namespace xmrig;
MemInfo info;
info.size = cn_select_memory(algorithm) * count;
constexpr const size_t align_size = 2 * 1024 * 1024;
info.size = ((info.size + align_size - 1) / align_size) * align_size;
info.pages = info.size / align_size;
allocate(info, m_enabled);
for (size_t i = 0; i < count; ++i) {
cryptonight_ctx *c = static_cast<cryptonight_ctx *>(_mm_malloc(sizeof(cryptonight_ctx), 4096));
c->memory = info.memory + (i * cn_select_memory(algorithm));
c->memory = memory + (i * size);
c->generated_code = reinterpret_cast<cn_mainloop_fun_ms_abi>(xmrig::VirtualMemory::allocateExecutableMemory(0x4000));
c->generated_code_data.variant = xmrig::VARIANT_MAX;
c->generated_code = reinterpret_cast<cn_mainloop_fun_ms_abi>(VirtualMemory::allocateExecutableMemory(0x4000));
c->generated_code_data.algo = Algorithm::INVALID;
c->generated_code_data.height = std::numeric_limits<uint64_t>::max();
ctx[i] = c;
}
return info;
}
void Mem::release(cryptonight_ctx **ctx, size_t count, MemInfo &info)
void xmrig::CnCtx::release(cryptonight_ctx **ctx, size_t count)
{
if (info.memory == nullptr) {
if (ctx[0] == nullptr) {
return;
}
release(info);
for (size_t i = 0; i < count; ++i) {
_mm_free(ctx[i]);
}
}

View file

@ -4,8 +4,10 @@
* 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 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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
@ -21,30 +23,30 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_ASM_H
#define XMRIG_ASM_H
#ifndef XMRIG_CN_CTX_H
#define XMRIG_CN_CTX_H
#include "common/xmrig.h"
#include "rapidjson/fwd.h"
#include <stddef.h>
#include <stdint.h>
namespace xmrig {
struct cryptonight_ctx;
class Asm
namespace xmrig
{
class CnCtx
{
public:
static Assembly parse(const char *assembly, Assembly defaultValue = ASM_AUTO);
static Assembly parse(const rapidjson::Value &value, Assembly defaultValue = ASM_AUTO);
static const char *toString(Assembly assembly);
static rapidjson::Value toJSON(Assembly assembly);
inline static Assembly parse(bool enable) { return enable ? ASM_AUTO : ASM_NONE; }
static void create(cryptonight_ctx **ctx, uint8_t *memory, size_t size, size_t count);
static void release(cryptonight_ctx **ctx, size_t count);
};
} /* namespace xmrig */
#endif /* XMRIG_ASM_H */
#endif /* XMRIG_CN_CTX_H */

272
src/crypto/cn/CnHash.cpp Normal file
View file

@ -0,0 +1,272 @@
/* 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-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 <stdio.h>
#include "backend/cpu/Cpu.h"
#include "crypto/cn/CnHash.h"
#include "crypto/common/VirtualMemory.h"
#if defined(XMRIG_ARM)
# include "crypto/cn/CryptoNight_arm.h"
#else
# include "crypto/cn/CryptoNight_x86.h"
#endif
#define ADD_FN(algo) \
m_map[algo][AV_SINGLE][Assembly::NONE] = cryptonight_single_hash<algo, false>; \
m_map[algo][AV_SINGLE_SOFT][Assembly::NONE] = cryptonight_single_hash<algo, true>; \
m_map[algo][AV_DOUBLE][Assembly::NONE] = cryptonight_double_hash<algo, false>; \
m_map[algo][AV_DOUBLE_SOFT][Assembly::NONE] = cryptonight_double_hash<algo, true>; \
m_map[algo][AV_TRIPLE][Assembly::NONE] = cryptonight_triple_hash<algo, false>; \
m_map[algo][AV_TRIPLE_SOFT][Assembly::NONE] = cryptonight_triple_hash<algo, true>; \
m_map[algo][AV_QUAD][Assembly::NONE] = cryptonight_quad_hash<algo, false>; \
m_map[algo][AV_QUAD_SOFT][Assembly::NONE] = cryptonight_quad_hash<algo, true>; \
m_map[algo][AV_PENTA][Assembly::NONE] = cryptonight_penta_hash<algo, false>; \
m_map[algo][AV_PENTA_SOFT][Assembly::NONE] = cryptonight_penta_hash<algo, true>;
#ifdef XMRIG_FEATURE_ASM
# define ADD_FN_ASM(algo) \
m_map[algo][AV_SINGLE][Assembly::INTEL] = cryptonight_single_hash_asm<algo, Assembly::INTEL>; \
m_map[algo][AV_SINGLE][Assembly::RYZEN] = cryptonight_single_hash_asm<algo, Assembly::RYZEN>; \
m_map[algo][AV_SINGLE][Assembly::BULLDOZER] = cryptonight_single_hash_asm<algo, Assembly::BULLDOZER>; \
m_map[algo][AV_DOUBLE][Assembly::INTEL] = cryptonight_double_hash_asm<algo, Assembly::INTEL>; \
m_map[algo][AV_DOUBLE][Assembly::RYZEN] = cryptonight_double_hash_asm<algo, Assembly::RYZEN>; \
m_map[algo][AV_DOUBLE][Assembly::BULLDOZER] = cryptonight_double_hash_asm<algo, Assembly::BULLDOZER>;
extern "C" void cnv2_mainloop_ivybridge_asm(cryptonight_ctx **ctx);
extern "C" void cnv2_mainloop_ryzen_asm(cryptonight_ctx **ctx);
extern "C" void cnv2_mainloop_bulldozer_asm(cryptonight_ctx **ctx);
extern "C" void cnv2_double_mainloop_sandybridge_asm(cryptonight_ctx **ctx);
namespace xmrig {
cn_mainloop_fun cn_half_mainloop_ivybridge_asm = nullptr;
cn_mainloop_fun cn_half_mainloop_ryzen_asm = nullptr;
cn_mainloop_fun cn_half_mainloop_bulldozer_asm = nullptr;
cn_mainloop_fun cn_half_double_mainloop_sandybridge_asm = nullptr;
cn_mainloop_fun cn_trtl_mainloop_ivybridge_asm = nullptr;
cn_mainloop_fun cn_trtl_mainloop_ryzen_asm = nullptr;
cn_mainloop_fun cn_trtl_mainloop_bulldozer_asm = nullptr;
cn_mainloop_fun cn_trtl_double_mainloop_sandybridge_asm = nullptr;
cn_mainloop_fun cn_zls_mainloop_ivybridge_asm = nullptr;
cn_mainloop_fun cn_zls_mainloop_ryzen_asm = nullptr;
cn_mainloop_fun cn_zls_mainloop_bulldozer_asm = nullptr;
cn_mainloop_fun cn_zls_double_mainloop_sandybridge_asm = nullptr;
cn_mainloop_fun cn_double_mainloop_ivybridge_asm = nullptr;
cn_mainloop_fun cn_double_mainloop_ryzen_asm = nullptr;
cn_mainloop_fun cn_double_mainloop_bulldozer_asm = nullptr;
cn_mainloop_fun cn_double_double_mainloop_sandybridge_asm = nullptr;
template<typename T, typename U>
static void patchCode(T dst, U src, const uint32_t iterations, const uint32_t mask = CnAlgo<Algorithm::CN_HALF>().mask())
{
const uint8_t* p = reinterpret_cast<const uint8_t*>(src);
// Workaround for Visual Studio placing trampoline in debug builds.
# if defined(_MSC_VER)
if (p[0] == 0xE9) {
p += *(int32_t*)(p + 1) + 5;
}
# endif
size_t size = 0;
while (*(uint32_t*)(p + size) != 0xDEADC0DE) {
++size;
}
size += sizeof(uint32_t);
memcpy((void*) dst, (const void*) src, size);
uint8_t* patched_data = reinterpret_cast<uint8_t*>(dst);
for (size_t i = 0; i + sizeof(uint32_t) <= size; ++i) {
switch (*(uint32_t*)(patched_data + i)) {
case CnAlgo<Algorithm::CN_2>().iterations():
*(uint32_t*)(patched_data + i) = iterations;
break;
case CnAlgo<Algorithm::CN_2>().mask():
*(uint32_t*)(patched_data + i) = mask;
break;
}
}
}
static void patchAsmVariants()
{
const int allocation_size = 65536;
uint8_t *base = static_cast<uint8_t *>(VirtualMemory::allocateExecutableMemory(allocation_size));
cn_half_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x0000);
cn_half_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x1000);
cn_half_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x2000);
cn_half_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x3000);
# ifdef XMRIG_ALGO_CN_PICO
cn_trtl_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x4000);
cn_trtl_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x5000);
cn_trtl_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x6000);
cn_trtl_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x7000);
# endif
cn_zls_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x8000);
cn_zls_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x9000);
cn_zls_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xA000);
cn_zls_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xB000);
cn_double_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xC000);
cn_double_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xD000);
cn_double_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xE000);
cn_double_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xF000);
{
constexpr uint32_t ITER = CnAlgo<Algorithm::CN_HALF>().iterations();
patchCode(cn_half_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, ITER);
patchCode(cn_half_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, ITER);
patchCode(cn_half_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, ITER);
patchCode(cn_half_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER);
}
# ifdef XMRIG_ALGO_CN_PICO
{
constexpr uint32_t ITER = CnAlgo<Algorithm::CN_PICO_0>().iterations();
constexpr uint32_t MASK = CnAlgo<Algorithm::CN_PICO_0>().mask();
patchCode(cn_trtl_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, ITER, MASK);
patchCode(cn_trtl_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, ITER, MASK);
patchCode(cn_trtl_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, ITER, MASK);
patchCode(cn_trtl_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER, MASK);
}
# endif
{
constexpr uint32_t ITER = CnAlgo<Algorithm::CN_ZLS>().iterations();
patchCode(cn_zls_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, ITER);
patchCode(cn_zls_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, ITER);
patchCode(cn_zls_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, ITER);
patchCode(cn_zls_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER);
}
{
constexpr uint32_t ITER = CnAlgo<Algorithm::CN_DOUBLE>().iterations();
patchCode(cn_double_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, ITER);
patchCode(cn_double_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, ITER);
patchCode(cn_double_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, ITER);
patchCode(cn_double_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER);
}
VirtualMemory::protectExecutableMemory(base, allocation_size);
VirtualMemory::flushInstructionCache(base, allocation_size);
}
} // namespace xmrig
#else
# define ADD_FN_ASM(algo)
#endif
static const xmrig::CnHash cnHash;
xmrig::CnHash::CnHash()
{
ADD_FN(Algorithm::CN_0);
ADD_FN(Algorithm::CN_1);
ADD_FN(Algorithm::CN_2);
ADD_FN(Algorithm::CN_R);
ADD_FN(Algorithm::CN_WOW);
ADD_FN(Algorithm::CN_FAST);
ADD_FN(Algorithm::CN_HALF);
ADD_FN(Algorithm::CN_XAO);
ADD_FN(Algorithm::CN_RTO);
ADD_FN(Algorithm::CN_RWZ);
ADD_FN(Algorithm::CN_ZLS);
ADD_FN(Algorithm::CN_DOUBLE);
ADD_FN_ASM(Algorithm::CN_2);
ADD_FN_ASM(Algorithm::CN_HALF);
ADD_FN_ASM(Algorithm::CN_R);
ADD_FN_ASM(Algorithm::CN_WOW);
ADD_FN_ASM(Algorithm::CN_RWZ);
ADD_FN_ASM(Algorithm::CN_ZLS);
ADD_FN_ASM(Algorithm::CN_DOUBLE);
# ifdef XMRIG_ALGO_CN_GPU
m_map[Algorithm::CN_GPU][AV_SINGLE][Assembly::NONE] = cryptonight_single_hash_gpu<Algorithm::CN_GPU, false>;
m_map[Algorithm::CN_GPU][AV_SINGLE_SOFT][Assembly::NONE] = cryptonight_single_hash_gpu<Algorithm::CN_GPU, true>;
# endif
# ifdef XMRIG_ALGO_CN_LITE
ADD_FN(Algorithm::CN_LITE_0);
ADD_FN(Algorithm::CN_LITE_1);
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
ADD_FN(Algorithm::CN_HEAVY_0);
ADD_FN(Algorithm::CN_HEAVY_TUBE);
ADD_FN(Algorithm::CN_HEAVY_XHV);
# endif
# ifdef XMRIG_ALGO_CN_PICO
ADD_FN(Algorithm::CN_PICO_0);
ADD_FN_ASM(Algorithm::CN_PICO_0);
# endif
# ifdef XMRIG_FEATURE_ASM
patchAsmVariants();
# endif
}
xmrig::cn_hash_fun xmrig::CnHash::fn(const Algorithm &algorithm, AlgoVariant av, Assembly::Id assembly)
{
if (!algorithm.isValid()) {
return nullptr;
}
# ifdef XMRIG_FEATURE_ASM
cn_hash_fun fun = cnHash.m_map[algorithm][av][Cpu::assembly(assembly)];
if (fun) {
return fun;
}
# endif
return cnHash.m_map[algorithm][av][Assembly::NONE];
}

78
src/crypto/cn/CnHash.h Normal file
View file

@ -0,0 +1,78 @@
/* 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-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_CN_HASH_H
#define XMRIG_CN_HASH_H
#include <stddef.h>
#include <stdint.h>
#include "crypto/cn/CnAlgo.h"
#include "crypto/common/Assembly.h"
struct cryptonight_ctx;
namespace xmrig
{
typedef void (*cn_hash_fun)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx **ctx, uint64_t height);
typedef void (*cn_mainloop_fun)(cryptonight_ctx **ctx);
class CnHash
{
public:
enum AlgoVariant {
AV_AUTO, // --av=0 Automatic mode.
AV_SINGLE, // --av=1 Single hash mode
AV_DOUBLE, // --av=2 Double hash mode
AV_SINGLE_SOFT, // --av=3 Single hash mode (Software AES)
AV_DOUBLE_SOFT, // --av=4 Double hash mode (Software AES)
AV_TRIPLE, // --av=5 Triple hash mode
AV_QUAD, // --av=6 Quard hash mode
AV_PENTA, // --av=7 Penta hash mode
AV_TRIPLE_SOFT, // --av=8 Triple hash mode (Software AES)
AV_QUAD_SOFT, // --av=9 Quard hash mode (Software AES)
AV_PENTA_SOFT, // --av=10 Penta hash mode (Software AES)
AV_MAX
};
CnHash();
static cn_hash_fun fn(const Algorithm &algorithm, AlgoVariant av, Assembly::Id assembly);
private:
cn_hash_fun m_map[Algorithm::MAX][AV_MAX][Assembly::MAX] = {};
};
} /* namespace xmrig */
#endif /* XMRIG_CN_HASH_H */

View file

@ -42,10 +42,10 @@ typedef void(*cn_mainloop_fun_ms_abi)(cryptonight_ctx**) ABI_ATTRIBUTE;
struct cryptonight_r_data {
int variant;
int algo;
uint64_t height;
bool match(const int v, const uint64_t h) const { return (v == variant) && (h == height); }
bool match(const int a, const uint64_t h) const { return (a == algo) && (h == height); }
};

View file

@ -28,12 +28,12 @@
#define XMRIG_CRYPTONIGHT_ARM_H
#include "common/crypto/keccak.h"
#include "crypto/common/portable/mm_malloc.h"
#include "crypto/cn/CryptoNight_constants.h"
#include "crypto/cn/CnAlgo.h"
#include "crypto/cn/CryptoNight_monero.h"
#include "crypto/cn/CryptoNight.h"
#include "crypto/cn/soft_aes.h"
#include "crypto/common/keccak.h"
#include "crypto/common/portable/mm_malloc.h"
extern "C"
@ -226,9 +226,14 @@ inline void mix_and_propagate(__m128i& x0, __m128i& x1, __m128i& x2, __m128i& x3
}
template<xmrig::Algo ALGO, size_t MEM, bool SOFT_AES>
namespace xmrig {
template<Algorithm::Id ALGO, bool SOFT_AES>
static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
{
constexpr CnAlgo<ALGO> props;
__m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
@ -243,7 +248,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
xin6 = _mm_load_si128(input + 10);
xin7 = _mm_load_si128(input + 11);
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
if (props.isHeavy()) {
for (size_t i = 0; i < 16; i++) {
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
@ -260,7 +265,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
}
}
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
for (size_t i = 0; i < props.memory() / sizeof(__m128i); i += 8) {
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
@ -284,37 +289,17 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
}
#ifdef XMRIG_ALGO_CN_GPU
template<xmrig::Algo ALGO, size_t MEM>
void cn_explode_scratchpad_gpu(const uint8_t *input, uint8_t *output)
{
constexpr size_t hash_size = 200; // 25x8 bytes
alignas(16) uint64_t hash[25];
for (uint64_t i = 0; i < MEM / 512; i++)
{
memcpy(hash, input, hash_size);
hash[0] ^= i;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 160);
output += 160;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 176);
output += 176;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 176);
output += 176;
}
}
#endif
template<xmrig::Algo ALGO, size_t MEM, bool SOFT_AES>
template<Algorithm::Id ALGO, bool SOFT_AES>
static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
{
constexpr CnAlgo<ALGO> props;
# ifdef XMRIG_ALGO_CN_GPU
constexpr bool IS_HEAVY = props.isHeavy() || ALGO == Algorithm::CN_GPU;
# else
constexpr bool IS_HEAVY = props.isHeavy();
# endif
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
@ -329,8 +314,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout6 = _mm_load_si128(output + 10);
xout7 = _mm_load_si128(output + 11);
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
{
for (size_t i = 0; i < props.memory() / sizeof(__m128i); i += 8) {
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
@ -351,13 +335,13 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
if (IS_HEAVY) {
mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
}
}
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
if (IS_HEAVY) {
for (size_t i = 0; i < props.memory() / sizeof(__m128i); i += 8) {
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
@ -408,6 +392,9 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
}
} /* namespace xmrig */
static inline __m128i aes_round_tweak_div(const __m128i &in, const __m128i &key)
{
alignas(16) uint32_t k[4];
@ -430,13 +417,18 @@ static inline __m128i aes_round_tweak_div(const __m128i &in, const __m128i &key)
}
template<xmrig::Variant VARIANT, xmrig::Variant BASE>
namespace xmrig {
template<Algorithm::Id ALGO>
static inline void cryptonight_monero_tweak(const uint8_t* l, uint64_t idx, __m128i ax0, __m128i bx0, __m128i bx1, __m128i& cx)
{
constexpr CnAlgo<ALGO> props;
uint64_t* mem_out = (uint64_t*)&l[idx];
if (BASE == xmrig::VARIANT_2) {
VARIANT2_SHUFFLE(l, idx, ax0, bx0, bx1, cx, (VARIANT == xmrig::VARIANT_RWZ ? 1 : 0));
if (props.base() == Algorithm::CN_2) {
VARIANT2_SHUFFLE(l, idx, ax0, bx0, bx1, cx, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
_mm_store_si128((__m128i *)mem_out, _mm_xor_si128(bx0, cx));
} else {
__m128i tmp = _mm_xor_si128(bx0, cx);
@ -446,7 +438,7 @@ static inline void cryptonight_monero_tweak(const uint8_t* l, uint64_t idx, __m1
uint8_t x = vh >> 24;
static const uint16_t table = 0x7531;
const uint8_t index = (((x >> (VARIANT == xmrig::VARIANT_XTL ? 4 : 3)) & 6) | (x & 1)) << 1;
const uint8_t index = (((x >> (3)) & 6) | (x & 1)) << 1;
vh ^= ((table >> index) & 0x3) << 28;
mem_out[1] = vh;
@ -454,24 +446,28 @@ static inline void cryptonight_monero_tweak(const uint8_t* l, uint64_t idx, __m1
}
template<xmrig::Algo ALGO, bool SOFT_AES, xmrig::Variant VARIANT>
template<Algorithm::Id ALGO, bool SOFT_AES>
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO, VARIANT>();
constexpr size_t MEM = xmrig::cn_select_memory<ALGO>();
constexpr xmrig::Variant BASE = xmrig::cn_base_variant<VARIANT>();
constexpr CnAlgo<ALGO> props;
constexpr size_t MASK = props.mask();
constexpr Algorithm::Id BASE = props.base();
if (BASE == xmrig::VARIANT_1 && size < 43) {
# ifdef XMRIG_ALGO_CN_HEAVY
constexpr bool IS_CN_HEAVY_TUBE = ALGO == Algorithm::CN_HEAVY_TUBE;
# else
constexpr bool IS_CN_HEAVY_TUBE = false;
# endif
if (BASE == Algorithm::CN_1 && size < 43) {
memset(output, 0, 32);
return;
}
xmrig::keccak(input, size, ctx[0]->state);
keccak(input, size, ctx[0]->state);
cn_explode_scratchpad<ALGO, SOFT_AES>(reinterpret_cast<const __m128i *>(ctx[0]->state), reinterpret_cast<__m128i *>(ctx[0]->memory));
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->state, (__m128i*) ctx[0]->memory);
const uint8_t* l0 = ctx[0]->memory;
uint8_t* l0 = ctx[0]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
VARIANT1_INIT(0);
@ -485,14 +481,14 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
uint64_t idx0 = al0;
for (size_t i = 0; i < ITERATIONS; i++) {
for (size_t i = 0; i < props.iterations(); i++) {
__m128i cx;
if (VARIANT == xmrig::VARIANT_TUBE || !SOFT_AES) {
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
if (IS_CN_HEAVY_TUBE || !SOFT_AES) {
cx = _mm_load_si128(reinterpret_cast<const __m128i *>(&l0[idx0 & MASK]));
}
const __m128i ax0 = _mm_set_epi64x(ah0, al0);
if (VARIANT == xmrig::VARIANT_TUBE) {
if (IS_CN_HEAVY_TUBE) {
cx = aes_round_tweak_div(cx, ax0);
}
else if (SOFT_AES) {
@ -502,8 +498,8 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
cx = _mm_aesenc_si128(cx, ax0);
}
if (BASE == xmrig::VARIANT_1 || BASE == xmrig::VARIANT_2) {
cryptonight_monero_tweak<VARIANT, BASE>(l0, idx0 & MASK, ax0, bx0, bx1, cx);
if (BASE == Algorithm::CN_1 || BASE == Algorithm::CN_2) {
cryptonight_monero_tweak<ALGO>(l0, idx0 & MASK, ax0, bx0, bx1, cx);
} else {
_mm_store_si128((__m128i *)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
}
@ -514,10 +510,10 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
cl = ((uint64_t*) &l0[idx0 & MASK])[0];
ch = ((uint64_t*) &l0[idx0 & MASK])[1];
if (BASE == xmrig::VARIANT_2) {
if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) {
if (BASE == Algorithm::CN_2) {
if (props.isR()) {
VARIANT4_RANDOM_MATH(0, al0, ah0, cl, bx0, bx1);
if (VARIANT == xmrig::VARIANT_4) {
if (ALGO == Algorithm::CN_R) {
al0 ^= r0[2] | ((uint64_t)(r0[3]) << 32);
ah0 ^= r0[0] | ((uint64_t)(r0[1]) << 32);
}
@ -528,11 +524,11 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
lo = __umul128(idx0, cl, &hi);
if (BASE == xmrig::VARIANT_2) {
if (VARIANT == xmrig::VARIANT_4) {
if (BASE == Algorithm::CN_2) {
if (ALGO == Algorithm::CN_R) {
VARIANT2_SHUFFLE(l0, idx0 & MASK, ax0, bx0, bx1, cx, 0);
} else {
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx0, bx1, hi, lo, (VARIANT == xmrig::VARIANT_RWZ ? 1 : 0));
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx0, bx1, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
}
}
@ -541,9 +537,9 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
((uint64_t*)&l0[idx0 & MASK])[0] = al0;
if (BASE == xmrig::VARIANT_1 && (VARIANT == xmrig::VARIANT_TUBE || VARIANT == xmrig::VARIANT_RTO)) {
if (IS_CN_HEAVY_TUBE || ALGO == Algorithm::CN_RTO) {
((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0 ^ al0;
} else if (BASE == xmrig::VARIANT_1) {
} else if (BASE == Algorithm::CN_1) {
((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0;
} else {
((uint64_t*)&l0[idx0 & MASK])[1] = ah0;
@ -553,7 +549,8 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
ah0 ^= ch;
idx0 = al0;
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
# ifdef XMRIG_ALGO_CN_HEAVY
if (props.isHeavy()) {
const int64x2_t x = vld1q_s64(reinterpret_cast<const int64_t *>(&l0[idx0 & MASK]));
const int64_t n = vgetq_lane_s64(x, 0);
const int32_t d = vgetq_lane_s32(x, 2);
@ -561,75 +558,111 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
((int64_t*)&l0[idx0 & MASK])[0] = n ^ q;
if (VARIANT == xmrig::VARIANT_XHV) {
if (ALGO == Algorithm::CN_HEAVY_XHV) {
idx0 = (~d) ^ q;
}
else {
idx0 = d ^ q;
}
}
# endif
if (BASE == xmrig::VARIANT_2) {
if (BASE == Algorithm::CN_2) {
bx1 = bx0;
}
bx0 = cx;
}
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->memory, (__m128i*) ctx[0]->state);
xmrig::keccakf(h0, 24);
cn_implode_scratchpad<ALGO, SOFT_AES>(reinterpret_cast<const __m128i *>(ctx[0]->memory), reinterpret_cast<__m128i *>(ctx[0]->state));
keccakf(h0, 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
}
} /* namespace xmrig */
#ifdef XMRIG_ALGO_CN_GPU
template<size_t ITER, uint32_t MASK>
void cn_gpu_inner_arm(const uint8_t *spad, uint8_t *lpad);
template<xmrig::Algo ALGO, bool SOFT_AES, xmrig::Variant VARIANT>
namespace xmrig {
template<size_t MEM>
void cn_explode_scratchpad_gpu(const uint8_t *input, uint8_t *output)
{
constexpr size_t hash_size = 200; // 25x8 bytes
alignas(16) uint64_t hash[25];
for (uint64_t i = 0; i < MEM / 512; i++) {
memcpy(hash, input, hash_size);
hash[0] ^= i;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 160);
output += 160;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 176);
output += 176;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 176);
output += 176;
}
}
template<xmrig::Algorithm::Id ALGO, bool SOFT_AES>
inline void cryptonight_single_hash_gpu(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height)
{
constexpr size_t MASK = xmrig::CRYPTONIGHT_GPU_MASK;
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO, VARIANT>();
constexpr size_t MEM = xmrig::cn_select_memory<ALGO>();
constexpr CnAlgo<ALGO> props;
static_assert(MASK > 0 && ITERATIONS > 0 && MEM > 0, "unsupported algorithm/variant");
xmrig::keccak(input, size, ctx[0]->state);
cn_explode_scratchpad_gpu<ALGO, MEM>(ctx[0]->state, ctx[0]->memory);
keccak(input, size, ctx[0]->state);
cn_explode_scratchpad_gpu<props.memory()>(ctx[0]->state, ctx[0]->memory);
fesetround(FE_TONEAREST);
cn_gpu_inner_arm<ITERATIONS, MASK>(ctx[0]->state, ctx[0]->memory);
cn_gpu_inner_arm<props.iterations(), props.mask()>(ctx[0]->state, ctx[0]->memory);
cn_implode_scratchpad<xmrig::CRYPTONIGHT_HEAVY, MEM, SOFT_AES>((__m128i*) ctx[0]->memory, (__m128i*) ctx[0]->state);
xmrig::keccakf((uint64_t*) ctx[0]->state, 24);
cn_implode_scratchpad<ALGO, SOFT_AES>(reinterpret_cast<const __m128i *>(ctx[0]->memory), reinterpret_cast<__m128i *>(ctx[0]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[0]->state), 24);
memcpy(output, ctx[0]->state, 32);
}
} /* namespace xmrig */
#endif
template<xmrig::Algo ALGO, bool SOFT_AES, xmrig::Variant VARIANT>
namespace xmrig {
template<Algorithm::Id ALGO, bool SOFT_AES>
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx, uint64_t height)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO, VARIANT>();
constexpr size_t MEM = xmrig::cn_select_memory<ALGO>();
constexpr xmrig::Variant BASE = xmrig::cn_base_variant<VARIANT>();
constexpr CnAlgo<ALGO> props;
constexpr size_t MASK = props.mask();
constexpr Algorithm::Id BASE = props.base();
if (BASE == xmrig::VARIANT_1 && size < 43) {
# ifdef XMRIG_ALGO_CN_HEAVY
constexpr bool IS_CN_HEAVY_TUBE = ALGO == Algorithm::CN_HEAVY_TUBE;
# else
constexpr bool IS_CN_HEAVY_TUBE = false;
# endif
if (BASE == Algorithm::CN_1 && size < 43) {
memset(output, 0, 64);
return;
}
xmrig::keccak(input, size, ctx[0]->state);
xmrig::keccak(input + size, size, ctx[1]->state);
keccak(input, size, ctx[0]->state);
keccak(input + size, size, ctx[1]->state);
const uint8_t* l0 = ctx[0]->memory;
const uint8_t* l1 = ctx[1]->memory;
uint8_t *l0 = ctx[0]->memory;
uint8_t *l1 = ctx[1]->memory;
uint64_t *h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t *h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
@ -640,8 +673,8 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
VARIANT4_RANDOM_MATH_INIT(0);
VARIANT4_RANDOM_MATH_INIT(1);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) h0, (__m128i*) l0);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) h1, (__m128i*) l1);
cn_explode_scratchpad<ALGO, SOFT_AES>(reinterpret_cast<const __m128i *>(h0), reinterpret_cast<__m128i *>(l0));
cn_explode_scratchpad<ALGO, SOFT_AES>(reinterpret_cast<const __m128i *>(h1), reinterpret_cast<__m128i *>(l1));
uint64_t al0 = h0[0] ^ h0[4];
uint64_t al1 = h1[0] ^ h1[4];
@ -656,16 +689,16 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
uint64_t idx0 = al0;
uint64_t idx1 = al1;
for (size_t i = 0; i < ITERATIONS; i++) {
for (size_t i = 0; i < props.iterations(); i++) {
__m128i cx0, cx1;
if (VARIANT == xmrig::VARIANT_TUBE || !SOFT_AES) {
if (IS_CN_HEAVY_TUBE || !SOFT_AES) {
cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
}
const __m128i ax0 = _mm_set_epi64x(ah0, al0);
const __m128i ax1 = _mm_set_epi64x(ah1, al1);
if (VARIANT == xmrig::VARIANT_TUBE) {
if (IS_CN_HEAVY_TUBE) {
cx0 = aes_round_tweak_div(cx0, ax0);
cx1 = aes_round_tweak_div(cx1, ax1);
}
@ -678,9 +711,9 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
cx1 = _mm_aesenc_si128(cx1, ax1);
}
if (BASE == xmrig::VARIANT_1 || (BASE == xmrig::VARIANT_2)) {
cryptonight_monero_tweak<VARIANT, BASE>(l0, idx0 & MASK, ax0, bx00, bx01, cx0);
cryptonight_monero_tweak<VARIANT, BASE>(l1, idx1 & MASK, ax1, bx10, bx11, cx1);
if (BASE == Algorithm::CN_1 || BASE == Algorithm::CN_2) {
cryptonight_monero_tweak<ALGO>(l0, idx0 & MASK, ax0, bx00, bx01, cx0);
cryptonight_monero_tweak<ALGO>(l1, idx1 & MASK, ax1, bx10, bx11, cx1);
} else {
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx00, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx10, cx1));
@ -693,10 +726,10 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
cl = ((uint64_t*) &l0[idx0 & MASK])[0];
ch = ((uint64_t*) &l0[idx0 & MASK])[1];
if (BASE == xmrig::VARIANT_2) {
if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) {
if (BASE == Algorithm::CN_2) {
if (props.isR()) {
VARIANT4_RANDOM_MATH(0, al0, ah0, cl, bx00, bx01);
if (VARIANT == xmrig::VARIANT_4) {
if (ALGO == Algorithm::CN_R) {
al0 ^= r0[2] | ((uint64_t)(r0[3]) << 32);
ah0 ^= r0[0] | ((uint64_t)(r0[1]) << 32);
}
@ -707,11 +740,11 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
lo = __umul128(idx0, cl, &hi);
if (BASE == xmrig::VARIANT_2) {
if (VARIANT == xmrig::VARIANT_4) {
if (BASE == Algorithm::CN_2) {
if (ALGO == Algorithm::CN_R) {
VARIANT2_SHUFFLE(l0, idx0 & MASK, ax0, bx00, bx01, cx0, 0);
} else {
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx00, bx01, hi, lo, (VARIANT == xmrig::VARIANT_RWZ ? 1 : 0));
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx00, bx01, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
}
}
@ -720,9 +753,9 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
((uint64_t*)&l0[idx0 & MASK])[0] = al0;
if (BASE == xmrig::VARIANT_1 && (VARIANT == xmrig::VARIANT_TUBE || VARIANT == xmrig::VARIANT_RTO)) {
if (IS_CN_HEAVY_TUBE || ALGO == Algorithm::CN_RTO) {
((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0 ^ al0;
} else if (BASE == xmrig::VARIANT_1) {
} else if (BASE == Algorithm::CN_1) {
((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0;
} else {
((uint64_t*)&l0[idx0 & MASK])[1] = ah0;
@ -732,7 +765,8 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
ah0 ^= ch;
idx0 = al0;
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
# ifdef XMRIG_ALGO_CN_HEAVY
if (props.isHeavy()) {
const int64x2_t x = vld1q_s64(reinterpret_cast<const int64_t *>(&l0[idx0 & MASK]));
const int64_t n = vgetq_lane_s64(x, 0);
const int32_t d = vgetq_lane_s32(x, 2);
@ -740,21 +774,22 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
((int64_t*)&l0[idx0 & MASK])[0] = n ^ q;
if (VARIANT == xmrig::VARIANT_XHV) {
if (ALGO == Algorithm::CN_HEAVY_XHV) {
idx0 = (~d) ^ q;
}
else {
idx0 = d ^ q;
}
}
# endif
cl = ((uint64_t*) &l1[idx1 & MASK])[0];
ch = ((uint64_t*) &l1[idx1 & MASK])[1];
if (BASE == xmrig::VARIANT_2) {
if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) {
if (BASE == Algorithm::CN_2) {
if (props.isR()) {
VARIANT4_RANDOM_MATH(1, al1, ah1, cl, bx10, bx11);
if (VARIANT == xmrig::VARIANT_4) {
if (ALGO == Algorithm::CN_R) {
al1 ^= r1[2] | ((uint64_t)(r1[3]) << 32);
ah1 ^= r1[0] | ((uint64_t)(r1[1]) << 32);
}
@ -765,11 +800,11 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
lo = __umul128(idx1, cl, &hi);
if (BASE == xmrig::VARIANT_2) {
if (VARIANT == xmrig::VARIANT_4) {
if (BASE == Algorithm::CN_2) {
if (ALGO == Algorithm::CN_R) {
VARIANT2_SHUFFLE(l1, idx1 & MASK, ax1, bx10, bx11, cx1, 0);
} else {
VARIANT2_SHUFFLE2(l1, idx1 & MASK, ax1, bx10, bx11, hi, lo, (VARIANT == xmrig::VARIANT_RWZ ? 1 : 0));
VARIANT2_SHUFFLE2(l1, idx1 & MASK, ax1, bx10, bx11, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
}
}
@ -778,9 +813,9 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
((uint64_t*)&l1[idx1 & MASK])[0] = al1;
if (BASE == xmrig::VARIANT_1 && (VARIANT == xmrig::VARIANT_TUBE || VARIANT == xmrig::VARIANT_RTO)) {
if (IS_CN_HEAVY_TUBE || ALGO == Algorithm::CN_RTO) {
((uint64_t*)&l1[idx1 & MASK])[1] = ah1 ^ tweak1_2_1 ^ al1;
} else if (BASE == xmrig::VARIANT_1) {
} else if (BASE == Algorithm::CN_1) {
((uint64_t*)&l1[idx1 & MASK])[1] = ah1 ^ tweak1_2_1;
} else {
((uint64_t*)&l1[idx1 & MASK])[1] = ah1;
@ -790,7 +825,8 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
ah1 ^= ch;
idx1 = al1;
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
# ifdef XMRIG_ALGO_CN_HEAVY
if (props.isHeavy()) {
const int64x2_t x = vld1q_s64(reinterpret_cast<const int64_t *>(&l1[idx1 & MASK]));
const int64_t n = vgetq_lane_s64(x, 0);
const int32_t d = vgetq_lane_s32(x, 2);
@ -798,47 +834,54 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
((int64_t*)&l1[idx1 & MASK])[0] = n ^ q;
if (VARIANT == xmrig::VARIANT_XHV) {
if (ALGO == Algorithm::CN_HEAVY_XHV) {
idx1 = (~d) ^ q;
}
else {
idx1 = d ^ q;
}
}
if (BASE == xmrig::VARIANT_2) {
# endif
if (BASE == Algorithm::CN_2) {
bx01 = bx00;
bx11 = bx10;
}
bx00 = cx0;
bx10 = cx1;
}
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) l0, (__m128i*) h0);
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) l1, (__m128i*) h1);
cn_implode_scratchpad<ALGO, SOFT_AES>(reinterpret_cast<const __m128i *>(l0), reinterpret_cast<__m128i *>(h0));
cn_implode_scratchpad<ALGO, SOFT_AES>(reinterpret_cast<const __m128i *>(l1), reinterpret_cast<__m128i *>(h1));
xmrig::keccakf(h0, 24);
xmrig::keccakf(h1, 24);
keccakf(h0, 24);
keccakf(h1, 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
extra_hashes[ctx[1]->state[0] & 3](ctx[1]->state, 200, output + 32);
}
template<xmrig::Algo ALGO, bool SOFT_AES, xmrig::Variant VARIANT>
template<Algorithm::Id ALGO, bool SOFT_AES>
inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx, uint64_t height)
{
}
template<xmrig::Algo ALGO, bool SOFT_AES, xmrig::Variant VARIANT>
template<Algorithm::Id ALGO, bool SOFT_AES>
inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx, uint64_t height)
{
}
template<xmrig::Algo ALGO, bool SOFT_AES, xmrig::Variant VARIANT>
template<Algorithm::Id ALGO, bool SOFT_AES>
inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx, uint64_t height)
{
}
#endif /* __CRYPTONIGHT_ARM_H__ */
} /* namespace xmrig */
#endif /* XMRIG_CRYPTONIGHT_ARM_H */

View file

@ -1,254 +0,0 @@
/* 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-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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/>.
*/
#ifndef XMRIG_CRYPTONIGHT_CONSTANTS_H
#define XMRIG_CRYPTONIGHT_CONSTANTS_H
#include <stddef.h>
#include <stdint.h>
#include "common/xmrig.h"
namespace xmrig
{
constexpr const size_t CRYPTONIGHT_MEMORY = 2 * 1024 * 1024;
constexpr const uint32_t CRYPTONIGHT_MASK = 0x1FFFF0;
constexpr const uint32_t CRYPTONIGHT_ITER = 0x80000;
constexpr const uint32_t CRYPTONIGHT_HALF_ITER = 0x40000;
constexpr const uint32_t CRYPTONIGHT_XAO_ITER = 0x100000;
constexpr const uint32_t CRYPTONIGHT_DOUBLE_ITER = 0x100000;
constexpr const uint32_t CRYPTONIGHT_WALTZ_ITER = 0x60000;
constexpr const uint32_t CRYPTONIGHT_ZLS_ITER = 0x60000;
constexpr const uint32_t CRYPTONIGHT_GPU_ITER = 0xC000;
constexpr const uint32_t CRYPTONIGHT_GPU_MASK = 0x1FFFC0;
constexpr const size_t CRYPTONIGHT_LITE_MEMORY = 1 * 1024 * 1024;
constexpr const uint32_t CRYPTONIGHT_LITE_MASK = 0xFFFF0;
constexpr const uint32_t CRYPTONIGHT_LITE_ITER = 0x40000;
constexpr const size_t CRYPTONIGHT_HEAVY_MEMORY = 4 * 1024 * 1024;
constexpr const uint32_t CRYPTONIGHT_HEAVY_MASK = 0x3FFFF0;
constexpr const uint32_t CRYPTONIGHT_HEAVY_ITER = 0x40000;
constexpr const size_t CRYPTONIGHT_PICO_MEMORY = 256 * 1024;
constexpr const uint32_t CRYPTONIGHT_PICO_MASK = 0x1FFF0;
constexpr const uint32_t CRYPTONIGHT_PICO_ITER = 0x40000;
constexpr const uint32_t CRYPTONIGHT_TRTL_ITER = 0x10000;
template<Algo ALGO> inline constexpr size_t cn_select_memory() { return 0; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT>() { return CRYPTONIGHT_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_PICO>() { return CRYPTONIGHT_PICO_MEMORY; }
inline size_t cn_select_memory(Algo algorithm, Variant v = VARIANT_AUTO)
{
switch(algorithm)
{
case CRYPTONIGHT:
return CRYPTONIGHT_MEMORY;
case CRYPTONIGHT_LITE:
return CRYPTONIGHT_LITE_MEMORY;
case CRYPTONIGHT_HEAVY:
return CRYPTONIGHT_HEAVY_MEMORY;
case CRYPTONIGHT_PICO:
return CRYPTONIGHT_PICO_MEMORY;
case RANDOM_X:
return (v == VARIANT_RX_WOW) ? CRYPTONIGHT_LITE_MEMORY : CRYPTONIGHT_MEMORY;
default:
break;
}
return 0;
}
template<Algo ALGO> inline constexpr uint32_t cn_select_mask() { return 0; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT>() { return CRYPTONIGHT_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_PICO>() { return CRYPTONIGHT_PICO_MASK; }
inline uint32_t cn_select_mask(Algo algorithm)
{
switch(algorithm)
{
case CRYPTONIGHT:
return CRYPTONIGHT_MASK;
case CRYPTONIGHT_LITE:
return CRYPTONIGHT_LITE_MASK;
case CRYPTONIGHT_HEAVY:
return CRYPTONIGHT_HEAVY_MASK;
case CRYPTONIGHT_PICO:
return CRYPTONIGHT_PICO_MASK;
default:
break;
}
return 0;
}
template<Algo ALGO, Variant variant> inline constexpr uint32_t cn_select_iter() { return 0; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_0>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_1>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_2>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_WOW>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_4>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_XTL>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_HALF>() { return CRYPTONIGHT_HALF_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_MSR>() { return CRYPTONIGHT_HALF_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_XAO>() { return CRYPTONIGHT_XAO_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_RTO>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_GPU>() { return CRYPTONIGHT_GPU_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_RWZ>() { return CRYPTONIGHT_WALTZ_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_ZLS>() { return CRYPTONIGHT_ZLS_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_DOUBLE>() { return CRYPTONIGHT_DOUBLE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_LITE, VARIANT_0>() { return CRYPTONIGHT_LITE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_LITE, VARIANT_1>() { return CRYPTONIGHT_LITE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_0>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_XHV>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_TUBE>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_PICO, VARIANT_TRTL>() { return CRYPTONIGHT_TRTL_ITER; }
inline uint32_t cn_select_iter(Algo algorithm, Variant variant)
{
switch (variant) {
case VARIANT_MSR:
case VARIANT_HALF:
return CRYPTONIGHT_HALF_ITER;
case VARIANT_GPU:
return CRYPTONIGHT_GPU_ITER;
case VARIANT_RTO:
case VARIANT_DOUBLE:
return CRYPTONIGHT_XAO_ITER;
case VARIANT_TRTL:
return CRYPTONIGHT_TRTL_ITER;
case VARIANT_RWZ:
case VARIANT_ZLS:
return CRYPTONIGHT_WALTZ_ITER;
default:
break;
}
switch(algorithm)
{
case CRYPTONIGHT:
return CRYPTONIGHT_ITER;
case CRYPTONIGHT_LITE:
return CRYPTONIGHT_LITE_ITER;
case CRYPTONIGHT_HEAVY:
return CRYPTONIGHT_HEAVY_ITER;
case CRYPTONIGHT_PICO:
return CRYPTONIGHT_TRTL_ITER;
default:
break;
}
return 0;
}
template<Variant variant> inline constexpr Variant cn_base_variant() { return VARIANT_0; }
template<> inline constexpr Variant cn_base_variant<VARIANT_0>() { return VARIANT_0; }
template<> inline constexpr Variant cn_base_variant<VARIANT_1>() { return VARIANT_1; }
template<> inline constexpr Variant cn_base_variant<VARIANT_TUBE>() { return VARIANT_1; }
template<> inline constexpr Variant cn_base_variant<VARIANT_XTL>() { return VARIANT_1; }
template<> inline constexpr Variant cn_base_variant<VARIANT_MSR>() { return VARIANT_1; }
template<> inline constexpr Variant cn_base_variant<VARIANT_XHV>() { return VARIANT_0; }
template<> inline constexpr Variant cn_base_variant<VARIANT_XAO>() { return VARIANT_0; }
template<> inline constexpr Variant cn_base_variant<VARIANT_RTO>() { return VARIANT_1; }
template<> inline constexpr Variant cn_base_variant<VARIANT_2>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_HALF>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_TRTL>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_GPU>() { return VARIANT_GPU; }
template<> inline constexpr Variant cn_base_variant<VARIANT_WOW>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_4>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_RWZ>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_ZLS>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_DOUBLE>() { return VARIANT_2; }
inline Variant cn_base_variant(Variant variant)
{
switch (variant) {
case VARIANT_0:
case VARIANT_XHV:
case VARIANT_XAO:
return VARIANT_0;
case VARIANT_1:
case VARIANT_TUBE:
case VARIANT_XTL:
case VARIANT_MSR:
case VARIANT_RTO:
return VARIANT_1;
case VARIANT_GPU:
return VARIANT_GPU;
default:
break;
}
return VARIANT_2;
}
template<Variant variant> inline constexpr bool cn_is_cryptonight_r() { return false; }
template<> inline constexpr bool cn_is_cryptonight_r<VARIANT_WOW>() { return true; }
template<> inline constexpr bool cn_is_cryptonight_r<VARIANT_4>() { return true; }
} /* namespace xmrig */
#endif /* XMRIG_CRYPTONIGHT_CONSTANTS_H */

Some files were not shown because too many files have changed in this diff Show more