diff --git a/src/backend/common/WorkerJob.h b/src/backend/common/WorkerJob.h index 2f01ea3d9..51b849ac2 100644 --- a/src/backend/common/WorkerJob.h +++ b/src/backend/common/WorkerJob.h @@ -66,14 +66,12 @@ public: inline bool nextRound(uint32_t rounds, uint32_t roundSize) { - bool ok = true; m_rounds[index()]++; if ((m_rounds[index()] % rounds) == 0) { for (size_t i = 0; i < N; ++i) { - *nonce(i) = Nonce::next(index(), *nonce(i), rounds * roundSize, currentJob().isNicehash(), &ok); - if (!ok) { - break; + if (!Nonce::next(index(), nonce(i), rounds * roundSize, nonceMask())) { + return false; } } } @@ -83,13 +81,14 @@ public: } } - return ok; + return true; } private: inline int32_t nonceOffset() const { return currentJob().nonceOffset(); } inline size_t nonceSize() const { return currentJob().nonceSize(); } + inline uint64_t nonceMask() const { return m_nonce_mask[index()]; } inline void save(const Job &job, uint32_t reserveCount, Nonce::Backend backend) { @@ -97,12 +96,13 @@ private: const size_t size = job.size(); m_jobs[index()] = job; m_rounds[index()] = 0; + m_nonce_mask[index()] = job.isNicehash() ? 0xFFFFFFULL : (nonceSize() == sizeof(uint64_t) ? (-1ull >> (job.extraNonce().size() * 4 + 1)): 0xFFFFFFFFULL); m_jobs[index()].setBackend(backend); 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()); + Nonce::next(index(), nonce(i), reserveCount, nonceMask()); } } @@ -110,6 +110,7 @@ private: alignas(16) uint8_t m_blobs[2][Job::kMaxBlobSize * N]{}; Job m_jobs[2]; uint32_t m_rounds[2] = { 0, 0 }; + uint64_t m_nonce_mask[2]; uint64_t m_sequence = 0; uint8_t m_index = 0; }; @@ -125,41 +126,23 @@ inline uint32_t *xmrig::WorkerJob<1>::nonce(size_t) template<> inline bool xmrig::WorkerJob<1>::nextRound(uint32_t rounds, uint32_t roundSize) { - bool ok = true; m_rounds[index()]++; uint32_t* n = nonce(); - const uint32_t prev_nonce = *n; if ((m_rounds[index()] % rounds) == 0) { - *n = Nonce::next(index(), *n, rounds * roundSize, currentJob().isNicehash(), &ok); + if (!Nonce::next(index(), n, rounds * roundSize, nonceMask())) { + return false; + } + if (nonceSize() == sizeof(uint64_t)) { + m_jobs[index()].nonce()[1] = n[1]; + } } else { *n += roundSize; } - // Increment higher 32 bits of a 64-bit nonce when lower 32 bits overflow - if (!currentJob().isNicehash() && (nonceSize() == sizeof(uint64_t))) { - const bool wrapped = (*n < prev_nonce); - const bool wraps_this_round = (static_cast(*n) + roundSize > (1ULL << 32)); - - // Account for the case when starting nonce hasn't wrapped yet, but some nonces in the current round will wrap - if (wrapped || wraps_this_round) { - // Set lower 32 bits to 0 when higher 32 bits change - Nonce::reset(index()); - - // Sets *n to 0 and Nonce::m_nonce[index] to the correct next value - *n = 0; - Nonce::next(index(), *n, rounds * roundSize, currentJob().isNicehash(), &ok); - - ++n[1]; - - Job& job = m_jobs[index()]; - memcpy(job.blob(), blob(), job.size()); - } - } - - return ok; + return true; } @@ -169,11 +152,12 @@ inline void xmrig::WorkerJob<1>::save(const Job &job, uint32_t reserveCount, Non m_index = job.index(); m_jobs[index()] = job; m_rounds[index()] = 0; + m_nonce_mask[index()] = job.isNicehash() ? 0xFFFFFFULL : (nonceSize() == sizeof(uint64_t) ? (-1ull >> (job.extraNonce().size() * 4 + 1)): 0xFFFFFFFFULL); m_jobs[index()].setBackend(backend); memcpy(blob(), job.blob(), job.size()); - *nonce() = Nonce::next(index(), *nonce(), reserveCount, currentJob().isNicehash()); + Nonce::next(index(), nonce(), reserveCount, nonceMask()); } diff --git a/src/crypto/common/Nonce.cpp b/src/crypto/common/Nonce.cpp index f896c5612..2c5a47a9a 100644 --- a/src/crypto/common/Nonce.cpp +++ b/src/crypto/common/Nonce.cpp @@ -26,18 +26,14 @@ #include "crypto/common/Nonce.h" -#include - - namespace xmrig { std::atomic Nonce::m_paused; std::atomic Nonce::m_sequence[Nonce::MAX]; -uint32_t Nonce::m_nonces[2] = { 0, 0 }; +std::atomic Nonce::m_nonces[2] = { {0}, {0} }; -static std::mutex mutex; static Nonce nonce; @@ -54,40 +50,32 @@ xmrig::Nonce::Nonce() } -uint32_t xmrig::Nonce::next(uint8_t index, uint32_t nonce, uint32_t reserveCount, bool nicehash, bool *ok) +bool xmrig::Nonce::next(uint8_t index, uint32_t *nonce, uint32_t reserveCount, uint64_t mask) { - uint32_t next; - - std::lock_guard lock(mutex); - - if (nicehash) { - if ((m_nonces[index] + reserveCount) > 0x1000000) { - if (ok) { - *ok = false; - } + if (reserveCount == 0 || mask < reserveCount - 1) { + return false; + } + uint64_t counter = m_nonces[index].fetch_add(reserveCount, std::memory_order_relaxed); + while (true) { + if (mask < counter) { + return false; + } else if (mask - counter <= reserveCount - 1) { pause(true); - - return 0; + if (mask - counter < reserveCount - 1) { + return false; + } } - - next = (nonce & 0xFF000000) | m_nonces[index]; + else if (0xFFFFFFFFUL - (uint32_t)counter < reserveCount - 1) { + counter = m_nonces[index].fetch_add(reserveCount, std::memory_order_relaxed); + continue; + } + *nonce = (nonce[0] & ~mask) | counter; + if (mask > 0xFFFFFFFFULL) { + nonce[1] = (nonce[1] & (~mask >> 32)) | (counter >> 32); + } + return true; } - else { - next = m_nonces[index]; - } - - m_nonces[index] += reserveCount; - - return next; -} - - -void xmrig::Nonce::reset(uint8_t index) -{ - std::lock_guard lock(mutex); - - m_nonces[index] = 0; } diff --git a/src/crypto/common/Nonce.h b/src/crypto/common/Nonce.h index 4fa47b873..05c842987 100644 --- a/src/crypto/common/Nonce.h +++ b/src/crypto/common/Nonce.h @@ -49,18 +49,18 @@ public: static inline bool isPaused() { return m_paused.load(std::memory_order_relaxed); } static inline uint64_t sequence(Backend backend) { return m_sequence[backend].load(std::memory_order_relaxed); } static inline void pause(bool paused) { m_paused = paused; } + static inline void reset(uint8_t index) { m_nonces[index] = 0; } static inline void stop(Backend backend) { m_sequence[backend] = 0; } static inline void touch(Backend backend) { m_sequence[backend]++; } - static uint32_t next(uint8_t index, uint32_t nonce, uint32_t reserveCount, bool nicehash, bool *ok = nullptr); - static void reset(uint8_t index); + static bool next(uint8_t index, uint32_t *nonce, uint32_t reserveCount, uint64_t mask); static void stop(); static void touch(); private: static std::atomic m_paused; static std::atomic m_sequence[MAX]; - static uint32_t m_nonces[2]; + static std::atomic m_nonces[2]; };