Merge remote-tracking branch 'remotes/origin/feature-advanced-threads' into dev

This commit is contained in:
XMRig 2018-04-19 19:45:29 +07:00
commit 9be897eb6b
79 changed files with 1738 additions and 1058 deletions

View file

@ -14,15 +14,17 @@ include (cmake/cpu.cmake)
set(HEADERS
src/api/NetworkState.h
src/App.h
src/common/config/CommonConfig.h
src/common/config/ConfigLoader.h
src/common/config/ConfigWatcher.h
src/common/Platform.h
src/common/utils/c_str.h
src/common/utils/mm_malloc.h
src/common/xmrig.h
src/Console.h
src/core/CommonConfig.h
src/core/Config.cpp
src/core/ConfigLoader.cpp
src/core/ConfigLoader.h
src/core/ConfigLoader_platform.h
src/core/ConfigWatcher.cpp
src/core/Controller.h
src/core/utils/c_str.h
src/Cpu.h
src/interfaces/IClientListener.h
src/interfaces/IConfig.h
@ -51,17 +53,14 @@ set(HEADERS
src/net/strategies/FailoverStrategy.h
src/net/strategies/SinglePoolStrategy.h
src/net/SubmitResult.h
src/Platform.h
src/Summary.h
src/version.h
src/workers/CpuThread.h
src/workers/DoubleWorker.h
src/workers/Handle.h
src/workers/Hashrate.h
src/workers/SingleWorker.h
src/workers/MultiWorker.h
src/workers/Worker.h
src/workers/Workers.h
src/xmrig.h
)
set(HEADERS_CRYPTO
@ -89,11 +88,12 @@ endif()
set(SOURCES
src/api/NetworkState.cpp
src/App.cpp
src/common/config/CommonConfig.cpp
src/common/config/ConfigLoader.cpp
src/common/config/ConfigWatcher.cpp
src/common/Platform.cpp
src/Console.cpp
src/core/CommonConfig.cpp
src/core/Config.cpp
src/core/ConfigLoader.cpp
src/core/ConfigWatcher.cpp
src/core/Controller.cpp
src/log/ConsoleLog.cpp
src/log/FileLog.cpp
@ -107,13 +107,11 @@ set(SOURCES
src/net/strategies/FailoverStrategy.cpp
src/net/strategies/SinglePoolStrategy.cpp
src/net/SubmitResult.cpp
src/Platform.cpp
src/Summary.cpp
src/workers/CpuThread.cpp
src/workers/DoubleWorker.cpp
src/workers/Handle.cpp
src/workers/Hashrate.cpp
src/workers/SingleWorker.cpp
src/workers/MultiWorker.cpp
src/workers/Worker.cpp
src/workers/Workers.cpp
src/xmrig.cpp
@ -131,9 +129,9 @@ if (WIN32)
set(SOURCES_OS
res/app.rc
src/App_win.cpp
src/common/Platform_win.cpp
src/Cpu_win.cpp
src/Mem_win.cpp
src/Platform_win.cpp
)
add_definitions(/DWIN32)
@ -141,16 +139,16 @@ if (WIN32)
elseif (APPLE)
set(SOURCES_OS
src/App_unix.cpp
src/common/Platform_mac.cpp
src/Cpu_mac.cpp
src/Mem_unix.cpp
src/Platform_mac.cpp
)
else()
set(SOURCES_OS
src/App_unix.cpp
src/common/Platform_unix.cpp
src/Cpu_unix.cpp
src/Mem_unix.cpp
src/Platform_unix.cpp
)
set(EXTRA_LIBS pthread rt)
@ -215,14 +213,14 @@ if (WITH_HTTPD)
set(HTTPD_SOURCES
src/api/Api.h
src/api/ApiRouter.h
src/api/HttpBody.h
src/api/Httpd.h
src/api/HttpReply.h
src/api/HttpRequest.h
src/common/api/HttpBody.h
src/common/api/Httpd.h
src/common/api/HttpReply.h
src/common/api/HttpRequest.h
src/api/Api.cpp
src/api/ApiRouter.cpp
src/api/Httpd.cpp
src/api/HttpRequest.cpp
src/common/api/Httpd.cpp
src/common/api/HttpRequest.cpp
)
else()
message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_HTTPD=OFF` to build without http deamon support")

View file

@ -13,10 +13,10 @@ endif()
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-strict-aliasing")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-exceptions -fno-rtti")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s")
if (XMRIG_ARMv8)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a+crypto")

53
doc/API.md Normal file
View file

@ -0,0 +1,53 @@
# HTTP API
If you want use API you need choice a port where is internal HTTP server will listen for incoming connections. API will not available if miner built without `libmicrohttpd`.
Example configuration:
```json
"api": {
"port": 44444,
"access-token": "TOKEN",
"worker-id": null,
"ipv6": false,
"restricted": false
},
```
* **port** Port for incoming connections `http://<miner ip>:<port>`.
* **access-token** [Bearer](https://gist.github.com/xmrig/c75fdd1f8e0f3bac05500be2ab718f8e#file-api-html-L54) access token to secure access to API.
* **worker-id** Optional worker name, if not set will be detected automatically.
* **ipv6** Enable (`true`) or disable (`false`) IPv6 for API.
* **restricted** Use `false` to allow remote configuration.
If you prefer use command line options instead of config file, you can use options: `--api-port`, `--api-access-token`, `--api-worker-id`, `--api-ipv6` and `api-no-restricted`.
## Endpoints
### GET /1/summary
Get miner summary information. [Example](api/1/summary.json).
### GET /1/threads
Get detailed information about miner threads. [Example](api/1/threads.json).
## Restricted endpoints
All API endpoints below allow access to sensitive information and remote configure miner. You should set `access-token` and allow unrestricted access (`"restricted": false`).
### GET /1/config
Get current miner configuration. [Example](api/1/config.json).
### PUT /1/config
Update current miner configuration. Common use case, get current configuration, make changes, and upload it to miner.
Curl example:
```
curl -v --data-binary @config.json -X PUT -H "Content-Type: application/json" -H "Authorization: Bearer SECRET" http://127.0.0.1:44444/1/config
```

63
doc/api/1/config.json Normal file
View file

@ -0,0 +1,63 @@
{
"algo": "cryptonight",
"api": {
"port": 44444,
"access-token": "TOKEN",
"worker-id": null,
"ipv6": false,
"restricted": false
},
"av": 1,
"background": false,
"colors": true,
"cpu-affinity": null,
"cpu-priority": null,
"donate-level": 5,
"huge-pages": true,
"hw-aes": null,
"log-file": null,
"max-cpu-usage": 75,
"pools": [
{
"url": "pool.monero.hashvault.pro:3333",
"user": "48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD",
"pass": "x",
"keepalive": false,
"nicehash": false,
"variant": -1
},
{
"url": "pool.supportxmr.com:3333",
"user": "48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD",
"pass": "x",
"keepalive": false,
"nicehash": false,
"variant": -1
}
],
"print-time": 60,
"retries": 5,
"retry-pause": 5,
"safe": false,
"threads": [
{
"low_power_mode": 1,
"affine_to_cpu": 0
},
{
"low_power_mode": 1,
"affine_to_cpu": 1
},
{
"low_power_mode": 1,
"affine_to_cpu": 2
},
{
"low_power_mode": 1,
"affine_to_cpu": 3
}
],
"user-agent": null,
"syslog": false,
"watch": false
}

73
doc/api/1/summary.json Normal file
View file

@ -0,0 +1,73 @@
{
"id": "92f3104f9a2ee78c",
"worker_id": "Ubuntu-1604-xenial-64-minimal",
"version": "2.6.0-beta3",
"kind": "cpu",
"ua": "XMRig/2.6.0-beta3 (Linux x86_64) libuv/1.8.0 gcc/5.4.0",
"cpu": {
"brand": "Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz",
"aes": true,
"x64": true,
"sockets": 1
},
"algo": "cryptonight",
"hugepages": true,
"donate_level": 5,
"hashrate": {
"total": [
296.24,
296.23,
295.97
],
"highest": 296.5,
"threads": [
[
73.39,
73.39,
73.28
],
[
74.72,
74.72,
74.71
],
[
74.72,
74.72,
74.71
],
[
73.39,
73.39,
73.27
]
]
},
"results": {
"diff_current": 9990,
"shares_good": 30,
"shares_total": 30,
"avg_time": 31,
"hashes_total": 311833,
"best": [
278199,
181923,
103717,
96632,
56154,
51580,
45667,
33159,
29581,
29514
],
"error_log": []
},
"connection": {
"pool": "pool.monero.hashvault.pro:3333",
"uptime": 953,
"ping": 35,
"failures": 0,
"error_log": []
}
}

65
doc/api/1/threads.json Normal file
View file

@ -0,0 +1,65 @@
{
"hugepages": [
4,
4
],
"memory": 8388608,
"threads": [
{
"type": "cpu",
"algo": "cryptonight",
"av": 1,
"low_power_mode": 1,
"affine_to_cpu": 0,
"priority": -1,
"soft_aes": false,
"hashrate": [
73.39,
73.4,
73.28
]
},
{
"type": "cpu",
"algo": "cryptonight",
"av": 1,
"low_power_mode": 1,
"affine_to_cpu": 1,
"priority": -1,
"soft_aes": false,
"hashrate": [
74.72,
74.72,
74.7
]
},
{
"type": "cpu",
"algo": "cryptonight",
"av": 1,
"low_power_mode": 1,
"affine_to_cpu": 2,
"priority": -1,
"soft_aes": false,
"hashrate": [
74.71,
74.72,
74.7
]
},
{
"type": "cpu",
"algo": "cryptonight",
"av": 1,
"low_power_mode": 1,
"affine_to_cpu": 3,
"priority": -1,
"soft_aes": false,
"hashrate": [
73.39,
73.4,
73.28
]
}
]
}

View file

@ -28,6 +28,7 @@
#include "api/Api.h"
#include "App.h"
#include "common/Platform.h"
#include "Console.h"
#include "core/Config.h"
#include "core/Controller.h"
@ -38,14 +39,13 @@
#include "log/Log.h"
#include "Mem.h"
#include "net/Network.h"
#include "Platform.h"
#include "Summary.h"
#include "version.h"
#include "workers/Workers.h"
#ifndef XMRIG_NO_HTTPD
# include "api/Httpd.h"
# include "common/api/Httpd.h"
#endif
@ -76,8 +76,6 @@ App::App(int argc, char **argv) :
App::~App()
{
Mem::release();
uv_tty_reset_mode();
delete m_console;
@ -101,11 +99,7 @@ int App::exec()
background();
Mem::allocate(m_controller->config()->algorithm(),
m_controller->config()->threadsCount(),
m_controller->config()->isDoubleHash(),
m_controller->config()->isHugePages()
);
Mem::init(m_controller->config()->isHugePages());
Summary::print(m_controller);

View file

@ -31,7 +31,6 @@
#include "App.h"
#include "core/Config.h"
#include "core/Controller.h"
#include "Cpu.h"
#include "log/Log.h"
@ -39,11 +38,6 @@ void App::background()
{
signal(SIGPIPE, SIG_IGN);
const int64_t affinity = m_controller->config()->affinity();
if (affinity != -1L) {
Cpu::setAffinity(-1, affinity);
}
if (!m_controller->config()->isBackground()) {
return;
}

View file

@ -27,18 +27,12 @@
#include "App.h"
#include "Cpu.h"
#include "core/Controller.h"
#include "core/Config.h"
void App::background()
{
const int64_t affinity = m_controller->config()->affinity();
if (affinity != -1L) {
Cpu::setAffinity(-1, affinity);
}
if (!m_controller->config()->isBackground()) {
return;
}

View file

@ -26,26 +26,27 @@
#include <math.h>
#include <string.h>
#include "Cpu.h"
bool Cpu::m_l2_exclusive = false;
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
int Cpu::m_totalThreads = 0;
bool Cpu::m_l2_exclusive = false;
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
size_t Cpu::m_totalThreads = 0;
int Cpu::optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage)
size_t Cpu::optimalThreadsCount(size_t size, int maxCpuUsage)
{
if (m_totalThreads == 1) {
return 1;
}
int cache = 0;
size_t cache = 0;
if (m_l3_cache) {
cache = m_l2_exclusive ? (m_l2_cache + m_l3_cache) : m_l3_cache;
}
@ -53,22 +54,14 @@ int Cpu::optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage)
cache = m_l2_cache;
}
int count = 0;
int size = 2048;
if (algo == xmrig::CRYPTONIGHT_LITE) {
size = 1024;
}
else if (algo == xmrig::CRYPTONIGHT_HEAVY) {
size = 4096;
}
if (doubleHash) {
size *= 2;
}
size_t count = 0;
if (cache) {
count = cache / size;
if (cache % size >= size / 2) {
count++;
}
}
else {
count = m_totalThreads / 2;

View file

@ -28,9 +28,6 @@
#include <stdint.h>
#include "xmrig.h"
class Cpu
{
public:
@ -40,9 +37,8 @@ public:
BMI2 = 4
};
static int optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage);
static size_t optimalThreadsCount(size_t size, int maxCpuUsage);
static void init();
static void setAffinity(int id, uint64_t mask);
static inline bool hasAES() { return (m_flags & AES) != 0; }
static inline bool isX64() { return (m_flags & X86_64) != 0; }
@ -63,7 +59,7 @@ private:
static int m_l3_cache;
static int m_sockets;
static int m_totalCores;
static int m_totalThreads;
static size_t m_totalThreads;
};

View file

@ -4,8 +4,8 @@
* 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 2016-2017 XMRig <support@xmrig.com>
*
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 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
@ -28,16 +28,16 @@
#include "Cpu.h"
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
int Cpu::m_totalThreads = 0;
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
size_t Cpu::m_totalThreads = 0;
int Cpu::optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage)
size_t Cpu::optimalThreadsCount(size_t size, int maxCpuUsage)
{
return m_totalThreads;
}

View file

@ -4,8 +4,8 @@
* 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 2016-2017 XMRig <support@xmrig.com>
*
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2018 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
@ -38,8 +38,3 @@ void Cpu::init()
initCommon();
}
void Cpu::setAffinity(int id, uint64_t mask)
{
}

View file

@ -52,28 +52,3 @@ void Cpu::init()
initCommon();
}
void Cpu::setAffinity(int id, uint64_t mask)
{
cpu_set_t set;
CPU_ZERO(&set);
for (int i = 0; i < m_totalThreads; i++) {
if (mask & (1UL << i)) {
CPU_SET(i, &set);
}
}
if (id == -1) {
# ifndef __FreeBSD__
sched_setaffinity(0, sizeof(&set), &set);
# endif
} else {
# ifndef __ANDROID__
pthread_setaffinity_np(pthread_self(), sizeof(&set), &set);
# else
sched_setaffinity(gettid(), sizeof(&set), &set);
# endif
}
}

View file

@ -39,14 +39,3 @@ void Cpu::init()
initCommon();
}
void Cpu::setAffinity(int id, uint64_t mask)
{
if (id == -1) {
SetProcessAffinityMask(GetCurrentProcess(), mask);
}
else {
SetThreadAffinityMask(GetCurrentThread(), mask);
}
}

View file

@ -23,70 +23,49 @@
*/
#include <memory.h>
#include "common/utils/mm_malloc.h"
#include "crypto/CryptoNight.h"
#include "crypto/CryptoNight_constants.h"
#include "Mem.h"
bool Mem::m_doubleHash = false;
int Mem::m_algo = 0;
int Mem::m_flags = 0;
int Mem::m_threads = 0;
size_t Mem::m_offset = 0;
size_t Mem::m_size = 0;
alignas(16) uint8_t *Mem::m_memory = nullptr;
bool Mem::m_enabled = true;
int Mem::m_flags = 0;
cryptonight_ctx *Mem::create(int threadId)
MemInfo Mem::create(cryptonight_ctx **ctx, xmrig::Algo algorithm, size_t count)
{
using namespace xmrig;
MemInfo info;
info.size = cn_select_memory(algorithm) * count;
# ifndef XMRIG_NO_AEON
if (m_algo == xmrig::CRYPTONIGHT_LITE) {
return createLite(threadId);
}
info.size += info.size % cn_select_memory<CRYPTONIGHT>();
# endif
const size_t size = m_algo == xmrig::CRYPTONIGHT_HEAVY ? xmrig::cn_select_memory<xmrig::CRYPTONIGHT_HEAVY>()
: xmrig::cn_select_memory<xmrig::CRYPTONIGHT>();
info.pages = info.size / cn_select_memory<CRYPTONIGHT>();
cryptonight_ctx *ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[size - sizeof(cryptonight_ctx) * (threadId + 1)]);
allocate(info, m_enabled);
const int ratio = m_doubleHash ? 2 : 1;
ctx->memory = &m_memory[size * (threadId * ratio + 1)];
for (size_t i = 0; i < count; ++i) {
cryptonight_ctx *c = static_cast<cryptonight_ctx *>(_mm_malloc(sizeof(cryptonight_ctx), 4096));
c->memory = info.memory + (i * cn_select_memory(algorithm));
return ctx;
}
void *Mem::calloc(size_t num, size_t size)
{
void *mem = &m_memory[m_offset];
m_offset += (num * size);
memset(mem, 0, num * size);
return mem;
}
#ifndef XMRIG_NO_AEON
cryptonight_ctx *Mem::createLite(int threadId) {
cryptonight_ctx *ctx;
if (!m_doubleHash) {
const size_t offset = MONERO_MEMORY * (threadId + 1);
ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[offset + AEON_MEMORY]);
ctx->memory = &m_memory[offset];
return ctx;
ctx[i] = c;
}
ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[MONERO_MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]);
ctx->memory = &m_memory[MONERO_MEMORY * (threadId + 1)];
return ctx;
return info;
}
#endif
void Mem::release(cryptonight_ctx **ctx, size_t count, MemInfo &info)
{
release(info);
for (size_t i = 0; i < count; ++i) {
_mm_free(ctx[i]);
}
}

View file

@ -30,12 +30,22 @@
#include <stdint.h>
#include "xmrig.h"
#include "common/xmrig.h"
struct cryptonight_ctx;
struct MemInfo
{
alignas(16) uint8_t *memory;
size_t hugePages;
size_t pages;
size_t size;
};
class Mem
{
public:
@ -45,29 +55,18 @@ public:
Lock = 4
};
static bool allocate(xmrig::Algo algo, int threads, bool doubleHash, bool enabled);
static cryptonight_ctx *create(int threadId);
static void *calloc(size_t num, size_t size);
static void release();
static MemInfo create(cryptonight_ctx **ctx, xmrig::Algo algorithm, size_t count);
static void init(bool enabled);
static void release(cryptonight_ctx **ctx, size_t count, MemInfo &info);
static inline bool isDoubleHash() { return m_doubleHash; }
static inline bool isHugepagesAvailable() { return (m_flags & HugepagesAvailable) != 0; }
static inline bool isHugepagesEnabled() { return (m_flags & HugepagesEnabled) != 0; }
static inline int flags() { return m_flags; }
static inline int threads() { return m_threads; }
private:
static bool m_doubleHash;
static int m_algo;
static int m_flags;
static int m_threads;
static size_t m_offset;
static size_t m_size;
alignas(16) static uint8_t *m_memory;
static void allocate(MemInfo &info, bool enabled);
static void release(MemInfo &info);
# ifndef XMRIG_NO_AEON
static cryptonight_ctx *createLite(int threadId);
# endif
static int m_flags;
static bool m_enabled;
};

View file

@ -27,75 +27,63 @@
#include <sys/mman.h>
#if defined(XMRIG_ARM) && !defined(__clang__)
# include "aligned_malloc.h"
#else
# include <mm_malloc.h>
#endif
#include "common/utils/mm_malloc.h"
#include "common/xmrig.h"
#include "crypto/CryptoNight.h"
#include "log/Log.h"
#include "Mem.h"
#include "xmrig.h"
bool Mem::allocate(xmrig::Algo algo, int threads, bool doubleHash, bool enabled)
void Mem::init(bool enabled)
{
m_algo = algo;
m_threads = threads;
m_doubleHash = doubleHash;
m_enabled = enabled;
}
const int ratio = (doubleHash && algo != xmrig::CRYPTONIGHT_LITE) ? 2 : 1;
m_size = MONERO_MEMORY * (threads * ratio + 1);
if (algo == xmrig::CRYPTONIGHT_HEAVY) {
m_size *= 2;
}
void Mem::allocate(MemInfo &info, bool enabled)
{
info.hugePages = 0;
if (!enabled) {
m_memory = static_cast<uint8_t*>(_mm_malloc(m_size, 16));
return true;
}
info.memory = static_cast<uint8_t*>(_mm_malloc(info.size, 4096));
m_flags |= HugepagesAvailable;
return;
}
# if defined(__APPLE__)
m_memory = static_cast<uint8_t*>(mmap(0, m_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0));
info.memory = static_cast<uint8_t*>(mmap(0, info.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0));
# elif defined(__FreeBSD__)
m_memory = static_cast<uint8_t*>(mmap(0, m_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0));
info.memory = static_cast<uint8_t*>(mmap(0, info.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0));
# else
m_memory = static_cast<uint8_t*>(mmap(0, m_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0));
info.memory = static_cast<uint8_t*>(mmap(0, info.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0));
# endif
if (m_memory == MAP_FAILED) {
m_memory = static_cast<uint8_t*>(_mm_malloc(m_size, 16));
return true;
if (info.memory == MAP_FAILED) {
return allocate(info, false);;
}
m_flags |= HugepagesEnabled;
info.hugePages = info.pages;
if (madvise(m_memory, m_size, MADV_RANDOM | MADV_WILLNEED) != 0) {
if (madvise(info.memory, info.size, MADV_RANDOM | MADV_WILLNEED) != 0) {
LOG_ERR("madvise failed");
}
if (mlock(m_memory, m_size) == 0) {
if (mlock(info.memory, info.size) == 0) {
m_flags |= Lock;
}
return true;
}
void Mem::release()
void Mem::release(MemInfo &info)
{
if (m_flags & HugepagesEnabled) {
if (info.hugePages) {
if (m_flags & Lock) {
munlock(m_memory, m_size);
munlock(info.memory, info.size);
}
munmap(m_memory, m_size);
munmap(info.memory, info.size);
}
else {
_mm_free(m_memory);
_mm_free(info.memory);
}
}

View file

@ -28,16 +28,13 @@
#include <ntsecapi.h>
#include <tchar.h>
#ifdef __GNUC__
# include <mm_malloc.h>
#else
# include <malloc.h>
#endif
#include "log/Log.h"
#include "common/utils/mm_malloc.h"
#include "common/xmrig.h"
#include "crypto/CryptoNight.h"
#include "crypto/CryptoNight_constants.h"
#include "log/Log.h"
#include "Mem.h"
#include "xmrig.h"
/*****************************************************************
@ -145,46 +142,43 @@ static BOOL TrySetLockPagesPrivilege() {
}
bool Mem::allocate(xmrig::Algo algo, int threads, bool doubleHash, bool enabled)
void Mem::init(bool enabled)
{
m_algo = algo;
m_threads = threads;
m_doubleHash = doubleHash;
m_enabled = enabled;
const int ratio = (doubleHash && algo != xmrig::CRYPTONIGHT_LITE) ? 2 : 1;
m_size = MONERO_MEMORY * (threads * ratio + 1);
if (algo == xmrig::CRYPTONIGHT_HEAVY) {
m_size *= 2;
}
if (!enabled) {
m_memory = static_cast<uint8_t*>(_mm_malloc(m_size, 16));
return true;
}
if (TrySetLockPagesPrivilege()) {
if (enabled && TrySetLockPagesPrivilege()) {
m_flags |= HugepagesAvailable;
}
m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, m_size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE));
if (!m_memory) {
m_memory = static_cast<uint8_t*>(_mm_malloc(m_size, 16));
}
else {
m_flags |= HugepagesEnabled;
}
return true;
}
void Mem::release()
void Mem::allocate(MemInfo &info, bool enabled)
{
if (m_flags & HugepagesEnabled) {
VirtualFree(m_memory, 0, MEM_RELEASE);
info.hugePages = 0;
if (!enabled) {
info.memory = static_cast<uint8_t*>(_mm_malloc(info.size, 4096));
return;
}
info.memory = static_cast<uint8_t*>(VirtualAlloc(nullptr, info.size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE));
if (info.memory) {
info.hugePages = info.pages;
return;
}
allocate(info, false);
}
void Mem::release(MemInfo &info)
{
if (info.hugePages) {
VirtualFree(info.memory, 0, MEM_RELEASE);
}
else {
_mm_free(m_memory);
_mm_free(info.memory);
}
}

View file

@ -58,14 +58,15 @@ static void print_versions(xmrig::Config *config)
static void print_memory(xmrig::Config *config) {
# ifdef _WIN32
if (config->isColors()) {
Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s",
Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable",
Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled");
Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s",
Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable");
}
else {
Log::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled");
Log::i()->text(" * HUGE PAGES: %s", Mem::isHugepagesAvailable() ? "available" : "unavailable");
}
# endif
}
@ -92,21 +93,30 @@ static void print_cpu(xmrig::Config *config)
static void print_threads(xmrig::Config *config)
{
char buf[32];
if (config->affinity() != -1L) {
snprintf(buf, 32, ", affinity=0x%" PRIX64, config->affinity());
if (config->threadsMode() != xmrig::Config::Advanced) {
char buf[32];
if (config->affinity() != -1L) {
snprintf(buf, 32, ", affinity=0x%" PRIX64, config->affinity());
}
else {
buf[0] = '\0';
}
Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s",
config->threadsCount(),
config->algoName(),
config->algoVariant(),
config->isColors() && config->donateLevel() == 0 ? "\x1B[01;31m" : "",
config->donateLevel(),
buf);
}
else {
buf[0] = '\0';
Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, %sdonate=%d%%" : " * THREADS: %d, %s, %sdonate=%d%%",
config->threadsCount(),
config->algoName(),
config->isColors() && config->donateLevel() == 0 ? "\x1B[01;31m" : "",
config->donateLevel());
}
Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s",
config->threadsCount(),
config->algoName(),
config->algoVariant(),
config->isColors() && config->donateLevel() == 0 ? "\x1B[01;31m" : "",
config->donateLevel(),
buf);
}

View file

@ -26,8 +26,8 @@
#include "api/Api.h"
#include "api/ApiRouter.h"
#include "api/HttpReply.h"
#include "api/HttpRequest.h"
#include "common/api/HttpReply.h"
#include "common/api/HttpRequest.h"
ApiRouter *Api::m_router = nullptr;
@ -62,16 +62,6 @@ void Api::exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply)
}
void Api::tick(const Hashrate *hashrate)
{
if (!m_router) {
return;
}
m_router->tick(hashrate);
}
void Api::tick(const NetworkState &network)
{
if (!m_router) {

View file

@ -47,7 +47,6 @@ public:
static void release();
static void exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply);
static void tick(const Hashrate *hashrate);
static void tick(const NetworkState &results);
private:

View file

@ -33,20 +33,21 @@
#include "api/ApiRouter.h"
#include "api/HttpReply.h"
#include "api/HttpRequest.h"
#include "common/api/HttpReply.h"
#include "common/api/HttpRequest.h"
#include "common/Platform.h"
#include "core/Config.h"
#include "core/Controller.h"
#include "Cpu.h"
#include "interfaces/IThread.h"
#include "Mem.h"
#include "net/Job.h"
#include "Platform.h"
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "version.h"
#include "workers/Hashrate.h"
#include "workers/Workers.h"
extern "C"
@ -68,10 +69,6 @@ static inline double normalize(double d)
ApiRouter::ApiRouter(xmrig::Controller *controller) :
m_controller(controller)
{
m_threads = controller->config()->threadsCount();
m_hashrate = new double[m_threads * 3]();
memset(m_totalHashrate, 0, sizeof(m_totalHashrate));
memset(m_workerId, 0, sizeof(m_workerId));
setWorkerId(controller->config()->apiWorkerId());
@ -81,7 +78,6 @@ ApiRouter::ApiRouter(xmrig::Controller *controller) :
ApiRouter::~ApiRouter()
{
delete [] m_hashrate;
}
@ -129,21 +125,6 @@ void ApiRouter::exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply)
}
void ApiRouter::tick(const Hashrate *hashrate)
{
for (int i = 0; i < m_threads; ++i) {
m_hashrate[i * 3] = hashrate->calc((size_t) i, Hashrate::ShortInterval);
m_hashrate[i * 3 + 1] = hashrate->calc((size_t) i, Hashrate::MediumInterval);
m_hashrate[i * 3 + 2] = hashrate->calc((size_t) i, Hashrate::LargeInterval);
}
m_totalHashrate[0] = hashrate->calc(Hashrate::ShortInterval);
m_totalHashrate[1] = hashrate->calc(Hashrate::MediumInterval);
m_totalHashrate[2] = hashrate->calc(Hashrate::LargeInterval);
m_highestHashrate = hashrate->highest();
}
void ApiRouter::tick(const NetworkState &network)
{
m_network = network;
@ -225,21 +206,23 @@ void ApiRouter::getHashrate(rapidjson::Document &doc) const
rapidjson::Value total(rapidjson::kArrayType);
rapidjson::Value threads(rapidjson::kArrayType);
for (int i = 0; i < 3; ++i) {
total.PushBack(normalize(m_totalHashrate[i]), allocator);
}
const Hashrate *hr = Workers::hashrate();
for (int i = 0; i < m_threads * 3; i += 3) {
total.PushBack(normalize(hr->calc(Hashrate::ShortInterval)), allocator);
total.PushBack(normalize(hr->calc(Hashrate::MediumInterval)), allocator);
total.PushBack(normalize(hr->calc(Hashrate::LargeInterval)), allocator);
for (size_t i = 0; i < Workers::threads(); i++) {
rapidjson::Value thread(rapidjson::kArrayType);
thread.PushBack(normalize(m_hashrate[i]), allocator);
thread.PushBack(normalize(m_hashrate[i + 1]), allocator);
thread.PushBack(normalize(m_hashrate[i + 2]), allocator);
thread.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
thread.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
thread.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
threads.PushBack(thread, allocator);
}
hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", normalize(m_highestHashrate), allocator);
hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", normalize(hr->highest()), allocator);
hashrate.AddMember("threads", threads, allocator);
doc.AddMember("hashrate", hashrate, allocator);
}
@ -267,7 +250,7 @@ void ApiRouter::getMiner(rapidjson::Document &doc) const
doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator);
doc.AddMember("cpu", cpu, allocator);
doc.AddMember("algo", rapidjson::StringRef(m_controller->config()->algoName()), allocator);
doc.AddMember("hugepages", Mem::isHugepagesEnabled(), allocator);
doc.AddMember("hugepages", Workers::hugePages() > 0, allocator);
doc.AddMember("donate_level", m_controller->config()->donateLevel(), allocator);
}
@ -298,13 +281,28 @@ void ApiRouter::getResults(rapidjson::Document &doc) const
void ApiRouter::getThreads(rapidjson::Document &doc) const
{
doc.SetArray();
doc.SetObject();
auto &allocator = doc.GetAllocator();
const Hashrate *hr = Workers::hashrate();
Workers::threadsSummary(doc);
const std::vector<xmrig::IThread *> &threads = m_controller->config()->threads();
rapidjson::Value list(rapidjson::kArrayType);
for (const xmrig::IThread *thread : threads) {
doc.PushBack(thread->toAPI(doc), doc.GetAllocator());
rapidjson::Value value = thread->toAPI(doc);
rapidjson::Value hashrate(rapidjson::kArrayType);
hashrate.PushBack(normalize(hr->calc(thread->index(), Hashrate::ShortInterval)), allocator);
hashrate.PushBack(normalize(hr->calc(thread->index(), Hashrate::MediumInterval)), allocator);
hashrate.PushBack(normalize(hr->calc(thread->index(), Hashrate::LargeInterval)), allocator);
value.AddMember("hashrate", hashrate, allocator);
list.PushBack(value, allocator);
}
doc.AddMember("threads", list, allocator);
}

View file

@ -49,7 +49,6 @@ public:
void get(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) const;
void exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply);
void tick(const Hashrate *hashrate);
void tick(const NetworkState &results);
protected:
@ -69,10 +68,6 @@ private:
char m_id[17];
char m_workerId[128];
double *m_hashrate;
double m_highestHashrate;
double m_totalHashrate[3];
int m_threads;
NetworkState m_network;
xmrig::Controller *m_controller;
};

View file

@ -29,16 +29,16 @@
#include "Platform.h"
char *Platform::m_defaultConfigName = nullptr;
char *Platform::m_userAgent = nullptr;
char Platform::m_defaultConfigName[520] = { 0 };
xmrig::c_str Platform::m_userAgent;
const char *Platform::defaultConfigName()
{
size_t size = 520;
if (m_defaultConfigName == nullptr) {
m_defaultConfigName = new char[size];
if (*m_defaultConfigName) {
return m_defaultConfigName;
}
if (uv_exepath(m_defaultConfigName, &size) < 0) {
@ -58,5 +58,6 @@ const char *Platform::defaultConfigName()
}
}
*m_defaultConfigName = '\0';
return nullptr;
}

View file

@ -25,20 +25,26 @@
#define __PLATFORM_H__
#include <stdint.h>
#include "common/utils/c_str.h"
class Platform
{
public:
static bool setThreadAffinity(uint64_t cpu_id);
static const char *defaultConfigName();
static void init(const char *userAgent);
static void release();
static void setProcessPriority(int priority);
static void setThreadPriority(int priority);
static inline const char *userAgent() { return m_userAgent; }
static inline const char *userAgent() { return m_userAgent.data(); }
private:
static char *m_defaultConfigName;
static char *m_userAgent;
static char m_defaultConfigName[520];
static xmrig::c_str m_userAgent;
};

View file

@ -22,6 +22,8 @@
*/
#include <mach/thread_act.h>
#include <mach/thread_policy.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
@ -53,15 +55,24 @@ static inline char *createUserAgent()
}
void Platform::init(const char *userAgent)
bool Platform::setThreadAffinity(uint64_t cpu_id)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
thread_port_t mach_thread;
thread_affinity_policy_data_t policy = { static_cast<integer_t>(cpu_id) };
mach_thread = pthread_mach_thread_np(pthread_self());
return thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 1) == KERN_SUCCESS;
}
void Platform::release()
void Platform::init(const char *userAgent)
{
delete [] m_userAgent;
if (userAgent) {
m_userAgent = userAgent;
}
else {
m_userAgent = createUserAgent();
}
}

View file

@ -21,6 +21,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef __FreeBSD__
# include <sys/types.h>
# include <sys/param.h>
# include <sys/cpuset.h>
# include <pthread_np.h>
#endif
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
@ -37,6 +45,11 @@
#endif
#ifdef __FreeBSD__
typedef cpuset_t cpu_set_t;
#endif
static inline char *createUserAgent()
{
const size_t max = 160;
@ -63,15 +76,28 @@ static inline char *createUserAgent()
}
void Platform::init(const char *userAgent)
bool Platform::setThreadAffinity(uint64_t cpu_id)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
cpu_set_t mn;
CPU_ZERO(&mn);
CPU_SET(cpu_id, &mn);
# ifndef __ANDROID__
return pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &mn) == 0;
# else
return sched_setaffinity(gettid(), sizeof(cpu_set_t), &mn) == 0;
# endif
}
void Platform::release()
void Platform::init(const char *userAgent)
{
delete [] m_userAgent;
if (userAgent) {
m_userAgent = userAgent;
}
else {
m_userAgent = createUserAgent();
}
}

View file

@ -27,9 +27,11 @@
#include <uv.h>
#include "log/Log.h"
#include "Platform.h"
#include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
@ -82,16 +84,24 @@ static inline char *createUserAgent()
}
void Platform::init(const char *userAgent)
bool Platform::setThreadAffinity(uint64_t cpu_id)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
if (cpu_id >= 64) {
LOG_ERR("Unable to set affinity. Windows supports only affinity up to 63.");
}
return SetThreadAffinityMask(GetCurrentThread(), 1ULL << cpu_id) != 0;
}
void Platform::release()
void Platform::init(const char *userAgent)
{
delete [] m_defaultConfigName;
delete [] m_userAgent;
if (userAgent) {
m_userAgent = userAgent;
}
else {
m_userAgent = createUserAgent();
}
}
@ -131,7 +141,6 @@ void Platform::setProcessPriority(int priority)
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {

View file

@ -25,9 +25,9 @@
#include <microhttpd.h>
#include <string.h>
#include "api/HttpBody.h"
#include "api/HttpRequest.h"
#include "api/HttpReply.h"
#include "common/api/HttpBody.h"
#include "common/api/HttpRequest.h"
#include "common/api/HttpReply.h"
#ifndef MHD_HTTP_PAYLOAD_TOO_LARGE

View file

@ -27,9 +27,9 @@
#include "api/Api.h"
#include "api/Httpd.h"
#include "api/HttpReply.h"
#include "api/HttpRequest.h"
#include "common/api/Httpd.h"
#include "common/api/HttpReply.h"
#include "common/api/HttpRequest.h"
#include "log/Log.h"

View file

@ -29,14 +29,13 @@
#include <uv.h>
#include "core/CommonConfig.h"
#include "common/config/CommonConfig.h"
#include "donate.h"
#include "log/Log.h"
#include "net/Pool.h"
#include "rapidjson/document.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/prettywriter.h"
#include "xmrig.h"
xmrig::CommonConfig::CommonConfig() :
@ -206,12 +205,12 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg)
case SyslogKey: /* --syslog */
case KeepAliveKey: /* --keepalive */
case NicehashKey: /* --nicehash */
case ApiIPv6Key: /* --api-ipv6 */
return parseBoolean(key, true);
case ColorKey: /* --no-color */
case WatchKey: /* --no-watch */
case ApiRestrictedKey: /* --api-no-restricted */
case ApiIPv6Key: /* --api-no-ipv6 */
return parseBoolean(key, false);
case DonateLevelKey: /* --donate-level */

View file

@ -28,10 +28,10 @@
#include <vector>
#include "core/utils/c_str.h"
#include "common/utils/c_str.h"
#include "common/xmrig.h"
#include "interfaces/IConfig.h"
#include "net/Pool.h"
#include "xmrig.h"
namespace xmrig {

View file

@ -32,14 +32,14 @@
#endif
#include "common/config/ConfigLoader.h"
#include "common/config/ConfigWatcher.h"
#include "common/Platform.h"
#include "core/ConfigCreator.h"
#include "core/ConfigLoader.h"
#include "core/ConfigLoader_platform.h"
#include "core/ConfigWatcher.h"
#include "interfaces/IConfig.h"
#include "interfaces/IWatcherListener.h"
#include "net/Pool.h"
#include "Platform.h"
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
#include "rapidjson/filereadstream.h"

View file

@ -25,9 +25,9 @@
#include <stdio.h>
#include "common/config/ConfigLoader.h"
#include "common/config/ConfigWatcher.h"
#include "core/ConfigCreator.h"
#include "core/ConfigLoader.h"
#include "core/ConfigWatcher.h"
#include "interfaces/IWatcherListener.h"
#include "log/Log.h"

View file

@ -29,7 +29,7 @@
#include <uv.h>
#include "core/utils/c_str.h"
#include "common/utils/c_str.h"
#include "rapidjson/fwd.h"

View file

@ -5,7 +5,6 @@
* 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 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
@ -22,35 +21,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SINGLEWORKER_H__
#define __SINGLEWORKER_H__
#ifndef __MM_MALLOC_PORTABLE_H__
#define __MM_MALLOC_PORTABLE_H__
#include "net/Job.h"
#include "net/JobResult.h"
#include "workers/Worker.h"
#ifdef _WIN32
# ifdef __GNUC__
# include <mm_malloc.h>
# else
# include <malloc.h>
# endif
#else
# if defined(XMRIG_ARM) && !defined(__clang__)
# include "aligned_malloc.h"
# else
# include <mm_malloc.h>
# endif
#endif
class Handle;
class SingleWorker : public Worker
{
public:
SingleWorker(Handle *handle);
bool start() override;
private:
bool resume(const Job &job);
bool selfTest();
void consumeJob();
void save(const Job &job);
Job m_job;
Job m_paused;
JobResult m_result;
};
#endif /* __SINGLEWORKER_H__ */
#endif /* __MM_MALLOC_PORTABLE_H__ */

View file

@ -64,6 +64,13 @@ enum Variant {
};
enum AesMode {
AES_AUTO,
AES_HW,
AES_SOFT
};
} /* namespace xmrig */

View file

@ -26,32 +26,29 @@
#include <inttypes.h>
#include "common/config/ConfigLoader.h"
#include "core/Config.h"
#include "core/ConfigCreator.h"
#include "core/ConfigLoader.h"
#include "Cpu.h"
#include "crypto/CryptoNight_constants.h"
#include "net/Pool.h"
#include "rapidjson/document.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/prettywriter.h"
#include "workers/CpuThread.h"
#include "xmrig.h"
static char affinity_tmp[20] = { 0 };
xmrig::Config::Config() : xmrig::CommonConfig(),
m_aesMode(AES_AUTO),
m_algoVariant(AV_AUTO),
m_doubleHash(false),
m_dryRun(false),
m_hugePages(true),
m_safe(false),
m_maxCpuUsage(75),
m_printTime(60),
m_priority(-1),
m_affinity(-1L),
m_threadsCount(0)
m_priority(-1)
{
}
@ -69,53 +66,49 @@ bool xmrig::Config::reload(const char *json)
void xmrig::Config::getJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
doc.SetObject();
auto &allocator = doc.GetAllocator();
doc.AddMember("algo", rapidjson::StringRef(algoName()), allocator);
doc.AddMember("algo", StringRef(algoName()), allocator);
rapidjson::Value api(rapidjson::kObjectType);
Value api(kObjectType);
api.AddMember("port", apiPort(), allocator);
api.AddMember("access-token", apiToken() ? rapidjson::Value(rapidjson::StringRef(apiToken())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator);
api.AddMember("worker-id", apiWorkerId() ? rapidjson::Value(rapidjson::StringRef(apiWorkerId())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator);
api.AddMember("access-token", apiToken() ? Value(StringRef(apiToken())).Move() : Value(kNullType).Move(), allocator);
api.AddMember("worker-id", apiWorkerId() ? Value(StringRef(apiWorkerId())).Move() : Value(kNullType).Move(), allocator);
api.AddMember("ipv6", isApiIPv6(), allocator);
api.AddMember("restricted", isApiRestricted(), allocator);
doc.AddMember("api", api, allocator);
doc.AddMember("av", algoVariant(), allocator);
doc.AddMember("background", isBackground(), allocator);
doc.AddMember("colors", isColors(), allocator);
doc.AddMember("colors", isColors(), allocator);
if (affinity() != -1L) {
snprintf(affinity_tmp, sizeof(affinity_tmp) - 1, "0x%" PRIX64, affinity());
doc.AddMember("cpu-affinity", rapidjson::StringRef(affinity_tmp), allocator);
doc.AddMember("cpu-affinity", StringRef(affinity_tmp), allocator);
}
else {
doc.AddMember("cpu-affinity", rapidjson::kNullType, allocator);
}
if (priority() != -1) {
doc.AddMember("cpu-priority", priority(), allocator);
}
else {
doc.AddMember("cpu-priority", rapidjson::kNullType, allocator);
doc.AddMember("cpu-affinity", kNullType, allocator);
}
doc.AddMember("cpu-priority", priority() != -1 ? Value(priority()) : Value(kNullType), allocator);
doc.AddMember("donate-level", donateLevel(), allocator);
doc.AddMember("huge-pages", isHugePages(), allocator);
doc.AddMember("log-file", logFile() ? rapidjson::Value(rapidjson::StringRef(logFile())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator);
doc.AddMember("hw-aes", m_aesMode == AES_AUTO ? Value(kNullType) : Value(m_aesMode == AES_HW), allocator);
doc.AddMember("log-file", logFile() ? Value(StringRef(logFile())).Move() : Value(kNullType).Move(), allocator);
doc.AddMember("max-cpu-usage", m_maxCpuUsage, allocator);
rapidjson::Value pools(rapidjson::kArrayType);
Value pools(kArrayType);
for (const Pool &pool : m_pools) {
rapidjson::Value obj(rapidjson::kObjectType);
Value obj(kObjectType);
obj.AddMember("url", rapidjson::StringRef(pool.url()), allocator);
obj.AddMember("user", rapidjson::StringRef(pool.user()), allocator);
obj.AddMember("pass", rapidjson::StringRef(pool.password()), allocator);
obj.AddMember("url", StringRef(pool.url()), allocator);
obj.AddMember("user", StringRef(pool.user()), allocator);
obj.AddMember("pass", StringRef(pool.password()), allocator);
if (pool.keepAlive() == 0 || pool.keepAlive() == Pool::kKeepAliveTimeout) {
obj.AddMember("keepalive", pool.keepAlive() > 0, allocator);
@ -135,8 +128,21 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
doc.AddMember("retries", retries(), allocator);
doc.AddMember("retry-pause", retryPause(), allocator);
doc.AddMember("safe", m_safe, allocator);
doc.AddMember("threads", threadsCount(), allocator);
doc.AddMember("user-agent", userAgent() ? rapidjson::Value(rapidjson::StringRef(userAgent())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator);
if (threadsMode() == Advanced) {
Value threads(kArrayType);
for (const IThread *thread : m_threads.list) {
threads.PushBack(thread->toConfig(doc), doc.GetAllocator());
}
doc.AddMember("threads", threads, allocator);
}
else {
doc.AddMember("threads", threadsMode() == Automatic ? Value(kNullType) : Value(threadsCount()), allocator);
}
doc.AddMember("user-agent", userAgent() ? Value(StringRef(userAgent())).Move() : Value(kNullType).Move(), allocator);
# ifdef HAVE_SYSLOG_H
doc.AddMember("syslog", isSyslog(), allocator);
@ -158,23 +164,34 @@ bool xmrig::Config::adjust()
return false;
}
m_algoVariant = getAlgoVariant();
if (m_algoVariant == AV_DOUBLE || m_algoVariant == AV_DOUBLE_SOFT) {
m_doubleHash = true;
if (!m_threads.cpu.empty()) {
m_threads.mode = Advanced;
const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT;
for (size_t i = 0; i < m_threads.cpu.size(); ++i) {
m_threads.list.push_back(CpuThread::createFromData(i, m_algorithm, m_threads.cpu[i], m_priority, softAES));
}
return true;
}
if (!m_threadsCount) {
m_threadsCount = Cpu::optimalThreadsCount(m_algorithm, m_doubleHash, m_maxCpuUsage);
m_algoVariant = getAlgoVariant();
m_threads.mode = m_threads.count ? Simple : Automatic;
const size_t size = CpuThread::multiway(m_algoVariant) * cn_select_memory(m_algorithm) / 1024;
if (!m_threads.count) {
m_threads.count = Cpu::optimalThreadsCount(size, m_maxCpuUsage);
}
else if (m_safe) {
const size_t count = Cpu::optimalThreadsCount(m_algorithm, m_doubleHash, m_maxCpuUsage);
if (m_threadsCount > count) {
m_threadsCount = count;
const size_t count = Cpu::optimalThreadsCount(size, m_maxCpuUsage);
if (m_threads.count > count) {
m_threads.count = count;
}
}
for (size_t i = 0; i < m_threadsCount; ++i) {
m_threads.push_back(CpuThread::createFromAV(i, m_algorithm, m_algoVariant, m_affinity, m_priority));
for (size_t i = 0; i < m_threads.count; ++i) {
m_threads.list.push_back(CpuThread::createFromAV(i, m_algorithm, m_algoVariant, m_threads.mask, m_priority));
}
return true;
@ -188,18 +205,22 @@ bool xmrig::Config::parseBoolean(int key, bool enable)
}
switch (key) {
case xmrig::IConfig::SafeKey: /* --safe */
case IConfig::SafeKey: /* --safe */
m_safe = enable;
break;
case xmrig::IConfig::HugePagesKey: /* --no-huge-pages */
case IConfig::HugePagesKey: /* --no-huge-pages */
m_hugePages = enable;
break;
case xmrig::IConfig::DryRunKey: /* --dry-run */
case IConfig::DryRunKey: /* --dry-run */
m_dryRun = enable;
break;
case IConfig::HardwareAESKey: /* hw-aes config only */
m_aesMode = enable ? AES_HW : AES_SOFT;
break;
default:
break;
}
@ -229,7 +250,7 @@ bool xmrig::Config::parseString(int key, const char *arg)
case xmrig::IConfig::ThreadsKey: /* --threads */
if (strncmp(arg, "all", 3) == 0) {
m_threadsCount = Cpu::threads();
m_threads.count = Cpu::threads();
return true;
}
@ -258,7 +279,7 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg)
switch (key) {
case xmrig::IConfig::CPUAffinityKey: /* --cpu-affinity */
if (arg) {
m_affinity = arg;
m_threads.mask = arg;
}
break;
@ -272,6 +293,23 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg)
void xmrig::Config::parseJSON(const rapidjson::Document &doc)
{
const rapidjson::Value &threads = doc["threads"];
if (threads.IsArray()) {
for (const rapidjson::Value &value : threads.GetArray()) {
if (!value.IsObject()) {
continue;
}
if (value.HasMember("low_power_mode")) {
auto data = CpuThread::parse(value);
if (data.valid) {
m_threads.cpu.push_back(std::move(data));
}
}
}
}
}
@ -280,7 +318,7 @@ bool xmrig::Config::parseInt(int key, int arg)
switch (key) {
case xmrig::IConfig::ThreadsKey: /* --threads */
if (arg >= 0 && arg < 1024) {
m_threadsCount = arg;
m_threads.count = arg;
}
break;

View file

@ -29,9 +29,10 @@
#include <vector>
#include "core/CommonConfig.h"
#include "common/config/CommonConfig.h"
#include "common/xmrig.h"
#include "rapidjson/fwd.h"
#include "xmrig.h"
#include "workers/CpuThread.h"
class Addr;
@ -60,6 +61,13 @@ class IWatcherListener;
class Config : public CommonConfig
{
public:
enum ThreadsMode {
Automatic,
Simple,
Advanced
};
Config();
~Config();
@ -67,15 +75,15 @@ public:
void getJSON(rapidjson::Document &doc) const override;
inline AesMode aesMode() const { return m_aesMode; }
inline AlgoVariant algoVariant() const { return m_algoVariant; }
inline bool isDoubleHash() const { return m_doubleHash; }
inline bool isDryRun() const { return m_dryRun; }
inline bool isHugePages() const { return m_hugePages; }
inline const std::vector<IThread *> &threads() const { return m_threads; }
inline int printTime() const { return m_printTime; }
inline const std::vector<IThread *> &threads() const { return m_threads.list; }
inline int priority() const { return m_priority; }
inline int threadsCount() const { return m_threadsCount; }
inline int64_t affinity() const { return m_affinity; }
inline int threadsCount() const { return m_threads.list.size(); }
inline int64_t affinity() const { return m_threads.mask; }
inline ThreadsMode threadsMode() const { return m_threads.mode; }
static Config *load(int argc, char **argv, IWatcherListener *listener);
@ -94,17 +102,27 @@ private:
AlgoVariant getAlgoVariantLite() const;
# endif
struct Threads
{
inline Threads() : mask(-1L), count(0), mode(Automatic) {}
int64_t mask;
size_t count;
std::vector<CpuThread::Data> cpu;
std::vector<IThread *> list;
ThreadsMode mode;
};
AesMode m_aesMode;
AlgoVariant m_algoVariant;
bool m_doubleHash;
bool m_dryRun;
bool m_hugePages;
bool m_safe;
int m_maxCpuUsage;
int m_printTime;
int m_priority;
int64_t m_affinity;
size_t m_threadsCount;
std::vector<IThread *> m_threads;
Threads m_threads;
};

View file

@ -85,6 +85,8 @@ Options:\n\
--api-port=N port for the miner API\n\
--api-access-token=T access token for API\n\
--api-worker-id=ID custom worker-id for API\n\
--api-ipv6 enable IPv6 support for API\n\
--api-no-restricted enable full remote access (only if API token set)\n\
-h, --help display this help and exit\n\
-V, --version output version information and exit\n\
";
@ -98,7 +100,7 @@ static struct option const options[] = {
{ "api-access-token", 1, nullptr, xmrig::IConfig::ApiAccessTokenKey },
{ "api-port", 1, nullptr, xmrig::IConfig::ApiPort },
{ "api-worker-id", 1, nullptr, xmrig::IConfig::ApiWorkerIdKey },
{ "api-no-ipv6", 0, nullptr, xmrig::IConfig::ApiIPv6Key },
{ "api-ipv6", 0, nullptr, xmrig::IConfig::ApiIPv6Key },
{ "api-no-restricted", 0, nullptr, xmrig::IConfig::ApiRestrictedKey },
{ "av", 1, nullptr, xmrig::IConfig::AVKey },
{ "background", 0, nullptr, xmrig::IConfig::BackgroundKey },
@ -150,6 +152,7 @@ static struct option const config_options[] = {
{ "syslog", 0, nullptr, xmrig::IConfig::SyslogKey },
{ "threads", 1, nullptr, xmrig::IConfig::ThreadsKey },
{ "user-agent", 1, nullptr, xmrig::IConfig::UserAgentKey },
{ "hw-aes", 0, nullptr, xmrig::IConfig::HardwareAESKey },
{ 0, 0, 0, 0 }
};

View file

@ -25,8 +25,9 @@
#include <assert.h>
#include "common/config/ConfigLoader.h"
#include "common/Platform.h"
#include "core/Config.h"
#include "core/ConfigLoader.h"
#include "core/Controller.h"
#include "Cpu.h"
#include "interfaces/IControllerListener.h"
@ -34,7 +35,6 @@
#include "log/FileLog.h"
#include "log/Log.h"
#include "net/Network.h"
#include "Platform.h"
#ifdef HAVE_SYSLOG_H
@ -73,7 +73,6 @@ xmrig::Controller::Controller()
xmrig::Controller::~Controller()
{
ConfigLoader::release();
Platform::release();
delete d_ptr;
}

View file

@ -30,18 +30,8 @@
#include <stdint.h>
#define AEON_MEMORY 1048576
#define AEON_MASK 0xFFFF0
#define AEON_ITER 0x40000
#define MONERO_MEMORY 2097152
#define MONERO_MASK 0x1FFFF0
#define MONERO_ITER 0x80000
struct cryptonight_ctx {
alignas(16) uint8_t state0[200];
alignas(16) uint8_t state1[200];
alignas(16) uint8_t state[200];
alignas(16) uint8_t* memory;
};

View file

@ -27,13 +27,7 @@
#define __CRYPTONIGHT_ARM_H__
#if defined(XMRIG_ARM) && !defined(__clang__)
# include "aligned_malloc.h"
#else
# include <mm_malloc.h>
#endif
#include "common/utils/mm_malloc.h"
#include "crypto/CryptoNight.h"
#include "crypto/CryptoNight_constants.h"
#include "crypto/CryptoNight_monero.h"
@ -79,6 +73,19 @@ static inline __attribute__((always_inline)) __m128i _mm_set_epi64x(const uint64
}
#ifdef XMRIG_ARMv8
static inline __attribute__((always_inline)) __m128i _mm_aesenc_si128(__m128i v, __m128i rkey)
{
alignas(16) const __m128i zero = { 0 };
return veorq_u8(vaesmcq_u8(vaeseq_u8(v, zero)), rkey );
}
#else
static inline __attribute__((always_inline)) __m128i _mm_aesenc_si128(__m128i v, __m128i rkey)
{
}
#endif
/* this one was not implemented yet so here it is */
static inline __attribute__((always_inline)) uint64_t _mm_cvtsi128_si64(__m128i a)
{
@ -161,19 +168,19 @@ static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, _
*k0 = xout0;
*k1 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x01>(&xout0, &xout2) : soft_aes_genkey_sub<0x01>(&xout0, &xout2);
soft_aes_genkey_sub<0x01>(&xout0, &xout2);
*k2 = xout0;
*k3 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x02>(&xout0, &xout2) : soft_aes_genkey_sub<0x02>(&xout0, &xout2);
soft_aes_genkey_sub<0x02>(&xout0, &xout2);
*k4 = xout0;
*k5 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x04>(&xout0, &xout2) : soft_aes_genkey_sub<0x04>(&xout0, &xout2);
soft_aes_genkey_sub<0x04>(&xout0, &xout2);
*k6 = xout0;
*k7 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x08>(&xout0, &xout2) : soft_aes_genkey_sub<0x08>(&xout0, &xout2);
soft_aes_genkey_sub<0x08>(&xout0, &xout2);
*k8 = xout0;
*k9 = xout2;
}
@ -192,18 +199,16 @@ static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2,
*x6 = soft_aesenc((uint32_t*)x6, key);
*x7 = soft_aesenc((uint32_t*)x7, key);
}
# ifndef XMRIG_ARMv7
else {
*x0 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x0), key));
*x1 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x1), key));
*x2 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x2), key));
*x3 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x3), key));
*x4 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x4), key));
*x5 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x5), key));
*x6 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x6), key));
*x7 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x7), key));
*x0 = _mm_aesenc_si128(*x0, key);
*x1 = _mm_aesenc_si128(*x1, key);
*x2 = _mm_aesenc_si128(*x2, key);
*x3 = _mm_aesenc_si128(*x3, key);
*x4 = _mm_aesenc_si128(*x4, key);
*x5 = _mm_aesenc_si128(*x5, key);
*x6 = _mm_aesenc_si128(*x6, key);
*x7 = _mm_aesenc_si128(*x7, key);
}
# endif
}
@ -240,10 +245,6 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
for (size_t i = 0; i < 16; i++) {
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
@ -253,30 +254,13 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
if (!SOFT_AES) {
xin0 ^= k9;
xin1 ^= k9;
xin2 ^= k9;
xin3 ^= k9;
xin4 ^= k9;
xin5 ^= k9;
xin6 ^= k9;
xin7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
mix_and_propagate(xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7);
}
}
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
@ -286,20 +270,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
if (!SOFT_AES) {
xin0 ^= k9;
xin1 ^= k9;
xin2 ^= k9;
xin3 ^= k9;
xin4 ^= k9;
xin5 ^= k9;
xin6 ^= k9;
xin7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
_mm_store_si128(output + i + 0, xin0);
_mm_store_si128(output + i + 1, xin1);
@ -341,10 +312,6 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
@ -354,20 +321,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (!SOFT_AES) {
xout0 ^= k9;
xout1 ^= k9;
xout2 ^= k9;
xout3 ^= k9;
xout4 ^= k9;
xout5 ^= k9;
xout6 ^= k9;
xout7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
@ -385,10 +339,6 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
@ -398,29 +348,12 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (!SOFT_AES) {
xout0 ^= k9;
xout1 ^= k9;
xout2 ^= k9;
xout3 ^= k9;
xout4 ^= k9;
xout5 ^= k9;
xout6 ^= k9;
xout7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
}
for (size_t i = 0; i < 16; i++) {
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
@ -430,20 +363,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (!SOFT_AES) {
xout0 ^= k9;
xout1 ^= k9;
xout2 ^= k9;
xout3 ^= k9;
xout4 ^= k9;
xout5 ^= k9;
xout6 ^= k9;
xout7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
}
@ -460,8 +380,23 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
}
static inline void cryptonight_monero_tweak(uint64_t* mem_out, __m128i tmp)
{
mem_out[0] = EXTRACT64(tmp);
uint64_t vh = vgetq_lane_u64(tmp, 1);
uint8_t x = vh >> 24;
static const uint16_t table = 0x7531;
const uint8_t index = (((x >> 3) & 6) | (x & 1)) << 1;
vh ^= ((table >> index) & 0x3) << 28;
mem_out[1] = vh;
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
@ -472,14 +407,14 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
return;
}
keccak(input, (int) size, ctx->state0, 200);
keccak(input, (int) size, ctx[0]->state, 200);
VARIANT1_INIT(0);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx->state0, (__m128i*) ctx->memory);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->state, (__m128i*) ctx[0]->memory);
const uint8_t* l0 = ctx->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
const uint8_t* l0 = ctx[0]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t al0 = h0[0] ^ h0[4];
uint64_t ah0 = h0[1] ^ h0[5];
@ -495,13 +430,15 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
}
else {
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
# ifndef XMRIG_ARMv7
cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0);
# endif
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
}
if (VARIANT > 0) {
cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
} else {
_mm_store_si128((__m128i *)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
VARIANT1_1(&l0[idx0 & MASK]);
idx0 = EXTRACT64(cx);
bx0 = cx;
@ -532,15 +469,15 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
}
}
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx->memory, (__m128i*) ctx->state0);
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->memory, (__m128i*) ctx[0]->state);
keccakf(h0, 24);
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
@ -551,16 +488,16 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
return;
}
keccak(input, (int) size, ctx->state0, 200);
keccak(input + size, (int) size, ctx->state1, 200);
keccak(input, (int) size, ctx[0]->state, 200);
keccak(input + size, (int) size, ctx[1]->state, 200);
VARIANT1_INIT(0);
VARIANT1_INIT(1);
const uint8_t* l0 = ctx->memory;
const uint8_t* l1 = ctx->memory + MEM;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx->state1);
const uint8_t* l0 = ctx[0]->memory;
const uint8_t* l1 = ctx[1]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) h0, (__m128i*) l0);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) h1, (__m128i*) l1);
@ -586,16 +523,17 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
else {
cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
# ifndef XMRIG_ARMv7
cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0);
cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1);
# endif
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
VARIANT1_1(&l0[idx0 & MASK]);
VARIANT1_1(&l1[idx1 & MASK]);
if (VARIANT > 0) {
cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
cryptonight_monero_tweak((uint64_t*)&l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
} else {
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
};
idx0 = EXTRACT64(cx0);
idx1 = EXTRACT64(cx1);
@ -661,25 +599,25 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
keccakf(h0, 24);
keccakf(h1, 24);
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, output + 32);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
extra_hashes[ctx[1]->state[0] & 3](ctx[1]->state, 200, output + 32);
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx)
{
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx)
{
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx)
{
}

View file

@ -29,7 +29,7 @@
#include <stdint.h>
#include "xmrig.h"
#include "common/xmrig.h"
namespace xmrig

View file

@ -32,14 +32,14 @@
uint64_t tweak1_2_##part = 0; \
if (VARIANT > 0) { \
tweak1_2_##part = (*reinterpret_cast<const uint64_t*>(input + 35 + part * size) ^ \
*(reinterpret_cast<const uint64_t*>(ctx->state##part) + 24)); \
*(reinterpret_cast<const uint64_t*>(ctx[part]->state) + 24)); \
}
#else
# define VARIANT1_INIT(part) \
uint64_t tweak1_2_##part = 0; \
if (VARIANT > 0) { \
volatile const uint64_t a = *reinterpret_cast<const uint64_t*>(input + 35 + part * size); \
volatile const uint64_t b = *(reinterpret_cast<const uint64_t*>(ctx->state##part) + 24); \
volatile const uint64_t b = *(reinterpret_cast<const uint64_t*>(ctx[part]->state) + 24); \
tweak1_2_##part = a ^ b; \
}
#endif

View file

@ -26,62 +26,107 @@
#define __CRYPTONIGHT_TEST_H__
const static uint8_t test_input[152] = {
const static uint8_t test_input[380] = {
0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01,
0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19,
0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9,
0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F,
0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46,
0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02,
0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01
0x07, 0x07, 0xB4, 0x87, 0xD0, 0xD6, 0x05, 0x26, 0xE0, 0xC6, 0xDD, 0x9B, 0xC7, 0x18, 0xC3, 0xCF,
0x52, 0x04, 0xBD, 0x4F, 0x9B, 0x27, 0xF6, 0x73, 0xB9, 0x3F, 0xEF, 0x7B, 0xB2, 0xF7, 0x2B, 0xBB,
0x3F, 0x3E, 0x9C, 0x3E, 0x9D, 0x33, 0x1E, 0xDE, 0xAD, 0xBE, 0xEF, 0x4E, 0x00, 0x91, 0x81, 0x29,
0x74, 0xB2, 0x70, 0xE7, 0x6D, 0xD2, 0x2A, 0x5F, 0x52, 0x04, 0x93, 0xE6, 0x18, 0x89, 0x40, 0xD8,
0xC6, 0xE3, 0x90, 0x6E, 0xAA, 0x6A, 0xB7, 0xE2, 0x08, 0x7E, 0x78, 0x0E,
0x01, 0x00, 0xEE, 0xB2, 0xD1, 0xD6, 0x05, 0xFF, 0x27, 0x7F, 0x26, 0xDB, 0xAA, 0xB2, 0xC9, 0x26,
0x30, 0xC6, 0xCF, 0x11, 0x64, 0xEA, 0x6C, 0x8A, 0xE0, 0x98, 0x01, 0xF8, 0x75, 0x4B, 0x49, 0xAF,
0x79, 0x70, 0xAE, 0xEE, 0xA7, 0x62, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x47, 0x8C, 0x63, 0xE7, 0xD8,
0x40, 0x02, 0x3C, 0xDA, 0xEA, 0x92, 0x52, 0x53, 0xAC, 0xFD, 0xC7, 0x8A, 0x4C, 0x31, 0xB2, 0xF2,
0xEC, 0x72, 0x7B, 0xFF, 0xCE, 0xC0, 0xE7, 0x12, 0xD4, 0xE9, 0x2A, 0x01,
0x07, 0x07, 0xA9, 0xB7, 0xD1, 0xD6, 0x05, 0x3F, 0x0D, 0x5E, 0xFD, 0xC7, 0x03, 0xFC, 0xFC, 0xD2,
0xCE, 0xBC, 0x44, 0xD8, 0xAB, 0x44, 0xA6, 0xA0, 0x3A, 0xE4, 0x4D, 0x8F, 0x15, 0xAF, 0x62, 0x17,
0xD1, 0xE0, 0x92, 0x85, 0xE4, 0x73, 0xF9, 0x00, 0x00, 0x00, 0xA0, 0xFC, 0x09, 0xDE, 0xAB, 0xF5,
0x8B, 0x6F, 0x1D, 0xCA, 0xA8, 0xBA, 0xAC, 0x74, 0xDD, 0x74, 0x19, 0xD5, 0xD6, 0x10, 0xEC, 0x38,
0xCF, 0x50, 0x29, 0x6A, 0x07, 0x0B, 0x93, 0x8F, 0x8F, 0xA8, 0x10, 0x04
};
const static uint8_t test_output_v0[64] = {
const static uint8_t test_output_v0[160] = {
0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00,
0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66,
0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F,
0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00
0xA1, 0xB4, 0xFA, 0xE3, 0xE5, 0x76, 0xCE, 0xCF, 0xB7, 0x9C, 0xAF, 0x3E, 0x29, 0x92, 0xE4, 0xE0,
0x31, 0x24, 0x05, 0x48, 0xBF, 0x8D, 0x5F, 0x7B, 0x11, 0x03, 0x60, 0xAA, 0xD7, 0x50, 0x3F, 0x0C,
0x2D, 0x30, 0xF3, 0x87, 0x4F, 0x86, 0xA1, 0x4A, 0xB5, 0xA2, 0x1A, 0x08, 0xD0, 0x44, 0x2C, 0x9D,
0x16, 0xE9, 0x28, 0x49, 0xA1, 0xFF, 0x85, 0x6F, 0x12, 0xBB, 0x7D, 0xAB, 0x11, 0x1C, 0xE7, 0xF7,
0x2D, 0x9D, 0x19, 0xE4, 0xD2, 0x26, 0x44, 0x1E, 0xCD, 0x22, 0x08, 0x24, 0xA8, 0x97, 0x46, 0x62,
0x04, 0x84, 0x90, 0x4A, 0xEE, 0x99, 0x14, 0xED, 0xB8, 0xC6, 0x0D, 0x37, 0xA1, 0x66, 0x17, 0xB0
};
// Monero v7
const static uint8_t test_output_v1[64] = {
0xC9, 0xFA, 0xE8, 0x42, 0x5D, 0x86, 0x88, 0xDC, 0x23, 0x6B, 0xCD, 0xBC, 0x42, 0xFD, 0xB4, 0x2D,
0x37, 0x6C, 0x6E, 0xC1, 0x90, 0x50, 0x1A, 0xA8, 0x4B, 0x04, 0xA4, 0xB4, 0xCF, 0x1E, 0xE1, 0x22,
const static uint8_t test_output_v1[160] = {
0xF2, 0x2D, 0x3D, 0x62, 0x03, 0xD2, 0xA0, 0x8B, 0x41, 0xD9, 0x02, 0x72, 0x78, 0xD8, 0xBC, 0xC9,
0x83, 0xAC, 0xAD, 0xA9, 0xB6, 0x8E, 0x52, 0xE3, 0xC6, 0x89, 0x69, 0x2A, 0x50, 0xE9, 0x21, 0xD9
0x83, 0xAC, 0xAD, 0xA9, 0xB6, 0x8E, 0x52, 0xE3, 0xC6, 0x89, 0x69, 0x2A, 0x50, 0xE9, 0x21, 0xD9,
0xC9, 0xFA, 0xE8, 0x42, 0x5D, 0x86, 0x88, 0xDC, 0x23, 0x6B, 0xCD, 0xBC, 0x42, 0xFD, 0xB4, 0x2D,
0x37, 0x6C, 0x6E, 0xC1, 0x90, 0x50, 0x1A, 0xA8, 0x4B, 0x04, 0xA4, 0xB4, 0xCF, 0x1E, 0xE1, 0x22,
0xE7, 0x8C, 0x5A, 0x6E, 0x38, 0x30, 0x68, 0x4A, 0x73, 0xFC, 0x1B, 0xC6, 0x6D, 0xFC, 0x8D, 0x98,
0xB4, 0xC2, 0x23, 0x39, 0xAD, 0xE0, 0x9D, 0xF6, 0x6D, 0x8C, 0x6A, 0xAA, 0xF9, 0xB2, 0xE3, 0x4C,
0xB6, 0x90, 0x6C, 0xE6, 0x15, 0x5E, 0x46, 0x07, 0x9C, 0xB2, 0x6B, 0xAC, 0x3B, 0xAC, 0x1A, 0xDE,
0x92, 0x2C, 0xD6, 0x0C, 0x46, 0x9D, 0x9B, 0xC2, 0x84, 0x52, 0x65, 0xF6, 0xBD, 0xFA, 0x0D, 0x74,
0x00, 0x66, 0x10, 0x07, 0xF1, 0x19, 0x06, 0x3A, 0x6C, 0xFF, 0xEE, 0xB2, 0x40, 0xE5, 0x88, 0x2B,
0x6C, 0xAB, 0x6B, 0x1D, 0x88, 0xB8, 0x44, 0x25, 0xF4, 0xEA, 0xB7, 0xEC, 0xBA, 0x12, 0x8A, 0x24
};
#ifndef XMRIG_NO_AEON
const static uint8_t test_output_v0_lite[64] = {
const static uint8_t test_output_v0_lite[160] = {
0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88,
0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE,
0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD,
0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88
0x38, 0x08, 0xE1, 0x17, 0x0B, 0x99, 0x8D, 0x1A, 0x3C, 0xCE, 0x35, 0xC5, 0xC7, 0x3A, 0x00, 0x2E,
0xCB, 0x54, 0xF0, 0x78, 0x2E, 0x9E, 0xDB, 0xC7, 0xDF, 0x2E, 0x71, 0x9A, 0x16, 0x97, 0xC4, 0x18,
0x4B, 0x97, 0x07, 0xFE, 0x5D, 0x98, 0x9A, 0xD6, 0xD8, 0xE5, 0x92, 0x66, 0x87, 0x7F, 0x19, 0x37,
0xA2, 0x5E, 0xE6, 0x96, 0xB5, 0x97, 0x33, 0x89, 0xE0, 0xA7, 0xC9, 0xDD, 0x4A, 0x7E, 0x9E, 0x53,
0xBE, 0x91, 0x2B, 0xF5, 0xF5, 0xAF, 0xDD, 0x09, 0xA2, 0xF4, 0xA4, 0x56, 0xEB, 0x96, 0x22, 0xC9,
0x94, 0xFB, 0x7B, 0x28, 0xC9, 0x97, 0x65, 0x04, 0xAC, 0x4F, 0x84, 0x71, 0xDA, 0x6E, 0xD8, 0xC5
};
// AEON v7
const static uint8_t test_output_v1_lite[64] = {
const static uint8_t test_output_v1_lite[160] = {
0x6D, 0x8C, 0xDC, 0x44, 0x4E, 0x9B, 0xBB, 0xFD, 0x68, 0xFC, 0x43, 0xFC, 0xD4, 0x85, 0x5B, 0x22,
0x8C, 0x8A, 0x1B, 0xD9, 0x1D, 0x9D, 0x00, 0x28, 0x5B, 0xEC, 0x02, 0xB7, 0xCA, 0x2D, 0x67, 0x41,
0x87, 0xC4, 0xE5, 0x70, 0x65, 0x3E, 0xB4, 0xC2, 0xB4, 0x2B, 0x7A, 0x0D, 0x54, 0x65, 0x59, 0x45,
0x2D, 0xFA, 0xB5, 0x73, 0xB8, 0x2E, 0xC5, 0x2F, 0x15, 0x2B, 0x7F, 0xF9, 0x8E, 0x79, 0x44, 0x6F,
0x6D, 0x8C, 0xDC, 0x44, 0x4E, 0x9B, 0xBB, 0xFD, 0x68, 0xFC, 0x43, 0xFC, 0xD4, 0x85, 0x5B, 0x22,
0x8C, 0x8A, 0x1B, 0xD9, 0x1D, 0x9D, 0x00, 0x28, 0x5B, 0xEC, 0x02, 0xB7, 0xCA, 0x2D, 0x67, 0x41
0x16, 0x08, 0x74, 0xC7, 0xA2, 0xD2, 0xA3, 0x97, 0x95, 0x76, 0xCA, 0x4D, 0x06, 0x39, 0x7A, 0xAB,
0x6C, 0x87, 0x58, 0x33, 0x4D, 0xC8, 0x5A, 0xAB, 0x04, 0x27, 0xFE, 0x8B, 0x1C, 0x23, 0x2F, 0x32,
0xC0, 0x44, 0xFF, 0x0D, 0xB5, 0x3B, 0x27, 0x96, 0x06, 0x89, 0x7B, 0xA3, 0x0B, 0xD0, 0xCE, 0x9E,
0x90, 0x22, 0x77, 0x5A, 0xAD, 0xA1, 0xE5, 0xB6, 0xFC, 0xCB, 0x39, 0x7E, 0x2B, 0x10, 0xEE, 0xB4,
0x8C, 0x2B, 0xA4, 0x1F, 0x60, 0x76, 0x39, 0xD7, 0xF6, 0x46, 0x77, 0x18, 0x20, 0xAD, 0xD4, 0xC9,
0x87, 0xF7, 0x37, 0xDA, 0xFD, 0xBA, 0xBA, 0xD2, 0xF2, 0x68, 0xDC, 0x26, 0x8D, 0x1B, 0x08, 0xC6
};
#endif
#ifndef XMRIG_NO_SUMO
const static uint8_t test_output_heavy[64] = {
const static uint8_t test_output_heavy[160] = {
0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64,
0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2,
0x4D, 0x94, 0x7D, 0xD6, 0xDB, 0x6E, 0x07, 0x48, 0x26, 0x4A, 0x51, 0x2E, 0xAC, 0xF3, 0x25, 0x4A,
0x1F, 0x1A, 0xA2, 0x5B, 0xFC, 0x0A, 0xAD, 0x82, 0xDE, 0xA8, 0x99, 0x96, 0x88, 0x52, 0xD2, 0x7D,
0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64,
0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2
0x3E, 0xE1, 0x23, 0x03, 0x5A, 0x63, 0x7B, 0x66, 0xF6, 0xD7, 0xC2, 0x2A, 0x34, 0x5E, 0x88, 0xE7,
0xFA, 0xC4, 0x25, 0x36, 0x54, 0xCB, 0xD2, 0x5C, 0x2F, 0x80, 0x2A, 0xF9, 0xCC, 0x43, 0xF7, 0xCD,
0xE5, 0x18, 0xA8, 0x05, 0x60, 0x18, 0xA5, 0x73, 0x72, 0x9B, 0x32, 0xDC, 0x69, 0x83, 0xC1, 0xE1,
0x1F, 0xDB, 0xDA, 0x6B, 0xAC, 0xEC, 0x9F, 0x67, 0xF8, 0x27, 0x1D, 0xC7, 0xE6, 0x46, 0x42, 0xF9,
0x53, 0x62, 0x0A, 0x54, 0x7D, 0x43, 0xEA, 0x18, 0x94, 0xED, 0xD8, 0x92, 0x06, 0x6A, 0xA1, 0x51,
0xAD, 0xB1, 0xFD, 0x89, 0xFB, 0x5C, 0xB4, 0x25, 0x6A, 0xDD, 0xB0, 0x09, 0xC5, 0x72, 0x87, 0xEB
};
#endif

View file

@ -403,7 +403,7 @@ static inline void cryptonight_monero_tweak(uint64_t* mem_out, __m128i tmp)
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
@ -414,20 +414,20 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
return;
}
keccak(input, (int) size, ctx->state0, 200);
keccak(input, (int) size, ctx[0]->state, 200);
VARIANT1_INIT(0)
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx->state0, (__m128i*) ctx->memory);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->state, (__m128i*) ctx[0]->memory);
const uint8_t* l0 = ctx->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
const uint8_t* l0 = ctx[0]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t al0 = h0[0] ^ h0[4];
uint64_t ah0 = h0[1] ^ h0[5];
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
uint64_t idx0 = h0[0] ^ h0[4];
uint64_t idx0 = al0;
for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx;
@ -476,15 +476,15 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
}
}
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx->memory, (__m128i*) ctx->state0);
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->memory, (__m128i*) ctx[0]->state);
keccakf(h0, 24);
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
@ -495,16 +495,16 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
return;
}
keccak(input, (int) size, ctx->state0, 200);
keccak(input + size, (int) size, ctx->state1, 200);
keccak(input, (int) size, ctx[0]->state, 200);
keccak(input + size, (int) size, ctx[1]->state, 200);
VARIANT1_INIT(0);
VARIANT1_INIT(1);
const uint8_t* l0 = ctx->memory;
const uint8_t* l1 = ctx->memory + MEM;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx->state1);
const uint8_t* l0 = ctx[0]->memory;
const uint8_t* l1 = ctx[1]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) h0, (__m128i*) l0);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) h1, (__m128i*) l1);
@ -517,8 +517,8 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
uint64_t idx0 = h0[0] ^ h0[4];
uint64_t idx1 = h1[0] ^ h1[4];
uint64_t idx0 = al0;
uint64_t idx1 = al1;
for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx0, cx1;
@ -606,26 +606,382 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
keccakf(h0, 24);
keccakf(h1, 24);
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, output + 32);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
extra_hashes[ctx[1]->state[0] & 3](ctx[1]->state, 200, output + 32);
}
#define CN_STEP1(a, b, c, l, ptr, idx) \
ptr = reinterpret_cast<__m128i*>(&l[idx & MASK]); \
c = _mm_load_si128(ptr);
#define CN_STEP2(a, b, c, l, ptr, idx) \
if (SOFT_AES) { \
c = soft_aesenc(c, a); \
} else { \
c = _mm_aesenc_si128(c, a); \
} \
\
b = _mm_xor_si128(b, c); \
\
if (VARIANT > 0) { \
cryptonight_monero_tweak(reinterpret_cast<uint64_t*>(ptr), b); \
} else { \
_mm_store_si128(ptr, b); \
}
#define CN_STEP3(a, b, c, l, ptr, idx) \
idx = EXTRACT64(c); \
ptr = reinterpret_cast<__m128i*>(&l[idx & MASK]); \
b = _mm_load_si128(ptr);
#define CN_STEP4(a, b, c, l, mc, ptr, idx) \
lo = __umul128(idx, EXTRACT64(b), &hi); \
a = _mm_add_epi64(a, _mm_set_epi64x(lo, hi)); \
\
if (VARIANT > 0) { \
_mm_store_si128(ptr, _mm_xor_si128(a, mc)); \
} else { \
_mm_store_si128(ptr, a); \
} \
\
a = _mm_xor_si128(a, b); \
idx = EXTRACT64(a); \
\
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { \
int64_t n = ((int64_t*)&l[idx & MASK])[0]; \
int32_t d = ((int32_t*)&l[idx & MASK])[2]; \
int64_t q = n / (d | 0x5); \
((int64_t*)&l[idx & MASK])[0] = n ^ q; \
idx = d ^ q; \
}
#define CONST_INIT(ctx, n) \
__m128i mc##n; \
if (VARIANT > 0) { \
mc##n = _mm_set_epi64x(*reinterpret_cast<const uint64_t*>(input + n * size + 35) ^ \
*(reinterpret_cast<const uint64_t*>((ctx)->state) + 24), 0); \
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
constexpr size_t MEM = xmrig::cn_select_memory<ALGO>();
if (VARIANT > 0 && size < 43) {
memset(output, 0, 32 * 3);
return;
}
for (size_t i = 0; i < 3; i++) {
keccak(input + size * i, static_cast<int>(size), ctx[i]->state, 200);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory));
}
CONST_INIT(ctx[0], 0);
CONST_INIT(ctx[1], 1);
CONST_INIT(ctx[2], 2);
uint8_t* l0 = ctx[0]->memory;
uint8_t* l1 = ctx[1]->memory;
uint8_t* l2 = ctx[2]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
uint64_t* h2 = reinterpret_cast<uint64_t*>(ctx[2]->state);
__m128i ax0 = _mm_set_epi64x(h0[1] ^ h0[5], h0[0] ^ h0[4]);
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
__m128i ax1 = _mm_set_epi64x(h1[1] ^ h1[5], h1[0] ^ h1[4]);
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
__m128i ax2 = _mm_set_epi64x(h2[1] ^ h2[5], h2[0] ^ h2[4]);
__m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]);
__m128i cx0 = _mm_set_epi64x(0, 0);
__m128i cx1 = _mm_set_epi64x(0, 0);
__m128i cx2 = _mm_set_epi64x(0, 0);
uint64_t idx0, idx1, idx2;
idx0 = EXTRACT64(ax0);
idx1 = EXTRACT64(ax1);
idx2 = EXTRACT64(ax2);
for (size_t i = 0; i < ITERATIONS / 2; i++) {
uint64_t hi, lo;
__m128i *ptr0, *ptr1, *ptr2;
// EVEN ROUND
CN_STEP1(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP1(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP1(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP2(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP2(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP2(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP3(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP3(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP3(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP4(ax0, bx0, cx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, bx1, cx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, bx2, cx2, l2, mc2, ptr2, idx2);
// ODD ROUND
CN_STEP1(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP1(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP1(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP2(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP2(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP2(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP3(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP3(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP3(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP4(ax0, cx0, bx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, cx1, bx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, cx2, bx2, l2, mc2, ptr2, idx2);
}
for (size_t i = 0; i < 3; i++) {
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i);
}
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
constexpr size_t MEM = xmrig::cn_select_memory<ALGO>();
if (VARIANT > 0 && size < 43) {
memset(output, 0, 32 * 4);
return;
}
for (size_t i = 0; i < 4; i++) {
keccak(input + size * i, static_cast<int>(size), ctx[i]->state, 200);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory));
}
CONST_INIT(ctx[0], 0);
CONST_INIT(ctx[1], 1);
CONST_INIT(ctx[2], 2);
CONST_INIT(ctx[3], 3);
uint8_t* l0 = ctx[0]->memory;
uint8_t* l1 = ctx[1]->memory;
uint8_t* l2 = ctx[2]->memory;
uint8_t* l3 = ctx[3]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
uint64_t* h2 = reinterpret_cast<uint64_t*>(ctx[2]->state);
uint64_t* h3 = reinterpret_cast<uint64_t*>(ctx[3]->state);
__m128i ax0 = _mm_set_epi64x(h0[1] ^ h0[5], h0[0] ^ h0[4]);
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
__m128i ax1 = _mm_set_epi64x(h1[1] ^ h1[5], h1[0] ^ h1[4]);
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
__m128i ax2 = _mm_set_epi64x(h2[1] ^ h2[5], h2[0] ^ h2[4]);
__m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]);
__m128i ax3 = _mm_set_epi64x(h3[1] ^ h3[5], h3[0] ^ h3[4]);
__m128i bx3 = _mm_set_epi64x(h3[3] ^ h3[7], h3[2] ^ h3[6]);
__m128i cx0 = _mm_set_epi64x(0, 0);
__m128i cx1 = _mm_set_epi64x(0, 0);
__m128i cx2 = _mm_set_epi64x(0, 0);
__m128i cx3 = _mm_set_epi64x(0, 0);
uint64_t idx0, idx1, idx2, idx3;
idx0 = _mm_cvtsi128_si64(ax0);
idx1 = _mm_cvtsi128_si64(ax1);
idx2 = _mm_cvtsi128_si64(ax2);
idx3 = _mm_cvtsi128_si64(ax3);
for (size_t i = 0; i < ITERATIONS / 2; i++)
{
uint64_t hi, lo;
__m128i *ptr0, *ptr1, *ptr2, *ptr3;
// EVEN ROUND
CN_STEP1(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP1(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP1(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP1(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP2(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP2(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP2(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP2(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP3(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP3(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP3(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP3(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP4(ax0, bx0, cx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, bx1, cx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, bx2, cx2, l2, mc2, ptr2, idx2);
CN_STEP4(ax3, bx3, cx3, l3, mc3, ptr3, idx3);
// ODD ROUND
CN_STEP1(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP1(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP1(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP1(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP2(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP2(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP2(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP2(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP3(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP3(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP3(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP3(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP4(ax0, cx0, bx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, cx1, bx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, cx2, bx2, l2, mc2, ptr2, idx2);
CN_STEP4(ax3, cx3, bx3, l3, mc3, ptr3, idx3);
}
for (size_t i = 0; i < 4; i++) {
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i);
}
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
}
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
constexpr size_t MEM = xmrig::cn_select_memory<ALGO>();
if (VARIANT > 0 && size < 43) {
memset(output, 0, 32 * 5);
return;
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
{
for (size_t i = 0; i < 5; i++) {
keccak(input + size * i, static_cast<int>(size), ctx[i]->state, 200);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory));
}
CONST_INIT(ctx[0], 0);
CONST_INIT(ctx[1], 1);
CONST_INIT(ctx[2], 2);
CONST_INIT(ctx[3], 3);
CONST_INIT(ctx[4], 4);
uint8_t* l0 = ctx[0]->memory;
uint8_t* l1 = ctx[1]->memory;
uint8_t* l2 = ctx[2]->memory;
uint8_t* l3 = ctx[3]->memory;
uint8_t* l4 = ctx[4]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
uint64_t* h2 = reinterpret_cast<uint64_t*>(ctx[2]->state);
uint64_t* h3 = reinterpret_cast<uint64_t*>(ctx[3]->state);
uint64_t* h4 = reinterpret_cast<uint64_t*>(ctx[4]->state);
__m128i ax0 = _mm_set_epi64x(h0[1] ^ h0[5], h0[0] ^ h0[4]);
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
__m128i ax1 = _mm_set_epi64x(h1[1] ^ h1[5], h1[0] ^ h1[4]);
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
__m128i ax2 = _mm_set_epi64x(h2[1] ^ h2[5], h2[0] ^ h2[4]);
__m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]);
__m128i ax3 = _mm_set_epi64x(h3[1] ^ h3[5], h3[0] ^ h3[4]);
__m128i bx3 = _mm_set_epi64x(h3[3] ^ h3[7], h3[2] ^ h3[6]);
__m128i ax4 = _mm_set_epi64x(h4[1] ^ h4[5], h4[0] ^ h4[4]);
__m128i bx4 = _mm_set_epi64x(h4[3] ^ h4[7], h4[2] ^ h4[6]);
__m128i cx0 = _mm_set_epi64x(0, 0);
__m128i cx1 = _mm_set_epi64x(0, 0);
__m128i cx2 = _mm_set_epi64x(0, 0);
__m128i cx3 = _mm_set_epi64x(0, 0);
__m128i cx4 = _mm_set_epi64x(0, 0);
uint64_t idx0, idx1, idx2, idx3, idx4;
idx0 = _mm_cvtsi128_si64(ax0);
idx1 = _mm_cvtsi128_si64(ax1);
idx2 = _mm_cvtsi128_si64(ax2);
idx3 = _mm_cvtsi128_si64(ax3);
idx4 = _mm_cvtsi128_si64(ax4);
for (size_t i = 0; i < ITERATIONS / 2; i++)
{
uint64_t hi, lo;
__m128i *ptr0, *ptr1, *ptr2, *ptr3, *ptr4;
// EVEN ROUND
CN_STEP1(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP1(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP1(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP1(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP1(ax4, bx4, cx4, l4, ptr4, idx4);
CN_STEP2(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP2(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP2(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP2(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP2(ax4, bx4, cx4, l4, ptr4, idx4);
CN_STEP3(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP3(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP3(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP3(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP3(ax4, bx4, cx4, l4, ptr4, idx4);
CN_STEP4(ax0, bx0, cx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, bx1, cx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, bx2, cx2, l2, mc2, ptr2, idx2);
CN_STEP4(ax3, bx3, cx3, l3, mc3, ptr3, idx3);
CN_STEP4(ax4, bx4, cx4, l4, mc4, ptr4, idx4);
// ODD ROUND
CN_STEP1(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP1(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP1(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP1(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP1(ax4, cx4, bx4, l4, ptr4, idx4);
CN_STEP2(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP2(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP2(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP2(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP2(ax4, cx4, bx4, l4, ptr4, idx4);
CN_STEP3(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP3(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP3(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP3(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP3(ax4, cx4, bx4, l4, ptr4, idx4);
CN_STEP4(ax0, cx0, bx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, cx1, bx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, cx2, bx2, l2, mc2, ptr2, idx2);
CN_STEP4(ax3, cx3, bx3, l3, mc3, ptr3, idx3);
CN_STEP4(ax4, cx4, bx4, l4, mc4, ptr4, idx4);
}
for (size_t i = 0; i < 5; i++) {
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i);
}
}
#endif /* __CRYPTONIGHT_X86_H__ */

View file

@ -105,6 +105,23 @@ static inline __m128i soft_aesenc(const uint32_t* in, __m128i key)
return _mm_xor_si128(out, key);
}
static inline __m128i soft_aesenc(__m128i in, __m128i key)
{
uint32_t x0, x1, x2, x3;
x0 = _mm_cvtsi128_si32(in);
x1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0x55));
x2 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xAA));
x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xFF));
__m128i out = _mm_set_epi32(
(saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]),
(saes_table[0][x2 & 0xff] ^ saes_table[1][(x3 >> 8) & 0xff] ^ saes_table[2][(x0 >> 16) & 0xff] ^ saes_table[3][x1 >> 24]),
(saes_table[0][x1 & 0xff] ^ saes_table[1][(x2 >> 8) & 0xff] ^ saes_table[2][(x3 >> 16) & 0xff] ^ saes_table[3][x0 >> 24]),
(saes_table[0][x0 & 0xff] ^ saes_table[1][(x1 >> 8) & 0xff] ^ saes_table[2][(x2 >> 16) & 0xff] ^ saes_table[3][x3 >> 24]));
return _mm_xor_si128(out, key);
}
static inline uint32_t sub_word(uint32_t key)
{
return (saes_sbox[key >> 24 ] << 24) |

View file

@ -74,6 +74,7 @@ public:
MaxCPUUsageKey = 1004,
SafeKey = 1005,
ThreadsKey = 't',
HardwareAESKey = 1011,
// xmrig-proxy
AccessLogFileKey = 'A',

View file

@ -27,8 +27,8 @@
#include <stdint.h>
#include "common/xmrig.h"
#include "rapidjson/fwd.h"
#include "xmrig.h"
namespace xmrig {
@ -43,14 +43,23 @@ public:
CUDA
};
enum Multiway {
SingleWay = 1,
DoubleWay,
TripleWay,
QuadWay,
PentaWay
};
virtual ~IThread() {}
virtual Algo algorithm() const = 0;
virtual int multiway() const = 0;
virtual int priority() const = 0;
virtual int64_t affinity() const = 0;
virtual size_t index() const = 0;
virtual Type type() const = 0;
virtual Algo algorithm() const = 0;
virtual int priority() const = 0;
virtual int64_t affinity() const = 0;
virtual Multiway multiway() const = 0;
virtual rapidjson::Value toConfig(rapidjson::Document &doc) const = 0;
virtual size_t index() const = 0;
virtual Type type() const = 0;
# ifndef XMRIG_NO_API
virtual rapidjson::Value toAPI(rapidjson::Document &doc) const = 0;

View file

@ -33,10 +33,11 @@ class IWorker
public:
virtual ~IWorker() {}
virtual bool start() = 0;
virtual bool selfTest() = 0;
virtual size_t id() const = 0;
virtual uint64_t hashCount() const = 0;
virtual uint64_t timestamp() const = 0;
virtual void start() = 0;
};

View file

@ -4,8 +4,8 @@
* 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 2016-2017 XMRig <support@xmrig.com>
*
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 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
@ -38,6 +38,8 @@ Log *Log::m_self = nullptr;
void Log::message(Log::Level level, const char* fmt, ...)
{
uv_mutex_lock(&m_mutex);
va_list args;
va_list copy;
va_start(args, fmt);
@ -47,11 +49,15 @@ void Log::message(Log::Level level, const char* fmt, ...)
backend->message(level, fmt, copy);
va_end(copy);
}
uv_mutex_unlock(&m_mutex);
}
void Log::text(const char* fmt, ...)
{
uv_mutex_lock(&m_mutex);
va_list args;
va_list copy;
va_start(args, fmt);
@ -63,6 +69,8 @@ void Log::text(const char* fmt, ...)
}
va_end(args);
uv_mutex_unlock(&m_mutex);
}

View file

@ -4,8 +4,8 @@
* 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 2016-2017 XMRig <support@xmrig.com>
*
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 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
@ -25,6 +25,7 @@
#define __LOG_H__
#include <assert.h>
#include <uv.h>
#include <vector>
@ -54,20 +55,28 @@ public:
constexpr static const char* kCL_GRAY = "\x1B[90m";
# endif
static inline Log* i() { return m_self; }
static inline Log* i() { assert(m_self != nullptr); return m_self; }
static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); }
static inline void init() { if (!m_self) { m_self = new Log();} }
static inline void release() { delete m_self; }
static inline void init() { if (!m_self) { new Log(); } }
static inline void release() { assert(m_self != nullptr); delete m_self; }
void message(Level level, const char* fmt, ...);
void text(const char* fmt, ...);
private:
inline Log() {}
inline Log() {
assert(m_self == nullptr);
uv_mutex_init(&m_mutex);
m_self = this;
}
~Log();
static Log *m_self;
std::vector<ILogBackend*> m_backends;
uv_mutex_t m_mutex;
};

View file

@ -209,6 +209,17 @@ void Job::toHex(const unsigned char* in, unsigned int len, char* out)
}
#ifdef APP_DEBUG
char *Job::toHex(const unsigned char* in, unsigned int len)
{
char *out = new char[len * 2 + 1]();
toHex(in, len, out);
return out;
}
#endif
bool Job::operator==(const Job &other) const
{
return m_id == other.m_id && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0;

View file

@ -30,8 +30,8 @@
#include <stdint.h>
#include "common/xmrig.h"
#include "net/Id.h"
#include "xmrig.h"
class Job
@ -69,6 +69,10 @@ public:
static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
static void toHex(const unsigned char* in, unsigned int len, char* out);
# ifdef APP_DEBUG
static char *toHex(const unsigned char* in, unsigned int len);
# endif
bool operator==(const Job &other) const;
bool operator!=(const Job &other) const;

View file

@ -28,8 +28,8 @@
#include <stdint.h>
#include "core/utils/c_str.h"
#include "xmrig.h"
#include "common/utils/c_str.h"
#include "common/xmrig.h"
class Pool

View file

@ -22,13 +22,13 @@
*/
#include "common/Platform.h"
#include "common/xmrig.h"
#include "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/Job.h"
#include "net/strategies/DonateStrategy.h"
#include "net/strategies/FailoverStrategy.h"
#include "Platform.h"
#include "xmrig.h"
extern "C"

View file

@ -22,10 +22,10 @@
*/
#include "common/Platform.h"
#include "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/strategies/FailoverStrategy.h"
#include "Platform.h"
FailoverStrategy::FailoverStrategy(const std::vector<Pool> &urls, int retryPause, int retries, IStrategyListener *listener, bool quiet) :

View file

@ -22,10 +22,10 @@
*/
#include "common/Platform.h"
#include "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/strategies/SinglePoolStrategy.h"
#include "Platform.h"
SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, IStrategyListener *listener, bool quiet) :

View file

@ -24,7 +24,7 @@
#include <assert.h>
#include "core/CommonConfig.h"
#include "net/Pool.h"
#include "rapidjson/document.h"
#include "workers/CpuThread.h"
@ -54,6 +54,12 @@ xmrig::CpuThread::~CpuThread()
}
bool xmrig::CpuThread::isSoftAES(AlgoVariant av)
{
return av == AV_SINGLE_SOFT || av == AV_DOUBLE_SOFT || av > AV_PENTA;
}
xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant av, Variant variant)
{
assert(variant == VARIANT_NONE || variant == VARIANT_V1);
@ -138,42 +144,6 @@ xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, Algo algorithm, A
{
assert(av > AV_AUTO && av < AV_MAX);
Multiway multiway = SingleWay;
bool softAES = false;
switch (av) {
case AV_SINGLE_SOFT:
softAES = true;
break;
case AV_DOUBLE_SOFT:
softAES = true;
case AV_DOUBLE:
multiway = DoubleWay;
break;
case AV_TRIPLE_SOFT:
softAES = true;
case AV_TRIPLE:
multiway = TripleWay;
break;
case AV_QUAD_SOFT:
softAES = true;
case AV_QUAD:
multiway = QuadWay;
break;
case AV_PENTA_SOFT:
softAES = true;
case AV_PENTA:
multiway = PentaWay;
break;
default:
break;
}
int64_t cpuId = -1L;
if (affinity != -1L) {
@ -193,14 +163,92 @@ xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, Algo algorithm, A
}
}
return new CpuThread(index, algorithm, av, multiway, cpuId, priority, softAES, false);
return new CpuThread(index, algorithm, av, multiway(av), cpuId, priority, isSoftAES(av), false);
}
xmrig::CpuThread *xmrig::CpuThread::createFromData(size_t index, Algo algorithm, const CpuThread::Data &data, int priority, bool softAES)
{
int av = AV_AUTO;
const Multiway multiway = data.multiway;
if (multiway <= DoubleWay) {
av = softAES ? (multiway + 2) : multiway;
}
else {
av = softAES ? (multiway + 5) : (multiway + 2);
}
assert(av > AV_AUTO && av < AV_MAX);
return new CpuThread(index, algorithm, static_cast<AlgoVariant>(av), multiway, data.affinity, priority, softAES, false);
}
xmrig::CpuThread::Data xmrig::CpuThread::parse(const rapidjson::Value &object)
{
Data data;
const auto &multiway = object["low_power_mode"];
if (multiway.IsBool()) {
data.multiway = multiway.IsTrue() ? DoubleWay : SingleWay;
data.valid = true;
}
else if (multiway.IsUint()) {
data.setMultiway(multiway.GetInt());
}
if (!data.valid) {
return data;
}
const auto &affinity = object["affine_to_cpu"];
if (affinity.IsUint64()) {
data.affinity = affinity.GetInt64();
}
return data;
}
xmrig::IThread::Multiway xmrig::CpuThread::multiway(AlgoVariant av)
{
switch (av) {
case AV_SINGLE:
case AV_SINGLE_SOFT:
return SingleWay;
case AV_DOUBLE_SOFT:
case AV_DOUBLE:
return DoubleWay;
case AV_TRIPLE_SOFT:
case AV_TRIPLE:
return TripleWay;
case AV_QUAD_SOFT:
case AV_QUAD:
return QuadWay;
case AV_PENTA_SOFT:
case AV_PENTA:
return PentaWay;
default:
break;
}
return SingleWay;
}
#ifndef XMRIG_NO_API
rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const
{
rapidjson::Value obj(rapidjson::kObjectType);
using namespace rapidjson;
Value obj(kObjectType);
auto &allocator = doc.GetAllocator();
obj.AddMember("type", "cpu", allocator);
@ -214,3 +262,17 @@ rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const
return obj;
}
#endif
rapidjson::Value xmrig::CpuThread::toConfig(rapidjson::Document &doc) const
{
using namespace rapidjson;
Value obj(kObjectType);
auto &allocator = doc.GetAllocator();
obj.AddMember("low_power_mode", multiway(), allocator);
obj.AddMember("affine_to_cpu", affinity() == -1L ? Value(kFalseType) : Value(affinity()), allocator);
return obj;
}

View file

@ -25,8 +25,8 @@
#define __CPUTHREAD_H__
#include "common/xmrig.h"
#include "interfaces/IThread.h"
#include "xmrig.h"
struct cryptonight_ctx;
@ -38,37 +38,54 @@ namespace xmrig {
class CpuThread : public IThread
{
public:
enum Multiway {
SingleWay = 1,
DoubleWay,
TripleWay,
QuadWay,
PentaWay
struct Data
{
inline Data() : valid(false), affinity(-1L), multiway(SingleWay) {}
inline void setMultiway(int value)
{
if (value >= SingleWay && value <= PentaWay) {
multiway = static_cast<Multiway>(value);
valid = true;
}
}
bool valid;
int64_t affinity;
Multiway multiway;
};
CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch);
~CpuThread();
typedef void (*cn_hash_fun)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx);
typedef void (*cn_hash_fun)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx **ctx);
static bool isSoftAES(AlgoVariant av);
static cn_hash_fun fn(Algo algorithm, AlgoVariant av, Variant variant);
static CpuThread *createFromAV(size_t index, Algo algorithm, AlgoVariant av, int64_t affinity, int priority);
static CpuThread *createFromData(size_t index, Algo algorithm, const CpuThread::Data &data, int priority, bool softAES);
static Data parse(const rapidjson::Value &object);
static Multiway multiway(AlgoVariant av);
inline bool isPrefetch() const { return m_prefetch; }
inline bool isSoftAES() const { return m_softAES; }
inline cn_hash_fun fn(Variant variant) const { return fn(m_algorithm, m_av, variant); }
inline Algo algorithm() const override { return m_algorithm; }
inline int multiway() const override { return m_multiway; }
inline int priority() const override { return m_priority; }
inline int64_t affinity() const override { return m_affinity; }
inline Multiway multiway() const override { return m_multiway; }
inline size_t index() const override { return m_index; }
inline Type type() const override { return CPU; }
protected:
# ifndef XMRIG_NO_API
rapidjson::Value toAPI(rapidjson::Document &doc) const override;
# endif
rapidjson::Value toConfig(rapidjson::Document &doc) const override;
private:
const Algo m_algorithm;
const AlgoVariant m_av;

View file

@ -25,11 +25,10 @@
#include "workers/Handle.h"
Handle::Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays, int64_t affinity) :
m_affinity(affinity),
Handle::Handle(xmrig::IThread *config, uint32_t offset, size_t totalWays) :
m_worker(nullptr),
m_totalThreads(totalThreads),
m_totalWays(totalWays),
m_offset(offset),
m_config(config)
{
}

View file

@ -25,6 +25,7 @@
#define __HANDLE_H__
#include <assert.h>
#include <stdint.h>
#include <uv.h>
@ -38,23 +39,21 @@ class IWorker;
class Handle
{
public:
Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays, int64_t affinity);
Handle(xmrig::IThread *config, uint32_t offset, size_t totalWays);
void join();
void start(void (*callback) (void *));
inline int64_t affinity() const { return m_affinity; }
inline IWorker *worker() const { return m_worker; }
inline size_t threadId() const { return m_config->index(); }
inline size_t totalThreads() const { return m_totalThreads; }
inline size_t totalWays() const { return m_totalWays; }
inline void setWorker(IWorker *worker) { m_worker = worker; }
inline uint32_t offset() const { return m_offset; }
inline void setWorker(IWorker *worker) { assert(worker != nullptr); m_worker = worker; }
inline xmrig::IThread *config() const { return m_config; }
private:
int64_t m_affinity;
IWorker *m_worker;
size_t m_totalThreads;
size_t m_totalWays;
uint32_t m_offset;
uv_thread_t m_thread;
xmrig::IThread *m_config;
};

View file

@ -22,6 +22,7 @@
*/
#include <assert.h>
#include <chrono>
#include <math.h>
#include <memory.h>
@ -45,7 +46,7 @@ inline const char *format(double h, char* buf, size_t size)
}
Hashrate::Hashrate(int threads, xmrig::Controller *controller) :
Hashrate::Hashrate(size_t threads, xmrig::Controller *controller) :
m_highest(0.0),
m_threads(threads),
m_controller(controller)
@ -54,13 +55,10 @@ Hashrate::Hashrate(int threads, xmrig::Controller *controller) :
m_timestamps = new uint64_t*[threads];
m_top = new uint32_t[threads];
for (int i = 0; i < threads; i++) {
m_counts[i] = new uint64_t[kBucketSize];
m_timestamps[i] = new uint64_t[kBucketSize];
m_top[i] = 0;
memset(m_counts[0], 0, sizeof(uint64_t) * kBucketSize);
memset(m_timestamps[0], 0, sizeof(uint64_t) * kBucketSize);
for (size_t i = 0; i < threads; i++) {
m_counts[i] = new uint64_t[kBucketSize]();
m_timestamps[i] = new uint64_t[kBucketSize]();
m_top[i] = 0;
}
const int printTime = controller->config()->printTime();
@ -79,7 +77,7 @@ double Hashrate::calc(size_t ms) const
double result = 0.0;
double data;
for (int i = 0; i < m_threads; ++i) {
for (size_t i = 0; i < m_threads; ++i) {
data = calc(i, ms);
if (isnormal(data)) {
result += data;
@ -92,6 +90,8 @@ double Hashrate::calc(size_t ms) const
double Hashrate::calc(size_t threadId, size_t ms) const
{
assert(threadId < m_threads);
using namespace std::chrono;
const uint64_t now = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();

View file

@ -43,7 +43,7 @@ public:
LargeInterval = 900000
};
Hashrate(int threads, xmrig::Controller *controller);
Hashrate(size_t threads, xmrig::Controller *controller);
double calc(size_t ms) const;
double calc(size_t threadId, size_t ms) const;
void add(size_t threadId, uint64_t count, uint64_t timestamp);
@ -52,7 +52,7 @@ public:
void updateHighest();
inline double highest() const { return m_highest; }
inline int threads() const { return m_threads; }
inline size_t threads() const { return m_threads; }
private:
static void onReport(uv_timer_t *handle);
@ -61,7 +61,7 @@ private:
constexpr static size_t kBucketMask = kBucketSize - 1;
double m_highest;
int m_threads;
size_t m_threads;
uint32_t* m_top;
uint64_t** m_counts;
uint64_t** m_timestamps;

View file

@ -28,46 +28,59 @@
#include "crypto/CryptoNight_test.h"
#include "workers/CpuThread.h"
#include "workers/DoubleWorker.h"
#include "workers/MultiWorker.h"
#include "workers/Workers.h"
class DoubleWorker::State
{
public:
inline State() :
nonce1(0),
nonce2(0)
{}
Job job;
uint32_t nonce1;
uint32_t nonce2;
uint8_t blob[84 * 2];
};
DoubleWorker::DoubleWorker(Handle *handle)
template<size_t N>
MultiWorker<N>::MultiWorker(Handle *handle)
: Worker(handle)
{
m_state = new State();
m_pausedState = new State();
m_memory = Mem::create(m_ctx, m_thread->algorithm(), N);
}
DoubleWorker::~DoubleWorker()
template<size_t N>
MultiWorker<N>::~MultiWorker()
{
delete m_state;
delete m_pausedState;
Mem::release(m_ctx, N, m_memory);
}
bool DoubleWorker::start()
template<size_t N>
bool MultiWorker<N>::selfTest()
{
if (!selfTest()) {
if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) {
return false;
}
m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_hash, m_ctx);
if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_hash, test_output_v0, sizeof m_hash) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx);
return memcmp(m_hash, test_output_v1, sizeof m_hash) == 0;
}
# ifndef XMRIG_NO_AEON
if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_hash, test_output_v0_lite, sizeof m_hash) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx);
return memcmp(m_hash, test_output_v1_lite, sizeof m_hash) == 0;
}
# endif
# ifndef XMRIG_NO_SUMO
return m_thread->algorithm() == xmrig::CRYPTONIGHT_HEAVY && memcmp(m_hash, test_output_heavy, sizeof m_hash) == 0;
# else
return false;
# endif
}
template<size_t N>
void MultiWorker<N>::start()
{
while (Workers::sequence() > 0) {
if (Workers::isPaused()) {
do {
@ -83,38 +96,35 @@ bool DoubleWorker::start()
}
while (!Workers::isOutdated(m_sequence)) {
if ((m_count & 0xF) == 0) {
if ((m_count & 0x7) == 0) {
storeStats();
}
m_count += 2;
*Job::nonce(m_state->blob) = ++m_state->nonce1;
*Job::nonce(m_state->blob + m_state->job.size()) = ++m_state->nonce2;
m_thread->fn(m_state.job.variant())(m_state.blob, m_state.job.size(), m_hash, m_ctx);
m_thread->fn(m_state->job.variant())(m_state->blob, m_state->job.size(), m_hash, m_ctx);
for (size_t i = 0; i < N; ++i) {
if (*reinterpret_cast<uint64_t*>(m_hash + (i * 32) + 24) < m_state.job.target()) {
Workers::submit(JobResult(m_state.job.poolId(), m_state.job.id(), *nonce(i), m_hash + (i * 32), m_state.job.diff()));
}
if (*reinterpret_cast<uint64_t*>(m_hash + 24) < m_state->job.target()) {
Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, m_state->job.diff()));
*nonce(i) += 1;
}
if (*reinterpret_cast<uint64_t*>(m_hash + 32 + 24) < m_state->job.target()) {
Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, m_state->job.diff()));
}
m_count += N;
std::this_thread::yield();
}
consumeJob();
}
return true;
}
bool DoubleWorker::resume(const Job &job)
template<size_t N>
bool MultiWorker<N>::resume(const Job &job)
{
if (m_state->job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState->job.id()) {
*m_state = *m_pausedState;
if (m_state.job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState.job.id()) {
m_state = m_pausedState;
return true;
}
@ -122,41 +132,12 @@ bool DoubleWorker::resume(const Job &job)
}
bool DoubleWorker::selfTest()
{
if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) {
return false;
}
m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_hash, m_ctx);
if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_hash, test_output_v0, 64) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx);
return memcmp(m_hash, test_output_v1, 64) == 0;
}
# ifndef XMRIG_NO_AEON
if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_hash, test_output_v0_lite, 64) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx);
return memcmp(m_hash, test_output_v1_lite, 64) == 0;
}
# endif
# ifndef XMRIG_NO_SUMO
return m_thread->algorithm() == xmrig::CRYPTONIGHT_HEAVY && memcmp(m_hash, test_output_heavy, 64) == 0;
# else
return false;
# endif
}
void DoubleWorker::consumeJob()
template<size_t N>
void MultiWorker<N>::consumeJob()
{
Job job = Workers::job();
m_sequence = Workers::sequence();
if (m_state->job == job) {
if (m_state.job == job) {
return;
}
@ -166,24 +147,39 @@ void DoubleWorker::consumeJob()
return;
}
m_state->job = std::move(job);
memcpy(m_state->blob, m_state->job.blob(), m_state->job.size());
memcpy(m_state->blob + m_state->job.size(), m_state->job.blob(), m_state->job.size());
m_state.job = job;
if (m_state->job.isNicehash()) {
m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / m_totalWays * m_id);
m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / m_totalWays * (m_id + m_totalThreads));
const size_t size = m_state.job.size();
memcpy(m_state.blob, m_state.job.blob(), m_state.job.size());
if (N > 1) {
for (size_t i = 1; i < N; ++i) {
memcpy(m_state.blob + (i * size), m_state.blob, size);
}
}
else {
m_state->nonce1 = 0xffffffffU / m_totalWays * m_id;
m_state->nonce2 = 0xffffffffU / m_totalWays * (m_id + m_totalThreads);
for (size_t i = 0; i < N; ++i) {
if (m_state.job.isNicehash()) {
*nonce(i) = (*nonce(i) & 0xff000000U) + (0xffffffU / m_totalWays * (m_offset + i));
}
else {
*nonce(i) = 0xffffffffU / m_totalWays * (m_offset + i);
}
}
}
void DoubleWorker::save(const Job &job)
template<size_t N>
void MultiWorker<N>::save(const Job &job)
{
if (job.poolId() == -1 && m_state->job.poolId() >= 0) {
*m_pausedState = *m_state;
if (job.poolId() == -1 && m_state.job.poolId() >= 0) {
m_pausedState = m_state;
}
}
template class MultiWorker<1>;
template class MultiWorker<2>;
template class MultiWorker<3>;
template class MultiWorker<4>;
template class MultiWorker<5>;

View file

@ -22,10 +22,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DOUBLEWORKER_H__
#define __DOUBLEWORKER_H__
#ifndef __MULTIWORKER_H__
#define __MULTIWORKER_H__
#include "Mem.h"
#include "net/Job.h"
#include "net/JobResult.h"
#include "workers/Worker.h"
@ -34,26 +35,39 @@
class Handle;
class DoubleWorker : public Worker
template<size_t N>
class MultiWorker : public Worker
{
public:
DoubleWorker(Handle *handle);
~DoubleWorker();
MultiWorker(Handle *handle);
~MultiWorker();
bool start() override;
protected:
bool selfTest() override;
void start() override;
private:
bool resume(const Job &job);
bool selfTest();
void consumeJob();
void save(const Job &job);
class State;
inline uint32_t *nonce(size_t index)
{
return reinterpret_cast<uint32_t*>(m_state.blob + (index * m_state.job.size()) + 39);
}
uint8_t m_hash[64];
State *m_state;
State *m_pausedState;
struct State
{
alignas(16) uint8_t blob[96 * N];
Job job;
};
cryptonight_ctx *m_ctx[N];
State m_pausedState;
State m_state;
uint8_t m_hash[N * 32];
};
#endif /* __SINGLEWORKER_H__ */
#endif /* __MULTIWORKER_H__ */

View file

@ -1,158 +0,0 @@
/* 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 2016-2018 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 <thread>
#include "crypto/CryptoNight_test.h"
#include "workers/CpuThread.h"
#include "workers/SingleWorker.h"
#include "workers/Workers.h"
SingleWorker::SingleWorker(Handle *handle)
: Worker(handle)
{
}
bool SingleWorker::start()
{
if (!selfTest()) {
return false;
}
while (Workers::sequence() > 0) {
if (Workers::isPaused()) {
do {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
while (Workers::isPaused());
if (Workers::sequence() == 0) {
break;
}
consumeJob();
}
while (!Workers::isOutdated(m_sequence)) {
if ((m_count & 0xF) == 0) {
storeStats();
}
m_count++;
*m_job.nonce() = ++m_result.nonce;
m_thread->fn(m_job.variant())(m_job.blob(), m_job.size(), m_result.result, m_ctx);
if (*reinterpret_cast<uint64_t*>(m_result.result + 24) < m_job.target()) {
Workers::submit(m_result);
}
std::this_thread::yield();
}
consumeJob();
}
return true;
}
bool SingleWorker::resume(const Job &job)
{
if (m_job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_paused.id()) {
m_job = m_paused;
m_result = m_job;
m_result.nonce = *m_job.nonce();
return true;
}
return false;
}
bool SingleWorker::selfTest()
{
if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) {
return false;
}
m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_result.result, m_ctx);
if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_result.result, test_output_v0, 32) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_result.result, m_ctx);
return memcmp(m_result.result, test_output_v1, 32) == 0;
}
# ifndef XMRIG_NO_AEON
if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_result.result, test_output_v0_lite, 32) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_result.result, m_ctx);
return memcmp(m_result.result, test_output_v1_lite, 32) == 0;
}
# endif
# ifndef XMRIG_NO_SUMO
return m_thread->algorithm() == xmrig::CRYPTONIGHT_HEAVY && memcmp(m_result.result, test_output_heavy, 32) == 0;
# else
return false;
# endif
}
void SingleWorker::consumeJob()
{
Job job = Workers::job();
m_sequence = Workers::sequence();
if (m_job == job) {
return;
}
save(job);
if (resume(job)) {
return;
}
m_job = std::move(job);
m_result = m_job;
if (m_job.isNicehash()) {
m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_totalWays * m_id);
}
else {
m_result.nonce = 0xffffffffU / m_totalWays * m_id;
}
}
void SingleWorker::save(const Job &job)
{
if (job.poolId() == -1 && m_job.poolId() >= 0) {
m_paused = m_job;
}
}

View file

@ -24,9 +24,8 @@
#include <chrono>
#include "common/Platform.h"
#include "Cpu.h"
#include "Mem.h"
#include "Platform.h"
#include "workers/CpuThread.h"
#include "workers/Handle.h"
#include "workers/Worker.h"
@ -34,25 +33,19 @@
Worker::Worker(Handle *handle) :
m_id(handle->threadId()),
m_totalThreads(handle->totalThreads()),
m_totalWays(handle->totalWays()),
m_offset(handle->offset()),
m_hashCount(0),
m_timestamp(0),
m_count(0),
m_sequence(0),
m_thread(static_cast<xmrig::CpuThread *>(handle->config()))
{
if (Cpu::threads() > 1 && handle->affinity() != -1L) {
Cpu::setAffinity(m_id, handle->affinity());
if (Cpu::threads() > 1 && m_thread->affinity() != -1L) {
Platform::setThreadAffinity(m_thread->affinity());
}
Platform::setThreadPriority(handle->config()->priority());
m_ctx = Mem::create(m_id);
}
Worker::~Worker()
{
Platform::setThreadPriority(m_thread->priority());
}

View file

@ -30,6 +30,7 @@
#include "interfaces/IWorker.h"
#include "Mem.h"
struct cryptonight_ctx;
@ -45,8 +46,8 @@ class Worker : public IWorker
{
public:
Worker(Handle *handle);
~Worker();
inline const MemInfo &memory() const { return m_memory; }
inline size_t id() const override { return m_id; }
inline uint64_t hashCount() const override { return m_hashCount.load(std::memory_order_relaxed); }
inline uint64_t timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); }
@ -54,10 +55,10 @@ public:
protected:
void storeStats();
cryptonight_ctx *m_ctx;
size_t m_id;
size_t m_totalThreads;
size_t m_totalWays;
const size_t m_id;
const size_t m_totalWays;
const uint32_t m_offset;
MemInfo m_memory;
std::atomic<uint64_t> m_hashCount;
std::atomic<uint64_t> m_timestamp;
uint64_t m_count;

View file

@ -28,23 +28,24 @@
#include "api/Api.h"
#include "core/Config.h"
#include "core/Controller.h"
#include "crypto/CryptoNight_constants.h"
#include "interfaces/IJobResultListener.h"
#include "interfaces/IThread.h"
#include "log/Log.h"
#include "Mem.h"
#include "workers/DoubleWorker.h"
#include "rapidjson/document.h"
#include "workers/Handle.h"
#include "workers/Hashrate.h"
#include "workers/SingleWorker.h"
#include "workers/MultiWorker.h"
#include "workers/Workers.h"
#include "log/Log.h"
bool Workers::m_active = false;
bool Workers::m_enabled = true;
Hashrate *Workers::m_hashrate = nullptr;
IJobResultListener *Workers::m_listener = nullptr;
Job Workers::m_job;
Workers::LaunchStatus Workers::m_status;
std::atomic<int> Workers::m_paused;
std::atomic<uint64_t> Workers::m_sequence;
std::list<JobResult> Workers::m_queue;
@ -66,6 +67,26 @@ Job Workers::job()
}
size_t Workers::hugePages()
{
uv_mutex_lock(&m_mutex);
const size_t hugePages = m_status.hugePages;
uv_mutex_unlock(&m_mutex);
return hugePages;
}
size_t Workers::threads()
{
uv_mutex_lock(&m_mutex);
const size_t threads = m_status.threads;
uv_mutex_unlock(&m_mutex);
return threads;
}
void Workers::printHashrate(bool detail)
{
m_hashrate->print();
@ -111,10 +132,12 @@ void Workers::setJob(const Job &job, bool donate)
void Workers::start(xmrig::Controller *controller)
{
const std::vector<xmrig::IThread *> &threads = controller->config()->threads();
m_status.algo = controller->config()->algorithm();
m_status.colors = controller->config()->isHugePages();
m_status.threads = threads.size();
size_t totalWays = 0;
for (const xmrig::IThread *thread : threads) {
totalWays += thread->multiway();
m_status.ways += thread->multiway();
}
m_hashrate = new Hashrate(threads.size(), controller);
@ -129,8 +152,12 @@ void Workers::start(xmrig::Controller *controller)
uv_timer_init(uv_default_loop(), &m_timer);
uv_timer_start(&m_timer, Workers::onTick, 500, 500);
uint32_t offset = 0;
for (xmrig::IThread *thread : threads) {
Handle *handle = new Handle(thread, threads.size(), totalWays, controller->config()->affinity());
Handle *handle = new Handle(thread, offset, m_status.ways);
offset += thread->multiway();
m_workers.push_back(handle);
handle->start(Workers::onReady);
}
@ -162,23 +189,66 @@ void Workers::submit(const JobResult &result)
}
#ifndef XMRIG_NO_API
void Workers::threadsSummary(rapidjson::Document &doc)
{
uv_mutex_lock(&m_mutex);
const uint64_t pages[2] = { m_status.hugePages, m_status.pages };
const uint64_t memory = m_status.ways * xmrig::cn_select_memory(m_status.algo);
uv_mutex_unlock(&m_mutex);
auto &allocator = doc.GetAllocator();
rapidjson::Value hugepages(rapidjson::kArrayType);
hugepages.PushBack(pages[0], allocator);
hugepages.PushBack(pages[1], allocator);
doc.AddMember("hugepages", hugepages, allocator);
doc.AddMember("memory", memory, allocator);
}
#endif
void Workers::onReady(void *arg)
{
auto handle = static_cast<Handle*>(arg);
if (Mem::isDoubleHash()) {
handle->setWorker(new DoubleWorker(handle));
}
else {
handle->setWorker(new SingleWorker(handle));
IWorker *worker = nullptr;
switch (handle->config()->multiway()) {
case 1:
worker = new MultiWorker<1>(handle);
break;
case 2:
worker = new MultiWorker<2>(handle);
break;
case 3:
worker = new MultiWorker<3>(handle);
break;
case 4:
worker = new MultiWorker<4>(handle);
break;
case 5:
worker = new MultiWorker<5>(handle);
break;
default:
break;
}
const bool rc = handle->worker()->start();
handle->setWorker(worker);
if (!rc) {
uv_mutex_lock(&m_mutex);
if (!worker->selfTest()) {
LOG_ERR("thread %zu error: \"hash self-test failed\".", handle->worker()->id());
uv_mutex_unlock(&m_mutex);
return;
}
start(worker);
}
@ -214,8 +284,35 @@ void Workers::onTick(uv_timer_t *handle)
if ((m_ticks++ & 0xF) == 0) {
m_hashrate->updateHighest();
}
# ifndef XMRIG_NO_API
Api::tick(m_hashrate);
# endif
}
void Workers::start(IWorker *worker)
{
const Worker *w = static_cast<const Worker *>(worker);
uv_mutex_lock(&m_mutex);
m_status.started++;
m_status.pages += w->memory().pages;
m_status.hugePages += w->memory().hugePages;
if (m_status.started == m_status.threads) {
const double percent = (double) m_status.hugePages / m_status.pages * 100.0;
const size_t memory = m_status.ways * xmrig::cn_select_memory(m_status.algo) / 1048576;
if (m_status.colors) {
LOG_INFO("\x1B[01;32mREADY (CPU)\x1B[0m threads \x1B[01;36m%zu(%zu)\x1B[0m huge pages %s%zu/%zu %1.0f%%\x1B[0m memory \x1B[01;36m%zu.0 MB",
m_status.threads, m_status.ways,
(m_status.hugePages == m_status.pages ? "\x1B[01;32m" : (m_status.hugePages == 0 ? "\x1B[01;31m" : "\x1B[01;33m")),
m_status.hugePages, m_status.pages, percent, memory);
}
else {
LOG_INFO("READY (CPU) threads %zu(%zu) huge pages %zu/%zu %f%% memory %zu.0 MB",
m_status.threads, m_status.ways, m_status.hugePages, m_status.pages, percent, memory);
}
}
uv_mutex_unlock(&m_mutex);
worker->start();
}

View file

@ -32,11 +32,13 @@
#include "net/Job.h"
#include "net/JobResult.h"
#include "rapidjson/fwd.h"
class Handle;
class Hashrate;
class IJobResultListener;
class IWorker;
namespace xmrig {
@ -48,6 +50,8 @@ class Workers
{
public:
static Job job();
static size_t hugePages();
static size_t threads();
static void printHashrate(bool detail);
static void setEnabled(bool enabled);
static void setJob(const Job &job, bool donate);
@ -58,20 +62,49 @@ public:
static inline bool isEnabled() { return m_enabled; }
static inline bool isOutdated(uint64_t sequence) { return m_sequence.load(std::memory_order_relaxed) != sequence; }
static inline bool isPaused() { return m_paused.load(std::memory_order_relaxed) == 1; }
static inline Hashrate *hashrate() { return m_hashrate; }
static inline uint64_t sequence() { return m_sequence.load(std::memory_order_relaxed); }
static inline void pause() { m_active = false; m_paused = 1; m_sequence++; }
static inline void setListener(IJobResultListener *listener) { m_listener = listener; }
# ifndef XMRIG_NO_API
static void threadsSummary(rapidjson::Document &doc);
# endif
private:
static void onReady(void *arg);
static void onResult(uv_async_t *handle);
static void onTick(uv_timer_t *handle);
static void start(IWorker *worker);
class LaunchStatus
{
public:
inline LaunchStatus() :
colors(true),
hugePages(0),
pages(0),
started(0),
threads(0),
ways(0),
algo(xmrig::CRYPTONIGHT)
{}
bool colors;
size_t hugePages;
size_t pages;
size_t started;
size_t threads;
size_t ways;
xmrig::Algo algo;
};
static bool m_active;
static bool m_enabled;
static Hashrate *m_hashrate;
static IJobResultListener *m_listener;
static Job m_job;
static LaunchStatus m_status;
static std::atomic<int> m_paused;
static std::atomic<uint64_t> m_sequence;
static std::list<JobResult> m_queue;