diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4dfc18bd2..800a7184a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
- Fixed [terminal issues](https://github.com/xmrig/xmrig-proxy/issues/2#issuecomment-319914085) after exit on Linux and OS X.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f6d189e8b..04fccdc12 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,12 +28,13 @@ set(HEADERS
src/net/Job.h
src/net/JobResult.h
src/net/Network.h
- src/net/SubmitResult.h
- src/net/Url.h
src/net/strategies/DonateStrategy.h
src/net/strategies/FailoverStrategy.h
src/net/strategies/SinglePoolStrategy.h
+ src/net/SubmitResult.h
+ src/net/Url.h
src/Options.h
+ src/Platform.h
src/Summary.h
src/version.h
src/workers/DoubleWorker.h
@@ -73,6 +74,7 @@ set(SOURCES
src/net/strategies/SinglePoolStrategy.cpp
src/net/Url.cpp
src/Options.cpp
+ src/Platform.cpp
src/Summary.cpp
src/workers/DoubleWorker.cpp
src/workers/Handle.cpp
@@ -100,7 +102,7 @@ if (WIN32)
src/App_win.cpp
src/Cpu_win.cpp
src/Mem_win.cpp
- src/net/Network_win.cpp
+ src/Platform_win.cpp
)
add_definitions(/DWIN32)
@@ -110,14 +112,14 @@ elseif (APPLE)
src/App_unix.cpp
src/Cpu_mac.cpp
src/Mem_unix.cpp
- src/net/Network_mac.cpp
+ src/Platform_mac.cpp
)
else()
set(SOURCES_OS
src/App_unix.cpp
src/Cpu_unix.cpp
src/Mem_unix.cpp
- src/net/Network_unix.cpp
+ src/Platform_unix.cpp
)
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_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)
diff --git a/README.md b/README.md
index 7811f711c..972777df6 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,9 @@
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++.
-
+* This is the CPU-mining version, there is also a [NVIDIA GPU version](https://github.com/xmrig/xmrig-nvidia).
+
+
#### Table of contents
* [Features](#features)
@@ -30,17 +32,17 @@ Originally based on cpuminer-multi with heavy optimizations/rewrites and removin
## Download
* Binary releases: https://github.com/xmrig/xmrig/releases
* 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
### 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
```
-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.
@@ -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)
-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)
- --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
--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
-c, --config=FILE load a JSON-format configuration file
- --max-cpu-usage=N maximum cpu usage for automatic threads mode (default 75)
- --safe safe adjust threads and av settings for current cpu
+ -l, --log-file=FILE log all output to a file
+ --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
--print-time=N print hashrate report every N seconds
-h, --help display this help 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
Since version 0.8.0.
* `--av=1` For CPUs with hardware AES.
@@ -88,8 +96,8 @@ Since version 0.8.0.
### CPU mining performance
-* **i7-6700** - 290+ H/s (4 threads, cpu affinity 0xAA)
-* **Dual E5620** - 377 H/s (12 threads, cpu affinity 0xEEEE)
+* **Intel i7-7700** - 307 H/s (4 threads)
+* **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.
diff --git a/src/3rdparty/getopt/getopt.h b/src/3rdparty/getopt/getopt.h
index 0cb88895d..bcbff179e 100644
--- a/src/3rdparty/getopt/getopt.h
+++ b/src/3rdparty/getopt/getopt.h
@@ -56,7 +56,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#pragma warning(disable:4996);
+#pragma warning(disable:4996)
#define __GETOPT_H__
diff --git a/src/3rdparty/jansson/dump.c b/src/3rdparty/jansson/dump.c
index a23fabb7c..0f8996e79 100644
--- a/src/3rdparty/jansson/dump.c
+++ b/src/3rdparty/jansson/dump.c
@@ -5,6 +5,10 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#ifdef _MSC_VER
+#pragma warning(disable:4090)
+#endif
+
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
@@ -15,8 +19,11 @@
#include
#include
#include
-#ifdef HAVE_UNISTD_H
-#include
+
+#if defined(HAVE_UNISTD_H)
+# include
+#elif defined(_MSC_VER)
+# include
#endif
#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)
{
int *dest = (int *)data;
-#ifdef HAVE_UNISTD_H
+# if defined(HAVE_UNISTD_H)
if(write(*dest, buffer, size) == (ssize_t)size)
return 0;
-#endif
+# elif (defined(_MSC_VER))
+ if (write(*dest, buffer, (unsigned int) size) == (int) size)
+ return 0;
+# endif
return -1;
}
diff --git a/src/3rdparty/jansson/hashtable.c b/src/3rdparty/jansson/hashtable.c
index c819319a7..dcc1687b7 100644
--- a/src/3rdparty/jansson/hashtable.c
+++ b/src/3rdparty/jansson/hashtable.c
@@ -5,6 +5,10 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#ifdef _MSC_VER
+#pragma warning(disable:4334)
+#endif
+
#if HAVE_CONFIG_H
#include
#endif
diff --git a/src/3rdparty/jansson/load.c b/src/3rdparty/jansson/load.c
index c212489a1..d9399696b 100644
--- a/src/3rdparty/jansson/load.c
+++ b/src/3rdparty/jansson/load.c
@@ -17,8 +17,13 @@
#include
#include
#include
-#ifdef HAVE_UNISTD_H
-#include
+
+#if defined(HAVE_UNISTD_H)
+# include
+#elif defined(_MSC_VER)
+# include
+# define HAVE_UNISTD_H
+# define STDIN_FILENO 0
#endif
#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)
{
- uint8_t c;
#ifdef HAVE_UNISTD_H
+ uint8_t c;
if (read(*fd, &c, 1) == 1)
return c;
#endif
diff --git a/src/App.cpp b/src/App.cpp
index de6f2785d..c172c045a 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -36,6 +36,7 @@
#include "Mem.h"
#include "net/Network.h"
#include "Options.h"
+#include "Platform.h"
#include "Summary.h"
#include "version.h"
#include "workers/Workers.h"
@@ -80,6 +81,9 @@ App::App(int argc, char **argv) :
}
# endif
+ Platform::init(m_options->userAgent());
+ Platform::setProcessPriority(m_options->priority());
+
m_network = new Network(m_options);
uv_signal_init(uv_default_loop(), &m_signal);
@@ -109,10 +113,10 @@ int App::exec()
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();
- Workers::start(m_options->affinity());
+ Workers::start(m_options->affinity(), m_options->priority());
m_network->connect();
@@ -120,10 +124,11 @@ int App::exec()
uv_loop_close(uv_default_loop());
uv_tty_reset_mode();
- free(m_network);
- free(m_options);
+ delete m_network;
+ Options::release();
Mem::release();
+ Platform::release();
return r;
}
diff --git a/src/Cpu.cpp b/src/Cpu.cpp
index e8f7ee175..2e79b6dfd 100644
--- a/src/Cpu.cpp
+++ b/src/Cpu.cpp
@@ -68,7 +68,7 @@ int Cpu::optimalThreadsCount(int algo, bool doubleHash, int 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;
diff --git a/src/Cpu.h b/src/Cpu.h
index 8b7c3643c..9444274d2 100644
--- a/src/Cpu.h
+++ b/src/Cpu.h
@@ -41,8 +41,8 @@ public:
static void init();
static void setAffinity(int id, uint64_t mask);
- static inline bool hasAES() { return m_flags & AES; }
- static inline bool isX64() { return m_flags & X86_64; }
+ static inline bool hasAES() { return (m_flags & AES) != 0; }
+ static inline bool isX64() { return (m_flags & X86_64) != 0; }
static inline const char *brand() { return m_brand; }
static inline int cores() { return m_totalCores; }
static inline int l2() { return m_l2_cache; }
diff --git a/src/Mem.h b/src/Mem.h
index 58b91ac75..58dba8485 100644
--- a/src/Mem.h
+++ b/src/Mem.h
@@ -44,14 +44,14 @@ public:
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 void *calloc(size_t num, size_t size);
static void release();
static inline bool isDoubleHash() { return m_doubleHash; }
- static inline bool isHugepagesAvailable() { return m_flags & HugepagesAvailable; }
- static inline bool isHugepagesEnabled() { return m_flags & HugepagesEnabled; }
+ 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; }
diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp
index 6de2bd409..7c41fd16a 100644
--- a/src/Mem_unix.cpp
+++ b/src/Mem_unix.cpp
@@ -33,7 +33,7 @@
#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_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 size_t size = MEMORY * (threads * ratio + 1);
+ if (!enabled) {
+ m_memory = static_cast(_mm_malloc(size, 16));
+ return true;
+ }
+
m_flags |= HugepagesAvailable;
# if defined(__APPLE__)
diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp
index f47b6ae4a..a4f92cfe3 100644
--- a/src/Mem_win.cpp
+++ b/src/Mem_win.cpp
@@ -85,9 +85,8 @@ static BOOL SetLockPagesPrivilege() {
static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) {
LSA_UNICODE_STRING lsaString;
- DWORD dwLen = 0;
- dwLen = wcslen(string);
+ DWORD dwLen = (DWORD) wcslen(string);
lsaString.Buffer = (LPWSTR) string;
lsaString.Length = (USHORT)((dwLen) * 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));
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;
}
@@ -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_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 size_t size = MEMORY * (threads * ratio + 1);
+ if (!enabled) {
+ m_memory = static_cast(_mm_malloc(size, 16));
+ return true;
+ }
+
if (TrySetLockPagesPrivilege()) {
m_flags |= HugepagesAvailable;
}
diff --git a/src/Options.cpp b/src/Options.cpp
index 1a1e1c698..36d570b43 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -38,6 +38,7 @@
#include "donate.h"
#include "net/Url.h"
#include "Options.h"
+#include "Platform.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, --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-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\
--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\
-c, --config=FILE load a JSON-format configuration 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' },
{ "config", 1, nullptr, 'c' },
{ "cpu-affinity", 1, nullptr, 1020 },
+ { "cpu-priority", 1, nullptr, 1021 },
{ "donate-level", 1, nullptr, 1003 },
{ "help", 0, nullptr, 'h' },
{ "keepalive", 0, nullptr ,'k' },
@@ -98,6 +103,7 @@ static struct option const options[] = {
{ "max-cpu-usage", 1, nullptr, 1004 },
{ "nicehash", 0, nullptr, 1006 },
{ "no-color", 0, nullptr, 1002 },
+ { "no-huge-pages", 0, nullptr, 1009 },
{ "pass", 1, nullptr, 'p' },
{ "print-time", 1, nullptr, 1007 },
{ "retries", 1, nullptr, 'r' },
@@ -107,6 +113,7 @@ static struct option const options[] = {
{ "threads", 1, nullptr, 't' },
{ "url", 1, nullptr, 'o' },
{ "user", 1, nullptr, 'u' },
+ { "user-agent", 1, nullptr, 1008 },
{ "userpass", 1, nullptr, 'O' },
{ "version", 0, nullptr, 'V' },
{ 0, 0, 0, 0 }
@@ -117,8 +124,11 @@ static struct option const config_options[] = {
{ "algo", 1, nullptr, 'a' },
{ "av", 1, nullptr, 'v' },
{ "background", 0, nullptr, 'B' },
+ { "colors", 0, nullptr, 2000 },
{ "cpu-affinity", 1, nullptr, 1020 },
+ { "cpu-priority", 1, nullptr, 1021 },
{ "donate-level", 1, nullptr, 1003 },
+ { "huge-pages", 0, nullptr, 1009 },
{ "log-file", 1, nullptr, 'l' },
{ "max-cpu-usage", 1, nullptr, 1004 },
{ "print-time", 1, nullptr, 1007 },
@@ -127,7 +137,7 @@ static struct option const config_options[] = {
{ "safe", 0, nullptr, 1005 },
{ "syslog", 0, nullptr, 'S' },
{ "threads", 1, nullptr, 't' },
- { "colors", 0, nullptr, 2000 },
+ { "user-agent", 1, nullptr, 1008 },
{ 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 = new Options(argc, argv);
@@ -202,15 +184,18 @@ Options::Options(int argc, char **argv) :
m_background(false),
m_colors(true),
m_doubleHash(false),
+ m_hugePages(true),
m_ready(false),
m_safe(false),
m_syslog(false),
m_logFile(nullptr),
+ m_userAgent(nullptr),
m_algo(0),
m_algoVariant(0),
m_donateLevel(kDonateLevel),
m_maxCpuUsage(75),
m_printTime(60),
+ m_priority(-1),
m_retries(5),
m_retryPause(5),
m_threads(0),
@@ -237,9 +222,7 @@ Options::Options(int argc, char **argv) :
}
if (!m_pools[0]->isValid()) {
- char *fileName = defaultConfigName();
- parseConfig(fileName);
- delete [] fileName;
+ parseConfig(Platform::defaultConfigName());
}
if (!m_pools[0]->isValid()) {
@@ -326,16 +309,20 @@ bool Options::parseArg(int key, const char *arg)
case 1003: /* --donate-level */
case 1004: /* --max-cpu-usage */
case 1007: /* --print-time */
+ case 1021: /* --cpu-priority */
return parseArg(key, strtol(arg, nullptr, 10));
case 'B': /* --background */
case 'k': /* --keepalive */
case 'S': /* --syslog */
- case 1002: /* --no-color */
case 1005: /* --safe */
case 1006: /* --nicehash */
return parseBoolean(key, true);
+ case 1002: /* --no-color */
+ case 1009: /* --no-huge-pages */
+ return parseBoolean(key, false);
+
case 'V': /* --version */
showVersion();
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));
}
+ case 1008: /* --user-agent */
+ free(m_userAgent);
+ m_userAgent = strdup(arg);
+ break;
+
default:
showUsage(1);
return false;
@@ -371,7 +363,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
- m_retries = arg;
+ m_retries = (int) arg;
break;
case 'R': /* --retry-pause */
@@ -380,7 +372,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
- m_retryPause = arg;
+ m_retryPause = (int) arg;
break;
case 't': /* --threads */
@@ -389,7 +381,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
- m_threads = arg;
+ m_threads = (int) arg;
break;
case 'v': /* --av */
@@ -398,7 +390,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
- m_algoVariant = arg;
+ m_algoVariant = (int) arg;
break;
case 1003: /* --donate-level */
@@ -407,7 +399,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
- m_donateLevel = arg;
+ m_donateLevel = (int) arg;
break;
case 1004: /* --max-cpu-usage */
@@ -416,7 +408,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
- m_maxCpuUsage = arg;
+ m_maxCpuUsage = (int) arg;
break;
case 1007: /* --print-time */
@@ -425,7 +417,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
- m_printTime = arg;
+ m_printTime = (int) arg;
break;
case 1020: /* --cpu-affinity */
@@ -434,6 +426,12 @@ bool Options::parseArg(int key, uint64_t arg)
}
break;
+ case 1021: /* --cpu-priority */
+ if (arg <= 5) {
+ m_priority = (int) arg;
+ }
+ break;
+
default:
break;
}
@@ -471,6 +469,10 @@ bool Options::parseBoolean(int key, bool enable)
m_pools.back()->setNicehash(enable);
break;
+ case 1009: /* --no-huge-pages */
+ m_hugePages = enable;
+ break;
+
case 2000: /* colors */
m_colors = enable;
break;
@@ -497,8 +499,20 @@ Url *Options::parseUrl(const char *arg) const
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_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 (config) {
@@ -609,7 +623,7 @@ bool Options::setAlgo(const char *algo)
{
for (size_t i = 0; i < ARRAY_SIZE(algo_names); i++) {
if (algo_names[i] && !strcmp(algo, algo_names[i])) {
- m_algo = i;
+ m_algo = (int) i;
break;
}
diff --git a/src/Options.h b/src/Options.h
index 7a6a7339f..e85441d94 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -57,18 +57,23 @@ public:
inline bool background() const { return m_background; }
inline bool colors() const { return m_colors; }
inline bool doubleHash() const { return m_doubleHash; }
+ inline bool hugePages() const { return m_hugePages; }
inline bool syslog() const { return m_syslog; }
inline const char *logFile() const { return m_logFile; }
+ inline const char *userAgent() const { return m_userAgent; }
inline const std::vector &pools() const { return m_pools; }
inline int algo() const { return m_algo; }
inline int algoVariant() const { return m_algoVariant; }
inline int donateLevel() const { return m_donateLevel; }
inline int printTime() const { return m_printTime; }
+ inline int priority() const { return m_priority; }
inline int retries() const { return m_retries; }
inline int retryPause() const { return m_retryPause; }
inline int threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; }
+ inline static void release() { delete m_self; }
+
const char *algoName() const;
private:
@@ -98,15 +103,18 @@ private:
bool m_background;
bool m_colors;
bool m_doubleHash;
+ bool m_hugePages;
bool m_ready;
bool m_safe;
bool m_syslog;
char *m_logFile;
+ char *m_userAgent;
int m_algo;
int m_algoVariant;
int m_donateLevel;
int m_maxCpuUsage;
int m_printTime;
+ int m_priority;
int m_retries;
int m_retryPause;
int m_threads;
diff --git a/src/net/Network_unix.cpp b/src/Platform.cpp
similarity index 59%
rename from src/net/Network_unix.cpp
rename to src/Platform.cpp
index 546d1b8a2..4ddb14296 100644
--- a/src/net/Network_unix.cpp
+++ b/src/Platform.cpp
@@ -22,29 +22,41 @@
*/
-#include
+#include
+#include
-#include "net/Network.h"
-#include "version.h"
+#include "Platform.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(malloc(max));
- int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION);
+ if (m_defaultConfigName == nullptr) {
+ m_defaultConfigName = new char[size];
+ }
-# 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
+ if (uv_exepath(m_defaultConfigName, &size) < 0) {
+ return nullptr;
+ }
-# ifdef __GNUC__
- length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
-# endif
+ if (size < 500) {
+# ifdef WIN32
+ 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;
}
diff --git a/src/net/Network_mac.cpp b/src/Platform.h
similarity index 69%
rename from src/net/Network_mac.cpp
rename to src/Platform.h
index c3c42a3e5..87c8cc4db 100644
--- a/src/net/Network_mac.cpp
+++ b/src/Platform.h
@@ -21,19 +21,25 @@
* along with this program. If not, see .
*/
-
-#include
-
-#include "net/Network.h"
-#include "version.h"
+#ifndef __PLATFORM_H__
+#define __PLATFORM_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(malloc(max));
- 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__);
+ static inline const char *userAgent() { return m_userAgent; }
- return buf;
-}
+private:
+ static char *m_defaultConfigName;
+ static char *m_userAgent;
+};
+
+
+#endif /* __PLATFORM_H__ */
diff --git a/src/Platform_mac.cpp b/src/Platform_mac.cpp
new file mode 100644
index 000000000..5e53aacb9
--- /dev/null
+++ b/src/Platform_mac.cpp
@@ -0,0 +1,108 @@
+/* XMRig
+ * Copyright 2010 Jeff Garzik
+ * Copyright 2012-2014 pooler
+ * Copyright 2014 Lucas Jones
+ * Copyright 2014-2016 Wolf9466
+ * Copyright 2016 Jay D Dee
+ * Copyright 2016-2017 XMRig
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+#include
+#include
+#include
+
+
+#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);
+}
+
diff --git a/src/Platform_unix.cpp b/src/Platform_unix.cpp
new file mode 100644
index 000000000..27d8de372
--- /dev/null
+++ b/src/Platform_unix.cpp
@@ -0,0 +1,127 @@
+/* XMRig
+ * Copyright 2010 Jeff Garzik
+ * Copyright 2012-2014 pooler
+ * Copyright 2014 Lucas Jones
+ * Copyright 2014-2016 Wolf9466
+ * Copyright 2016 Jay D Dee
+ * Copyright 2016-2017 XMRig
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+
+
+#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, ¶m) != 0) {
+ sched_setscheduler(0, SCHED_BATCH, ¶m);
+ }
+ }
+}
diff --git a/src/net/Network_win.cpp b/src/Platform_win.cpp
similarity index 56%
rename from src/net/Network_win.cpp
rename to src/Platform_win.cpp
index 6ae5e3223..880bdd982 100644
--- a/src/net/Network_win.cpp
+++ b/src/Platform_win.cpp
@@ -24,11 +24,16 @@
#include
#include
+#include
-#include "net/Network.h"
+#include "Platform.h"
#include "version.h"
+#ifdef XMRIG_NVIDIA_PROJECT
+# include "nvidia/cryptonight.h"
+#endif
+
static inline OSVERSIONINFOEX winOsVersion()
{
@@ -48,12 +53,12 @@ static inline OSVERSIONINFOEX winOsVersion()
}
-char *Network::userAgent()
+static inline char *createUserAgent()
{
const auto osver = winOsVersion();
- const size_t max = 128;
+ const size_t max = 160;
- char *buf = static_cast(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);
# 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());
# 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__);
# elif _MSC_VER
@@ -70,3 +80,91 @@ char *Network::userAgent()
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);
+}
+
diff --git a/src/config.json b/src/config.json
index a0ce1a3bc..afc2936be 100644
--- a/src/config.json
+++ b/src/config.json
@@ -4,6 +4,7 @@
"background": false,
"colors": true,
"cpu-affinity": null,
+ "cpu-priority": null,
"donate-level": 5,
"log-file": null,
"max-cpu-usage": 75,
diff --git a/src/crypto/CryptoNight_p.h b/src/crypto/CryptoNight_p.h
index a74a4ee0e..b85a9da66 100644
--- a/src/crypto/CryptoNight_p.h
+++ b/src/crypto/CryptoNight_p.h
@@ -311,7 +311,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
template
inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx)
{
- keccak(static_cast(input), size, ctx->state0, 200);
+ keccak(static_cast(input), (int) size, ctx->state0, 200);
cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory);
@@ -365,8 +365,8 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
template
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 + size, size, ctx->state1, 200);
+ keccak((const uint8_t *) input, (int) size, ctx->state0, 200);
+ keccak((const uint8_t *) input + size, (int) size, ctx->state1, 200);
const uint8_t* l0 = ctx->memory;
const uint8_t* l1 = ctx->memory + MEM;
diff --git a/src/crypto/c_blake256.c b/src/crypto/c_blake256.c
index 0b484b945..00a84c229 100644
--- a/src/crypto/c_blake256.c
+++ b/src/crypto/c_blake256.c
@@ -148,7 +148,7 @@ void blake256_update(state *S, const uint8_t *data, uint64_t datalen) {
if (datalen > 0) {
memcpy((void *) (S->buf + left), (void *) data, datalen >> 3);
- S->buflen = (left << 3) + datalen;
+ S->buflen = (left << 3) + (int) datalen;
} else {
S->buflen = 0;
}
diff --git a/src/interfaces/IStrategy.h b/src/interfaces/IStrategy.h
index b7f5d6524..660529ea2 100644
--- a/src/interfaces/IStrategy.h
+++ b/src/interfaces/IStrategy.h
@@ -41,6 +41,7 @@ public:
virtual void connect() = 0;
virtual void resume() = 0;
virtual void stop() = 0;
+ virtual void tick(uint64_t now) = 0;
};
diff --git a/src/log/ConsoleLog.cpp b/src/log/ConsoleLog.cpp
index 51e8040a1..6439eb07a 100644
--- a/src/log/ConsoleLog.cpp
+++ b/src/log/ConsoleLog.cpp
@@ -40,7 +40,10 @@
ConsoleLog::ConsoleLog(bool 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);
# ifdef WIN32
@@ -58,6 +61,10 @@ ConsoleLog::ConsoleLog(bool colors) :
void ConsoleLog::message(int level, const char* fmt, va_list args)
{
+ if (!isWritable()) {
+ return;
+ }
+
time_t now = time(nullptr);
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[len];
+ char *buf = new char[64 + strlen(fmt) + 2];
sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
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)
{
- const int len = 64 + strlen(fmt) + 2;
- char *buf = new char[len];
+ if (!isWritable()) {
+ return;
+ }
+
+ char *buf = new char[64 + strlen(fmt) + 2];
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(&m_tty)) == 1 && uv_guess_handle(1) == UV_TTY;
+}
+
+
void ConsoleLog::print(char *fmt, va_list args)
{
vsnprintf(m_buf, sizeof(m_buf) - 1, fmt, args);
diff --git a/src/log/ConsoleLog.h b/src/log/ConsoleLog.h
index b96b5e50c..e3d06e601 100644
--- a/src/log/ConsoleLog.h
+++ b/src/log/ConsoleLog.h
@@ -40,6 +40,7 @@ public:
void text(const char *fmt, va_list args) override;
private:
+ bool isWritable() const;
void print(char *fmt, va_list args);
bool m_colors;
diff --git a/src/log/FileLog.cpp b/src/log/FileLog.cpp
index 224c600dc..9a8711a45 100644
--- a/src/log/FileLog.cpp
+++ b/src/log/FileLog.cpp
@@ -88,7 +88,7 @@ void FileLog::onWrite(uv_fs_t *req)
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(malloc(sizeof(uv_fs_t)));
req->data = buf.base;
diff --git a/src/log/Log.h b/src/log/Log.h
index 16e94e0b9..e193125fd 100644
--- a/src/log/Log.h
+++ b/src/log/Log.h
@@ -77,10 +77,14 @@ private:
#ifdef APP_DEBUG
# 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_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__)
#else
-# define LOG_DEBUG(x, ...)
# define LOG_DEBUG_ERR(x, ...)
# define LOG_DEBUG_WARN(x, ...)
#endif
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index bc44c7dd7..c2518be93 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -56,13 +56,14 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_failures(0),
m_recvBufPos(0),
m_state(UnconnectedState),
+ m_expire(0),
m_stream(nullptr),
m_socket(nullptr)
{
memset(m_ip, 0, sizeof(m_ip));
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_socktype = SOCK_STREAM;
@@ -71,10 +72,10 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_recvBuf.base = static_cast(malloc(kRecvBufSize));
m_recvBuf.len = kRecvBufSize;
- auto loop = uv_default_loop();
- uv_timer_init(loop, &m_retriesTimer);
- uv_timer_init(loop, &m_responseTimer);
- uv_timer_init(loop, &m_keepAliveTimer);
+# ifndef XMRIG_PROXY_PROJECT
+ m_keepAliveTimer.data = this;
+ uv_timer_init(uv_default_loop(), &m_keepAliveTimer);
+# endif
}
@@ -93,12 +94,12 @@ Client::~Client()
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);
- 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);
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;
req->data = buf.base;
@@ -108,8 +109,7 @@ int64_t Client::send(char *data, size_t size)
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++;
}
@@ -134,9 +134,11 @@ void Client::connect(const Url *url)
void Client::disconnect()
{
+# ifndef XMRIG_PROXY_PROJECT
uv_timer_stop(&m_keepAliveTimer);
- uv_timer_stop(&m_responseTimer);
- uv_timer_stop(&m_retriesTimer);
+# endif
+
+ m_expire = 0;
m_failures = -1;
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)
{
char *req = static_cast(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)
{
if (!json_is_object(params)) {
@@ -231,6 +273,7 @@ int Client::resolve(const char *host)
{
setState(HostLookupState);
+ m_expire = 0;
m_recvBufPos = 0;
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")));
}
- if (id == 1 || (message && strncasecmp(message, "Unauthenticated", 15) == 0)) {
+ if (id == 1 || isCriticalError(message)) {
close();
}
@@ -432,19 +475,20 @@ void Client::reconnect()
{
setState(ConnectingState);
- uv_timer_stop(&m_responseTimer);
+# ifndef XMRIG_PROXY_PROJECT
if (m_url.isKeepAlive()) {
uv_timer_stop(&m_keepAliveTimer);
}
+# endif
if (m_failures == -1) {
return m_listener->onClose(this, -1);
}
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()
{
- uv_timer_stop(&m_responseTimer);
+ m_expire = 0;
+
+# ifndef XMRIG_PROXY_PROJECT
if (!m_url.isKeepAlive()) {
return;
}
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);
if (nread < 0) {
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();;
diff --git a/src/net/Client.h b/src/net/Client.h
index b04c2c3b5..f554e3417 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -62,6 +62,7 @@ public:
void connect(const Url *url);
void disconnect();
void setUrl(const Url *url);
+ void tick(uint64_t now);
inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; }
inline const char *host() const { return m_url.host(); }
@@ -76,6 +77,7 @@ public:
private:
constexpr static size_t kRecvBufSize = 4096;
+ bool isCriticalError(const char *message);
bool parseJob(const json_t *params, int *code);
bool parseLogin(const json_t *result, int *code);
int resolve(const char *host);
@@ -112,14 +114,16 @@ private:
SocketState m_state;
static int64_t m_sequence;
std::map m_results;
+ uint64_t m_expire;
Url m_url;
uv_buf_t m_recvBuf;
uv_getaddrinfo_t m_resolver;
uv_stream_t *m_stream;
uv_tcp_t *m_socket;
+
+# ifndef XMRIG_PROXY_PROJECT
uv_timer_t m_keepAliveTimer;
- uv_timer_t m_responseTimer;
- uv_timer_t m_retriesTimer;
+# endif
};
diff --git a/src/net/Job.cpp b/src/net/Job.cpp
index 4929aaf5d..bce65e628 100644
--- a/src/net/Job.cpp
+++ b/src/net/Job.cpp
@@ -82,7 +82,7 @@ bool Job::setBlob(const char *blob)
return false;
}
- if (!fromHex(blob, m_size * 2, m_blob)) {
+ if (!fromHex(blob, (int) m_size * 2, m_blob)) {
return false;
}
diff --git a/src/net/Job.h b/src/net/Job.h
index e7fca53e8..86160584b 100644
--- a/src/net/Job.h
+++ b/src/net/Job.h
@@ -42,11 +42,12 @@ public:
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
inline const char *id() const { return m_id; }
+ inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + 39); }
inline const uint8_t *blob() const { return m_blob; }
inline int poolId() const { return m_poolId; }
+ inline size_t size() const { return m_size; }
inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); }
- inline uint32_t diff() const { return m_diff; }
- inline uint32_t size() const { return m_size; }
+ inline uint32_t diff() const { return (uint32_t) m_diff; }
inline uint64_t target() const { return m_target; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
@@ -67,7 +68,7 @@ private:
int m_poolId;
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.
- uint32_t m_size;
+ size_t m_size;
uint64_t m_diff;
uint64_t m_target;
diff --git a/src/net/JobResult.h b/src/net/JobResult.h
index 9ced3cac8..de3b17ad3 100644
--- a/src/net/JobResult.h
+++ b/src/net/JobResult.h
@@ -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) {
memcpy(jobId, job.id(), sizeof(jobId));
poolId = job.poolId();
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index 86c5ee7ad..d732c7748 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -21,6 +21,9 @@
* along with this program. If not, see .
*/
+#ifdef _MSC_VER
+#pragma warning(disable:4244)
+#endif
#include
#include
@@ -35,11 +38,11 @@
#include "net/strategies/SinglePoolStrategy.h"
#include "net/Url.h"
#include "Options.h"
+#include "Platform.h"
#include "workers/Workers.h"
Network::Network(const Options *options) :
- m_donateActive(false),
m_options(options),
m_donate(nullptr),
m_accepted(0),
@@ -48,26 +51,29 @@ Network::Network(const Options *options) :
srand(time(0) ^ (uintptr_t) this);
Workers::setListener(this);
- m_agent = userAgent();
const std::vector &pools = options->pools();
if (pools.size() > 1) {
- m_strategy = new FailoverStrategy(pools, m_agent, this);
+ m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this);
}
else {
- m_strategy = new SinglePoolStrategy(pools.front(), m_agent, this);
+ m_strategy = new SinglePoolStrategy(pools.front(), Platform::userAgent(), this);
}
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()
{
- free(m_agent);
}
@@ -164,3 +170,21 @@ void Network::setJob(Client *client, const Job &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(handle->data)->tick();
+}
diff --git a/src/net/Network.h b/src/net/Network.h
index 21046df9b..33806f634 100644
--- a/src/net/Network.h
+++ b/src/net/Network.h
@@ -47,8 +47,6 @@ public:
void connect();
void stop();
- static char *userAgent();
-
protected:
void onActive(Client *client) 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;
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;
IStrategy *m_donate;
IStrategy *m_strategy;
uint64_t m_accepted;
uint64_t m_rejected;
+ uv_timer_t m_timer;
};
diff --git a/src/net/Url.cpp b/src/net/Url.cpp
index 82b788d9d..a0024d261 100644
--- a/src/net/Url.cpp
+++ b/src/net/Url.cpp
@@ -121,7 +121,7 @@ bool Url::parse(const char *url)
memcpy(m_host, base, size - 1);
m_host[size - 1] = '\0';
- m_port = strtol(port, nullptr, 10);
+ m_port = (uint16_t) strtol(port, nullptr, 10);
return true;
}
diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp
index d87e83de1..0f9814514 100644
--- a/src/net/strategies/DonateStrategy.cpp
+++ b/src/net/strategies/DonateStrategy.cpp
@@ -24,17 +24,31 @@
#include "interfaces/IStrategyListener.h"
#include "net/Client.h"
+#include "net/Job.h"
#include "net/strategies/DonateStrategy.h"
#include "Options.h"
+extern "C"
+{
+#include "crypto/c_keccak.h"
+}
+
+
DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) :
m_active(false),
m_donateTime(Options::i()->donateLevel() * 60 * 1000),
m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000),
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(user), static_cast(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->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)
{
}
diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h
index 1c7597ef5..b54b0b176 100644
--- a/src/net/strategies/DonateStrategy.h
+++ b/src/net/strategies/DonateStrategy.h
@@ -49,6 +49,7 @@ public:
int64_t submit(const JobResult &result) override;
void connect() override;
void stop() override;
+ void tick(uint64_t now) override;
protected:
void onClose(Client *client, int failures) override;
diff --git a/src/net/strategies/FailoverStrategy.cpp b/src/net/strategies/FailoverStrategy.cpp
index 380cf9817..e25b8c581 100644
--- a/src/net/strategies/FailoverStrategy.cpp
+++ b/src/net/strategies/FailoverStrategy.cpp
@@ -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)
{
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)
{
- Client *client = new Client(m_pools.size(), agent, this);
+ Client *client = new Client((int) m_pools.size(), agent, this);
client->setUrl(url);
client->setRetryPause(Options::i()->retryPause() * 1000);
diff --git a/src/net/strategies/FailoverStrategy.h b/src/net/strategies/FailoverStrategy.h
index f0fa05146..616a08d71 100644
--- a/src/net/strategies/FailoverStrategy.h
+++ b/src/net/strategies/FailoverStrategy.h
@@ -49,6 +49,7 @@ public:
void connect() override;
void resume() override;
void stop() override;
+ void tick(uint64_t now) override;
protected:
void onClose(Client *client, int failures) override;
diff --git a/src/net/strategies/SinglePoolStrategy.cpp b/src/net/strategies/SinglePoolStrategy.cpp
index b1a6941ec..f38405f46 100644
--- a/src/net/strategies/SinglePoolStrategy.cpp
+++ b/src/net/strategies/SinglePoolStrategy.cpp
@@ -66,6 +66,12 @@ void SinglePoolStrategy::stop()
}
+void SinglePoolStrategy::tick(uint64_t now)
+{
+ m_client->tick(now);
+}
+
+
void SinglePoolStrategy::onClose(Client *client, int failures)
{
if (!isActive()) {
diff --git a/src/net/strategies/SinglePoolStrategy.h b/src/net/strategies/SinglePoolStrategy.h
index 51b1a88d8..c09d0305b 100644
--- a/src/net/strategies/SinglePoolStrategy.h
+++ b/src/net/strategies/SinglePoolStrategy.h
@@ -46,6 +46,7 @@ public:
void connect() override;
void resume() override;
void stop() override;
+ void tick(uint64_t now) override;
protected:
void onClose(Client *client, int failures) override;
diff --git a/src/version.h b/src/version.h
index 3d197ee39..81e953914 100644
--- a/src/version.h
+++ b/src/version.h
@@ -27,14 +27,14 @@
#define APP_ID "xmrig"
#define APP_NAME "XMRig"
#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_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com"
#define APP_VER_MAJOR 2
-#define APP_VER_MINOR 2
-#define APP_VER_BUILD 1
+#define APP_VER_MINOR 3
+#define APP_VER_BUILD 0
#define APP_VER_REV 0
#ifdef _MSC_VER
diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp
index 8b748cd3b..c461cee75 100644
--- a/src/workers/Handle.cpp
+++ b/src/workers/Handle.cpp
@@ -25,7 +25,8 @@
#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_threads(threads),
m_affinity(affinity),
diff --git a/src/workers/Handle.h b/src/workers/Handle.h
index a663fbe90..9faae0d0c 100644
--- a/src/workers/Handle.h
+++ b/src/workers/Handle.h
@@ -35,10 +35,11 @@ class IWorker;
class Handle
{
public:
- Handle(int threadId, int threads, int64_t affinity);
+ Handle(int threadId, int threads, int64_t affinity, int priority);
void join();
void start(void (*callback) (void *));
+ inline int priority() const { return m_priority; }
inline int threadId() const { return m_threadId; }
inline int threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; }
@@ -46,6 +47,7 @@ public:
inline void setWorker(IWorker *worker) { m_worker = worker; }
private:
+ int m_priority;
int m_threadId;
int m_threads;
int64_t m_affinity;
diff --git a/src/workers/Hashrate.cpp b/src/workers/Hashrate.cpp
index 4c3731562..5bc656982 100644
--- a/src/workers/Hashrate.cpp
+++ b/src/workers/Hashrate.cpp
@@ -127,8 +127,8 @@ double Hashrate::calc(size_t threadId, size_t ms) const
}
double hashes, time;
- hashes = lastestHashCnt - earliestHashCount;
- time = lastestStamp - earliestStamp;
+ hashes = (double) lastestHashCnt - earliestHashCount;
+ time = (double) lastestStamp - earliestStamp;
time /= 1000.0;
return hashes / time;
diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp
index 583c1d459..02646cedf 100644
--- a/src/workers/Worker.cpp
+++ b/src/workers/Worker.cpp
@@ -26,6 +26,7 @@
#include "Cpu.h"
#include "Mem.h"
+#include "Platform.h"
#include "workers/Handle.h"
#include "workers/Worker.h"
@@ -42,6 +43,7 @@ Worker::Worker(Handle *handle) :
Cpu::setAffinity(m_id, handle->affinity());
}
+ Platform::setThreadPriority(handle->priority());
m_ctx = Mem::create(m_id);
}
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
index b056c826c..e51f5d223 100644
--- a/src/workers/Workers.cpp
+++ b/src/workers/Workers.cpp
@@ -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();
m_hashrate = new Hashrate(threads);
@@ -114,7 +114,7 @@ void Workers::start(int64_t affinity)
uv_timer_start(&m_timer, Workers::onTick, 500, 500);
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);
handle->start(Workers::onReady);
}
diff --git a/src/workers/Workers.h b/src/workers/Workers.h
index 0caf22a20..e76d0a620 100644
--- a/src/workers/Workers.h
+++ b/src/workers/Workers.h
@@ -46,7 +46,7 @@ public:
static void printHashrate(bool detail);
static void setEnabled(bool enabled);
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 submit(const JobResult &result);