Merge branch 'dev'

This commit is contained in:
XMRig 2017-08-20 10:24:49 +03:00
commit f041571674
49 changed files with 747 additions and 168 deletions

View file

@ -1,3 +1,13 @@
# v2.3.0
- Added `--cpu-priority` option (0 idle, 2 normal to 5 highest).
- Added `--user-agent` option, to set custom user-agent string for pool. For example `cpuminer-multi/0.1`.
- Added `--no-huge-pages` option, to disable huge pages support.
- [#62](https://github.com/xmrig/xmrig/issues/62) Don't send the login to the dev pool.
- Force reconnect if pool block miner IP address. helps switch to backup pool.
- Fixed: failed open default config file if path contains non English characters.
- Fixed: error occurred if try use unavailable stdin or stdout, regression since version 2.2.0.
- Fixed: message about huge pages support successfully enabled on Windows was not shown in release builds.
# v2.2.1 # v2.2.1
- Fixed [terminal issues](https://github.com/xmrig/xmrig-proxy/issues/2#issuecomment-319914085) after exit on Linux and OS X. - Fixed [terminal issues](https://github.com/xmrig/xmrig-proxy/issues/2#issuecomment-319914085) after exit on Linux and OS X.

View file

@ -28,12 +28,13 @@ set(HEADERS
src/net/Job.h src/net/Job.h
src/net/JobResult.h src/net/JobResult.h
src/net/Network.h src/net/Network.h
src/net/SubmitResult.h
src/net/Url.h
src/net/strategies/DonateStrategy.h src/net/strategies/DonateStrategy.h
src/net/strategies/FailoverStrategy.h src/net/strategies/FailoverStrategy.h
src/net/strategies/SinglePoolStrategy.h src/net/strategies/SinglePoolStrategy.h
src/net/SubmitResult.h
src/net/Url.h
src/Options.h src/Options.h
src/Platform.h
src/Summary.h src/Summary.h
src/version.h src/version.h
src/workers/DoubleWorker.h src/workers/DoubleWorker.h
@ -73,6 +74,7 @@ set(SOURCES
src/net/strategies/SinglePoolStrategy.cpp src/net/strategies/SinglePoolStrategy.cpp
src/net/Url.cpp src/net/Url.cpp
src/Options.cpp src/Options.cpp
src/Platform.cpp
src/Summary.cpp src/Summary.cpp
src/workers/DoubleWorker.cpp src/workers/DoubleWorker.cpp
src/workers/Handle.cpp src/workers/Handle.cpp
@ -100,7 +102,7 @@ if (WIN32)
src/App_win.cpp src/App_win.cpp
src/Cpu_win.cpp src/Cpu_win.cpp
src/Mem_win.cpp src/Mem_win.cpp
src/net/Network_win.cpp src/Platform_win.cpp
) )
add_definitions(/DWIN32) add_definitions(/DWIN32)
@ -110,14 +112,14 @@ elseif (APPLE)
src/App_unix.cpp src/App_unix.cpp
src/Cpu_mac.cpp src/Cpu_mac.cpp
src/Mem_unix.cpp src/Mem_unix.cpp
src/net/Network_mac.cpp src/Platform_mac.cpp
) )
else() else()
set(SOURCES_OS set(SOURCES_OS
src/App_unix.cpp src/App_unix.cpp
src/Cpu_unix.cpp src/Cpu_unix.cpp
src/Mem_unix.cpp src/Mem_unix.cpp
src/net/Network_unix.cpp src/Platform_unix.cpp
) )
set(EXTRA_LIBS pthread) set(EXTRA_LIBS pthread)
@ -159,6 +161,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
add_definitions(/D_CRT_NONSTDC_NO_WARNINGS)
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)

View file

@ -2,7 +2,9 @@
XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support. XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support.
Originally based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code, since version 1.0.0 complete rewritten from scratch on C++. Originally based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code, since version 1.0.0 complete rewritten from scratch on C++.
<img src="https://i.imgur.com/OXoB10D.png" width="628" > * This is the CPU-mining version, there is also a [NVIDIA GPU version](https://github.com/xmrig/xmrig-nvidia).
<img src="http://i.imgur.com/OKZRVDh.png" width="619" >
#### Table of contents #### Table of contents
* [Features](#features) * [Features](#features)
@ -30,17 +32,17 @@ Originally based on cpuminer-multi with heavy optimizations/rewrites and removin
## Download ## Download
* Binary releases: https://github.com/xmrig/xmrig/releases * Binary releases: https://github.com/xmrig/xmrig/releases
* Git tree: https://github.com/xmrig/xmrig.git * Git tree: https://github.com/xmrig/xmrig.git
* Clone with `git clone https://github.com/xmrig/xmrig.git` * Clone with `git clone https://github.com/xmrig/xmrig.git` :hammer: [Build instructions](https://github.com/xmrig/xmrig/wiki/Build).
## Usage ## Usage
### Basic example ### Basic example
``` ```
xmrig.exe -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET -p x -k xmrig.exe -o pool.minemonero.pro:5555 -u YOUR_WALLET -p x -k
``` ```
### Failover ### Failover
``` ```
xmrig.exe -o pool.supportxmr.com:5555 -u YOUR_WALLET1 -k -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET2 -p x -k xmrig.exe -o pool.minemonero.pro:5555 -u YOUR_WALLET1 -p x -k -o pool.supportxmr.com:5555 -u YOUR_WALLET2 -p x -k
``` ```
For failover you can add multiple pools, maximum count not limited. For failover you can add multiple pools, maximum count not limited.
@ -56,19 +58,25 @@ For failover you can add multiple pools, maximum count not limited.
-k, --keepalive send keepalived for prevent timeout (need pool support) -k, --keepalive send keepalived for prevent timeout (need pool support)
-r, --retries=N number of times to retry before switch to backup server (default: 5) -r, --retries=N number of times to retry before switch to backup server (default: 5)
-R, --retry-pause=N time to pause between retries (default: 5) -R, --retry-pause=N time to pause between retries (default: 5)
--cpu-affinity set process affinity to cpu core(s), mask 0x3 for cores 0 and 1 --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)
--no-huge-pages disable huge pages support
--no-color disable colored output --no-color disable colored output
--donate-level=N donate level, default 5% (5 minutes in 100 minutes) --donate-level=N donate level, default 5% (5 minutes in 100 minutes)
--user-agent set custom user-agent string for pool
-B, --background run the miner in the background -B, --background run the miner in the background
-c, --config=FILE load a JSON-format configuration file -c, --config=FILE load a JSON-format configuration file
--max-cpu-usage=N maximum cpu usage for automatic threads mode (default 75) -l, --log-file=FILE log all output to a file
--safe safe adjust threads and av settings for current cpu --max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)
--safe safe adjust threads and av settings for current CPU
--nicehash enable nicehash support --nicehash enable nicehash support
--print-time=N print hashrate report every N seconds --print-time=N print hashrate report every N seconds
-h, --help display this help and exit -h, --help display this help and exit
-V, --version output version information and exit -V, --version output version information and exit
``` ```
Also you can use configuration via config file, default **config.json**. You can load multiple config files and combine it with command line options.
## Algorithm variations ## Algorithm variations
Since version 0.8.0. Since version 0.8.0.
* `--av=1` For CPUs with hardware AES. * `--av=1` For CPUs with hardware AES.
@ -88,8 +96,8 @@ Since version 0.8.0.
### CPU mining performance ### CPU mining performance
* **i7-6700** - 290+ H/s (4 threads, cpu affinity 0xAA) * **Intel i7-7700** - 307 H/s (4 threads)
* **Dual E5620** - 377 H/s (12 threads, cpu affinity 0xEEEE) * **AMD Ryzen 7 1700X** - 560 H/s (8 threads)
Please note performance is highly dependent on system load. The numbers above are obtained on an idle system. Tasks heavily using a processor cache, such as video playback, can greatly degrade hashrate. Optimal number of threads depends on the size of the L3 cache of a processor, 1 thread requires 2 MB of cache. Please note performance is highly dependent on system load. The numbers above are obtained on an idle system. Tasks heavily using a processor cache, such as video playback, can greatly degrade hashrate. Optimal number of threads depends on the size of the L3 cache of a processor, 1 thread requires 2 MB of cache.

View file

@ -56,7 +56,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma warning(disable:4996); #pragma warning(disable:4996)
#define __GETOPT_H__ #define __GETOPT_H__

View file

@ -5,6 +5,10 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#ifdef _MSC_VER
#pragma warning(disable:4090)
#endif
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
@ -15,8 +19,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> #if defined(HAVE_UNISTD_H)
# include <unistd.h>
#elif defined(_MSC_VER)
# include <io.h>
#endif #endif
#include "jansson.h" #include "jansson.h"
@ -62,10 +69,13 @@ static int dump_to_file(const char *buffer, size_t size, void *data)
static int dump_to_fd(const char *buffer, size_t size, void *data) static int dump_to_fd(const char *buffer, size_t size, void *data)
{ {
int *dest = (int *)data; int *dest = (int *)data;
#ifdef HAVE_UNISTD_H # if defined(HAVE_UNISTD_H)
if(write(*dest, buffer, size) == (ssize_t)size) if(write(*dest, buffer, size) == (ssize_t)size)
return 0; return 0;
#endif # elif (defined(_MSC_VER))
if (write(*dest, buffer, (unsigned int) size) == (int) size)
return 0;
# endif
return -1; return -1;
} }

View file

@ -5,6 +5,10 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#ifdef _MSC_VER
#pragma warning(disable:4334)
#endif
#if HAVE_CONFIG_H #if HAVE_CONFIG_H
#include <jansson_private_config.h> #include <jansson_private_config.h>
#endif #endif

View file

@ -17,8 +17,13 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> #if defined(HAVE_UNISTD_H)
# include <unistd.h>
#elif defined(_MSC_VER)
# include <io.h>
# define HAVE_UNISTD_H
# define STDIN_FILENO 0
#endif #endif
#include "jansson.h" #include "jansson.h"
@ -1034,8 +1039,8 @@ json_t *json_loadf(FILE *input, size_t flags, json_error_t *error)
static int fd_get_func(int *fd) static int fd_get_func(int *fd)
{ {
uint8_t c;
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
uint8_t c;
if (read(*fd, &c, 1) == 1) if (read(*fd, &c, 1) == 1)
return c; return c;
#endif #endif

View file

@ -36,6 +36,7 @@
#include "Mem.h" #include "Mem.h"
#include "net/Network.h" #include "net/Network.h"
#include "Options.h" #include "Options.h"
#include "Platform.h"
#include "Summary.h" #include "Summary.h"
#include "version.h" #include "version.h"
#include "workers/Workers.h" #include "workers/Workers.h"
@ -80,6 +81,9 @@ App::App(int argc, char **argv) :
} }
# endif # endif
Platform::init(m_options->userAgent());
Platform::setProcessPriority(m_options->priority());
m_network = new Network(m_options); m_network = new Network(m_options);
uv_signal_init(uv_default_loop(), &m_signal); uv_signal_init(uv_default_loop(), &m_signal);
@ -109,10 +113,10 @@ int App::exec()
return 1; return 1;
} }
Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash()); Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash(), m_options->hugePages());
Summary::print(); Summary::print();
Workers::start(m_options->affinity()); Workers::start(m_options->affinity(), m_options->priority());
m_network->connect(); m_network->connect();
@ -120,10 +124,11 @@ int App::exec()
uv_loop_close(uv_default_loop()); uv_loop_close(uv_default_loop());
uv_tty_reset_mode(); uv_tty_reset_mode();
free(m_network); delete m_network;
free(m_options);
Options::release();
Mem::release(); Mem::release();
Platform::release();
return r; return r;
} }

View file

@ -68,7 +68,7 @@ int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
} }
if (((float) count / m_totalThreads * 100) > maxCpuUsage) { if (((float) count / m_totalThreads * 100) > maxCpuUsage) {
count = ceil((float) m_totalThreads * (maxCpuUsage / 100.0)); count = (int) ceil((float) m_totalThreads * (maxCpuUsage / 100.0));
} }
return count < 1 ? 1 : count; return count < 1 ? 1 : count;

View file

@ -41,8 +41,8 @@ public:
static void init(); static void init();
static void setAffinity(int id, uint64_t mask); static void setAffinity(int id, uint64_t mask);
static inline bool hasAES() { return m_flags & AES; } static inline bool hasAES() { return (m_flags & AES) != 0; }
static inline bool isX64() { return m_flags & X86_64; } static inline bool isX64() { return (m_flags & X86_64) != 0; }
static inline const char *brand() { return m_brand; } static inline const char *brand() { return m_brand; }
static inline int cores() { return m_totalCores; } static inline int cores() { return m_totalCores; }
static inline int l2() { return m_l2_cache; } static inline int l2() { return m_l2_cache; }

View file

@ -44,14 +44,14 @@ public:
Lock = 4 Lock = 4
}; };
static bool allocate(int algo, int threads, bool doubleHash); static bool allocate(int algo, int threads, bool doubleHash, bool enabled);
static cryptonight_ctx *create(int threadId); static cryptonight_ctx *create(int threadId);
static void *calloc(size_t num, size_t size); static void *calloc(size_t num, size_t size);
static void release(); static void release();
static inline bool isDoubleHash() { return m_doubleHash; } static inline bool isDoubleHash() { return m_doubleHash; }
static inline bool isHugepagesAvailable() { return m_flags & HugepagesAvailable; } static inline bool isHugepagesAvailable() { return (m_flags & HugepagesAvailable) != 0; }
static inline bool isHugepagesEnabled() { return m_flags & HugepagesEnabled; } static inline bool isHugepagesEnabled() { return (m_flags & HugepagesEnabled) != 0; }
static inline int flags() { return m_flags; } static inline int flags() { return m_flags; }
static inline int threads() { return m_threads; } static inline int threads() { return m_threads; }

View file

@ -33,7 +33,7 @@
#include "Options.h" #include "Options.h"
bool Mem::allocate(int algo, int threads, bool doubleHash) bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
{ {
m_algo = algo; m_algo = algo;
m_threads = threads; m_threads = threads;
@ -42,6 +42,11 @@ bool Mem::allocate(int algo, int threads, bool doubleHash)
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1); const size_t size = MEMORY * (threads * ratio + 1);
if (!enabled) {
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true;
}
m_flags |= HugepagesAvailable; m_flags |= HugepagesAvailable;
# if defined(__APPLE__) # if defined(__APPLE__)

View file

@ -85,9 +85,8 @@ static BOOL SetLockPagesPrivilege() {
static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) { static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) {
LSA_UNICODE_STRING lsaString; LSA_UNICODE_STRING lsaString;
DWORD dwLen = 0;
dwLen = wcslen(string); DWORD dwLen = (DWORD) wcslen(string);
lsaString.Buffer = (LPWSTR) string; lsaString.Buffer = (LPWSTR) string;
lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR)); lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR));
lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR)); lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR));
@ -124,7 +123,7 @@ static BOOL ObtainLockPagesPrivilege() {
LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME)); LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME));
if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) { if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) {
LOG_DEBUG("Huge pages support was successfully enabled, but reboot required to use it"); LOG_NOTICE("Huge pages support was successfully enabled, but reboot required to use it");
result = TRUE; result = TRUE;
} }
@ -145,7 +144,7 @@ static BOOL TrySetLockPagesPrivilege() {
} }
bool Mem::allocate(int algo, int threads, bool doubleHash) bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
{ {
m_algo = algo; m_algo = algo;
m_threads = threads; m_threads = threads;
@ -154,6 +153,11 @@ bool Mem::allocate(int algo, int threads, bool doubleHash)
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1); const size_t size = MEMORY * (threads * ratio + 1);
if (!enabled) {
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true;
}
if (TrySetLockPagesPrivilege()) { if (TrySetLockPagesPrivilege()) {
m_flags |= HugepagesAvailable; m_flags |= HugepagesAvailable;
} }

View file

@ -38,6 +38,7 @@
#include "donate.h" #include "donate.h"
#include "net/Url.h" #include "net/Url.h"
#include "Options.h" #include "Options.h"
#include "Platform.h"
#include "version.h" #include "version.h"
@ -63,8 +64,11 @@ Options:\n\
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\ -r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
-R, --retry-pause=N time to pause between retries (default: 5)\n\ -R, --retry-pause=N time to pause between retries (default: 5)\n\
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\ --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
--no-huge-pages disable huge pages support\n\
--no-color disable colored output\n\ --no-color disable colored output\n\
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
--user-agent set custom user-agent string for pool\n\
-B, --background run the miner in the background\n\ -B, --background run the miner in the background\n\
-c, --config=FILE load a JSON-format configuration file\n\ -c, --config=FILE load a JSON-format configuration file\n\
-l, --log-file=FILE log all output to a file\n" -l, --log-file=FILE log all output to a file\n"
@ -91,6 +95,7 @@ static struct option const options[] = {
{ "background", 0, nullptr, 'B' }, { "background", 0, nullptr, 'B' },
{ "config", 1, nullptr, 'c' }, { "config", 1, nullptr, 'c' },
{ "cpu-affinity", 1, nullptr, 1020 }, { "cpu-affinity", 1, nullptr, 1020 },
{ "cpu-priority", 1, nullptr, 1021 },
{ "donate-level", 1, nullptr, 1003 }, { "donate-level", 1, nullptr, 1003 },
{ "help", 0, nullptr, 'h' }, { "help", 0, nullptr, 'h' },
{ "keepalive", 0, nullptr ,'k' }, { "keepalive", 0, nullptr ,'k' },
@ -98,6 +103,7 @@ static struct option const options[] = {
{ "max-cpu-usage", 1, nullptr, 1004 }, { "max-cpu-usage", 1, nullptr, 1004 },
{ "nicehash", 0, nullptr, 1006 }, { "nicehash", 0, nullptr, 1006 },
{ "no-color", 0, nullptr, 1002 }, { "no-color", 0, nullptr, 1002 },
{ "no-huge-pages", 0, nullptr, 1009 },
{ "pass", 1, nullptr, 'p' }, { "pass", 1, nullptr, 'p' },
{ "print-time", 1, nullptr, 1007 }, { "print-time", 1, nullptr, 1007 },
{ "retries", 1, nullptr, 'r' }, { "retries", 1, nullptr, 'r' },
@ -107,6 +113,7 @@ static struct option const options[] = {
{ "threads", 1, nullptr, 't' }, { "threads", 1, nullptr, 't' },
{ "url", 1, nullptr, 'o' }, { "url", 1, nullptr, 'o' },
{ "user", 1, nullptr, 'u' }, { "user", 1, nullptr, 'u' },
{ "user-agent", 1, nullptr, 1008 },
{ "userpass", 1, nullptr, 'O' }, { "userpass", 1, nullptr, 'O' },
{ "version", 0, nullptr, 'V' }, { "version", 0, nullptr, 'V' },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
@ -117,8 +124,11 @@ static struct option const config_options[] = {
{ "algo", 1, nullptr, 'a' }, { "algo", 1, nullptr, 'a' },
{ "av", 1, nullptr, 'v' }, { "av", 1, nullptr, 'v' },
{ "background", 0, nullptr, 'B' }, { "background", 0, nullptr, 'B' },
{ "colors", 0, nullptr, 2000 },
{ "cpu-affinity", 1, nullptr, 1020 }, { "cpu-affinity", 1, nullptr, 1020 },
{ "cpu-priority", 1, nullptr, 1021 },
{ "donate-level", 1, nullptr, 1003 }, { "donate-level", 1, nullptr, 1003 },
{ "huge-pages", 0, nullptr, 1009 },
{ "log-file", 1, nullptr, 'l' }, { "log-file", 1, nullptr, 'l' },
{ "max-cpu-usage", 1, nullptr, 1004 }, { "max-cpu-usage", 1, nullptr, 1004 },
{ "print-time", 1, nullptr, 1007 }, { "print-time", 1, nullptr, 1007 },
@ -127,7 +137,7 @@ static struct option const config_options[] = {
{ "safe", 0, nullptr, 1005 }, { "safe", 0, nullptr, 1005 },
{ "syslog", 0, nullptr, 'S' }, { "syslog", 0, nullptr, 'S' },
{ "threads", 1, nullptr, 't' }, { "threads", 1, nullptr, 't' },
{ "colors", 0, nullptr, 2000 }, { "user-agent", 1, nullptr, 1008 },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
@ -151,34 +161,6 @@ static const char *algo_names[] = {
}; };
static char *defaultConfigName()
{
size_t size = 512;
char *buf = new char[size];
if (uv_exepath(buf, &size) < 0) {
delete [] buf;
return nullptr;
}
if (size < 500) {
# ifdef WIN32
char *p = strrchr(buf, '\\');
# else
char *p = strrchr(buf, '/');
# endif
if (p) {
strcpy(p + 1, "config.json");
return buf;
}
}
delete [] buf;
return nullptr;
}
Options *Options::parse(int argc, char **argv) Options *Options::parse(int argc, char **argv)
{ {
Options *options = new Options(argc, argv); Options *options = new Options(argc, argv);
@ -202,15 +184,18 @@ Options::Options(int argc, char **argv) :
m_background(false), m_background(false),
m_colors(true), m_colors(true),
m_doubleHash(false), m_doubleHash(false),
m_hugePages(true),
m_ready(false), m_ready(false),
m_safe(false), m_safe(false),
m_syslog(false), m_syslog(false),
m_logFile(nullptr), m_logFile(nullptr),
m_userAgent(nullptr),
m_algo(0), m_algo(0),
m_algoVariant(0), m_algoVariant(0),
m_donateLevel(kDonateLevel), m_donateLevel(kDonateLevel),
m_maxCpuUsage(75), m_maxCpuUsage(75),
m_printTime(60), m_printTime(60),
m_priority(-1),
m_retries(5), m_retries(5),
m_retryPause(5), m_retryPause(5),
m_threads(0), m_threads(0),
@ -237,9 +222,7 @@ Options::Options(int argc, char **argv) :
} }
if (!m_pools[0]->isValid()) { if (!m_pools[0]->isValid()) {
char *fileName = defaultConfigName(); parseConfig(Platform::defaultConfigName());
parseConfig(fileName);
delete [] fileName;
} }
if (!m_pools[0]->isValid()) { if (!m_pools[0]->isValid()) {
@ -326,16 +309,20 @@ bool Options::parseArg(int key, const char *arg)
case 1003: /* --donate-level */ case 1003: /* --donate-level */
case 1004: /* --max-cpu-usage */ case 1004: /* --max-cpu-usage */
case 1007: /* --print-time */ case 1007: /* --print-time */
case 1021: /* --cpu-priority */
return parseArg(key, strtol(arg, nullptr, 10)); return parseArg(key, strtol(arg, nullptr, 10));
case 'B': /* --background */ case 'B': /* --background */
case 'k': /* --keepalive */ case 'k': /* --keepalive */
case 'S': /* --syslog */ case 'S': /* --syslog */
case 1002: /* --no-color */
case 1005: /* --safe */ case 1005: /* --safe */
case 1006: /* --nicehash */ case 1006: /* --nicehash */
return parseBoolean(key, true); return parseBoolean(key, true);
case 1002: /* --no-color */
case 1009: /* --no-huge-pages */
return parseBoolean(key, false);
case 'V': /* --version */ case 'V': /* --version */
showVersion(); showVersion();
return false; return false;
@ -353,6 +340,11 @@ bool Options::parseArg(int key, const char *arg)
return parseArg(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); return parseArg(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10));
} }
case 1008: /* --user-agent */
free(m_userAgent);
m_userAgent = strdup(arg);
break;
default: default:
showUsage(1); showUsage(1);
return false; return false;
@ -371,7 +363,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false; return false;
} }
m_retries = arg; m_retries = (int) arg;
break; break;
case 'R': /* --retry-pause */ case 'R': /* --retry-pause */
@ -380,7 +372,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false; return false;
} }
m_retryPause = arg; m_retryPause = (int) arg;
break; break;
case 't': /* --threads */ case 't': /* --threads */
@ -389,7 +381,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false; return false;
} }
m_threads = arg; m_threads = (int) arg;
break; break;
case 'v': /* --av */ case 'v': /* --av */
@ -398,7 +390,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false; return false;
} }
m_algoVariant = arg; m_algoVariant = (int) arg;
break; break;
case 1003: /* --donate-level */ case 1003: /* --donate-level */
@ -407,7 +399,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false; return false;
} }
m_donateLevel = arg; m_donateLevel = (int) arg;
break; break;
case 1004: /* --max-cpu-usage */ case 1004: /* --max-cpu-usage */
@ -416,7 +408,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false; return false;
} }
m_maxCpuUsage = arg; m_maxCpuUsage = (int) arg;
break; break;
case 1007: /* --print-time */ case 1007: /* --print-time */
@ -425,7 +417,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false; return false;
} }
m_printTime = arg; m_printTime = (int) arg;
break; break;
case 1020: /* --cpu-affinity */ case 1020: /* --cpu-affinity */
@ -434,6 +426,12 @@ bool Options::parseArg(int key, uint64_t arg)
} }
break; break;
case 1021: /* --cpu-priority */
if (arg <= 5) {
m_priority = (int) arg;
}
break;
default: default:
break; break;
} }
@ -471,6 +469,10 @@ bool Options::parseBoolean(int key, bool enable)
m_pools.back()->setNicehash(enable); m_pools.back()->setNicehash(enable);
break; break;
case 1009: /* --no-huge-pages */
m_hugePages = enable;
break;
case 2000: /* colors */ case 2000: /* colors */
m_colors = enable; m_colors = enable;
break; break;
@ -497,8 +499,20 @@ Url *Options::parseUrl(const char *arg) const
void Options::parseConfig(const char *fileName) void Options::parseConfig(const char *fileName)
{ {
uv_fs_t req;
const int fd = uv_fs_open(uv_default_loop(), &req, fileName, O_RDONLY, 0644, nullptr);
if (fd < 0) {
fprintf(stderr, "unable to open %s: %s\n", fileName, uv_strerror(fd));
return;
}
uv_fs_req_cleanup(&req);
json_error_t err; json_error_t err;
json_t *config = json_load_file(fileName, 0, &err); json_t *config = json_loadfd(fd, 0, &err);
uv_fs_close(uv_default_loop(), &req, fd, nullptr);
uv_fs_req_cleanup(&req);
if (!json_is_object(config)) { if (!json_is_object(config)) {
if (config) { if (config) {
@ -609,7 +623,7 @@ bool Options::setAlgo(const char *algo)
{ {
for (size_t i = 0; i < ARRAY_SIZE(algo_names); i++) { for (size_t i = 0; i < ARRAY_SIZE(algo_names); i++) {
if (algo_names[i] && !strcmp(algo, algo_names[i])) { if (algo_names[i] && !strcmp(algo, algo_names[i])) {
m_algo = i; m_algo = (int) i;
break; break;
} }

View file

@ -57,18 +57,23 @@ public:
inline bool background() const { return m_background; } inline bool background() const { return m_background; }
inline bool colors() const { return m_colors; } inline bool colors() const { return m_colors; }
inline bool doubleHash() const { return m_doubleHash; } inline bool doubleHash() const { return m_doubleHash; }
inline bool hugePages() const { return m_hugePages; }
inline bool syslog() const { return m_syslog; } inline bool syslog() const { return m_syslog; }
inline const char *logFile() const { return m_logFile; } inline const char *logFile() const { return m_logFile; }
inline const char *userAgent() const { return m_userAgent; }
inline const std::vector<Url*> &pools() const { return m_pools; } inline const std::vector<Url*> &pools() const { return m_pools; }
inline int algo() const { return m_algo; } inline int algo() const { return m_algo; }
inline int algoVariant() const { return m_algoVariant; } inline int algoVariant() const { return m_algoVariant; }
inline int donateLevel() const { return m_donateLevel; } inline int donateLevel() const { return m_donateLevel; }
inline int printTime() const { return m_printTime; } inline int printTime() const { return m_printTime; }
inline int priority() const { return m_priority; }
inline int retries() const { return m_retries; } inline int retries() const { return m_retries; }
inline int retryPause() const { return m_retryPause; } inline int retryPause() const { return m_retryPause; }
inline int threads() const { return m_threads; } inline int threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; } inline int64_t affinity() const { return m_affinity; }
inline static void release() { delete m_self; }
const char *algoName() const; const char *algoName() const;
private: private:
@ -98,15 +103,18 @@ private:
bool m_background; bool m_background;
bool m_colors; bool m_colors;
bool m_doubleHash; bool m_doubleHash;
bool m_hugePages;
bool m_ready; bool m_ready;
bool m_safe; bool m_safe;
bool m_syslog; bool m_syslog;
char *m_logFile; char *m_logFile;
char *m_userAgent;
int m_algo; int m_algo;
int m_algoVariant; int m_algoVariant;
int m_donateLevel; int m_donateLevel;
int m_maxCpuUsage; int m_maxCpuUsage;
int m_printTime; int m_printTime;
int m_priority;
int m_retries; int m_retries;
int m_retryPause; int m_retryPause;
int m_threads; int m_threads;

View file

@ -22,29 +22,41 @@
*/ */
#include <stdlib.h> #include <string.h>
#include <uv.h>
#include "net/Network.h" #include "Platform.h"
#include "version.h"
char *Network::userAgent() char *Platform::m_defaultConfigName = nullptr;
char *Platform::m_userAgent = nullptr;
const char *Platform::defaultConfigName()
{ {
const size_t max = 128; size_t size = 520;
char *buf = static_cast<char*>(malloc(max)); if (m_defaultConfigName == nullptr) {
int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION); m_defaultConfigName = new char[size];
}
# if defined(__x86_64__) if (uv_exepath(m_defaultConfigName, &size) < 0) {
length += snprintf(buf + length, max - length, "x86_64) libuv/%s", uv_version_string()); return nullptr;
# else }
length += snprintf(buf + length, max - length, "i686) libuv/%s", uv_version_string());
# endif
# ifdef __GNUC__ if (size < 500) {
length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); # ifdef WIN32
# endif char *p = strrchr(m_defaultConfigName, '\\');
# else
char *p = strrchr(m_defaultConfigName, '/');
# endif
return buf; if (p) {
strcpy(p + 1, "config.json");
return m_defaultConfigName;
}
}
return nullptr;
} }

View file

@ -21,19 +21,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __PLATFORM_H__
#include <stdlib.h> #define __PLATFORM_H__
#include "net/Network.h"
#include "version.h"
char *Network::userAgent() class Platform
{ {
const size_t max = 128; public:
static const char *defaultConfigName();
static void init(const char *userAgent);
static void release();
static void setProcessPriority(int priority);
static void setThreadPriority(int priority);
char *buf = static_cast<char*>(malloc(max)); static inline const char *userAgent() { return m_userAgent; }
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__);
return buf; private:
} static char *m_defaultConfigName;
static char *m_userAgent;
};
#endif /* __PLATFORM_H__ */

108
src/Platform_mac.cpp Normal file
View file

@ -0,0 +1,108 @@
/* 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 2016-2017 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 <stdlib.h>
#include <sys/resource.h>
#include <uv.h>
#include "Platform.h"
#include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
static inline char *createUserAgent()
{
const size_t max = 160;
char *buf = new char[max];
# ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s CUDA/%d.%d clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), cudaVersion / 1000, cudaVersion % 100, __clang_major__, __clang_minor__, __clang_patchlevel__);
# else
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__);
# endif
return buf;
}
void Platform::init(const char *userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
}
void Platform::release()
{
delete [] m_userAgent;
}
void Platform::setProcessPriority(int priority)
{
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
return;
}
int prio = 19;
switch (priority)
{
case 1:
prio = 5;
break;
case 2:
prio = 0;
break;
case 3:
prio = -5;
break;
case 4:
prio = -10;
break;
case 5:
prio = -15;
break;
default:
break;
}
setpriority(PRIO_PROCESS, 0, prio);
}

127
src/Platform_unix.cpp Normal file
View file

@ -0,0 +1,127 @@
/* 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 2016-2017 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 <sched.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <uv.h>
#include "Platform.h"
#include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
static inline char *createUserAgent()
{
const size_t max = 160;
char *buf = new char[max];
int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION);
# if defined(__x86_64__)
length += snprintf(buf + length, max - length, "x86_64) libuv/%s", uv_version_string());
# else
length += snprintf(buf + length, max - length, "i686) libuv/%s", uv_version_string());
# endif
# ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100);
# endif
# ifdef __GNUC__
length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# endif
return buf;
}
void Platform::init(const char *userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
}
void Platform::release()
{
delete [] m_userAgent;
}
void Platform::setProcessPriority(int priority)
{
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
return;
}
int prio = 19;
switch (priority)
{
case 1:
prio = 5;
break;
case 2:
prio = 0;
break;
case 3:
prio = -5;
break;
case 4:
prio = -10;
break;
case 5:
prio = -15;
break;
default:
break;
}
setpriority(PRIO_PROCESS, 0, prio);
if (priority == 0) {
sched_param param;
param.sched_priority = 0;
if (sched_setscheduler(0, SCHED_IDLE, &param) != 0) {
sched_setscheduler(0, SCHED_BATCH, &param);
}
}
}

View file

@ -24,11 +24,16 @@
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#include <uv.h>
#include "net/Network.h" #include "Platform.h"
#include "version.h" #include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
static inline OSVERSIONINFOEX winOsVersion() static inline OSVERSIONINFOEX winOsVersion()
{ {
@ -48,12 +53,12 @@ static inline OSVERSIONINFOEX winOsVersion()
} }
char *Network::userAgent() static inline char *createUserAgent()
{ {
const auto osver = winOsVersion(); const auto osver = winOsVersion();
const size_t max = 128; const size_t max = 160;
char *buf = static_cast<char*>(malloc(max)); char *buf = new char[max];
int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion); int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion);
# if defined(__x86_64__) || defined(_M_AMD64) # if defined(__x86_64__) || defined(_M_AMD64)
@ -62,6 +67,11 @@ char *Network::userAgent()
length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string()); length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string());
# endif # endif
# ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100);
# endif
# ifdef __GNUC__ # ifdef __GNUC__
length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# elif _MSC_VER # elif _MSC_VER
@ -70,3 +80,91 @@ char *Network::userAgent()
return buf; return buf;
} }
void Platform::init(const char *userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
}
void Platform::release()
{
delete [] m_defaultConfigName;
delete [] m_userAgent;
}
void Platform::setProcessPriority(int priority)
{
if (priority == -1) {
return;
}
DWORD prio = IDLE_PRIORITY_CLASS;
switch (priority)
{
case 1:
prio = BELOW_NORMAL_PRIORITY_CLASS;
break;
case 2:
prio = NORMAL_PRIORITY_CLASS;
break;
case 3:
prio = ABOVE_NORMAL_PRIORITY_CLASS;
break;
case 4:
prio = HIGH_PRIORITY_CLASS;
break;
case 5:
prio = REALTIME_PRIORITY_CLASS;
default:
break;
}
SetPriorityClass(GetCurrentProcess(), prio);
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
return;
}
int prio = THREAD_PRIORITY_IDLE;
switch (priority)
{
case 1:
prio = THREAD_PRIORITY_BELOW_NORMAL;
break;
case 2:
prio = THREAD_PRIORITY_NORMAL;
break;
case 3:
prio = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case 4:
prio = THREAD_PRIORITY_HIGHEST;
break;
case 5:
prio = THREAD_PRIORITY_TIME_CRITICAL;
break;
default:
break;
}
SetThreadPriority(GetCurrentThread(), prio);
}

View file

@ -4,6 +4,7 @@
"background": false, "background": false,
"colors": true, "colors": true,
"cpu-affinity": null, "cpu-affinity": null,
"cpu-priority": null,
"donate-level": 5, "donate-level": 5,
"log-file": null, "log-file": null,
"max-cpu-usage": 75, "max-cpu-usage": 75,

View file

@ -311,7 +311,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES> template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx) inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx)
{ {
keccak(static_cast<const uint8_t*>(input), size, ctx->state0, 200); keccak(static_cast<const uint8_t*>(input), (int) size, ctx->state0, 200);
cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) ctx->state0, (__m128i*) ctx->memory); cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) ctx->state0, (__m128i*) ctx->memory);
@ -365,8 +365,8 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES> template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
{ {
keccak((const uint8_t *) input, size, ctx->state0, 200); keccak((const uint8_t *) input, (int) size, ctx->state0, 200);
keccak((const uint8_t *) input + size, size, ctx->state1, 200); keccak((const uint8_t *) input + size, (int) size, ctx->state1, 200);
const uint8_t* l0 = ctx->memory; const uint8_t* l0 = ctx->memory;
const uint8_t* l1 = ctx->memory + MEM; const uint8_t* l1 = ctx->memory + MEM;

View file

@ -148,7 +148,7 @@ void blake256_update(state *S, const uint8_t *data, uint64_t datalen) {
if (datalen > 0) { if (datalen > 0) {
memcpy((void *) (S->buf + left), (void *) data, datalen >> 3); memcpy((void *) (S->buf + left), (void *) data, datalen >> 3);
S->buflen = (left << 3) + datalen; S->buflen = (left << 3) + (int) datalen;
} else { } else {
S->buflen = 0; S->buflen = 0;
} }

View file

@ -41,6 +41,7 @@ public:
virtual void connect() = 0; virtual void connect() = 0;
virtual void resume() = 0; virtual void resume() = 0;
virtual void stop() = 0; virtual void stop() = 0;
virtual void tick(uint64_t now) = 0;
}; };

View file

@ -40,7 +40,10 @@
ConsoleLog::ConsoleLog(bool colors) : ConsoleLog::ConsoleLog(bool colors) :
m_colors(colors) m_colors(colors)
{ {
uv_tty_init(uv_default_loop(), &m_tty, 1, 0); if (uv_tty_init(uv_default_loop(), &m_tty, 1, 0) < 0) {
return;
}
uv_tty_set_mode(&m_tty, UV_TTY_MODE_NORMAL); uv_tty_set_mode(&m_tty, UV_TTY_MODE_NORMAL);
# ifdef WIN32 # ifdef WIN32
@ -58,6 +61,10 @@ ConsoleLog::ConsoleLog(bool colors) :
void ConsoleLog::message(int level, const char* fmt, va_list args) void ConsoleLog::message(int level, const char* fmt, va_list args)
{ {
if (!isWritable()) {
return;
}
time_t now = time(nullptr); time_t now = time(nullptr);
tm stime; tm stime;
@ -92,8 +99,7 @@ void ConsoleLog::message(int level, const char* fmt, va_list args)
} }
} }
const size_t len = 64 + strlen(fmt) + 2; char *buf = new char[64 + strlen(fmt) + 2];
char *buf = new char[len];
sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n", sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
stime.tm_year + 1900, stime.tm_year + 1900,
@ -113,8 +119,11 @@ void ConsoleLog::message(int level, const char* fmt, va_list args)
void ConsoleLog::text(const char* fmt, va_list args) void ConsoleLog::text(const char* fmt, va_list args)
{ {
const int len = 64 + strlen(fmt) + 2; if (!isWritable()) {
char *buf = new char[len]; return;
}
char *buf = new char[64 + strlen(fmt) + 2];
sprintf(buf, "%s%s\n", fmt, m_colors ? Log::kCL_N : ""); sprintf(buf, "%s%s\n", fmt, m_colors ? Log::kCL_N : "");
@ -122,6 +131,12 @@ void ConsoleLog::text(const char* fmt, va_list args)
} }
bool ConsoleLog::isWritable() const
{
return uv_is_writable(reinterpret_cast<const uv_stream_t*>(&m_tty)) == 1 && uv_guess_handle(1) == UV_TTY;
}
void ConsoleLog::print(char *fmt, va_list args) void ConsoleLog::print(char *fmt, va_list args)
{ {
vsnprintf(m_buf, sizeof(m_buf) - 1, fmt, args); vsnprintf(m_buf, sizeof(m_buf) - 1, fmt, args);

View file

@ -40,6 +40,7 @@ public:
void text(const char *fmt, va_list args) override; void text(const char *fmt, va_list args) override;
private: private:
bool isWritable() const;
void print(char *fmt, va_list args); void print(char *fmt, va_list args);
bool m_colors; bool m_colors;

View file

@ -88,7 +88,7 @@ void FileLog::onWrite(uv_fs_t *req)
void FileLog::write(char *data, size_t size) void FileLog::write(char *data, size_t size)
{ {
uv_buf_t buf = uv_buf_init(data, size); uv_buf_t buf = uv_buf_init(data, (unsigned int) size);
uv_fs_t *req = static_cast<uv_fs_t*>(malloc(sizeof(uv_fs_t))); uv_fs_t *req = static_cast<uv_fs_t*>(malloc(sizeof(uv_fs_t)));
req->data = buf.base; req->data = buf.base;

View file

@ -77,10 +77,14 @@ private:
#ifdef APP_DEBUG #ifdef APP_DEBUG
# define LOG_DEBUG(x, ...) Log::i()->message(Log::DEBUG, x, ##__VA_ARGS__) # define LOG_DEBUG(x, ...) Log::i()->message(Log::DEBUG, x, ##__VA_ARGS__)
#else
# define LOG_DEBUG(x, ...)
#endif
#if defined(APP_DEBUG) || defined(APP_DEVEL)
# define LOG_DEBUG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__) # define LOG_DEBUG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__)
# define LOG_DEBUG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__) # define LOG_DEBUG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__)
#else #else
# define LOG_DEBUG(x, ...)
# define LOG_DEBUG_ERR(x, ...) # define LOG_DEBUG_ERR(x, ...)
# define LOG_DEBUG_WARN(x, ...) # define LOG_DEBUG_WARN(x, ...)
#endif #endif

View file

@ -56,13 +56,14 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_failures(0), m_failures(0),
m_recvBufPos(0), m_recvBufPos(0),
m_state(UnconnectedState), m_state(UnconnectedState),
m_expire(0),
m_stream(nullptr), m_stream(nullptr),
m_socket(nullptr) m_socket(nullptr)
{ {
memset(m_ip, 0, sizeof(m_ip)); memset(m_ip, 0, sizeof(m_ip));
memset(&m_hints, 0, sizeof(m_hints)); memset(&m_hints, 0, sizeof(m_hints));
m_resolver.data = m_responseTimer.data = m_retriesTimer.data = m_keepAliveTimer.data = this; m_resolver.data = this;
m_hints.ai_family = PF_INET; m_hints.ai_family = PF_INET;
m_hints.ai_socktype = SOCK_STREAM; m_hints.ai_socktype = SOCK_STREAM;
@ -71,10 +72,10 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_recvBuf.base = static_cast<char*>(malloc(kRecvBufSize)); m_recvBuf.base = static_cast<char*>(malloc(kRecvBufSize));
m_recvBuf.len = kRecvBufSize; m_recvBuf.len = kRecvBufSize;
auto loop = uv_default_loop(); # ifndef XMRIG_PROXY_PROJECT
uv_timer_init(loop, &m_retriesTimer); m_keepAliveTimer.data = this;
uv_timer_init(loop, &m_responseTimer); uv_timer_init(uv_default_loop(), &m_keepAliveTimer);
uv_timer_init(loop, &m_keepAliveTimer); # endif
} }
@ -93,12 +94,12 @@ Client::~Client()
int64_t Client::send(char *data, size_t size) int64_t Client::send(char *data, size_t size)
{ {
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size ? size : strlen(data), data); LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size ? size : strlen(data), data);
if (state() != ConnectedState) { if (state() != ConnectedState || !uv_is_writable(m_stream)) {
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state); LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
return -1; return -1;
} }
uv_buf_t buf = uv_buf_init(data, size ? size : strlen(data)); uv_buf_t buf = uv_buf_init(data, (unsigned int) (size ? size : strlen(data)));
uv_write_t *req = new uv_write_t; uv_write_t *req = new uv_write_t;
req->data = buf.base; req->data = buf.base;
@ -108,8 +109,7 @@ int64_t Client::send(char *data, size_t size)
delete req; delete req;
}); });
uv_timer_start(&m_responseTimer, [](uv_timer_t *handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0); m_expire = uv_now(uv_default_loop()) + kResponseTimeout;
return m_sequence++; return m_sequence++;
} }
@ -134,9 +134,11 @@ void Client::connect(const Url *url)
void Client::disconnect() void Client::disconnect()
{ {
# ifndef XMRIG_PROXY_PROJECT
uv_timer_stop(&m_keepAliveTimer); uv_timer_stop(&m_keepAliveTimer);
uv_timer_stop(&m_responseTimer); # endif
uv_timer_stop(&m_retriesTimer);
m_expire = 0;
m_failures = -1; m_failures = -1;
close(); close();
@ -153,6 +155,24 @@ void Client::setUrl(const Url *url)
} }
void Client::tick(uint64_t now)
{
if (m_expire == 0 || now < m_expire) {
return;
}
if (m_state == ConnectedState) {
LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port());
close();
}
if (m_state == ConnectingState) {
connect();
}
}
int64_t Client::submit(const JobResult &result) int64_t Client::submit(const JobResult &result)
{ {
char *req = static_cast<char*>(malloc(345)); char *req = static_cast<char*>(malloc(345));
@ -179,6 +199,28 @@ int64_t Client::submit(const JobResult &result)
} }
bool Client::isCriticalError(const char *message)
{
if (!message) {
return false;
}
if (strncasecmp(message, "Unauthenticated", 15) == 0) {
return true;
}
if (strncasecmp(message, "your IP is banned", 17) == 0) {
return true;
}
if (strncasecmp(message, "IP Address currently banned", 27) == 0) {
return true;
}
return false;
}
bool Client::parseJob(const json_t *params, int *code) bool Client::parseJob(const json_t *params, int *code)
{ {
if (!json_is_object(params)) { if (!json_is_object(params)) {
@ -231,6 +273,7 @@ int Client::resolve(const char *host)
{ {
setState(HostLookupState); setState(HostLookupState);
m_expire = 0;
m_recvBufPos = 0; m_recvBufPos = 0;
if (m_failures == -1) { if (m_failures == -1) {
@ -384,7 +427,7 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
LOG_ERR("[%s:%u] error: \"%s\", code: %" PRId64, m_url.host(), m_url.port(), message, json_integer_value(json_object_get(error, "code"))); LOG_ERR("[%s:%u] error: \"%s\", code: %" PRId64, m_url.host(), m_url.port(), message, json_integer_value(json_object_get(error, "code")));
} }
if (id == 1 || (message && strncasecmp(message, "Unauthenticated", 15) == 0)) { if (id == 1 || isCriticalError(message)) {
close(); close();
} }
@ -432,19 +475,20 @@ void Client::reconnect()
{ {
setState(ConnectingState); setState(ConnectingState);
uv_timer_stop(&m_responseTimer); # ifndef XMRIG_PROXY_PROJECT
if (m_url.isKeepAlive()) { if (m_url.isKeepAlive()) {
uv_timer_stop(&m_keepAliveTimer); uv_timer_stop(&m_keepAliveTimer);
} }
# endif
if (m_failures == -1) { if (m_failures == -1) {
return m_listener->onClose(this, -1); return m_listener->onClose(this, -1);
} }
m_failures++; m_failures++;
m_listener->onClose(this, m_failures); m_listener->onClose(this, (int) m_failures);
uv_timer_start(&m_retriesTimer, [](uv_timer_t *handle) { getClient(handle->data)->connect(); }, m_retryPause, 0); m_expire = uv_now(uv_default_loop()) + m_retryPause;
} }
@ -462,12 +506,15 @@ void Client::setState(SocketState state)
void Client::startTimeout() void Client::startTimeout()
{ {
uv_timer_stop(&m_responseTimer); m_expire = 0;
# ifndef XMRIG_PROXY_PROJECT
if (!m_url.isKeepAlive()) { if (!m_url.isKeepAlive()) {
return; return;
} }
uv_timer_start(&m_keepAliveTimer, [](uv_timer_t *handle) { getClient(handle->data)->ping(); }, kKeepAliveTimeout, 0); uv_timer_start(&m_keepAliveTimer, [](uv_timer_t *handle) { getClient(handle->data)->ping(); }, kKeepAliveTimeout, 0);
# endif
} }
@ -523,7 +570,7 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
auto client = getClient(stream->data); auto client = getClient(stream->data);
if (nread < 0) { if (nread < 0) {
if (nread != UV_EOF && !client->m_quiet) { if (nread != UV_EOF && !client->m_quiet) {
LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(nread)); LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror((int) nread));
} }
return client->close();; return client->close();;

View file

@ -62,6 +62,7 @@ public:
void connect(const Url *url); void connect(const Url *url);
void disconnect(); void disconnect();
void setUrl(const Url *url); void setUrl(const Url *url);
void tick(uint64_t now);
inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; } inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; }
inline const char *host() const { return m_url.host(); } inline const char *host() const { return m_url.host(); }
@ -76,6 +77,7 @@ public:
private: private:
constexpr static size_t kRecvBufSize = 4096; constexpr static size_t kRecvBufSize = 4096;
bool isCriticalError(const char *message);
bool parseJob(const json_t *params, int *code); bool parseJob(const json_t *params, int *code);
bool parseLogin(const json_t *result, int *code); bool parseLogin(const json_t *result, int *code);
int resolve(const char *host); int resolve(const char *host);
@ -112,14 +114,16 @@ private:
SocketState m_state; SocketState m_state;
static int64_t m_sequence; static int64_t m_sequence;
std::map<int64_t, SubmitResult> m_results; std::map<int64_t, SubmitResult> m_results;
uint64_t m_expire;
Url m_url; Url m_url;
uv_buf_t m_recvBuf; uv_buf_t m_recvBuf;
uv_getaddrinfo_t m_resolver; uv_getaddrinfo_t m_resolver;
uv_stream_t *m_stream; uv_stream_t *m_stream;
uv_tcp_t *m_socket; uv_tcp_t *m_socket;
# ifndef XMRIG_PROXY_PROJECT
uv_timer_t m_keepAliveTimer; uv_timer_t m_keepAliveTimer;
uv_timer_t m_responseTimer; # endif
uv_timer_t m_retriesTimer;
}; };

View file

@ -82,7 +82,7 @@ bool Job::setBlob(const char *blob)
return false; return false;
} }
if (!fromHex(blob, m_size * 2, m_blob)) { if (!fromHex(blob, (int) m_size * 2, m_blob)) {
return false; return false;
} }

View file

@ -42,11 +42,12 @@ public:
inline bool isNicehash() const { return m_nicehash; } inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return m_size > 0 && m_diff > 0; } inline bool isValid() const { return m_size > 0 && m_diff > 0; }
inline const char *id() const { return m_id; } inline const char *id() const { return m_id; }
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(m_blob + 39); }
inline const uint8_t *blob() const { return m_blob; } inline const uint8_t *blob() const { return m_blob; }
inline int poolId() const { return m_poolId; } inline int poolId() const { return m_poolId; }
inline size_t size() const { return m_size; }
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); } inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
inline uint32_t diff() const { return m_diff; } inline uint32_t diff() const { return (uint32_t) m_diff; }
inline uint32_t size() const { return m_size; }
inline uint64_t target() const { return m_target; } inline uint64_t target() const { return m_target; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; } inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
@ -67,7 +68,7 @@ private:
int m_poolId; int m_poolId;
VAR_ALIGN(16, char m_id[64]); VAR_ALIGN(16, char m_id[64]);
VAR_ALIGN(16, uint8_t m_blob[84]); // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk. VAR_ALIGN(16, uint8_t m_blob[84]); // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk.
uint32_t m_size; size_t m_size;
uint64_t m_diff; uint64_t m_diff;
uint64_t m_target; uint64_t m_target;

View file

@ -43,6 +43,15 @@ public:
} }
inline JobResult(const Job &job) : poolId(0), diff(0), nonce(0)
{
memcpy(jobId, job.id(), sizeof(jobId));
poolId = job.poolId();
diff = job.diff();
nonce = *job.nonce();
}
inline JobResult &operator=(const Job &job) { inline JobResult &operator=(const Job &job) {
memcpy(jobId, job.id(), sizeof(jobId)); memcpy(jobId, job.id(), sizeof(jobId));
poolId = job.poolId(); poolId = job.poolId();

View file

@ -21,6 +21,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
#include <inttypes.h> #include <inttypes.h>
#include <memory> #include <memory>
@ -35,11 +38,11 @@
#include "net/strategies/SinglePoolStrategy.h" #include "net/strategies/SinglePoolStrategy.h"
#include "net/Url.h" #include "net/Url.h"
#include "Options.h" #include "Options.h"
#include "Platform.h"
#include "workers/Workers.h" #include "workers/Workers.h"
Network::Network(const Options *options) : Network::Network(const Options *options) :
m_donateActive(false),
m_options(options), m_options(options),
m_donate(nullptr), m_donate(nullptr),
m_accepted(0), m_accepted(0),
@ -48,26 +51,29 @@ Network::Network(const Options *options) :
srand(time(0) ^ (uintptr_t) this); srand(time(0) ^ (uintptr_t) this);
Workers::setListener(this); Workers::setListener(this);
m_agent = userAgent();
const std::vector<Url*> &pools = options->pools(); const std::vector<Url*> &pools = options->pools();
if (pools.size() > 1) { if (pools.size() > 1) {
m_strategy = new FailoverStrategy(pools, m_agent, this); m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this);
} }
else { else {
m_strategy = new SinglePoolStrategy(pools.front(), m_agent, this); m_strategy = new SinglePoolStrategy(pools.front(), Platform::userAgent(), this);
} }
if (m_options->donateLevel() > 0) { if (m_options->donateLevel() > 0) {
m_donate = new DonateStrategy(m_agent, this); m_donate = new DonateStrategy(Platform::userAgent(), this);
} }
m_timer.data = this;
uv_timer_init(uv_default_loop(), &m_timer);
uv_timer_start(&m_timer, Network::onTick, kTickInterval, kTickInterval);
} }
Network::~Network() Network::~Network()
{ {
free(m_agent);
} }
@ -164,3 +170,21 @@ void Network::setJob(Client *client, const Job &job)
Workers::setJob(job); Workers::setJob(job);
} }
void Network::tick()
{
const uint64_t now = uv_now(uv_default_loop());
m_strategy->tick(now);
if (m_donate) {
m_donate->tick(now);
}
}
void Network::onTick(uv_timer_t *handle)
{
static_cast<Network*>(handle->data)->tick();
}

View file

@ -47,8 +47,6 @@ public:
void connect(); void connect();
void stop(); void stop();
static char *userAgent();
protected: protected:
void onActive(Client *client) override; void onActive(Client *client) override;
void onJob(Client *client, const Job &job) override; void onJob(Client *client, const Job &job) override;
@ -57,15 +55,19 @@ protected:
void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override; void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
private: private:
void setJob(Client *client, const Job &job); constexpr static int kTickInterval = 1 * 1000;
void setJob(Client *client, const Job &job);
void tick();
static void onTick(uv_timer_t *handle);
bool m_donateActive;
char *m_agent;
const Options *m_options; const Options *m_options;
IStrategy *m_donate; IStrategy *m_donate;
IStrategy *m_strategy; IStrategy *m_strategy;
uint64_t m_accepted; uint64_t m_accepted;
uint64_t m_rejected; uint64_t m_rejected;
uv_timer_t m_timer;
}; };

View file

@ -121,7 +121,7 @@ bool Url::parse(const char *url)
memcpy(m_host, base, size - 1); memcpy(m_host, base, size - 1);
m_host[size - 1] = '\0'; m_host[size - 1] = '\0';
m_port = strtol(port, nullptr, 10); m_port = (uint16_t) strtol(port, nullptr, 10);
return true; return true;
} }

View file

@ -24,17 +24,31 @@
#include "interfaces/IStrategyListener.h" #include "interfaces/IStrategyListener.h"
#include "net/Client.h" #include "net/Client.h"
#include "net/Job.h"
#include "net/strategies/DonateStrategy.h" #include "net/strategies/DonateStrategy.h"
#include "Options.h" #include "Options.h"
extern "C"
{
#include "crypto/c_keccak.h"
}
DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) : DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) :
m_active(false), m_active(false),
m_donateTime(Options::i()->donateLevel() * 60 * 1000), m_donateTime(Options::i()->donateLevel() * 60 * 1000),
m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000), m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000),
m_listener(listener) m_listener(listener)
{ {
Url *url = new Url("fee.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, Options::i()->pools().front()->user(), nullptr, false, true); uint8_t hash[200];
char userId[65] = { 0 };
const char *user = Options::i()->pools().front()->user();
keccak(reinterpret_cast<const uint8_t *>(user), static_cast<int>(strlen(user)), hash, sizeof(hash));
Job::toHex(hash, 32, userId);
Url *url = new Url("fee.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, userId, nullptr, false, true);
m_client = new Client(-1, agent, this); m_client = new Client(-1, agent, this);
m_client->setUrl(url); m_client->setUrl(url);
@ -69,6 +83,12 @@ void DonateStrategy::stop()
} }
void DonateStrategy::tick(uint64_t now)
{
m_client->tick(now);
}
void DonateStrategy::onClose(Client *client, int failures) void DonateStrategy::onClose(Client *client, int failures)
{ {
} }

View file

@ -49,6 +49,7 @@ public:
int64_t submit(const JobResult &result) override; int64_t submit(const JobResult &result) override;
void connect() override; void connect() override;
void stop() override; void stop() override;
void tick(uint64_t now) override;
protected: protected:
void onClose(Client *client, int failures) override; void onClose(Client *client, int failures) override;

View file

@ -74,6 +74,14 @@ void FailoverStrategy::stop()
} }
void FailoverStrategy::tick(uint64_t now)
{
for (Client *client : m_pools) {
client->tick(now);
}
}
void FailoverStrategy::onClose(Client *client, int failures) void FailoverStrategy::onClose(Client *client, int failures)
{ {
if (failures == -1) { if (failures == -1) {
@ -132,7 +140,7 @@ void FailoverStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t di
void FailoverStrategy::add(const Url *url, const char *agent) void FailoverStrategy::add(const Url *url, const char *agent)
{ {
Client *client = new Client(m_pools.size(), agent, this); Client *client = new Client((int) m_pools.size(), agent, this);
client->setUrl(url); client->setUrl(url);
client->setRetryPause(Options::i()->retryPause() * 1000); client->setRetryPause(Options::i()->retryPause() * 1000);

View file

@ -49,6 +49,7 @@ public:
void connect() override; void connect() override;
void resume() override; void resume() override;
void stop() override; void stop() override;
void tick(uint64_t now) override;
protected: protected:
void onClose(Client *client, int failures) override; void onClose(Client *client, int failures) override;

View file

@ -66,6 +66,12 @@ void SinglePoolStrategy::stop()
} }
void SinglePoolStrategy::tick(uint64_t now)
{
m_client->tick(now);
}
void SinglePoolStrategy::onClose(Client *client, int failures) void SinglePoolStrategy::onClose(Client *client, int failures)
{ {
if (!isActive()) { if (!isActive()) {

View file

@ -46,6 +46,7 @@ public:
void connect() override; void connect() override;
void resume() override; void resume() override;
void stop() override; void stop() override;
void tick(uint64_t now) override;
protected: protected:
void onClose(Client *client, int failures) override; void onClose(Client *client, int failures) override;

View file

@ -27,14 +27,14 @@
#define APP_ID "xmrig" #define APP_ID "xmrig"
#define APP_NAME "XMRig" #define APP_NAME "XMRig"
#define APP_DESC "Monero (XMR) CPU miner" #define APP_DESC "Monero (XMR) CPU miner"
#define APP_VERSION "2.2.1" #define APP_VERSION "2.3.0-dev"
#define APP_DOMAIN "xmrig.com" #define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com" #define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com"
#define APP_VER_MAJOR 2 #define APP_VER_MAJOR 2
#define APP_VER_MINOR 2 #define APP_VER_MINOR 3
#define APP_VER_BUILD 1 #define APP_VER_BUILD 0
#define APP_VER_REV 0 #define APP_VER_REV 0
#ifdef _MSC_VER #ifdef _MSC_VER

View file

@ -25,7 +25,8 @@
#include "workers/Handle.h" #include "workers/Handle.h"
Handle::Handle(int threadId, int threads, int64_t affinity) : Handle::Handle(int threadId, int threads, int64_t affinity, int priority) :
m_priority(priority),
m_threadId(threadId), m_threadId(threadId),
m_threads(threads), m_threads(threads),
m_affinity(affinity), m_affinity(affinity),

View file

@ -35,10 +35,11 @@ class IWorker;
class Handle class Handle
{ {
public: public:
Handle(int threadId, int threads, int64_t affinity); Handle(int threadId, int threads, int64_t affinity, int priority);
void join(); void join();
void start(void (*callback) (void *)); void start(void (*callback) (void *));
inline int priority() const { return m_priority; }
inline int threadId() const { return m_threadId; } inline int threadId() const { return m_threadId; }
inline int threads() const { return m_threads; } inline int threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; } inline int64_t affinity() const { return m_affinity; }
@ -46,6 +47,7 @@ public:
inline void setWorker(IWorker *worker) { m_worker = worker; } inline void setWorker(IWorker *worker) { m_worker = worker; }
private: private:
int m_priority;
int m_threadId; int m_threadId;
int m_threads; int m_threads;
int64_t m_affinity; int64_t m_affinity;

View file

@ -127,8 +127,8 @@ double Hashrate::calc(size_t threadId, size_t ms) const
} }
double hashes, time; double hashes, time;
hashes = lastestHashCnt - earliestHashCount; hashes = (double) lastestHashCnt - earliestHashCount;
time = lastestStamp - earliestStamp; time = (double) lastestStamp - earliestStamp;
time /= 1000.0; time /= 1000.0;
return hashes / time; return hashes / time;

View file

@ -26,6 +26,7 @@
#include "Cpu.h" #include "Cpu.h"
#include "Mem.h" #include "Mem.h"
#include "Platform.h"
#include "workers/Handle.h" #include "workers/Handle.h"
#include "workers/Worker.h" #include "workers/Worker.h"
@ -42,6 +43,7 @@ Worker::Worker(Handle *handle) :
Cpu::setAffinity(m_id, handle->affinity()); Cpu::setAffinity(m_id, handle->affinity());
} }
Platform::setThreadPriority(handle->priority());
m_ctx = Mem::create(m_id); m_ctx = Mem::create(m_id);
} }

View file

@ -98,7 +98,7 @@ void Workers::setJob(const Job &job)
} }
void Workers::start(int64_t affinity) void Workers::start(int64_t affinity, int priority)
{ {
const int threads = Mem::threads(); const int threads = Mem::threads();
m_hashrate = new Hashrate(threads); m_hashrate = new Hashrate(threads);
@ -114,7 +114,7 @@ void Workers::start(int64_t affinity)
uv_timer_start(&m_timer, Workers::onTick, 500, 500); uv_timer_start(&m_timer, Workers::onTick, 500, 500);
for (int i = 0; i < threads; ++i) { for (int i = 0; i < threads; ++i) {
Handle *handle = new Handle(i, threads, affinity); Handle *handle = new Handle(i, threads, affinity, priority);
m_workers.push_back(handle); m_workers.push_back(handle);
handle->start(Workers::onReady); handle->start(Workers::onReady);
} }

View file

@ -46,7 +46,7 @@ public:
static void printHashrate(bool detail); static void printHashrate(bool detail);
static void setEnabled(bool enabled); static void setEnabled(bool enabled);
static void setJob(const Job &job); static void setJob(const Job &job);
static void start(int64_t affinity); static void start(int64_t affinity, int priority);
static void stop(); static void stop();
static void submit(const JobResult &result); static void submit(const JobResult &result);