mirror of
https://github.com/xmrig/xmrig.git
synced 2025-12-07 07:55:04 -05:00
Compare commits
101 Commits
v4.3.0-bet
...
v4.6.2-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c4b76f3f7 | ||
|
|
835228d9f7 | ||
|
|
2847c814d2 | ||
|
|
f77c4c67f2 | ||
|
|
13d256e737 | ||
|
|
ed4cfd55ac | ||
|
|
f965fd5a8c | ||
|
|
472ec1a0e6 | ||
|
|
74d62c92cd | ||
|
|
7e47b04676 | ||
|
|
d19c152d9a | ||
|
|
2abea46a87 | ||
|
|
e450e62b40 | ||
|
|
e6afd12d4f | ||
|
|
2ba19c9827 | ||
|
|
426bc8f0c4 | ||
|
|
f9f7567b17 | ||
|
|
d2b3ffc710 | ||
|
|
ed2f2c5a60 | ||
|
|
c235145121 | ||
|
|
f8d1488e33 | ||
|
|
0013e610d5 | ||
|
|
2c9b034c08 | ||
|
|
455cdf96f0 | ||
|
|
5519e97e6e | ||
|
|
4c4a674a4b | ||
|
|
239aecb0bb | ||
|
|
b1e23b46dd | ||
|
|
9d679462ed | ||
|
|
be31811920 | ||
|
|
26ed6254dc | ||
|
|
1cb4d73fe3 | ||
|
|
f110b5000b | ||
|
|
83f437f979 | ||
|
|
175a7b06b7 | ||
|
|
9d580693db | ||
|
|
3bdf7111ce | ||
|
|
23ebcfb2db | ||
|
|
b1eac17d60 | ||
|
|
9dfa38f1e7 | ||
|
|
80fd0f9fab | ||
|
|
58174e5e91 | ||
|
|
ab7f0cb4cc | ||
|
|
f6f480264e | ||
|
|
8cd265c38c | ||
|
|
99fe304c1f | ||
|
|
7889634b40 | ||
|
|
0e224abb0a | ||
|
|
c9f7cbae09 | ||
|
|
2e537013a2 | ||
|
|
7cb9b92347 | ||
|
|
bb2cc0deb7 | ||
|
|
d4a3024996 | ||
|
|
77d5b73724 | ||
|
|
ec717f27b5 | ||
|
|
0fc215c457 | ||
|
|
534a764023 | ||
|
|
dc705d88ab | ||
|
|
6e9fd5a430 | ||
|
|
e3f37bc2f9 | ||
|
|
f6d58c7d46 | ||
|
|
48545c5916 | ||
|
|
f7dcfffdb1 | ||
|
|
52281906c6 | ||
|
|
487b2a3655 | ||
|
|
71ee145f70 | ||
|
|
da20d74145 | ||
|
|
c29fa62260 | ||
|
|
5613912ec4 | ||
|
|
b77c5428f9 | ||
|
|
2012ce384e | ||
|
|
6b40ede2bc | ||
|
|
128c5f67ad | ||
|
|
578bebb04d | ||
|
|
5611249af7 | ||
|
|
a56febcd13 | ||
|
|
0ad992985c | ||
|
|
1a66c3f1a1 | ||
|
|
a2ef2fd9d9 | ||
|
|
5c02cb50da | ||
|
|
998c55030a | ||
|
|
079de97fab | ||
|
|
432addab33 | ||
|
|
10d292092a | ||
|
|
a02ee96651 | ||
|
|
d783febad6 | ||
|
|
ea6d9073b7 | ||
|
|
83a5923568 | ||
|
|
9e2b63890c | ||
|
|
ed08895d4a | ||
|
|
5b4026694d | ||
|
|
c9798ba2e9 | ||
|
|
3752551e53 | ||
|
|
a62f6f9552 | ||
|
|
e9d2e194f3 | ||
|
|
6009fffa7b | ||
|
|
fad1e5fb3c | ||
|
|
228f02c361 | ||
|
|
72c45d882b | ||
|
|
4dc7a8103b | ||
|
|
71108e1bde |
25
CHANGELOG.md
25
CHANGELOG.md
@@ -1,3 +1,28 @@
|
|||||||
|
# v4.6.2-beta
|
||||||
|
- [#1274](https://github.com/xmrig/xmrig/issues/1274) Added `--cuda-devices` command line option.
|
||||||
|
- [#1277](https://github.com/xmrig/xmrig/pull/1277) Fixed function names for clang on Apple.
|
||||||
|
|
||||||
|
# v4.6.1-beta
|
||||||
|
- [#1272](https://github.com/xmrig/xmrig/pull/1272) Optimized hashrate calculation.
|
||||||
|
- [#1273](https://github.com/xmrig/xmrig/issues/1273) Fixed crash when use `GET /2/backends` API endpoint with disabled CUDA.
|
||||||
|
|
||||||
|
# v4.6.0-beta
|
||||||
|
- [#1263](https://github.com/xmrig/xmrig/pull/1263) Added new option `dataset_host` for NVIDIA GPUs with less than 4 GB memory (RandomX only).
|
||||||
|
|
||||||
|
# v4.5.0-beta
|
||||||
|
- Added NVIDIA CUDA support via external [CUDA plugun](https://github.com/xmrig/xmrig-cuda). XMRig now is unified 3 in 1 miner.
|
||||||
|
|
||||||
|
# v4.4.0-beta
|
||||||
|
- [#1068](https://github.com/xmrig/xmrig/pull/1068) Added support for `self-select` stratum protocol extension.
|
||||||
|
- [#1240](https://github.com/xmrig/xmrig/pull/1240) Sync with the latest RandomX code.
|
||||||
|
- [#1241](https://github.com/xmrig/xmrig/issues/1241) Fixed regression with colors on old Windows systems.
|
||||||
|
- [#1243](https://github.com/xmrig/xmrig/pull/1243) Fixed incorrect OpenCL memory size detection in some cases.
|
||||||
|
- [#1247](https://github.com/xmrig/xmrig/pull/1247) Fixed ARM64 RandomX code alignment.
|
||||||
|
- [#1248](https://github.com/xmrig/xmrig/pull/1248) Fixed RandomX code cache cleanup on iOS/Darwin.
|
||||||
|
|
||||||
|
# v4.3.1-beta
|
||||||
|
- Fixed regression in v4.3.0, miner didn't create `cn` mining profile with default config example.
|
||||||
|
|
||||||
# v4.3.0-beta
|
# v4.3.0-beta
|
||||||
- [#1227](https://github.com/xmrig/xmrig/pull/1227) Added new algorithm `rx/arq`, RandomX variant for upcoming ArQmA fork.
|
- [#1227](https://github.com/xmrig/xmrig/pull/1227) Added new algorithm `rx/arq`, RandomX variant for upcoming ArQmA fork.
|
||||||
- [#808](https://github.com/xmrig/xmrig/issues/808#issuecomment-539297156) Added experimental support for persistent memory for CPU mining threads.
|
- [#808](https://github.com/xmrig/xmrig/issues/808#issuecomment-539297156) Added experimental support for persistent memory for CPU mining threads.
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ option(WITH_TLS "Enable OpenSSL support" ON)
|
|||||||
option(WITH_ASM "Enable ASM PoW implementations" ON)
|
option(WITH_ASM "Enable ASM PoW implementations" ON)
|
||||||
option(WITH_EMBEDDED_CONFIG "Enable internal embedded JSON config" OFF)
|
option(WITH_EMBEDDED_CONFIG "Enable internal embedded JSON config" OFF)
|
||||||
option(WITH_OPENCL "Enable OpenCL backend" ON)
|
option(WITH_OPENCL "Enable OpenCL backend" ON)
|
||||||
|
option(WITH_CUDA "Enable CUDA backend" ON)
|
||||||
|
option(WITH_NVML "Enable NVML (NVIDIA Management Library) support (only if CUDA backend enabled)" ON)
|
||||||
option(WITH_STRICT_CACHE "Enable strict checks for OpenCL cache" ON)
|
option(WITH_STRICT_CACHE "Enable strict checks for OpenCL cache" ON)
|
||||||
option(WITH_INTERLEAVE_DEBUG_LOG "Enable debug log for threads interleave" OFF)
|
option(WITH_INTERLEAVE_DEBUG_LOG "Enable debug log for threads interleave" OFF)
|
||||||
|
|
||||||
|
|||||||
29
README.md
29
README.md
@@ -9,19 +9,15 @@
|
|||||||
[](https://github.com/xmrig/xmrig/stargazers)
|
[](https://github.com/xmrig/xmrig/stargazers)
|
||||||
[](https://github.com/xmrig/xmrig/network)
|
[](https://github.com/xmrig/xmrig/network)
|
||||||
|
|
||||||
XMRig is a high performance RandomX and CryptoNight CPU miner, with official support for Windows.
|
XMRig High performance, open source, cross platform RandomX, CryptoNight and Argon2 CPU/GPU miner, with official support for Windows.
|
||||||
|
|
||||||
* This is the **CPU-mining** version, there is also a [NVIDIA GPU version](https://github.com/xmrig/xmrig-nvidia) and [AMD GPU version]( https://github.com/xmrig/xmrig-amd).
|
## Mining backends
|
||||||
|
- **CPU** (x64/x86/ARM)
|
||||||
|
- **OpenCL** for AMD GPUs.
|
||||||
|
- **CUDA** for NVIDIA GPUs via external [CUDA plugin](https://github.com/xmrig/xmrig-cuda).
|
||||||
|
|
||||||
<img src="doc/screenshot.png" width="808" >
|
<img src="doc/screenshot.png" width="808" >
|
||||||
|
|
||||||
#### Table of contents
|
|
||||||
* [Download](#download)
|
|
||||||
* [Usage](#usage)
|
|
||||||
* [Build](https://github.com/xmrig/xmrig/wiki/Build)
|
|
||||||
* [Donations](#donations)
|
|
||||||
* [Contacts](#contacts)
|
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
* Binary releases: https://github.com/xmrig/xmrig/releases
|
* Binary releases: https://github.com/xmrig/xmrig/releases
|
||||||
* Git tree: https://github.com/xmrig/xmrig.git
|
* Git tree: https://github.com/xmrig/xmrig.git
|
||||||
@@ -30,6 +26,9 @@ XMRig is a high performance RandomX and CryptoNight CPU miner, with official sup
|
|||||||
## Usage
|
## Usage
|
||||||
The preferred way to configure the miner is the [JSON config file](src/config.json) as it is more flexible and human friendly. The command line interface does not cover all features, such as mining profiles for different algorithms. Important options can be changed during runtime without miner restart by editing the config file or executing API calls.
|
The preferred way to configure the miner is the [JSON config file](src/config.json) as it is more flexible and human friendly. The command line interface does not cover all features, such as mining profiles for different algorithms. Important options can be changed during runtime without miner restart by editing the config file or executing API calls.
|
||||||
|
|
||||||
|
* **[xmrig.com/wizard](https://xmrig.com/wizard)** helps you create initial configuration for the miner.
|
||||||
|
* **[workers.xmrig.info](http://workers.xmrig.info)** helps manage your miners via HTTP API.
|
||||||
|
|
||||||
### Command line options
|
### Command line options
|
||||||
```
|
```
|
||||||
Network:
|
Network:
|
||||||
@@ -75,15 +74,23 @@ API:
|
|||||||
|
|
||||||
OpenCL backend:
|
OpenCL backend:
|
||||||
--opencl enable OpenCL mining backend
|
--opencl enable OpenCL mining backend
|
||||||
--opencl-devices=N list of OpenCL devices to use
|
--opencl-devices=N comma separated list of OpenCL devices to use
|
||||||
--opencl-platform=N OpenCL platform index or name
|
--opencl-platform=N OpenCL platform index or name
|
||||||
--opencl-loader=N path to OpenCL-ICD-Loader (OpenCL.dll or libOpenCL.so)
|
--opencl-loader=PATH path to OpenCL-ICD-Loader (OpenCL.dll or libOpenCL.so)
|
||||||
--opencl-no-cache disable OpenCL cache
|
--opencl-no-cache disable OpenCL cache
|
||||||
--print-platforms print available OpenCL platforms and exit
|
--print-platforms print available OpenCL platforms and exit
|
||||||
|
|
||||||
|
CUDA backend:
|
||||||
|
--cuda enable CUDA mining backend
|
||||||
|
--cuda-loader=PATH path to CUDA plugin (xmrig-cuda.dll or libxmrig-cuda.so)
|
||||||
|
--cuda-devices=N comma separated list of CUDA devices to use
|
||||||
|
--no-nvml disable NVML (NVIDIA Management Library) support
|
||||||
|
|
||||||
Logging:
|
Logging:
|
||||||
|
-S, --syslog use system log for output messages
|
||||||
-l, --log-file=FILE log all output to a file
|
-l, --log-file=FILE log all output to a file
|
||||||
--print-time=N print hashrate report every N seconds
|
--print-time=N print hashrate report every N seconds
|
||||||
|
--health-print-time=N print health report every N seconds
|
||||||
--no-color disable colored output
|
--no-color disable colored output
|
||||||
|
|
||||||
Misc:
|
Misc:
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
|||||||
|
|
||||||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
|
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
|
||||||
|
|
||||||
|
add_definitions(/DHAVE_BUILTIN_CLEAR_CACHE)
|
||||||
|
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")
|
||||||
|
|||||||
2
doc/build/CMAKE_OPTIONS.md
vendored
2
doc/build/CMAKE_OPTIONS.md
vendored
@@ -21,6 +21,8 @@ This feature add external dependency to libhwloc (1.10.0+) (except MSVC builds).
|
|||||||
* **`-DWITH_TLS=OFF`** disable SSL/TLS support (secure connections to pool). This feature add external dependency to OpenSSL.
|
* **`-DWITH_TLS=OFF`** disable SSL/TLS support (secure connections to pool). This feature add external dependency to OpenSSL.
|
||||||
* **`-DWITH_ASM=OFF`** disable assembly optimizations for modern CryptoNight algorithms.
|
* **`-DWITH_ASM=OFF`** disable assembly optimizations for modern CryptoNight algorithms.
|
||||||
* **`-DWITH_EMBEDDED_CONFIG=ON`** Enable [embedded](https://github.com/xmrig/xmrig/issues/957) config support.
|
* **`-DWITH_EMBEDDED_CONFIG=ON`** Enable [embedded](https://github.com/xmrig/xmrig/issues/957) config support.
|
||||||
|
* **`-DWITH_OPENCL=OFF`** Disable OpenCL backend.
|
||||||
|
* **`-DWITH_CUDA=OFF`** Disable CUDA backend.
|
||||||
|
|
||||||
## Debug options
|
## Debug options
|
||||||
|
|
||||||
|
|||||||
25
src/App.cpp
25
src/App.cpp
@@ -98,29 +98,12 @@ int xmrig::App::exec()
|
|||||||
|
|
||||||
void xmrig::App::onConsoleCommand(char command)
|
void xmrig::App::onConsoleCommand(char command)
|
||||||
{
|
{
|
||||||
switch (command) {
|
if (command == 3) {
|
||||||
case 'h':
|
|
||||||
case 'H':
|
|
||||||
m_controller->miner()->printHashrate(true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
case 'P':
|
|
||||||
m_controller->miner()->setEnabled(false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
case 'R':
|
|
||||||
m_controller->miner()->setEnabled(true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
LOG_WARN("Ctrl+C received, exiting");
|
LOG_WARN("Ctrl+C received, exiting");
|
||||||
close();
|
close();
|
||||||
break;
|
}
|
||||||
|
else {
|
||||||
default:
|
m_controller->miner()->execCommand(command);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <cinttypes>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -59,10 +59,10 @@ inline static const char *asmName(Assembly::Id assembly)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void print_memory(Config *) {
|
static void print_memory(Config *config) {
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s",
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s",
|
||||||
"HUGE PAGES", VirtualMemory::isHugepagesAvailable() ? GREEN_BOLD("permission granted") : RED_BOLD("unavailable"));
|
"HUGE PAGES", config->cpu().isHugePages() ? (VirtualMemory::isHugepagesAvailable() ? GREEN_BOLD("permission granted") : RED_BOLD("unavailable")) : RED_BOLD("disabled"));
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,9 +126,9 @@ static void print_threads(Config *config)
|
|||||||
static void print_commands(Config *)
|
static void print_commands(Config *)
|
||||||
{
|
{
|
||||||
if (Log::colors) {
|
if (Log::colors) {
|
||||||
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS ") MAGENTA_BOLD("h") WHITE_BOLD("ashrate, ")
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS ") MAGENTA_BG(WHITE_BOLD_S "h") WHITE_BOLD("ashrate, ")
|
||||||
MAGENTA_BOLD("p") WHITE_BOLD("ause, ")
|
MAGENTA_BG(WHITE_BOLD_S "p") WHITE_BOLD("ause, ")
|
||||||
MAGENTA_BOLD("r") WHITE_BOLD("esume"));
|
MAGENTA_BG(WHITE_BOLD_S "r") WHITE_BOLD("esume"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log::print(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume");
|
Log::print(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume");
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
include (src/backend/cpu/cpu.cmake)
|
include (src/backend/cpu/cpu.cmake)
|
||||||
include (src/backend/opencl/opencl.cmake)
|
include (src/backend/opencl/opencl.cmake)
|
||||||
|
include (src/backend/cuda/cuda.cmake)
|
||||||
include (src/backend/common/common.cmake)
|
include (src/backend/common/common.cmake)
|
||||||
|
|
||||||
|
|
||||||
@@ -7,10 +8,12 @@ set(HEADERS_BACKEND
|
|||||||
"${HEADERS_BACKEND_COMMON}"
|
"${HEADERS_BACKEND_COMMON}"
|
||||||
"${HEADERS_BACKEND_CPU}"
|
"${HEADERS_BACKEND_CPU}"
|
||||||
"${HEADERS_BACKEND_OPENCL}"
|
"${HEADERS_BACKEND_OPENCL}"
|
||||||
|
"${HEADERS_BACKEND_CUDA}"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES_BACKEND
|
set(SOURCES_BACKEND
|
||||||
"${SOURCES_BACKEND_COMMON}"
|
"${SOURCES_BACKEND_COMMON}"
|
||||||
"${SOURCES_BACKEND_CPU}"
|
"${SOURCES_BACKEND_CPU}"
|
||||||
"${SOURCES_BACKEND_OPENCL}"
|
"${SOURCES_BACKEND_OPENCL}"
|
||||||
|
"${SOURCES_BACKEND_CUDA}"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ inline static const char *format(double h, char *buf, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
xmrig::Hashrate::Hashrate(size_t threads) :
|
xmrig::Hashrate::Hashrate(size_t threads) :
|
||||||
m_highest(0.0),
|
|
||||||
m_threads(threads)
|
m_threads(threads)
|
||||||
{
|
{
|
||||||
m_counts = new uint64_t*[threads];
|
m_counts = new uint64_t*[threads];
|
||||||
@@ -100,30 +99,30 @@ double xmrig::Hashrate::calc(size_t threadId, size_t ms) const
|
|||||||
|
|
||||||
uint64_t earliestHashCount = 0;
|
uint64_t earliestHashCount = 0;
|
||||||
uint64_t earliestStamp = 0;
|
uint64_t earliestStamp = 0;
|
||||||
uint64_t lastestStamp = 0;
|
|
||||||
uint64_t lastestHashCnt = 0;
|
|
||||||
bool haveFullSet = false;
|
bool haveFullSet = false;
|
||||||
|
|
||||||
for (size_t i = 1; i < kBucketSize; i++) {
|
const uint64_t timeStampLimit = xmrig::Chrono::highResolutionMSecs() - ms;
|
||||||
const size_t idx = (m_top[threadId] - i) & kBucketMask;
|
uint64_t* timestamps = m_timestamps[threadId];
|
||||||
|
uint64_t* counts = m_counts[threadId];
|
||||||
|
|
||||||
if (m_timestamps[threadId][idx] == 0) {
|
const size_t idx_start = (m_top[threadId] - 1) & kBucketMask;
|
||||||
|
size_t idx = idx_start;
|
||||||
|
|
||||||
|
uint64_t lastestStamp = timestamps[idx];
|
||||||
|
uint64_t lastestHashCnt = counts[idx];
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (timestamps[idx] < timeStampLimit) {
|
||||||
|
haveFullSet = (timestamps[idx] != 0);
|
||||||
|
if (idx != idx_start) {
|
||||||
|
idx = (idx + 1) & kBucketMask;
|
||||||
|
earliestStamp = timestamps[idx];
|
||||||
|
earliestHashCount = counts[idx];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
idx = (idx - 1) & kBucketMask;
|
||||||
if (lastestStamp == 0) {
|
} while (idx != idx_start);
|
||||||
lastestStamp = m_timestamps[threadId][idx];
|
|
||||||
lastestHashCnt = m_counts[threadId][idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmrig::Chrono::highResolutionMSecs() - m_timestamps[threadId][idx] > ms) {
|
|
||||||
haveFullSet = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
earliestStamp = m_timestamps[threadId][idx];
|
|
||||||
earliestHashCount = m_counts[threadId][idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) {
|
if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) {
|
||||||
return nan("");
|
return nan("");
|
||||||
@@ -150,15 +149,6 @@ void xmrig::Hashrate::add(size_t threadId, uint64_t count, uint64_t timestamp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Hashrate::updateHighest()
|
|
||||||
{
|
|
||||||
double highest = calc(ShortInterval);
|
|
||||||
if (std::isnormal(highest) && highest > m_highest) {
|
|
||||||
m_highest = highest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char *xmrig::Hashrate::format(double h, char *buf, size_t size)
|
const char *xmrig::Hashrate::format(double h, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
return ::format(h, buf, size);
|
return ::format(h, buf, size);
|
||||||
|
|||||||
@@ -53,9 +53,7 @@ public:
|
|||||||
double calc(size_t ms) const;
|
double calc(size_t ms) const;
|
||||||
double calc(size_t threadId, size_t ms) const;
|
double calc(size_t threadId, size_t ms) const;
|
||||||
void add(size_t threadId, uint64_t count, uint64_t timestamp);
|
void add(size_t threadId, uint64_t count, uint64_t timestamp);
|
||||||
void updateHighest();
|
|
||||||
|
|
||||||
inline double highest() const { return m_highest; }
|
|
||||||
inline size_t threads() const { return m_threads; }
|
inline size_t threads() const { return m_threads; }
|
||||||
|
|
||||||
static const char *format(double h, char *buf, size_t size);
|
static const char *format(double h, char *buf, size_t size);
|
||||||
@@ -70,7 +68,6 @@ private:
|
|||||||
constexpr static size_t kBucketSize = 2 << 11;
|
constexpr static size_t kBucketSize = 2 << 11;
|
||||||
constexpr static size_t kBucketMask = kBucketSize - 1;
|
constexpr static size_t kBucketMask = kBucketSize - 1;
|
||||||
|
|
||||||
double m_highest;
|
|
||||||
size_t m_threads;
|
size_t m_threads;
|
||||||
uint32_t* m_top;
|
uint32_t* m_top;
|
||||||
uint64_t** m_counts;
|
uint64_t** m_counts;
|
||||||
|
|||||||
@@ -27,10 +27,15 @@
|
|||||||
#define XMRIG_TAGS_H
|
#define XMRIG_TAGS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
const char *backend_tag(uint32_t backend);
|
||||||
const char *cpu_tag();
|
const char *cpu_tag();
|
||||||
|
const char *net_tag();
|
||||||
|
|
||||||
|
|
||||||
#ifdef XMRIG_FEATURE_OPENCL
|
#ifdef XMRIG_FEATURE_OPENCL
|
||||||
@@ -38,6 +43,12 @@ const char *ocl_tag();
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_CUDA
|
||||||
|
const char *cuda_tag();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef XMRIG_ALGO_RANDOMX
|
#ifdef XMRIG_ALGO_RANDOMX
|
||||||
const char *rx_tag();
|
const char *rx_tag();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -34,6 +34,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_CUDA
|
||||||
|
# include "backend/cuda/CudaThreads.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
@@ -167,4 +172,8 @@ template class Threads<CpuThreads>;
|
|||||||
template class Threads<OclThreads>;
|
template class Threads<OclThreads>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_CUDA
|
||||||
|
template class Threads<CudaThreads>;
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace xmrig
|
} // namespace xmrig
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define XMRIG_WORKERJOB_H
|
#define XMRIG_WORKERJOB_H
|
||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
#include "base/net/stratum/Job.h"
|
#include "base/net/stratum/Job.h"
|
||||||
@@ -47,9 +47,9 @@ public:
|
|||||||
inline uint8_t index() const { return m_index; }
|
inline uint8_t index() const { return m_index; }
|
||||||
|
|
||||||
|
|
||||||
inline void add(const Job &job, uint64_t sequence, uint32_t reserveCount)
|
inline void add(const Job &job, uint32_t reserveCount, Nonce::Backend backend)
|
||||||
{
|
{
|
||||||
m_sequence = sequence;
|
m_sequence = Nonce::sequence(backend);
|
||||||
|
|
||||||
if (currentJob() == job) {
|
if (currentJob() == job) {
|
||||||
return;
|
return;
|
||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
save(job, reserveCount);
|
save(job, reserveCount, backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -82,13 +82,15 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void save(const Job &job, uint32_t reserveCount)
|
inline void save(const Job &job, uint32_t reserveCount, Nonce::Backend backend)
|
||||||
{
|
{
|
||||||
m_index = job.index();
|
m_index = job.index();
|
||||||
const size_t size = job.size();
|
const size_t size = job.size();
|
||||||
m_jobs[index()] = job;
|
m_jobs[index()] = job;
|
||||||
m_rounds[index()] = 0;
|
m_rounds[index()] = 0;
|
||||||
|
|
||||||
|
m_jobs[index()].setBackend(backend);
|
||||||
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
memcpy(m_blobs[index()] + (i * size), job.blob(), size);
|
memcpy(m_blobs[index()] + (i * size), job.blob(), size);
|
||||||
*nonce(i) = Nonce::next(index(), *nonce(i), reserveCount, job.isNicehash());
|
*nonce(i) = Nonce::next(index(), *nonce(i), reserveCount, job.isNicehash());
|
||||||
@@ -96,7 +98,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
alignas(16) uint8_t m_blobs[2][Job::kMaxBlobSize * N];
|
alignas(16) uint8_t m_blobs[2][Job::kMaxBlobSize * N]{};
|
||||||
Job m_jobs[2];
|
Job m_jobs[2];
|
||||||
uint32_t m_rounds[2] = { 0, 0 };
|
uint32_t m_rounds[2] = { 0, 0 };
|
||||||
uint64_t m_sequence = 0;
|
uint64_t m_sequence = 0;
|
||||||
@@ -126,12 +128,14 @@ inline void xmrig::WorkerJob<1>::nextRound(uint32_t rounds, uint32_t roundSize)
|
|||||||
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void xmrig::WorkerJob<1>::save(const Job &job, uint32_t reserveCount)
|
inline void xmrig::WorkerJob<1>::save(const Job &job, uint32_t reserveCount, Nonce::Backend backend)
|
||||||
{
|
{
|
||||||
m_index = job.index();
|
m_index = job.index();
|
||||||
m_jobs[index()] = job;
|
m_jobs[index()] = job;
|
||||||
m_rounds[index()] = 0;
|
m_rounds[index()] = 0;
|
||||||
|
|
||||||
|
m_jobs[index()].setBackend(backend);
|
||||||
|
|
||||||
memcpy(blob(), job.blob(), job.size());
|
memcpy(blob(), job.blob(), job.size());
|
||||||
*nonce() = Nonce::next(index(), *nonce(), reserveCount, currentJob().isNicehash());
|
*nonce() = Nonce::next(index(), *nonce(), reserveCount, currentJob().isNicehash());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_CUDA
|
||||||
|
# include "backend/cuda/CudaWorker.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
@@ -139,8 +144,6 @@ void xmrig::Workers<T>::tick(uint64_t)
|
|||||||
|
|
||||||
d_ptr->hashrate->add(handle->id(), handle->worker()->hashCount(), handle->worker()->timestamp());
|
d_ptr->hashrate->add(handle->id(), handle->worker()->hashCount(), handle->worker()->timestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
d_ptr->hashrate->updateHighest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -217,4 +220,16 @@ template class Workers<OclLaunchData>;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_CUDA
|
||||||
|
template<>
|
||||||
|
xmrig::IWorker *xmrig::Workers<CudaLaunchData>::create(Thread<CudaLaunchData> *handle)
|
||||||
|
{
|
||||||
|
return new CudaWorker(handle->id(), handle->config());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template class Workers<CudaLaunchData>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
} // namespace xmrig
|
} // namespace xmrig
|
||||||
|
|||||||
@@ -37,6 +37,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_CUDA
|
||||||
|
# include "backend/cuda/CudaLaunchData.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
@@ -80,6 +85,13 @@ extern template class Workers<OclLaunchData>;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_CUDA
|
||||||
|
template<>
|
||||||
|
IWorker *Workers<CudaLaunchData>::create(Thread<CudaLaunchData> *handle);
|
||||||
|
extern template class Workers<CudaLaunchData>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
} // namespace xmrig
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ public:
|
|||||||
virtual const Hashrate *hashrate() const = 0;
|
virtual const Hashrate *hashrate() const = 0;
|
||||||
virtual const String &profileName() const = 0;
|
virtual const String &profileName() const = 0;
|
||||||
virtual const String &type() const = 0;
|
virtual const String &type() const = 0;
|
||||||
|
virtual void execCommand(char command) = 0;
|
||||||
virtual void prepare(const Job &nextJob) = 0;
|
virtual void prepare(const Job &nextJob) = 0;
|
||||||
virtual void printHashrate(bool details) = 0;
|
virtual void printHashrate(bool details) = 0;
|
||||||
virtual void setJob(const Job &job) = 0;
|
virtual void setJob(const Job &job) = 0;
|
||||||
|
|||||||
@@ -146,10 +146,11 @@ public:
|
|||||||
|
|
||||||
inline void start()
|
inline void start()
|
||||||
{
|
{
|
||||||
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"),
|
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" thread%s)") " scratchpad " CYAN_BOLD("%zu KB"),
|
||||||
tag,
|
tag,
|
||||||
profileName.data(),
|
profileName.data(),
|
||||||
threads.size(),
|
threads.size(),
|
||||||
|
threads.size() > 1 ? "s" : "",
|
||||||
algo.l3() / 1024
|
algo.l3() / 1024
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -210,6 +211,24 @@ public:
|
|||||||
} // namespace xmrig
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::backend_tag(uint32_t backend)
|
||||||
|
{
|
||||||
|
# ifdef XMRIG_FEATURE_OPENCL
|
||||||
|
if (backend == Nonce::OPENCL) {
|
||||||
|
return ocl_tag();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_CUDA
|
||||||
|
if (backend == Nonce::CUDA) {
|
||||||
|
return cuda_tag();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *xmrig::cpu_tag()
|
const char *xmrig::cpu_tag()
|
||||||
{
|
{
|
||||||
return tag;
|
return tag;
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ public:
|
|||||||
~CpuBackend() override;
|
~CpuBackend() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
inline void execCommand(char) override {}
|
||||||
|
|
||||||
bool isEnabled() const override;
|
bool isEnabled() const override;
|
||||||
bool isEnabled(const Algorithm &algorithm) const override;
|
bool isEnabled(const Algorithm &algorithm) const override;
|
||||||
const Hashrate *hashrate() const override;
|
const Hashrate *hashrate() const override;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ size_t inline generate<Algorithm::CN>(Threads<CpuThreads> &threads, uint32_t lim
|
|||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
|
||||||
count += generate("cn", threads, Algorithm::CN_0, limit);
|
count += generate("cn", threads, Algorithm::CN_1, limit);
|
||||||
|
|
||||||
if (!threads.isExist(Algorithm::CN_0)) {
|
if (!threads.isExist(Algorithm::CN_0)) {
|
||||||
threads.disable(Algorithm::CN_0);
|
threads.disable(Algorithm::CN_0);
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ void xmrig::CpuWorker<N>::consumeJob()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_job.add(m_miner->job(), Nonce::sequence(Nonce::CPU), kReserveCount);
|
m_job.add(m_miner->job(), kReserveCount, Nonce::CPU);
|
||||||
|
|
||||||
# ifdef XMRIG_ALGO_RANDOMX
|
# ifdef XMRIG_ALGO_RANDOMX
|
||||||
if (m_job.currentJob().algorithm().family() == Algorithm::RANDOM_X) {
|
if (m_job.currentJob().algorithm().family() == Algorithm::RANDOM_X) {
|
||||||
|
|||||||
524
src/backend/cuda/CudaBackend.cpp
Normal file
524
src/backend/cuda/CudaBackend.cpp
Normal file
@@ -0,0 +1,524 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/CudaBackend.h"
|
||||||
|
#include "backend/common/Hashrate.h"
|
||||||
|
#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/CudaWorker.h"
|
||||||
|
#include "backend/cuda/wrappers/CudaDevice.h"
|
||||||
|
#include "backend/cuda/wrappers/CudaLib.h"
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
|
#include "base/net/stratum/Job.h"
|
||||||
|
#include "base/tools/Chrono.h"
|
||||||
|
#include "base/tools/String.h"
|
||||||
|
#include "core/config/Config.h"
|
||||||
|
#include "core/Controller.h"
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_API
|
||||||
|
# include "base/api/interfaces/IApiRequest.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_NVML
|
||||||
|
#include "backend/cuda/wrappers/NvmlLib.h"
|
||||||
|
|
||||||
|
namespace xmrig { static const char *kNvmlLabel = "NVML"; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
extern template class Threads<CudaThreads>;
|
||||||
|
|
||||||
|
|
||||||
|
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";
|
||||||
|
static std::mutex mutex;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void printDisabled(const char *label, const char *reason)
|
||||||
|
{
|
||||||
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") RED_BOLD("disabled") "%s", label, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct CudaLaunchStatus
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline size_t threads() const { return m_threads; }
|
||||||
|
|
||||||
|
inline bool started(bool ready)
|
||||||
|
{
|
||||||
|
ready ? m_started++ : m_errors++;
|
||||||
|
|
||||||
|
return (m_started + m_errors) == m_threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void start(size_t threads)
|
||||||
|
{
|
||||||
|
m_started = 0;
|
||||||
|
m_errors = 0;
|
||||||
|
m_threads = threads;
|
||||||
|
m_ts = Chrono::steadyMSecs();
|
||||||
|
CudaWorker::ready = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void print() const
|
||||||
|
{
|
||||||
|
if (m_started == 0) {
|
||||||
|
LOG_ERR("%s " RED_BOLD("disabled") YELLOW(" (failed to start threads)"), tag);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("%s" GREEN_BOLD(" READY") " threads " "%s%zu/%zu" BLACK_BOLD(" (%" PRIu64 " ms)"),
|
||||||
|
tag,
|
||||||
|
m_errors == 0 ? CYAN_BOLD_S : YELLOW_BOLD_S,
|
||||||
|
m_started,
|
||||||
|
m_threads,
|
||||||
|
Chrono::steadyMSecs() - m_ts
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_errors = 0;
|
||||||
|
size_t m_started = 0;
|
||||||
|
size_t m_threads = 0;
|
||||||
|
uint64_t m_ts = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CudaBackendPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline CudaBackendPrivate(Controller *controller) :
|
||||||
|
controller(controller)
|
||||||
|
{
|
||||||
|
init(controller->config()->cuda());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void init(const CudaConfig &cuda)
|
||||||
|
{
|
||||||
|
if (!cuda.isEnabled()) {
|
||||||
|
return printDisabled(kLabel, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CudaLib::init(cuda.loader())) {
|
||||||
|
return printDisabled(kLabel, RED_S " (failed to load CUDA plugin)");
|
||||||
|
}
|
||||||
|
|
||||||
|
runtimeVersion = CudaLib::runtimeVersion();
|
||||||
|
driverVersion = CudaLib::driverVersion();
|
||||||
|
|
||||||
|
if (!runtimeVersion || !driverVersion || !CudaLib::deviceCount()) {
|
||||||
|
return printDisabled(kLabel, RED_S " (no devices)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!devices.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
devices = CudaLib::devices(cuda.bfactor(), cuda.bsleep(), cuda.devicesHint());
|
||||||
|
if (devices.empty()) {
|
||||||
|
return printDisabled(kLabel, RED_S " (no devices)");
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") "/" WHITE_BOLD("%s") BLACK_BOLD("/%s"), kLabel,
|
||||||
|
CudaLib::version(runtimeVersion).c_str(), CudaLib::version(driverVersion).c_str(), CudaLib::pluginVersion());
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
if (cuda.isNvmlEnabled()) {
|
||||||
|
if (NvmlLib::init(cuda.nvmlLoader())) {
|
||||||
|
NvmlLib::assign(devices);
|
||||||
|
|
||||||
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") "/" GREEN_BOLD("%s") " press " MAGENTA_BG(WHITE_BOLD_S "e") " for health report",
|
||||||
|
kNvmlLabel,
|
||||||
|
NvmlLib::version(),
|
||||||
|
NvmlLib::driverVersion()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printDisabled(kNvmlLabel, RED_S " (failed to load NVML)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printDisabled(kNvmlLabel, "");
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
for (const CudaDevice &device : devices) {
|
||||||
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu") YELLOW(" %s") GREEN_BOLD(" %s ") WHITE_BOLD("%u/%u MHz") " smx:" WHITE_BOLD("%u") " arch:" WHITE_BOLD("%u%u") " mem:" CYAN("%zu/%zu") " MB",
|
||||||
|
"CUDA GPU",
|
||||||
|
device.index(),
|
||||||
|
device.topology().toString().data(),
|
||||||
|
device.name().data(),
|
||||||
|
device.clock(),
|
||||||
|
device.memoryClock(),
|
||||||
|
device.smx(),
|
||||||
|
device.computeCapability(true),
|
||||||
|
device.computeCapability(false),
|
||||||
|
device.freeMemSize() / oneMiB,
|
||||||
|
device.globalMemSize() / oneMiB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void start(const Job &)
|
||||||
|
{
|
||||||
|
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" thread%s)") " scratchpad " CYAN_BOLD("%zu KB"),
|
||||||
|
tag,
|
||||||
|
profileName.data(),
|
||||||
|
threads.size(),
|
||||||
|
threads.size() > 1 ? "s" : "",
|
||||||
|
algo.l3() / 1024
|
||||||
|
);
|
||||||
|
|
||||||
|
Log::print(WHITE_BOLD("| # | GPU | BUS ID | I | T | B | BF | BS | MEM | NAME"));
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (const auto &data : threads) {
|
||||||
|
Log::print("|" CYAN_BOLD("%3zu") " |" CYAN_BOLD("%4u") " |" YELLOW(" %7s") " |" CYAN_BOLD("%5d") " |" CYAN_BOLD("%4d") " |"
|
||||||
|
CYAN_BOLD("%4d") " |" CYAN_BOLD("%3d") " |" CYAN_BOLD("%4d") " |" CYAN("%5zu") " | " GREEN("%s"),
|
||||||
|
i,
|
||||||
|
data.thread.index(),
|
||||||
|
data.device.topology().toString().data(),
|
||||||
|
data.thread.threads() * data.thread.blocks(),
|
||||||
|
data.thread.threads(),
|
||||||
|
data.thread.blocks(),
|
||||||
|
data.thread.bfactor(),
|
||||||
|
data.thread.bsleep(),
|
||||||
|
(data.thread.threads() * data.thread.blocks()) * algo.l3() / oneMiB,
|
||||||
|
data.device.name().data()
|
||||||
|
);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
status.start(threads.size());
|
||||||
|
workers.start(threads);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
void printHealth()
|
||||||
|
{
|
||||||
|
for (const auto &device : devices) {
|
||||||
|
const auto health = NvmlLib::health(device.nvmlDevice());
|
||||||
|
|
||||||
|
std::string clocks;
|
||||||
|
if (health.clock && health.memClock) {
|
||||||
|
clocks += " " + std::to_string(health.clock) + "/" + std::to_string(health.memClock) + " MHz";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fans;
|
||||||
|
if (!health.fanSpeed.empty()) {
|
||||||
|
for (uint32_t i = 0; i < health.fanSpeed.size(); ++i) {
|
||||||
|
fans += " fan" + std::to_string(i) + ":" CYAN_BOLD_S + std::to_string(health.fanSpeed[i]) + "%" CLEAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO(CYAN_BOLD("#%u") YELLOW(" %s") MAGENTA_BOLD("%4uW") CSI "1;%um %2uC" CLEAR WHITE_BOLD("%s") "%s",
|
||||||
|
device.index(),
|
||||||
|
device.topology().toString().data(),
|
||||||
|
health.power,
|
||||||
|
health.temperature < 60 ? 32 : (health.temperature > 85 ? 31 : 33),
|
||||||
|
health.temperature,
|
||||||
|
clocks.c_str(),
|
||||||
|
fans.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
Algorithm algo;
|
||||||
|
Controller *controller;
|
||||||
|
CudaLaunchStatus status;
|
||||||
|
std::vector<CudaDevice> devices;
|
||||||
|
std::vector<CudaLaunchData> threads;
|
||||||
|
String profileName;
|
||||||
|
uint32_t driverVersion = 0;
|
||||||
|
uint32_t runtimeVersion = 0;
|
||||||
|
Workers<CudaLaunchData> workers;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::cuda_tag()
|
||||||
|
{
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaBackend::CudaBackend(Controller *controller) :
|
||||||
|
d_ptr(new CudaBackendPrivate(controller))
|
||||||
|
{
|
||||||
|
d_ptr->workers.setBackend(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaBackend::~CudaBackend()
|
||||||
|
{
|
||||||
|
delete d_ptr;
|
||||||
|
|
||||||
|
CudaLib::close();
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
NvmlLib::close();
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaBackend::isEnabled() const
|
||||||
|
{
|
||||||
|
return d_ptr->controller->config()->cuda().isEnabled() && CudaLib::isInitialized() && !d_ptr->devices.empty();;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaBackend::isEnabled(const Algorithm &algorithm) const
|
||||||
|
{
|
||||||
|
return !d_ptr->controller->config()->cuda().threads().get(algorithm).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const xmrig::Hashrate *xmrig::CudaBackend::hashrate() const
|
||||||
|
{
|
||||||
|
return d_ptr->workers.hashrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const xmrig::String &xmrig::CudaBackend::profileName() const
|
||||||
|
{
|
||||||
|
return d_ptr->profileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const xmrig::String &xmrig::CudaBackend::type() const
|
||||||
|
{
|
||||||
|
return kType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaBackend::execCommand(char command)
|
||||||
|
{
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
if (command == 'e' || command == 'E') {
|
||||||
|
d_ptr->printHealth();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaBackend::prepare(const Job &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaBackend::printHashrate(bool details)
|
||||||
|
{
|
||||||
|
if (!details || !hashrate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char num[8 * 3] = { 0 };
|
||||||
|
|
||||||
|
Log::print(WHITE_BOLD_S "| CUDA # | AFFINITY | 10s H/s | 60s H/s | 15m H/s |");
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (const auto &data : d_ptr->threads) {
|
||||||
|
Log::print("| %8zu | %8" PRId64 " | %7s | %7s | %7s |" CYAN_BOLD(" #%u") YELLOW(" %s") GREEN(" %s"),
|
||||||
|
i,
|
||||||
|
data.thread.affinity(),
|
||||||
|
Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval), num, sizeof num / 3),
|
||||||
|
Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval), num + 8, sizeof num / 3),
|
||||||
|
Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3),
|
||||||
|
data.device.index(),
|
||||||
|
data.device.topology().toString().data(),
|
||||||
|
data.device.name().data()
|
||||||
|
);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::print(WHITE_BOLD_S "| - | - | %7s | %7s | %7s |",
|
||||||
|
Hashrate::format(hashrate()->calc(Hashrate::ShortInterval), num, sizeof num / 3),
|
||||||
|
Hashrate::format(hashrate()->calc(Hashrate::MediumInterval), num + 8, sizeof num / 3),
|
||||||
|
Hashrate::format(hashrate()->calc(Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaBackend::setJob(const Job &job)
|
||||||
|
{
|
||||||
|
const auto &cuda = d_ptr->controller->config()->cuda();
|
||||||
|
if (cuda.isEnabled()) {
|
||||||
|
d_ptr->init(cuda);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEnabled()) {
|
||||||
|
return stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto threads = cuda.get(d_ptr->controller->miner(), job.algorithm(), d_ptr->devices);
|
||||||
|
if (!d_ptr->threads.empty() && d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d_ptr->algo = job.algorithm();
|
||||||
|
d_ptr->profileName = cuda.threads().profileName(job.algorithm());
|
||||||
|
|
||||||
|
if (d_ptr->profileName.isNull() || threads.empty()) {
|
||||||
|
LOG_WARN("%s " RED_BOLD("disabled") YELLOW(" (no suitable configuration found)"), tag);
|
||||||
|
|
||||||
|
return stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
stop();
|
||||||
|
|
||||||
|
d_ptr->threads = std::move(threads);
|
||||||
|
d_ptr->start(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaBackend::start(IWorker *worker, bool ready)
|
||||||
|
{
|
||||||
|
mutex.lock();
|
||||||
|
|
||||||
|
if (d_ptr->status.started(ready)) {
|
||||||
|
d_ptr->status.print();
|
||||||
|
|
||||||
|
CudaWorker::ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex.unlock();
|
||||||
|
|
||||||
|
if (ready) {
|
||||||
|
worker->start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaBackend::stop()
|
||||||
|
{
|
||||||
|
if (d_ptr->threads.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint64_t ts = Chrono::steadyMSecs();
|
||||||
|
|
||||||
|
d_ptr->workers.stop();
|
||||||
|
d_ptr->threads.clear();
|
||||||
|
|
||||||
|
LOG_INFO("%s" YELLOW(" stopped") BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaBackend::tick(uint64_t ticks)
|
||||||
|
{
|
||||||
|
d_ptr->workers.tick(ticks);
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
auto seconds = d_ptr->controller->config()->healthPrintTime();
|
||||||
|
if (seconds && ticks && (ticks % (seconds * 2)) == 0) {
|
||||||
|
d_ptr->printHealth();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_API
|
||||||
|
rapidjson::Value xmrig::CudaBackend::toJSON(rapidjson::Document &doc) const
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
Value out(kObjectType);
|
||||||
|
out.AddMember("type", type().toJSON(), allocator);
|
||||||
|
out.AddMember("enabled", isEnabled(), allocator);
|
||||||
|
out.AddMember("algo", d_ptr->algo.toJSON(), allocator);
|
||||||
|
out.AddMember("profile", profileName().toJSON(), allocator);
|
||||||
|
|
||||||
|
if (CudaLib::isReady()) {
|
||||||
|
Value versions(kObjectType);
|
||||||
|
versions.AddMember("cuda-runtime", Value(CudaLib::version(d_ptr->runtimeVersion).c_str(), allocator), allocator);
|
||||||
|
versions.AddMember("cuda-driver", Value(CudaLib::version(d_ptr->driverVersion).c_str(), allocator), allocator);
|
||||||
|
versions.AddMember("plugin", String(CudaLib::pluginVersion()).toJSON(doc), allocator);
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
if (NvmlLib::isReady()) {
|
||||||
|
versions.AddMember("nvml", StringRef(NvmlLib::version()), allocator);
|
||||||
|
versions.AddMember("driver", StringRef(NvmlLib::driverVersion()), allocator);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
out.AddMember("versions", versions, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d_ptr->threads.empty() || !hashrate()) {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.AddMember("hashrate", hashrate()->toJSON(doc), allocator);
|
||||||
|
|
||||||
|
Value threads(kArrayType);
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (const auto &data : d_ptr->threads) {
|
||||||
|
Value thread = data.thread.toJSON(doc);
|
||||||
|
thread.AddMember("hashrate", hashrate()->toJSON(i, doc), allocator);
|
||||||
|
|
||||||
|
data.device.toJSON(thread, doc);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
threads.PushBack(thread, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
out.AddMember("threads", threads, allocator);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaBackend::handleRequest(IApiRequest &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
80
src/backend/cuda/CudaBackend.h
Normal file
80
src/backend/cuda/CudaBackend.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDABACKEND_H
|
||||||
|
#define XMRIG_CUDABACKEND_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/common/interfaces/IBackend.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class Controller;
|
||||||
|
class CudaBackendPrivate;
|
||||||
|
class Miner;
|
||||||
|
|
||||||
|
|
||||||
|
class CudaBackend : public IBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(CudaBackend)
|
||||||
|
|
||||||
|
CudaBackend(Controller *controller);
|
||||||
|
|
||||||
|
~CudaBackend() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool isEnabled() const override;
|
||||||
|
bool isEnabled(const Algorithm &algorithm) const override;
|
||||||
|
const Hashrate *hashrate() const override;
|
||||||
|
const String &profileName() const override;
|
||||||
|
const String &type() const override;
|
||||||
|
void execCommand(char command) override;
|
||||||
|
void prepare(const Job &nextJob) override;
|
||||||
|
void printHashrate(bool details) override;
|
||||||
|
void setJob(const Job &job) override;
|
||||||
|
void start(IWorker *worker, bool ready) override;
|
||||||
|
void stop() override;
|
||||||
|
void tick(uint64_t ticks) override;
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_API
|
||||||
|
rapidjson::Value toJSON(rapidjson::Document &doc) const override;
|
||||||
|
void handleRequest(IApiRequest &request) override;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
CudaBackendPrivate *d_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_CUDABACKEND_H */
|
||||||
197
src/backend/cuda/CudaConfig.cpp
Normal file
197
src/backend/cuda/CudaConfig.cpp
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/CudaConfig.h"
|
||||||
|
#include "backend/common/Tags.h"
|
||||||
|
#include "backend/cuda/CudaConfig_gen.h"
|
||||||
|
#include "backend/cuda/wrappers/CudaLib.h"
|
||||||
|
#include "base/io/json/Json.h"
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
static bool generated = false;
|
||||||
|
static const char *kDevicesHint = "devices-hint";
|
||||||
|
static const char *kEnabled = "enabled";
|
||||||
|
static const char *kLoader = "loader";
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_NVML
|
||||||
|
static const char *kNvml = "nvml";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
extern template class Threads<CudaThreads>;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rapidjson::Value xmrig::CudaConfig::toJSON(rapidjson::Document &doc) const
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
Value obj(kObjectType);
|
||||||
|
|
||||||
|
obj.AddMember(StringRef(kEnabled), m_enabled, allocator);
|
||||||
|
obj.AddMember(StringRef(kLoader), m_loader.toJSON(), allocator);
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
if (m_nvmlLoader.isNull()) {
|
||||||
|
obj.AddMember(StringRef(kNvml), m_nvml, allocator);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj.AddMember(StringRef(kNvml), m_nvmlLoader.toJSON(), allocator);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
m_threads.toJSON(obj, doc);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<xmrig::CudaLaunchData> xmrig::CudaConfig::get(const Miner *miner, const Algorithm &algorithm, const std::vector<CudaDevice> &devices) const
|
||||||
|
{
|
||||||
|
auto deviceIndex = [&devices](uint32_t index) -> int {
|
||||||
|
for (uint32_t i = 0; i < devices.size(); ++i) {
|
||||||
|
if (devices[i].index() == index) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<CudaLaunchData> out;
|
||||||
|
const auto &threads = m_threads.get(algorithm);
|
||||||
|
|
||||||
|
if (threads.isEmpty()) {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.reserve(threads.count());
|
||||||
|
|
||||||
|
for (const auto &thread : threads.data()) {
|
||||||
|
const int index = deviceIndex(thread.index());
|
||||||
|
if (index == -1) {
|
||||||
|
LOG_INFO("%s" YELLOW(" skip non-existing device with index ") YELLOW_BOLD("%u"), cuda_tag(), thread.index());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.emplace_back(miner, algorithm, thread, devices[static_cast<size_t>(index)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
auto &nvml = Json::getValue(value, kNvml);
|
||||||
|
if (nvml.IsString()) {
|
||||||
|
m_nvmlLoader = nvml.GetString();
|
||||||
|
}
|
||||||
|
else if (nvml.IsBool()) {
|
||||||
|
m_nvml = nvml.GetBool();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
m_threads.read(value);
|
||||||
|
|
||||||
|
generate();
|
||||||
|
}
|
||||||
|
else if (value.IsBool()) {
|
||||||
|
m_enabled = value.GetBool();
|
||||||
|
|
||||||
|
generate();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_shouldSave = true;
|
||||||
|
|
||||||
|
generate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaConfig::generate()
|
||||||
|
{
|
||||||
|
if (generated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEnabled() || m_threads.has("*")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CudaLib::init(loader())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CudaLib::runtimeVersion() || !CudaLib::driverVersion() || !CudaLib::deviceCount()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto devices = CudaLib::devices(bfactor(), bsleep(), m_devicesHint);
|
||||||
|
if (devices.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
count += xmrig::generate<Algorithm::CN>(m_threads, devices);
|
||||||
|
count += xmrig::generate<Algorithm::CN_LITE>(m_threads, devices);
|
||||||
|
count += xmrig::generate<Algorithm::CN_HEAVY>(m_threads, devices);
|
||||||
|
count += xmrig::generate<Algorithm::CN_PICO>(m_threads, devices);
|
||||||
|
count += xmrig::generate<Algorithm::RANDOM_X>(m_threads, devices);
|
||||||
|
|
||||||
|
generated = true;
|
||||||
|
m_shouldSave = count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaConfig::setDevicesHint(const char *devicesHint)
|
||||||
|
{
|
||||||
|
if (devicesHint == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto indexes = String(devicesHint).split(',');
|
||||||
|
m_devicesHint.reserve(indexes.size());
|
||||||
|
|
||||||
|
for (const auto &index : indexes) {
|
||||||
|
m_devicesHint.push_back(strtoul(index, nullptr, 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/backend/cuda/CudaConfig.h
Normal file
87
src/backend/cuda/CudaConfig.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDACONFIG_H
|
||||||
|
#define XMRIG_CUDACONFIG_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/CudaLaunchData.h"
|
||||||
|
#include "backend/common/Threads.h"
|
||||||
|
#include "backend/cuda/CudaThreads.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class CudaConfig
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CudaConfig() = default;
|
||||||
|
|
||||||
|
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
||||||
|
std::vector<CudaLaunchData> get(const Miner *miner, const Algorithm &algorithm, const std::vector<CudaDevice> &devices) const;
|
||||||
|
void read(const rapidjson::Value &value);
|
||||||
|
|
||||||
|
inline bool isEnabled() const { return m_enabled; }
|
||||||
|
inline bool isShouldSave() const { return m_shouldSave; }
|
||||||
|
inline const std::vector<uint32_t> &devicesHint() const { return m_devicesHint; }
|
||||||
|
inline const String &loader() const { return m_loader; }
|
||||||
|
inline const Threads<CudaThreads> &threads() const { return m_threads; }
|
||||||
|
inline int32_t bfactor() const { return m_bfactor; }
|
||||||
|
inline int32_t bsleep() const { return m_bsleep; }
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
inline bool isNvmlEnabled() const { return m_nvml; }
|
||||||
|
inline const String &nvmlLoader() const { return m_nvmlLoader; }
|
||||||
|
# endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
void generate();
|
||||||
|
void setDevicesHint(const char *devicesHint);
|
||||||
|
|
||||||
|
bool m_enabled = false;
|
||||||
|
bool m_shouldSave = false;
|
||||||
|
std::vector<uint32_t> m_devicesHint;
|
||||||
|
String m_loader;
|
||||||
|
Threads<CudaThreads> m_threads;
|
||||||
|
|
||||||
|
# ifdef _WIN32
|
||||||
|
int32_t m_bfactor = 6;
|
||||||
|
int32_t m_bsleep = 25;
|
||||||
|
# else
|
||||||
|
int32_t m_bfactor = 0;
|
||||||
|
int32_t m_bsleep = 0;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
bool m_nvml = true;
|
||||||
|
String m_nvmlLoader;
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_CUDACONFIG_H */
|
||||||
137
src/backend/cuda/CudaConfig_gen.h
Normal file
137
src/backend/cuda/CudaConfig_gen.h
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDACONFIG_GEN_H
|
||||||
|
#define XMRIG_CUDACONFIG_GEN_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/common/Threads.h"
|
||||||
|
#include "backend/cuda/CudaThreads.h"
|
||||||
|
#include "backend/cuda/wrappers/CudaDevice.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
static inline size_t generate(const char *key, Threads<CudaThreads> &threads, const Algorithm &algorithm, const std::vector<CudaDevice> &devices)
|
||||||
|
{
|
||||||
|
if (threads.isExist(algorithm) || threads.has(key)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return threads.move(key, CudaThreads(devices, algorithm));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<Algorithm::Family FAMILY>
|
||||||
|
static inline size_t generate(Threads<CudaThreads> &, const std::vector<CudaDevice> &) { return 0; }
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
size_t inline generate<Algorithm::CN>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
count += generate("cn", threads, Algorithm::CN_1, devices);
|
||||||
|
count += generate("cn/2", threads, Algorithm::CN_2, devices);
|
||||||
|
|
||||||
|
if (!threads.isExist(Algorithm::CN_0)) {
|
||||||
|
threads.disable(Algorithm::CN_0);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef XMRIG_ALGO_CN_GPU
|
||||||
|
count += generate("cn/gpu", threads, Algorithm::CN_GPU, devices);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_ALGO_CN_LITE
|
||||||
|
template<>
|
||||||
|
size_t inline generate<Algorithm::CN_LITE>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
|
||||||
|
{
|
||||||
|
size_t count = generate("cn-lite", threads, Algorithm::CN_LITE_1, devices);
|
||||||
|
|
||||||
|
if (!threads.isExist(Algorithm::CN_LITE_0)) {
|
||||||
|
threads.disable(Algorithm::CN_LITE_0);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_ALGO_CN_HEAVY
|
||||||
|
template<>
|
||||||
|
size_t inline generate<Algorithm::CN_HEAVY>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
|
||||||
|
{
|
||||||
|
return generate("cn-heavy", threads, Algorithm::CN_HEAVY_0, devices);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_ALGO_CN_PICO
|
||||||
|
template<>
|
||||||
|
size_t inline generate<Algorithm::CN_PICO>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
|
||||||
|
{
|
||||||
|
return generate("cn-pico", threads, Algorithm::CN_PICO_0, devices);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_ALGO_RANDOMX
|
||||||
|
template<>
|
||||||
|
size_t inline generate<Algorithm::RANDOM_X>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
auto rx = CudaThreads(devices, Algorithm::RX_0);
|
||||||
|
auto wow = CudaThreads(devices, Algorithm::RX_WOW);
|
||||||
|
auto arq = CudaThreads(devices, Algorithm::RX_ARQ);
|
||||||
|
|
||||||
|
if (!threads.isExist(Algorithm::RX_WOW) && wow != rx) {
|
||||||
|
count += threads.move("rx/wow", std::move(wow));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!threads.isExist(Algorithm::RX_ARQ) && arq != rx) {
|
||||||
|
count += threads.move("rx/arq", std::move(arq));
|
||||||
|
}
|
||||||
|
|
||||||
|
count += threads.move("rx", std::move(rx));
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_CUDACONFIG_GEN_H */
|
||||||
51
src/backend/cuda/CudaLaunchData.cpp
Normal file
51
src/backend/cuda/CudaLaunchData.cpp
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/CudaLaunchData.h"
|
||||||
|
#include "backend/common/Tags.h"
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaLaunchData::CudaLaunchData(const Miner *miner, const Algorithm &algorithm, const CudaThread &thread, const CudaDevice &device) :
|
||||||
|
algorithm(algorithm),
|
||||||
|
miner(miner),
|
||||||
|
device(device),
|
||||||
|
thread(thread)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaLaunchData::isEqual(const CudaLaunchData &other) const
|
||||||
|
{
|
||||||
|
return (other.algorithm.family() == algorithm.family() &&
|
||||||
|
other.algorithm.l3() == algorithm.l3() &&
|
||||||
|
other.thread == thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::CudaLaunchData::tag()
|
||||||
|
{
|
||||||
|
return cuda_tag();
|
||||||
|
}
|
||||||
66
src/backend/cuda/CudaLaunchData.h
Normal file
66
src/backend/cuda/CudaLaunchData.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDALAUNCHDATA_H
|
||||||
|
#define XMRIG_CUDALAUNCHDATA_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/CudaThread.h"
|
||||||
|
#include "crypto/common/Algorithm.h"
|
||||||
|
#include "crypto/common/Nonce.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class CudaDevice;
|
||||||
|
class Miner;
|
||||||
|
|
||||||
|
|
||||||
|
class CudaLaunchData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CudaLaunchData(const Miner *miner, const Algorithm &algorithm, const CudaThread &thread, const CudaDevice &device);
|
||||||
|
|
||||||
|
bool isEqual(const CudaLaunchData &other) const;
|
||||||
|
|
||||||
|
inline constexpr static Nonce::Backend backend() { return Nonce::CUDA; }
|
||||||
|
|
||||||
|
inline bool operator!=(const CudaLaunchData &other) const { return !isEqual(other); }
|
||||||
|
inline bool operator==(const CudaLaunchData &other) const { return isEqual(other); }
|
||||||
|
|
||||||
|
static const char *tag();
|
||||||
|
|
||||||
|
const Algorithm algorithm;
|
||||||
|
const Miner *miner;
|
||||||
|
const CudaDevice &device;
|
||||||
|
const CudaThread thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_OCLLAUNCHDATA_H */
|
||||||
113
src/backend/cuda/CudaThread.cpp
Normal file
113
src/backend/cuda/CudaThread.cpp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/CudaThread.h"
|
||||||
|
#include "backend/cuda/wrappers/CudaLib.h"
|
||||||
|
#include "base/io/json/Json.h"
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
static const char *kAffinity = "affinity";
|
||||||
|
static const char *kBFactor = "bfactor";
|
||||||
|
static const char *kBlocks = "blocks";
|
||||||
|
static const char *kBSleep = "bsleep";
|
||||||
|
static const char *kIndex = "index";
|
||||||
|
static const char *kThreads = "threads";
|
||||||
|
static const char *kDatasetHost = "dataset_host";
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaThread::CudaThread(const rapidjson::Value &value)
|
||||||
|
{
|
||||||
|
if (!value.IsObject()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_index = Json::getUint(value, kIndex);
|
||||||
|
m_threads = Json::getInt(value, kThreads);
|
||||||
|
m_blocks = Json::getInt(value, kBlocks);
|
||||||
|
m_bfactor = std::min(Json::getUint(value, kBFactor, m_bfactor), 12u);
|
||||||
|
m_bsleep = Json::getUint(value, kBSleep, m_bsleep);
|
||||||
|
m_affinity = Json::getUint64(value, kAffinity, m_affinity);
|
||||||
|
|
||||||
|
if (Json::getValue(value, kDatasetHost).IsInt()) {
|
||||||
|
m_datasetHost = Json::getInt(value, kDatasetHost, m_datasetHost) != 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_datasetHost = Json::getBool(value, kDatasetHost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaThread::CudaThread(uint32_t index, nvid_ctx *ctx) :
|
||||||
|
m_blocks(CudaLib::deviceInt(ctx, CudaLib::DeviceBlocks)),
|
||||||
|
m_datasetHost(CudaLib::deviceInt(ctx, CudaLib::DeviceDatasetHost)),
|
||||||
|
m_threads(CudaLib::deviceInt(ctx, CudaLib::DeviceThreads)),
|
||||||
|
m_index(index),
|
||||||
|
m_bfactor(CudaLib::deviceUint(ctx, CudaLib::DeviceBFactor)),
|
||||||
|
m_bsleep(CudaLib::deviceUint(ctx, CudaLib::DeviceBSleep))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaThread::isEqual(const CudaThread &other) const
|
||||||
|
{
|
||||||
|
return m_blocks == other.m_blocks &&
|
||||||
|
m_threads == other.m_threads &&
|
||||||
|
m_affinity == other.m_affinity &&
|
||||||
|
m_index == other.m_index &&
|
||||||
|
m_bfactor == other.m_bfactor &&
|
||||||
|
m_bsleep == other.m_bsleep &&
|
||||||
|
m_datasetHost == other.m_datasetHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rapidjson::Value xmrig::CudaThread::toJSON(rapidjson::Document &doc) const
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
Value out(kObjectType);
|
||||||
|
|
||||||
|
out.AddMember(StringRef(kIndex), index(), allocator);
|
||||||
|
out.AddMember(StringRef(kThreads), threads(), allocator);
|
||||||
|
out.AddMember(StringRef(kBlocks), blocks(), allocator);
|
||||||
|
out.AddMember(StringRef(kBFactor), bfactor(), allocator);
|
||||||
|
out.AddMember(StringRef(kBSleep), bsleep(), allocator);
|
||||||
|
out.AddMember(StringRef(kAffinity), affinity(), allocator);
|
||||||
|
|
||||||
|
if (m_datasetHost >= 0) {
|
||||||
|
out.AddMember(StringRef(kDatasetHost), m_datasetHost > 0, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
81
src/backend/cuda/CudaThread.h
Normal file
81
src/backend/cuda/CudaThread.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDATHREAD_H
|
||||||
|
#define XMRIG_CUDATHREAD_H
|
||||||
|
|
||||||
|
|
||||||
|
using nvid_ctx = struct nvid_ctx;
|
||||||
|
|
||||||
|
|
||||||
|
#include "crypto/common/Algorithm.h"
|
||||||
|
#include "rapidjson/fwd.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class CudaThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CudaThread() = delete;
|
||||||
|
CudaThread(const rapidjson::Value &value);
|
||||||
|
CudaThread(uint32_t index, nvid_ctx *ctx);
|
||||||
|
|
||||||
|
inline bool isValid() const { return m_blocks > 0 && m_threads > 0; }
|
||||||
|
inline int32_t bfactor() const { return static_cast<int32_t>(m_bfactor); }
|
||||||
|
inline int32_t blocks() const { return m_blocks; }
|
||||||
|
inline int32_t bsleep() const { return static_cast<int32_t>(m_bsleep); }
|
||||||
|
inline int32_t datasetHost() const { return m_datasetHost; }
|
||||||
|
inline int32_t threads() const { return m_threads; }
|
||||||
|
inline int64_t affinity() const { return m_affinity; }
|
||||||
|
inline uint32_t index() const { return m_index; }
|
||||||
|
|
||||||
|
inline bool operator!=(const CudaThread &other) const { return !isEqual(other); }
|
||||||
|
inline bool operator==(const CudaThread &other) const { return isEqual(other); }
|
||||||
|
|
||||||
|
bool isEqual(const CudaThread &other) const;
|
||||||
|
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t m_blocks = 0;
|
||||||
|
int32_t m_datasetHost = -1;
|
||||||
|
int32_t m_threads = 0;
|
||||||
|
int64_t m_affinity = -1;
|
||||||
|
uint32_t m_index = 0;
|
||||||
|
|
||||||
|
# ifdef _WIN32
|
||||||
|
uint32_t m_bfactor = 6;
|
||||||
|
uint32_t m_bsleep = 25;
|
||||||
|
# else
|
||||||
|
uint32_t m_bfactor = 0;
|
||||||
|
uint32_t m_bsleep = 0;
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_CUDATHREAD_H */
|
||||||
79
src/backend/cuda/CudaThreads.cpp
Normal file
79
src/backend/cuda/CudaThreads.cpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/CudaThreads.h"
|
||||||
|
#include "base/io/json/Json.h"
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaThreads::CudaThreads(const rapidjson::Value &value)
|
||||||
|
{
|
||||||
|
if (value.IsArray()) {
|
||||||
|
for (auto &v : value.GetArray()) {
|
||||||
|
CudaThread thread(v);
|
||||||
|
if (thread.isValid()) {
|
||||||
|
add(std::move(thread));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaThreads::CudaThreads(const std::vector<CudaDevice> &devices, const Algorithm &algorithm)
|
||||||
|
{
|
||||||
|
for (const auto &device : devices) {
|
||||||
|
device.generate(algorithm, *this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaThreads::isEqual(const CudaThreads &other) const
|
||||||
|
{
|
||||||
|
if (isEmpty() && other.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count() == other.count() && std::equal(m_data.begin(), m_data.end(), other.m_data.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rapidjson::Value xmrig::CudaThreads::toJSON(rapidjson::Document &doc) const
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
Value out(kArrayType);
|
||||||
|
|
||||||
|
out.SetArray();
|
||||||
|
|
||||||
|
for (const CudaThread &thread : m_data) {
|
||||||
|
out.PushBack(thread.toJSON(doc), allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
66
src/backend/cuda/CudaThreads.h
Normal file
66
src/backend/cuda/CudaThreads.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDATHREADS_H
|
||||||
|
#define XMRIG_CUDATHREADS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/CudaThread.h"
|
||||||
|
#include "backend/cuda/wrappers/CudaDevice.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class CudaThreads
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CudaThreads() = default;
|
||||||
|
CudaThreads(const rapidjson::Value &value);
|
||||||
|
CudaThreads(const std::vector<CudaDevice> &devices, const Algorithm &algorithm);
|
||||||
|
|
||||||
|
inline bool isEmpty() const { return m_data.empty(); }
|
||||||
|
inline const std::vector<CudaThread> &data() const { return m_data; }
|
||||||
|
inline size_t count() const { return m_data.size(); }
|
||||||
|
inline void add(CudaThread &&thread) { m_data.push_back(thread); }
|
||||||
|
inline void reserve(size_t capacity) { m_data.reserve(capacity); }
|
||||||
|
|
||||||
|
inline bool operator!=(const CudaThreads &other) const { return !isEqual(other); }
|
||||||
|
inline bool operator==(const CudaThreads &other) const { return isEqual(other); }
|
||||||
|
|
||||||
|
bool isEqual(const CudaThreads &other) const;
|
||||||
|
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<CudaThread> m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_CUDATHREADS_H */
|
||||||
171
src/backend/cuda/CudaWorker.cpp
Normal file
171
src/backend/cuda/CudaWorker.cpp
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/CudaWorker.h"
|
||||||
|
#include "backend/common/Tags.h"
|
||||||
|
#include "backend/cuda/runners/CudaCnRunner.h"
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
|
#include "base/tools/Chrono.h"
|
||||||
|
#include "core/Miner.h"
|
||||||
|
#include "crypto/common/Nonce.h"
|
||||||
|
#include "net/JobResults.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_ALGO_RANDOMX
|
||||||
|
# include "backend/cuda/runners/CudaRxRunner.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr uint32_t kReserveCount = 32768;
|
||||||
|
std::atomic<bool> CudaWorker::ready;
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool isReady() { return !Nonce::isPaused() && CudaWorker::ready; }
|
||||||
|
static inline uint32_t roundSize(uint32_t intensity) { return kReserveCount / intensity + 1; }
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaWorker::CudaWorker(size_t id, const CudaLaunchData &data) :
|
||||||
|
Worker(id, data.thread.affinity(), -1),
|
||||||
|
m_algorithm(data.algorithm),
|
||||||
|
m_miner(data.miner)
|
||||||
|
{
|
||||||
|
switch (m_algorithm.family()) {
|
||||||
|
case Algorithm::RANDOM_X:
|
||||||
|
# ifdef XMRIG_ALGO_RANDOMX
|
||||||
|
m_runner = new CudaRxRunner(id, data);
|
||||||
|
# endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Algorithm::ARGON2:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
m_runner = new CudaCnRunner(id, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_runner || !m_runner->init()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaWorker::~CudaWorker()
|
||||||
|
{
|
||||||
|
delete m_runner;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaWorker::selfTest()
|
||||||
|
{
|
||||||
|
return m_runner != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t xmrig::CudaWorker::intensity() const
|
||||||
|
{
|
||||||
|
return m_runner ? m_runner->intensity() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaWorker::start()
|
||||||
|
{
|
||||||
|
while (Nonce::sequence(Nonce::CUDA) > 0) {
|
||||||
|
if (!isReady()) {
|
||||||
|
do {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||||
|
}
|
||||||
|
while (!isReady() && Nonce::sequence(Nonce::CUDA) > 0);
|
||||||
|
|
||||||
|
if (Nonce::sequence(Nonce::CUDA) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!consumeJob()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!Nonce::isOutdated(Nonce::CUDA, m_job.sequence())) {
|
||||||
|
uint32_t foundNonce[10] = { 0 };
|
||||||
|
uint32_t foundCount = 0;
|
||||||
|
|
||||||
|
if (!m_runner->run(*m_job.nonce(), &foundCount, foundNonce)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundCount) {
|
||||||
|
JobResults::submit(m_job.currentJob(), foundNonce, foundCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t batch_size = intensity();
|
||||||
|
m_job.nextRound(roundSize(batch_size), batch_size);
|
||||||
|
|
||||||
|
storeStats();
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!consumeJob()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaWorker::consumeJob()
|
||||||
|
{
|
||||||
|
if (Nonce::sequence(Nonce::CUDA) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t batch_size = intensity();
|
||||||
|
m_job.add(m_miner->job(), roundSize(batch_size) * batch_size, Nonce::CUDA);
|
||||||
|
|
||||||
|
return m_runner->set(m_job.currentJob(), m_job.blob());;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaWorker::storeStats()
|
||||||
|
{
|
||||||
|
if (!isReady()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_count += intensity();
|
||||||
|
|
||||||
|
Worker::storeStats();
|
||||||
|
}
|
||||||
73
src/backend/cuda/CudaWorker.h
Normal file
73
src/backend/cuda/CudaWorker.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDAWORKER_H
|
||||||
|
#define XMRIG_CUDAWORKER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/common/Worker.h"
|
||||||
|
#include "backend/common/WorkerJob.h"
|
||||||
|
#include "backend/cuda/CudaLaunchData.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
|
#include "net/JobResult.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class ICudaRunner;
|
||||||
|
|
||||||
|
|
||||||
|
class CudaWorker : public Worker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(CudaWorker)
|
||||||
|
|
||||||
|
CudaWorker(size_t id, const CudaLaunchData &data);
|
||||||
|
|
||||||
|
~CudaWorker() override;
|
||||||
|
|
||||||
|
static std::atomic<bool> ready;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool selfTest() override;
|
||||||
|
size_t intensity() const override;
|
||||||
|
void start() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool consumeJob();
|
||||||
|
void storeStats();
|
||||||
|
|
||||||
|
const Algorithm m_algorithm;
|
||||||
|
const Miner *m_miner;
|
||||||
|
ICudaRunner *m_runner = nullptr;
|
||||||
|
WorkerJob<1> m_job;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_CUDAWORKER_H */
|
||||||
53
src/backend/cuda/cuda.cmake
Normal file
53
src/backend/cuda/cuda.cmake
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
if (WITH_CUDA)
|
||||||
|
add_definitions(/DXMRIG_FEATURE_CUDA)
|
||||||
|
|
||||||
|
set(HEADERS_BACKEND_CUDA
|
||||||
|
src/backend/cuda/CudaBackend.h
|
||||||
|
src/backend/cuda/CudaConfig_gen.h
|
||||||
|
src/backend/cuda/CudaConfig.h
|
||||||
|
src/backend/cuda/CudaLaunchData.h
|
||||||
|
src/backend/cuda/CudaThread.h
|
||||||
|
src/backend/cuda/CudaThreads.h
|
||||||
|
src/backend/cuda/CudaWorker.h
|
||||||
|
src/backend/cuda/interfaces/ICudaRunner.h
|
||||||
|
src/backend/cuda/runners/CudaBaseRunner.h
|
||||||
|
src/backend/cuda/runners/CudaCnRunner.h
|
||||||
|
src/backend/cuda/runners/CudaRxRunner.h
|
||||||
|
src/backend/cuda/wrappers/CudaDevice.h
|
||||||
|
src/backend/cuda/wrappers/CudaLib.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SOURCES_BACKEND_CUDA
|
||||||
|
src/backend/cuda/CudaBackend.cpp
|
||||||
|
src/backend/cuda/CudaConfig.cpp
|
||||||
|
src/backend/cuda/CudaLaunchData.cpp
|
||||||
|
src/backend/cuda/CudaThread.cpp
|
||||||
|
src/backend/cuda/CudaThreads.cpp
|
||||||
|
src/backend/cuda/CudaWorker.cpp
|
||||||
|
src/backend/cuda/runners/CudaBaseRunner.cpp
|
||||||
|
src/backend/cuda/runners/CudaCnRunner.cpp
|
||||||
|
src/backend/cuda/runners/CudaRxRunner.cpp
|
||||||
|
src/backend/cuda/wrappers/CudaDevice.cpp
|
||||||
|
src/backend/cuda/wrappers/CudaLib.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
if (WITH_NVML AND NOT APPLE)
|
||||||
|
add_definitions(/DXMRIG_FEATURE_NVML)
|
||||||
|
|
||||||
|
list(APPEND HEADERS_BACKEND_CUDA
|
||||||
|
src/backend/cuda/wrappers/nvml_lite.h
|
||||||
|
src/backend/cuda/wrappers/NvmlHealth.h
|
||||||
|
src/backend/cuda/wrappers/NvmlLib.h
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND SOURCES_BACKEND_CUDA src/backend/cuda/wrappers/NvmlLib.cpp)
|
||||||
|
else()
|
||||||
|
remove_definitions(/DXMRIG_FEATURE_NVML)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
remove_definitions(/DXMRIG_FEATURE_CUDA)
|
||||||
|
remove_definitions(/DXMRIG_FEATURE_NVML)
|
||||||
|
|
||||||
|
set(HEADERS_BACKEND_CUDA "")
|
||||||
|
set(SOURCES_BACKEND_CUDA "")
|
||||||
|
endif()
|
||||||
71
src/backend/cuda/interfaces/ICudaRunner.h
Normal file
71
src/backend/cuda/interfaces/ICudaRunner.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_ICUDARUNNER_H
|
||||||
|
#define XMRIG_ICUDARUNNER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/tools/Object.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class Job;
|
||||||
|
|
||||||
|
|
||||||
|
class ICudaRunner
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE(ICudaRunner)
|
||||||
|
|
||||||
|
ICudaRunner() = default;
|
||||||
|
virtual ~ICudaRunner() = default;
|
||||||
|
|
||||||
|
// virtual cl_context ctx() const = 0;
|
||||||
|
// virtual const Algorithm &algorithm() const = 0;
|
||||||
|
// virtual const char *buildOptions() const = 0;
|
||||||
|
// virtual const char *deviceKey() const = 0;
|
||||||
|
// virtual const char *source() const = 0;
|
||||||
|
// virtual const OclLaunchData &data() const = 0;
|
||||||
|
virtual size_t intensity() const = 0;
|
||||||
|
// virtual size_t threadId() const = 0;
|
||||||
|
// virtual uint32_t deviceIndex() const = 0;
|
||||||
|
// virtual void build() = 0;
|
||||||
|
virtual bool init() = 0;
|
||||||
|
virtual bool run(uint32_t startNonce, uint32_t *rescount, uint32_t *resnonce) = 0;
|
||||||
|
virtual bool set(const Job &job, uint8_t *blob) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// virtual size_t bufferSize() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XMRIG_ICUDARUNNER_H
|
||||||
83
src/backend/cuda/runners/CudaBaseRunner.cpp
Normal file
83
src/backend/cuda/runners/CudaBaseRunner.cpp
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/runners/CudaBaseRunner.h"
|
||||||
|
#include "backend/cuda/wrappers/CudaLib.h"
|
||||||
|
#include "backend/cuda/CudaLaunchData.h"
|
||||||
|
#include "backend/common/Tags.h"
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
|
#include "base/net/stratum/Job.h"
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaBaseRunner::CudaBaseRunner(size_t id, const CudaLaunchData &data) :
|
||||||
|
m_data(data),
|
||||||
|
m_threadId(id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaBaseRunner::~CudaBaseRunner()
|
||||||
|
{
|
||||||
|
CudaLib::release(m_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaBaseRunner::init()
|
||||||
|
{
|
||||||
|
m_ctx = CudaLib::alloc(m_data.thread.index(), m_data.thread.bfactor(), m_data.thread.bsleep());
|
||||||
|
if (CudaLib::deviceInfo(m_ctx, m_data.thread.blocks(), m_data.thread.threads(), m_data.algorithm, m_data.thread.datasetHost()) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return callWrapper(CudaLib::deviceInit(m_ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaBaseRunner::set(const Job &job, uint8_t *blob)
|
||||||
|
{
|
||||||
|
m_height = job.height();
|
||||||
|
m_target = job.target();
|
||||||
|
|
||||||
|
return callWrapper(CudaLib::setJob(m_ctx, blob, job.size(), job.algorithm()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t xmrig::CudaBaseRunner::intensity() const
|
||||||
|
{
|
||||||
|
return m_data.thread.threads() * m_data.thread.blocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaBaseRunner::callWrapper(bool result) const
|
||||||
|
{
|
||||||
|
if (!result) {
|
||||||
|
const char *error = CudaLib::lastError(m_ctx);
|
||||||
|
if (error) {
|
||||||
|
LOG_ERR("%s" RED_S " thread " RED_BOLD("#%zu") RED_S " failed with error " RED_BOLD("%s"), cuda_tag(), m_threadId, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
68
src/backend/cuda/runners/CudaBaseRunner.h
Normal file
68
src/backend/cuda/runners/CudaBaseRunner.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDABASERUNNER_H
|
||||||
|
#define XMRIG_CUDABASERUNNER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/interfaces/ICudaRunner.h"
|
||||||
|
|
||||||
|
|
||||||
|
using nvid_ctx = struct nvid_ctx;
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class CudaLaunchData;
|
||||||
|
|
||||||
|
|
||||||
|
class CudaBaseRunner : public ICudaRunner
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(CudaBaseRunner)
|
||||||
|
|
||||||
|
CudaBaseRunner(size_t id, const CudaLaunchData &data);
|
||||||
|
~CudaBaseRunner() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool init() override;
|
||||||
|
bool set(const Job &job, uint8_t *blob) override;
|
||||||
|
size_t intensity() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool callWrapper(bool result) const;
|
||||||
|
|
||||||
|
const CudaLaunchData &m_data;
|
||||||
|
const size_t m_threadId;
|
||||||
|
nvid_ctx *m_ctx = nullptr;
|
||||||
|
uint64_t m_height = 0;
|
||||||
|
uint64_t m_target = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XMRIG_CUDABASERUNNER_H
|
||||||
38
src/backend/cuda/runners/CudaCnRunner.cpp
Normal file
38
src/backend/cuda/runners/CudaCnRunner.cpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/runners/CudaCnRunner.h"
|
||||||
|
#include "backend/cuda/wrappers/CudaLib.h"
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaCnRunner::CudaCnRunner(size_t index, const CudaLaunchData &data) : CudaBaseRunner(index, data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaCnRunner::run(uint32_t startNonce, uint32_t *rescount, uint32_t *resnonce)
|
||||||
|
{
|
||||||
|
return callWrapper(CudaLib::cnHash(m_ctx, startNonce, m_height, m_target, rescount, resnonce));
|
||||||
|
}
|
||||||
48
src/backend/cuda/runners/CudaCnRunner.h
Normal file
48
src/backend/cuda/runners/CudaCnRunner.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDACNRUNNER_H
|
||||||
|
#define XMRIG_CUDACNRUNNER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/runners/CudaBaseRunner.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class CudaCnRunner : public CudaBaseRunner
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CudaCnRunner(size_t index, const CudaLaunchData &data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool run(uint32_t startNonce, uint32_t *rescount, uint32_t *resnonce) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XMRIG_CUDACNRUNNER_H
|
||||||
66
src/backend/cuda/runners/CudaRxRunner.cpp
Normal file
66
src/backend/cuda/runners/CudaRxRunner.cpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/runners/CudaRxRunner.h"
|
||||||
|
#include "backend/cuda/CudaLaunchData.h"
|
||||||
|
#include "backend/cuda/wrappers/CudaLib.h"
|
||||||
|
#include "base/net/stratum/Job.h"
|
||||||
|
#include "crypto/rx/Rx.h"
|
||||||
|
#include "crypto/rx/RxDataset.h"
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaRxRunner::CudaRxRunner(size_t index, const CudaLaunchData &data) : CudaBaseRunner(index, data),
|
||||||
|
m_datasetHost(data.thread.datasetHost() > 0)
|
||||||
|
{
|
||||||
|
m_intensity = m_data.thread.threads() * m_data.thread.blocks();
|
||||||
|
const size_t scratchpads_size = m_intensity * m_data.algorithm.l3();
|
||||||
|
const size_t num_scratchpads = scratchpads_size / m_data.algorithm.l3();
|
||||||
|
|
||||||
|
if (m_intensity > num_scratchpads) {
|
||||||
|
m_intensity = num_scratchpads;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_intensity -= m_intensity % 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaRxRunner::run(uint32_t startNonce, uint32_t *rescount, uint32_t *resnonce)
|
||||||
|
{
|
||||||
|
return callWrapper(CudaLib::rxHash(m_ctx, startNonce, m_target, rescount, resnonce));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaRxRunner::set(const Job &job, uint8_t *blob)
|
||||||
|
{
|
||||||
|
const bool rc = CudaBaseRunner::set(job, blob);
|
||||||
|
if (!rc || m_ready) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dataset = Rx::dataset(job, 0);
|
||||||
|
m_ready = callWrapper(CudaLib::rxPrepare(m_ctx, dataset->raw(), dataset->size(false), m_datasetHost, m_intensity));
|
||||||
|
|
||||||
|
return m_ready;
|
||||||
|
}
|
||||||
56
src/backend/cuda/runners/CudaRxRunner.h
Normal file
56
src/backend/cuda/runners/CudaRxRunner.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDARXRUNNER_H
|
||||||
|
#define XMRIG_CUDARXRUNNER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/runners/CudaBaseRunner.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class CudaRxRunner : public CudaBaseRunner
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CudaRxRunner(size_t index, const CudaLaunchData &data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
inline size_t intensity() const override { return m_intensity; }
|
||||||
|
|
||||||
|
bool run(uint32_t startNonce, uint32_t *rescount, uint32_t *resnonce) override;
|
||||||
|
bool set(const Job &job, uint8_t *blob) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_ready = false;
|
||||||
|
const bool m_datasetHost = false;
|
||||||
|
size_t m_intensity = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XMRIG_CUDARXRUNNER_H
|
||||||
152
src/backend/cuda/wrappers/CudaDevice.cpp
Normal file
152
src/backend/cuda/wrappers/CudaDevice.cpp
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/wrappers/CudaDevice.h"
|
||||||
|
#include "backend/cuda/CudaThreads.h"
|
||||||
|
#include "backend/cuda/wrappers/CudaLib.h"
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
|
#include "crypto/common/Algorithm.h"
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_NVML
|
||||||
|
# include "backend/cuda/wrappers/NvmlLib.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaDevice::CudaDevice(uint32_t index, int32_t bfactor, int32_t bsleep) :
|
||||||
|
m_index(index)
|
||||||
|
{
|
||||||
|
auto ctx = CudaLib::alloc(index, bfactor, bsleep);
|
||||||
|
if (CudaLib::deviceInfo(ctx, 0, 0, Algorithm::INVALID) != 0) {
|
||||||
|
CudaLib::release(ctx);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ctx = ctx;
|
||||||
|
m_name = CudaLib::deviceName(ctx);
|
||||||
|
m_topology = PciTopology(CudaLib::deviceUint(ctx, CudaLib::DevicePciBusID), CudaLib::deviceUint(ctx, CudaLib::DevicePciDeviceID), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaDevice::CudaDevice(CudaDevice &&other) noexcept :
|
||||||
|
m_index(other.m_index),
|
||||||
|
m_ctx(other.m_ctx),
|
||||||
|
m_topology(other.m_topology),
|
||||||
|
m_name(std::move(other.m_name))
|
||||||
|
{
|
||||||
|
other.m_ctx = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::CudaDevice::~CudaDevice()
|
||||||
|
{
|
||||||
|
CudaLib::release(m_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t xmrig::CudaDevice::freeMemSize() const
|
||||||
|
{
|
||||||
|
return CudaLib::deviceUlong(m_ctx, CudaLib::DeviceMemoryFree);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t xmrig::CudaDevice::globalMemSize() const
|
||||||
|
{
|
||||||
|
return CudaLib::deviceUlong(m_ctx, CudaLib::DeviceMemoryTotal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t xmrig::CudaDevice::clock() const
|
||||||
|
{
|
||||||
|
return CudaLib::deviceUint(m_ctx, CudaLib::DeviceClockRate) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t xmrig::CudaDevice::computeCapability(bool major) const
|
||||||
|
{
|
||||||
|
return CudaLib::deviceUint(m_ctx, major ? CudaLib::DeviceArchMajor : CudaLib::DeviceArchMinor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t xmrig::CudaDevice::memoryClock() const
|
||||||
|
{
|
||||||
|
return CudaLib::deviceUint(m_ctx, CudaLib::DeviceMemoryClockRate) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t xmrig::CudaDevice::smx() const
|
||||||
|
{
|
||||||
|
return CudaLib::deviceUint(m_ctx, CudaLib::DeviceSmx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaDevice::generate(const Algorithm &algorithm, CudaThreads &threads) const
|
||||||
|
{
|
||||||
|
if (CudaLib::deviceInfo(m_ctx, -1, -1, algorithm) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
threads.add(CudaThread(m_index, m_ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_API
|
||||||
|
void xmrig::CudaDevice::toJSON(rapidjson::Value &out, rapidjson::Document &doc) const
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
out.AddMember("name", name().toJSON(doc), allocator);
|
||||||
|
out.AddMember("bus_id", topology().toString().toJSON(doc), allocator);
|
||||||
|
out.AddMember("smx", smx(), allocator);
|
||||||
|
out.AddMember("arch", arch(), allocator);
|
||||||
|
out.AddMember("global_mem", static_cast<uint64_t>(globalMemSize()), allocator);
|
||||||
|
out.AddMember("clock", clock(), allocator);
|
||||||
|
out.AddMember("memory_clock", memoryClock(), allocator);
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
if (m_nvmlDevice) {
|
||||||
|
auto data = NvmlLib::health(m_nvmlDevice);
|
||||||
|
|
||||||
|
Value health(kObjectType);
|
||||||
|
health.AddMember("temperature", data.temperature, allocator);
|
||||||
|
health.AddMember("power", data.power, allocator);
|
||||||
|
health.AddMember("clock", data.clock, allocator);
|
||||||
|
health.AddMember("mem_clock", data.memClock, allocator);
|
||||||
|
|
||||||
|
Value fanSpeed(kArrayType);
|
||||||
|
for (auto speed : data.fanSpeed) {
|
||||||
|
fanSpeed.PushBack(speed, allocator);
|
||||||
|
}
|
||||||
|
health.AddMember("fan_speed", fanSpeed, allocator);
|
||||||
|
|
||||||
|
out.AddMember("health", health, allocator);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
94
src/backend/cuda/wrappers/CudaDevice.h
Normal file
94
src/backend/cuda/wrappers/CudaDevice.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDADEVICE_H
|
||||||
|
#define XMRIG_CUDADEVICE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/common/misc/PciTopology.h"
|
||||||
|
#include "base/tools/String.h"
|
||||||
|
|
||||||
|
|
||||||
|
using nvid_ctx = struct nvid_ctx;
|
||||||
|
using nvmlDevice_t = struct nvmlDevice_st *;
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class Algorithm;
|
||||||
|
class CudaThreads;
|
||||||
|
|
||||||
|
|
||||||
|
class CudaDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CudaDevice() = delete;
|
||||||
|
CudaDevice(const CudaDevice &other) = delete;
|
||||||
|
CudaDevice(CudaDevice &&other) noexcept;
|
||||||
|
CudaDevice(uint32_t index, int32_t bfactor, int32_t bsleep);
|
||||||
|
~CudaDevice();
|
||||||
|
|
||||||
|
size_t freeMemSize() const;
|
||||||
|
size_t globalMemSize() const;
|
||||||
|
uint32_t clock() const;
|
||||||
|
uint32_t computeCapability(bool major = true) const;
|
||||||
|
uint32_t memoryClock() const;
|
||||||
|
uint32_t smx() const;
|
||||||
|
void generate(const Algorithm &algorithm, CudaThreads &threads) const;
|
||||||
|
|
||||||
|
inline bool isValid() const { return m_ctx != nullptr; }
|
||||||
|
inline const PciTopology &topology() const { return m_topology; }
|
||||||
|
inline const String &name() const { return m_name; }
|
||||||
|
inline uint32_t arch() const { return (computeCapability(true) * 10) + computeCapability(false); }
|
||||||
|
inline uint32_t index() const { return m_index; }
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
inline nvmlDevice_t nvmlDevice() const { return m_nvmlDevice; }
|
||||||
|
inline void setNvmlDevice(nvmlDevice_t device) { m_nvmlDevice = device; }
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_API
|
||||||
|
void toJSON(rapidjson::Value &out, rapidjson::Document &doc) const;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
CudaDevice &operator=(const CudaDevice &other) = delete;
|
||||||
|
CudaDevice &operator=(CudaDevice &&other) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint32_t m_index = 0;
|
||||||
|
nvid_ctx *m_ctx = nullptr;
|
||||||
|
PciTopology m_topology;
|
||||||
|
String m_name;
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_NVML
|
||||||
|
nvmlDevice_t m_nvmlDevice = nullptr;
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_CUDADEVICE_H */
|
||||||
330
src/backend/cuda/wrappers/CudaLib.cpp
Normal file
330
src/backend/cuda/wrappers/CudaLib.cpp
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/wrappers/CudaLib.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
enum Version : uint32_t
|
||||||
|
{
|
||||||
|
ApiVersion,
|
||||||
|
DriverVersion,
|
||||||
|
RuntimeVersion
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static uv_lib_t cudaLib;
|
||||||
|
|
||||||
|
|
||||||
|
static const char *kAlloc = "alloc";
|
||||||
|
static const char *kCnHash = "cnHash";
|
||||||
|
static const char *kDeviceCount = "deviceCount";
|
||||||
|
static const char *kDeviceInfo = "deviceInfo";
|
||||||
|
static const char *kDeviceInit = "deviceInit";
|
||||||
|
static const char *kDeviceInt = "deviceInt";
|
||||||
|
static const char *kDeviceName = "deviceName";
|
||||||
|
static const char *kDeviceUint = "deviceUint";
|
||||||
|
static const char *kDeviceUlong = "deviceUlong";
|
||||||
|
static const char *kInit = "init";
|
||||||
|
static const char *kLastError = "lastError";
|
||||||
|
static const char *kPluginVersion = "pluginVersion";
|
||||||
|
static const char *kRelease = "release";
|
||||||
|
static const char *kRxHash = "rxHash";
|
||||||
|
static const char *kRxPrepare = "rxPrepare";
|
||||||
|
static const char *kSetJob = "setJob";
|
||||||
|
static const char *kSymbolNotFound = "symbol not found";
|
||||||
|
static const char *kVersion = "version";
|
||||||
|
|
||||||
|
|
||||||
|
using alloc_t = nvid_ctx * (*)(uint32_t, int32_t, int32_t);
|
||||||
|
using cnHash_t = bool (*)(nvid_ctx *, uint32_t, uint64_t, uint64_t, uint32_t *, uint32_t *);
|
||||||
|
using deviceCount_t = uint32_t (*)();
|
||||||
|
using deviceInfo_t = int32_t (*)(nvid_ctx *, int32_t, int32_t, int32_t, int32_t);
|
||||||
|
using deviceInit_t = bool (*)(nvid_ctx *);
|
||||||
|
using deviceInt_t = int32_t (*)(nvid_ctx *, CudaLib::DeviceProperty);
|
||||||
|
using deviceName_t = const char * (*)(nvid_ctx *);
|
||||||
|
using deviceUint_t = uint32_t (*)(nvid_ctx *, CudaLib::DeviceProperty);
|
||||||
|
using deviceUlong_t = uint64_t (*)(nvid_ctx *, CudaLib::DeviceProperty);
|
||||||
|
using init_t = void (*)();
|
||||||
|
using lastError_t = const char * (*)(nvid_ctx *);
|
||||||
|
using pluginVersion_t = const char * (*)();
|
||||||
|
using release_t = void (*)(nvid_ctx *);
|
||||||
|
using rxHash_t = bool (*)(nvid_ctx *, uint32_t, uint64_t, uint32_t *, uint32_t *);
|
||||||
|
using rxPrepare_t = bool (*)(nvid_ctx *, const void *, size_t, bool, uint32_t);
|
||||||
|
using setJob_t = bool (*)(nvid_ctx *, const void *, size_t, int32_t);
|
||||||
|
using version_t = uint32_t (*)(Version);
|
||||||
|
|
||||||
|
|
||||||
|
static alloc_t pAlloc = nullptr;
|
||||||
|
static cnHash_t pCnHash = nullptr;
|
||||||
|
static deviceCount_t pDeviceCount = nullptr;
|
||||||
|
static deviceInfo_t pDeviceInfo = nullptr;
|
||||||
|
static deviceInit_t pDeviceInit = nullptr;
|
||||||
|
static deviceInt_t pDeviceInt = nullptr;
|
||||||
|
static deviceName_t pDeviceName = nullptr;
|
||||||
|
static deviceUint_t pDeviceUint = nullptr;
|
||||||
|
static deviceUlong_t pDeviceUlong = nullptr;
|
||||||
|
static init_t pInit = nullptr;
|
||||||
|
static lastError_t pLastError = nullptr;
|
||||||
|
static pluginVersion_t pPluginVersion = nullptr;
|
||||||
|
static release_t pRelease = nullptr;
|
||||||
|
static rxHash_t pRxHash = nullptr;
|
||||||
|
static rxPrepare_t pRxPrepare = nullptr;
|
||||||
|
static setJob_t pSetJob = nullptr;
|
||||||
|
static version_t pVersion = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
#define DLSYM(x) if (uv_dlsym(&cudaLib, k##x, reinterpret_cast<void**>(&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() noexcept
|
||||||
|
{
|
||||||
|
return uv_dlerror(&cudaLib);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaLib::close()
|
||||||
|
{
|
||||||
|
uv_dlclose(&cudaLib);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaLib::cnHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t height, uint64_t target, uint32_t *rescount, uint32_t *resnonce)
|
||||||
|
{
|
||||||
|
return pCnHash(ctx, startNonce, height, target, rescount, resnonce);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaLib::deviceInit(nvid_ctx *ctx) noexcept
|
||||||
|
{
|
||||||
|
return pDeviceInit(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaLib::rxHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t target, uint32_t *rescount, uint32_t *resnonce) noexcept
|
||||||
|
{
|
||||||
|
return pRxHash(ctx, startNonce, target, rescount, resnonce);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaLib::rxPrepare(nvid_ctx *ctx, const void *dataset, size_t datasetSize, bool dataset_host, uint32_t batchSize) noexcept
|
||||||
|
{
|
||||||
|
return pRxPrepare(ctx, dataset, datasetSize, dataset_host, batchSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaLib::setJob(nvid_ctx *ctx, const void *data, size_t size, const Algorithm &algorithm) noexcept
|
||||||
|
{
|
||||||
|
return pSetJob(ctx, data, size, algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::CudaLib::deviceName(nvid_ctx *ctx) noexcept
|
||||||
|
{
|
||||||
|
return pDeviceName(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::CudaLib::lastError(nvid_ctx *ctx) noexcept
|
||||||
|
{
|
||||||
|
return pLastError(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::CudaLib::pluginVersion() noexcept
|
||||||
|
{
|
||||||
|
return pPluginVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xmrig::CudaLib::deviceInfo(nvid_ctx *ctx, int32_t blocks, int32_t threads, const Algorithm &algorithm, int32_t dataset_host) noexcept
|
||||||
|
{
|
||||||
|
return pDeviceInfo(ctx, blocks, threads, algorithm, dataset_host);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t xmrig::CudaLib::deviceInt(nvid_ctx *ctx, DeviceProperty property) noexcept
|
||||||
|
{
|
||||||
|
return pDeviceInt(ctx, property);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nvid_ctx *xmrig::CudaLib::alloc(uint32_t id, int32_t bfactor, int32_t bsleep) noexcept
|
||||||
|
{
|
||||||
|
return pAlloc(id, bfactor, bsleep);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string xmrig::CudaLib::version(uint32_t version)
|
||||||
|
{
|
||||||
|
return std::to_string(version / 1000) + "." + std::to_string((version % 1000) / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<xmrig::CudaDevice> xmrig::CudaLib::devices(int32_t bfactor, int32_t bsleep, const std::vector<uint32_t> &hints) noexcept
|
||||||
|
{
|
||||||
|
const uint32_t count = deviceCount();
|
||||||
|
if (!count) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CudaDevice> out;
|
||||||
|
out.reserve(count);
|
||||||
|
|
||||||
|
if (hints.empty()) {
|
||||||
|
for (uint32_t i = 0; i < count; ++i) {
|
||||||
|
CudaDevice device(i, bfactor, bsleep);
|
||||||
|
if (device.isValid()) {
|
||||||
|
out.emplace_back(std::move(device));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (const uint32_t i : hints) {
|
||||||
|
if (i >= count) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CudaDevice device(i, bfactor, bsleep);
|
||||||
|
if (device.isValid()) {
|
||||||
|
out.emplace_back(std::move(device));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t xmrig::CudaLib::deviceCount() noexcept
|
||||||
|
{
|
||||||
|
return pDeviceCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t xmrig::CudaLib::deviceUint(nvid_ctx *ctx, DeviceProperty property) noexcept
|
||||||
|
{
|
||||||
|
return pDeviceUint(ctx, property);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t xmrig::CudaLib::driverVersion() noexcept
|
||||||
|
{
|
||||||
|
return pVersion(DriverVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t xmrig::CudaLib::runtimeVersion() noexcept
|
||||||
|
{
|
||||||
|
return pVersion(RuntimeVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t xmrig::CudaLib::deviceUlong(nvid_ctx *ctx, DeviceProperty property) noexcept
|
||||||
|
{
|
||||||
|
return pDeviceUlong(ctx, property);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::CudaLib::release(nvid_ctx *ctx) noexcept
|
||||||
|
{
|
||||||
|
pRelease(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::CudaLib::load()
|
||||||
|
{
|
||||||
|
if (uv_dlsym(&cudaLib, kVersion, reinterpret_cast<void**>(&pVersion)) == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pVersion(ApiVersion) != 2u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
DLSYM(Alloc);
|
||||||
|
DLSYM(CnHash);
|
||||||
|
DLSYM(DeviceCount);
|
||||||
|
DLSYM(DeviceInfo);
|
||||||
|
DLSYM(DeviceInit);
|
||||||
|
DLSYM(DeviceInt);
|
||||||
|
DLSYM(DeviceName);
|
||||||
|
DLSYM(DeviceUint);
|
||||||
|
DLSYM(DeviceUlong);
|
||||||
|
DLSYM(Init);
|
||||||
|
DLSYM(LastError);
|
||||||
|
DLSYM(PluginVersion);
|
||||||
|
DLSYM(Release);
|
||||||
|
DLSYM(RxHash);
|
||||||
|
DLSYM(RxPrepare);
|
||||||
|
DLSYM(SetJob);
|
||||||
|
DLSYM(Version);
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInit();
|
||||||
|
|
||||||
|
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 "libxmrig-cuda.so";
|
||||||
|
# endif
|
||||||
|
}
|
||||||
109
src/backend/cuda/wrappers/CudaLib.h
Normal file
109
src/backend/cuda/wrappers/CudaLib.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_CUDALIB_H
|
||||||
|
#define XMRIG_CUDALIB_H
|
||||||
|
|
||||||
|
|
||||||
|
using nvid_ctx = struct nvid_ctx;
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/wrappers/CudaDevice.h"
|
||||||
|
#include "base/tools/String.h"
|
||||||
|
#include "crypto/common/Algorithm.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class CudaLib
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum DeviceProperty : uint32_t
|
||||||
|
{
|
||||||
|
DeviceId,
|
||||||
|
DeviceAlgorithm,
|
||||||
|
DeviceArchMajor,
|
||||||
|
DeviceArchMinor,
|
||||||
|
DeviceSmx,
|
||||||
|
DeviceBlocks,
|
||||||
|
DeviceThreads,
|
||||||
|
DeviceBFactor,
|
||||||
|
DeviceBSleep,
|
||||||
|
DeviceClockRate,
|
||||||
|
DeviceMemoryClockRate,
|
||||||
|
DeviceMemoryTotal,
|
||||||
|
DeviceMemoryFree,
|
||||||
|
DevicePciBusID,
|
||||||
|
DevicePciDeviceID,
|
||||||
|
DevicePciDomainID,
|
||||||
|
DeviceDatasetHost,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool init(const char *fileName = nullptr);
|
||||||
|
static const char *lastError() noexcept;
|
||||||
|
static void close();
|
||||||
|
|
||||||
|
static inline bool isInitialized() { return m_initialized; }
|
||||||
|
static inline bool isReady() noexcept { return m_ready; }
|
||||||
|
static inline const String &loader() { return m_loader; }
|
||||||
|
|
||||||
|
static bool cnHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t height, uint64_t target, uint32_t *rescount, uint32_t *resnonce);
|
||||||
|
static bool deviceInit(nvid_ctx *ctx) noexcept;
|
||||||
|
static bool rxHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t target, uint32_t *rescount, uint32_t *resnonce) noexcept;
|
||||||
|
static bool rxPrepare(nvid_ctx *ctx, const void *dataset, size_t datasetSize, bool dataset_host, uint32_t batchSize) noexcept;
|
||||||
|
static bool setJob(nvid_ctx *ctx, const void *data, size_t size, const Algorithm &algorithm) noexcept;
|
||||||
|
static const char *deviceName(nvid_ctx *ctx) noexcept;
|
||||||
|
static const char *lastError(nvid_ctx *ctx) noexcept;
|
||||||
|
static const char *pluginVersion() noexcept;
|
||||||
|
static int deviceInfo(nvid_ctx *ctx, int32_t blocks, int32_t threads, const Algorithm &algorithm, int32_t dataset_host = -1) noexcept;
|
||||||
|
static int32_t deviceInt(nvid_ctx *ctx, DeviceProperty property) noexcept;
|
||||||
|
static nvid_ctx *alloc(uint32_t id, int32_t bfactor, int32_t bsleep) noexcept;
|
||||||
|
static std::string version(uint32_t version);
|
||||||
|
static std::vector<CudaDevice> devices(int32_t bfactor, int32_t bsleep, const std::vector<uint32_t> &hints) noexcept;
|
||||||
|
static uint32_t deviceCount() noexcept;
|
||||||
|
static uint32_t deviceUint(nvid_ctx *ctx, DeviceProperty property) noexcept;
|
||||||
|
static uint32_t driverVersion() noexcept;
|
||||||
|
static uint32_t runtimeVersion() noexcept;
|
||||||
|
static uint64_t deviceUlong(nvid_ctx *ctx, DeviceProperty property) 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 */
|
||||||
43
src/backend/cuda/wrappers/NvmlHealth.h
Normal file
43
src/backend/cuda/wrappers/NvmlHealth.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_NVMLHEALTH_H
|
||||||
|
#define XMRIG_NVMLHEALTH_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
struct NvmlHealth
|
||||||
|
{
|
||||||
|
std::vector<uint32_t> fanSpeed;
|
||||||
|
uint32_t clock = 0;
|
||||||
|
uint32_t memClock = 0;
|
||||||
|
uint32_t power = 0;
|
||||||
|
uint32_t temperature = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_NVMLHEALTH_H */
|
||||||
227
src/backend/cuda/wrappers/NvmlLib.cpp
Normal file
227
src/backend/cuda/wrappers/NvmlLib.cpp
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/wrappers/NvmlLib.h"
|
||||||
|
#include "backend/cuda/wrappers/nvml_lite.h"
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
static uv_lib_t nvmlLib;
|
||||||
|
|
||||||
|
|
||||||
|
static const char *kNvmlDeviceGetClockInfo = "nvmlDeviceGetClockInfo";
|
||||||
|
static const char *kNvmlDeviceGetCount = "nvmlDeviceGetCount_v2";
|
||||||
|
static const char *kNvmlDeviceGetFanSpeed = "nvmlDeviceGetFanSpeed";
|
||||||
|
static const char *kNvmlDeviceGetFanSpeed_v2 = "nvmlDeviceGetFanSpeed_v2";
|
||||||
|
static const char *kNvmlDeviceGetHandleByIndex = "nvmlDeviceGetHandleByIndex_v2";
|
||||||
|
static const char *kNvmlDeviceGetPciInfo = "nvmlDeviceGetPciInfo_v2";
|
||||||
|
static const char *kNvmlDeviceGetPowerUsage = "nvmlDeviceGetPowerUsage";
|
||||||
|
static const char *kNvmlDeviceGetTemperature = "nvmlDeviceGetTemperature";
|
||||||
|
static const char *kNvmlInit = "nvmlInit_v2";
|
||||||
|
static const char *kNvmlShutdown = "nvmlShutdown";
|
||||||
|
static const char *kNvmlSystemGetDriverVersion = "nvmlSystemGetDriverVersion";
|
||||||
|
static const char *kNvmlSystemGetNVMLVersion = "nvmlSystemGetNVMLVersion";
|
||||||
|
static const char *kSymbolNotFound = "symbol not found";
|
||||||
|
|
||||||
|
|
||||||
|
static nvmlReturn_t (*pNvmlDeviceGetClockInfo)(nvmlDevice_t device, uint32_t type, uint32_t *clock) = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlDeviceGetCount)(uint32_t *deviceCount) = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlDeviceGetFanSpeed_v2)(nvmlDevice_t device, uint32_t fan, uint32_t *speed) = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlDeviceGetFanSpeed)(nvmlDevice_t device, uint32_t *speed) = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlDeviceGetHandleByIndex)(uint32_t index, nvmlDevice_t *device) = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlDeviceGetPciInfo)(nvmlDevice_t device, nvmlPciInfo_t *pci) = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlDeviceGetPowerUsage)(nvmlDevice_t device, uint32_t *power) = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlDeviceGetTemperature)(nvmlDevice_t device, uint32_t sensorType, uint32_t *temp) = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlInit)() = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlShutdown)() = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlSystemGetDriverVersion)(char *version, uint32_t length) = nullptr;
|
||||||
|
static nvmlReturn_t (*pNvmlSystemGetNVMLVersion)(char *version, uint32_t length) = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
#define DLSYM(x) if (uv_dlsym(&nvmlLib, k##x, reinterpret_cast<void**>(&p##x)) == -1) { throw std::runtime_error(kSymbolNotFound); }
|
||||||
|
|
||||||
|
|
||||||
|
bool NvmlLib::m_initialized = false;
|
||||||
|
bool NvmlLib::m_ready = false;
|
||||||
|
char NvmlLib::m_driverVersion[80] = { 0 };
|
||||||
|
char NvmlLib::m_nvmlVersion[80] = { 0 };
|
||||||
|
String NvmlLib::m_loader;
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::NvmlLib::init(const char *fileName)
|
||||||
|
{
|
||||||
|
if (!m_initialized) {
|
||||||
|
m_loader = fileName;
|
||||||
|
m_ready = dlopen() && load();
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *xmrig::NvmlLib::lastError() noexcept
|
||||||
|
{
|
||||||
|
return uv_dlerror(&nvmlLib);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::NvmlLib::close()
|
||||||
|
{
|
||||||
|
if (m_ready) {
|
||||||
|
pNvmlShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_dlclose(&nvmlLib);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::NvmlLib::assign(std::vector<CudaDevice> &devices)
|
||||||
|
{
|
||||||
|
uint32_t count = 0;
|
||||||
|
if (pNvmlDeviceGetCount(&count) != NVML_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
nvmlDevice_t nvmlDevice;
|
||||||
|
if (pNvmlDeviceGetHandleByIndex(i, &nvmlDevice) != NVML_SUCCESS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvmlPciInfo_t pci;
|
||||||
|
if (pNvmlDeviceGetPciInfo(nvmlDevice, &pci) != NVML_SUCCESS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &device : devices) {
|
||||||
|
if (device.topology().bus() == pci.bus && device.topology().device() == pci.device) {
|
||||||
|
device.setNvmlDevice(nvmlDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NvmlHealth xmrig::NvmlLib::health(nvmlDevice_t device)
|
||||||
|
{
|
||||||
|
if (!device) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
NvmlHealth health;
|
||||||
|
pNvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &health.temperature);
|
||||||
|
pNvmlDeviceGetPowerUsage(device, &health.power);
|
||||||
|
pNvmlDeviceGetClockInfo(device, NVML_CLOCK_SM, &health.clock);
|
||||||
|
pNvmlDeviceGetClockInfo(device, NVML_CLOCK_MEM, &health.memClock);
|
||||||
|
|
||||||
|
if (health.power) {
|
||||||
|
health.power /= 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t speed = 0;
|
||||||
|
|
||||||
|
if (pNvmlDeviceGetFanSpeed_v2) {
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
while (pNvmlDeviceGetFanSpeed_v2(device, i, &speed) == NVML_SUCCESS) {
|
||||||
|
health.fanSpeed.push_back(speed);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pNvmlDeviceGetFanSpeed(device, &speed);
|
||||||
|
|
||||||
|
health.fanSpeed.push_back(speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return health;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::NvmlLib::dlopen()
|
||||||
|
{
|
||||||
|
if (!m_loader.isNull()) {
|
||||||
|
return uv_dlopen(m_loader, &nvmlLib) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef _WIN32
|
||||||
|
if (uv_dlopen("nvml.dll", &nvmlLib) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char path[MAX_PATH] = { 0 };
|
||||||
|
ExpandEnvironmentStringsA("%PROGRAMFILES%\\NVIDIA Corporation\\NVSMI\\nvml.dll", path, sizeof(path));
|
||||||
|
|
||||||
|
return uv_dlopen(path, &nvmlLib) == 0;
|
||||||
|
# else
|
||||||
|
return uv_dlopen("libnvidia-ml.so", &nvmlLib) == 0;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::NvmlLib::load()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
DLSYM(NvmlDeviceGetClockInfo);
|
||||||
|
DLSYM(NvmlDeviceGetCount);
|
||||||
|
DLSYM(NvmlDeviceGetFanSpeed);
|
||||||
|
DLSYM(NvmlDeviceGetHandleByIndex);
|
||||||
|
DLSYM(NvmlDeviceGetPciInfo);
|
||||||
|
DLSYM(NvmlDeviceGetPowerUsage);
|
||||||
|
DLSYM(NvmlDeviceGetTemperature);
|
||||||
|
DLSYM(NvmlInit);
|
||||||
|
DLSYM(NvmlShutdown);
|
||||||
|
DLSYM(NvmlSystemGetDriverVersion);
|
||||||
|
DLSYM(NvmlSystemGetNVMLVersion);
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_dlsym(&nvmlLib, kNvmlDeviceGetFanSpeed_v2, reinterpret_cast<void**>(&pNvmlDeviceGetFanSpeed_v2));
|
||||||
|
|
||||||
|
if (pNvmlInit() != NVML_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pNvmlSystemGetDriverVersion(m_driverVersion, sizeof(m_driverVersion));
|
||||||
|
pNvmlSystemGetNVMLVersion(m_nvmlVersion, sizeof(m_nvmlVersion));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
66
src/backend/cuda/wrappers/NvmlLib.h
Normal file
66
src/backend/cuda/wrappers/NvmlLib.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_NVMLLIB_H
|
||||||
|
#define XMRIG_NVMLLIB_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "backend/cuda/wrappers/CudaDevice.h"
|
||||||
|
#include "backend/cuda/wrappers/NvmlHealth.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class NvmlLib
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool init(const char *fileName = nullptr);
|
||||||
|
static const char *lastError() noexcept;
|
||||||
|
static void close();
|
||||||
|
|
||||||
|
static bool assign(std::vector<CudaDevice> &devices);
|
||||||
|
static NvmlHealth health(nvmlDevice_t device);
|
||||||
|
|
||||||
|
static inline bool isInitialized() noexcept { return m_initialized; }
|
||||||
|
static inline bool isReady() noexcept { return m_ready; }
|
||||||
|
static inline const char *driverVersion() noexcept { return m_driverVersion; }
|
||||||
|
static inline const char *version() noexcept { return m_nvmlVersion; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool dlopen();
|
||||||
|
static bool load();
|
||||||
|
|
||||||
|
static bool m_initialized;
|
||||||
|
static bool m_ready;
|
||||||
|
static char m_driverVersion[80];
|
||||||
|
static char m_nvmlVersion[80];
|
||||||
|
static String m_loader;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_NVMLLIB_H */
|
||||||
55
src/backend/cuda/wrappers/nvml_lite.h
Normal file
55
src/backend/cuda/wrappers/nvml_lite.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2019 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_NVML_LITE_H
|
||||||
|
#define XMRIG_NVML_LITE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
|
#define NVML_SUCCESS 0
|
||||||
|
#define NVML_TEMPERATURE_GPU 0
|
||||||
|
#define NVML_CLOCK_SM 1
|
||||||
|
#define NVML_CLOCK_MEM 2
|
||||||
|
|
||||||
|
|
||||||
|
using nvmlReturn_t = uint32_t;
|
||||||
|
using nvmlDevice_t = struct nvmlDevice_st *;
|
||||||
|
|
||||||
|
|
||||||
|
struct nvmlPciInfo_t
|
||||||
|
{
|
||||||
|
char busIdLegacy[16]{};
|
||||||
|
unsigned int domain = 0;
|
||||||
|
unsigned int bus = 0;
|
||||||
|
unsigned int device = 0;
|
||||||
|
unsigned int pciDeviceId = 0;
|
||||||
|
unsigned int pciSubSystemId = 0;
|
||||||
|
|
||||||
|
char busId[32]{};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_NVML_LITE_H */
|
||||||
@@ -153,7 +153,8 @@ public:
|
|||||||
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu ") WHITE_BOLD("%s") "/" WHITE_BOLD("%s"), "OPENCL", platform.index(), platform.name().data(), platform.version().data());
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu ") WHITE_BOLD("%s") "/" WHITE_BOLD("%s"), "OPENCL", platform.index(), platform.name().data(), platform.version().data());
|
||||||
|
|
||||||
for (const OclDevice &device : devices) {
|
for (const OclDevice &device : devices) {
|
||||||
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu") YELLOW(" %s") " %s " WHITE_BOLD("%uMHz") " cu:" WHITE_BOLD("%u") " mem:" CYAN("%zu/%zu") " MB", "OPENCL GPU",
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu") YELLOW(" %s") " %s " WHITE_BOLD("%u MHz") " cu:" WHITE_BOLD("%u") " mem:" CYAN("%zu/%zu") " MB",
|
||||||
|
"OPENCL GPU",
|
||||||
device.index(),
|
device.index(),
|
||||||
device.topology().toString().data(),
|
device.topology().toString().data(),
|
||||||
device.printableName().data(),
|
device.printableName().data(),
|
||||||
@@ -167,10 +168,11 @@ public:
|
|||||||
|
|
||||||
inline void start(const Job &job)
|
inline void start(const Job &job)
|
||||||
{
|
{
|
||||||
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"),
|
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" thread%s)") " scratchpad " CYAN_BOLD("%zu KB"),
|
||||||
tag,
|
tag,
|
||||||
profileName.data(),
|
profileName.data(),
|
||||||
threads.size(),
|
threads.size(),
|
||||||
|
threads.size() > 1 ? "s" : "",
|
||||||
algo.l3() / 1024
|
algo.l3() / 1024
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -284,7 +286,7 @@ void xmrig::OclBackend::printHashrate(bool details)
|
|||||||
Log::print(WHITE_BOLD_S "| OPENCL # | AFFINITY | 10s H/s | 60s H/s | 15m H/s |");
|
Log::print(WHITE_BOLD_S "| OPENCL # | AFFINITY | 10s H/s | 60s H/s | 15m H/s |");
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (const OclLaunchData &data : d_ptr->threads) {
|
for (const auto &data : d_ptr->threads) {
|
||||||
Log::print("| %8zu | %8" PRId64 " | %7s | %7s | %7s |" CYAN_BOLD(" #%u") YELLOW(" %s") " %s",
|
Log::print("| %8zu | %8" PRId64 " | %7s | %7s | %7s |" CYAN_BOLD(" #%u") YELLOW(" %s") " %s",
|
||||||
i,
|
i,
|
||||||
data.affinity,
|
data.affinity,
|
||||||
@@ -309,7 +311,7 @@ void xmrig::OclBackend::printHashrate(bool details)
|
|||||||
|
|
||||||
void xmrig::OclBackend::setJob(const Job &job)
|
void xmrig::OclBackend::setJob(const Job &job)
|
||||||
{
|
{
|
||||||
const OclConfig &cl = d_ptr->controller->config()->cl();
|
const auto &cl = d_ptr->controller->config()->cl();
|
||||||
if (cl.isEnabled()) {
|
if (cl.isEnabled()) {
|
||||||
d_ptr->init(cl);
|
d_ptr->init(cl);
|
||||||
}
|
}
|
||||||
@@ -318,7 +320,7 @@ void xmrig::OclBackend::setJob(const Job &job)
|
|||||||
return stop();
|
return stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<OclLaunchData> threads = cl.get(d_ptr->controller->miner(), job.algorithm(), d_ptr->platform, d_ptr->devices, tag);
|
auto threads = cl.get(d_ptr->controller->miner(), job.algorithm(), d_ptr->platform, d_ptr->devices);
|
||||||
if (!d_ptr->threads.empty() && d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) {
|
if (!d_ptr->threads.empty() && d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -408,7 +410,7 @@ rapidjson::Value xmrig::OclBackend::toJSON(rapidjson::Document &doc) const
|
|||||||
Value threads(kArrayType);
|
Value threads(kArrayType);
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (const OclLaunchData &data : d_ptr->threads) {
|
for (const auto &data : d_ptr->threads) {
|
||||||
Value thread = data.thread.toJSON(doc);
|
Value thread = data.thread.toJSON(doc);
|
||||||
thread.AddMember("affinity", data.affinity, allocator);
|
thread.AddMember("affinity", data.affinity, allocator);
|
||||||
thread.AddMember("hashrate", hashrate()->toJSON(i, doc), allocator);
|
thread.AddMember("hashrate", hashrate()->toJSON(i, doc), allocator);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "backend/common/interfaces/IBackend.h"
|
#include "backend/common/interfaces/IBackend.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -43,17 +44,15 @@ class Miner;
|
|||||||
class OclBackend : public IBackend
|
class OclBackend : public IBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OclBackend() = delete;
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(OclBackend)
|
||||||
OclBackend(const OclBackend &other) = delete;
|
|
||||||
OclBackend(Controller *controller);
|
OclBackend(Controller *controller);
|
||||||
OclBackend(OclBackend &&other) = delete;
|
|
||||||
|
|
||||||
~OclBackend() override;
|
~OclBackend() override;
|
||||||
|
|
||||||
OclBackend &operator=(const OclBackend &other) = delete;
|
|
||||||
OclBackend &operator=(OclBackend &&other) = delete;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
inline void execCommand(char) override {}
|
||||||
|
|
||||||
bool isEnabled() const override;
|
bool isEnabled() const override;
|
||||||
bool isEnabled(const Algorithm &algorithm) const override;
|
bool isEnabled(const Algorithm &algorithm) const override;
|
||||||
const Hashrate *hashrate() const override;
|
const Hashrate *hashrate() const override;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "backend/opencl/OclConfig.h"
|
#include "backend/opencl/OclConfig.h"
|
||||||
|
#include "backend/common/Tags.h"
|
||||||
#include "backend/opencl/OclConfig_gen.h"
|
#include "backend/opencl/OclConfig_gen.h"
|
||||||
#include "backend/opencl/wrappers/OclLib.h"
|
#include "backend/opencl/wrappers/OclLib.h"
|
||||||
#include "base/io/json/Json.h"
|
#include "base/io/json/Json.h"
|
||||||
@@ -113,10 +114,10 @@ rapidjson::Value xmrig::OclConfig::toJSON(rapidjson::Document &doc) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<xmrig::OclLaunchData> xmrig::OclConfig::get(const Miner *miner, const Algorithm &algorithm, const OclPlatform &platform, const std::vector<OclDevice> &devices, const char *tag) const
|
std::vector<xmrig::OclLaunchData> xmrig::OclConfig::get(const Miner *miner, const Algorithm &algorithm, const OclPlatform &platform, const std::vector<OclDevice> &devices) const
|
||||||
{
|
{
|
||||||
std::vector<OclLaunchData> out;
|
std::vector<OclLaunchData> out;
|
||||||
const OclThreads &threads = m_threads.get(algorithm);
|
const auto &threads = m_threads.get(algorithm);
|
||||||
|
|
||||||
if (threads.isEmpty()) {
|
if (threads.isEmpty()) {
|
||||||
return out;
|
return out;
|
||||||
@@ -124,9 +125,9 @@ std::vector<xmrig::OclLaunchData> xmrig::OclConfig::get(const Miner *miner, cons
|
|||||||
|
|
||||||
out.reserve(threads.count() * 2);
|
out.reserve(threads.count() * 2);
|
||||||
|
|
||||||
for (const OclThread &thread : threads.data()) {
|
for (const auto &thread : threads.data()) {
|
||||||
if (thread.index() >= devices.size()) {
|
if (thread.index() >= devices.size()) {
|
||||||
LOG_INFO("%s" YELLOW(" skip non-existing device with index ") YELLOW_BOLD("%u"), tag, thread.index());
|
LOG_INFO("%s" YELLOW(" skip non-existing device with index ") YELLOW_BOLD("%u"), ocl_tag(), thread.index());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
OclPlatform platform() const;
|
OclPlatform platform() const;
|
||||||
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
||||||
std::vector<OclLaunchData> get(const Miner *miner, const Algorithm &algorithm, const OclPlatform &platform, const std::vector<OclDevice> &devices, const char *tag) const;
|
std::vector<OclLaunchData> get(const Miner *miner, const Algorithm &algorithm, const OclPlatform &platform, const std::vector<OclDevice> &devices) const;
|
||||||
void read(const rapidjson::Value &value);
|
void read(const rapidjson::Value &value);
|
||||||
|
|
||||||
inline bool isCacheEnabled() const { return m_cache; }
|
inline bool isCacheEnabled() const { return m_cache; }
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ size_t inline generate<Algorithm::CN>(Threads<OclThreads> &threads, const std::v
|
|||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
|
||||||
count += generate("cn", threads, Algorithm::CN_0, devices);
|
count += generate("cn", threads, Algorithm::CN_1, devices);
|
||||||
count += generate("cn/2", threads, Algorithm::CN_2, devices);
|
count += generate("cn/2", threads, Algorithm::CN_2, devices);
|
||||||
|
|
||||||
if (!threads.isExist(Algorithm::CN_0)) {
|
if (!threads.isExist(Algorithm::CN_0)) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ xmrig::OclThreads::OclThreads(const rapidjson::Value &value)
|
|||||||
|
|
||||||
xmrig::OclThreads::OclThreads(const std::vector<OclDevice> &devices, const Algorithm &algorithm)
|
xmrig::OclThreads::OclThreads(const std::vector<OclDevice> &devices, const Algorithm &algorithm)
|
||||||
{
|
{
|
||||||
for (const OclDevice &device : devices) {
|
for (const auto &device : devices) {
|
||||||
device.generate(algorithm, *this);
|
device.generate(algorithm, *this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ bool xmrig::OclWorker::consumeJob()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_job.add(m_miner->job(), Nonce::sequence(Nonce::OPENCL), roundSize(m_intensity) * m_intensity);
|
m_job.add(m_miner->job(), roundSize(m_intensity) * m_intensity, Nonce::OPENCL);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m_runner->set(m_job.currentJob(), m_job.blob());
|
m_runner->set(m_job.currentJob(), m_job.blob());
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "backend/common/Worker.h"
|
#include "backend/common/Worker.h"
|
||||||
#include "backend/common/WorkerJob.h"
|
#include "backend/common/WorkerJob.h"
|
||||||
#include "backend/opencl/OclLaunchData.h"
|
#include "backend/opencl/OclLaunchData.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
#include "net/JobResult.h"
|
#include "net/JobResult.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -42,16 +43,12 @@ class IOclRunner;
|
|||||||
class OclWorker : public Worker
|
class OclWorker : public Worker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OclWorker() = delete;
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(OclWorker)
|
||||||
OclWorker(const OclWorker &other) = delete;
|
|
||||||
OclWorker(OclWorker &&other) = delete;
|
|
||||||
OclWorker(size_t id, const OclLaunchData &data);
|
OclWorker(size_t id, const OclLaunchData &data);
|
||||||
|
|
||||||
~OclWorker() override;
|
~OclWorker() override;
|
||||||
|
|
||||||
OclWorker &operator=(const OclWorker &other) = delete;
|
|
||||||
OclWorker &operator=(OclWorker &&other) = delete;
|
|
||||||
|
|
||||||
static std::atomic<bool> ready;
|
static std::atomic<bool> ready;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ constexpr size_t oneGiB = 1024 * 1024 * 1024;
|
|||||||
|
|
||||||
|
|
||||||
xmrig::OclBaseRunner::OclBaseRunner(size_t id, const OclLaunchData &data) :
|
xmrig::OclBaseRunner::OclBaseRunner(size_t id, const OclLaunchData &data) :
|
||||||
m_algorithm(data.algorithm),
|
|
||||||
m_ctx(data.ctx),
|
m_ctx(data.ctx),
|
||||||
|
m_algorithm(data.algorithm),
|
||||||
m_source(OclSource::get(data.algorithm)),
|
m_source(OclSource::get(data.algorithm)),
|
||||||
m_data(data),
|
m_data(data),
|
||||||
m_align(OclLib::getUint(data.device.id(), CL_DEVICE_MEM_BASE_ADDR_ALIGN)),
|
m_align(OclLib::getUint(data.device.id(), CL_DEVICE_MEM_BASE_ADDR_ALIGN)),
|
||||||
|
|||||||
@@ -70,21 +70,21 @@ protected:
|
|||||||
void enqueueWriteBuffer(cl_mem buffer, cl_bool blocking_write, size_t offset, size_t size, const void *ptr);
|
void enqueueWriteBuffer(cl_mem buffer, cl_bool blocking_write, size_t offset, size_t size, const void *ptr);
|
||||||
void finalize(uint32_t *hashOutput);
|
void finalize(uint32_t *hashOutput);
|
||||||
|
|
||||||
Algorithm m_algorithm;
|
|
||||||
cl_command_queue m_queue = nullptr;
|
cl_command_queue m_queue = nullptr;
|
||||||
cl_context m_ctx;
|
cl_context m_ctx;
|
||||||
cl_mem m_buffer = nullptr;
|
cl_mem m_buffer = nullptr;
|
||||||
cl_mem m_input = nullptr;
|
cl_mem m_input = nullptr;
|
||||||
cl_mem m_output = nullptr;
|
cl_mem m_output = nullptr;
|
||||||
cl_program m_program = nullptr;
|
cl_program m_program = nullptr;
|
||||||
|
const Algorithm m_algorithm;
|
||||||
const char *m_source;
|
const char *m_source;
|
||||||
const OclLaunchData &m_data;
|
const OclLaunchData &m_data;
|
||||||
const size_t m_align;
|
const size_t m_align;
|
||||||
const size_t m_threadId;
|
const size_t m_threadId;
|
||||||
|
const uint32_t m_intensity;
|
||||||
size_t m_offset = 0;
|
size_t m_offset = 0;
|
||||||
std::string m_deviceKey;
|
std::string m_deviceKey;
|
||||||
std::string m_options;
|
std::string m_options;
|
||||||
uint32_t m_intensity;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,8 @@ xmrig::OclDevice::OclDevice(uint32_t index, cl_device_id id, cl_platform_id plat
|
|||||||
m_board(OclLib::getString(id, 0x4038 /* CL_DEVICE_BOARD_NAME_AMD */)),
|
m_board(OclLib::getString(id, 0x4038 /* CL_DEVICE_BOARD_NAME_AMD */)),
|
||||||
m_name(OclLib::getString(id, CL_DEVICE_NAME)),
|
m_name(OclLib::getString(id, CL_DEVICE_NAME)),
|
||||||
m_vendor(OclLib::getString(id, CL_DEVICE_VENDOR)),
|
m_vendor(OclLib::getString(id, CL_DEVICE_VENDOR)),
|
||||||
|
m_maxMemoryAlloc(OclLib::getUlong(id, CL_DEVICE_MAX_MEM_ALLOC_SIZE)),
|
||||||
|
m_globalMemory(OclLib::getUlong(id, CL_DEVICE_GLOBAL_MEM_SIZE)),
|
||||||
m_computeUnits(OclLib::getUint(id, CL_DEVICE_MAX_COMPUTE_UNITS, 1)),
|
m_computeUnits(OclLib::getUint(id, CL_DEVICE_MAX_COMPUTE_UNITS, 1)),
|
||||||
m_index(index)
|
m_index(index)
|
||||||
{
|
{
|
||||||
@@ -155,24 +157,6 @@ xmrig::OclDevice::OclDevice(uint32_t index, cl_device_id id, cl_platform_id plat
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t xmrig::OclDevice::freeMemSize() const
|
|
||||||
{
|
|
||||||
return std::min(maxMemAllocSize(), globalMemSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t xmrig::OclDevice::globalMemSize() const
|
|
||||||
{
|
|
||||||
return OclLib::getUlong(id(), CL_DEVICE_GLOBAL_MEM_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t xmrig::OclDevice::maxMemAllocSize() const
|
|
||||||
{
|
|
||||||
return OclLib::getUlong(id(), CL_DEVICE_MAX_MEM_ALLOC_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
xmrig::String xmrig::OclDevice::printableName() const
|
xmrig::String xmrig::OclDevice::printableName() const
|
||||||
{
|
{
|
||||||
const size_t size = m_board.size() + m_name.size() + 64;
|
const size_t size = m_board.size() + m_name.size() + 64;
|
||||||
|
|||||||
@@ -26,13 +26,13 @@
|
|||||||
#define XMRIG_OCLDEVICE_H
|
#define XMRIG_OCLDEVICE_H
|
||||||
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
|
|
||||||
#include "backend/common/misc/PciTopology.h"
|
#include "backend/common/misc/PciTopology.h"
|
||||||
#include "backend/opencl/wrappers/OclVendor.h"
|
#include "backend/opencl/wrappers/OclVendor.h"
|
||||||
#include "base/tools/String.h"
|
#include "base/tools/String.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
using cl_device_id = struct _cl_device_id *;
|
using cl_device_id = struct _cl_device_id *;
|
||||||
using cl_platform_id = struct _cl_platform_id *;
|
using cl_platform_id = struct _cl_platform_id *;
|
||||||
@@ -62,9 +62,6 @@ public:
|
|||||||
OclDevice() = delete;
|
OclDevice() = delete;
|
||||||
OclDevice(uint32_t index, cl_device_id id, cl_platform_id platform);
|
OclDevice(uint32_t index, cl_device_id id, cl_platform_id platform);
|
||||||
|
|
||||||
size_t freeMemSize() const;
|
|
||||||
size_t globalMemSize() const;
|
|
||||||
size_t maxMemAllocSize() const;
|
|
||||||
String printableName() const;
|
String printableName() const;
|
||||||
uint32_t clock() const;
|
uint32_t clock() const;
|
||||||
void generate(const Algorithm &algorithm, OclThreads &threads) const;
|
void generate(const Algorithm &algorithm, OclThreads &threads) const;
|
||||||
@@ -78,6 +75,9 @@ public:
|
|||||||
inline OclVendor vendorId() const { return m_vendorId; }
|
inline OclVendor vendorId() const { return m_vendorId; }
|
||||||
inline Type type() const { return m_type; }
|
inline Type type() const { return m_type; }
|
||||||
inline uint32_t computeUnits() const { return m_computeUnits; }
|
inline uint32_t computeUnits() const { return m_computeUnits; }
|
||||||
|
inline size_t freeMemSize() const { return std::min(maxMemAllocSize(), globalMemSize()); }
|
||||||
|
inline size_t globalMemSize() const { return m_globalMemory; }
|
||||||
|
inline size_t maxMemAllocSize() const { return m_maxMemoryAlloc; }
|
||||||
inline uint32_t index() const { return m_index; }
|
inline uint32_t index() const { return m_index; }
|
||||||
|
|
||||||
# ifdef XMRIG_FEATURE_API
|
# ifdef XMRIG_FEATURE_API
|
||||||
@@ -90,6 +90,8 @@ private:
|
|||||||
const String m_board;
|
const String m_board;
|
||||||
const String m_name;
|
const String m_name;
|
||||||
const String m_vendor;
|
const String m_vendor;
|
||||||
|
const size_t m_maxMemoryAlloc = 0;
|
||||||
|
const size_t m_globalMemory = 0;
|
||||||
const uint32_t m_computeUnits = 1;
|
const uint32_t m_computeUnits = 1;
|
||||||
const uint32_t m_index = 0;
|
const uint32_t m_index = 0;
|
||||||
OclVendor m_vendorId = OCL_VENDOR_UNKNOWN;
|
OclVendor m_vendorId = OCL_VENDOR_UNKNOWN;
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ static const char *kRetainMemObject = "clRetainMemObject";
|
|||||||
static const char *kRetainProgram = "clRetainProgram";
|
static const char *kRetainProgram = "clRetainProgram";
|
||||||
static const char *kSetKernelArg = "clSetKernelArg";
|
static const char *kSetKernelArg = "clSetKernelArg";
|
||||||
static const char *kSetMemObjectDestructorCallback = "clSetMemObjectDestructorCallback";
|
static const char *kSetMemObjectDestructorCallback = "clSetMemObjectDestructorCallback";
|
||||||
|
static const char *kSymbolNotFound = "symbol not found";
|
||||||
static const char *kUnloadPlatformCompiler = "clUnloadPlatformCompiler";
|
static const char *kUnloadPlatformCompiler = "clUnloadPlatformCompiler";
|
||||||
|
|
||||||
|
|
||||||
@@ -156,7 +157,7 @@ static setKernelArg_t pSetKernelArg = nu
|
|||||||
static setMemObjectDestructorCallback_t pSetMemObjectDestructorCallback = nullptr;
|
static setMemObjectDestructorCallback_t pSetMemObjectDestructorCallback = nullptr;
|
||||||
static unloadPlatformCompiler_t pUnloadPlatformCompiler = nullptr;
|
static unloadPlatformCompiler_t pUnloadPlatformCompiler = nullptr;
|
||||||
|
|
||||||
#define DLSYM(x) if (uv_dlsym(&oclLib, k##x, reinterpret_cast<void**>(&p##x)) == -1) { return false; }
|
#define DLSYM(x) if (uv_dlsym(&oclLib, k##x, reinterpret_cast<void**>(&p##x)) == -1) { throw std::runtime_error(kSymbolNotFound); }
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -210,39 +211,43 @@ void xmrig::OclLib::close()
|
|||||||
|
|
||||||
bool xmrig::OclLib::load()
|
bool xmrig::OclLib::load()
|
||||||
{
|
{
|
||||||
DLSYM(CreateCommandQueue);
|
try {
|
||||||
DLSYM(CreateContext);
|
DLSYM(CreateCommandQueue);
|
||||||
DLSYM(BuildProgram);
|
DLSYM(CreateContext);
|
||||||
DLSYM(EnqueueNDRangeKernel);
|
DLSYM(BuildProgram);
|
||||||
DLSYM(EnqueueReadBuffer);
|
DLSYM(EnqueueNDRangeKernel);
|
||||||
DLSYM(EnqueueWriteBuffer);
|
DLSYM(EnqueueReadBuffer);
|
||||||
DLSYM(Finish);
|
DLSYM(EnqueueWriteBuffer);
|
||||||
DLSYM(GetDeviceIDs);
|
DLSYM(Finish);
|
||||||
DLSYM(GetDeviceInfo);
|
DLSYM(GetDeviceIDs);
|
||||||
DLSYM(GetPlatformInfo);
|
DLSYM(GetDeviceInfo);
|
||||||
DLSYM(GetPlatformIDs);
|
DLSYM(GetPlatformInfo);
|
||||||
DLSYM(GetProgramBuildInfo);
|
DLSYM(GetPlatformIDs);
|
||||||
DLSYM(GetProgramInfo);
|
DLSYM(GetProgramBuildInfo);
|
||||||
DLSYM(SetKernelArg);
|
DLSYM(GetProgramInfo);
|
||||||
DLSYM(CreateKernel);
|
DLSYM(SetKernelArg);
|
||||||
DLSYM(CreateBuffer);
|
DLSYM(CreateKernel);
|
||||||
DLSYM(CreateProgramWithBinary);
|
DLSYM(CreateBuffer);
|
||||||
DLSYM(CreateProgramWithSource);
|
DLSYM(CreateProgramWithBinary);
|
||||||
DLSYM(ReleaseMemObject);
|
DLSYM(CreateProgramWithSource);
|
||||||
DLSYM(ReleaseProgram);
|
DLSYM(ReleaseMemObject);
|
||||||
DLSYM(ReleaseKernel);
|
DLSYM(ReleaseProgram);
|
||||||
DLSYM(ReleaseCommandQueue);
|
DLSYM(ReleaseKernel);
|
||||||
DLSYM(ReleaseContext);
|
DLSYM(ReleaseCommandQueue);
|
||||||
DLSYM(GetKernelInfo);
|
DLSYM(ReleaseContext);
|
||||||
DLSYM(GetCommandQueueInfo);
|
DLSYM(GetKernelInfo);
|
||||||
DLSYM(GetMemObjectInfo);
|
DLSYM(GetCommandQueueInfo);
|
||||||
DLSYM(GetContextInfo);
|
DLSYM(GetMemObjectInfo);
|
||||||
DLSYM(ReleaseDevice);
|
DLSYM(GetContextInfo);
|
||||||
DLSYM(UnloadPlatformCompiler);
|
DLSYM(ReleaseDevice);
|
||||||
DLSYM(SetMemObjectDestructorCallback);
|
DLSYM(UnloadPlatformCompiler);
|
||||||
DLSYM(CreateSubBuffer);
|
DLSYM(SetMemObjectDestructorCallback);
|
||||||
DLSYM(RetainProgram);
|
DLSYM(CreateSubBuffer);
|
||||||
DLSYM(RetainMemObject);
|
DLSYM(RetainProgram);
|
||||||
|
DLSYM(RetainMemObject);
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
# if defined(CL_VERSION_2_0)
|
# if defined(CL_VERSION_2_0)
|
||||||
uv_dlsym(&oclLib, kCreateCommandQueueWithProperties, reinterpret_cast<void**>(&pCreateCommandQueueWithProperties));
|
uv_dlsym(&oclLib, kCreateCommandQueueWithProperties, reinterpret_cast<void**>(&pCreateCommandQueueWithProperties));
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ set(HEADERS_BASE
|
|||||||
src/base/net/stratum/strategies/FailoverStrategy.h
|
src/base/net/stratum/strategies/FailoverStrategy.h
|
||||||
src/base/net/stratum/strategies/SinglePoolStrategy.h
|
src/base/net/stratum/strategies/SinglePoolStrategy.h
|
||||||
src/base/net/stratum/SubmitResult.h
|
src/base/net/stratum/SubmitResult.h
|
||||||
|
src/base/net/stratum/Url.h
|
||||||
src/base/net/tools/RecvBuf.h
|
src/base/net/tools/RecvBuf.h
|
||||||
src/base/net/tools/Storage.h
|
src/base/net/tools/Storage.h
|
||||||
src/base/tools/Arguments.h
|
src/base/tools/Arguments.h
|
||||||
@@ -78,6 +79,7 @@ set(SOURCES_BASE
|
|||||||
src/base/net/stratum/Pools.cpp
|
src/base/net/stratum/Pools.cpp
|
||||||
src/base/net/stratum/strategies/FailoverStrategy.cpp
|
src/base/net/stratum/strategies/FailoverStrategy.cpp
|
||||||
src/base/net/stratum/strategies/SinglePoolStrategy.cpp
|
src/base/net/stratum/strategies/SinglePoolStrategy.cpp
|
||||||
|
src/base/net/stratum/Url.cpp
|
||||||
src/base/tools/Arguments.cpp
|
src/base/tools/Arguments.cpp
|
||||||
src/base/tools/Buffer.cpp
|
src/base/tools/Buffer.cpp
|
||||||
src/base/tools/String.cpp
|
src/base/tools/String.cpp
|
||||||
@@ -137,6 +139,7 @@ if (WITH_HTTP)
|
|||||||
src/base/net/http/HttpResponse.h
|
src/base/net/http/HttpResponse.h
|
||||||
src/base/net/http/HttpServer.h
|
src/base/net/http/HttpServer.h
|
||||||
src/base/net/stratum/DaemonClient.h
|
src/base/net/stratum/DaemonClient.h
|
||||||
|
src/base/net/stratum/SelfSelectClient.h
|
||||||
src/base/net/tools/TcpServer.h
|
src/base/net/tools/TcpServer.h
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -152,6 +155,7 @@ if (WITH_HTTP)
|
|||||||
src/base/net/http/HttpResponse.cpp
|
src/base/net/http/HttpResponse.cpp
|
||||||
src/base/net/http/HttpServer.cpp
|
src/base/net/http/HttpServer.cpp
|
||||||
src/base/net/stratum/DaemonClient.cpp
|
src/base/net/stratum/DaemonClient.cpp
|
||||||
|
src/base/net/stratum/SelfSelectClient.cpp
|
||||||
src/base/net/tools/TcpServer.cpp
|
src/base/net/tools/TcpServer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ bool xmrig::Json::getBool(const rapidjson::Value &obj, const char *key, bool def
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *xmrig::Json::getString(const rapidjson::Value &obj, const char *key, const char *defaultValue)
|
const char *xmrig::Json::getString(const rapidjson::Value &obj, const char *key, const char *defaultValue)
|
||||||
{
|
{
|
||||||
assert(obj.IsObject());
|
assert(obj.IsObject());
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ private:
|
|||||||
#define WHITE_S CSI "0;37m" // another name for LT.GRAY
|
#define WHITE_S CSI "0;37m" // another name for LT.GRAY
|
||||||
#define WHITE_BOLD_S CSI "1;37m" // actually white
|
#define WHITE_BOLD_S CSI "1;37m" // actually white
|
||||||
|
|
||||||
|
#define GREEN_BG_BOLD_S CSI "42;1m"
|
||||||
#define BLUE_BG_S CSI "44m"
|
#define BLUE_BG_S CSI "44m"
|
||||||
#define BLUE_BG_BOLD_S CSI "44;1m"
|
#define BLUE_BG_BOLD_S CSI "44;1m"
|
||||||
#define MAGENTA_BG_S CSI "45m"
|
#define MAGENTA_BG_S CSI "45m"
|
||||||
@@ -107,6 +108,7 @@ private:
|
|||||||
#define WHITE(x) WHITE_S x CLEAR
|
#define WHITE(x) WHITE_S x CLEAR
|
||||||
#define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR
|
#define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR
|
||||||
|
|
||||||
|
#define GREEN_BG_BOLD(x) GREEN_BG_BOLD_S x CLEAR
|
||||||
#define BLUE_BG(x) BLUE_BG_S x CLEAR
|
#define BLUE_BG(x) BLUE_BG_S x CLEAR
|
||||||
#define BLUE_BG_BOLD(x) BLUE_BG_BOLD_S x CLEAR
|
#define BLUE_BG_BOLD(x) BLUE_BG_BOLD_S x CLEAR
|
||||||
#define MAGENTA_BG(x) MAGENTA_BG_S x CLEAR
|
#define MAGENTA_BG(x) MAGENTA_BG_S x CLEAR
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ xmrig::ConsoleLog::ConsoleLog()
|
|||||||
uv_tty_set_mode(m_tty, UV_TTY_MODE_NORMAL);
|
uv_tty_set_mode(m_tty, UV_TTY_MODE_NORMAL);
|
||||||
|
|
||||||
# ifdef WIN32
|
# ifdef WIN32
|
||||||
|
m_stream = reinterpret_cast<uv_stream_t*>(m_tty);
|
||||||
|
|
||||||
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
|
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
if (handle != INVALID_HANDLE_VALUE) {
|
if (handle != INVALID_HANDLE_VALUE) {
|
||||||
DWORD mode = 0;
|
DWORD mode = 0;
|
||||||
@@ -67,14 +69,26 @@ xmrig::ConsoleLog::~ConsoleLog()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::ConsoleLog::print(int, const char *line, size_t, size_t, bool colors)
|
void xmrig::ConsoleLog::print(int, const char *line, size_t, size_t size, bool colors)
|
||||||
{
|
{
|
||||||
if (!m_tty || Log::colors != colors) {
|
if (!m_tty || Log::colors != colors) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ifdef _WIN32
|
||||||
|
uv_buf_t buf = uv_buf_init(const_cast<char *>(line), static_cast<unsigned int>(size));
|
||||||
|
|
||||||
|
if (!isWritable()) {
|
||||||
|
fputs(line, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uv_try_write(m_stream, &buf, 1);
|
||||||
|
}
|
||||||
|
# else
|
||||||
fputs(line, stdout);
|
fputs(line, stdout);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -83,3 +97,15 @@ bool xmrig::ConsoleLog::isSupported() const
|
|||||||
const uv_handle_type type = uv_guess_handle(1);
|
const uv_handle_type type = uv_guess_handle(1);
|
||||||
return type == UV_TTY || type == UV_NAMED_PIPE;
|
return type == UV_TTY || type == UV_NAMED_PIPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
bool xmrig::ConsoleLog::isWritable() const
|
||||||
|
{
|
||||||
|
if (!m_stream || uv_is_writable(m_stream) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isSupported();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -53,6 +53,12 @@ private:
|
|||||||
bool isSupported() const;
|
bool isSupported() const;
|
||||||
|
|
||||||
uv_tty_t *m_tty = nullptr;
|
uv_tty_t *m_tty = nullptr;
|
||||||
|
|
||||||
|
# ifdef _WIN32
|
||||||
|
bool isWritable() const;
|
||||||
|
|
||||||
|
uv_stream_t *m_stream = nullptr;
|
||||||
|
# endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,9 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
|
|||||||
case IConfig::FingerprintKey: /* --tls-fingerprint */
|
case IConfig::FingerprintKey: /* --tls-fingerprint */
|
||||||
return add(doc, kPools, "tls-fingerprint", arg);
|
return add(doc, kPools, "tls-fingerprint", arg);
|
||||||
|
|
||||||
|
case IConfig::SelfSelectKey: /* --self-select */
|
||||||
|
return add(doc, kPools, "self-select", arg);
|
||||||
|
|
||||||
case IConfig::LogFileKey: /* --log-file */
|
case IConfig::LogFileKey: /* --log-file */
|
||||||
return set(doc, "log-file", arg);
|
return set(doc, "log-file", arg);
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,10 @@
|
|||||||
#define XMRIG_ICLIENT_H
|
#define XMRIG_ICLIENT_H
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "rapidjson/fwd.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -51,31 +54,35 @@ public:
|
|||||||
EXT_MAX
|
EXT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using Callback = std::function<void(const rapidjson::Value &result, bool success, uint64_t elapsed)>;
|
||||||
|
|
||||||
virtual ~IClient() = default;
|
virtual ~IClient() = default;
|
||||||
|
|
||||||
virtual bool disconnect() = 0;
|
virtual bool disconnect() = 0;
|
||||||
virtual bool hasExtension(Extension extension) const noexcept = 0;
|
virtual bool hasExtension(Extension extension) const noexcept = 0;
|
||||||
virtual bool isEnabled() const = 0;
|
virtual bool isEnabled() const = 0;
|
||||||
virtual bool isTLS() const = 0;
|
virtual bool isTLS() const = 0;
|
||||||
virtual const char *mode() const = 0;
|
virtual const char *mode() const = 0;
|
||||||
virtual const char *tlsFingerprint() const = 0;
|
virtual const char *tlsFingerprint() const = 0;
|
||||||
virtual const char *tlsVersion() const = 0;
|
virtual const char *tlsVersion() const = 0;
|
||||||
virtual const Job &job() const = 0;
|
virtual const Job &job() const = 0;
|
||||||
virtual const Pool &pool() const = 0;
|
virtual const Pool &pool() const = 0;
|
||||||
virtual const String &ip() const = 0;
|
virtual const String &ip() const = 0;
|
||||||
virtual int id() const = 0;
|
virtual int id() const = 0;
|
||||||
virtual int64_t submit(const JobResult &result) = 0;
|
virtual int64_t send(const rapidjson::Value &obj, Callback callback) = 0;
|
||||||
virtual void connect() = 0;
|
virtual int64_t send(const rapidjson::Value &obj) = 0;
|
||||||
virtual void connect(const Pool &pool) = 0;
|
virtual int64_t sequence() const = 0;
|
||||||
virtual void deleteLater() = 0;
|
virtual int64_t submit(const JobResult &result) = 0;
|
||||||
virtual void setAlgo(const Algorithm &algo) = 0;
|
virtual void connect() = 0;
|
||||||
virtual void setEnabled(bool enabled) = 0;
|
virtual void connect(const Pool &pool) = 0;
|
||||||
virtual void setPool(const Pool &pool) = 0;
|
virtual void deleteLater() = 0;
|
||||||
virtual void setQuiet(bool quiet) = 0;
|
virtual void setAlgo(const Algorithm &algo) = 0;
|
||||||
virtual void setRetries(int retries) = 0;
|
virtual void setEnabled(bool enabled) = 0;
|
||||||
virtual void setRetryPause(uint64_t ms) = 0;
|
virtual void setPool(const Pool &pool) = 0;
|
||||||
virtual void tick(uint64_t now) = 0;
|
virtual void setQuiet(bool quiet) = 0;
|
||||||
|
virtual void setRetries(int retries) = 0;
|
||||||
|
virtual void setRetryPause(uint64_t ms) = 0;
|
||||||
|
virtual void tick(uint64_t now) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define XMRIG_ICLIENTLISTENER_H
|
#define XMRIG_ICLIENTLISTENER_H
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
#include "rapidjson/fwd.h"
|
#include "rapidjson/fwd.h"
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public:
|
|||||||
ProxyDonateKey = 1017,
|
ProxyDonateKey = 1017,
|
||||||
DaemonKey = 1018,
|
DaemonKey = 1018,
|
||||||
DaemonPollKey = 1019,
|
DaemonPollKey = 1019,
|
||||||
|
SelfSelectKey = 1028,
|
||||||
|
|
||||||
// xmrig common
|
// xmrig common
|
||||||
CPUPriorityKey = 1021,
|
CPUPriorityKey = 1021,
|
||||||
@@ -133,6 +134,10 @@ public:
|
|||||||
CudaLaunchKey = 1204,
|
CudaLaunchKey = 1204,
|
||||||
CudaAffinityKey = 1205,
|
CudaAffinityKey = 1205,
|
||||||
CudaMaxUsageKey = 1206,
|
CudaMaxUsageKey = 1206,
|
||||||
|
CudaKey = 1207,
|
||||||
|
CudaLoaderKey = 1208,
|
||||||
|
NvmlKey = 1209,
|
||||||
|
HealthPrintTimeKey = 1210,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~IConfig() = default;
|
virtual ~IConfig() = default;
|
||||||
|
|||||||
@@ -78,9 +78,7 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) :
|
xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) :
|
||||||
HttpContext(HTTP_RESPONSE, listener),
|
HttpContext(HTTP_RESPONSE, listener)
|
||||||
m_quiet(false),
|
|
||||||
m_port(0)
|
|
||||||
{
|
{
|
||||||
this->method = method;
|
this->method = method;
|
||||||
this->url = url;
|
this->url = url;
|
||||||
@@ -127,7 +125,7 @@ void xmrig::HttpClient::onResolved(const Dns &dns, int status)
|
|||||||
|
|
||||||
sockaddr *addr = dns.get().addr(m_port);
|
sockaddr *addr = dns.get().addr(m_port);
|
||||||
|
|
||||||
uv_connect_t *req = new uv_connect_t;
|
auto req = new uv_connect_t;
|
||||||
req->data = this;
|
req->data = this;
|
||||||
|
|
||||||
uv_tcp_connect(req, m_tcp, addr, onConnect);
|
uv_tcp_connect(req, m_tcp, addr, onConnect);
|
||||||
@@ -140,7 +138,7 @@ void xmrig::HttpClient::handshake()
|
|||||||
headers.insert({ "Connection", "close" });
|
headers.insert({ "Connection", "close" });
|
||||||
headers.insert({ "User-Agent", Platform::userAgent() });
|
headers.insert({ "User-Agent", Platform::userAgent() });
|
||||||
|
|
||||||
if (body.size()) {
|
if (!body.empty()) {
|
||||||
headers.insert({ "Content-Length", std::to_string(body.size()) });
|
headers.insert({ "Content-Length", std::to_string(body.size()) });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,14 +167,14 @@ void xmrig::HttpClient::read(const char *data, size_t size)
|
|||||||
|
|
||||||
void xmrig::HttpClient::write(const std::string &header)
|
void xmrig::HttpClient::write(const std::string &header)
|
||||||
{
|
{
|
||||||
ClientWriteBaton *baton = new ClientWriteBaton(header, std::move(body));
|
auto baton = new ClientWriteBaton(header, std::move(body));
|
||||||
uv_write(&baton->req, stream(), baton->bufs, baton->count(), ClientWriteBaton::onWrite);
|
uv_write(&baton->req, stream(), baton->bufs, baton->count(), ClientWriteBaton::onWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::HttpClient::onConnect(uv_connect_t *req, int status)
|
void xmrig::HttpClient::onConnect(uv_connect_t *req, int status)
|
||||||
{
|
{
|
||||||
HttpClient *client = static_cast<HttpClient *>(req->data);
|
auto client = static_cast<HttpClient *>(req->data);
|
||||||
if (!client) {
|
if (!client) {
|
||||||
delete req;
|
delete req;
|
||||||
return;
|
return;
|
||||||
@@ -205,7 +203,7 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status)
|
|||||||
},
|
},
|
||||||
[](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf)
|
[](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf)
|
||||||
{
|
{
|
||||||
HttpClient *client = static_cast<HttpClient*>(tcp->data);
|
auto client = static_cast<HttpClient*>(tcp->data);
|
||||||
|
|
||||||
if (nread >= 0) {
|
if (nread >= 0) {
|
||||||
client->read(buf->base, static_cast<size_t>(nread));
|
client->read(buf->base, static_cast<size_t>(nread));
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "base/net/http/HttpContext.h"
|
#include "base/net/http/HttpContext.h"
|
||||||
#include "base/kernel/interfaces/IDnsListener.h"
|
#include "base/kernel/interfaces/IDnsListener.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -41,6 +42,8 @@ class String;
|
|||||||
class HttpClient : public HttpContext, public IDnsListener
|
class HttpClient : public HttpContext, public IDnsListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(HttpClient);
|
||||||
|
|
||||||
HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0);
|
HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0);
|
||||||
~HttpClient() override;
|
~HttpClient() override;
|
||||||
|
|
||||||
@@ -57,13 +60,13 @@ protected:
|
|||||||
virtual void read(const char *data, size_t size);
|
virtual void read(const char *data, size_t size);
|
||||||
virtual void write(const std::string &header);
|
virtual void write(const std::string &header);
|
||||||
|
|
||||||
bool m_quiet;
|
bool m_quiet = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void onConnect(uv_connect_t *req, int status);
|
static void onConnect(uv_connect_t *req, int status);
|
||||||
|
|
||||||
Dns *m_dns;
|
Dns *m_dns;
|
||||||
uint16_t m_port;
|
uint16_t m_port = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ void xmrig::HttpContext::closeAll()
|
|||||||
|
|
||||||
int xmrig::HttpContext::onHeaderField(http_parser *parser, const char *at, size_t length)
|
int xmrig::HttpContext::onHeaderField(http_parser *parser, const char *at, size_t length)
|
||||||
{
|
{
|
||||||
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
|
auto ctx = static_cast<HttpContext*>(parser->data);
|
||||||
|
|
||||||
if (ctx->m_wasHeaderValue) {
|
if (ctx->m_wasHeaderValue) {
|
||||||
if (!ctx->m_lastHeaderField.empty()) {
|
if (!ctx->m_lastHeaderField.empty()) {
|
||||||
@@ -155,7 +155,7 @@ int xmrig::HttpContext::onHeaderField(http_parser *parser, const char *at, size_
|
|||||||
|
|
||||||
int xmrig::HttpContext::onHeaderValue(http_parser *parser, const char *at, size_t length)
|
int xmrig::HttpContext::onHeaderValue(http_parser *parser, const char *at, size_t length)
|
||||||
{
|
{
|
||||||
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
|
auto ctx = static_cast<HttpContext*>(parser->data);
|
||||||
|
|
||||||
if (!ctx->m_wasHeaderValue) {
|
if (!ctx->m_wasHeaderValue) {
|
||||||
ctx->m_lastHeaderValue = std::string(at, length);
|
ctx->m_lastHeaderValue = std::string(at, length);
|
||||||
@@ -185,7 +185,7 @@ void xmrig::HttpContext::attach(http_parser_settings *settings)
|
|||||||
settings->on_header_value = onHeaderValue;
|
settings->on_header_value = onHeaderValue;
|
||||||
|
|
||||||
settings->on_headers_complete = [](http_parser* parser) -> int {
|
settings->on_headers_complete = [](http_parser* parser) -> int {
|
||||||
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
|
auto ctx = static_cast<HttpContext*>(parser->data);
|
||||||
ctx->status = parser->status_code;
|
ctx->status = parser->status_code;
|
||||||
|
|
||||||
if (parser->type == HTTP_REQUEST) {
|
if (parser->type == HTTP_REQUEST) {
|
||||||
@@ -208,7 +208,7 @@ void xmrig::HttpContext::attach(http_parser_settings *settings)
|
|||||||
|
|
||||||
settings->on_message_complete = [](http_parser *parser) -> int
|
settings->on_message_complete = [](http_parser *parser) -> int
|
||||||
{
|
{
|
||||||
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
|
auto ctx = static_cast<HttpContext*>(parser->data);
|
||||||
ctx->m_listener->onHttpData(*ctx);
|
ctx->m_listener->onHttpData(*ctx);
|
||||||
ctx->m_listener = nullptr;
|
ctx->m_listener = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -28,15 +28,16 @@
|
|||||||
#define XMRIG_HTTPCONTEXT_H
|
#define XMRIG_HTTPCONTEXT_H
|
||||||
|
|
||||||
|
|
||||||
typedef struct http_parser http_parser;
|
using http_parser = struct http_parser;
|
||||||
typedef struct http_parser_settings http_parser_settings;
|
using http_parser_settings = struct http_parser_settings;
|
||||||
typedef struct uv_connect_s uv_connect_t;
|
using uv_connect_t = struct uv_connect_s;
|
||||||
typedef struct uv_handle_s uv_handle_t;
|
using uv_handle_t = struct uv_handle_s;
|
||||||
typedef struct uv_stream_s uv_stream_t;
|
using uv_stream_t = struct uv_stream_s;
|
||||||
typedef struct uv_tcp_s uv_tcp_t;
|
using uv_tcp_t = struct uv_tcp_s;
|
||||||
|
|
||||||
|
|
||||||
#include "base/net/http/HttpData.h"
|
#include "base/net/http/HttpData.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -48,6 +49,8 @@ class IHttpListener;
|
|||||||
class HttpContext : public HttpData
|
class HttpContext : public HttpData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(HttpContext)
|
||||||
|
|
||||||
HttpContext(int parser_type, IHttpListener *listener);
|
HttpContext(int parser_type, IHttpListener *listener);
|
||||||
virtual ~HttpContext();
|
virtual ~HttpContext();
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <cassert>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
|||||||
@@ -28,10 +28,10 @@
|
|||||||
#define XMRIG_HTTPSCLIENT_H
|
#define XMRIG_HTTPSCLIENT_H
|
||||||
|
|
||||||
|
|
||||||
typedef struct bio_st BIO;
|
using BIO = struct bio_st;
|
||||||
typedef struct ssl_ctx_st SSL_CTX;
|
using SSL_CTX = struct ssl_ctx_st;
|
||||||
typedef struct ssl_st SSL;
|
using SSL = struct ssl_st;
|
||||||
typedef struct x509_st X509;
|
using X509 = struct x509_st;
|
||||||
|
|
||||||
|
|
||||||
#include "base/net/http/HttpClient.h"
|
#include "base/net/http/HttpClient.h"
|
||||||
@@ -44,6 +44,8 @@ namespace xmrig {
|
|||||||
class HttpsClient : public HttpClient
|
class HttpsClient : public HttpClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(HttpsClient)
|
||||||
|
|
||||||
HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint);
|
HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint);
|
||||||
~HttpsClient() override;
|
~HttpsClient() override;
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "base/kernel/interfaces/IClientListener.h"
|
#include "base/kernel/interfaces/IClientListener.h"
|
||||||
#include "base/net/stratum/BaseClient.h"
|
#include "base/net/stratum/BaseClient.h"
|
||||||
#include "base/net/stratum/SubmitResult.h"
|
#include "base/net/stratum/SubmitResult.h"
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -36,18 +37,38 @@ int64_t BaseClient::m_sequence = 1;
|
|||||||
|
|
||||||
|
|
||||||
xmrig::BaseClient::BaseClient(int id, IClientListener *listener) :
|
xmrig::BaseClient::BaseClient(int id, IClientListener *listener) :
|
||||||
m_quiet(false),
|
|
||||||
m_listener(listener),
|
m_listener(listener),
|
||||||
m_id(id),
|
m_id(id)
|
||||||
m_retries(5),
|
|
||||||
m_failures(0),
|
|
||||||
m_state(UnconnectedState),
|
|
||||||
m_retryPause(5000),
|
|
||||||
m_enabled(true)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::BaseClient::handleResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error)
|
||||||
|
{
|
||||||
|
if (id == 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_callbacks.find(id);
|
||||||
|
if (it != m_callbacks.end()) {
|
||||||
|
const uint64_t elapsed = Chrono::steadyMSecs() - it->second.ts;
|
||||||
|
|
||||||
|
if (error.IsObject()) {
|
||||||
|
it->second.callback(error, false, elapsed);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it->second.callback(result, true, elapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_callbacks.erase(it);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::BaseClient::handleSubmitResponse(int64_t id, const char *error)
|
bool xmrig::BaseClient::handleSubmitResponse(int64_t id, const char *error)
|
||||||
{
|
{
|
||||||
auto it = m_results.find(id);
|
auto it = m_results.find(id);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "base/kernel/interfaces/IClient.h"
|
#include "base/kernel/interfaces/IClient.h"
|
||||||
#include "base/net/stratum/Job.h"
|
#include "base/net/stratum/Job.h"
|
||||||
#include "base/net/stratum/Pool.h"
|
#include "base/net/stratum/Pool.h"
|
||||||
|
#include "base/tools/Chrono.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -46,11 +47,13 @@ class BaseClient : public IClient
|
|||||||
public:
|
public:
|
||||||
BaseClient(int id, IClientListener *listener);
|
BaseClient(int id, IClientListener *listener);
|
||||||
|
|
||||||
|
protected:
|
||||||
inline bool isEnabled() const override { return m_enabled; }
|
inline bool isEnabled() const override { return m_enabled; }
|
||||||
inline const Job &job() const override { return m_job; }
|
inline const Job &job() const override { return m_job; }
|
||||||
inline const Pool &pool() const override { return m_pool; }
|
inline const Pool &pool() const override { return m_pool; }
|
||||||
inline const String &ip() const override { return m_ip; }
|
inline const String &ip() const override { return m_ip; }
|
||||||
inline int id() const override { return m_id; }
|
inline int id() const override { return m_id; }
|
||||||
|
inline int64_t sequence() const override { return m_sequence; }
|
||||||
inline void setAlgo(const Algorithm &algo) override { m_pool.setAlgo(algo); }
|
inline void setAlgo(const Algorithm &algo) override { m_pool.setAlgo(algo); }
|
||||||
inline void setEnabled(bool enabled) override { m_enabled = enabled; }
|
inline void setEnabled(bool enabled) override { m_enabled = enabled; }
|
||||||
inline void setPool(const Pool &pool) override { if (pool.isValid()) { m_pool = pool; } }
|
inline void setPool(const Pool &pool) override { if (pool.isValid()) { m_pool = pool; } }
|
||||||
@@ -68,26 +71,36 @@ protected:
|
|||||||
ReconnectingState
|
ReconnectingState
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SendResult
|
||||||
|
{
|
||||||
|
inline SendResult(Callback &&callback) : callback(callback), ts(Chrono::steadyMSecs()) {}
|
||||||
|
|
||||||
|
Callback callback;
|
||||||
|
const uint64_t ts;
|
||||||
|
};
|
||||||
|
|
||||||
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
|
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
|
||||||
|
|
||||||
|
bool handleResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error);
|
||||||
bool handleSubmitResponse(int64_t id, const char *error = nullptr);
|
bool handleSubmitResponse(int64_t id, const char *error = nullptr);
|
||||||
|
|
||||||
bool m_quiet;
|
bool m_quiet = false;
|
||||||
IClientListener *m_listener;
|
IClientListener *m_listener;
|
||||||
int m_id;
|
int m_id;
|
||||||
int m_retries;
|
int m_retries = 5;
|
||||||
int64_t m_failures;
|
int64_t m_failures = 0;
|
||||||
Job m_job;
|
Job m_job;
|
||||||
Pool m_pool;
|
Pool m_pool;
|
||||||
SocketState m_state;
|
SocketState m_state = UnconnectedState;
|
||||||
|
std::map<int64_t, SendResult> m_callbacks;
|
||||||
std::map<int64_t, SubmitResult> m_results;
|
std::map<int64_t, SubmitResult> m_results;
|
||||||
String m_ip;
|
String m_ip;
|
||||||
uint64_t m_retryPause;
|
uint64_t m_retryPause = 5000;
|
||||||
|
|
||||||
static int64_t m_sequence;
|
static int64_t m_sequence;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_enabled;
|
bool m_enabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2019 jtgrassie <https://github.com/jtgrassie>
|
||||||
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@@ -22,11 +23,11 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <cassert>
|
||||||
#include <inttypes.h>
|
#include <cinttypes>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
@@ -136,6 +137,41 @@ const char *xmrig::Client::tlsVersion() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64_t xmrig::Client::send(const rapidjson::Value &obj, Callback callback)
|
||||||
|
{
|
||||||
|
assert(obj["id"] == sequence());
|
||||||
|
|
||||||
|
m_callbacks.insert({ sequence(), std::move(callback) });
|
||||||
|
|
||||||
|
return send(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64_t xmrig::Client::send(const rapidjson::Value &obj)
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
|
||||||
|
Value value;
|
||||||
|
|
||||||
|
StringBuffer buffer(nullptr, 512);
|
||||||
|
Writer<StringBuffer> writer(buffer);
|
||||||
|
obj.Accept(writer);
|
||||||
|
|
||||||
|
const size_t size = buffer.GetSize();
|
||||||
|
if (size > (sizeof(m_sendBuf) - 2)) {
|
||||||
|
LOG_ERR("[%s] send failed: \"send buffer overflow: %zu > %zu\"", url(), size, (sizeof(m_sendBuf) - 2));
|
||||||
|
close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(m_sendBuf, buffer.GetString(), size);
|
||||||
|
m_sendBuf[size] = '\n';
|
||||||
|
m_sendBuf[size + 1] = '\0';
|
||||||
|
|
||||||
|
return send(size + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int64_t xmrig::Client::submit(const JobResult &result)
|
int64_t xmrig::Client::submit(const JobResult &result)
|
||||||
{
|
{
|
||||||
# ifndef XMRIG_PROXY_PROJECT
|
# ifndef XMRIG_PROXY_PROJECT
|
||||||
@@ -176,9 +212,9 @@ int64_t xmrig::Client::submit(const JobResult &result)
|
|||||||
JsonRequest::create(doc, m_sequence, "submit", params);
|
JsonRequest::create(doc, m_sequence, "submit", params);
|
||||||
|
|
||||||
# ifdef XMRIG_PROXY_PROJECT
|
# ifdef XMRIG_PROXY_PROJECT
|
||||||
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id);
|
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id, 0);
|
||||||
# else
|
# else
|
||||||
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff());
|
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), 0, result.backend);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
return send(doc);
|
return send(doc);
|
||||||
@@ -320,9 +356,23 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!job.setBlob(params["blob"].GetString())) {
|
# ifdef XMRIG_FEATURE_HTTP
|
||||||
*code = 4;
|
if (m_pool.mode() == Pool::MODE_SELF_SELECT) {
|
||||||
return false;
|
job.setExtraNonce(Json::getString(params, "extra_nonce"));
|
||||||
|
job.setPoolWallet(Json::getString(params, "pool_wallet"));
|
||||||
|
|
||||||
|
if (job.extraNonce().isNull() || job.poolWallet().isNull()) {
|
||||||
|
*code = 4;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
if (!job.setBlob(params["blob"].GetString())) {
|
||||||
|
*code = 4;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!job.setTarget(params["target"].GetString())) {
|
if (!job.setTarget(params["target"].GetString())) {
|
||||||
@@ -345,7 +395,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (job.algorithm().family() == Algorithm::RANDOM_X && !job.setSeedHash(Json::getString(params, "seed_hash"))) {
|
if (m_pool.mode() != Pool::MODE_SELF_SELECT && job.algorithm().family() == Algorithm::RANDOM_X && !job.setSeedHash(Json::getString(params, "seed_hash"))) {
|
||||||
if (!isQuiet()) {
|
if (!isQuiet()) {
|
||||||
LOG_ERR("[%s] failed to parse field \"seed_hash\" required by RandomX", url(), algo);
|
LOG_ERR("[%s] failed to parse field \"seed_hash\" required by RandomX", url(), algo);
|
||||||
}
|
}
|
||||||
@@ -473,29 +523,6 @@ int xmrig::Client::resolve(const String &host)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int64_t xmrig::Client::send(const rapidjson::Document &doc)
|
|
||||||
{
|
|
||||||
using namespace rapidjson;
|
|
||||||
|
|
||||||
StringBuffer buffer(nullptr, 512);
|
|
||||||
Writer<StringBuffer> writer(buffer);
|
|
||||||
doc.Accept(writer);
|
|
||||||
|
|
||||||
const size_t size = buffer.GetSize();
|
|
||||||
if (size > (sizeof(m_sendBuf) - 2)) {
|
|
||||||
LOG_ERR("[%s] send failed: \"send buffer overflow: %zu > %zu\"", url(), size, (sizeof(m_sendBuf) - 2));
|
|
||||||
close();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(m_sendBuf, buffer.GetString(), size);
|
|
||||||
m_sendBuf[size] = '\n';
|
|
||||||
m_sendBuf[size + 1] = '\0';
|
|
||||||
|
|
||||||
return send(size + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int64_t xmrig::Client::send(size_t size)
|
int64_t xmrig::Client::send(size_t size)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("[%s] send (%d bytes): \"%.*s\"", url(), size, static_cast<int>(size) - 1, m_sendBuf);
|
LOG_DEBUG("[%s] send (%d bytes): \"%.*s\"", url(), size, static_cast<int>(size) - 1, m_sendBuf);
|
||||||
@@ -719,6 +746,10 @@ void xmrig::Client::parseNotification(const char *method, const rapidjson::Value
|
|||||||
|
|
||||||
void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error)
|
void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error)
|
||||||
{
|
{
|
||||||
|
if (handleResponse(id, result, error)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (error.IsObject()) {
|
if (error.IsObject()) {
|
||||||
const char *message = error["message"].GetString();
|
const char *message = error["message"].GetString();
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2019 jtgrassie <https://github.com/jtgrassie>
|
||||||
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@@ -40,10 +41,11 @@
|
|||||||
#include "base/net/stratum/SubmitResult.h"
|
#include "base/net/stratum/SubmitResult.h"
|
||||||
#include "base/net/tools/RecvBuf.h"
|
#include "base/net/tools/RecvBuf.h"
|
||||||
#include "base/net/tools/Storage.h"
|
#include "base/net/tools/Storage.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
#include "crypto/common/Algorithm.h"
|
#include "crypto/common/Algorithm.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct bio_st BIO;
|
using BIO = struct bio_st;
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -56,6 +58,8 @@ class JobResult;
|
|||||||
class Client : public BaseClient, public IDnsListener, public ILineListener
|
class Client : public BaseClient, public IDnsListener, public ILineListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(Client)
|
||||||
|
|
||||||
constexpr static uint64_t kConnectTimeout = 20 * 1000;
|
constexpr static uint64_t kConnectTimeout = 20 * 1000;
|
||||||
constexpr static uint64_t kResponseTimeout = 20 * 1000;
|
constexpr static uint64_t kResponseTimeout = 20 * 1000;
|
||||||
|
|
||||||
@@ -73,6 +77,8 @@ protected:
|
|||||||
bool isTLS() const override;
|
bool isTLS() const override;
|
||||||
const char *tlsFingerprint() const override;
|
const char *tlsFingerprint() const override;
|
||||||
const char *tlsVersion() const override;
|
const char *tlsVersion() const override;
|
||||||
|
int64_t send(const rapidjson::Value &obj, Callback callback) override;
|
||||||
|
int64_t send(const rapidjson::Value &obj) override;
|
||||||
int64_t submit(const JobResult &result) override;
|
int64_t submit(const JobResult &result) override;
|
||||||
void connect() override;
|
void connect() override;
|
||||||
void connect(const Pool &pool) override;
|
void connect(const Pool &pool) override;
|
||||||
@@ -95,7 +101,6 @@ private:
|
|||||||
bool send(BIO *bio);
|
bool send(BIO *bio);
|
||||||
bool verifyAlgorithm(const Algorithm &algorithm, const char *algo) const;
|
bool verifyAlgorithm(const Algorithm &algorithm, const char *algo) const;
|
||||||
int resolve(const String &host);
|
int resolve(const String &host);
|
||||||
int64_t send(const rapidjson::Document &doc);
|
|
||||||
int64_t send(size_t size);
|
int64_t send(size_t size);
|
||||||
void connect(sockaddr *addr);
|
void connect(sockaddr *addr);
|
||||||
void handshake();
|
void handshake();
|
||||||
|
|||||||
@@ -117,9 +117,9 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result)
|
|||||||
JsonRequest::create(doc, m_sequence, "submitblock", params);
|
JsonRequest::create(doc, m_sequence, "submitblock", params);
|
||||||
|
|
||||||
# ifdef XMRIG_PROXY_PROJECT
|
# ifdef XMRIG_PROXY_PROJECT
|
||||||
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id);
|
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id, 0);
|
||||||
# else
|
# else
|
||||||
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff());
|
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), 0, result.backend);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
send(HTTP_POST, kJsonRPC, doc);
|
send(HTTP_POST, kJsonRPC, doc);
|
||||||
|
|||||||
@@ -27,9 +27,10 @@
|
|||||||
#define XMRIG_DAEMONCLIENT_H
|
#define XMRIG_DAEMONCLIENT_H
|
||||||
|
|
||||||
|
|
||||||
#include "base/net/stratum/BaseClient.h"
|
|
||||||
#include "base/kernel/interfaces/ITimerListener.h"
|
|
||||||
#include "base/kernel/interfaces/IHttpListener.h"
|
#include "base/kernel/interfaces/IHttpListener.h"
|
||||||
|
#include "base/kernel/interfaces/ITimerListener.h"
|
||||||
|
#include "base/net/stratum/BaseClient.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -38,6 +39,8 @@ namespace xmrig {
|
|||||||
class DaemonClient : public BaseClient, public ITimerListener, public IHttpListener
|
class DaemonClient : public BaseClient, public ITimerListener, public IHttpListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(DaemonClient)
|
||||||
|
|
||||||
DaemonClient(int id, IClientListener *listener);
|
DaemonClient(int id, IClientListener *listener);
|
||||||
~DaemonClient() override;
|
~DaemonClient() override;
|
||||||
|
|
||||||
@@ -51,12 +54,14 @@ protected:
|
|||||||
void onHttpData(const HttpData &data) override;
|
void onHttpData(const HttpData &data) override;
|
||||||
void onTimer(const Timer *timer) override;
|
void onTimer(const Timer *timer) override;
|
||||||
|
|
||||||
inline bool hasExtension(Extension) const noexcept override { return false; }
|
inline bool hasExtension(Extension) const noexcept override { return false; }
|
||||||
inline const char *mode() const override { return "daemon"; }
|
inline const char *mode() const override { return "daemon"; }
|
||||||
inline const char *tlsFingerprint() const override { return m_tlsFingerprint; }
|
inline const char *tlsFingerprint() const override { return m_tlsFingerprint; }
|
||||||
inline const char *tlsVersion() const override { return m_tlsVersion; }
|
inline const char *tlsVersion() const override { return m_tlsVersion; }
|
||||||
inline void deleteLater() override { delete this; }
|
inline int64_t send(const rapidjson::Value &, Callback) override { return -1; }
|
||||||
inline void tick(uint64_t) override {}
|
inline int64_t send(const rapidjson::Value &) override { return -1; }
|
||||||
|
inline void deleteLater() override { delete this; }
|
||||||
|
inline void tick(uint64_t) override {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isOutdated(uint64_t height, const char *hash) const;
|
bool isOutdated(uint64_t height, const char *hash) const;
|
||||||
|
|||||||
@@ -152,16 +152,19 @@ void xmrig::Job::setDiff(uint64_t diff)
|
|||||||
|
|
||||||
void xmrig::Job::copy(const Job &other)
|
void xmrig::Job::copy(const Job &other)
|
||||||
{
|
{
|
||||||
m_algorithm = other.m_algorithm;
|
m_algorithm = other.m_algorithm;
|
||||||
m_nicehash = other.m_nicehash;
|
m_nicehash = other.m_nicehash;
|
||||||
m_size = other.m_size;
|
m_size = other.m_size;
|
||||||
m_clientId = other.m_clientId;
|
m_clientId = other.m_clientId;
|
||||||
m_id = other.m_id;
|
m_id = other.m_id;
|
||||||
m_diff = other.m_diff;
|
m_backend = other.m_backend;
|
||||||
m_height = other.m_height;
|
m_diff = other.m_diff;
|
||||||
m_target = other.m_target;
|
m_height = other.m_height;
|
||||||
m_index = other.m_index;
|
m_target = other.m_target;
|
||||||
m_seed = other.m_seed;
|
m_index = other.m_index;
|
||||||
|
m_seed = other.m_seed;
|
||||||
|
m_extraNonce = other.m_extraNonce;
|
||||||
|
m_poolWallet = other.m_poolWallet;
|
||||||
|
|
||||||
memcpy(m_blob, other.m_blob, sizeof(m_blob));
|
memcpy(m_blob, other.m_blob, sizeof(m_blob));
|
||||||
|
|
||||||
@@ -172,3 +175,34 @@ void xmrig::Job::copy(const Job &other)
|
|||||||
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
|
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Job::move(Job &&other)
|
||||||
|
{
|
||||||
|
m_algorithm = other.m_algorithm;
|
||||||
|
m_nicehash = other.m_nicehash;
|
||||||
|
m_size = other.m_size;
|
||||||
|
m_clientId = std::move(other.m_clientId);
|
||||||
|
m_id = std::move(other.m_id);
|
||||||
|
m_backend = other.m_backend;
|
||||||
|
m_diff = other.m_diff;
|
||||||
|
m_height = other.m_height;
|
||||||
|
m_target = other.m_target;
|
||||||
|
m_index = other.m_index;
|
||||||
|
m_seed = std::move(other.m_seed);
|
||||||
|
m_extraNonce = std::move(other.m_extraNonce);
|
||||||
|
m_poolWallet = std::move(other.m_poolWallet);
|
||||||
|
|
||||||
|
memcpy(m_blob, other.m_blob, sizeof(m_blob));
|
||||||
|
|
||||||
|
other.m_size = 0;
|
||||||
|
other.m_diff = 0;
|
||||||
|
other.m_algorithm = Algorithm::INVALID;
|
||||||
|
|
||||||
|
# ifdef XMRIG_PROXY_PROJECT
|
||||||
|
m_rawSeedHash = std::move(other.m_rawSeedHash);
|
||||||
|
|
||||||
|
memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob));
|
||||||
|
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ public:
|
|||||||
|
|
||||||
Job() = default;
|
Job() = default;
|
||||||
Job(bool nicehash, const Algorithm &algorithm, const String &clientId);
|
Job(bool nicehash, const Algorithm &algorithm, const String &clientId);
|
||||||
|
|
||||||
|
inline Job(const Job &other) { copy(other); }
|
||||||
|
inline Job(Job &&other) noexcept { move(std::move(other)); }
|
||||||
|
|
||||||
~Job() = default;
|
~Job() = default;
|
||||||
|
|
||||||
bool isEqual(const Job &other) const;
|
bool isEqual(const Job &other) const;
|
||||||
@@ -58,28 +62,34 @@ public:
|
|||||||
bool setTarget(const char *target);
|
bool setTarget(const char *target);
|
||||||
void setDiff(uint64_t diff);
|
void setDiff(uint64_t diff);
|
||||||
|
|
||||||
inline bool isNicehash() const { return m_nicehash; }
|
inline bool isNicehash() const { return m_nicehash; }
|
||||||
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
|
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
|
||||||
inline bool setId(const char *id) { return m_id = id; }
|
inline bool setId(const char *id) { return m_id = id; }
|
||||||
inline const Algorithm &algorithm() const { return m_algorithm; }
|
inline const Algorithm &algorithm() const { return m_algorithm; }
|
||||||
inline const Buffer &seed() const { return m_seed; }
|
inline const Buffer &seed() const { return m_seed; }
|
||||||
inline const String &clientId() const { return m_clientId; }
|
inline const String &clientId() const { return m_clientId; }
|
||||||
inline const String &id() const { return m_id; }
|
inline const String &extraNonce() const { return m_extraNonce; }
|
||||||
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(m_blob + 39); }
|
inline const String &id() const { return m_id; }
|
||||||
inline const uint8_t *blob() const { return m_blob; }
|
inline const String &poolWallet() const { return m_poolWallet; }
|
||||||
inline size_t size() const { return m_size; }
|
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(m_blob + 39); }
|
||||||
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
|
inline const uint8_t *blob() const { return m_blob; }
|
||||||
inline uint64_t diff() const { return m_diff; }
|
inline size_t size() const { return m_size; }
|
||||||
inline uint64_t height() const { return m_height; }
|
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
|
||||||
inline uint64_t target() const { return m_target; }
|
inline uint32_t backend() const { return m_backend; }
|
||||||
inline uint8_t fixedByte() const { return *(m_blob + 42); }
|
inline uint64_t diff() const { return m_diff; }
|
||||||
inline uint8_t index() const { return m_index; }
|
inline uint64_t height() const { return m_height; }
|
||||||
inline void reset() { m_size = 0; m_diff = 0; }
|
inline uint64_t target() const { return m_target; }
|
||||||
inline void setAlgorithm(const Algorithm::Id id) { m_algorithm = id; }
|
inline uint8_t fixedByte() const { return *(m_blob + 42); }
|
||||||
inline void setAlgorithm(const char *algo) { m_algorithm = algo; }
|
inline uint8_t index() const { return m_index; }
|
||||||
inline void setClientId(const String &id) { m_clientId = id; }
|
inline void reset() { m_size = 0; m_diff = 0; }
|
||||||
inline void setHeight(uint64_t height) { m_height = height; }
|
inline void setAlgorithm(const Algorithm::Id id) { m_algorithm = id; }
|
||||||
inline void setIndex(uint8_t index) { m_index = index; }
|
inline void setAlgorithm(const char *algo) { m_algorithm = algo; }
|
||||||
|
inline void setBackend(uint32_t backend) { m_backend = backend; }
|
||||||
|
inline void setClientId(const String &id) { m_clientId = id; }
|
||||||
|
inline void setExtraNonce(const String &extraNonce) { m_extraNonce = extraNonce; }
|
||||||
|
inline void setHeight(uint64_t height) { m_height = height; }
|
||||||
|
inline void setIndex(uint8_t index) { m_index = index; }
|
||||||
|
inline void setPoolWallet(const String &poolWallet) { m_poolWallet = poolWallet; }
|
||||||
|
|
||||||
# ifdef XMRIG_PROXY_PROJECT
|
# ifdef XMRIG_PROXY_PROJECT
|
||||||
inline char *rawBlob() { return m_rawBlob; }
|
inline char *rawBlob() { return m_rawBlob; }
|
||||||
@@ -91,19 +101,24 @@ public:
|
|||||||
static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast<uint32_t*>(blob + 39); }
|
static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast<uint32_t*>(blob + 39); }
|
||||||
static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
|
static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
|
||||||
|
|
||||||
inline bool operator==(const Job &other) const { return isEqual(other); }
|
|
||||||
inline bool operator!=(const Job &other) const { return !isEqual(other); }
|
inline bool operator!=(const Job &other) const { return !isEqual(other); }
|
||||||
|
inline bool operator==(const Job &other) const { return isEqual(other); }
|
||||||
inline Job &operator=(const Job &other) { copy(other); return *this; }
|
inline Job &operator=(const Job &other) { copy(other); return *this; }
|
||||||
|
inline Job &operator=(Job &&other) noexcept { move(std::move(other)); return *this; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void copy(const Job &other);
|
void copy(const Job &other);
|
||||||
|
void move(Job &&other);
|
||||||
|
|
||||||
Algorithm m_algorithm;
|
Algorithm m_algorithm;
|
||||||
bool m_nicehash = false;
|
bool m_nicehash = false;
|
||||||
Buffer m_seed;
|
Buffer m_seed;
|
||||||
size_t m_size = 0;
|
size_t m_size = 0;
|
||||||
String m_clientId;
|
String m_clientId;
|
||||||
|
String m_extraNonce;
|
||||||
String m_id;
|
String m_id;
|
||||||
|
String m_poolWallet;
|
||||||
|
uint32_t m_backend = 0;
|
||||||
uint64_t m_diff = 0;
|
uint64_t m_diff = 0;
|
||||||
uint64_t m_height = 0;
|
uint64_t m_height = 0;
|
||||||
uint64_t m_target = 0;
|
uint64_t m_target = 0;
|
||||||
@@ -111,8 +126,8 @@ private:
|
|||||||
uint8_t m_index = 0;
|
uint8_t m_index = 0;
|
||||||
|
|
||||||
# ifdef XMRIG_PROXY_PROJECT
|
# ifdef XMRIG_PROXY_PROJECT
|
||||||
char m_rawBlob[kMaxBlobSize * 2 + 8];
|
char m_rawBlob[kMaxBlobSize * 2 + 8]{};
|
||||||
char m_rawTarget[24];
|
char m_rawTarget[24]{};
|
||||||
String m_rawSeedHash;
|
String m_rawSeedHash;
|
||||||
# endif
|
# endif
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,24 +24,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <cassert>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
#include "base/io/json/Json.h"
|
|
||||||
#include "base/net/stratum/Pool.h"
|
#include "base/net/stratum/Pool.h"
|
||||||
|
#include "base/io/json/Json.h"
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
|
#include "base/kernel/Platform.h"
|
||||||
|
#include "base/net/stratum/Client.h"
|
||||||
#include "rapidjson/document.h"
|
#include "rapidjson/document.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef APP_DEBUG
|
#ifdef XMRIG_FEATURE_HTTP
|
||||||
# include "base/io/log/Log.h"
|
# include "base/net/stratum/DaemonClient.h"
|
||||||
#endif
|
# include "base/net/stratum/SelfSelectClient.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# define strncasecmp _strnicmp
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -57,6 +57,7 @@ static const char *kKeepalive = "keepalive";
|
|||||||
static const char *kNicehash = "nicehash";
|
static const char *kNicehash = "nicehash";
|
||||||
static const char *kPass = "pass";
|
static const char *kPass = "pass";
|
||||||
static const char *kRigId = "rig-id";
|
static const char *kRigId = "rig-id";
|
||||||
|
static const char *kSelfSelect = "self-select";
|
||||||
static const char *kTls = "tls";
|
static const char *kTls = "tls";
|
||||||
static const char *kUrl = "url";
|
static const char *kUrl = "url";
|
||||||
static const char *kUser = "user";
|
static const char *kUser = "user";
|
||||||
@@ -64,54 +65,23 @@ static const char *kUser = "user";
|
|||||||
const String Pool::kDefaultPassword = "x";
|
const String Pool::kDefaultPassword = "x";
|
||||||
const String Pool::kDefaultUser = "x";
|
const String Pool::kDefaultUser = "x";
|
||||||
|
|
||||||
static const char kStratumTcp[] = "stratum+tcp://";
|
|
||||||
static const char kStratumSsl[] = "stratum+ssl://";
|
|
||||||
|
|
||||||
#ifdef XMRIG_FEATURE_HTTP
|
|
||||||
static const char kDaemonHttp[] = "daemon+http://";
|
|
||||||
static const char kDaemonHttps[] = "daemon+https://";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xmrig::Pool::Pool() :
|
|
||||||
m_keepAlive(0),
|
|
||||||
m_flags(0),
|
|
||||||
m_port(kDefaultPort),
|
|
||||||
m_pollInterval(kDefaultPollInterval)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Parse url.
|
|
||||||
*
|
|
||||||
* Valid urls:
|
|
||||||
* example.com
|
|
||||||
* example.com:3333
|
|
||||||
* stratum+tcp://example.com
|
|
||||||
* stratum+tcp://example.com:3333
|
|
||||||
*
|
|
||||||
* @param url
|
|
||||||
*/
|
|
||||||
xmrig::Pool::Pool(const char *url) :
|
xmrig::Pool::Pool(const char *url) :
|
||||||
m_keepAlive(0),
|
m_flags(1 << FLAG_ENABLED),
|
||||||
m_flags(1),
|
m_pollInterval(kDefaultPollInterval),
|
||||||
m_port(kDefaultPort),
|
m_url(url)
|
||||||
m_pollInterval(kDefaultPollInterval)
|
|
||||||
{
|
{
|
||||||
parse(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xmrig::Pool::Pool(const rapidjson::Value &object) :
|
xmrig::Pool::Pool(const rapidjson::Value &object) :
|
||||||
m_keepAlive(0),
|
m_flags(1 << FLAG_ENABLED),
|
||||||
m_flags(1),
|
m_pollInterval(kDefaultPollInterval),
|
||||||
m_port(kDefaultPort),
|
m_url(Json::getString(object, kUrl))
|
||||||
m_pollInterval(kDefaultPollInterval)
|
|
||||||
{
|
{
|
||||||
if (!parse(Json::getString(object, kUrl))) {
|
if (!m_url.isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,11 +92,18 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
|
|||||||
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
|
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
|
||||||
m_algorithm = Json::getString(object, kAlgo);
|
m_algorithm = Json::getString(object, kAlgo);
|
||||||
m_coin = Json::getString(object, kCoin);
|
m_coin = Json::getString(object, kCoin);
|
||||||
|
m_daemon = Json::getString(object, kSelfSelect);
|
||||||
|
|
||||||
m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true));
|
m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true));
|
||||||
m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash));
|
m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash));
|
||||||
m_flags.set(FLAG_TLS, Json::getBool(object, kTls, m_flags.test(FLAG_TLS)));
|
m_flags.set(FLAG_TLS, Json::getBool(object, kTls) || m_url.isTLS());
|
||||||
m_flags.set(FLAG_DAEMON, Json::getBool(object, kDaemon, m_flags.test(FLAG_DAEMON)));
|
|
||||||
|
if (m_daemon.isValid()) {
|
||||||
|
m_mode = MODE_SELF_SELECT;
|
||||||
|
}
|
||||||
|
else if (Json::getBool(object, kDaemon)) {
|
||||||
|
m_mode = MODE_DAEMON;
|
||||||
|
}
|
||||||
|
|
||||||
const rapidjson::Value &keepalive = Json::getValue(object, kKeepalive);
|
const rapidjson::Value &keepalive = Json::getValue(object, kKeepalive);
|
||||||
if (keepalive.IsInt()) {
|
if (keepalive.IsInt()) {
|
||||||
@@ -140,21 +117,12 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
|
|||||||
|
|
||||||
xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls) :
|
xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls) :
|
||||||
m_keepAlive(keepAlive),
|
m_keepAlive(keepAlive),
|
||||||
m_flags(1),
|
m_flags(1 << FLAG_ENABLED),
|
||||||
m_host(host),
|
|
||||||
m_password(password),
|
m_password(password),
|
||||||
m_user(user),
|
m_user(user),
|
||||||
m_port(port),
|
m_pollInterval(kDefaultPollInterval),
|
||||||
m_pollInterval(kDefaultPollInterval)
|
m_url(host, port, tls)
|
||||||
{
|
{
|
||||||
const size_t size = m_host.size() + 8;
|
|
||||||
assert(size > 8);
|
|
||||||
|
|
||||||
char *url = new char[size]();
|
|
||||||
snprintf(url, size - 1, "%s:%d", m_host.data(), m_port);
|
|
||||||
|
|
||||||
m_url = url;
|
|
||||||
|
|
||||||
m_flags.set(FLAG_NICEHASH, nicehash);
|
m_flags.set(FLAG_NICEHASH, nicehash);
|
||||||
m_flags.set(FLAG_TLS, tls);
|
m_flags.set(FLAG_TLS, tls);
|
||||||
}
|
}
|
||||||
@@ -169,12 +137,18 @@ bool xmrig::Pool::isEnabled() const
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifndef XMRIG_FEATURE_HTTP
|
# ifndef XMRIG_FEATURE_HTTP
|
||||||
if (isDaemon()) {
|
if (m_mode == MODE_DAEMON) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
if (isDaemon() && (!algorithm().isValid() && !coin().isValid())) {
|
# ifndef XMRIG_FEATURE_HTTP
|
||||||
|
if (m_mode == MODE_SELF_SELECT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (m_mode == MODE_DAEMON && (!algorithm().isValid() && !coin().isValid())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,79 +160,43 @@ bool xmrig::Pool::isEqual(const Pool &other) const
|
|||||||
{
|
{
|
||||||
return (m_flags == other.m_flags
|
return (m_flags == other.m_flags
|
||||||
&& m_keepAlive == other.m_keepAlive
|
&& m_keepAlive == other.m_keepAlive
|
||||||
&& m_port == other.m_port
|
|
||||||
&& m_algorithm == other.m_algorithm
|
&& m_algorithm == other.m_algorithm
|
||||||
&& m_coin == other.m_coin
|
&& m_coin == other.m_coin
|
||||||
|
&& m_mode == other.m_mode
|
||||||
&& m_fingerprint == other.m_fingerprint
|
&& m_fingerprint == other.m_fingerprint
|
||||||
&& m_host == other.m_host
|
|
||||||
&& m_password == other.m_password
|
&& m_password == other.m_password
|
||||||
&& m_rigId == other.m_rigId
|
&& m_rigId == other.m_rigId
|
||||||
&& m_url == other.m_url
|
&& m_url == other.m_url
|
||||||
&& m_user == other.m_user
|
&& m_user == other.m_user
|
||||||
&& m_pollInterval == other.m_pollInterval
|
&& m_pollInterval == other.m_pollInterval
|
||||||
|
&& m_daemon == other.m_daemon
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::Pool::parse(const char *url)
|
xmrig::IClient *xmrig::Pool::createClient(int id, IClientListener *listener) const
|
||||||
{
|
{
|
||||||
assert(url != nullptr);
|
IClient *client = nullptr;
|
||||||
if (url == nullptr) {
|
|
||||||
return false;
|
if (m_mode == MODE_POOL) {
|
||||||
|
client = new Client(id, Platform::userAgent(), listener);
|
||||||
|
}
|
||||||
|
# ifdef XMRIG_FEATURE_HTTP
|
||||||
|
else if (m_mode == MODE_DAEMON) {
|
||||||
|
client = new DaemonClient(id, listener);
|
||||||
|
}
|
||||||
|
else if (m_mode == MODE_SELF_SELECT) {
|
||||||
|
client = new SelfSelectClient(id, Platform::userAgent(), listener);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
assert(client != nullptr);
|
||||||
|
|
||||||
|
if (client) {
|
||||||
|
client->setPool(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *p = strstr(url, "://");
|
return client;
|
||||||
const char *base = url;
|
|
||||||
|
|
||||||
if (p) {
|
|
||||||
if (strncasecmp(url, kStratumTcp, sizeof(kStratumTcp) - 1) == 0) {
|
|
||||||
m_flags.set(FLAG_DAEMON, false);
|
|
||||||
m_flags.set(FLAG_TLS, false);
|
|
||||||
}
|
|
||||||
else if (strncasecmp(url, kStratumSsl, sizeof(kStratumSsl) - 1) == 0) {
|
|
||||||
m_flags.set(FLAG_DAEMON, false);
|
|
||||||
m_flags.set(FLAG_TLS, true);
|
|
||||||
}
|
|
||||||
# ifdef XMRIG_FEATURE_HTTP
|
|
||||||
else if (strncasecmp(url, kDaemonHttps, sizeof(kDaemonHttps) - 1) == 0) {
|
|
||||||
m_flags.set(FLAG_DAEMON, true);
|
|
||||||
m_flags.set(FLAG_TLS, true);
|
|
||||||
}
|
|
||||||
else if (strncasecmp(url, kDaemonHttp, sizeof(kDaemonHttp) - 1) == 0) {
|
|
||||||
m_flags.set(FLAG_DAEMON, true);
|
|
||||||
m_flags.set(FLAG_TLS, false);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
base = p + 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strlen(base) || *base == '/') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_url = url;
|
|
||||||
if (base[0] == '[') {
|
|
||||||
return parseIPv6(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *port = strchr(base, ':');
|
|
||||||
if (!port) {
|
|
||||||
m_host = base;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t size = static_cast<size_t>(port++ - base + 1);
|
|
||||||
char *host = new char[size]();
|
|
||||||
memcpy(host, base, size - 1);
|
|
||||||
|
|
||||||
m_host = host;
|
|
||||||
m_port = static_cast<uint16_t>(strtol(port, nullptr, 10));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -272,10 +210,10 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
|
|||||||
|
|
||||||
obj.AddMember(StringRef(kAlgo), m_algorithm.toJSON(), allocator);
|
obj.AddMember(StringRef(kAlgo), m_algorithm.toJSON(), allocator);
|
||||||
obj.AddMember(StringRef(kCoin), m_coin.toJSON(), allocator);
|
obj.AddMember(StringRef(kCoin), m_coin.toJSON(), allocator);
|
||||||
obj.AddMember(StringRef(kUrl), m_url.toJSON(), allocator);
|
obj.AddMember(StringRef(kUrl), url().toJSON(), allocator);
|
||||||
obj.AddMember(StringRef(kUser), m_user.toJSON(), allocator);
|
obj.AddMember(StringRef(kUser), m_user.toJSON(), allocator);
|
||||||
|
|
||||||
if (!isDaemon()) {
|
if (m_mode != MODE_DAEMON) {
|
||||||
obj.AddMember(StringRef(kPass), m_password.toJSON(), allocator);
|
obj.AddMember(StringRef(kPass), m_password.toJSON(), allocator);
|
||||||
obj.AddMember(StringRef(kRigId), m_rigId.toJSON(), allocator);
|
obj.AddMember(StringRef(kRigId), m_rigId.toJSON(), allocator);
|
||||||
|
|
||||||
@@ -294,22 +232,44 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
|
|||||||
obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator);
|
obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator);
|
||||||
obj.AddMember(StringRef(kTls), isTLS(), allocator);
|
obj.AddMember(StringRef(kTls), isTLS(), allocator);
|
||||||
obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator);
|
obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator);
|
||||||
obj.AddMember(StringRef(kDaemon), m_flags.test(FLAG_DAEMON), allocator);
|
obj.AddMember(StringRef(kDaemon), m_mode == MODE_DAEMON, allocator);
|
||||||
|
|
||||||
if (isDaemon()) {
|
if (m_mode == MODE_DAEMON) {
|
||||||
obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator);
|
obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
obj.AddMember(StringRef(kSelfSelect), m_daemon.url().toJSON(), allocator);
|
||||||
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string xmrig::Pool::printableName() const
|
||||||
|
{
|
||||||
|
std::string out(CSI "1;" + std::to_string(isEnabled() ? (isTLS() ? 32 : 36) : 31) + "m" + url().data() + CLEAR);
|
||||||
|
|
||||||
|
if (m_coin.isValid()) {
|
||||||
|
out += std::string(" coin ") + WHITE_BOLD_S + m_coin.name() + CLEAR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out += std::string(" algo ") + WHITE_BOLD_S + (m_algorithm.isValid() ? m_algorithm.shortName() : "auto") + CLEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mode == MODE_SELF_SELECT) {
|
||||||
|
out += std::string(" self-select ") + CSI "1;" + std::to_string(m_daemon.isTLS() ? 32 : 36) + "m" + m_daemon.url().data() + CLEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef APP_DEBUG
|
#ifdef APP_DEBUG
|
||||||
void xmrig::Pool::print() const
|
void xmrig::Pool::print() const
|
||||||
{
|
{
|
||||||
LOG_NOTICE("url: %s", m_url.data());
|
LOG_NOTICE("url: %s", url().data());
|
||||||
LOG_DEBUG ("host: %s", m_host.data());
|
LOG_DEBUG ("host: %s", host().data());
|
||||||
LOG_DEBUG ("port: %d", static_cast<int>(m_port));
|
LOG_DEBUG ("port: %d", static_cast<int>(port()));
|
||||||
LOG_DEBUG ("user: %s", m_user.data());
|
LOG_DEBUG ("user: %s", m_user.data());
|
||||||
LOG_DEBUG ("pass: %s", m_password.data());
|
LOG_DEBUG ("pass: %s", m_password.data());
|
||||||
LOG_DEBUG ("rig-id %s", m_rigId.data());
|
LOG_DEBUG ("rig-id %s", m_rigId.data());
|
||||||
@@ -318,26 +278,3 @@ void xmrig::Pool::print() const
|
|||||||
LOG_DEBUG ("keepAlive: %d", m_keepAlive);
|
LOG_DEBUG ("keepAlive: %d", m_keepAlive);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
bool xmrig::Pool::parseIPv6(const char *addr)
|
|
||||||
{
|
|
||||||
const char *end = strchr(addr, ']');
|
|
||||||
if (!end) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *port = strchr(end, ':');
|
|
||||||
if (!port) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t size = static_cast<size_t>(end - addr);
|
|
||||||
char *host = new char[size]();
|
|
||||||
memcpy(host, addr + 1, size - 1);
|
|
||||||
|
|
||||||
m_host = host;
|
|
||||||
m_port = static_cast<uint16_t>(strtol(port + 1, nullptr, 10));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
#include "base/tools/String.h"
|
#include "base/net/stratum/Url.h"
|
||||||
#include "crypto/common/Coin.h"
|
#include "crypto/common/Coin.h"
|
||||||
#include "rapidjson/fwd.h"
|
#include "rapidjson/fwd.h"
|
||||||
|
|
||||||
@@ -39,15 +39,17 @@
|
|||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class IClient;
|
||||||
|
class IClientListener;
|
||||||
|
|
||||||
|
|
||||||
class Pool
|
class Pool
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Flags {
|
enum Mode {
|
||||||
FLAG_ENABLED,
|
MODE_POOL,
|
||||||
FLAG_NICEHASH,
|
MODE_DAEMON,
|
||||||
FLAG_TLS,
|
MODE_SELF_SELECT
|
||||||
FLAG_DAEMON,
|
|
||||||
FLAG_MAX
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const String kDefaultPassword;
|
static const String kDefaultPassword;
|
||||||
@@ -57,7 +59,7 @@ public:
|
|||||||
constexpr static uint16_t kDefaultPort = 3333;
|
constexpr static uint16_t kDefaultPort = 3333;
|
||||||
constexpr static uint64_t kDefaultPollInterval = 1000;
|
constexpr static uint64_t kDefaultPollInterval = 1000;
|
||||||
|
|
||||||
Pool();
|
Pool() = default;
|
||||||
Pool(const char *url);
|
Pool(const char *url);
|
||||||
Pool(const rapidjson::Value &object);
|
Pool(const rapidjson::Value &object);
|
||||||
Pool(const char *host,
|
Pool(const char *host,
|
||||||
@@ -69,20 +71,21 @@ public:
|
|||||||
bool tls = false
|
bool tls = false
|
||||||
);
|
);
|
||||||
|
|
||||||
inline bool isDaemon() const { return m_flags.test(FLAG_DAEMON); }
|
|
||||||
inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); }
|
inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); }
|
||||||
inline bool isTLS() const { return m_flags.test(FLAG_TLS); }
|
inline bool isTLS() const { return m_flags.test(FLAG_TLS); }
|
||||||
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
|
inline bool isValid() const { return m_url.isValid(); }
|
||||||
inline const Algorithm &algorithm() const { return m_algorithm; }
|
inline const Algorithm &algorithm() const { return m_algorithm; }
|
||||||
inline const Coin &coin() const { return m_coin; }
|
inline const Coin &coin() const { return m_coin; }
|
||||||
inline const String &fingerprint() const { return m_fingerprint; }
|
inline const String &fingerprint() const { return m_fingerprint; }
|
||||||
inline const String &host() const { return m_host; }
|
inline const String &host() const { return m_url.host(); }
|
||||||
inline const String &password() const { return !m_password.isNull() ? m_password : kDefaultPassword; }
|
inline const String &password() const { return !m_password.isNull() ? m_password : kDefaultPassword; }
|
||||||
inline const String &rigId() const { return m_rigId; }
|
inline const String &rigId() const { return m_rigId; }
|
||||||
inline const String &url() const { return m_url; }
|
inline const String &url() const { return m_url.url(); }
|
||||||
inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; }
|
inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; }
|
||||||
|
inline const Url &daemon() const { return m_daemon; }
|
||||||
inline int keepAlive() const { return m_keepAlive; }
|
inline int keepAlive() const { return m_keepAlive; }
|
||||||
inline uint16_t port() const { return m_port; }
|
inline Mode mode() const { return m_mode; }
|
||||||
|
inline uint16_t port() const { return m_url.port(); }
|
||||||
inline uint64_t pollInterval() const { return m_pollInterval; }
|
inline uint64_t pollInterval() const { return m_pollInterval; }
|
||||||
inline void setAlgo(const Algorithm &algorithm) { m_algorithm = algorithm; }
|
inline void setAlgo(const Algorithm &algorithm) { m_algorithm = algorithm; }
|
||||||
inline void setPassword(const String &password) { m_password = password; }
|
inline void setPassword(const String &password) { m_password = password; }
|
||||||
@@ -94,31 +97,37 @@ public:
|
|||||||
|
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
bool isEqual(const Pool &other) const;
|
bool isEqual(const Pool &other) const;
|
||||||
bool parse(const char *url);
|
IClient *createClient(int id, IClientListener *listener) const;
|
||||||
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
||||||
|
std::string printableName() const;
|
||||||
|
|
||||||
# ifdef APP_DEBUG
|
# ifdef APP_DEBUG
|
||||||
void print() const;
|
void print() const;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum Flags {
|
||||||
|
FLAG_ENABLED,
|
||||||
|
FLAG_NICEHASH,
|
||||||
|
FLAG_TLS,
|
||||||
|
FLAG_MAX
|
||||||
|
};
|
||||||
|
|
||||||
inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); }
|
inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); }
|
||||||
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
|
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
|
||||||
|
|
||||||
bool parseIPv6(const char *addr);
|
|
||||||
|
|
||||||
Algorithm m_algorithm;
|
Algorithm m_algorithm;
|
||||||
Coin m_coin;
|
Coin m_coin;
|
||||||
int m_keepAlive;
|
int m_keepAlive = 0;
|
||||||
std::bitset<FLAG_MAX> m_flags;
|
Mode m_mode = MODE_POOL;
|
||||||
|
std::bitset<FLAG_MAX> m_flags = 0;
|
||||||
String m_fingerprint;
|
String m_fingerprint;
|
||||||
String m_host;
|
|
||||||
String m_password;
|
String m_password;
|
||||||
String m_rigId;
|
String m_rigId;
|
||||||
String m_url;
|
|
||||||
String m_user;
|
String m_user;
|
||||||
uint16_t m_port;
|
uint64_t m_pollInterval = kDefaultPollInterval;
|
||||||
uint64_t m_pollInterval;
|
Url m_daemon;
|
||||||
|
Url m_url;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ xmrig::IStrategy *xmrig::Pools::createStrategy(IStrategyListener *listener) cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FailoverStrategy *strategy = new FailoverStrategy(retryPause(), retries(), listener);
|
auto strategy = new FailoverStrategy(retryPause(), retries(), listener);
|
||||||
for (const Pool &pool : m_data) {
|
for (const Pool &pool : m_data) {
|
||||||
if (pool.isEnabled()) {
|
if (pool.isEnabled()) {
|
||||||
strategy->add(pool);
|
strategy->add(pool);
|
||||||
@@ -135,13 +135,7 @@ void xmrig::Pools::print() const
|
|||||||
{
|
{
|
||||||
size_t i = 1;
|
size_t i = 1;
|
||||||
for (const Pool &pool : m_data) {
|
for (const Pool &pool : m_data) {
|
||||||
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " %s " WHITE_BOLD("%s"),
|
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") "%s", i, pool.printableName().c_str());
|
||||||
i,
|
|
||||||
(pool.isEnabled() ? (pool.isTLS() ? 32 : 36) : 31),
|
|
||||||
pool.url().data(),
|
|
||||||
pool.coin().isValid() ? "coin" : "algo",
|
|
||||||
pool.coin().isValid() ? pool.coin().name() : (pool.algorithm().isValid() ? pool.algorithm().shortName() : "auto")
|
|
||||||
);
|
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|||||||
306
src/base/net/stratum/SelfSelectClient.cpp
Normal file
306
src/base/net/stratum/SelfSelectClient.cpp
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2019 jtgrassie <https://github.com/jtgrassie>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/net/stratum/SelfSelectClient.h"
|
||||||
|
#include "3rdparty/http-parser/http_parser.h"
|
||||||
|
#include "base/io/json/Json.h"
|
||||||
|
#include "base/io/json/JsonRequest.h"
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
|
#include "base/net/http/HttpClient.h"
|
||||||
|
#include "base/net/stratum/Client.h"
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
#include "rapidjson/error/en.h"
|
||||||
|
#include "rapidjson/stringbuffer.h"
|
||||||
|
#include "rapidjson/writer.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_TLS
|
||||||
|
# include "base/net/http/HttpsClient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
static const char *kBlob = "blob";
|
||||||
|
static const char *kBlockhashingBlob = "blockhashing_blob";
|
||||||
|
static const char *kBlocktemplateBlob = "blocktemplate_blob";
|
||||||
|
static const char *kDifficulty = "difficulty";
|
||||||
|
static const char *kHeight = "height";
|
||||||
|
static const char *kId = "id";
|
||||||
|
static const char *kJobId = "job_id";
|
||||||
|
static const char *kNextSeedHash = "next_seed_hash";
|
||||||
|
static const char *kPrevHash = "prev_hash";
|
||||||
|
static const char *kSeedHash = "seed_hash";
|
||||||
|
|
||||||
|
static const char * const required_fields[] = { kBlocktemplateBlob, kBlockhashingBlob, kHeight, kDifficulty, kPrevHash };
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::SelfSelectClient::SelfSelectClient(int id, const char *agent, IClientListener *listener) :
|
||||||
|
m_listener(listener)
|
||||||
|
{
|
||||||
|
m_client = new Client(id, agent, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::SelfSelectClient::~SelfSelectClient()
|
||||||
|
{
|
||||||
|
delete m_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::tick(uint64_t now)
|
||||||
|
{
|
||||||
|
m_client->tick(now);
|
||||||
|
|
||||||
|
if (m_state == RetryState) {
|
||||||
|
if (Chrono::steadyMSecs() - m_timestamp < m_retryPause) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBlockTemplate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::onJobReceived(IClient *, const Job &job, const rapidjson::Value &)
|
||||||
|
{
|
||||||
|
m_job = job;
|
||||||
|
|
||||||
|
getBlockTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::onLogin(IClient *, rapidjson::Document &doc, rapidjson::Value ¶ms)
|
||||||
|
{
|
||||||
|
params.AddMember("mode", "self-select", doc.GetAllocator());
|
||||||
|
|
||||||
|
m_listener->onLogin(this, doc, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::SelfSelectClient::parseResponse(int64_t id, rapidjson::Value &result, const rapidjson::Value &error)
|
||||||
|
{
|
||||||
|
if (id == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.IsObject()) {
|
||||||
|
LOG_ERR("[%s] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", pool().daemon().url().data(), Json::getString(error, "message"), Json::getInt(error, "code"));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.IsObject()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto field : required_fields) {
|
||||||
|
if (!result.HasMember(field)) {
|
||||||
|
LOG_ERR("[%s] required field " RED_BOLD("\"%s\"") RED_S " not found", pool().daemon().url().data(), field);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_job.setBlob(result[kBlockhashingBlob].GetString())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pool().coin().isValid()) {
|
||||||
|
m_job.setAlgorithm(pool().coin().algorithm(m_job.blob()[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_job.setHeight(Json::getUint64(result, kHeight));
|
||||||
|
m_job.setSeedHash(Json::getString(result, kSeedHash));
|
||||||
|
|
||||||
|
submitBlockTemplate(result);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::getBlockTemplate()
|
||||||
|
{
|
||||||
|
setState(WaitState);
|
||||||
|
|
||||||
|
using namespace rapidjson;
|
||||||
|
Document doc(kObjectType);
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
Value params(kObjectType);
|
||||||
|
params.AddMember("wallet_address", m_job.poolWallet().toJSON(), allocator);
|
||||||
|
params.AddMember("extra_nonce", m_job.extraNonce().toJSON(), allocator);
|
||||||
|
|
||||||
|
JsonRequest::create(doc, m_sequence++, "getblocktemplate", params);
|
||||||
|
|
||||||
|
send(HTTP_POST, "/json_rpc", doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::retry()
|
||||||
|
{
|
||||||
|
setState(RetryState);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::send(int method, const char *url, const char *data, size_t size)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("[%s] " MAGENTA_BOLD("\"%s %s\"") BLACK_BOLD_S " send (%zu bytes): \"%.*s\"",
|
||||||
|
pool().daemon().url().data(),
|
||||||
|
http_method_str(static_cast<http_method>(method)),
|
||||||
|
url,
|
||||||
|
size,
|
||||||
|
static_cast<int>(size),
|
||||||
|
data);
|
||||||
|
|
||||||
|
HttpClient *client;
|
||||||
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
|
if (pool().daemon().isTLS()) {
|
||||||
|
client = new HttpsClient(method, url, this, data, size, String());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
client = new HttpClient(method, url, this, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
client->setQuiet(isQuiet());
|
||||||
|
client->connect(pool().daemon().host(), pool().daemon().port());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::send(int method, const char *url, const rapidjson::Document &doc)
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
|
||||||
|
StringBuffer buffer(nullptr, 512);
|
||||||
|
Writer<StringBuffer> writer(buffer);
|
||||||
|
doc.Accept(writer);
|
||||||
|
|
||||||
|
send(method, url, buffer.GetString(), buffer.GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::setState(State state)
|
||||||
|
{
|
||||||
|
if (m_state == state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case IdleState:
|
||||||
|
m_timestamp = 0;
|
||||||
|
m_failures = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WaitState:
|
||||||
|
m_timestamp = Chrono::steadyMSecs();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RetryState:
|
||||||
|
m_timestamp = Chrono::steadyMSecs();
|
||||||
|
|
||||||
|
if (m_failures > m_retries) {
|
||||||
|
m_listener->onClose(this, static_cast<int>(m_failures));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_failures++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::submitBlockTemplate(rapidjson::Value &result)
|
||||||
|
{
|
||||||
|
using namespace rapidjson;
|
||||||
|
Document doc(kObjectType);
|
||||||
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
Value params(kObjectType);
|
||||||
|
params.AddMember(StringRef(kId), m_job.clientId().toJSON(), allocator);
|
||||||
|
params.AddMember(StringRef(kJobId), m_job.id().toJSON(), allocator);
|
||||||
|
params.AddMember(StringRef(kBlob), result[kBlocktemplateBlob], allocator);
|
||||||
|
params.AddMember(StringRef(kHeight), m_job.height(), allocator);
|
||||||
|
params.AddMember(StringRef(kDifficulty), result[kDifficulty], allocator);
|
||||||
|
params.AddMember(StringRef(kPrevHash), result[kPrevHash], allocator);
|
||||||
|
params.AddMember(StringRef(kSeedHash), result[kSeedHash], allocator);
|
||||||
|
params.AddMember(StringRef(kNextSeedHash), result[kNextSeedHash], allocator);
|
||||||
|
|
||||||
|
JsonRequest::create(doc, sequence(), "block_template", params);
|
||||||
|
|
||||||
|
send(doc, [this](const rapidjson::Value &result, bool success, uint64_t elapsed) {
|
||||||
|
if (!success) {
|
||||||
|
if (!isQuiet()) {
|
||||||
|
LOG_ERR("[%s] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", pool().daemon().url().data(), Json::getString(result, "message"), Json::getInt(result, "code"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return retry();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_failures > m_retries) {
|
||||||
|
m_listener->onLoginSuccess(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(IdleState);
|
||||||
|
m_listener->onJobReceived(this, m_job, rapidjson::Value{});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::onHttpData(const HttpData &data)
|
||||||
|
{
|
||||||
|
if (data.status != HTTP_STATUS_OK) {
|
||||||
|
return retry();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", pool().daemon().url().data(), static_cast<int>(data.body.size()), static_cast<int>(data.body.size()), data.body.c_str());
|
||||||
|
|
||||||
|
rapidjson::Document doc;
|
||||||
|
if (doc.Parse(data.body.c_str()).HasParseError()) {
|
||||||
|
if (!isQuiet()) {
|
||||||
|
LOG_ERR("[%s] JSON decode failed: \"%s\"", pool().daemon().url().data(), rapidjson::GetParseError_En(doc.GetParseError()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return retry();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int64_t id = Json::getInt64(doc, "id", -1);
|
||||||
|
if (id > 0 && m_sequence - id != 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parseResponse(id, doc["result"], Json::getObject(doc, "error"))) {
|
||||||
|
retry();
|
||||||
|
}
|
||||||
|
}
|
||||||
123
src/base/net/stratum/SelfSelectClient.h
Normal file
123
src/base/net/stratum/SelfSelectClient.h
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2019 jtgrassie <https://github.com/jtgrassie>
|
||||||
|
* Copyright 2016-2019 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_SELFSELECTCLIENT_H
|
||||||
|
#define XMRIG_SELFSELECTCLIENT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/kernel/interfaces/IClient.h"
|
||||||
|
#include "base/kernel/interfaces/IClientListener.h"
|
||||||
|
#include "base/kernel/interfaces/IHttpListener.h"
|
||||||
|
#include "base/net/stratum/Job.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class SelfSelectClient : public IClient, public IClientListener, public IHttpListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(SelfSelectClient)
|
||||||
|
|
||||||
|
SelfSelectClient(int id, const char *agent, IClientListener *listener);
|
||||||
|
~SelfSelectClient() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// IClient
|
||||||
|
inline bool disconnect() override { return m_client->disconnect(); }
|
||||||
|
inline bool hasExtension(Extension extension) const noexcept override { return m_client->hasExtension(extension); }
|
||||||
|
inline bool isEnabled() const override { return m_client->isEnabled(); }
|
||||||
|
inline bool isTLS() const override { return m_client->isTLS(); }
|
||||||
|
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 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(); }
|
||||||
|
inline int64_t send(const rapidjson::Value &obj, Callback callback) override { return m_client->send(obj, callback); }
|
||||||
|
inline int64_t send(const rapidjson::Value &obj) override { return m_client->send(obj); }
|
||||||
|
inline int64_t sequence() const override { return m_client->sequence(); }
|
||||||
|
inline int64_t submit(const JobResult &result) override { return m_client->submit(result); }
|
||||||
|
inline void connect() override { m_client->connect(); }
|
||||||
|
inline void connect(const Pool &pool) override { m_client->connect(pool); }
|
||||||
|
inline void deleteLater() override { m_client->deleteLater(); }
|
||||||
|
inline void setAlgo(const Algorithm &algo) override { m_client->setAlgo(algo); }
|
||||||
|
inline void setEnabled(bool enabled) override { m_client->setEnabled(enabled); }
|
||||||
|
inline void setPool(const Pool &pool) override { m_client->setPool(pool); }
|
||||||
|
inline void setQuiet(bool quiet) override { m_client->setQuiet(quiet); m_quiet = quiet; }
|
||||||
|
inline void setRetries(int retries) override { m_client->setRetries(retries); m_retries = retries; }
|
||||||
|
inline void setRetryPause(uint64_t ms) override { m_client->setRetryPause(ms); m_retryPause = ms; }
|
||||||
|
|
||||||
|
void tick(uint64_t now) override;
|
||||||
|
|
||||||
|
// IClientListener
|
||||||
|
inline void onClose(IClient *, int failures) override { m_listener->onClose(this, failures); setState(IdleState); m_active = false; }
|
||||||
|
inline void onLoginSuccess(IClient *) override { m_listener->onLoginSuccess(this); setState(IdleState); m_active = true; }
|
||||||
|
inline void onResultAccepted(IClient *, const SubmitResult &result, const char *error) override { m_listener->onResultAccepted(this, result, error); }
|
||||||
|
inline void onVerifyAlgorithm(const IClient *, const Algorithm &algorithm, bool *ok) override { m_listener->onVerifyAlgorithm(this, algorithm, ok); }
|
||||||
|
|
||||||
|
void onJobReceived(IClient *, const Job &job, const rapidjson::Value ¶ms) override;
|
||||||
|
void onLogin(IClient *, rapidjson::Document &doc, rapidjson::Value ¶ms) override;
|
||||||
|
|
||||||
|
// IHttpListener
|
||||||
|
void onHttpData(const HttpData &data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum State {
|
||||||
|
IdleState,
|
||||||
|
WaitState,
|
||||||
|
RetryState
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
|
||||||
|
|
||||||
|
bool parseResponse(int64_t id, rapidjson::Value &result, const rapidjson::Value &error);
|
||||||
|
void getBlockTemplate();
|
||||||
|
void retry();
|
||||||
|
void send(int method, const char *url, const char *data = nullptr, size_t size = 0);
|
||||||
|
void send(int method, const char *url, const rapidjson::Document &doc);
|
||||||
|
void setState(State state);
|
||||||
|
void submitBlockTemplate(rapidjson::Value &result);
|
||||||
|
|
||||||
|
bool m_active = false;
|
||||||
|
bool m_quiet = false;
|
||||||
|
IClient *m_client;
|
||||||
|
IClientListener *m_listener;
|
||||||
|
int m_retries = 5;
|
||||||
|
int64_t m_failures = 0;
|
||||||
|
int64_t m_sequence = 1;
|
||||||
|
Job m_job;
|
||||||
|
State m_state = IdleState;
|
||||||
|
uint64_t m_retryPause = 5000;
|
||||||
|
uint64_t m_timestamp = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_SELFSELECTCLIENT_H */
|
||||||
@@ -35,34 +35,28 @@ namespace xmrig {
|
|||||||
class SubmitResult
|
class SubmitResult
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline SubmitResult() :
|
SubmitResult() = default;
|
||||||
reqId(0),
|
|
||||||
seq(0),
|
|
||||||
actualDiff(0),
|
|
||||||
diff(0),
|
|
||||||
elapsed(0),
|
|
||||||
m_start(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
inline SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId = 0) :
|
inline SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId, uint32_t backend) :
|
||||||
reqId(reqId),
|
reqId(reqId),
|
||||||
seq(seq),
|
seq(seq),
|
||||||
|
backend(backend),
|
||||||
actualDiff(actualDiff),
|
actualDiff(actualDiff),
|
||||||
diff(diff),
|
diff(diff),
|
||||||
elapsed(0),
|
|
||||||
m_start(Chrono::steadyMSecs())
|
m_start(Chrono::steadyMSecs())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline void done() { elapsed = Chrono::steadyMSecs() - m_start; }
|
inline void done() { elapsed = Chrono::steadyMSecs() - m_start; }
|
||||||
|
|
||||||
int64_t reqId;
|
int64_t reqId = 0;
|
||||||
int64_t seq;
|
int64_t seq = 0;
|
||||||
uint64_t actualDiff;
|
uint32_t backend = 0;
|
||||||
uint64_t diff;
|
uint64_t actualDiff = 0;
|
||||||
uint64_t elapsed;
|
uint64_t diff = 0;
|
||||||
|
uint64_t elapsed = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t m_start;
|
uint64_t m_start = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
163
src/base/net/stratum/Url.cpp
Normal file
163
src/base/net/stratum/Url.cpp
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2019 Howard Chu <https://github.com/hyc>
|
||||||
|
* Copyright 2016-2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/net/stratum/Url.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# define strncasecmp _strnicmp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
static const char kStratumTcp[] = "stratum+tcp://";
|
||||||
|
static const char kStratumSsl[] = "stratum+ssl://";
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_HTTP
|
||||||
|
static const char kDaemonHttp[] = "daemon+http://";
|
||||||
|
static const char kDaemonHttps[] = "daemon+https://";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::Url::Url(const char *url)
|
||||||
|
{
|
||||||
|
parse(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmrig::Url::Url(const char *host, uint16_t port, bool tls, Scheme scheme) :
|
||||||
|
m_tls(tls),
|
||||||
|
m_scheme(scheme),
|
||||||
|
m_host(host),
|
||||||
|
m_port(port)
|
||||||
|
{
|
||||||
|
const size_t size = m_host.size() + 8;
|
||||||
|
assert(size > 8);
|
||||||
|
|
||||||
|
char *url = new char[size]();
|
||||||
|
snprintf(url, size - 1, "%s:%d", m_host.data(), m_port);
|
||||||
|
|
||||||
|
m_url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::Url::isEqual(const Url &other) const
|
||||||
|
{
|
||||||
|
return (m_tls == other.m_tls && m_scheme == other.m_scheme && m_host == other.m_host && m_url == other.m_url && m_port == other.m_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::Url::parse(const char *url)
|
||||||
|
{
|
||||||
|
if (url == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *p = strstr(url, "://");
|
||||||
|
const char *base = url;
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
if (strncasecmp(url, kStratumTcp, sizeof(kStratumTcp) - 1) == 0) {
|
||||||
|
m_scheme = STRATUM;
|
||||||
|
m_tls = false;
|
||||||
|
}
|
||||||
|
else if (strncasecmp(url, kStratumSsl, sizeof(kStratumSsl) - 1) == 0) {
|
||||||
|
m_scheme = STRATUM;
|
||||||
|
m_tls = true;
|
||||||
|
}
|
||||||
|
# ifdef XMRIG_FEATURE_HTTP
|
||||||
|
else if (strncasecmp(url, kDaemonHttps, sizeof(kDaemonHttps) - 1) == 0) {
|
||||||
|
m_scheme = DAEMON;
|
||||||
|
m_tls = true;
|
||||||
|
}
|
||||||
|
else if (strncasecmp(url, kDaemonHttp, sizeof(kDaemonHttp) - 1) == 0) {
|
||||||
|
m_scheme = DAEMON;
|
||||||
|
m_tls = false;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = p + 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strlen(base) || *base == '/') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_url = url;
|
||||||
|
if (base[0] == '[') {
|
||||||
|
return parseIPv6(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *port = strchr(base, ':');
|
||||||
|
if (!port) {
|
||||||
|
m_host = base;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto size = static_cast<size_t>(port++ - base + 1);
|
||||||
|
char *host = new char[size]();
|
||||||
|
memcpy(host, base, size - 1);
|
||||||
|
|
||||||
|
m_host = host;
|
||||||
|
m_port = static_cast<uint16_t>(strtol(port, nullptr, 10));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::Url::parseIPv6(const char *addr)
|
||||||
|
{
|
||||||
|
const char *end = strchr(addr, ']');
|
||||||
|
if (!end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *port = strchr(end, ':');
|
||||||
|
if (!port) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto size = static_cast<size_t>(end - addr);
|
||||||
|
char *host = new char[size]();
|
||||||
|
memcpy(host, addr + 1, size - 1);
|
||||||
|
|
||||||
|
m_host = host;
|
||||||
|
m_port = static_cast<uint16_t>(strtol(port + 1, nullptr, 10));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
77
src/base/net/stratum/Url.h
Normal file
77
src/base/net/stratum/Url.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||||
|
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2019 Howard Chu <https://github.com/hyc>
|
||||||
|
* Copyright 2016-2019 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_URL_H
|
||||||
|
#define XMRIG_URL_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/tools/String.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class Url
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Scheme {
|
||||||
|
UNSPECIFIED,
|
||||||
|
STRATUM,
|
||||||
|
DAEMON
|
||||||
|
};
|
||||||
|
|
||||||
|
Url() = default;
|
||||||
|
Url(const char *url);
|
||||||
|
Url(const char *host, uint16_t port, bool tls = false, Scheme scheme = UNSPECIFIED);
|
||||||
|
|
||||||
|
inline bool isTLS() const { return m_tls; }
|
||||||
|
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
|
||||||
|
inline const String &host() const { return m_host; }
|
||||||
|
inline const String &url() const { return m_url; }
|
||||||
|
inline Scheme scheme() const { return m_scheme; }
|
||||||
|
inline uint16_t port() const { return m_port; }
|
||||||
|
|
||||||
|
inline bool operator!=(const Url &other) const { return !isEqual(other); }
|
||||||
|
inline bool operator==(const Url &other) const { return isEqual(other); }
|
||||||
|
|
||||||
|
bool isEqual(const Url &other) const;
|
||||||
|
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool parse(const char *url);
|
||||||
|
bool parseIPv6(const char *addr);
|
||||||
|
|
||||||
|
bool m_tls = false;
|
||||||
|
Scheme m_scheme = UNSPECIFIED;
|
||||||
|
String m_host;
|
||||||
|
String m_url;
|
||||||
|
uint16_t m_port = 3333;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_URL_H */
|
||||||
@@ -23,15 +23,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/net/stratum/strategies/FailoverStrategy.h"
|
||||||
|
#include "base/kernel/interfaces/IClient.h"
|
||||||
#include "base/kernel/interfaces/IStrategyListener.h"
|
#include "base/kernel/interfaces/IStrategyListener.h"
|
||||||
#include "base/kernel/Platform.h"
|
#include "base/kernel/Platform.h"
|
||||||
#include "base/net/stratum/Client.h"
|
|
||||||
#include "base/net/stratum/strategies/FailoverStrategy.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef XMRIG_FEATURE_HTTP
|
|
||||||
# include "base/net/stratum/DaemonClient.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
xmrig::FailoverStrategy::FailoverStrategy(const std::vector<Pool> &pools, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
|
xmrig::FailoverStrategy::FailoverStrategy(const std::vector<Pool> &pools, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
|
||||||
@@ -69,16 +64,8 @@ xmrig::FailoverStrategy::~FailoverStrategy()
|
|||||||
|
|
||||||
void xmrig::FailoverStrategy::add(const Pool &pool)
|
void xmrig::FailoverStrategy::add(const Pool &pool)
|
||||||
{
|
{
|
||||||
const int id = static_cast<int>(m_pools.size());
|
IClient *client = pool.createClient(static_cast<int>(m_pools.size()), this);
|
||||||
|
|
||||||
# ifdef XMRIG_FEATURE_HTTP
|
|
||||||
IClient *client = !pool.isDaemon() ? static_cast<IClient *>(new Client(id, Platform::userAgent(), this))
|
|
||||||
: static_cast<IClient *>(new DaemonClient(id, this));
|
|
||||||
# else
|
|
||||||
IClient *client = new Client(id, Platform::userAgent(), this);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
client->setPool(pool);
|
|
||||||
client->setRetries(m_retries);
|
client->setRetries(m_retries);
|
||||||
client->setRetryPause(m_retryPause * 1000);
|
client->setRetryPause(m_retryPause * 1000);
|
||||||
client->setQuiet(m_quiet);
|
client->setQuiet(m_quiet);
|
||||||
@@ -123,8 +110,8 @@ void xmrig::FailoverStrategy::setAlgo(const Algorithm &algo)
|
|||||||
|
|
||||||
void xmrig::FailoverStrategy::stop()
|
void xmrig::FailoverStrategy::stop()
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_pools.size(); ++i) {
|
for (auto &pool : m_pools) {
|
||||||
m_pools[i]->disconnect();
|
pool->disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_index = 0;
|
m_index = 0;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "base/kernel/interfaces/IClientListener.h"
|
#include "base/kernel/interfaces/IClientListener.h"
|
||||||
#include "base/kernel/interfaces/IStrategy.h"
|
#include "base/kernel/interfaces/IStrategy.h"
|
||||||
#include "base/net/stratum/Pool.h"
|
#include "base/net/stratum/Pool.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -44,6 +45,8 @@ class IStrategyListener;
|
|||||||
class FailoverStrategy : public IStrategy, public IClientListener
|
class FailoverStrategy : public IStrategy, public IClientListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(FailoverStrategy)
|
||||||
|
|
||||||
FailoverStrategy(const std::vector<Pool> &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet = false);
|
FailoverStrategy(const std::vector<Pool> &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet = false);
|
||||||
FailoverStrategy(int retryPause, int retries, IStrategyListener *listener, bool quiet = false);
|
FailoverStrategy(int retryPause, int retries, IStrategyListener *listener, bool quiet = false);
|
||||||
~FailoverStrategy() override;
|
~FailoverStrategy() override;
|
||||||
|
|||||||
@@ -23,33 +23,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/net/stratum/strategies/SinglePoolStrategy.h"
|
||||||
|
#include "base/kernel/interfaces/IClient.h"
|
||||||
#include "base/kernel/interfaces/IStrategyListener.h"
|
#include "base/kernel/interfaces/IStrategyListener.h"
|
||||||
#include "base/kernel/Platform.h"
|
#include "base/kernel/Platform.h"
|
||||||
#include "base/net/stratum/Client.h"
|
#include "base/net/stratum/Pool.h"
|
||||||
#include "base/net/stratum/strategies/SinglePoolStrategy.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef XMRIG_FEATURE_HTTP
|
|
||||||
# include "base/net/stratum/DaemonClient.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
xmrig::SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
|
xmrig::SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
|
||||||
m_active(false),
|
m_active(false),
|
||||||
m_listener(listener)
|
m_listener(listener)
|
||||||
{
|
{
|
||||||
# ifdef XMRIG_FEATURE_HTTP
|
m_client = pool.createClient(0, this);
|
||||||
if (!pool.isDaemon()) {
|
|
||||||
m_client = new Client(0, Platform::userAgent(), this);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_client = new DaemonClient(0, this);
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
m_client = new Client(0, Platform::userAgent(), this);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
m_client->setPool(pool);
|
|
||||||
m_client->setRetries(retries);
|
m_client->setRetries(retries);
|
||||||
m_client->setRetryPause(retryPause * 1000);
|
m_client->setRetryPause(retryPause * 1000);
|
||||||
m_client->setQuiet(quiet);
|
m_client->setQuiet(quiet);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "base/kernel/interfaces/IClientListener.h"
|
#include "base/kernel/interfaces/IClientListener.h"
|
||||||
#include "base/kernel/interfaces/IStrategy.h"
|
#include "base/kernel/interfaces/IStrategy.h"
|
||||||
|
#include "base/tools/Object.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
@@ -41,6 +42,8 @@ class Pool;
|
|||||||
class SinglePoolStrategy : public IStrategy, public IClientListener
|
class SinglePoolStrategy : public IStrategy, public IClientListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(SinglePoolStrategy)
|
||||||
|
|
||||||
SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet = false);
|
SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet = false);
|
||||||
~SinglePoolStrategy() override;
|
~SinglePoolStrategy() override;
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,13 @@
|
|||||||
"cn/0": false,
|
"cn/0": false,
|
||||||
"cn-lite/0": false
|
"cn-lite/0": false
|
||||||
},
|
},
|
||||||
|
"cuda": {
|
||||||
|
"enabled": false,
|
||||||
|
"loader": null,
|
||||||
|
"nvml": true,
|
||||||
|
"cn/0": false,
|
||||||
|
"cn-lite/0": false
|
||||||
|
},
|
||||||
"donate-level": 5,
|
"donate-level": 5,
|
||||||
"donate-over-proxy": 1,
|
"donate-over-proxy": 1,
|
||||||
"log-file": null,
|
"log-file": null,
|
||||||
@@ -54,13 +61,15 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"tls": false,
|
"tls": false,
|
||||||
"tls-fingerprint": null,
|
"tls-fingerprint": null,
|
||||||
"daemon": false
|
"daemon": false,
|
||||||
|
"self-select": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"print-time": 60,
|
"print-time": 60,
|
||||||
|
"health-print-time": 60,
|
||||||
"retries": 5,
|
"retries": 5,
|
||||||
"retry-pause": 5,
|
"retry-pause": 5,
|
||||||
"syslog": false,
|
"syslog": false,
|
||||||
"user-agent": null,
|
"user-agent": null,
|
||||||
"watch": true
|
"watch": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XMRIG_FEATURE_CUDA
|
||||||
|
# include "backend/cuda/CudaBackend.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef XMRIG_ALGO_RANDOMX
|
#ifdef XMRIG_ALGO_RANDOMX
|
||||||
# include "crypto/rx/RxConfig.h"
|
# include "crypto/rx/RxConfig.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -152,6 +157,7 @@ public:
|
|||||||
reply.AddMember("ua", StringRef(Platform::userAgent()), allocator);
|
reply.AddMember("ua", StringRef(Platform::userAgent()), allocator);
|
||||||
reply.AddMember("cpu", Cpu::toJSON(doc), allocator);
|
reply.AddMember("cpu", Cpu::toJSON(doc), allocator);
|
||||||
reply.AddMember("donate_level", controller->config()->pools().donateLevel(), allocator);
|
reply.AddMember("donate_level", controller->config()->pools().donateLevel(), allocator);
|
||||||
|
reply.AddMember("paused", !enabled, allocator);
|
||||||
|
|
||||||
Value algo(kArrayType);
|
Value algo(kArrayType);
|
||||||
|
|
||||||
@@ -269,12 +275,17 @@ xmrig::Miner::Miner(Controller *controller)
|
|||||||
|
|
||||||
d_ptr->timer = new Timer(this);
|
d_ptr->timer = new Timer(this);
|
||||||
|
|
||||||
|
d_ptr->backends.reserve(3);
|
||||||
d_ptr->backends.push_back(new CpuBackend(controller));
|
d_ptr->backends.push_back(new CpuBackend(controller));
|
||||||
|
|
||||||
# ifdef XMRIG_FEATURE_OPENCL
|
# ifdef XMRIG_FEATURE_OPENCL
|
||||||
d_ptr->backends.push_back(new OclBackend(controller));
|
d_ptr->backends.push_back(new OclBackend(controller));
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# ifdef XMRIG_FEATURE_CUDA
|
||||||
|
d_ptr->backends.push_back(new CudaBackend(controller));
|
||||||
|
# endif
|
||||||
|
|
||||||
d_ptr->rebuild();
|
d_ptr->rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,6 +328,34 @@ xmrig::Job xmrig::Miner::job() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::Miner::execCommand(char command)
|
||||||
|
{
|
||||||
|
switch (command) {
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
printHashrate(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
case 'P':
|
||||||
|
setEnabled(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
setEnabled(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto backend : d_ptr->backends) {
|
||||||
|
backend->execCommand(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::Miner::pause()
|
void xmrig::Miner::pause()
|
||||||
{
|
{
|
||||||
d_ptr->active = false;
|
d_ptr->active = false;
|
||||||
@@ -382,7 +421,7 @@ void xmrig::Miner::setJob(const Job &job, bool donate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ifdef XMRIG_ALGO_RANDOMX
|
# ifdef XMRIG_ALGO_RANDOMX
|
||||||
if (d_ptr->algorithm.family() == Algorithm::RANDOM_X && job.algorithm().family() == Algorithm::RANDOM_X && !Rx::isReady(job)) {
|
if (job.algorithm().family() == Algorithm::RANDOM_X && !Rx::isReady(job)) {
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
@@ -455,7 +494,8 @@ void xmrig::Miner::onTimer(const Timer *)
|
|||||||
|
|
||||||
d_ptr->maxHashrate[d_ptr->algorithm] = std::max(d_ptr->maxHashrate[d_ptr->algorithm], maxHashrate);
|
d_ptr->maxHashrate[d_ptr->algorithm] = std::max(d_ptr->maxHashrate[d_ptr->algorithm], maxHashrate);
|
||||||
|
|
||||||
if ((d_ptr->ticks % (d_ptr->controller->config()->printTime() * 2)) == 0) {
|
auto seconds = d_ptr->controller->config()->printTime();
|
||||||
|
if (seconds && (d_ptr->ticks % (seconds * 2)) == 0) {
|
||||||
printHashrate(false);
|
printHashrate(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public:
|
|||||||
const Algorithms &algorithms() const;
|
const Algorithms &algorithms() const;
|
||||||
const std::vector<IBackend *> &backends() const;
|
const std::vector<IBackend *> &backends() const;
|
||||||
Job job() const;
|
Job job() const;
|
||||||
|
void execCommand(char command);
|
||||||
void pause();
|
void pause();
|
||||||
void printHashrate(bool details);
|
void printHashrate(bool details);
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user