diff --git a/README.md b/README.md index 814f927b..6b7ce909 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ CPU backend: --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer --randomx-init=N threads count to initialize RandomX dataset --randomx-no-numa disable NUMA support for RandomX + --randomx-mode=MODE RandomX mode: auto, fast, light API: --api-worker-id=ID custom worker-id for API diff --git a/doc/build/CMAKE_OPTIONS.md b/doc/build/CMAKE_OPTIONS.md index 33a62bd2..654299de 100644 --- a/doc/build/CMAKE_OPTIONS.md +++ b/doc/build/CMAKE_OPTIONS.md @@ -1,5 +1,5 @@ # CMake options -This document contains list of useful cmake options. +**Recent version of this document: https://xmrig.com/docs/miner/cmake-options** ## Algorithms diff --git a/src/App.cpp b/src/App.cpp index 04b05451..1908482c 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -33,6 +33,7 @@ #include "base/io/Console.h" #include "base/io/log/Log.h" #include "base/kernel/Signals.h" +#include "base/kernel/Platform.h" #include "core/config/Config.h" #include "core/Controller.h" #include "core/Miner.h" @@ -89,6 +90,8 @@ int xmrig::App::exec() m_controller->start(); + Platform::setThreadPriority(5); + rc = uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_loop_close(uv_default_loop()); diff --git a/src/Summary.cpp b/src/Summary.cpp index 2055e972..757297c5 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -102,6 +102,23 @@ static void print_cpu(Config *) } +static void print_memory() +{ + constexpr size_t oneGiB = 1024U * 1024U * 1024U; + const auto freeMem = static_cast(uv_get_free_memory()); + const auto totalMem = static_cast(uv_get_total_memory()); + + const double percent = freeMem > 0 ? ((totalMem - freeMem) / totalMem * 100.0) : 100.0; + + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%.1f/%.1f GB") BLACK_BOLD(" (%.0f%%)"), + "MEMORY", + (totalMem - freeMem) / oneGiB, + totalMem / oneGiB, + percent + ); +} + + static void print_threads(Config *config) { Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s%d%%"), @@ -144,6 +161,7 @@ void xmrig::Summary::print(Controller *controller) controller->config()->printVersions(); print_memory(controller->config()); print_cpu(controller->config()); + print_memory(); print_threads(controller->config()); controller->config()->pools().print(); diff --git a/src/backend/common/Workers.cpp b/src/backend/common/Workers.cpp index 8e195b66..1efa6cbe 100644 --- a/src/backend/common/Workers.cpp +++ b/src/backend/common/Workers.cpp @@ -109,6 +109,11 @@ void xmrig::Workers::start(const std::vector &data) for (Thread *worker : m_workers) { worker->start(Workers::onReady); + + // This sleep is important for optimal caching! + // Threads must allocate scratchpads in order so that adjacent cores will use adjacent scratchpads + // Sub-optimal caching can result in up to 0.5% hashrate penalty + std::this_thread::sleep_for(std::chrono::milliseconds(20)); } } @@ -163,7 +168,7 @@ void xmrig::Workers::onReady(void *arg) assert(worker != nullptr); if (!worker || !worker->selfTest()) { - LOG_ERR("%s " RED("thread ") RED_BOLD("#%zu") RED(" self-test failed"), T::tag(), worker->id()); + LOG_ERR("%s " RED("thread ") RED_BOLD("#%zu") RED(" self-test failed"), T::tag(), worker ? worker->id() : 0); handle->backend()->start(worker, false); delete worker; diff --git a/src/backend/common/interfaces/IRxStorage.h b/src/backend/common/interfaces/IRxStorage.h index 49273ee3..9e0407b0 100644 --- a/src/backend/common/interfaces/IRxStorage.h +++ b/src/backend/common/interfaces/IRxStorage.h @@ -24,6 +24,9 @@ #define XMRIG_IRXSTORAGE_H +#include "crypto/rx/RxConfig.h" + + #include #include @@ -41,9 +44,9 @@ class IRxStorage public: virtual ~IRxStorage() = default; - virtual RxDataset *dataset(const Job &job, uint32_t nodeId) const = 0; - virtual std::pair hugePages() const = 0; - virtual void init(const RxSeed &seed, uint32_t threads, bool hugePages) = 0; + virtual RxDataset *dataset(const Job &job, uint32_t nodeId) const = 0; + virtual std::pair hugePages() const = 0; + virtual void init(const RxSeed &seed, uint32_t threads, bool hugePages, RxConfig::Mode mode) = 0; }; diff --git a/src/backend/cpu/CpuWorker.cpp b/src/backend/cpu/CpuWorker.cpp index f64882ba..7584b686 100644 --- a/src/backend/cpu/CpuWorker.cpp +++ b/src/backend/cpu/CpuWorker.cpp @@ -185,8 +185,20 @@ void xmrig::CpuWorker::start() consumeJob(); } + uint64_t storeStatsMask = 7; + +# ifdef XMRIG_ALGO_RANDOMX + bool first = true; + uint64_t tempHash[8] = {}; + + // RandomX is faster, we don't need to store stats so often + if (m_job.currentJob().algorithm().family() == Algorithm::RANDOM_X) { + storeStatsMask = 63; + } +# endif + while (!Nonce::isOutdated(Nonce::CPU, m_job.sequence())) { - if ((m_count & 0x7) == 0) { + if ((m_count & storeStatsMask) == 0) { storeStats(); } @@ -196,26 +208,34 @@ void xmrig::CpuWorker::start() break; } + uint32_t current_job_nonces[N]; + for (size_t i = 0; i < N; ++i) { + current_job_nonces[i] = *m_job.nonce(i); + } + # ifdef XMRIG_ALGO_RANDOMX if (job.algorithm().family() == Algorithm::RANDOM_X) { - randomx_calculate_hash(m_vm->get(), m_job.blob(), job.size(), m_hash); + if (first) { + first = false; + randomx_calculate_hash_first(m_vm->get(), tempHash, m_job.blob(), job.size()); + } + m_job.nextRound(kReserveCount, 1); + randomx_calculate_hash_next(m_vm->get(), tempHash, m_job.blob(), job.size(), m_hash); } else # endif { fn(job.algorithm())(m_job.blob(), job.size(), m_hash, m_ctx, job.height()); + m_job.nextRound(kReserveCount, 1); } for (size_t i = 0; i < N; ++i) { if (*reinterpret_cast(m_hash + (i * 32) + 24) < job.target()) { - JobResults::submit(job, *m_job.nonce(i), m_hash + (i * 32)); + JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32)); } } - m_job.nextRound(kReserveCount, 1); m_count += N; - - std::this_thread::yield(); } consumeJob(); diff --git a/src/backend/cuda/CudaBackend.cpp b/src/backend/cuda/CudaBackend.cpp index 8ba7ed5c..5bb1cbdd 100644 --- a/src/backend/cuda/CudaBackend.cpp +++ b/src/backend/cuda/CudaBackend.cpp @@ -64,7 +64,7 @@ namespace xmrig { extern template class Threads; -constexpr const size_t oneMiB = 1024u * 1024u; +constexpr const size_t oneMiB = 1024U * 1024U; static const char *kLabel = "CUDA"; static const char *tag = GREEN_BG_BOLD(WHITE_BOLD_S " nv "); static const String kType = "cuda"; @@ -249,7 +249,7 @@ public: std::string fans; if (!health.fanSpeed.empty()) { - for (uint32_t i = 0; i < health.fanSpeed.size(); ++i) { + for (size_t i = 0; i < health.fanSpeed.size(); ++i) { fans += " fan" + std::to_string(i) + ":" CYAN_BOLD_S + std::to_string(health.fanSpeed[i]) + "%" CLEAR; } } diff --git a/src/backend/opencl/OclBackend.cpp b/src/backend/opencl/OclBackend.cpp index bbf60443..af97b71e 100644 --- a/src/backend/opencl/OclBackend.cpp +++ b/src/backend/opencl/OclBackend.cpp @@ -58,7 +58,7 @@ namespace xmrig { extern template class Threads; -constexpr const size_t oneMiB = 1024u * 1024u; +constexpr const size_t oneMiB = 1024U * 1024U; static const char *tag = MAGENTA_BG_BOLD(WHITE_BOLD_S " ocl "); static const String kType = "opencl"; static std::mutex mutex; diff --git a/src/base/api/Api.cpp b/src/base/api/Api.cpp index 22f00b77..c66241c9 100644 --- a/src/base/api/Api.cpp +++ b/src/base/api/Api.cpp @@ -49,12 +49,48 @@ #endif +#include + + +namespace xmrig { + + +static rapidjson::Value getResources(rapidjson::Document &doc) +{ + using namespace rapidjson; + auto &allocator = doc.GetAllocator(); + + size_t rss = 0; + uv_resident_set_memory(&rss); + + Value out(kObjectType); + Value memory(kObjectType); + Value load_average(kArrayType); + + memory.AddMember("free", uv_get_free_memory(), allocator); + memory.AddMember("total", uv_get_total_memory(), allocator); + memory.AddMember("resident_set_memory", static_cast(rss), allocator); + + double loadavg[3] = { 0.0 }; + uv_loadavg(loadavg); + load_average.PushBack(loadavg[0], allocator); + load_average.PushBack(loadavg[1], allocator); + load_average.PushBack(loadavg[2], allocator); + + out.AddMember("memory", memory, allocator); + out.AddMember("load_average", load_average, allocator); + out.AddMember("hardware_concurrency", std::thread::hardware_concurrency(), allocator); + + return out; +} + + +} // namespace xmrig + + xmrig::Api::Api(Base *base) : m_base(base), - m_id(), - m_workerId(), - m_timestamp(Chrono::currentMSecsSinceEpoch()), - m_httpd(nullptr) + m_timestamp(Chrono::currentMSecsSinceEpoch()) { base->addListener(this); @@ -117,10 +153,13 @@ void xmrig::Api::exec(IApiRequest &request) 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::currentMSecsSinceEpoch() - m_timestamp) / 1000, allocator); - request.reply().AddMember("restricted", request.isRestricted(), allocator); + + auto &reply = request.reply(); + reply.AddMember("id", StringRef(m_id), allocator); + reply.AddMember("worker_id", StringRef(m_workerId), allocator); + reply.AddMember("uptime", (Chrono::currentMSecsSinceEpoch() - m_timestamp) / 1000, allocator); + reply.AddMember("restricted", request.isRestricted(), allocator); + reply.AddMember("resources", getResources(request.doc()), allocator); Value features(kArrayType); # ifdef XMRIG_FEATURE_API @@ -144,7 +183,7 @@ void xmrig::Api::exec(IApiRequest &request) # ifdef XMRIG_FEATURE_OPENCL features.PushBack("opencl", allocator); # endif - request.reply().AddMember("features", features, allocator); + reply.AddMember("features", features, allocator); } for (IApiListener *listener : m_listeners) { @@ -179,13 +218,13 @@ void xmrig::Api::genId(const String &id) if (!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) { uint8_t hash[200]; const size_t addrSize = sizeof(interfaces[i].phys_addr); - const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t); - const uint16_t port = static_cast(m_base->config()->http().port()); + const size_t inSize = (sizeof(APP_KIND) - 1) + addrSize + sizeof(uint16_t); + const auto port = static_cast(m_base->config()->http().port()); - uint8_t *input = new uint8_t[inSize](); + auto*input = new uint8_t[inSize](); memcpy(input, &port, sizeof(uint16_t)); memcpy(input + sizeof(uint16_t), interfaces[i].phys_addr, addrSize); - memcpy(input + sizeof(uint16_t) + addrSize, APP_KIND, strlen(APP_KIND)); + memcpy(input + sizeof(uint16_t) + addrSize, APP_KIND, (sizeof(APP_KIND) - 1)); keccak(input, inSize, hash); Buffer::toHex(hash, 8, m_id); diff --git a/src/base/api/Api.h b/src/base/api/Api.h index 0c1a728d..130ce78e 100644 --- a/src/base/api/Api.h +++ b/src/base/api/Api.h @@ -70,10 +70,10 @@ private: void genWorkerId(const String &id); Base *m_base; - char m_id[32]; - char m_workerId[128]; + char m_id[32]{}; + char m_workerId[128]{}; const uint64_t m_timestamp; - Httpd *m_httpd; + Httpd *m_httpd = nullptr; std::vector m_listeners; }; diff --git a/src/base/api/Httpd.cpp b/src/base/api/Httpd.cpp index e61e66f1..27e7dc44 100644 --- a/src/base/api/Httpd.cpp +++ b/src/base/api/Httpd.cpp @@ -23,9 +23,9 @@ */ +#include "base/api/Httpd.h" #include "3rdparty/http-parser/http_parser.h" #include "base/api/Api.h" -#include "base/api/Httpd.h" #include "base/io/log/Log.h" #include "base/net/http/HttpApiResponse.h" #include "base/net/http/HttpData.h" @@ -58,9 +58,7 @@ xmrig::Httpd::Httpd(Base *base) : } -xmrig::Httpd::~Httpd() -{ -} +xmrig::Httpd::~Httpd() = default; bool xmrig::Httpd::start() diff --git a/src/base/api/Httpd.h b/src/base/api/Httpd.h index 220bb7f5..ebfbcbf7 100644 --- a/src/base/api/Httpd.h +++ b/src/base/api/Httpd.h @@ -26,11 +26,12 @@ #define XMRIG_HTTPD_H -#include +#include #include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/IHttpListener.h" +#include "base/tools/Object.h" namespace xmrig { @@ -44,6 +45,8 @@ class TcpServer; class Httpd : public IBaseListener, public IHttpListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Httpd) + Httpd(Base *base); ~Httpd() override; diff --git a/src/base/api/requests/ApiRequest.cpp b/src/base/api/requests/ApiRequest.cpp index da73adee..4f0bd044 100644 --- a/src/base/api/requests/ApiRequest.cpp +++ b/src/base/api/requests/ApiRequest.cpp @@ -33,6 +33,4 @@ xmrig::ApiRequest::ApiRequest(Source source, bool restricted) : } -xmrig::ApiRequest::~ApiRequest() -{ -} +xmrig::ApiRequest::~ApiRequest() = default; diff --git a/src/base/api/requests/ApiRequest.h b/src/base/api/requests/ApiRequest.h index ad4b0c35..c87e822c 100644 --- a/src/base/api/requests/ApiRequest.h +++ b/src/base/api/requests/ApiRequest.h @@ -29,6 +29,7 @@ #include "base/api/interfaces/IApiRequest.h" #include "base/tools/String.h" +#include "base/tools/Object.h" namespace xmrig { @@ -37,6 +38,8 @@ namespace xmrig { class ApiRequest : public IApiRequest { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(ApiRequest) + ApiRequest(Source source, bool restricted); ~ApiRequest() override; @@ -63,8 +66,8 @@ protected: String m_rpcMethod; private: - bool m_restricted; - Source m_source; + const bool m_restricted; + const Source m_source; }; diff --git a/src/base/kernel/config/BaseConfig.cpp b/src/base/kernel/config/BaseConfig.cpp index 3da06b57..76056449 100644 --- a/src/base/kernel/config/BaseConfig.cpp +++ b/src/base/kernel/config/BaseConfig.cpp @@ -63,11 +63,6 @@ #include "version.h" -xmrig::BaseConfig::BaseConfig() -{ -} - - void xmrig::BaseConfig::printVersions() { char buf[256] = { 0 }; diff --git a/src/base/kernel/config/BaseConfig.h b/src/base/kernel/config/BaseConfig.h index 2e10c3ff..c700d109 100644 --- a/src/base/kernel/config/BaseConfig.h +++ b/src/base/kernel/config/BaseConfig.h @@ -31,9 +31,6 @@ #include "base/net/stratum/Pools.h" -struct option; - - namespace xmrig { @@ -43,7 +40,7 @@ class IJsonReader; class BaseConfig : public IConfig { public: - BaseConfig(); + BaseConfig() = default; inline bool isAutoSave() const { return m_autoSave; } inline bool isBackground() const { return m_background; } diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 7167e0bb..5044545a 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -89,6 +89,7 @@ public: AssemblyKey = 1015, RandomXInitKey = 1022, RandomXNumaKey = 1023, + RandomXModeKey = 1029, CPUMaxThreadsKey = 1026, MemoryPoolKey = 1027, @@ -125,6 +126,7 @@ public: TlsProtocolsKey = 1114, AlgoExtKey = 1115, ProxyPasswordKey = 1116, + LoginFileKey = 'L', // xmrig nvidia CudaMaxThreadsKey = 1200, diff --git a/src/base/kernel/interfaces/IStrategy.h b/src/base/kernel/interfaces/IStrategy.h index f2e58408..a0a24987 100644 --- a/src/base/kernel/interfaces/IStrategy.h +++ b/src/base/kernel/interfaces/IStrategy.h @@ -26,7 +26,7 @@ #define XMRIG_ISTRATEGY_H -#include +#include namespace xmrig { diff --git a/src/base/net/http/Http.cpp b/src/base/net/http/Http.cpp index 3c275824..c58080e6 100644 --- a/src/base/net/http/Http.cpp +++ b/src/base/net/http/Http.cpp @@ -23,9 +23,9 @@ */ +#include "base/net/http/Http.h" #include "3rdparty/rapidjson/document.h" #include "base/io/json/Json.h" -#include "base/net/http/Http.h" namespace xmrig { @@ -41,10 +41,7 @@ static const char *kToken = "access-token"; xmrig::Http::Http() : - m_enabled(false), - m_restricted(true), - m_host(kLocalhost), - m_port(0) + m_host(kLocalhost) { } diff --git a/src/base/net/http/Http.h b/src/base/net/http/Http.h index 21eb581a..0e8e4fbb 100644 --- a/src/base/net/http/Http.h +++ b/src/base/net/http/Http.h @@ -38,7 +38,7 @@ class Http public: Http(); - inline bool isAuthRequired() const { return m_restricted == false || !m_token.isNull(); } + inline bool isAuthRequired() const { return !m_restricted || !m_token.isNull(); } inline bool isEnabled() const { return m_enabled; } inline bool isRestricted() const { return m_restricted; } inline const String &host() const { return m_host; } @@ -58,11 +58,11 @@ public: void setPort(int port); private: - bool m_enabled; - bool m_restricted; + bool m_enabled = false; + bool m_restricted = true; String m_host; String m_token; - uint16_t m_port; + uint16_t m_port = 0; }; diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index 2699e663..9db1e809 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -66,7 +66,7 @@ public: inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast(req->data); } - uv_buf_t bufs[2]; + uv_buf_t bufs[2]{}; private: std::string m_body; diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index 1130d12c..af576257 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -24,27 +24,30 @@ */ +#include "base/net/http/HttpContext.h" +#include "3rdparty/http-parser/http_parser.h" +#include "base/kernel/interfaces/IHttpListener.h" +#include "base/tools/Chrono.h" + + #include #include -#include "3rdparty/http-parser/http_parser.h" -#include "base/kernel/interfaces/IHttpListener.h" -#include "base/net/http/HttpContext.h" - - namespace xmrig { + static http_parser_settings http_settings; static std::map storage; static uint64_t SEQUENCE = 0; + } // namespace xmrig xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) : HttpData(SEQUENCE++), - m_wasHeaderValue(false), + m_timestamp(Chrono::steadyMSecs()), m_listener(listener) { storage[id()] = this; @@ -96,6 +99,12 @@ std::string xmrig::HttpContext::ip() const } +uint64_t xmrig::HttpContext::elapsed() const +{ + return Chrono::steadyMSecs() - m_timestamp; +} + + void xmrig::HttpContext::close(int status) { if (status < 0 && m_listener) { diff --git a/src/base/net/http/HttpContext.h b/src/base/net/http/HttpContext.h index ba4418b6..9c304139 100644 --- a/src/base/net/http/HttpContext.h +++ b/src/base/net/http/HttpContext.h @@ -59,6 +59,7 @@ public: size_t parse(const char *data, size_t size); std::string ip() const; + uint64_t elapsed() const; void close(int status = 0); static HttpContext *get(uint64_t id); @@ -74,7 +75,8 @@ private: void setHeader(); - bool m_wasHeaderValue; + bool m_wasHeaderValue = false; + const uint64_t m_timestamp; http_parser *m_parser; IHttpListener *m_listener; std::string m_lastHeaderField; diff --git a/src/base/net/http/HttpData.h b/src/base/net/http/HttpData.h index ceb19b8e..1705e881 100644 --- a/src/base/net/http/HttpData.h +++ b/src/base/net/http/HttpData.h @@ -38,12 +38,12 @@ namespace xmrig { class HttpData { public: - inline HttpData(uint64_t id) : method(0), status(0), m_id(id) {} + inline HttpData(uint64_t id) : m_id(id) {} inline uint64_t id() const { return m_id; } - int method; - int status; + int method = 0; + int status = 0; std::map headers; std::string body; std::string url; diff --git a/src/base/net/http/HttpResponse.cpp b/src/base/net/http/HttpResponse.cpp index 7a4af838..ebd0bcf9 100644 --- a/src/base/net/http/HttpResponse.cpp +++ b/src/base/net/http/HttpResponse.cpp @@ -24,20 +24,23 @@ */ -#include -#include -#include - - +#include "base/net/http/HttpResponse.h" #include "3rdparty/http-parser/http_parser.h" #include "base/io/log/Log.h" #include "base/net/http/HttpContext.h" -#include "base/net/http/HttpResponse.h" #include "base/tools/Baton.h" +#include "base/tools/Object.h" + + +#include +#include +#include +#include namespace xmrig { + static const char *kCRLF = "\r\n"; static const char *kUserAgent = "user-agent"; @@ -45,6 +48,8 @@ static const char *kUserAgent = "user-agent"; class WriteBaton : public Baton { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(WriteBaton) + inline WriteBaton(const std::stringstream &ss, const char *data, size_t size, HttpContext *ctx) : m_ctx(ctx), m_header(ss.str()) @@ -79,7 +84,7 @@ public: inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast(req->data); } - uv_buf_t bufs[2]; + uv_buf_t bufs[2]{}; private: HttpContext *m_ctx; @@ -98,7 +103,7 @@ xmrig::HttpResponse::HttpResponse(uint64_t id, int statusCode) : bool xmrig::HttpResponse::isAlive() const { - HttpContext *ctx = HttpContext::get(m_id); + auto ctx = HttpContext::get(m_id); return ctx && uv_is_writable(ctx->stream()); } @@ -129,8 +134,8 @@ void xmrig::HttpResponse::end(const char *data, size_t size) ss << kCRLF; - HttpContext *ctx = HttpContext::get(m_id); - WriteBaton *baton = new WriteBaton(ss, data, size, ctx); + auto ctx = HttpContext::get(m_id); + auto baton = new WriteBaton(ss, data, size, ctx); # ifndef APP_DEBUG if (statusCode() >= 400) @@ -138,13 +143,14 @@ void xmrig::HttpResponse::end(const char *data, size_t size) { const bool err = statusCode() >= 400; - Log::print(err ? Log::ERR : Log::INFO, CYAN("%s ") CLEAR MAGENTA_BOLD("%s") WHITE_BOLD(" %s ") CSI "1;%dm%d " CLEAR WHITE_BOLD("%zu ") BLACK_BOLD("\"%s\""), + Log::print(err ? Log::ERR : Log::INFO, CYAN("%s ") CLEAR MAGENTA_BOLD("%s") WHITE_BOLD(" %s ") CSI "1;%dm%d " CLEAR WHITE_BOLD("%zu ") CYAN_BOLD("%" PRIu64 "ms ") BLACK_BOLD("\"%s\""), ctx->ip().c_str(), http_method_str(static_cast(ctx->method)), ctx->url.c_str(), err ? 31 : 32, statusCode(), baton->size(), + ctx->elapsed(), ctx->headers.count(kUserAgent) ? ctx->headers.at(kUserAgent).c_str() : nullptr ); } diff --git a/src/base/net/http/HttpServer.cpp b/src/base/net/http/HttpServer.cpp index 60db31f6..5aae1b6f 100644 --- a/src/base/net/http/HttpServer.cpp +++ b/src/base/net/http/HttpServer.cpp @@ -49,7 +49,7 @@ xmrig::HttpServer::~HttpServer() void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) { - HttpContext *ctx = new HttpContext(HTTP_REQUEST, m_listener); + auto ctx = new HttpContext(HTTP_REQUEST, m_listener); uv_accept(stream, ctx->stream()); uv_read_start(ctx->stream(), @@ -65,11 +65,11 @@ void xmrig::HttpServer::onConnection(uv_stream_t *stream, uint16_t) }, [](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) { - HttpContext *ctx = static_cast(tcp->data); + auto ctx = static_cast(tcp->data); if (nread >= 0) { - const size_t size = static_cast(nread); - const size_t parsed = ctx->parse(buf->base, size); + const auto size = static_cast(nread); + const auto parsed = ctx->parse(buf->base, size); if (parsed < size) { ctx->close(); diff --git a/src/base/net/http/HttpServer.h b/src/base/net/http/HttpServer.h index 45f3843d..74e846b9 100644 --- a/src/base/net/http/HttpServer.h +++ b/src/base/net/http/HttpServer.h @@ -28,11 +28,12 @@ #define XMRIG_HTTPSERVER_H -typedef struct http_parser http_parser; -typedef struct http_parser_settings http_parser_settings; +using http_parser = struct http_parser; +using http_parser_settings = struct http_parser_settings; #include "base/kernel/interfaces/ITcpServerListener.h" +#include "base/tools/Object.h" namespace xmrig { @@ -44,6 +45,8 @@ class IHttpListener; class HttpServer : public ITcpServerListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(HttpServer) + HttpServer(IHttpListener *listener); ~HttpServer() override; diff --git a/src/base/net/stratum/SelfSelectClient.h b/src/base/net/stratum/SelfSelectClient.h index c48c5078..44b07212 100644 --- a/src/base/net/stratum/SelfSelectClient.h +++ b/src/base/net/stratum/SelfSelectClient.h @@ -54,7 +54,7 @@ protected: inline const char *mode() const override { return m_client->mode(); } inline const char *tlsFingerprint() const override { return m_client->tlsFingerprint(); } inline const char *tlsVersion() const override { return m_client->tlsVersion(); } - inline const Job &job() const override { return m_client->job(); } + inline const Job &job() const override { return m_job; } inline const Pool &pool() const override { return m_client->pool(); } inline const String &ip() const override { return m_client->ip(); } inline int id() const override { return m_client->id(); } diff --git a/src/base/tools/Arguments.cpp b/src/base/tools/Arguments.cpp index 3713dd11..933173aa 100644 --- a/src/base/tools/Arguments.cpp +++ b/src/base/tools/Arguments.cpp @@ -60,17 +60,17 @@ void xmrig::Arguments::add(const char *arg) const size_t size = strlen(arg); if (size > 4 && arg[0] == '-' && arg[1] == '-') { - const char *p = strstr(arg, "="); + const char *p = strchr(arg, '='); if (p) { - const size_t keySize = static_cast(p - arg); + const auto keySize = static_cast(p - arg); - m_data.push_back(String(arg, keySize)); - m_data.push_back(arg + keySize + 1); + m_data.emplace_back(arg, keySize); + m_data.emplace_back(arg + keySize + 1); return; } } - m_data.push_back(arg); + m_data.emplace_back(arg); } diff --git a/src/base/tools/Buffer.cpp b/src/base/tools/Buffer.cpp index c12e601d..982f9d36 100644 --- a/src/base/tools/Buffer.cpp +++ b/src/base/tools/Buffer.cpp @@ -31,10 +31,12 @@ static inline uint8_t hf_hex2bin(uint8_t c, bool &err) if (c >= '0' && c <= '9') { return c - '0'; } - else if (c >= 'a' && c <= 'f') { + + if (c >= 'a' && c <= 'f') { return c - 'a' + 0xA; } - else if (c >= 'A' && c <= 'F') { + + if (c >= 'A' && c <= 'F') { return c - 'A' + 0xA; } @@ -77,7 +79,9 @@ xmrig::Buffer::Buffer(const char *data, size_t size) xmrig::Buffer::Buffer(size_t size) : m_size(size) { - m_data = new char[size](); + if (size > 0) { + m_data = new char[size](); + } } @@ -105,6 +109,10 @@ void xmrig::Buffer::from(const char *data, size_t size) xmrig::Buffer xmrig::Buffer::allocUnsafe(size_t size) { + if (size == 0) { + return {}; + } + Buffer buf; buf.m_size = size; buf.m_data = new char[size]; @@ -169,6 +177,13 @@ xmrig::String xmrig::Buffer::toHex() const void xmrig::Buffer::copy(const char *data, size_t size) { + if (size == 0) { + m_data = nullptr; + m_size = 0; + + return; + } + m_data = new char[size]; m_size = size; diff --git a/src/config.json b/src/config.json index fbc60474..fbbf8225 100644 --- a/src/config.json +++ b/src/config.json @@ -16,6 +16,7 @@ "colors": true, "randomx": { "init": -1, + "mode": "auto", "numa": true }, "cpu": { diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index d0264258..667d9117 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -160,6 +160,9 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const case IConfig::RandomXNumaKey: /* --randomx-no-numa */ return set(doc, kRandomX, "numa", false); + + case IConfig::RandomXModeKey: /* --randomx-mode */ + return set(doc, kRandomX, "mode", arg); # endif # ifdef XMRIG_FEATURE_OPENCL diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index 80fcf87f..608ac48e 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -96,6 +96,7 @@ static const option options[] = { # ifdef XMRIG_ALGO_RANDOMX { "randomx-init", 1, nullptr, IConfig::RandomXInitKey }, { "randomx-no-numa", 0, nullptr, IConfig::RandomXNumaKey }, + { "randomx-mode", 1, nullptr, IConfig::RandomXModeKey }, # endif # ifdef XMRIG_FEATURE_OPENCL { "opencl", 0, nullptr, IConfig::OclKey }, diff --git a/src/core/config/usage.h b/src/core/config/usage.h index 48b34b81..dcae30f4 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -86,6 +86,7 @@ static inline const std::string &usage() # ifdef XMRIG_ALGO_RANDOMX u += " --randomx-init=N threads count to initialize RandomX dataset\n"; u += " --randomx-no-numa disable NUMA support for RandomX\n"; + u += " --randomx-mode=MODE RandomX mode: auto, fast, light\n"; # endif # ifdef XMRIG_FEATURE_HTTP diff --git a/src/crypto/randomx/aes_hash.cpp b/src/crypto/randomx/aes_hash.cpp index fe149dfe..4a400d0a 100644 --- a/src/crypto/randomx/aes_hash.cpp +++ b/src/crypto/randomx/aes_hash.cpp @@ -212,3 +212,84 @@ void fillAes4Rx4(void *state, size_t outputSize, void *buffer) { template void fillAes4Rx4(void *state, size_t outputSize, void *buffer); template void fillAes4Rx4(void *state, size_t outputSize, void *buffer); + +template +void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state) { + uint8_t* scratchpadPtr = (uint8_t*)scratchpad; + const uint8_t* scratchpadEnd = scratchpadPtr + scratchpadSize; + + // initial state + rx_vec_i128 hash_state0 = rx_set_int_vec_i128(AES_HASH_1R_STATE0); + rx_vec_i128 hash_state1 = rx_set_int_vec_i128(AES_HASH_1R_STATE1); + rx_vec_i128 hash_state2 = rx_set_int_vec_i128(AES_HASH_1R_STATE2); + rx_vec_i128 hash_state3 = rx_set_int_vec_i128(AES_HASH_1R_STATE3); + + const rx_vec_i128 key0 = rx_set_int_vec_i128(AES_GEN_1R_KEY0); + const rx_vec_i128 key1 = rx_set_int_vec_i128(AES_GEN_1R_KEY1); + const rx_vec_i128 key2 = rx_set_int_vec_i128(AES_GEN_1R_KEY2); + const rx_vec_i128 key3 = rx_set_int_vec_i128(AES_GEN_1R_KEY3); + + rx_vec_i128 fill_state0 = rx_load_vec_i128((rx_vec_i128*)fill_state + 0); + rx_vec_i128 fill_state1 = rx_load_vec_i128((rx_vec_i128*)fill_state + 1); + rx_vec_i128 fill_state2 = rx_load_vec_i128((rx_vec_i128*)fill_state + 2); + rx_vec_i128 fill_state3 = rx_load_vec_i128((rx_vec_i128*)fill_state + 3); + + constexpr int PREFETCH_DISTANCE = 4096; + const char* prefetchPtr = ((const char*)scratchpad) + PREFETCH_DISTANCE; + scratchpadEnd -= PREFETCH_DISTANCE; + + for (int i = 0; i < 2; ++i) { + //process 64 bytes at a time in 4 lanes + while (scratchpadPtr < scratchpadEnd) { + hash_state0 = aesenc(hash_state0, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 0)); + hash_state1 = aesdec(hash_state1, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 1)); + hash_state2 = aesenc(hash_state2, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 2)); + hash_state3 = aesdec(hash_state3, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 3)); + + fill_state0 = aesdec(fill_state0, key0); + fill_state1 = aesenc(fill_state1, key1); + fill_state2 = aesdec(fill_state2, key2); + fill_state3 = aesenc(fill_state3, key3); + + rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 0, fill_state0); + rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 1, fill_state1); + rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 2, fill_state2); + rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 3, fill_state3); + + rx_prefetch_t0(prefetchPtr); + + scratchpadPtr += 64; + prefetchPtr += 64; + } + prefetchPtr = (const char*) scratchpad; + scratchpadEnd += PREFETCH_DISTANCE; + } + + rx_store_vec_i128((rx_vec_i128*)fill_state + 0, fill_state0); + rx_store_vec_i128((rx_vec_i128*)fill_state + 1, fill_state1); + rx_store_vec_i128((rx_vec_i128*)fill_state + 2, fill_state2); + rx_store_vec_i128((rx_vec_i128*)fill_state + 3, fill_state3); + + //two extra rounds to achieve full diffusion + rx_vec_i128 xkey0 = rx_set_int_vec_i128(AES_HASH_1R_XKEY0); + rx_vec_i128 xkey1 = rx_set_int_vec_i128(AES_HASH_1R_XKEY1); + + hash_state0 = aesenc(hash_state0, xkey0); + hash_state1 = aesdec(hash_state1, xkey0); + hash_state2 = aesenc(hash_state2, xkey0); + hash_state3 = aesdec(hash_state3, xkey0); + + hash_state0 = aesenc(hash_state0, xkey1); + hash_state1 = aesdec(hash_state1, xkey1); + hash_state2 = aesenc(hash_state2, xkey1); + hash_state3 = aesdec(hash_state3, xkey1); + + //output hash + rx_store_vec_i128((rx_vec_i128*)hash + 0, hash_state0); + rx_store_vec_i128((rx_vec_i128*)hash + 1, hash_state1); + rx_store_vec_i128((rx_vec_i128*)hash + 2, hash_state2); + rx_store_vec_i128((rx_vec_i128*)hash + 3, hash_state3); +} + +template void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state); +template void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state); diff --git a/src/crypto/randomx/aes_hash.hpp b/src/crypto/randomx/aes_hash.hpp index b4d0e940..9f75f73a 100644 --- a/src/crypto/randomx/aes_hash.hpp +++ b/src/crypto/randomx/aes_hash.hpp @@ -38,3 +38,6 @@ void fillAes1Rx4(void *state, size_t outputSize, void *buffer); template void fillAes4Rx4(void *state, size_t outputSize, void *buffer); + +template +void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state); diff --git a/src/crypto/randomx/intrin_portable.h b/src/crypto/randomx/intrin_portable.h index 346c433a..1dcd3ad3 100644 --- a/src/crypto/randomx/intrin_portable.h +++ b/src/crypto/randomx/intrin_portable.h @@ -102,6 +102,7 @@ typedef __m128d rx_vec_f128; #define rx_aligned_alloc(a, b) _mm_malloc(a,b) #define rx_aligned_free(a) _mm_free(a) #define rx_prefetch_nta(x) _mm_prefetch((const char *)(x), _MM_HINT_NTA) +#define rx_prefetch_t0(x) _mm_prefetch((const char *)(x), _MM_HINT_T0) #define rx_load_vec_f128 _mm_load_pd #define rx_store_vec_f128 _mm_store_pd @@ -201,6 +202,7 @@ typedef union{ #define rx_aligned_alloc(a, b) malloc(a) #define rx_aligned_free(a) free(a) #define rx_prefetch_nta(x) +#define rx_prefetch_t0(x) /* Splat 64-bit long long to 2 64-bit long longs */ FORCE_INLINE __m128i vec_splat2sd (int64_t scalar) @@ -399,6 +401,10 @@ inline void rx_prefetch_nta(void* ptr) { asm volatile ("prfm pldl1strm, [%0]\n" : : "r" (ptr)); } +inline void rx_prefetch_t0(const void* ptr) { + asm volatile ("prfm pldl1strm, [%0]\n" : : "r" (ptr)); +} + FORCE_INLINE rx_vec_f128 rx_load_vec_f128(const double* pd) { return vld1q_f64((const float64_t*)pd); } @@ -532,6 +538,7 @@ typedef union { #define rx_aligned_alloc(a, b) malloc(a) #define rx_aligned_free(a) free(a) #define rx_prefetch_nta(x) +#define rx_prefetch_t0(x) FORCE_INLINE rx_vec_f128 rx_load_vec_f128(const double* pd) { rx_vec_f128 x; diff --git a/src/crypto/randomx/jit_compiler_x86.cpp b/src/crypto/randomx/jit_compiler_x86.cpp index 2a342535..bfde7d00 100644 --- a/src/crypto/randomx/jit_compiler_x86.cpp +++ b/src/crypto/randomx/jit_compiler_x86.cpp @@ -29,6 +29,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "crypto/randomx/jit_compiler_x86.hpp" #include "crypto/randomx/jit_compiler_x86_static.hpp" #include "crypto/randomx/superscalar.hpp" @@ -36,6 +37,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "crypto/randomx/reciprocal.h" #include "crypto/randomx/virtual_memory.hpp" +#ifdef _MSC_VER +# include +#else +# include +#endif + namespace randomx { /* @@ -108,7 +115,7 @@ namespace randomx { const int32_t codeSshPrefetchSize = codeShhEnd - codeShhPrefetch; const int32_t codeSshInitSize = codeProgramEnd - codeShhInit; - const int32_t epilogueOffset = CodeSize - epilogueSize; + const int32_t epilogueOffset = (CodeSize - epilogueSize) & ~63; constexpr int32_t superScalarHashOffset = 32768; static const uint8_t REX_ADD_RR[] = { 0x4d, 0x03 }; @@ -183,6 +190,7 @@ namespace randomx { static const uint8_t REX_ADD_I[] = { 0x49, 0x81 }; static const uint8_t REX_TEST[] = { 0x49, 0xF7 }; static const uint8_t JZ[] = { 0x0f, 0x84 }; + static const uint8_t JZ_SHORT = 0x74; static const uint8_t RET = 0xc3; static const uint8_t LEA_32[] = { 0x41, 0x8d }; static const uint8_t MOVNTI[] = { 0x4c, 0x0f, 0xc3 }; @@ -197,20 +205,100 @@ namespace randomx { static const uint8_t NOP7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t NOP8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; -// static const uint8_t* NOPX[] = { NOP1, NOP2, NOP3, NOP4, NOP5, NOP6, NOP7, NOP8 }; + static const uint8_t* NOPX[] = { NOP1, NOP2, NOP3, NOP4, NOP5, NOP6, NOP7, NOP8 }; + + static const uint8_t JMP_ALIGN_PREFIX[14][16] = { + {}, + {0x2E}, + {0x2E, 0x2E}, + {0x2E, 0x2E, 0x2E}, + {0x2E, 0x2E, 0x2E, 0x2E}, + {0x2E, 0x2E, 0x2E, 0x2E, 0x2E}, + {0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E}, + {0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E}, + {0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E}, + {0x90, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E}, + {0x66, 0x90, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E}, + {0x66, 0x66, 0x90, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E}, + {0x0F, 0x1F, 0x40, 0x00, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E}, + {0x0F, 0x1F, 0x44, 0x00, 0x00, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E}, + }; + + bool JitCompilerX86::BranchesWithin32B = false; size_t JitCompilerX86::getCodeSize() { return codePos < prologueSize ? 0 : codePos - prologueSize; } + static inline void cpuid(uint32_t level, int32_t output[4]) + { + memset(output, 0, sizeof(int32_t) * 4); + +# ifdef _MSC_VER + __cpuid(output, static_cast(level)); +# else + __cpuid_count(level, 0, output[0], output[1], output[2], output[3]); +# endif + } + + // CPU-specific tweaks + void JitCompilerX86::applyTweaks() { + int32_t info[4]; + cpuid(0, info); + + int32_t manufacturer[4]; + manufacturer[0] = info[1]; + manufacturer[1] = info[3]; + manufacturer[2] = info[2]; + manufacturer[3] = 0; + + if (strcmp((const char*)manufacturer, "GenuineIntel") == 0) { + struct + { + unsigned int stepping : 4; + unsigned int model : 4; + unsigned int family : 4; + unsigned int processor_type : 2; + unsigned int reserved1 : 2; + unsigned int ext_model : 4; + unsigned int ext_family : 8; + unsigned int reserved2 : 4; + } processor_info; + + cpuid(1, info); + memcpy(&processor_info, info, sizeof(processor_info)); + + // Intel JCC erratum mitigation + if (processor_info.family == 6) { + const uint32_t model = processor_info.model | (processor_info.ext_model << 4); + const uint32_t stepping = processor_info.stepping; + + // Affected CPU models and stepping numbers are taken from https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf + BranchesWithin32B = + ((model == 0x4E) && (stepping == 0x3)) || + ((model == 0x55) && (stepping == 0x4)) || + ((model == 0x5E) && (stepping == 0x3)) || + ((model == 0x8E) && (stepping >= 0x9) && (stepping <= 0xC)) || + ((model == 0x9E) && (stepping >= 0x9) && (stepping <= 0xD)) || + ((model == 0xA6) && (stepping == 0x0)) || + ((model == 0xAE) && (stepping == 0xA)); + } + } + } + + static std::atomic codeOffset; + JitCompilerX86::JitCompilerX86() { - code = (uint8_t*)allocExecutableMemory(CodeSize); + applyTweaks(); + allocatedCode = (uint8_t*)allocExecutableMemory(CodeSize * 2); + // Shift code base address to improve caching - all threads will use different L2/L3 cache sets + code = allocatedCode + (codeOffset.fetch_add(59 * 64) % CodeSize); memcpy(code, codePrologue, prologueSize); memcpy(code + epilogueOffset, codeEpilogue, epilogueSize); } JitCompilerX86::~JitCompilerX86() { - freePagedMemory(code, CodeSize); + freePagedMemory(allocatedCode, CodeSize); } void JitCompilerX86::generateProgram(Program& prog, ProgramConfiguration& pcfg) { @@ -307,6 +395,22 @@ namespace randomx { emit(RandomX_CurrentConfig.codePrefetchScratchpadTweaked, prefetchScratchpadSize, code, codePos); memcpy(code + codePos, codeLoopStore, loopStoreSize); codePos += loopStoreSize; + + if (BranchesWithin32B) { + const uint32_t branch_begin = static_cast(codePos); + const uint32_t branch_end = static_cast(branch_begin + 9); + + // If the jump crosses or touches 32-byte boundary, align it + if ((branch_begin ^ branch_end) >= 32) { + uint32_t alignment_size = 32 - (branch_begin & 31); + if (alignment_size > 8) { + emit(NOPX[alignment_size - 9], alignment_size - 8, code, codePos); + alignment_size = 8; + } + emit(NOPX[alignment_size - 1], alignment_size, code, codePos); + } + } + emit(SUB_EBX, code, codePos); emit(JNZ, code, codePos); emit32(prologueSize - codePos - 4, code, codePos); @@ -408,12 +512,13 @@ namespace randomx { } } - void JitCompilerX86::genAddressReg(const Instruction& instr, uint8_t* code, int& codePos, bool rax) { - emit(LEA_32, code, codePos); - emitByte(0x80 + instr.src + (rax ? 0 : 8), code, codePos); - if (instr.src == RegisterNeedsSib) { - emitByte(0x24, code, codePos); - } + template + FORCE_INLINE void JitCompilerX86::genAddressReg(const Instruction& instr, uint8_t* code, int& codePos) { + const uint32_t src = *((uint32_t*)&instr) & 0xFF0000; + + *(uint32_t*)(code + codePos) = (rax ? 0x24808d41 : 0x24888d41) + src; + codePos += (src == (RegisterNeedsSib << 16)) ? 4 : 3; + emit32(instr.getImm32(), code, codePos); if (rax) emitByte(AND_EAX_I, code, codePos); @@ -422,12 +527,14 @@ namespace randomx { emit32(instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask, code, codePos); } - void JitCompilerX86::genAddressRegDst(const Instruction& instr, uint8_t* code, int& codePos) { - emit(LEA_32, code, codePos); - emitByte(0x80 + instr.dst, code, codePos); - if (instr.dst == RegisterNeedsSib) { - emitByte(0x24, code, codePos); - } + template void JitCompilerX86::genAddressReg(const Instruction& instr, uint8_t* code, int& codePos); + template void JitCompilerX86::genAddressReg(const Instruction& instr, uint8_t* code, int& codePos); + + FORCE_INLINE void JitCompilerX86::genAddressRegDst(const Instruction& instr, uint8_t* code, int& codePos) { + const uint32_t dst = static_cast(instr.dst) << 16; + *(uint32_t*)(code + codePos) = 0x24808d41 + dst; + codePos += (dst == (RegisterNeedsSib << 16)) ? 4 : 3; + emit32(instr.getImm32(), code, codePos); emitByte(AND_EAX_I, code, codePos); if (instr.getModCond() < StoreL3Condition) { @@ -438,7 +545,7 @@ namespace randomx { } } - void JitCompilerX86::genAddressImm(const Instruction& instr, uint8_t* code, int& codePos) { + FORCE_INLINE void JitCompilerX86::genAddressImm(const Instruction& instr, uint8_t* code, int& codePos) { emit32(instr.getImm32() & ScratchpadL3Mask, code, codePos); } @@ -483,7 +590,7 @@ namespace randomx { int pos = codePos; if (instr.src != instr.dst) { - genAddressReg(instr, p, pos); + genAddressReg(instr, p, pos); emit32(template_IADD_M[instr.dst], p, pos); } else { @@ -523,7 +630,7 @@ namespace randomx { int pos = codePos; if (instr.src != instr.dst) { - genAddressReg(instr, p, pos); + genAddressReg(instr, p, pos); emit(REX_SUB_RM, p, pos); emitByte(0x04 + 8 * instr.dst, p, pos); emitByte(0x06, p, pos); @@ -561,7 +668,7 @@ namespace randomx { int pos = codePos; if (instr.src != instr.dst) { - genAddressReg(instr, p, pos); + genAddressReg(instr, p, pos); emit(REX_IMUL_RM, p, pos); emitByte(0x04 + 8 * instr.dst, p, pos); emitByte(0x06, p, pos); @@ -596,7 +703,7 @@ namespace randomx { int pos = codePos; if (instr.src != instr.dst) { - genAddressReg(instr, p, pos, false); + genAddressReg(instr, p, pos); emit(REX_MOV_RR64, p, pos); emitByte(0xc0 + instr.dst, p, pos); emit(REX_MUL_MEM, p, pos); @@ -635,7 +742,7 @@ namespace randomx { int pos = codePos; if (instr.src != instr.dst) { - genAddressReg(instr, p, pos, false); + genAddressReg(instr, p, pos); emit(REX_MOV_RR64, p, pos); emitByte(0xc0 + instr.dst, p, pos); emit(REX_IMUL_MEM, p, pos); @@ -704,7 +811,7 @@ namespace randomx { int pos = codePos; if (instr.src != instr.dst) { - genAddressReg(instr, p, pos); + genAddressReg(instr, p, pos); emit(REX_XOR_RM, p, pos); emitByte(0x04 + 8 * instr.dst, p, pos); emitByte(0x06, p, pos); @@ -801,7 +908,7 @@ namespace randomx { int pos = codePos; const uint32_t dst = instr.dst % RegisterCountFlt; - genAddressReg(instr, p, pos); + genAddressReg(instr, p, pos); emit(REX_CVTDQ2PD_XMM12, p, pos); emit(REX_ADDPD, p, pos); emitByte(0xc4 + 8 * dst, p, pos); @@ -826,7 +933,7 @@ namespace randomx { int pos = codePos; const uint32_t dst = instr.dst % RegisterCountFlt; - genAddressReg(instr, p, pos); + genAddressReg(instr, p, pos); emit(REX_CVTDQ2PD_XMM12, p, pos); emit(REX_SUBPD, p, pos); emitByte(0xc4 + 8 * dst, p, pos); @@ -862,7 +969,7 @@ namespace randomx { int pos = codePos; const uint32_t dst = instr.dst % RegisterCountFlt; - genAddressReg(instr, p, pos); + genAddressReg(instr, p, pos); emit(REX_CVTDQ2PD_XMM12, p, pos); emit(REX_ANDPS_XMM12, p, pos); emit(REX_DIVPD, p, pos); @@ -902,19 +1009,39 @@ namespace randomx { uint8_t* const p = code; int pos = codePos; - int reg = instr.dst; + const int reg = instr.dst; + int32_t jmp_offset = registerUsage[reg] - (pos + 16); + + if (BranchesWithin32B) { + const uint32_t branch_begin = static_cast(pos + 7); + const uint32_t branch_end = static_cast(branch_begin + ((jmp_offset >= -128) ? 9 : 13)); + + // If the jump crosses or touches 32-byte boundary, align it + if ((branch_begin ^ branch_end) >= 32) { + const uint32_t alignment_size = 32 - (branch_begin & 31); + jmp_offset -= alignment_size; + emit(JMP_ALIGN_PREFIX[alignment_size], alignment_size, p, pos); + } + } + emit(REX_ADD_I, p, pos); emitByte(0xc0 + reg, p, pos); - int shift = instr.getModCond() + RandomX_CurrentConfig.JumpOffset; - uint32_t imm = instr.getImm32() | (1UL << shift); - if (RandomX_CurrentConfig.JumpOffset > 0 || shift > 0) - imm &= ~(1UL << (shift - 1)); + const int shift = instr.getModCond() + RandomX_CurrentConfig.JumpOffset; + const uint32_t imm = (instr.getImm32() | (1UL << shift)) & ~(1UL << (shift - 1)); emit32(imm, p, pos); emit(REX_TEST, p, pos); emitByte(0xc0 + reg, p, pos); emit32(RandomX_CurrentConfig.ConditionMask_Calculated << shift, p, pos); - emit(JZ, p, pos); - emit32(registerUsage[reg] - (pos + 4), p, pos); + + if (jmp_offset >= -128) { + emitByte(JZ_SHORT, p, pos); + emitByte(jmp_offset, p, pos); + } + else { + emit(JZ, p, pos); + emit32(jmp_offset - 4, p, pos); + } + //mark all registers as used uint64_t* r = (uint64_t*) registerUsage; uint64_t k = pos; diff --git a/src/crypto/randomx/jit_compiler_x86.hpp b/src/crypto/randomx/jit_compiler_x86.hpp index 30b16f58..f1864018 100644 --- a/src/crypto/randomx/jit_compiler_x86.hpp +++ b/src/crypto/randomx/jit_compiler_x86.hpp @@ -67,12 +67,17 @@ namespace randomx { static InstructionGeneratorX86 engine[256]; int registerUsage[RegistersCount]; + uint8_t* allocatedCode; uint8_t* code; int32_t codePos; + static bool BranchesWithin32B; + + static void applyTweaks(); void generateProgramPrologue(Program&, ProgramConfiguration&); void generateProgramEpilogue(Program&, ProgramConfiguration&); - static void genAddressReg(const Instruction&, uint8_t* code, int& codePos, bool rax = true); + template + static void genAddressReg(const Instruction&, uint8_t* code, int& codePos); static void genAddressRegDst(const Instruction&, uint8_t* code, int& codePos); static void genAddressImm(const Instruction&, uint8_t* code, int& codePos); static void genSIB(int scale, int index, int base, uint8_t* code, int& codePos); diff --git a/src/crypto/randomx/randomx.cpp b/src/crypto/randomx/randomx.cpp index 4f56dc09..f9ce93f8 100644 --- a/src/crypto/randomx/randomx.cpp +++ b/src/crypto/randomx/randomx.cpp @@ -473,4 +473,22 @@ extern "C" { machine->getFinalResult(output, RANDOMX_HASH_SIZE); } + void randomx_calculate_hash_first(randomx_vm* machine, uint64_t (&tempHash)[8], const void* input, size_t inputSize) { + rx_blake2b(tempHash, sizeof(tempHash), input, inputSize, nullptr, 0); + machine->initScratchpad(tempHash); + } + + void randomx_calculate_hash_next(randomx_vm* machine, uint64_t (&tempHash)[8], const void* nextInput, size_t nextInputSize, void* output) { + machine->resetRoundingMode(); + for (uint32_t chain = 0; chain < RandomX_CurrentConfig.ProgramCount - 1; ++chain) { + machine->run(&tempHash); + rx_blake2b(tempHash, sizeof(tempHash), machine->getRegisterFile(), sizeof(randomx::RegisterFile), nullptr, 0); + } + machine->run(&tempHash); + + // Finish current hash and fill the scratchpad for the next hash at the same time + rx_blake2b(tempHash, sizeof(tempHash), nextInput, nextInputSize, nullptr, 0); + machine->hashAndFill(output, RANDOMX_HASH_SIZE, tempHash); + } + } diff --git a/src/crypto/randomx/randomx.h b/src/crypto/randomx/randomx.h index 6e074dba..ea3bb099 100644 --- a/src/crypto/randomx/randomx.h +++ b/src/crypto/randomx/randomx.h @@ -338,6 +338,9 @@ RANDOMX_EXPORT void randomx_destroy_vm(randomx_vm *machine); */ RANDOMX_EXPORT void randomx_calculate_hash(randomx_vm *machine, const void *input, size_t inputSize, void *output); +RANDOMX_EXPORT void randomx_calculate_hash_first(randomx_vm* machine, uint64_t (&tempHash)[8], const void* input, size_t inputSize); +RANDOMX_EXPORT void randomx_calculate_hash_next(randomx_vm* machine, uint64_t (&tempHash)[8], const void* nextInput, size_t nextInputSize, void* output); + #if defined(__cplusplus) } #endif diff --git a/src/crypto/randomx/virtual_machine.cpp b/src/crypto/randomx/virtual_machine.cpp index 2913c7e5..ecd187e2 100644 --- a/src/crypto/randomx/virtual_machine.cpp +++ b/src/crypto/randomx/virtual_machine.cpp @@ -114,6 +114,12 @@ namespace randomx { rx_blake2b(out, outSize, ®, sizeof(RegisterFile), nullptr, 0); } + template + void VmBase::hashAndFill(void* out, size_t outSize, uint64_t (&fill_state)[8]) { + hashAndFillAes1Rx4(scratchpad, ScratchpadSize, ®.a, fill_state); + rx_blake2b(out, outSize, ®, sizeof(RegisterFile), nullptr, 0); + } + template void VmBase::initScratchpad(void* seed) { fillAes1Rx4(seed, ScratchpadSize, scratchpad); diff --git a/src/crypto/randomx/virtual_machine.hpp b/src/crypto/randomx/virtual_machine.hpp index c85af009..d3718d04 100644 --- a/src/crypto/randomx/virtual_machine.hpp +++ b/src/crypto/randomx/virtual_machine.hpp @@ -39,6 +39,7 @@ public: virtual ~randomx_vm() = 0; virtual void setScratchpad(uint8_t *scratchpad) = 0; virtual void getFinalResult(void* out, size_t outSize) = 0; + virtual void hashAndFill(void* out, size_t outSize, uint64_t (&fill_state)[8]) = 0; virtual void setDataset(randomx_dataset* dataset) { } virtual void setCache(randomx_cache* cache) { } virtual void initScratchpad(void* seed) = 0; @@ -82,6 +83,7 @@ namespace randomx { void setScratchpad(uint8_t *scratchpad) override; void initScratchpad(void* seed) override; void getFinalResult(void* out, size_t outSize) override; + void hashAndFill(void* out, size_t outSize, uint64_t (&fill_state)[8]) override; protected: void generateProgram(void* seed); diff --git a/src/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index 115c0f62..b08f844e 100644 --- a/src/crypto/rx/Rx.cpp +++ b/src/crypto/rx/Rx.cpp @@ -70,7 +70,7 @@ bool xmrig::Rx::init(const Job &job, const RxConfig &config, bool hugePages) return true; } - d_ptr->queue.enqueue(job, config.nodeset(), config.threads(), hugePages); + d_ptr->queue.enqueue(job, config.nodeset(), config.threads(), hugePages, config.mode()); return false; } diff --git a/src/crypto/rx/RxBasicStorage.cpp b/src/crypto/rx/RxBasicStorage.cpp index dcabad5b..bc1ceb2d 100644 --- a/src/crypto/rx/RxBasicStorage.cpp +++ b/src/crypto/rx/RxBasicStorage.cpp @@ -69,11 +69,11 @@ public: } - inline void createDataset(bool hugePages) + inline void createDataset(bool hugePages, RxConfig::Mode mode) { const uint64_t ts = Chrono::steadyMSecs(); - m_dataset = new RxDataset(hugePages, true); + m_dataset = new RxDataset(hugePages, true, mode); printAllocStatus(ts); } @@ -150,19 +150,19 @@ xmrig::RxDataset *xmrig::RxBasicStorage::dataset(const Job &job, uint32_t) const std::pair xmrig::RxBasicStorage::hugePages() const { if (!d_ptr->dataset()) { - return { 0u, 0u }; + return { 0U, 0U }; } return d_ptr->dataset()->hugePages(); } -void xmrig::RxBasicStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages) +void xmrig::RxBasicStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, RxConfig::Mode mode) { d_ptr->setSeed(seed); if (!d_ptr->dataset()) { - d_ptr->createDataset(hugePages); + d_ptr->createDataset(hugePages, mode); } d_ptr->initDataset(threads); diff --git a/src/crypto/rx/RxBasicStorage.h b/src/crypto/rx/RxBasicStorage.h index 63eba1d9..bd6575d2 100644 --- a/src/crypto/rx/RxBasicStorage.h +++ b/src/crypto/rx/RxBasicStorage.h @@ -50,7 +50,7 @@ public: protected: RxDataset *dataset(const Job &job, uint32_t nodeId) const override; std::pair hugePages() const override; - void init(const RxSeed &seed, uint32_t threads, bool hugePages) override; + void init(const RxSeed &seed, uint32_t threads, bool hugePages, RxConfig::Mode mode) override; private: RxBasicStoragePrivate *d_ptr; diff --git a/src/crypto/rx/RxConfig.cpp b/src/crypto/rx/RxConfig.cpp index 07f45eac..ef823e60 100644 --- a/src/crypto/rx/RxConfig.cpp +++ b/src/crypto/rx/RxConfig.cpp @@ -25,9 +25,54 @@ #include "crypto/rx/RxConfig.h" #include "backend/cpu/Cpu.h" +#include "rapidjson/document.h" + + +#include +#include + + +#ifdef _MSC_VER +# define strcasecmp _stricmp +#endif + + +namespace xmrig { + + +static const std::array modeNames = { "auto", "fast", "light" }; + + +} // namespace xmrig + + +const char *xmrig::RxConfig::modeName() const +{ + return modeNames[m_mode]; +} uint32_t xmrig::RxConfig::threads() const { return m_threads < 1 ? static_cast(Cpu::info()->threads()) : static_cast(m_threads); } + + +xmrig::RxConfig::Mode xmrig::RxConfig::readMode(const rapidjson::Value &value) const +{ + if (value.IsUint()) { + return static_cast(std::min(value.GetUint(), ModeMax - 1)); + } + + if (value.IsString()) { + auto mode = value.GetString(); + + for (size_t i = 0; i < modeNames.size(); i++) { + if (strcasecmp(mode, modeNames[i]) == 0) { + return static_cast(i); + } + } + } + + return AutoMode; +} diff --git a/src/crypto/rx/RxConfig.h b/src/crypto/rx/RxConfig.h index 52a832a2..13ebb9d1 100644 --- a/src/crypto/rx/RxConfig.h +++ b/src/crypto/rx/RxConfig.h @@ -38,6 +38,13 @@ namespace xmrig { class RxConfig { public: + enum Mode : uint32_t { + AutoMode, + FastMode, + LightMode, + ModeMax + }; + bool read(const rapidjson::Value &value); rapidjson::Value toJSON(rapidjson::Document &doc) const; @@ -47,11 +54,17 @@ public: inline std::vector nodeset() const { return std::vector(); } # endif + const char *modeName() const; uint32_t threads() const; + inline Mode mode() const { return m_mode; } + private: + Mode readMode(const rapidjson::Value &value) const; + bool m_numa = true; int m_threads = -1; + Mode m_mode = AutoMode; # ifdef XMRIG_FEATURE_HWLOC std::vector m_nodeset; diff --git a/src/crypto/rx/RxConfig_basic.cpp b/src/crypto/rx/RxConfig_basic.cpp index 26ef7a90..1311b220 100644 --- a/src/crypto/rx/RxConfig_basic.cpp +++ b/src/crypto/rx/RxConfig_basic.cpp @@ -31,6 +31,7 @@ namespace xmrig { static const char *kInit = "init"; +static const char *kMode = "mode"; } @@ -42,6 +43,7 @@ rapidjson::Value xmrig::RxConfig::toJSON(rapidjson::Document &doc) const Value obj(kObjectType); obj.AddMember(StringRef(kInit), m_threads, allocator); + obj.AddMember(StringRef(kMode), StringRef(modeName()), allocator); return obj; } @@ -51,6 +53,7 @@ bool xmrig::RxConfig::read(const rapidjson::Value &value) { if (value.IsObject()) { m_threads = Json::getInt(value, kInit, m_threads); + m_mode = readMode(Json::getValue(value, kMode)); return true; } diff --git a/src/crypto/rx/RxConfig_hwloc.cpp b/src/crypto/rx/RxConfig_hwloc.cpp index 66f086f2..4fc57fb6 100644 --- a/src/crypto/rx/RxConfig_hwloc.cpp +++ b/src/crypto/rx/RxConfig_hwloc.cpp @@ -33,6 +33,7 @@ namespace xmrig { static const char *kInit = "init"; +static const char *kMode = "mode"; static const char *kNUMA = "numa"; } @@ -46,6 +47,7 @@ rapidjson::Value xmrig::RxConfig::toJSON(rapidjson::Document &doc) const Value obj(kObjectType); obj.AddMember(StringRef(kInit), m_threads, allocator); + obj.AddMember(StringRef(kMode), StringRef(modeName()), allocator); if (!m_nodeset.empty()) { Value numa(kArrayType); @@ -68,6 +70,13 @@ bool xmrig::RxConfig::read(const rapidjson::Value &value) { if (value.IsObject()) { m_threads = Json::getInt(value, kInit, m_threads); + m_mode = readMode(Json::getValue(value, kMode)); + + if (m_mode == LightMode) { + m_numa = false; + + return true; + } const auto &numa = Json::getValue(value, kNUMA); if (numa.IsArray()) { diff --git a/src/crypto/rx/RxDataset.cpp b/src/crypto/rx/RxDataset.cpp index 62887a01..ce41a58e 100644 --- a/src/crypto/rx/RxDataset.cpp +++ b/src/crypto/rx/RxDataset.cpp @@ -26,6 +26,8 @@ #include "crypto/rx/RxDataset.h" +#include "backend/common/Tags.h" +#include "base/io/log/Log.h" #include "crypto/common/VirtualMemory.h" #include "crypto/randomx/randomx.h" #include "crypto/rx/RxAlgo.h" @@ -33,12 +35,14 @@ #include +#include static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mismatch"); -xmrig::RxDataset::RxDataset(bool hugePages, bool cache) +xmrig::RxDataset::RxDataset(bool hugePages, bool cache, RxConfig::Mode mode) : + m_mode(mode) { allocate(hugePages); @@ -118,7 +122,7 @@ size_t xmrig::RxDataset::size(bool cache) const std::pair xmrig::RxDataset::hugePages(bool cache) const { - constexpr size_t twoMiB = 2u * 1024u * 1024u; + constexpr size_t twoMiB = 2U * 1024U * 1024U; constexpr size_t cacheSize = VirtualMemory::align(RxCache::maxSize(), twoMiB) / twoMiB; size_t total = VirtualMemory::align(maxSize(), twoMiB) / twoMiB; @@ -157,6 +161,18 @@ void xmrig::RxDataset::setRaw(const void *raw) void xmrig::RxDataset::allocate(bool hugePages) { + if (m_mode == RxConfig::LightMode) { + LOG_ERR(CLEAR "%s" RED_BOLD_S "fast RandomX mode disabled by config", rx_tag()); + + return; + } + + if (m_mode == RxConfig::AutoMode && uv_get_total_memory() < (maxSize() + RxCache::maxSize())) { + LOG_ERR(CLEAR "%s" RED_BOLD_S "not enough memory for RandomX dataset", rx_tag()); + + return; + } + if (hugePages) { m_flags = RANDOMX_FLAG_LARGE_PAGES; m_dataset = randomx_alloc_dataset(static_cast(m_flags)); diff --git a/src/crypto/rx/RxDataset.h b/src/crypto/rx/RxDataset.h index 9b4f4120..30455956 100644 --- a/src/crypto/rx/RxDataset.h +++ b/src/crypto/rx/RxDataset.h @@ -28,9 +28,10 @@ #define XMRIG_RX_DATASET_H +#include "base/tools/Object.h" #include "crypto/common/Algorithm.h" #include "crypto/randomx/configuration.h" -#include "base/tools/Object.h" +#include "crypto/rx/RxConfig.h" struct randomx_dataset; @@ -49,7 +50,7 @@ class RxDataset public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxDataset) - RxDataset(bool hugePages, bool cache); + RxDataset(bool hugePages, bool cache, RxConfig::Mode mode); RxDataset(RxCache *cache); ~RxDataset(); @@ -69,9 +70,10 @@ public: private: void allocate(bool hugePages); - int m_flags = 0; - randomx_dataset *m_dataset = nullptr; - RxCache *m_cache = nullptr; + const RxConfig::Mode m_mode = RxConfig::FastMode; + int m_flags = 0; + randomx_dataset *m_dataset = nullptr; + RxCache *m_cache = nullptr; }; diff --git a/src/crypto/rx/RxNUMAStorage.cpp b/src/crypto/rx/RxNUMAStorage.cpp index 6d8ec167..646d3d95 100644 --- a/src/crypto/rx/RxNUMAStorage.cpp +++ b/src/crypto/rx/RxNUMAStorage.cpp @@ -198,7 +198,7 @@ private: return; } - auto dataset = new RxDataset(hugePages, false); + auto dataset = new RxDataset(hugePages, false, RxConfig::FastMode); if (!dataset->get()) { printSkipped(nodeId, "failed to allocate dataset"); @@ -339,14 +339,14 @@ xmrig::RxDataset *xmrig::RxNUMAStorage::dataset(const Job &job, uint32_t nodeId) std::pair xmrig::RxNUMAStorage::hugePages() const { if (!d_ptr->isAllocated()) { - return { 0u, 0u }; + return { 0U, 0U }; } return d_ptr->hugePages(); } -void xmrig::RxNUMAStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages) +void xmrig::RxNUMAStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, RxConfig::Mode) { d_ptr->setSeed(seed); diff --git a/src/crypto/rx/RxNUMAStorage.h b/src/crypto/rx/RxNUMAStorage.h index 3afdd81d..bed0bc75 100644 --- a/src/crypto/rx/RxNUMAStorage.h +++ b/src/crypto/rx/RxNUMAStorage.h @@ -53,7 +53,7 @@ public: protected: RxDataset *dataset(const Job &job, uint32_t nodeId) const override; std::pair hugePages() const override; - void init(const RxSeed &seed, uint32_t threads, bool hugePages) override; + void init(const RxSeed &seed, uint32_t threads, bool hugePages, RxConfig::Mode mode) override; private: RxNUMAStoragePrivate *d_ptr; diff --git a/src/crypto/rx/RxQueue.cpp b/src/crypto/rx/RxQueue.cpp index 6614d407..b420d0c2 100644 --- a/src/crypto/rx/RxQueue.cpp +++ b/src/crypto/rx/RxQueue.cpp @@ -90,11 +90,11 @@ std::pair xmrig::RxQueue::hugePages() { std::lock_guard lock(m_mutex); - return m_storage && m_state == STATE_IDLE ? m_storage->hugePages() : std::pair(0u, 0u); + return m_storage && m_state == STATE_IDLE ? m_storage->hugePages() : std::pair(0U, 0U); } -void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages) +void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode) { std::unique_lock lock(m_mutex); @@ -114,7 +114,7 @@ void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector &no return; } - m_queue.emplace_back(seed, nodeset, threads, hugePages); + m_queue.emplace_back(seed, nodeset, threads, hugePages, mode); m_seed = seed; m_state = STATE_PENDING; @@ -156,7 +156,7 @@ void xmrig::RxQueue::backgroundInit() Buffer::toHex(item.seed.data().data(), 8).data() ); - m_storage->init(item.seed, item.threads, item.hugePages); + m_storage->init(item.seed, item.threads, item.hugePages, item.mode); lock = std::unique_lock(m_mutex); diff --git a/src/crypto/rx/RxQueue.h b/src/crypto/rx/RxQueue.h index 28407a87..2d77e2e3 100644 --- a/src/crypto/rx/RxQueue.h +++ b/src/crypto/rx/RxQueue.h @@ -29,6 +29,7 @@ #include "base/tools/Object.h" +#include "crypto/rx/RxConfig.h" #include "crypto/rx/RxSeed.h" @@ -52,14 +53,16 @@ class RxDataset; class RxQueueItem { public: - RxQueueItem(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages) : + RxQueueItem(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode) : hugePages(hugePages), + mode(mode), seed(seed), nodeset(nodeset), threads(threads) {} const bool hugePages; + const RxConfig::Mode mode; const RxSeed seed; const std::vector nodeset; const uint32_t threads; @@ -77,7 +80,7 @@ public: bool isReady(const Job &job); RxDataset *dataset(const Job &job, uint32_t nodeId); std::pair hugePages(); - void enqueue(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages); + void enqueue(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode); private: enum State { diff --git a/src/version.h b/src/version.h index 3b976705..1cbae1b0 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 miner" -#define APP_VERSION "5.0.1" +#define APP_VERSION "5.1.0" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_KIND "miner" #define APP_VER_MAJOR 5 -#define APP_VER_MINOR 0 -#define APP_VER_PATCH 1 +#define APP_VER_MINOR 1 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1920)