diff --git a/CHANGELOG.md b/CHANGELOG.md index 11b82cbf..25fc9ad2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v2.16.0-beta +- [#1036](https://github.com/xmrig/xmrig/pull/1036) Added RandomWOW (RandomX with different preferences) algorithm support for [Wownero](http://wownero.org/). + - Algorithm name used by miner is `randomx/wow` or `rx/wow`. + - Currently runtime algorithm switching NOT supported with other algorithms. + # v2.15.4-beta - Added global uptime and extended connection information in API. - API now return current algorithm instead of global algorithm specified in config. diff --git a/CMakeLists.txt b/CMakeLists.txt index 2dfd52e0..a402174a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ option(WITH_CN_LITE "CryptoNight-Lite support" ON) option(WITH_CN_HEAVY "CryptoNight-Heavy support" ON) option(WITH_CN_PICO "CryptoNight-Pico support" ON) option(WITH_CN_GPU "CryptoNight-GPU support" ON) +option(WITH_RANDOMX "RandomX support" ON) option(WITH_HTTP "HTTP protocol support (client/server)" ON) option(WITH_DEBUG_LOG "Enable debug log output" OFF) option(WITH_TLS "Enable OpenSSL support" ON) @@ -161,6 +162,17 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") find_package(UV REQUIRED) +if (WITH_RANDOMX) + find_package(RandomX REQUIRED) + include_directories(${RANDOMX_INCLUDE_DIR}) + + add_definitions(/DXMRIG_ALGO_RANDOMX) +else() + set(RANDOMX_LIBRARIES "") + + remove_definitions(/DXMRIG_ALGO_RANDOMX) +endif() + include(cmake/flags.cmake) if (WITH_LIBCPUID) @@ -231,4 +243,4 @@ if (WITH_DEBUG_LOG) endif() add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTP_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) -target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) +target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${RANDOMX_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) diff --git a/cmake/FindRandomX.cmake b/cmake/FindRandomX.cmake new file mode 100644 index 00000000..5696d563 --- /dev/null +++ b/cmake/FindRandomX.cmake @@ -0,0 +1,25 @@ +find_path( + RANDOMX_INCLUDE_DIR + NAMES randomx.h + PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS" + PATH_SUFFIXES "include" + NO_DEFAULT_PATH +) + +find_path(RANDOMX_INCLUDE_DIR NAMES randomx.h) + +find_library( + RANDOMX_LIBRARY + NAMES librandomx.a randomx librandomx + PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS" + PATH_SUFFIXES "lib" + NO_DEFAULT_PATH +) + +find_library(RANDOMX_LIBRARY NAMES librandomx.a randomx librandomx) + +set(RANDOMX_LIBRARIES ${RANDOMX_LIBRARY}) +set(RANDOMX_INCLUDE_DIRS ${RANDOMX_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(RANDOMX DEFAULT_MSG RANDOMX_LIBRARY RANDOMX_INCLUDE_DIR) diff --git a/src/Mem.cpp b/src/Mem.cpp index 574c5ff2..e8eabe3b 100644 --- a/src/Mem.cpp +++ b/src/Mem.cpp @@ -69,6 +69,10 @@ MemInfo Mem::create(cryptonight_ctx **ctx, const xmrig::Algorithm &algorithm, si void Mem::release(cryptonight_ctx **ctx, size_t count, MemInfo &info) { + if (info.memory == nullptr) { + return; + } + release(info); for (size_t i = 0; i < count; ++i) { diff --git a/src/Mem.h b/src/Mem.h index f43e005d..5c60d281 100644 --- a/src/Mem.h +++ b/src/Mem.h @@ -39,11 +39,11 @@ struct cryptonight_ctx; struct MemInfo { - alignas(16) uint8_t *memory; + alignas(16) uint8_t *memory = nullptr; - size_t hugePages; - size_t pages; - size_t size; + size_t hugePages = 0; + size_t pages = 0; + size_t size = 0; }; diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 4234407c..592fa7c3 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -37,6 +37,7 @@ #endif +#include "base/io/json/Json.h" #include "base/io/json/JsonRequest.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" @@ -333,13 +334,8 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) job.setAlgorithm(params["algo"].GetString()); } - if (params.HasMember("height")) { - const rapidjson::Value &variant = params["height"]; - - if (variant.IsUint64()) { - job.setHeight(variant.GetUint64()); - } - } + job.setSeedHash(Json::getString(params, "seed_hash")); + job.setHeight(Json::getUint64(params, "height")); if (!verifyAlgorithm(job.algorithm())) { *code = 6; diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 769e2116..70cc9151 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -220,6 +220,7 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) return false; } + job.setSeedHash(Json::getString(params, "seed_hash")); job.setHeight(Json::getUint64(params, kHeight)); job.setDiff(Json::getUint64(params, "difficulty")); job.setId(blocktemplate.data() + blocktemplate.size() - 32); diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 293d0f46..7e846b3b 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -40,7 +40,8 @@ xmrig::Job::Job() : m_diff(0), m_height(0), m_target(0), - m_blob() + m_blob(), + m_seedHash() { } @@ -54,7 +55,8 @@ xmrig::Job::Job(int poolId, bool nicehash, const Algorithm &algorithm, const Str m_diff(0), m_height(0), m_target(0), - m_blob() + m_blob(), + m_seedHash() { } @@ -103,6 +105,20 @@ bool xmrig::Job::setBlob(const char *blob) } +bool xmrig::Job::setSeedHash(const char *hash) +{ + if (!hash || (strlen(hash) != sizeof(m_seedHash) * 2)) { + return false; + } + +# ifdef XMRIG_PROXY_PROJECT + m_rawSeedHash = hash; +# endif + + return Buffer::fromHex(hash, sizeof(m_seedHash) * 2, m_seedHash); +} + + bool xmrig::Job::setTarget(const char *target) { if (!target) { diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 518a337e..c229f95c 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -52,6 +52,7 @@ public: bool isEqual(const Job &other) const; bool setBlob(const char *blob); + bool setSeedHash(const char *hash); bool setTarget(const char *target); void setDiff(uint64_t diff); @@ -63,6 +64,7 @@ public: inline const String &id() const { return m_id; } inline const uint32_t *nonce() const { return reinterpret_cast(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 size_t size() const { return m_size; } inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); } @@ -77,9 +79,10 @@ public: inline void setPoolId(int poolId) { m_poolId = poolId; } # ifdef XMRIG_PROXY_PROJECT - inline char *rawBlob() { return m_rawBlob; } - inline const char *rawBlob() const { return m_rawBlob; } - inline const char *rawTarget() const { return m_rawTarget; } + inline char *rawBlob() { return m_rawBlob; } + inline const char *rawBlob() const { return m_rawBlob; } + inline const char *rawTarget() const { return m_rawTarget; } + inline const String &rawSeedHash() const { return m_rawSeedHash; } # endif static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast(blob + 39); } @@ -99,10 +102,12 @@ private: uint64_t m_height; uint64_t m_target; uint8_t m_blob[kMaxBlobSize]; + uint8_t m_seedHash[32]; # ifdef XMRIG_PROXY_PROJECT char m_rawBlob[kMaxBlobSize * 2 + 8]; char m_rawTarget[24]; + String m_rawSeedHash; # endif }; diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index d82c3225..69ac065f 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -55,6 +55,12 @@ xmrig::Config::Config() : } +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)) { @@ -146,11 +152,10 @@ bool xmrig::Config::finalize() Algorithm algorithm(Algorithm::CN_0); // FIXME algo if (!m_threads.cpu.empty()) { - m_threads.mode = Advanced; - const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT; + m_threads.mode = Advanced; for (size_t i = 0; i < m_threads.cpu.size(); ++i) { - m_threads.list.push_back(CpuThread::createFromData(i, algorithm, m_threads.cpu[i], m_priority, softAES)); + m_threads.list.push_back(CpuThread::createFromData(i, algorithm, m_threads.cpu[i], m_priority, !isHwAES())); } return true; @@ -159,7 +164,7 @@ bool xmrig::Config::finalize() const AlgoVariant av = getAlgoVariant(); m_threads.mode = m_threads.count ? Simple : Automatic; - const size_t size = CpuThread::multiway(av) * CnAlgo<>::memory(algorithm) / 1024; + const size_t size = CpuThread::multiway(av) * CnAlgo<>::memory(algorithm) / 1024; // FIXME MEMORY if (!m_threads.count) { m_threads.count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage); diff --git a/src/core/config/Config.h b/src/core/config/Config.h index 637f80df..0ff13fe7 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -67,10 +67,10 @@ public: Config(); + bool isHwAES() const; bool read(const IJsonReader &reader, const char *fileName) override; void getJSON(rapidjson::Document &doc) const override; - inline AesMode aesMode() const { return m_aesMode; } inline AlgoVariant algoVariant() const { return m_algoVariant; } inline Assembly assembly() const { return m_assembly; } inline bool isHugePages() const { return m_hugePages; } diff --git a/src/crypto/cn/CnAlgo.h b/src/crypto/cn/CnAlgo.h index 74ade22b..6c64f92e 100644 --- a/src/crypto/cn/CnAlgo.h +++ b/src/crypto/cn/CnAlgo.h @@ -127,6 +127,7 @@ private: # endif # ifdef XMRIG_ALGO_CN_PICO CN_MEMORY / 8, // CN_PICO_0 + 0, // RX_WOW # endif }; @@ -156,7 +157,8 @@ private: CN_ITER / 2, // CN_HEAVY_XHV # endif # ifdef XMRIG_ALGO_CN_PICO - CN_ITER / 8, // CN_PICO_0 + CN_ITER / 8, // CN_PICO_0, + 0, // RX_WOW # endif }; @@ -186,7 +188,8 @@ private: Algorithm::CN_0, // CN_HEAVY_XHV # endif # ifdef XMRIG_ALGO_CN_PICO - Algorithm::CN_2, // CN_PICO_0 + Algorithm::CN_2, // CN_PICO_0, + Algorithm::INVALID, // RX_WOW # endif }; }; diff --git a/src/crypto/common/Algorithm.cpp b/src/crypto/common/Algorithm.cpp index b2f93896..e70b0659 100644 --- a/src/crypto/common/Algorithm.cpp +++ b/src/crypto/common/Algorithm.cpp @@ -106,6 +106,10 @@ static AlgoName const algorithm_names[] = { { "cryptonight-ultralite", "cn-ultralite", Algorithm::CN_PICO_0 }, { "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO_0 }, # endif +# ifdef XMRIG_ALGO_RANDOMX + { "randomx/wow", "rx/wow", Algorithm::RX_WOW }, + { "randomx", "rx", Algorithm::RX_WOW }, +# endif }; @@ -133,6 +137,7 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id) case CN_XAO: case CN_RTO: case CN_RWZ: + case CN_ZLS: case CN_DOUBLE: # ifdef XMRIG_ALGO_CN_GPU case CN_GPU: @@ -153,10 +158,15 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id) # endif # ifdef XMRIG_ALGO_CN_PICO - case Algorithm::CN_PICO_0: + case CN_PICO_0: return CN_PICO; # endif +# ifdef XMRIG_ALGO_RANDOMX + case RX_WOW: + return RANDOM_X; +# endif + default: break; } diff --git a/src/crypto/common/Algorithm.h b/src/crypto/common/Algorithm.h index 690814e7..ccaf7de5 100644 --- a/src/crypto/common/Algorithm.h +++ b/src/crypto/common/Algorithm.h @@ -67,6 +67,9 @@ public: # endif # ifdef XMRIG_ALGO_CN_PICO CN_PICO_0, // "cn-pico" CryptoNight Turtle (TRTL) +# endif +# ifdef XMRIG_ALGO_RANDOMX + RX_WOW, // "rx/wow" RandomWOW # endif MAX }; @@ -76,7 +79,8 @@ public: CN, CN_LITE, CN_HEAVY, - CN_PICO + CN_PICO, + RANDOM_X }; inline Algorithm() {} diff --git a/src/version.h b/src/version.h index 309f8873..7e849c7e 100644 --- a/src/version.h +++ b/src/version.h @@ -28,15 +28,15 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.99.0-evo" +#define APP_VERSION "2.16.1-evo" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_KIND "cpu" #define APP_VER_MAJOR 2 -#define APP_VER_MINOR 99 -#define APP_VER_PATCH 0 +#define APP_VER_MINOR 16 +#define APP_VER_PATCH 1 #ifdef _MSC_VER # if (_MSC_VER >= 1920) diff --git a/src/workers/MultiWorker.cpp b/src/workers/MultiWorker.cpp index ffa34dda..52e98e0a 100644 --- a/src/workers/MultiWorker.cpp +++ b/src/workers/MultiWorker.cpp @@ -37,7 +37,9 @@ template xmrig::MultiWorker::MultiWorker(ThreadHandle *handle) : Worker(handle) { - m_memory = Mem::create(m_ctx, m_thread->algorithm(), N); + if (m_thread->algorithm().family() != Algorithm::RANDOM_X) { + m_memory = Mem::create(m_ctx, m_thread->algorithm(), N); + } } @@ -45,9 +47,34 @@ template xmrig::MultiWorker::~MultiWorker() { Mem::release(m_ctx, N, m_memory); + +# ifdef XMRIG_ALGO_RANDOMX + if (m_rx_vm) { + randomx_destroy_vm(m_rx_vm); + } +# endif } +#ifdef XMRIG_ALGO_RANDOMX +template +void xmrig::MultiWorker::allocateRandomX_VM() +{ + if (!m_rx_vm) { + int flags = RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT; + if (!m_thread->isSoftAES()) { + flags |= RANDOMX_FLAG_HARD_AES; + } + + m_rx_vm = randomx_create_vm(static_cast(flags), nullptr, Workers::getDataset()); + if (!m_rx_vm) { + m_rx_vm = randomx_create_vm(static_cast(flags - RANDOMX_FLAG_LARGE_PAGES), nullptr, Workers::getDataset()); + } + } +} +#endif + + template bool xmrig::MultiWorker::selfTest() { @@ -97,6 +124,12 @@ bool xmrig::MultiWorker::selfTest() } # endif +# ifdef XMRIG_ALGO_RANDOMX + if (m_thread->algorithm().family() == Algorithm::RANDOM_X) { + return true; + } +# endif + return false; } @@ -123,7 +156,17 @@ void xmrig::MultiWorker::start() storeStats(); } - m_thread->fn(m_state.job.algorithm())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height()); +# ifdef XMRIG_ALGO_RANDOMX + if (m_state.job.algorithm().family() == Algorithm::RANDOM_X) { + allocateRandomX_VM(); + Workers::updateDataset(m_state.job.seedHash(), m_totalWays); + randomx_calculate_hash(m_rx_vm, m_state.blob, m_state.job.size(), m_hash); + } + else +# endif + { + m_thread->fn(m_state.job.algorithm())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height()); + } for (size_t i = 0; i < N; ++i) { if (*reinterpret_cast(m_hash + (i * 32) + 24) < m_state.job.target()) { diff --git a/src/workers/MultiWorker.h b/src/workers/MultiWorker.h index 82898e1e..d695e030 100644 --- a/src/workers/MultiWorker.h +++ b/src/workers/MultiWorker.h @@ -27,6 +27,11 @@ #define XMRIG_MULTIWORKER_H +#ifdef XMRIG_ALGO_RANDOMX +# include +#endif + + #include "base/net/stratum/Job.h" #include "Mem.h" #include "net/JobResult.h" @@ -48,6 +53,10 @@ protected: void start() override; private: +# ifdef XMRIG_ALGO_RANDOMX + void allocateRandomX_VM(); +# endif + bool resume(const Job &job); bool verify(const Algorithm &algorithm, const uint8_t *referenceValue); bool verify2(const Algorithm &algorithm, const uint8_t *referenceValue); @@ -70,6 +79,10 @@ private: State m_pausedState; State m_state; uint8_t m_hash[N * 32]; + +# ifdef XMRIG_ALGO_RANDOMX + randomx_vm *m_rx_vm = nullptr; +# endif }; diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 1955677b..8f68838f 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -59,6 +59,14 @@ uv_rwlock_t Workers::m_rwlock; uv_timer_t *Workers::m_timer = nullptr; xmrig::Controller *Workers::m_controller = nullptr; +#ifdef XMRIG_ALGO_RANDOMX +uv_rwlock_t Workers::m_rx_dataset_lock; +randomx_cache *Workers::m_rx_cache = nullptr; +randomx_dataset *Workers::m_rx_dataset = nullptr; +uint8_t Workers::m_rx_seed_hash[32] = {}; +std::atomic Workers::m_rx_dataset_init_thread_counter = {}; +#endif + xmrig::Job Workers::job() { @@ -183,6 +191,10 @@ void Workers::start(xmrig::Controller *controller) uv_mutex_init(&m_mutex); uv_rwlock_init(&m_rwlock); +# ifdef XMRIG_ALGO_RANDOMX + uv_rwlock_init(&m_rx_dataset_lock); +# endif + m_sequence = 1; m_paused = 1; @@ -341,13 +353,90 @@ void Workers::start(IWorker *worker) const double percent = (double) m_status.hugePages / m_status.pages * 100.0; const size_t memory = m_status.ways * xmrig::CnAlgo<>::memory(m_status.algo) / 1024; - LOG_INFO(GREEN_BOLD("READY (CPU)") " threads " CYAN_BOLD("%zu(%zu)") " huge pages %s%zu/%zu %1.0f%%\x1B[0m memory " CYAN_BOLD("%zu KB") "", - m_status.threads, m_status.ways, - (m_status.hugePages == m_status.pages ? GREEN_BOLD_S : (m_status.hugePages == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), - m_status.hugePages, m_status.pages, percent, memory); +# ifdef XMRIG_ALGO_RANDOMX + if (m_status.algo.family() == xmrig::Algorithm::RANDOM_X) { + LOG_INFO(GREEN_BOLD("READY (CPU)") " threads " CYAN_BOLD("%zu(%zu)") " memory " CYAN_BOLD("%zu KB") "", + m_status.threads, m_status.ways, memory); + } else +# endif + { + LOG_INFO(GREEN_BOLD("READY (CPU)") " threads " CYAN_BOLD("%zu(%zu)") " huge pages %s%zu/%zu %1.0f%%\x1B[0m memory " CYAN_BOLD("%zu KB") "", + m_status.threads, m_status.ways, + (m_status.hugePages == m_status.pages ? GREEN_BOLD_S : (m_status.hugePages == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), + m_status.hugePages, m_status.pages, percent, memory); + } } uv_mutex_unlock(&m_mutex); worker->start(); } + + +#ifdef XMRIG_ALGO_RANDOMX +void Workers::updateDataset(const uint8_t* seed_hash, const uint32_t num_threads) +{ + // Check if we need to update cache and dataset + if (memcmp(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)) == 0) + return; + + const uint32_t thread_id = m_rx_dataset_init_thread_counter++; + LOG_DEBUG("Thread %u started updating RandomX dataset", thread_id); + + // Wait for all threads to get here + do { + if (m_sequence.load(std::memory_order_relaxed) == 0) { + // Exit immediately if workers were stopped + return; + } + std::this_thread::yield(); + } while (m_rx_dataset_init_thread_counter.load() != num_threads); + + // One of the threads updates cache + uv_rwlock_wrlock(&m_rx_dataset_lock); + if (memcmp(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)) != 0) { + memcpy(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)); + randomx_init_cache(m_rx_cache, m_rx_seed_hash, sizeof(m_rx_seed_hash)); + } + uv_rwlock_wrunlock(&m_rx_dataset_lock); + + // All threads update dataset + const uint32_t a = (randomx_dataset_item_count() * thread_id) / num_threads; + const uint32_t b = (randomx_dataset_item_count() * (thread_id + 1)) / num_threads; + randomx_init_dataset(m_rx_dataset, m_rx_cache, a, b - a); + + LOG_DEBUG("Thread %u finished updating RandomX dataset", thread_id); + + // Wait for all threads to complete + --m_rx_dataset_init_thread_counter; + do { + if (m_sequence.load(std::memory_order_relaxed) == 0) { + // Exit immediately if workers were stopped + return; + } + std::this_thread::yield(); + } while (m_rx_dataset_init_thread_counter.load() != 0); +} + +randomx_dataset* Workers::getDataset() +{ + if (m_rx_dataset) + return m_rx_dataset; + + uv_rwlock_wrlock(&m_rx_dataset_lock); + if (!m_rx_dataset) { + randomx_dataset* dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES); + if (!dataset) { + dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT); + } + m_rx_cache = randomx_alloc_cache(static_cast(RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES)); + if (!m_rx_cache) { + m_rx_cache = randomx_alloc_cache(RANDOMX_FLAG_JIT); + } + m_rx_dataset = dataset; + } + uv_rwlock_wrunlock(&m_rx_dataset_lock); + + return m_rx_dataset; +} +#endif diff --git a/src/workers/Workers.h b/src/workers/Workers.h index 24480517..d0787c4f 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -31,6 +31,10 @@ #include #include +#ifdef XMRIG_ALGO_RANDOMX +# include +#endif + #include "base/net/stratum/Job.h" #include "net/JobResult.h" #include "rapidjson/fwd.h" @@ -72,6 +76,11 @@ public: static void threadsSummary(rapidjson::Document &doc); # endif +# ifdef XMRIG_ALGO_RANDOMX + static void updateDataset(const uint8_t* seed_hash, uint32_t num_threads); + static randomx_dataset* getDataset(); +# endif + private: static void onReady(void *arg); static void onResult(uv_async_t *handle); @@ -113,6 +122,14 @@ private: static uv_rwlock_t m_rwlock; static uv_timer_t *m_timer; static xmrig::Controller *m_controller; + +# ifdef XMRIG_ALGO_RANDOMX + static uv_rwlock_t m_rx_dataset_lock; + static randomx_cache *m_rx_cache; + static randomx_dataset *m_rx_dataset; + static uint8_t m_rx_seed_hash[32]; + static std::atomic m_rx_dataset_init_thread_counter; +# endif };