diff --git a/src/base/base.cmake b/src/base/base.cmake index a49a717ee..533b551c4 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -4,6 +4,7 @@ set(HEADERS_BASE src/base/crypto/Coin.h src/base/crypto/keccak.h src/base/crypto/sha3.h + src/base/io/Async.h src/base/io/Console.h src/base/io/Env.h src/base/io/json/Json.h @@ -21,6 +22,7 @@ set(HEADERS_BASE src/base/kernel/config/BaseTransform.h src/base/kernel/config/Title.h src/base/kernel/Entry.h + src/base/kernel/interfaces/IAsyncListener.h src/base/kernel/interfaces/IBaseListener.h src/base/kernel/interfaces/IClient.h src/base/kernel/interfaces/IClientListener.h @@ -73,6 +75,7 @@ set(SOURCES_BASE src/base/crypto/Coin.cpp src/base/crypto/keccak.cpp src/base/crypto/sha3.cpp + src/base/io/Async.cpp src/base/io/Console.cpp src/base/io/Env.cpp src/base/io/json/Json.cpp @@ -127,7 +130,6 @@ elseif (APPLE) ) else() set(SOURCES_OS - src/base/io/Async.cpp src/base/io/json/Json_unix.cpp src/base/kernel/Platform_unix.cpp ) diff --git a/src/base/io/Async.cpp b/src/base/io/Async.cpp index f2bc5ff26..5ee637f2c 100644 --- a/src/base/io/Async.cpp +++ b/src/base/io/Async.cpp @@ -19,9 +19,12 @@ */ #include "base/io/Async.h" +#include "base/kernel/interfaces/IAsyncListener.h" +#include "base/tools/Handle.h" -#if defined(XMRIG_UV_PERFORMANCE_BUG) +// since 2019.05.16, Version 1.29.0 (Stable) https://github.com/xmrig/xmrig/pull/1889 +#if (UV_VERSION_MAJOR >= 1) && (UV_VERSION_MINOR >= 29) && defined(__linux__) #include <sys/eventfd.h> #include <sys/poll.h> #include <unistd.h> @@ -31,16 +34,28 @@ namespace xmrig { +struct uv_async_t: uv_poll_t +{ + using uv_async_cb = void (*)(uv_async_t *); + ~uv_async_t(); + int m_fd = -1; + uv_async_cb m_cb = nullptr; +}; + + +using uv_async_cb = uv_async_t::uv_async_cb; + + uv_async_t::~uv_async_t() { close(m_fd); } -static void on_schedule(uv_poll_t *handle, int status, int events) +static void on_schedule(uv_poll_t *handle, int, int) { static uint64_t val; - uv_async_t *async = reinterpret_cast<uv_async_t *>(handle); + auto async = reinterpret_cast<uv_async_t *>(handle); for (;;) { int r = read(async->m_fd, &val, sizeof(val)); @@ -64,7 +79,7 @@ static void on_schedule(uv_poll_t *handle, int status, int events) } -int uv_async_init(uv_loop_t *loop, uv_async_t *async, uv_async_cb cb) +static int uv_async_init(uv_loop_t *loop, uv_async_t *async, uv_async_cb cb) { int fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (fd < 0) { @@ -78,7 +93,7 @@ int uv_async_init(uv_loop_t *loop, uv_async_t *async, uv_async_cb cb) } -int uv_async_send(uv_async_t *async) +static int uv_async_send(uv_async_t *async) { static const uint64_t val = 1; int r; @@ -96,3 +111,41 @@ int uv_async_send(uv_async_t *async) } // namespace xmrig #endif + + +namespace xmrig { + + +class AsyncPrivate +{ +public: + IAsyncListener *listener = nullptr; + uv_async_t *async = nullptr; +}; + + +} // namespace xmrig + + +xmrig::Async::Async(IAsyncListener *listener) : d_ptr(new AsyncPrivate()) +{ + d_ptr->listener = listener; + d_ptr->async = new uv_async_t; + d_ptr->async->data = this; + + uv_async_init(uv_default_loop(), d_ptr->async, [](uv_async_t *handle) { static_cast<Async *>(handle->data)->d_ptr->listener->onAsync(); }); +} + + +xmrig::Async::~Async() +{ + Handle::close(d_ptr->async); + + delete d_ptr; +} + + +void xmrig::Async::send() +{ + uv_async_send(d_ptr->async); +} diff --git a/src/base/io/Async.h b/src/base/io/Async.h index 7d1993367..acf3b2cc2 100644 --- a/src/base/io/Async.h +++ b/src/base/io/Async.h @@ -22,7 +22,7 @@ #define XMRIG_ASYNC_H -#include <uv.h> +#include "base/tools/Object.h" // since 2019.05.16, Version 1.29.0 (Stable) @@ -49,4 +49,29 @@ extern int uv_async_send(uv_async_t *async); #endif +namespace xmrig { + + +class AsyncPrivate; +class IAsyncListener; + + +class Async +{ +public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Async) + + Async(IAsyncListener *listener); + ~Async(); + + void send(); + +private: + AsyncPrivate *d_ptr; +}; + + +} // namespace xmrig + + #endif /* XMRIG_ASYNC_H */ diff --git a/src/base/kernel/interfaces/IAsyncListener.h b/src/base/kernel/interfaces/IAsyncListener.h new file mode 100644 index 000000000..868646feb --- /dev/null +++ b/src/base/kernel/interfaces/IAsyncListener.h @@ -0,0 +1,47 @@ +/* XMRig + * Copyright 2018-2020 SChernykh <https://github.com/SChernykh> + * Copyright 2016-2020 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_IASYNCLISTENER_H +#define XMRIG_IASYNCLISTENER_H + + +#include "base/tools/Object.h" + + +namespace xmrig { + + +class Async; + + +class IAsyncListener +{ +public: + XMRIG_DISABLE_COPY_MOVE(IAsyncListener) + + IAsyncListener() = default; + virtual ~IAsyncListener() = default; + + virtual void onAsync() = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_IASYNCLISTENER_H diff --git a/src/crypto/rx/RxQueue.cpp b/src/crypto/rx/RxQueue.cpp index af139106f..8badab50f 100644 --- a/src/crypto/rx/RxQueue.cpp +++ b/src/crypto/rx/RxQueue.cpp @@ -27,9 +27,9 @@ #include "crypto/rx/RxQueue.h" #include "backend/common/interfaces/IRxListener.h" +#include "base/io/Async.h" #include "base/io/log/Log.h" #include "base/io/log/Tags.h" -#include "base/tools/Handle.h" #include "crypto/rx/RxBasicStorage.h" @@ -41,11 +41,7 @@ xmrig::RxQueue::RxQueue(IRxListener *listener) : m_listener(listener) { - m_async = new uv_async_t; - m_async->data = this; - - uv_async_init(uv_default_loop(), m_async, [](uv_async_t *handle) { static_cast<RxQueue *>(handle->data)->onReady(); }); - + m_async = std::make_shared<Async>(this); m_thread = std::thread(&RxQueue::backgroundInit, this); } @@ -61,8 +57,6 @@ xmrig::RxQueue::~RxQueue() m_thread.join(); delete m_storage; - - Handle::close(m_async); } @@ -167,7 +161,7 @@ void xmrig::RxQueue::backgroundInit() } m_state = STATE_IDLE; - uv_async_send(m_async); + m_async->send(); } } diff --git a/src/crypto/rx/RxQueue.h b/src/crypto/rx/RxQueue.h index bee2bbd2a..7b462cf4e 100644 --- a/src/crypto/rx/RxQueue.h +++ b/src/crypto/rx/RxQueue.h @@ -28,7 +28,7 @@ #define XMRIG_RX_QUEUE_H -#include "base/io/Async.h" +#include "base/kernel/interfaces/IAsyncListener.h" #include "base/tools/Object.h" #include "crypto/common/HugePagesInfo.h" #include "crypto/rx/RxConfig.h" @@ -40,9 +40,6 @@ #include <thread> -using uv_async_t = struct uv_async_s; - - namespace xmrig { @@ -75,19 +72,22 @@ public: }; -class RxQueue +class RxQueue : public IAsyncListener { public: XMRIG_DISABLE_COPY_MOVE(RxQueue); RxQueue(IRxListener *listener); - ~RxQueue(); + ~RxQueue() override; HugePagesInfo hugePages(); RxDataset *dataset(const Job &job, uint32_t nodeId); template<typename T> bool isReady(const T &seed); void enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority); +protected: + inline void onAsync() override { onReady(); } + private: enum State { STATE_IDLE, @@ -105,9 +105,9 @@ private: State m_state = STATE_IDLE; std::condition_variable m_cv; std::mutex m_mutex; + std::shared_ptr<Async> m_async; std::thread m_thread; std::vector<RxQueueItem> m_queue; - uv_async_t *m_async = nullptr; }; diff --git a/src/net/JobResults.cpp b/src/net/JobResults.cpp index c54b85d34..bb3771ef3 100644 --- a/src/net/JobResults.cpp +++ b/src/net/JobResults.cpp @@ -24,13 +24,13 @@ #include "net/JobResults.h" +#include "backend/common/Tags.h" #include "base/io/Async.h" #include "base/io/log/Log.h" -#include "base/tools/Handle.h" +#include "base/kernel/interfaces/IAsyncListener.h" #include "base/tools/Object.h" #include "net/interfaces/IJobResultListener.h" #include "net/JobResult.h" -#include "backend/common/Tags.h" #ifdef XMRIG_ALGO_RANDOMX @@ -57,6 +57,7 @@ #include <cassert> #include <list> +#include <memory> #include <mutex> #include <uv.h> @@ -193,7 +194,7 @@ static void getResults(JobBundle &bundle, std::vector<JobResult> &results, uint3 #endif -class JobResultsPrivate +class JobResultsPrivate : public IAsyncListener { public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(JobResultsPrivate) @@ -202,17 +203,11 @@ public: m_hwAES(hwAES), m_listener(listener) { - m_async = new uv_async_t; - m_async->data = this; - - uv_async_init(uv_default_loop(), m_async, JobResultsPrivate::onResult); + m_async = std::make_shared<Async>(this); } - inline ~JobResultsPrivate() - { - Handle::close(m_async); - } + ~JobResultsPrivate() override = default; inline void submit(const JobResult &result) @@ -220,7 +215,7 @@ public: std::lock_guard<std::mutex> lock(m_mutex); m_results.push_back(result); - uv_async_send(m_async); + m_async->send(); } @@ -230,11 +225,15 @@ public: std::lock_guard<std::mutex> lock(m_mutex); m_bundles.emplace_back(job, results, count, device_index); - uv_async_send(m_async); + m_async->send(); } # endif +protected: + inline void onAsync() override { submit(); } + + private: static void onResult(uv_async_t *handle) { static_cast<JobResultsPrivate*>(handle->data)->submit(); } @@ -300,7 +299,7 @@ private: IJobResultListener *m_listener; std::list<JobResult> m_results; std::mutex m_mutex; - uv_async_t *m_async; + std::shared_ptr<Async> m_async; # if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA) std::list<JobBundle> m_bundles;