diff --git a/src/backend/cuda/CudaBackend.cpp b/src/backend/cuda/CudaBackend.cpp index 784d21eb1..853d37e9f 100644 --- a/src/backend/cuda/CudaBackend.cpp +++ b/src/backend/cuda/CudaBackend.cpp @@ -32,6 +32,9 @@ #include "backend/common/interfaces/IWorker.h" #include "backend/common/Tags.h" #include "backend/common/Workers.h" +#include "backend/cuda/CudaConfig.h" +#include "backend/cuda/CudaThreads.h" +#include "backend/cuda/wrappers/CudaLib.h" #include "base/io/log/Log.h" #include "base/net/stratum/Job.h" #include "base/tools/Chrono.h" @@ -49,7 +52,7 @@ namespace xmrig { -extern template class Threads; +extern template class Threads; constexpr const size_t oneMiB = 1024u * 1024u; @@ -59,17 +62,42 @@ static std::mutex mutex; +static void printDisabled(const char *reason) +{ + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") RED_BOLD("disabled") "%s", "CUDA", reason); +} + + + class CudaBackendPrivate { public: inline CudaBackendPrivate(Controller *controller) : controller(controller) { + init(controller->config()->cuda()); } - void init(const OclConfig &cl) + void init(const CudaConfig &cuda) { + if (!cuda.isEnabled()) { + return printDisabled(""); + } + + if (!CudaLib::init(cuda.loader())) { + return printDisabled(RED_S " (failed to load CUDA plugin)"); + } + + if (!CudaLib::runtimeVersion() || !CudaLib::driverVersion() || !CudaLib::deviceCount()) { + return printDisabled(RED_S " (no devices)"); + } + + const uint32_t runtimeVersion = CudaLib::runtimeVersion(); + const uint32_t driverVersion = CudaLib::driverVersion(); + + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%u.%u") "/" WHITE_BOLD("%u.%u") BLACK_BOLD("/%s"), "CUDA", + runtimeVersion / 1000, runtimeVersion % 100, driverVersion / 1000, driverVersion % 100, CudaLib::pluginVersion()); } @@ -102,6 +130,8 @@ xmrig::CudaBackend::CudaBackend(Controller *controller) : xmrig::CudaBackend::~CudaBackend() { delete d_ptr; + + CudaLib::close(); } diff --git a/src/backend/cuda/CudaConfig.cpp b/src/backend/cuda/CudaConfig.cpp index 792131de9..ee4008222 100644 --- a/src/backend/cuda/CudaConfig.cpp +++ b/src/backend/cuda/CudaConfig.cpp @@ -35,6 +35,7 @@ namespace xmrig { static const char *kDevicesHint = "devices-hint"; static const char *kEnabled = "enabled"; +static const char *kLoader = "loader"; extern template class Threads; @@ -51,6 +52,7 @@ rapidjson::Value xmrig::CudaConfig::toJSON(rapidjson::Document &doc) const Value obj(kObjectType); obj.AddMember(StringRef(kEnabled), m_enabled, allocator); + obj.AddMember(StringRef(kLoader), m_loader.toJSON(), allocator); m_threads.toJSON(obj, doc); @@ -62,6 +64,7 @@ void xmrig::CudaConfig::read(const rapidjson::Value &value) { if (value.IsObject()) { m_enabled = Json::getBool(value, kEnabled, m_enabled); + m_loader = Json::getString(value, kLoader); setDevicesHint(Json::getString(value, kDevicesHint)); diff --git a/src/backend/cuda/CudaConfig.h b/src/backend/cuda/CudaConfig.h index 6feaa1304..16c06e60a 100644 --- a/src/backend/cuda/CudaConfig.h +++ b/src/backend/cuda/CudaConfig.h @@ -43,6 +43,7 @@ public: inline bool isEnabled() const { return m_enabled; } inline bool isShouldSave() const { return m_shouldSave; } + inline const String &loader() const { return m_loader; } inline const Threads &threads() const { return m_threads; } private: @@ -52,6 +53,7 @@ private: bool m_enabled = false; bool m_shouldSave = false; std::vector m_devicesHint; + String m_loader; Threads m_threads; }; diff --git a/src/backend/cuda/cuda.cmake b/src/backend/cuda/cuda.cmake index f8840c380..983e18a98 100644 --- a/src/backend/cuda/cuda.cmake +++ b/src/backend/cuda/cuda.cmake @@ -3,10 +3,11 @@ if (WITH_CUDA) set(HEADERS_BACKEND_CUDA src/backend/cuda/CudaBackend.h - src/backend/cuda/CudaConfig.h src/backend/cuda/CudaConfig_gen.h + src/backend/cuda/CudaConfig.h src/backend/cuda/CudaThread.h src/backend/cuda/CudaThreads.h + src/backend/cuda/wrappers/CudaLib.h ) set(SOURCES_BACKEND_CUDA @@ -14,6 +15,7 @@ if (WITH_CUDA) src/backend/cuda/CudaConfig.cpp src/backend/cuda/CudaThread.cpp src/backend/cuda/CudaThreads.cpp + src/backend/cuda/wrappers/CudaLib.cpp ) else() remove_definitions(/DXMRIG_FEATURE_CUDA) diff --git a/src/backend/cuda/wrappers/CudaLib.cpp b/src/backend/cuda/wrappers/CudaLib.cpp new file mode 100644 index 000000000..1d0754087 --- /dev/null +++ b/src/backend/cuda/wrappers/CudaLib.cpp @@ -0,0 +1,174 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * 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 . + */ + + +#include +#include + + +#include "backend/cuda/wrappers/CudaLib.h" +#include "base/io/log/Log.h" + + +namespace xmrig { + + +enum Version : uint32_t +{ + ApiVersion, + DriverVersion, + RuntimeVersion +}; + + +static uv_lib_t cudaLib; + + +static const char *kAlloc = "alloc"; +static const char *kDeviceCount = "deviceCount"; +static const char *kPluginVersion = "pluginVersion"; +static const char *kRelease = "release"; +static const char *kSymbolNotFound = "symbol not found"; +static const char *kVersion = "version"; + + +using alloc_t = nvid_ctx * (*)(size_t, int, int, int, int, int); +using deviceCount_t = size_t (*)(); +using pluginVersion_t = const char * (*)(); +using release_t = void (*)(nvid_ctx *); +using version_t = uint32_t (*)(Version); + + +static alloc_t pAlloc = nullptr; +static deviceCount_t pDeviceCount = nullptr; +static pluginVersion_t pPluginVersion = nullptr; +static release_t pRelease = nullptr; +static version_t pVersion = nullptr; + + +#define DLSYM(x) if (uv_dlsym(&cudaLib, k##x, reinterpret_cast(&p##x)) == -1) { throw std::runtime_error(kSymbolNotFound); } + + +bool CudaLib::m_initialized = false; +bool CudaLib::m_ready = false; +String CudaLib::m_loader; + + +} // namespace xmrig + + +bool xmrig::CudaLib::init(const char *fileName) +{ + if (!m_initialized) { + m_loader = fileName == nullptr ? defaultLoader() : fileName; + m_ready = uv_dlopen(m_loader, &cudaLib) == 0 && load(); + m_initialized = true; + } + + return m_ready; +} + + +const char *xmrig::CudaLib::lastError() +{ + return uv_dlerror(&cudaLib); +} + + +void xmrig::CudaLib::close() +{ + uv_dlclose(&cudaLib); +} + + +const char *xmrig::CudaLib::pluginVersion() noexcept +{ + return pPluginVersion(); +} + + +nvid_ctx *xmrig::CudaLib::alloc(size_t id, int blocks, int threads, int bfactor, int bsleep, const Algorithm &algorithm) noexcept +{ + return pAlloc(id, blocks, threads, bfactor, bsleep, algorithm); +} + + +size_t xmrig::CudaLib::deviceCount() noexcept +{ + return pDeviceCount(); +} + + +uint32_t xmrig::CudaLib::driverVersion() noexcept +{ + return pVersion(DriverVersion); +} + + +uint32_t xmrig::CudaLib::runtimeVersion() noexcept +{ + return pVersion(RuntimeVersion); +} + + +void xmrig::CudaLib::release(nvid_ctx *ctx) noexcept +{ + pRelease(ctx); +} + + +bool xmrig::CudaLib::load() +{ + if (uv_dlsym(&cudaLib, kVersion, reinterpret_cast(&pVersion)) == -1) { + return false; + } + + if (pVersion(ApiVersion) != 1u) { + return false; + } + + try { + DLSYM(Alloc); + DLSYM(DeviceCount); + DLSYM(PluginVersion); + DLSYM(Release); + DLSYM(Version); + } catch (std::exception &ex) { + return false; + } + + return true; +} + + +const char *xmrig::CudaLib::defaultLoader() +{ +# if defined(__APPLE__) + return "/System/Library/Frameworks/OpenCL.framework/OpenCL"; // FIXME +# elif defined(_WIN32) + return "xmrig-cuda.dll"; +# else + return "xmrig-cuda.so"; +# endif +} diff --git a/src/backend/cuda/wrappers/CudaLib.h b/src/backend/cuda/wrappers/CudaLib.h new file mode 100644 index 000000000..d82447e15 --- /dev/null +++ b/src/backend/cuda/wrappers/CudaLib.h @@ -0,0 +1,72 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * 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 . + */ + +#ifndef XMRIG_CUDALIB_H +#define XMRIG_CUDALIB_H + + +#include + + +#include "base/tools/String.h" +#include "crypto/common/Algorithm.h" + + +using nvid_ctx = struct nvid_ctx; + + +namespace xmrig { + + +class CudaLib +{ +public: + static bool init(const char *fileName = nullptr); + static const char *lastError(); + static void close(); + + static inline bool isInitialized() { return m_initialized; } + static inline const String &loader() { return m_loader; } + + static const char *pluginVersion() noexcept; + static nvid_ctx *alloc(size_t id, int blocks, int threads, int bfactor, int bsleep, const Algorithm &algorithm) noexcept; + static size_t deviceCount() noexcept; + static uint32_t driverVersion() noexcept; + static uint32_t runtimeVersion() noexcept; + static void release(nvid_ctx *ctx) noexcept; + +private: + static bool load(); + static const char *defaultLoader(); + + static bool m_initialized; + static bool m_ready; + static String m_loader; +}; + + +} // namespace xmrig + + +#endif /* XMRIG_CUDALIB_H */ diff --git a/src/backend/opencl/wrappers/OclLib.cpp b/src/backend/opencl/wrappers/OclLib.cpp index 1b530bae9..f156ed3d8 100644 --- a/src/backend/opencl/wrappers/OclLib.cpp +++ b/src/backend/opencl/wrappers/OclLib.cpp @@ -77,6 +77,7 @@ static const char *kRetainMemObject = "clRetainMemObject"; static const char *kRetainProgram = "clRetainProgram"; static const char *kSetKernelArg = "clSetKernelArg"; static const char *kSetMemObjectDestructorCallback = "clSetMemObjectDestructorCallback"; +static const char *kSymbolNotFound = "symbol not found"; static const char *kUnloadPlatformCompiler = "clUnloadPlatformCompiler"; @@ -156,7 +157,7 @@ static setKernelArg_t pSetKernelArg = nu static setMemObjectDestructorCallback_t pSetMemObjectDestructorCallback = nullptr; static unloadPlatformCompiler_t pUnloadPlatformCompiler = nullptr; -#define DLSYM(x) if (uv_dlsym(&oclLib, k##x, reinterpret_cast(&p##x)) == -1) { return false; } +#define DLSYM(x) if (uv_dlsym(&oclLib, k##x, reinterpret_cast(&p##x)) == -1) { throw std::runtime_error(kSymbolNotFound); } namespace xmrig { @@ -210,39 +211,43 @@ void xmrig::OclLib::close() bool xmrig::OclLib::load() { - DLSYM(CreateCommandQueue); - DLSYM(CreateContext); - DLSYM(BuildProgram); - DLSYM(EnqueueNDRangeKernel); - DLSYM(EnqueueReadBuffer); - DLSYM(EnqueueWriteBuffer); - DLSYM(Finish); - DLSYM(GetDeviceIDs); - DLSYM(GetDeviceInfo); - DLSYM(GetPlatformInfo); - DLSYM(GetPlatformIDs); - DLSYM(GetProgramBuildInfo); - DLSYM(GetProgramInfo); - DLSYM(SetKernelArg); - DLSYM(CreateKernel); - DLSYM(CreateBuffer); - DLSYM(CreateProgramWithBinary); - DLSYM(CreateProgramWithSource); - DLSYM(ReleaseMemObject); - DLSYM(ReleaseProgram); - DLSYM(ReleaseKernel); - DLSYM(ReleaseCommandQueue); - DLSYM(ReleaseContext); - DLSYM(GetKernelInfo); - DLSYM(GetCommandQueueInfo); - DLSYM(GetMemObjectInfo); - DLSYM(GetContextInfo); - DLSYM(ReleaseDevice); - DLSYM(UnloadPlatformCompiler); - DLSYM(SetMemObjectDestructorCallback); - DLSYM(CreateSubBuffer); - DLSYM(RetainProgram); - DLSYM(RetainMemObject); + try { + DLSYM(CreateCommandQueue); + DLSYM(CreateContext); + DLSYM(BuildProgram); + DLSYM(EnqueueNDRangeKernel); + DLSYM(EnqueueReadBuffer); + DLSYM(EnqueueWriteBuffer); + DLSYM(Finish); + DLSYM(GetDeviceIDs); + DLSYM(GetDeviceInfo); + DLSYM(GetPlatformInfo); + DLSYM(GetPlatformIDs); + DLSYM(GetProgramBuildInfo); + DLSYM(GetProgramInfo); + DLSYM(SetKernelArg); + DLSYM(CreateKernel); + DLSYM(CreateBuffer); + DLSYM(CreateProgramWithBinary); + DLSYM(CreateProgramWithSource); + DLSYM(ReleaseMemObject); + DLSYM(ReleaseProgram); + DLSYM(ReleaseKernel); + DLSYM(ReleaseCommandQueue); + DLSYM(ReleaseContext); + DLSYM(GetKernelInfo); + DLSYM(GetCommandQueueInfo); + DLSYM(GetMemObjectInfo); + DLSYM(GetContextInfo); + DLSYM(ReleaseDevice); + DLSYM(UnloadPlatformCompiler); + DLSYM(SetMemObjectDestructorCallback); + DLSYM(CreateSubBuffer); + DLSYM(RetainProgram); + DLSYM(RetainMemObject); + } catch (std::exception &ex) { + return false; + } # if defined(CL_VERSION_2_0) uv_dlsym(&oclLib, kCreateCommandQueueWithProperties, reinterpret_cast(&pCreateCommandQueueWithProperties)); diff --git a/src/crypto/cn/CnAlgo.h b/src/crypto/cn/CnAlgo.h index 296c52b73..b6a76089e 100644 --- a/src/crypto/cn/CnAlgo.h +++ b/src/crypto/cn/CnAlgo.h @@ -49,7 +49,7 @@ public: constexpr inline bool isR() const { return ALGO == Algorithm::CN_R; } constexpr inline size_t memory() const { static_assert(ALGO > Algorithm::INVALID && ALGO < Algorithm::RX_0, "invalid CRYPTONIGHT algorithm"); return CN_MEMORY; } constexpr inline uint32_t iterations() const { static_assert(ALGO > Algorithm::INVALID && ALGO < Algorithm::RX_0, "invalid CRYPTONIGHT algorithm"); return CN_ITER; } - constexpr inline uint32_t mask() const { return ((memory() - 1) / 16) * 16; } + constexpr inline uint32_t mask() const { return static_cast(((memory() - 1) / 16) * 16); } inline static size_t memory(Algorithm::Id algo) {