From 44782befea5e9300c76815d05d31df7989d3fcad Mon Sep 17 00:00:00 2001
From: XMRig <xmrig@bunkr.org>
Date: Tue, 16 May 2017 17:04:27 +0300
Subject: [PATCH 01/56] Fix 32 bit build.

---
 CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0425d8e99..12696ae76 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -132,7 +132,7 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
     add_executable(xmrig ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${SOURCES_CPUID} ${SOURCES_AEON})
     target_link_libraries(xmrig jansson curl ${CPUID_LIB} ${EXTRA_LIBS})
 else()
-    add_executable(xmrig32 ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${SOURCES_CPUID})
+    add_executable(xmrig32 ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${SOURCES_CPUID} ${SOURCES_AEON})
     target_link_libraries(xmrig32 jansson curl ${CPUID_LIB} ${EXTRA_LIBS})
 endif()
 

From 583d892eb5ecdc93375641ad5160e6b24a5d4888 Mon Sep 17 00:00:00 2001
From: XMRig <xmrig@bunkr.org>
Date: Wed, 24 May 2017 18:50:24 +0300
Subject: [PATCH 02/56] Workaround for AMD CPUs
 https://github.com/anrieff/libcpuid/issues/97

---
 cpu.c     | 11 +++++++++--
 version.h |  4 ++--
 xmrig.c   |  2 +-
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/cpu.c b/cpu.c
index bb8462389..2f6ef8b6f 100644
--- a/cpu.c
+++ b/cpu.c
@@ -31,7 +31,6 @@
 #endif
 
 #include "cpu.h"
-#include "utils/applog.h"
 
 
 #ifndef BUILD_TEST
@@ -47,9 +46,17 @@ void cpu_init_common() {
     cpu_info.total_logical_cpus = data.total_logical_cpus;
     cpu_info.sockets            = data.total_logical_cpus / data.num_logical_cpus;
     cpu_info.total_cores        = data.num_cores * cpu_info.sockets;
-    cpu_info.l2_cache           = data.l2_cache > 0 ? data.l2_cache * cpu_info.total_cores * cpu_info.sockets : 0;
     cpu_info.l3_cache           = data.l3_cache > 0 ? data.l3_cache * cpu_info.sockets : 0;
 
+    // Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97
+    if (data.vendor == VENDOR_AMD && data.l3_cache <= 0 && data.l2_assoc == 16 && data.ext_family >= 21) {
+        cpu_info.l2_cache = data.l2_cache * (cpu_info.total_cores / 2) * cpu_info.sockets;
+    }
+    else {
+        cpu_info.l2_cache = data.l2_cache > 0 ? data.l2_cache * cpu_info.total_cores * cpu_info.sockets : 0;
+    }
+
+
 #   ifdef __x86_64__
     cpu_info.flags |= CPU_FLAG_X86_64;
 #   endif
diff --git a/version.h b/version.h
index 8804e2713..6b453bdbe 100644
--- a/version.h
+++ b/version.h
@@ -27,14 +27,14 @@
 #define APP_ID        "xmrig"
 #define APP_NAME      "XMRig"
 #define APP_DESC      "Monero (XMR) CPU miner"
-#define APP_VERSION   "0.8.1"
+#define APP_VERSION   "0.8.2"
 #define APP_DOMAIN    "xmrig.com"
 #define APP_SITE      "www.xmrig.com"
 #define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com"
 
 #define APP_VER_MAJOR  0
 #define APP_VER_MINOR  8
-#define APP_VER_BUILD  1
+#define APP_VER_BUILD  2
 #define APP_VER_REV    0
 
 #endif /* __VERSION_H__ */
diff --git a/xmrig.c b/xmrig.c
index d3c423a50..7b14933b1 100644
--- a/xmrig.c
+++ b/xmrig.c
@@ -641,8 +641,8 @@ static bool start_mining() {
  * @return
  */
 int main(int argc, char *argv[]) {
-    cpu_init();
     applog_init();
+    cpu_init();
     parse_cmdline(argc, argv);
     persistent_memory_allocate();
     print_summary();

From eb3e2b886854d63493c3e2a8bac8fe261503aeaf Mon Sep 17 00:00:00 2001
From: XMRig <xmrig@bunkr.org>
Date: Thu, 25 May 2017 09:32:39 +0300
Subject: [PATCH 03/56] Fix gcc7 support.

---
 algo/cryptonight-lite/cryptonight_lite_aesni.h   | 4 ++--
 algo/cryptonight-lite/cryptonight_lite_softaes.h | 4 ++--
 algo/cryptonight/cryptonight_aesni.h             | 4 ++--
 algo/cryptonight/cryptonight_softaes.h           | 4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/algo/cryptonight-lite/cryptonight_lite_aesni.h b/algo/cryptonight-lite/cryptonight_lite_aesni.h
index 6c9d15cbf..e69c79b26 100644
--- a/algo/cryptonight-lite/cryptonight_lite_aesni.h
+++ b/algo/cryptonight-lite/cryptonight_lite_aesni.h
@@ -116,7 +116,7 @@ inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i*
 }
 
 
-inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
+static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
 {
     // This is more than we have registers, compiler will assign 2 keys on the stack
     __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
@@ -157,7 +157,7 @@ inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
 }
 
 
-inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
+static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
 {
     // This is more than we have registers, compiler will assign 2 keys on the stack
     __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
diff --git a/algo/cryptonight-lite/cryptonight_lite_softaes.h b/algo/cryptonight-lite/cryptonight_lite_softaes.h
index 15a0a574e..3b28d3223 100644
--- a/algo/cryptonight-lite/cryptonight_lite_softaes.h
+++ b/algo/cryptonight-lite/cryptonight_lite_softaes.h
@@ -97,7 +97,7 @@ inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i*
 }
 
 
-inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
+static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
 {
     // This is more than we have registers, compiler will assign 2 keys on the stack
     __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
@@ -138,7 +138,7 @@ inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
 }
 
 
-inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
+static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
 {
     // This is more than we have registers, compiler will assign 2 keys on the stack
     __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
diff --git a/algo/cryptonight/cryptonight_aesni.h b/algo/cryptonight/cryptonight_aesni.h
index 30ad690a5..dcbc740dd 100644
--- a/algo/cryptonight/cryptonight_aesni.h
+++ b/algo/cryptonight/cryptonight_aesni.h
@@ -116,7 +116,7 @@ inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i*
 }
 
 
-inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
+static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
 {
     // This is more than we have registers, compiler will assign 2 keys on the stack
     __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
@@ -157,7 +157,7 @@ inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
 }
 
 
-inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
+static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
 {
     // This is more than we have registers, compiler will assign 2 keys on the stack
     __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
diff --git a/algo/cryptonight/cryptonight_softaes.h b/algo/cryptonight/cryptonight_softaes.h
index 1948db05f..0d70f8ca5 100644
--- a/algo/cryptonight/cryptonight_softaes.h
+++ b/algo/cryptonight/cryptonight_softaes.h
@@ -97,7 +97,7 @@ inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i*
 }
 
 
-inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
+static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
 {
     // This is more than we have registers, compiler will assign 2 keys on the stack
     __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
@@ -138,7 +138,7 @@ inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
 }
 
 
-inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
+static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
 {
     // This is more than we have registers, compiler will assign 2 keys on the stack
     __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;

From ebb0f81f2f21938d8ba63eb1eefb337b5230c032 Mon Sep 17 00:00:00 2001
From: xmrig <xmrig@bunkr.org>
Date: Fri, 26 May 2017 09:07:45 +0300
Subject: [PATCH 04/56] Update CHANGELOG.md

---
 CHANGELOG.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef91b561d..2005d74d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# v0.8.2
+- Fixed L2 cache size detection for AMD CPUs (Bulldozer/Piledriver/Steamroller/Excavator architecture).
+- Fixed gcc 7.1 support.
+
 # v0.8.1
 - Added nicehash support, detects automaticaly by pool URL, for example `cryptonight.eu.nicehash.com:3355` or manually via option `--nicehash`.
 

From bc2b7d1895f56c83e21f68408734dd34069dbee6 Mon Sep 17 00:00:00 2001
From: Admin <admin@mac-admin.local>
Date: Fri, 26 May 2017 23:17:12 +0300
Subject: [PATCH 05/56] Initial OS X support.

---
 CMakeLists.txt                                |  3 +-
 .../cryptonight-lite/cryptonight_lite_aesni.h | 18 ++--
 .../cryptonight_lite_softaes.h                | 12 +--
 algo/cryptonight/cryptonight_aesni.h          | 18 ++--
 algo/cryptonight/cryptonight_softaes.h        | 10 +-
 mac/cpu_mac.c                                 | 47 ++++++++++
 mac/memory_mac.c                              | 47 ++++++++++
 mac/xmrig_mac.c                               | 91 +++++++++++++++++++
 memory.c                                      |  6 +-
 stratum.c                                     | 37 +++++---
 version.h                                     |  4 +-
 11 files changed, 244 insertions(+), 49 deletions(-)
 create mode 100644 mac/cpu_mac.c
 create mode 100644 mac/memory_mac.c
 create mode 100644 mac/xmrig_mac.c

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 12696ae76..39465124c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,6 +70,8 @@ if (WIN32)
     set(SOURCES_OS win/cpu_win.c win/memory_win.c win/xmrig_win.c win/app.rc compat/winansi.c)
     set(EXTRA_LIBS ws2_32)
     add_definitions(/D_WIN32_WINNT=0x600)
+elseif (APPLE)
+    set(SOURCES_OS mac/cpu_mac.c mac/memory_mac.c mac/xmrig_mac.c)
 else()
     set(SOURCES_OS unix/cpu_unix.c unix/memory_unix.c unix/xmrig_unix.c)
     set(EXTRA_LIBS pthread)
@@ -136,4 +138,3 @@ else()
     target_link_libraries(xmrig32 jansson curl ${CPUID_LIB} ${EXTRA_LIBS})
 endif()
 
-source_group("HEADERS" FILES ${HEADERS})
diff --git a/algo/cryptonight-lite/cryptonight_lite_aesni.h b/algo/cryptonight-lite/cryptonight_lite_aesni.h
index e69c79b26..bb528cfb4 100644
--- a/algo/cryptonight-lite/cryptonight_lite_aesni.h
+++ b/algo/cryptonight-lite/cryptonight_lite_aesni.h
@@ -41,7 +41,7 @@
 
 // This will shift and xor tmp1 into itself as 4 32-bit vals such as
 // sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
-inline __m128i sl_xor(__m128i tmp1)
+static inline __m128i sl_xor(__m128i tmp1)
 {
     __m128i tmp4;
     tmp4 = _mm_slli_si128(tmp1, 0x04);
@@ -54,31 +54,31 @@ inline __m128i sl_xor(__m128i tmp1)
 }
 
 
-inline void aes_genkey_sub1(__m128i* xout0, __m128i* xout2)
+static inline void aes_genkey_sub1(__m128i* xout0, __m128i* xout2)
 {
    aes_genkey_sub(0x1)
 }
 
 
-inline void aes_genkey_sub2(__m128i* xout0, __m128i* xout2)
+static inline void aes_genkey_sub2(__m128i* xout0, __m128i* xout2)
 {
    aes_genkey_sub(0x2)
 }
 
 
-inline void aes_genkey_sub4(__m128i* xout0, __m128i* xout2)
+static inline void aes_genkey_sub4(__m128i* xout0, __m128i* xout2)
 {
    aes_genkey_sub(0x4)
 }
 
 
-inline void aes_genkey_sub8(__m128i* xout0, __m128i* xout2)
+static inline void aes_genkey_sub8(__m128i* xout0, __m128i* xout2)
 {
    aes_genkey_sub(0x8)
 }
 
 
-inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
+static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
 {
     *x0 = _mm_aesenc_si128(*x0, key);
     *x1 = _mm_aesenc_si128(*x1, key);
@@ -91,7 +91,7 @@ inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128
 }
 
 
-inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
+static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
 {
     __m128i xout0 = _mm_load_si128(memory);
     __m128i xout2 = _mm_load_si128(memory + 1);
@@ -211,7 +211,7 @@ static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
 #if defined(__x86_64__)
 #   define EXTRACT64(X) _mm_cvtsi128_si64(X)
 
-inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
+static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
 {
     unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
     *hi = r >> 64;
@@ -226,7 +226,7 @@ inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
     ((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
     ((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
 
-inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
+static inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
     // multiplier   = ab = a * 2^32 + b
     // multiplicand = cd = c * 2^32 + d
     // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
diff --git a/algo/cryptonight-lite/cryptonight_lite_softaes.h b/algo/cryptonight-lite/cryptonight_lite_softaes.h
index 3b28d3223..bab3dcafe 100644
--- a/algo/cryptonight-lite/cryptonight_lite_softaes.h
+++ b/algo/cryptonight-lite/cryptonight_lite_softaes.h
@@ -33,7 +33,7 @@ extern __m128i soft_aeskeygenassist(__m128i key, uint8_t rcon);
 
 // This will shift and xor tmp1 into itself as 4 32-bit vals such as
 // sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
-inline __m128i sl_xor(__m128i tmp1)
+static inline __m128i sl_xor(__m128i tmp1)
 {
     __m128i tmp4;
     tmp4 = _mm_slli_si128(tmp1, 0x04);
@@ -46,7 +46,7 @@ inline __m128i sl_xor(__m128i tmp1)
 }
 
 
-inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
+static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
 {
     __m128i xout1 = soft_aeskeygenassist(*xout2, rcon);
     xout1  = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
@@ -59,7 +59,7 @@ inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
 }
 
 
-inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
+static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
 {
     *x0 = soft_aesenc(*x0, key);
     *x1 = soft_aesenc(*x1, key);
@@ -72,7 +72,7 @@ inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128
 }
 
 
-inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
+static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
 {
     __m128i xout0 = _mm_load_si128(memory);
     __m128i xout2 = _mm_load_si128(memory + 1);
@@ -192,7 +192,7 @@ static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
 #if defined(__x86_64__)
 #   define EXTRACT64(X) _mm_cvtsi128_si64(X)
 
-inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
+static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
 {
     unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
     *hi = r >> 64;
@@ -207,7 +207,7 @@ inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
     ((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
     ((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
 
-inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
+static inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
     // multiplier   = ab = a * 2^32 + b
     // multiplicand = cd = c * 2^32 + d
     // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
diff --git a/algo/cryptonight/cryptonight_aesni.h b/algo/cryptonight/cryptonight_aesni.h
index dcbc740dd..e4d6d42f1 100644
--- a/algo/cryptonight/cryptonight_aesni.h
+++ b/algo/cryptonight/cryptonight_aesni.h
@@ -41,7 +41,7 @@
 
 // This will shift and xor tmp1 into itself as 4 32-bit vals such as
 // sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
-inline __m128i sl_xor(__m128i tmp1)
+static inline __m128i sl_xor(__m128i tmp1)
 {
     __m128i tmp4;
     tmp4 = _mm_slli_si128(tmp1, 0x04);
@@ -54,31 +54,31 @@ inline __m128i sl_xor(__m128i tmp1)
 }
 
 
-inline void aes_genkey_sub1(__m128i* xout0, __m128i* xout2)
+static inline void aes_genkey_sub1(__m128i* xout0, __m128i* xout2)
 {
    aes_genkey_sub(0x1)
 }
 
 
-inline void aes_genkey_sub2(__m128i* xout0, __m128i* xout2)
+static inline void aes_genkey_sub2(__m128i* xout0, __m128i* xout2)
 {
    aes_genkey_sub(0x2)
 }
 
 
-inline void aes_genkey_sub4(__m128i* xout0, __m128i* xout2)
+static inline void aes_genkey_sub4(__m128i* xout0, __m128i* xout2)
 {
    aes_genkey_sub(0x4)
 }
 
 
-inline void aes_genkey_sub8(__m128i* xout0, __m128i* xout2)
+static inline void aes_genkey_sub8(__m128i* xout0, __m128i* xout2)
 {
    aes_genkey_sub(0x8)
 }
 
 
-inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
+static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
 {
     *x0 = _mm_aesenc_si128(*x0, key);
     *x1 = _mm_aesenc_si128(*x1, key);
@@ -91,7 +91,7 @@ inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128
 }
 
 
-inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
+static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
 {
     __m128i xout0 = _mm_load_si128(memory);
     __m128i xout2 = _mm_load_si128(memory + 1);
@@ -211,7 +211,7 @@ static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
 #if defined(__x86_64__)
 #   define EXTRACT64(X) _mm_cvtsi128_si64(X)
 
-inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
+static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
 {
     unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
     *hi = r >> 64;
@@ -226,7 +226,7 @@ inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
     ((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
     ((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
 
-inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
+static inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
     // multiplier   = ab = a * 2^32 + b
     // multiplicand = cd = c * 2^32 + d
     // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
diff --git a/algo/cryptonight/cryptonight_softaes.h b/algo/cryptonight/cryptonight_softaes.h
index 0d70f8ca5..f12ab8c67 100644
--- a/algo/cryptonight/cryptonight_softaes.h
+++ b/algo/cryptonight/cryptonight_softaes.h
@@ -33,7 +33,7 @@ extern __m128i soft_aeskeygenassist(__m128i key, uint8_t rcon);
 
 // This will shift and xor tmp1 into itself as 4 32-bit vals such as
 // sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
-inline __m128i sl_xor(__m128i tmp1)
+static inline __m128i sl_xor(__m128i tmp1)
 {
     __m128i tmp4;
     tmp4 = _mm_slli_si128(tmp1, 0x04);
@@ -46,7 +46,7 @@ inline __m128i sl_xor(__m128i tmp1)
 }
 
 
-inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
+static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
 {
     __m128i xout1 = soft_aeskeygenassist(*xout2, rcon);
     xout1  = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
@@ -59,7 +59,7 @@ inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
 }
 
 
-inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
+static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
 {
     *x0 = soft_aesenc(*x0, key);
     *x1 = soft_aesenc(*x1, key);
@@ -72,7 +72,7 @@ inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128
 }
 
 
-inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
+static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
 {
     __m128i xout0 = _mm_load_si128(memory);
     __m128i xout2 = _mm_load_si128(memory + 1);
@@ -192,7 +192,7 @@ static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
 #if defined(__x86_64__)
 #   define EXTRACT64(X) _mm_cvtsi128_si64(X)
 
-inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
+static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
 {
     unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
     *hi = r >> 64;
diff --git a/mac/cpu_mac.c b/mac/cpu_mac.c
new file mode 100644
index 000000000..88bda5419
--- /dev/null
+++ b/mac/cpu_mac.c
@@ -0,0 +1,47 @@
+/* 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 <unistd.h>
+#include <sched.h>
+#include <pthread.h>
+
+#include "cpu.h"
+
+
+struct cpu_info cpu_info = { 0 };
+void cpu_init_common();
+
+
+void cpu_init() {
+#   ifdef XMRIG_NO_LIBCPUID
+    cpu_info.total_logical_cpus = sysconf(_SC_NPROCESSORS_CONF);
+#   endif
+    
+    cpu_init_common();
+}
+
+
+int affine_to_cpu_mask(int id, unsigned long mask)
+{
+    return 0;
+}
diff --git a/mac/memory_mac.c b/mac/memory_mac.c
new file mode 100644
index 000000000..868ffb146
--- /dev/null
+++ b/mac/memory_mac.c
@@ -0,0 +1,47 @@
+/* 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 <mm_malloc.h>
+#include <sys/mman.h>
+
+#include "persistent_memory.h"
+#include "options.h"
+#include "utils/applog.h"
+
+char *persistent_memory;
+int persistent_memory_flags = 0;
+
+
+const char * persistent_memory_allocate() {
+    const int ratio = (opt_double_hash && opt_algo != ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
+    const int size = MEMORY * (opt_n_threads * ratio + 1);
+    
+    persistent_memory = _mm_malloc(size, 16);
+    return persistent_memory;
+}
+
+
+void persistent_memory_free() {
+    _mm_free(persistent_memory);
+}
diff --git a/mac/xmrig_mac.c b/mac/xmrig_mac.c
new file mode 100644
index 000000000..f7278c6db
--- /dev/null
+++ b/mac/xmrig_mac.c
@@ -0,0 +1,91 @@
+/* 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 <signal.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "options.h"
+#include "cpu.h"
+#include "utils/applog.h"
+
+
+static void signal_handler(int sig)
+{
+    switch (sig) {
+        case SIGHUP:
+            applog(LOG_WARNING, "SIGHUP received");
+            break;
+            
+        case SIGINT:
+            applog(LOG_WARNING, "SIGINT received, exiting");
+            proper_exit(0);
+            break;
+            
+        case SIGTERM:
+            applog(LOG_WARNING, "SIGTERM received, exiting");
+            proper_exit(0);
+            break;
+    }
+}
+
+
+void proper_exit(int reason) {
+    exit(reason);
+}
+
+
+void os_specific_init()
+{
+    if (opt_affinity != -1) {
+        affine_to_cpu_mask(-1, opt_affinity);
+    }
+    
+    if (opt_background) {
+        int i = fork();
+        if (i < 0) {
+            exit(1);
+        }
+        
+        if (i > 0) {
+            exit(0);
+        }
+        
+        i = setsid();
+        
+        if (i < 0) {
+            applog(LOG_ERR, "setsid() failed (errno = %d)", errno);
+        }
+        
+        i = chdir("/");
+        if (i < 0) {
+            applog(LOG_ERR, "chdir() failed (errno = %d)", errno);
+        }
+        
+        signal(SIGHUP, signal_handler);
+        signal(SIGTERM, signal_handler);
+    }
+    
+    signal(SIGINT, signal_handler);
+}
diff --git a/memory.c b/memory.c
index 2032a2548..112f11153 100644
--- a/memory.c
+++ b/memory.c
@@ -38,12 +38,12 @@ static void * create_persistent_ctx_lite(int thr_id) {
         const size_t offset = MEMORY * (thr_id + 1);
 
         ctx = (struct cryptonight_ctx *) &persistent_memory[offset + MEMORY_LITE];
-        ctx->memory = &persistent_memory[offset];
+        ctx->memory = (uint8_t*) &persistent_memory[offset];
         return ctx;
     }
 
     ctx = (struct cryptonight_ctx *) &persistent_memory[MEMORY - sizeof(struct cryptonight_ctx) * (thr_id + 1)];
-    ctx->memory = &persistent_memory[MEMORY * (thr_id + 1)];
+    ctx->memory = (uint8_t*) &persistent_memory[MEMORY * (thr_id + 1)];
 
     return ctx;
 }
@@ -70,7 +70,7 @@ void * create_persistent_ctx(int thr_id) {
     struct cryptonight_ctx *ctx = (struct cryptonight_ctx *) &persistent_memory[MEMORY - sizeof(struct cryptonight_ctx) * (thr_id + 1)];
 
     const int ratio = opt_double_hash ? 2 : 1;
-    ctx->memory = &persistent_memory[MEMORY * (thr_id * ratio + 1)];
+    ctx->memory = (uint8_t*) &persistent_memory[MEMORY * (thr_id * ratio + 1)];
 
     return ctx;
 }
diff --git a/stratum.c b/stratum.c
index 1f2a4b8e6..4e9372519 100644
--- a/stratum.c
+++ b/stratum.c
@@ -36,6 +36,10 @@
 #   include <poll.h>
 #endif
 
+#ifdef __APPLE_CC__
+#   include <netinet/in.h>
+#endif
+
 #include "stratum.h"
 #include "version.h"
 #include "stats.h"
@@ -537,31 +541,36 @@ static int sockopt_keepalive_cb(void *userdata, curl_socket_t fd, curlsocktype p
     int tcp_keepintvl = 50;
 
 #ifndef WIN32
-    if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
-        sizeof(keepalive))))
+    if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)))) {
         return 1;
-#ifdef __linux
-    if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT,
-        &tcp_keepcnt, sizeof(tcp_keepcnt))))
+    }
+    
+#   ifdef __linux
+    if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_keepcnt, sizeof(tcp_keepcnt)))) {
         return 1;
-    if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE,
-        &tcp_keepidle, sizeof(tcp_keepidle))))
+    }
+    
+    if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle)))) {
         return 1;
-    if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL,
-        &tcp_keepintvl, sizeof(tcp_keepintvl))))
+    }
+    
+    if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl)))) {
         return 1;
-#endif /* __linux */
-#ifdef __APPLE_CC__
-    if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE,
-        &tcp_keepintvl, sizeof(tcp_keepintvl))))
+    }
+#   endif /* __linux */
+    
+#   ifdef __APPLE_CC__
+    if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepintvl, sizeof(tcp_keepintvl)))) {
         return 1;
-#endif /* __APPLE_CC__ */
+    }
+#   endif /* __APPLE_CC__ */
 #else /* WIN32 */
     struct tcp_keepalive vals;
     vals.onoff = 1;
     vals.keepalivetime = tcp_keepidle * 1000;
     vals.keepaliveinterval = tcp_keepintvl * 1000;
     DWORD outputBytes;
+    
     if (unlikely(WSAIoctl(fd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals), NULL, 0, &outputBytes, NULL, NULL))) {
         return 1;
     }
diff --git a/version.h b/version.h
index 6b453bdbe..330d96975 100644
--- a/version.h
+++ b/version.h
@@ -27,14 +27,14 @@
 #define APP_ID        "xmrig"
 #define APP_NAME      "XMRig"
 #define APP_DESC      "Monero (XMR) CPU miner"
-#define APP_VERSION   "0.8.2"
+#define APP_VERSION   "0.8.3"
 #define APP_DOMAIN    "xmrig.com"
 #define APP_SITE      "www.xmrig.com"
 #define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com"
 
 #define APP_VER_MAJOR  0
 #define APP_VER_MINOR  8
-#define APP_VER_BUILD  2
+#define APP_VER_BUILD  3
 #define APP_VER_REV    0
 
 #endif /* __VERSION_H__ */

From 8a70202a98620fe007734a0b5317acb5ee27f9e3 Mon Sep 17 00:00:00 2001
From: XMRig <xmrig@bunkr.org>
Date: Sat, 27 May 2017 08:45:11 +0300
Subject: [PATCH 06/56] Fix.

---
 unix/memory_unix.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/unix/memory_unix.c b/unix/memory_unix.c
index fad7f730e..2e794a037 100644
--- a/unix/memory_unix.c
+++ b/unix/memory_unix.c
@@ -21,9 +21,6 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __MEMORY_H__
-#define __MEMORY_H__
-
 #include <stdlib.h>
 #include <mm_malloc.h>
 #include <sys/mman.h>
@@ -45,7 +42,7 @@ const char * persistent_memory_allocate() {
     persistent_memory = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0);
 
     if (persistent_memory == MAP_FAILED) {
-        persistent_memory = _mm_malloc(size, 4096);
+        persistent_memory = _mm_malloc(size, 16);
         return persistent_memory;
     }
 
@@ -77,6 +74,3 @@ void persistent_memory_free() {
         _mm_free(persistent_memory);
     }
 }
-
-
-#endif /* __MEMORY_H__ */

From 7741c341c71a50ab1c19fb33fe529a8cdc936e5e Mon Sep 17 00:00:00 2001
From: Admin <admin@mac-admin.local>
Date: Sat, 27 May 2017 10:34:42 +0300
Subject: [PATCH 07/56] Huge pages support on OS X.

---
 CMakeLists.txt   |  8 +++++++-
 mac/memory_mac.c | 33 +++++++++++++++++++++++++++++++--
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 39465124c..9d30acd3e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -87,7 +87,13 @@ if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
 endif()
 
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wno-pointer-to-int-cast")
-set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
+
+if (CMAKE_C_COMPILER_ID MATCHES "Clang")
+    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -fmerge-all-constants")
+else()
+    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
+endif()
+
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-use -fprofile-correction")
diff --git a/mac/memory_mac.c b/mac/memory_mac.c
index 868ffb146..3f5f714cb 100644
--- a/mac/memory_mac.c
+++ b/mac/memory_mac.c
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <mm_malloc.h>
 #include <sys/mman.h>
+#include <mach/vm_statistics.h>
 
 #include "persistent_memory.h"
 #include "options.h"
@@ -36,12 +37,40 @@ int persistent_memory_flags = 0;
 const char * persistent_memory_allocate() {
     const int ratio = (opt_double_hash && opt_algo != ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
     const int size = MEMORY * (opt_n_threads * ratio + 1);
+    persistent_memory_flags |= MEMORY_HUGEPAGES_AVAILABLE;
+    
+    persistent_memory = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
+    
+    if (persistent_memory == MAP_FAILED) {
+        persistent_memory = _mm_malloc(size, 16);
+        return persistent_memory;
+    }
+    
+    persistent_memory_flags |= MEMORY_HUGEPAGES_ENABLED;
+    
+    if (madvise(persistent_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0) {
+        applog(LOG_ERR, "madvise failed");
+    }
+    
+    if (mlock(persistent_memory, size) == 0) {
+        persistent_memory_flags |= MEMORY_LOCK;
+    }
     
-    persistent_memory = _mm_malloc(size, 16);
     return persistent_memory;
 }
 
 
 void persistent_memory_free() {
-    _mm_free(persistent_memory);
+    const int size = MEMORY * (opt_n_threads + 1);
+    
+    if (persistent_memory_flags & MEMORY_HUGEPAGES_ENABLED) {
+        if (persistent_memory_flags & MEMORY_LOCK) {
+            munlock(persistent_memory, size);
+        }
+        
+        munmap(persistent_memory, size);
+    }
+    else {
+        _mm_free(persistent_memory);
+    }
 }

From 668b23c5b00e3e6de1e263693222c3af6addd976 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Sun, 4 Jun 2017 20:52:21 +0300
Subject: [PATCH 08/56] Initial libuv support build.

---
 .gitignore                                    |   1 +
 CMakeLists.txt                                | 153 ++-----
 cmake/FindUV.cmake                            |   8 +
 {win => res}/app.ico                          | Bin
 {win => res}/app.rc                           |   2 +-
 .../3rdparty}/jansson/CMakeLists.txt          |   2 +
 {compat => src/3rdparty}/jansson/LICENSE      |   0
 {compat => src/3rdparty}/jansson/dump.c       |  64 ++-
 {compat => src/3rdparty}/jansson/error.c      |   0
 {compat => src/3rdparty}/jansson/hashtable.c  |   0
 {compat => src/3rdparty}/jansson/hashtable.h  |   0
 .../3rdparty}/jansson/hashtable_seed.c        |   4 +-
 {compat => src/3rdparty}/jansson/jansson.h    |   8 +-
 .../3rdparty}/jansson/jansson_config.h        |   0
 .../3rdparty}/jansson/jansson_private.h       |   1 +
 .../jansson/jansson_private_config.h          |   0
 {compat => src/3rdparty}/jansson/load.c       |  49 +-
 {compat => src/3rdparty}/jansson/lookup3.h    |   0
 {compat => src/3rdparty}/jansson/memory.c     |   0
 .../3rdparty}/jansson/pack_unpack.c           |   0
 {compat => src/3rdparty}/jansson/strbuffer.c  |   0
 {compat => src/3rdparty}/jansson/strbuffer.h  |   0
 {compat => src/3rdparty}/jansson/strconv.c    |   0
 {compat => src/3rdparty}/jansson/utf.c        |   0
 {compat => src/3rdparty}/jansson/utf.h        |   0
 {compat => src/3rdparty}/jansson/value.c      |   0
 compat/winansi.c => src/3rdparty/winansi.cpp  |   8 +-
 {compat => src/3rdparty}/winansi.h            |   5 +-
 src/App.cpp                                   |  84 ++++
 utils/threads.h => src/App.h                  |  37 +-
 src/Console.cpp                               | 139 ++++++
 src/Console.h                                 |  81 ++++
 src/Options.cpp                               | 433 ++++++++++++++++++
 src/Options.h                                 |  94 ++++
 donate.h => src/donate.h                      |   0
 src/interfaces/IClientListener.h              |  40 ++
 src/net/Client.cpp                            | 311 +++++++++++++
 src/net/Client.h                              |  87 ++++
 src/net/Network.cpp                           |  65 +++
 src/net/Network.h                             |  56 +++
 src/net/Network_win.cpp                       |  64 +++
 src/net/Url.cpp                               |  93 ++++
 src/net/Url.h                                 |  49 ++
 version.h => src/version.h                    |   8 +-
 src/xmrig.cpp                                 |  31 ++
 utils/applog.c                                | 151 ------
 utils/applog.h                                |  75 ---
 47 files changed, 1819 insertions(+), 384 deletions(-)
 create mode 100644 cmake/FindUV.cmake
 rename {win => res}/app.ico (100%)
 rename {win => res}/app.rc (96%)
 rename {compat => src/3rdparty}/jansson/CMakeLists.txt (91%)
 rename {compat => src/3rdparty}/jansson/LICENSE (100%)
 rename {compat => src/3rdparty}/jansson/dump.c (89%)
 rename {compat => src/3rdparty}/jansson/error.c (100%)
 rename {compat => src/3rdparty}/jansson/hashtable.c (100%)
 rename {compat => src/3rdparty}/jansson/hashtable.h (100%)
 rename {compat => src/3rdparty}/jansson/hashtable_seed.c (98%)
 rename {compat => src/3rdparty}/jansson/jansson.h (96%)
 rename {compat => src/3rdparty}/jansson/jansson_config.h (100%)
 rename {compat => src/3rdparty}/jansson/jansson_private.h (98%)
 rename {compat => src/3rdparty}/jansson/jansson_private_config.h (100%)
 rename {compat => src/3rdparty}/jansson/load.c (96%)
 rename {compat => src/3rdparty}/jansson/lookup3.h (100%)
 rename {compat => src/3rdparty}/jansson/memory.c (100%)
 rename {compat => src/3rdparty}/jansson/pack_unpack.c (100%)
 rename {compat => src/3rdparty}/jansson/strbuffer.c (100%)
 rename {compat => src/3rdparty}/jansson/strbuffer.h (100%)
 rename {compat => src/3rdparty}/jansson/strconv.c (100%)
 rename {compat => src/3rdparty}/jansson/utf.c (100%)
 rename {compat => src/3rdparty}/jansson/utf.h (100%)
 rename {compat => src/3rdparty}/jansson/value.c (100%)
 rename compat/winansi.c => src/3rdparty/winansi.cpp (98%)
 rename {compat => src/3rdparty}/winansi.h (92%)
 create mode 100644 src/App.cpp
 rename utils/threads.h => src/App.h (62%)
 create mode 100644 src/Console.cpp
 create mode 100644 src/Console.h
 create mode 100644 src/Options.cpp
 create mode 100644 src/Options.h
 rename donate.h => src/donate.h (100%)
 create mode 100644 src/interfaces/IClientListener.h
 create mode 100644 src/net/Client.cpp
 create mode 100644 src/net/Client.h
 create mode 100644 src/net/Network.cpp
 create mode 100644 src/net/Network.h
 create mode 100644 src/net/Network_win.cpp
 create mode 100644 src/net/Url.cpp
 create mode 100644 src/net/Url.h
 rename version.h => src/version.h (92%)
 create mode 100644 src/xmrig.cpp
 delete mode 100644 utils/applog.c
 delete mode 100644 utils/applog.h

diff --git a/.gitignore b/.gitignore
index 796b96d1c..189b414f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 /build
+/CMakeLists.txt.user
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9d30acd3e..1f485e11c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,99 +1,55 @@
 cmake_minimum_required(VERSION 3.0)
-project(xmrig C)
-
-option(WITH_LIBCPUID "Use Libcpuid" ON)
-option(WITH_AEON     "CryptoNight-Lite support" ON)
+project(xmrig)
 
 set(HEADERS
-    compat.h
-    algo/cryptonight/cryptonight.h
-    algo/cryptonight/cryptonight_aesni.h
-    algo/cryptonight/cryptonight_softaes.h
-    elist.h
-    xmrig.h
-    version.h
-    options.h
-    cpu.h
-    persistent_memory.h
-    stratum.h
-    stats.h
-    util.h
-    donate.h
-   )
-
-set(HEADERS_CRYPTO
-    crypto/c_groestl.h
-    crypto/c_blake256.h
-    crypto/c_jh.h
-    crypto/c_skein.h
-   )
-
-set(HEADERS_COMPAT
-    compat/winansi.h
-   )
-
-set(HEADERS_UTILS
-    utils/applog.h
-    utils/threads.h
-    utils/summary.h
+    src/App.h
+    src/interfaces/IClientListener.h
+    src/net/Client.h
+    src/net/Network.h
+    src/net/Url.h
+    src/Options.h
+    src/Console.h
+    src/version.h
    )
 
 set(SOURCES
-    xmrig.c
-    algo/cryptonight/cryptonight.c
-    algo/cryptonight/cryptonight_av1_aesni.c
-    algo/cryptonight/cryptonight_av2_aesni_double.c
-    algo/cryptonight/cryptonight_av3_softaes.c
-    algo/cryptonight/cryptonight_av4_softaes_double.c
-    util.c
-    options.c
-    stratum.c
-    stats.c
-    memory.c
-   )
-
-set(SOURCES_CRYPTO
-    crypto/c_keccak.c
-    crypto/c_groestl.c
-    crypto/c_blake256.c
-    crypto/c_jh.c
-    crypto/c_skein.c
-    crypto/soft_aes.c
-   )
-
-set(SOURCES_UTILS
-    utils/applog.c
-    utils/summary.c
+    src/App.cpp
+    src/net/Client.cpp
+    src/net/Network.cpp
+    src/net/Url.cpp
+    src/Options.cpp
+    src/Console.cpp
+    src/xmrig.cpp
    )
 
 if (WIN32)
-    set(SOURCES_OS win/cpu_win.c win/memory_win.c win/xmrig_win.c win/app.rc compat/winansi.c)
-    set(EXTRA_LIBS ws2_32)
-    add_definitions(/D_WIN32_WINNT=0x600)
-elseif (APPLE)
-    set(SOURCES_OS mac/cpu_mac.c mac/memory_mac.c mac/xmrig_mac.c)
+    set(SOURCES_OS
+        res/app.rc
+        src/3rdparty/winansi.cpp
+        src/3rdparty/winansi.h
+        src/net/Network_win.cpp
+        )
+
+    set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
 else()
     set(SOURCES_OS unix/cpu_unix.c unix/memory_unix.c unix/xmrig_unix.c)
     set(EXTRA_LIBS pthread)
 endif()
 
-include_directories(.)
-add_definitions(/DUSE_NATIVE_THREADS)
 add_definitions(/D_GNU_SOURCE)
 add_definitions(/DUNICODE)
+add_definitions(/DAPP_DEBUG)
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
+
+find_package(UV REQUIRED)
 
 if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
     set(CMAKE_BUILD_TYPE Release)
 endif()
 
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wno-pointer-to-int-cast")
-
-if (CMAKE_C_COMPILER_ID MATCHES "Clang")
-    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -fmerge-all-constants")
-else()
-    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
-endif()
-
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall")
+set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-use -fprofile-correction")
@@ -102,45 +58,12 @@ if (WIN32)
     set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
 endif()
 
-include_directories(compat/jansson)
-add_subdirectory(compat/jansson)
+include_directories(src)
+include_directories(src/3rdparty)
+include_directories(src/3rdparty/jansson)
+include_directories(${UV_INCLUDE_DIR})
 
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
-
-find_package(CURL REQUIRED)
-include_directories(${CURL_INCLUDE_DIRS})
-add_definitions(/DCURL_STATICLIB)
-link_directories(${CURL_LIBRARIES})
-
-if (WITH_LIBCPUID)
-    add_subdirectory(compat/libcpuid)
-
-    include_directories(compat/libcpuid)
-    set(CPUID_LIB cpuid)
-    set(SOURCES_CPUID cpu.c)
-else()
-    add_definitions(/DXMRIG_NO_LIBCPUID)
-    set(SOURCES_CPUID cpu_stub.c)
-endif()
-
-if (WITH_AEON)
-    set(SOURCES_AEON
-    algo/cryptonight-lite/cryptonight_lite_av1_aesni.c
-    algo/cryptonight-lite/cryptonight_lite_av2_aesni_double.c
-    algo/cryptonight-lite/cryptonight_lite_av3_softaes.c
-    algo/cryptonight-lite/cryptonight_lite_av4_softaes_double.c
-    algo/cryptonight-lite/cryptonight_lite_aesni.h
-    algo/cryptonight-lite/cryptonight_lite_softaes.h
-    )
-else()
-    add_definitions(/DXMRIG_NO_AEON)
-endif()
-
-if (CMAKE_SIZEOF_VOID_P EQUAL 8)
-    add_executable(xmrig ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${SOURCES_CPUID} ${SOURCES_AEON})
-    target_link_libraries(xmrig jansson curl ${CPUID_LIB} ${EXTRA_LIBS})
-else()
-    add_executable(xmrig32 ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${SOURCES_CPUID} ${SOURCES_AEON})
-    target_link_libraries(xmrig32 jansson curl ${CPUID_LIB} ${EXTRA_LIBS})
-endif()
+add_subdirectory(src/3rdparty/jansson)
 
+add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS})
+target_link_libraries(xmrig jansson ${UV_LIBRARIES} ${EXTRA_LIBS})
diff --git a/cmake/FindUV.cmake b/cmake/FindUV.cmake
new file mode 100644
index 000000000..c8a95e7ad
--- /dev/null
+++ b/cmake/FindUV.cmake
@@ -0,0 +1,8 @@
+find_path(UV_INCLUDE_DIR NAMES uv.h)
+find_library(UV_LIBRARY NAMES libuv)
+
+set(UV_LIBRARIES ${UV_LIBRARY})
+set(UV_INCLUDE_DIRS ${UV_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(UV DEFAULT_MSG UV_LIBRARY UV_INCLUDE_DIR)
diff --git a/win/app.ico b/res/app.ico
similarity index 100%
rename from win/app.ico
rename to res/app.ico
diff --git a/win/app.rc b/res/app.rc
similarity index 96%
rename from win/app.rc
rename to res/app.rc
index cb47aa3ca..800ce2dd5 100644
--- a/win/app.rc
+++ b/res/app.rc
@@ -1,5 +1,5 @@
 #include <windows.h>
-#include "../version.h"
+#include "../src/version.h"
 
 IDI_ICON1    ICON    DISCARDABLE    "app.ico"
 
diff --git a/compat/jansson/CMakeLists.txt b/src/3rdparty/jansson/CMakeLists.txt
similarity index 91%
rename from compat/jansson/CMakeLists.txt
rename to src/3rdparty/jansson/CMakeLists.txt
index 9a73da225..7bd74c671 100644
--- a/compat/jansson/CMakeLists.txt
+++ b/src/3rdparty/jansson/CMakeLists.txt
@@ -6,6 +6,8 @@ add_definitions(-DHAVE_CONFIG_H)
 # Add the lib sources.
 file(GLOB JANSSON_SRC *.c)
 
+set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os")
+
 set(JANSSON_HDR_PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/hashtable.h
    ${CMAKE_CURRENT_SOURCE_DIR}/jansson_private.h
diff --git a/compat/jansson/LICENSE b/src/3rdparty/jansson/LICENSE
similarity index 100%
rename from compat/jansson/LICENSE
rename to src/3rdparty/jansson/LICENSE
diff --git a/compat/jansson/dump.c b/src/3rdparty/jansson/dump.c
similarity index 89%
rename from compat/jansson/dump.c
rename to src/3rdparty/jansson/dump.c
index 6b1aabd45..a23fabb7c 100644
--- a/compat/jansson/dump.c
+++ b/src/3rdparty/jansson/dump.c
@@ -9,13 +9,17 @@
 #define _GNU_SOURCE
 #endif
 
+#include "jansson_private.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 #include "jansson.h"
-#include "jansson_private.h"
 #include "strbuffer.h"
 #include "utf.h"
 
@@ -25,11 +29,28 @@
 #define FLAGS_TO_INDENT(f)      ((f) & 0x1F)
 #define FLAGS_TO_PRECISION(f)   (((f) >> 11) & 0x1F)
 
+struct buffer {
+    const size_t size;
+    size_t used;
+    char *data;
+};
+
 static int dump_to_strbuffer(const char *buffer, size_t size, void *data)
 {
     return strbuffer_append_bytes((strbuffer_t *)data, buffer, size);
 }
 
+static int dump_to_buffer(const char *buffer, size_t size, void *data)
+{
+    struct buffer *buf = (struct buffer *)data;
+
+    if(buf->used + size <= buf->size)
+        memcpy(&buf->data[buf->used], buffer, size);
+
+    buf->used += size;
+    return 0;
+}
+
 static int dump_to_file(const char *buffer, size_t size, void *data)
 {
     FILE *dest = (FILE *)data;
@@ -38,6 +59,16 @@ static int dump_to_file(const char *buffer, size_t size, void *data)
     return 0;
 }
 
+static int dump_to_fd(const char *buffer, size_t size, void *data)
+{
+    int *dest = (int *)data;
+#ifdef HAVE_UNISTD_H
+    if(write(*dest, buffer, size) == (ssize_t)size)
+        return 0;
+#endif
+    return -1;
+}
+
 /* 32 spaces (the maximum indentation size) */
 static const char whitespace[] = "                                ";
 
@@ -168,6 +199,10 @@ static int compare_keys(const void *key1, const void *key2)
 static int do_dump(const json_t *json, size_t flags, int depth,
                    json_dump_callback_t dump, void *data)
 {
+    int embed = flags & JSON_EMBED;
+
+    flags &= ~JSON_EMBED;
+
     if(!json)
         return -1;
 
@@ -227,11 +262,11 @@ static int do_dump(const json_t *json, size_t flags, int depth,
 
             n = json_array_size(json);
 
-            if(dump("[", 1, data))
+            if(!embed && dump("[", 1, data))
                 goto array_error;
             if(n == 0) {
                 array->visited = 0;
-                return dump("]", 1, data);
+                return embed ? 0 : dump("]", 1, data);
             }
             if(dump_indent(flags, depth + 1, 0, dump, data))
                 goto array_error;
@@ -255,7 +290,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
             }
 
             array->visited = 0;
-            return dump("]", 1, data);
+            return embed ? 0 : dump("]", 1, data);
 
         array_error:
             array->visited = 0;
@@ -286,11 +321,11 @@ static int do_dump(const json_t *json, size_t flags, int depth,
 
             iter = json_object_iter((json_t *)json);
 
-            if(dump("{", 1, data))
+            if(!embed && dump("{", 1, data))
                 goto object_error;
             if(!iter) {
                 object->visited = 0;
-                return dump("}", 1, data);
+                return embed ? 0 : dump("}", 1, data);
             }
             if(dump_indent(flags, depth + 1, 0, dump, data))
                 goto object_error;
@@ -386,7 +421,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
             }
 
             object->visited = 0;
-            return dump("}", 1, data);
+            return embed ? 0 : dump("}", 1, data);
 
         object_error:
             object->visited = 0;
@@ -416,11 +451,26 @@ char *json_dumps(const json_t *json, size_t flags)
     return result;
 }
 
+size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags)
+{
+    struct buffer buf = { size, 0, buffer };
+
+    if(json_dump_callback(json, dump_to_buffer, (void *)&buf, flags))
+        return 0;
+
+    return buf.used;
+}
+
 int json_dumpf(const json_t *json, FILE *output, size_t flags)
 {
     return json_dump_callback(json, dump_to_file, (void *)output, flags);
 }
 
+int json_dumpfd(const json_t *json, int output, size_t flags)
+{
+    return json_dump_callback(json, dump_to_fd, (void *)&output, flags);
+}
+
 int json_dump_file(const json_t *json, const char *path, size_t flags)
 {
     int result;
diff --git a/compat/jansson/error.c b/src/3rdparty/jansson/error.c
similarity index 100%
rename from compat/jansson/error.c
rename to src/3rdparty/jansson/error.c
diff --git a/compat/jansson/hashtable.c b/src/3rdparty/jansson/hashtable.c
similarity index 100%
rename from compat/jansson/hashtable.c
rename to src/3rdparty/jansson/hashtable.c
diff --git a/compat/jansson/hashtable.h b/src/3rdparty/jansson/hashtable.h
similarity index 100%
rename from compat/jansson/hashtable.h
rename to src/3rdparty/jansson/hashtable.h
diff --git a/compat/jansson/hashtable_seed.c b/src/3rdparty/jansson/hashtable_seed.c
similarity index 98%
rename from compat/jansson/hashtable_seed.c
rename to src/3rdparty/jansson/hashtable_seed.c
index 751e0e326..8aed54068 100644
--- a/compat/jansson/hashtable_seed.c
+++ b/src/3rdparty/jansson/hashtable_seed.c
@@ -168,12 +168,12 @@ static uint32_t generate_seed() {
     int done = 0;
 
 #if !defined(_WIN32) && defined(USE_URANDOM)
-    if (!done && seed_from_urandom(&seed) == 0)
+    if (seed_from_urandom(&seed) == 0)
         done = 1;
 #endif
 
 #if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
-    if (!done && seed_from_windows_cryptoapi(&seed) == 0)
+    if (seed_from_windows_cryptoapi(&seed) == 0)
         done = 1;
 #endif
 
diff --git a/compat/jansson/jansson.h b/src/3rdparty/jansson/jansson.h
similarity index 96%
rename from compat/jansson/jansson.h
rename to src/3rdparty/jansson/jansson.h
index 591f2a944..a5927bd63 100644
--- a/compat/jansson/jansson.h
+++ b/src/3rdparty/jansson/jansson.h
@@ -21,11 +21,11 @@ extern "C" {
 /* version */
 
 #define JANSSON_MAJOR_VERSION  2
-#define JANSSON_MINOR_VERSION  9
+#define JANSSON_MINOR_VERSION  10
 #define JANSSON_MICRO_VERSION  0
 
 /* Micro version is omitted if it's 0 */
-#define JANSSON_VERSION  "2.9"
+#define JANSSON_VERSION  "2.10"
 
 /* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
    for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */
@@ -273,6 +273,7 @@ typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data);
 json_t *json_loads(const char *input, size_t flags, json_error_t *error);
 json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error);
 json_t *json_loadf(FILE *input, size_t flags, json_error_t *error);
+json_t *json_loadfd(int input, size_t flags, json_error_t *error);
 json_t *json_load_file(const char *path, size_t flags, json_error_t *error);
 json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error);
 
@@ -288,11 +289,14 @@ json_t *json_load_callback(json_load_callback_t callback, void *data, size_t fla
 #define JSON_ENCODE_ANY         0x200
 #define JSON_ESCAPE_SLASH       0x400
 #define JSON_REAL_PRECISION(n)  (((n) & 0x1F) << 11)
+#define JSON_EMBED              0x10000
 
 typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
 
 char *json_dumps(const json_t *json, size_t flags);
+size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags);
 int json_dumpf(const json_t *json, FILE *output, size_t flags);
+int json_dumpfd(const json_t *json, int output, size_t flags);
 int json_dump_file(const json_t *json, const char *path, size_t flags);
 int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags);
 
diff --git a/compat/jansson/jansson_config.h b/src/3rdparty/jansson/jansson_config.h
similarity index 100%
rename from compat/jansson/jansson_config.h
rename to src/3rdparty/jansson/jansson_config.h
diff --git a/compat/jansson/jansson_private.h b/src/3rdparty/jansson/jansson_private.h
similarity index 98%
rename from compat/jansson/jansson_private.h
rename to src/3rdparty/jansson/jansson_private.h
index 4a4927bb2..5ed961582 100644
--- a/compat/jansson/jansson_private.h
+++ b/src/3rdparty/jansson/jansson_private.h
@@ -8,6 +8,7 @@
 #ifndef JANSSON_PRIVATE_H
 #define JANSSON_PRIVATE_H
 
+#include "jansson_private_config.h"
 #include <stddef.h>
 #include "jansson.h"
 #include "hashtable.h"
diff --git a/compat/jansson/jansson_private_config.h b/src/3rdparty/jansson/jansson_private_config.h
similarity index 100%
rename from compat/jansson/jansson_private_config.h
rename to src/3rdparty/jansson/jansson_private_config.h
diff --git a/compat/jansson/load.c b/src/3rdparty/jansson/load.c
similarity index 96%
rename from compat/jansson/load.c
rename to src/3rdparty/jansson/load.c
index 7a8f96ecb..c212489a1 100644
--- a/compat/jansson/load.c
+++ b/src/3rdparty/jansson/load.c
@@ -9,15 +9,19 @@
 #define _GNU_SOURCE
 #endif
 
+#include "jansson_private.h"
+
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 #include "jansson.h"
-#include "jansson_private.h"
 #include "strbuffer.h"
 #include "utf.h"
 
@@ -340,7 +344,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
             /* control character */
             lex_unget_unsave(lex, c);
             if(c == '\n')
-                error_set(error, lex, "unexpected newline", c);
+                error_set(error, lex, "unexpected newline");
             else
                 error_set(error, lex, "control character 0x%x", c);
             goto out;
@@ -914,7 +918,7 @@ static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error)
 typedef struct
 {
     const char *data;
-    int pos;
+    size_t pos;
 } string_data_t;
 
 static int string_get(void *data)
@@ -1028,6 +1032,45 @@ json_t *json_loadf(FILE *input, size_t flags, json_error_t *error)
     return result;
 }
 
+static int fd_get_func(int *fd)
+{
+    uint8_t c;
+#ifdef HAVE_UNISTD_H
+    if (read(*fd, &c, 1) == 1)
+        return c;
+#endif
+    return EOF;
+}
+
+json_t *json_loadfd(int input, size_t flags, json_error_t *error)
+{
+    lex_t lex;
+    const char *source;
+    json_t *result;
+
+#ifdef HAVE_UNISTD_H
+    if(input == STDIN_FILENO)
+        source = "<stdin>";
+    else
+#endif
+        source = "<stream>";
+
+    jsonp_error_init(error, source);
+
+    if (input < 0) {
+        error_set(error, NULL, "wrong arguments");
+        return NULL;
+    }
+
+    if(lex_init(&lex, (get_func)fd_get_func, flags, &input))
+        return NULL;
+
+    result = parse_json(&lex, flags, error);
+
+    lex_close(&lex);
+    return result;
+}
+
 json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
 {
     json_t *result;
diff --git a/compat/jansson/lookup3.h b/src/3rdparty/jansson/lookup3.h
similarity index 100%
rename from compat/jansson/lookup3.h
rename to src/3rdparty/jansson/lookup3.h
diff --git a/compat/jansson/memory.c b/src/3rdparty/jansson/memory.c
similarity index 100%
rename from compat/jansson/memory.c
rename to src/3rdparty/jansson/memory.c
diff --git a/compat/jansson/pack_unpack.c b/src/3rdparty/jansson/pack_unpack.c
similarity index 100%
rename from compat/jansson/pack_unpack.c
rename to src/3rdparty/jansson/pack_unpack.c
diff --git a/compat/jansson/strbuffer.c b/src/3rdparty/jansson/strbuffer.c
similarity index 100%
rename from compat/jansson/strbuffer.c
rename to src/3rdparty/jansson/strbuffer.c
diff --git a/compat/jansson/strbuffer.h b/src/3rdparty/jansson/strbuffer.h
similarity index 100%
rename from compat/jansson/strbuffer.h
rename to src/3rdparty/jansson/strbuffer.h
diff --git a/compat/jansson/strconv.c b/src/3rdparty/jansson/strconv.c
similarity index 100%
rename from compat/jansson/strconv.c
rename to src/3rdparty/jansson/strconv.c
diff --git a/compat/jansson/utf.c b/src/3rdparty/jansson/utf.c
similarity index 100%
rename from compat/jansson/utf.c
rename to src/3rdparty/jansson/utf.c
diff --git a/compat/jansson/utf.h b/src/3rdparty/jansson/utf.h
similarity index 100%
rename from compat/jansson/utf.h
rename to src/3rdparty/jansson/utf.h
diff --git a/compat/jansson/value.c b/src/3rdparty/jansson/value.c
similarity index 100%
rename from compat/jansson/value.c
rename to src/3rdparty/jansson/value.c
diff --git a/compat/winansi.c b/src/3rdparty/winansi.cpp
similarity index 98%
rename from compat/winansi.c
rename to src/3rdparty/winansi.cpp
index 41cecd6ac..c6fbbc208 100644
--- a/compat/winansi.c
+++ b/src/3rdparty/winansi.cpp
@@ -11,7 +11,7 @@
 #include <stdio.h>
 #include <io.h>
 
-#include "compat/winansi.h"
+#include "winansi.h"
 /*
 * Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
 */
@@ -344,8 +344,8 @@ int winansi_vfprintf(FILE *stream, const char *format, va_list list)
 #endif
     va_end(cp);
 
-    if (len > sizeof(small_buf) - 1) {
-        buf = malloc(len + 1);
+    if ((unsigned) len > sizeof(small_buf) - 1) {
+        buf = (char*)malloc(len + 1);
         if (!buf)
             goto abort;
 
@@ -389,4 +389,4 @@ int winansi_printf(const char *format, ...)
     va_end(list);
 
     return rv;
-}
\ No newline at end of file
+}
diff --git a/compat/winansi.h b/src/3rdparty/winansi.h
similarity index 92%
rename from compat/winansi.h
rename to src/3rdparty/winansi.h
index 70c137348..47914c364 100644
--- a/compat/winansi.h
+++ b/src/3rdparty/winansi.h
@@ -1,12 +1,11 @@
 /*
  * ANSI emulation wrappers
  */
-#ifdef WIN32
+
 #include <windows.h>
 #include <stddef.h>
 #include <stdio.h>
 
-#define isatty(fd) _isatty(fd)
 #define fileno(fd) _fileno(fd)
 
 #ifdef __cplusplus
@@ -28,5 +27,3 @@ extern "C" {
 #define printf winansi_printf
 #define fprintf winansi_fprintf
 #define vfprintf winansi_vfprintf
-
-#endif
\ No newline at end of file
diff --git a/src/App.cpp b/src/App.cpp
new file mode 100644
index 000000000..ce9d2b2cd
--- /dev/null
+++ b/src/App.cpp
@@ -0,0 +1,84 @@
+/* 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 <uv.h>
+
+
+#include "App.h"
+#include "Console.h"
+#include "net/Client.h"
+#include "net/Network.h"
+#include "Options.h"
+#include "version.h"
+
+
+Client *client;
+uv_timer_t timer_req;
+
+
+void timer_cb(uv_timer_t* handle) {
+    LOG_DEBUG("TIMER");
+
+    client->disconnect();
+}
+
+
+App::App(int argc, char **argv)
+{
+    Console::init();
+    m_options = Options::parse(argc, argv);
+
+    m_network = new Network(m_options);
+}
+
+
+App::~App()
+{
+    LOG_DEBUG("~APP");
+
+    free(m_network);
+    free(m_options);
+}
+
+
+App::exec()
+{
+    if (!m_options->isReady()) {
+        return 0;
+    }
+
+    m_network->connect();
+
+//    uv_timer_init(uv_default_loop(), &timer_req);
+//    uv_timer_start(&timer_req, timer_cb, 5000, 5000);
+
+
+//    client = new Client();
+//    client->connect("192.168.2.34", 3333);
+
+    const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+    uv_loop_close(uv_default_loop());
+
+    return r;
+}
diff --git a/utils/threads.h b/src/App.h
similarity index 62%
rename from utils/threads.h
rename to src/App.h
index a2ef09f39..a6aef6fa1 100644
--- a/utils/threads.h
+++ b/src/App.h
@@ -21,21 +21,26 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __THREADS_H__
-#define __THREADS_H__
+#ifndef __APP_H__
+#define __APP_H__
 
-#if defined(WIN32) && defined(USE_NATIVE_THREADS)
-# include <windows.h>
-# define MUTEX               CRITICAL_SECTION
-# define MUTEX_INIT(mutex)   InitializeCriticalSection(&mutex)
-# define MUTEX_LOCK(mutex)   EnterCriticalSection(&mutex)
-# define MUTEX_UNLOCK(mutex) LeaveCriticalSection(&mutex)
-#else
-# include <pthread.h>
-# define MUTEX               pthread_mutex_t
-# define MUTEX_INIT(mutex)   pthread_mutex_init(&mutex, NULL)
-# define MUTEX_LOCK(mutex)   pthread_mutex_lock(&mutex)
-# define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(&mutex)
-#endif
 
-#endif /* __THREADS_H__ */
+class Options;
+class Network;
+
+
+class App
+{
+public:
+  App(int argc, char **argv);
+  ~App();
+
+  int exec();
+
+private:
+  Options *m_options;
+  Network *m_network;
+};
+
+
+#endif /* __APP_H__ */
diff --git a/src/Console.cpp b/src/Console.cpp
new file mode 100644
index 000000000..f57a71411
--- /dev/null
+++ b/src/Console.cpp
@@ -0,0 +1,139 @@
+/* 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 <time.h>
+
+#ifdef WIN32
+#   include <winsock2.h>
+#   include "3rdparty/winansi.h"
+#endif
+
+#include "Console.h"
+
+
+Console *Console::m_self = nullptr;
+
+
+void Console::init()
+{
+    if (!m_self) {
+        m_self = new Console();
+    }
+}
+
+
+void Console::message(Console::Level level, const char* fmt, ...)
+{
+    time_t now = time(nullptr);
+    tm stime;
+
+#   ifdef _WIN32
+    localtime_s(&stime, &now);
+#   else
+    localtime_r(&now, &stime);
+#   endif
+
+    va_list ap;
+    va_start(ap, fmt);
+
+    const char* color = nullptr;
+    if (m_colors) {
+        switch (level) {
+        case ERR:
+            color = kCL_RED;
+            break;
+
+        case WARNING:
+            color = kCL_YELLOW;
+            break;
+
+        case NOTICE:
+            color = kCL_WHITE;
+            break;
+
+        case DEBUG:
+            color = kCL_GRAY;
+            break;
+
+        default:
+            color = "";
+            break;
+        }
+    }
+
+    const size_t len = 64 + strlen(fmt) + 2;
+    char *buf = static_cast<char *>(alloca(len));
+
+    sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
+            stime.tm_year + 1900,
+            stime.tm_mon + 1,
+            stime.tm_mday,
+            stime.tm_hour,
+            stime.tm_min,
+            stime.tm_sec,
+            color,
+            fmt,
+            m_colors ? kCL_N : ""
+        );
+
+    uv_mutex_lock(&m_mutex);
+
+    vfprintf(stdout, buf, ap);
+    fflush(stdout);
+
+    uv_mutex_unlock(&m_mutex);
+
+    va_end(ap);
+}
+
+
+void Console::text(const char* fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+
+    const int len = 64 + strlen(fmt) + 2;
+    char *buf = static_cast<char *>(alloca(len));
+
+    sprintf(buf, "%s%s\n",
+            fmt,
+            m_colors ? kCL_N : ""
+        );
+
+    uv_mutex_lock(&m_mutex);
+
+    vfprintf(stdout, buf, ap);
+    fflush(stdout);
+
+    uv_mutex_unlock(&m_mutex);
+
+    va_end(ap);
+}
+
+
+Console::Console() :
+    m_colors(true)
+{
+    uv_mutex_init(&m_mutex);
+}
diff --git a/src/Console.h b/src/Console.h
new file mode 100644
index 000000000..a02e37612
--- /dev/null
+++ b/src/Console.h
@@ -0,0 +1,81 @@
+/* XMRig
+ * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
+ * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
+ * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
+ * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
+ * Copyright 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/>.
+ */
+
+#ifndef __CONSOLE_H__
+#define __CONSOLE_H__
+
+
+#include <uv.h>
+
+
+class Console
+{
+public:
+    enum Level {
+        ERR,
+        WARNING,
+        NOTICE,
+        INFO,
+        DEBUG
+    };
+
+    constexpr static const char* kCL_N      = "\x1B[0m";
+    constexpr static const char* kCL_RED    = "\x1B[31m";
+    constexpr static const char* kCL_YELLOW = "\x1B[33m";
+    constexpr static const char* kCL_WHITE  = "\x1B[01;37m";
+
+#   ifdef WIN32
+    constexpr static const char* kCL_GRAY = "\x1B[01;30m";
+#   else
+    constexpr static const char* kCL_GRAY = "\x1B[90m";
+#   endif
+
+    static inline Console* i() { return m_self; }
+    static void init();
+
+    void message(Level level, const char* fmt, ...);
+    void text(const char* fmt, ...);
+
+private:
+    Console();
+
+    static Console *m_self;
+    bool m_colors;
+    uv_mutex_t m_mutex;
+};
+
+
+#define LOG_ERR(x, ...)    Console::i()->message(Console::ERR,     x, ##__VA_ARGS__)
+#define LOG_WARN(x, ...)   Console::i()->message(Console::WARNING, x, ##__VA_ARGS__)
+#define LOG_NOTICE(x, ...) Console::i()->message(Console::NOTICE,  x, ##__VA_ARGS__)
+#define LOG_INFO(x, ...)   Console::i()->message(Console::INFO,    x, ##__VA_ARGS__)
+
+#ifdef APP_DEBUG
+#   define LOG_DEBUG(x, ...)     Console::i()->message(Console::DEBUG,   x, ##__VA_ARGS__)
+#   define LOG_DEBUG_ERR(x, ...) Console::i()->message(Console::ERR,     x, ##__VA_ARGS__)
+#else
+#   define LOG_DEBUG(x, ...)
+#   define LOG_DEBUG_ERR(x, ...)
+#endif
+
+#endif /* __CONSOLE_H__ */
diff --git a/src/Options.cpp b/src/Options.cpp
new file mode 100644
index 000000000..5a8551c41
--- /dev/null
+++ b/src/Options.cpp
@@ -0,0 +1,433 @@
+/* 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 <uv.h>
+#include <jansson.h>
+#include <getopt.h>
+
+
+#include "Console.h"
+#include "Options.h"
+#include "version.h"
+#include "donate.h"
+#include "net/Url.h"
+
+
+#ifndef ARRAY_SIZE
+#   define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+
+Options *Options::m_self = nullptr;
+
+
+static char const usage[] = "\
+Usage: " APP_ID " [OPTIONS]\n\
+Options:\n\
+  -a, --algo=ALGO       cryptonight (default) or cryptonight-lite\n\
+  -o, --url=URL         URL of mining server\n\
+  -b, --backup-url=URL  URL of backup mining server\n\
+  -O, --userpass=U:P    username:password pair for mining server\n\
+  -u, --user=USERNAME   username for mining server\n\
+  -p, --pass=PASSWORD   password for mining server\n\
+  -t, --threads=N       number of miner threads\n\
+  -v, --av=N            algorithm variation, 0 auto select\n\
+  -k, --keepalive       send keepalived for prevent timeout (need pool support)\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\
+      --no-color        disable colored output\n\
+      --donate-level=N  donate level, default 5%% (5 minutes in 100 minutes)\n\
+  -B, --background      run the miner in the background\n\
+  -c, --config=FILE     load a JSON-format configuration file\n\
+      --max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
+      --safe            safe adjust threads and av settings for current CPU\n\
+      --nicehash        enable nicehash support\n\
+  -h, --help            display this help and exit\n\
+  -V, --version         output version information and exit\n\
+";
+
+
+static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vb:";
+
+
+static struct option const options[] = {
+    { "algo",          1, nullptr, 'a'  },
+    { "av",            1, nullptr, 'v'  },
+    { "background",    0, nullptr, 'B'  },
+    { "backup-url",    1, nullptr, 'b'  },
+    { "config",        1, nullptr, 'c'  },
+    { "cpu-affinity",  1, nullptr, 1020 },
+    { "donate-level",  1, nullptr, 1003 },
+    { "help",          0, nullptr, 'h'  },
+    { "keepalive",     0, nullptr ,'k'  },
+    { "max-cpu-usage", 1, nullptr, 1004 },
+    { "nicehash",      0, nullptr, 1006 },
+    { "no-color",      0, nullptr, 1002 },
+    { "pass",          1, nullptr, 'p'  },
+    { "retries",       1, nullptr, 'r'  },
+    { "retry-pause",   1, nullptr, 'R'  },
+    { "safe",          0, nullptr, 1005 },
+    { "threads",       1, nullptr, 't'  },
+    { "url",           1, nullptr, 'o'  },
+    { "user",          1, nullptr, 'u'  },
+    { "userpass",      1, nullptr, 'O'  },
+    { "version",       0, nullptr, 'V'  },
+    { 0, 0, 0, 0 }
+};
+
+
+static const char *algo_names[] = {
+    "cryptonight",
+#   ifndef XMRIG_NO_AEON
+    "cryptonight-lite"
+#   endif
+};
+
+
+Options *Options::parse(int argc, char **argv)
+{
+    if (!m_self) {
+        m_self = new Options(argc, argv);
+    }
+
+    return m_self;
+}
+
+
+Options::Options(int argc, char **argv) :
+    m_background(false),
+    m_colors(true),
+    m_doubleHash(false),
+    m_keepalive(false),
+    m_nicehash(false),
+    m_ready(false),
+    m_safe(false),
+    m_pass(nullptr),
+    m_user(nullptr),
+    m_algo(0),
+    m_algoVariant(0),
+    m_donateLevel(DONATE_LEVEL),
+    m_maxCpuUsage(75),
+    m_retries(5),
+    m_retryPause(5),
+    m_threads(0),
+    m_affinity(-1L),
+    m_backupUrl(nullptr),
+    m_url(nullptr)
+{
+    int key;
+
+    while (1) {
+        key = getopt_long(argc, argv, short_options, options, NULL);
+        if (key < 0) {
+            break;
+        }
+
+        if (!parseArg(key, optarg)) {
+            return;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]);
+        return;
+    }
+
+    if (!m_url) {
+        LOG_ERR("No pool URL supplied. Exiting.", argv[0]);
+        return;
+    }
+
+    if (!m_nicehash && m_url->isNicehash()) {
+        m_nicehash = true;
+    }
+
+    if (!m_user) {
+        m_user = strdup("x");
+    }
+
+    if (!m_pass) {
+        m_pass = strdup("x");
+    }
+
+    m_ready = true;
+}
+
+
+Options::~Options()
+{
+    delete m_url;
+    delete m_backupUrl;
+
+    free(m_user);
+    free(m_pass);
+}
+
+
+bool Options::parseArg(int key, char *arg)
+{
+//    char *p;
+    int v;
+//    uint64_t ul;
+    Url *url;
+
+    switch (key) {
+    case 'a': /* --algo */
+        if (!setAlgo(arg)) {
+            return false;
+        }
+        break;
+
+    case 'O': /* --userpass */
+        if (!setUserpass(arg)) {
+            return false;
+        }
+        break;
+
+    case 'o': /* --url */
+        url = parseUrl(arg);
+        if (url) {
+            free(m_url);
+            m_url = url;
+        }
+        break;
+
+    case 'b': /* --backup-url */
+        url = parseUrl(arg);
+        if (url) {
+            free(m_backupUrl);
+            m_backupUrl = url;
+        }
+        break;
+
+    case 'u': /* --user */
+        free(m_user);
+        m_user = strdup(arg);
+        break;
+
+    case 'p': /* --pass */
+        free(m_pass);
+        m_pass = strdup(arg);
+        break;
+
+    case 'r': /* --retries */
+        v = atoi(arg);
+        if (v < 1 || v > 1000) {
+            showUsage(1);
+            return false;
+        }
+
+        m_retries = v;
+        break;
+
+    case 'R': /* --retry-pause */
+        v = atoi(arg);
+        if (v < 1 || v > 3600) {
+            showUsage(1);
+            return false;
+        }
+
+        m_retryPause = v;
+        break;
+
+    case 't': /* --threads */
+        v = atoi(arg);
+        if (v < 1 || v > 1024) {
+            showUsage(1);
+            return false;
+        }
+
+        m_threads = v;
+        break;
+
+    case 1004: /* --max-cpu-usage */
+        v = atoi(arg);
+        if (v < 1 || v > 100) {
+            showUsage(1);
+            return false;
+        }
+
+        m_maxCpuUsage = v;
+        break;
+
+    case 1005: /* --safe */
+        m_safe = true;
+        break;
+
+    case 'k': /* --keepalive */
+        m_keepalive = true;
+        break;
+
+    case 'V': /* --version */
+        showVersion();
+        return false;
+
+    case 'h': /* --help */
+        showUsage(0);
+        return false;
+
+    case 'B': /* --background */
+        m_background = true;
+        m_colors = false;
+        break;
+
+    case 'v': /* --av */
+        v = atoi(arg);
+        if (v < 0 || v > 1000) {
+            showUsage(1);
+            return false;
+        }
+
+        m_algoVariant = v;
+        break;
+
+    case 1020: /* --cpu-affinity */
+//        p  = strstr(arg, "0x");
+//        ul = p ? strtoul(p, NULL, 16) : atol(arg);
+//        if (ul > (1UL << cpu_info.total_logical_cpus) -1) {
+//            ul = -1;
+//        }
+
+//        opt_affinity = ul;
+        break;
+
+    case 1002: /* --no-color */
+        m_colors = false;
+        break;
+
+    case 1003: /* --donate-level */
+        v = atoi(arg);
+        if (v < 1 || v > 99) {
+            showUsage(1);
+            return false;
+        }
+
+        m_donateLevel = v;
+        break;
+
+    case 1006: /* --nicehash */
+        m_nicehash = true;
+        break;
+
+    default:
+        showUsage(1);
+        return false;
+    }
+
+    return true;
+}
+
+
+Url *Options::parseUrl(const char *arg) const
+{
+    auto url = new Url(arg);
+    if (!url->isValid()) {
+        delete url;
+        return nullptr;
+    }
+
+    return url;
+}
+
+
+void Options::showUsage(int status) const
+{
+    if (status) {
+        fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n");
+    }
+    else {
+        printf(usage);
+    }
+}
+
+
+void Options::showVersion()
+{
+    printf(APP_NAME " " APP_VERSION "\n built on " __DATE__
+
+    #ifdef __GNUC__
+    " with GCC");
+    printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
+    #endif
+
+    printf("\n features:"
+    #ifdef __i386__
+    " i386"
+    #endif
+    #ifdef __x86_64__
+    " x86_64"
+    #endif
+    #ifdef __AES__
+    " AES-NI"
+    #endif
+    "\n");
+
+    printf("\nlibuv/%s\n", uv_version_string());
+    printf("libjansson/%s\n", JANSSON_VERSION);
+}
+
+
+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;
+            break;
+        }
+
+#       ifndef XMRIG_NO_AEON
+        if (i == ARRAY_SIZE(algo_names) - 1 && !strcmp(algo, "cryptonight-light")) {
+            m_algo = ALGO_CRYPTONIGHT_LITE;
+            break;
+        }
+#       endif
+
+        if (i == ARRAY_SIZE(algo_names) - 1) {
+            showUsage(1);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+bool Options::setUserpass(const char *userpass)
+{
+    char *p = strchr(userpass, ':');
+    if (!p) {
+        showUsage(1);
+        return false;
+    }
+
+    free(m_user);
+    free(m_pass);
+
+    m_user = static_cast<char*>(calloc(p - userpass + 1, 1));
+    strncpy(m_user, userpass, p - userpass);
+    m_pass = strdup(p + 1);
+
+    return true;
+}
diff --git a/src/Options.h b/src/Options.h
new file mode 100644
index 000000000..eccfbcff3
--- /dev/null
+++ b/src/Options.h
@@ -0,0 +1,94 @@
+/* XMRig
+ * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
+ * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
+ * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
+ * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
+ * Copyright 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/>.
+ */
+
+#ifndef __OPTIONS_H__
+#define __OPTIONS_H__
+
+
+#include <stdint.h>
+
+
+class Url;
+
+
+class Options
+{
+public:
+    enum Algo {
+        ALGO_CRYPTONIGHT,      /* CryptoNight (Monero) */
+        ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */
+    };
+
+    enum AlgoVariant {
+        AV0_AUTO,
+        AV1_AESNI,
+        AV2_AESNI_DOUBLE,
+        AV3_SOFT_AES,
+        AV4_SOFT_AES_DOUBLE,
+        AV_MAX
+    };
+
+    static inline Options* i() { return m_self; }
+    static Options *parse(int argc, char **argv);
+
+    inline bool isReady() const     { return m_ready; }
+    inline const char *pass() const { return m_pass; }
+    inline const char *user() const { return m_user; }
+    inline Url *url() const         { return m_url; }
+
+private:
+    Options(int argc, char **argv);
+    ~Options();
+
+    static Options *m_self;
+
+    bool parseArg(int key, char *arg);
+    Url *parseUrl(const char *arg) const;
+    void showUsage(int status) const;
+    void showVersion(void);
+
+    bool setAlgo(const char *algo);
+    bool setUserpass(const char *userpass);
+
+    bool m_background;
+    bool m_colors;
+    bool m_doubleHash;
+    bool m_keepalive;
+    bool m_nicehash;
+    bool m_ready;
+    bool m_safe;
+    char *m_pass;
+    char *m_user;
+    int m_algo;
+    int m_algoVariant;
+    int m_donateLevel;
+    int m_maxCpuUsage;
+    int m_retries;
+    int m_retryPause;
+    int m_threads;
+    int64_t m_affinity;
+    Url *m_backupUrl;
+    Url *m_url;
+};
+
+#endif /* __OPTIONS_H__ */
diff --git a/donate.h b/src/donate.h
similarity index 100%
rename from donate.h
rename to src/donate.h
diff --git a/src/interfaces/IClientListener.h b/src/interfaces/IClientListener.h
new file mode 100644
index 000000000..26ff10aab
--- /dev/null
+++ b/src/interfaces/IClientListener.h
@@ -0,0 +1,40 @@
+/* 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/>.
+ */
+
+#ifndef __ICLIENTLISTENER_H__
+#define __ICLIENTLISTENER_H__
+
+
+class Client;
+
+
+class IClientListener
+{
+public:
+    virtual ~IClientListener() {}
+
+    virtual void onLoginCredentialsRequired(Client *client) = 0;
+};
+
+
+#endif // __ICLIENTLISTENER_H__
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
new file mode 100644
index 000000000..cb77ebadd
--- /dev/null
+++ b/src/net/Client.cpp
@@ -0,0 +1,311 @@
+/* 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 <jansson.h>
+
+
+#include "Console.h"
+#include "interfaces/IClientListener.h"
+#include "net/Client.h"
+#include "net/Url.h"
+
+
+Client::Client(IClientListener *listener) :
+    m_host(nullptr),
+    m_listener(listener),
+    m_recvBufPos(0),
+    m_state(UnconnectedState),
+    m_port(0),
+    m_stream(nullptr),
+    m_socket(nullptr)
+{
+    m_resolver.data = this;
+
+    m_hints.ai_family   = PF_INET;
+    m_hints.ai_socktype = SOCK_STREAM;
+    m_hints.ai_protocol = IPPROTO_TCP;
+    m_hints.ai_flags    = 0;
+
+    m_recvBuf.base = static_cast<char*>(malloc(kRecvBufSize));
+    m_recvBuf.len  = kRecvBufSize;
+}
+
+
+Client::~Client()
+{
+    free(m_recvBuf.base);
+    free(m_socket);
+    free(m_host);
+}
+
+
+/**
+ * @brief Connect to server.
+ *
+ * @param host
+ * @param port
+ */
+void Client::connect(const char *host, uint16_t port)
+{
+    m_host = strdup(host);
+    m_port = port;
+
+    LOG_DEBUG("[%s:%u] connect", m_host, m_port);
+
+    resolve(host);
+}
+
+
+/**
+ * @brief Connect to server.
+ *
+ * @param url
+ */
+void Client::connect(const Url *url)
+{
+    connect(url->host(), url->port());
+}
+
+
+void Client::disconnect()
+{
+    close();
+}
+
+
+void Client::login(const char *user, const char *pass, const char *agent)
+{
+    const size_t size = 96 + strlen(user) + strlen(pass) + strlen(agent);
+    char *req = static_cast<char*>(malloc(size));
+    snprintf(req, size, "{\"method\":\"login\",\"params\":{\"login\":\"%s\",\"pass\":\"%s\",\"agent\":\"%s\"},\"id\":1}\n", user, pass, agent);
+
+    send(req);
+}
+
+
+/**
+ * @brief Send raw data to server.
+ *
+ * @param data
+ */
+void Client::send(char *data)
+{
+    LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_host, m_port, strlen(data), data);
+    if (state() != ConnectedState) {
+        LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_host, m_port, m_state);
+        return;
+    }
+
+    uv_buf_t buf = uv_buf_init(data, strlen(data));
+
+    uv_write_t *req = static_cast<uv_write_t*>(malloc(sizeof(uv_write_t)));
+    req->data = buf.base;
+
+    uv_write(req, m_stream, &buf, 1, [](uv_write_t *req, int status) {
+        if (status) {
+            auto client = getClient(req->data);
+            LOG_ERR("[%s:%u] write error: \"%s\"", client->m_host, client->m_port, uv_strerror(status));
+        }
+
+        free(req->data);
+        free(req);
+    });
+}
+
+
+int Client::resolve(const char *host)
+{
+    setState(HostLookupState);
+
+    m_recvBufPos = 0;
+
+    const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints);
+    if (r) {
+        LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_port, uv_strerror(r));
+        return 1;
+    }
+
+    return 0;
+}
+
+
+void Client::close()
+{
+    if (m_state == UnconnectedState || m_state == ClosingState || !m_socket) {
+        return;
+    }
+
+    setState(ClosingState);
+    uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
+}
+
+
+void Client::connect(struct sockaddr *addr)
+{
+    setState(ConnectingState);
+
+    reinterpret_cast<struct sockaddr_in*>(addr)->sin_port = htons(m_port);
+    free(m_socket);
+
+    uv_connect_t *req = (uv_connect_t*) malloc(sizeof(uv_connect_t));
+    req->data = this;
+
+    m_socket = static_cast<uv_tcp_t*>(malloc(sizeof(uv_tcp_t)));
+    m_socket->data = this;
+
+    uv_tcp_init(uv_default_loop(), m_socket);
+    uv_tcp_nodelay(m_socket, 1);
+    uv_tcp_keepalive(m_socket, 1, 60);
+
+    uv_tcp_connect(req, m_socket, (const sockaddr*) addr, Client::onConnect);
+}
+
+
+void Client::parse(char *line, size_t len)
+{
+    line[len - 1] = '\0';
+
+    LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_host, m_port, len, line);
+
+    json_error_t err;
+    json_t *val = json_loads(line, 0, &err);
+
+    if (!val) {
+        LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_host, m_port, err.text);
+        return;
+    }
+}
+
+
+void Client::setState(SocketState state)
+{
+    LOG_DEBUG("[%s:%u] state: %d", m_host, m_port, state);
+
+    if (m_state == state) {
+        return;
+    }
+
+    m_state = state;
+}
+
+
+void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
+{
+    auto client = getClient(handle->data);
+
+    buf->base = &client->m_recvBuf.base[client->m_recvBufPos];
+    buf->len  = client->m_recvBuf.len - client->m_recvBufPos;
+}
+
+
+void Client::onClose(uv_handle_t *handle)
+{
+    auto client = getClient(handle->data);
+
+    free(client->m_socket);
+
+    client->m_stream = nullptr;
+    client->m_socket = nullptr;
+    client->setState(UnconnectedState);
+}
+
+
+void Client::onConnect(uv_connect_t *req, int status)
+{
+    auto client = getClient(req->data);
+    if (status < 0) {
+        LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_host, client->m_port, uv_strerror(status));
+        free(req);
+        return;
+    }
+
+    client->m_stream = static_cast<uv_stream_t*>(req->handle);
+    client->m_stream->data = req->data;
+    client->setState(ConnectedState);
+
+    uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead);
+    free(req);
+
+    client->m_listener->onLoginCredentialsRequired(client);
+}
+
+
+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) {
+            LOG_ERR("[%s:%u] read error: \"%s\"", client->m_host, client->m_port, uv_strerror(nread));
+        }
+
+        client->close();
+        return;
+    }
+
+    client->m_recvBufPos += nread;
+
+    char* end;
+    char* start = client->m_recvBuf.base;
+    size_t remaining = client->m_recvBufPos;
+
+    while ((end = static_cast<char*>(memchr(start, '\n', remaining))) != nullptr) {
+        end++;
+        size_t len = end - start;
+        client->parse(start, len);
+
+        remaining -= len;
+        start = end;
+    }
+
+    if (remaining == 0) {
+        client->m_recvBufPos = 0;
+        return;
+    }
+
+    if (start == client->m_recvBuf.base) {
+        return;
+    }
+
+    memcpy(client->m_recvBuf.base, start, remaining);
+    client->m_recvBufPos = remaining;
+}
+
+
+void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
+{
+    auto client = getClient(req->data);
+    if (status < 0) {
+        LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_host, client->m_port, uv_strerror(status));
+        return;
+    }
+
+    client->connect(res->ai_addr);
+    uv_freeaddrinfo(res);
+}
+
+
+Client *Client::getClient(void *data)
+{
+    return static_cast<Client*>(data);
+}
diff --git a/src/net/Client.h b/src/net/Client.h
new file mode 100644
index 000000000..181ea6419
--- /dev/null
+++ b/src/net/Client.h
@@ -0,0 +1,87 @@
+/* XMRig
+ * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
+ * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
+ * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
+ * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
+ * Copyright 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/>.
+ */
+
+#ifndef __CLIENT_H__
+#define __CLIENT_H__
+
+
+#include <uv.h>
+
+
+class Url;
+class IClientListener;
+
+
+class Client
+{
+public:
+    enum SocketState {
+        UnconnectedState,
+        HostLookupState,
+        ConnectingState,
+        ConnectedState,
+        ClosingState
+    };
+
+    Client(IClientListener *listener);
+    ~Client();
+
+    void connect(const char *host, uint16_t port);
+    void connect(const Url *url);
+    void disconnect();
+    void login(const char *user, const char *pass, const char *agent);
+    void send(char *data);
+
+    inline SocketState state() const { return m_state; }
+
+private:
+    constexpr static size_t kRecvBufSize = 4096;
+
+    int resolve(const char *host);
+    void close();
+    void connect(struct sockaddr *addr);
+    void parse(char *line, size_t len);
+    void setState(SocketState state);
+
+    static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
+    static void onClose(uv_handle_t *handle);
+    static void onConnect(uv_connect_t *req, int status);
+    static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
+    static void onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res);
+
+    static Client *getClient(void *data);
+
+    char *m_host;
+    IClientListener *m_listener;
+    size_t m_recvBufPos;
+    SocketState m_state;
+    struct addrinfo m_hints;
+    uint16_t m_port;
+    uv_buf_t m_recvBuf;
+    uv_getaddrinfo_t m_resolver;
+    uv_stream_t *m_stream;
+    uv_tcp_t *m_socket;
+};
+
+
+#endif /* __CLIENT_H__ */
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
new file mode 100644
index 000000000..91b626211
--- /dev/null
+++ b/src/net/Network.cpp
@@ -0,0 +1,65 @@
+/* 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 <uv.h>
+
+
+#include "Console.h"
+#include "net/Client.h"
+#include "net/Network.h"
+#include "Options.h"
+
+
+Network::Network(const Options *options) :
+    m_backupPool(nullptr),
+    m_donatePool(nullptr),
+    m_pool(nullptr),
+    m_options(options)
+{
+    m_agent = userAgent();
+    m_pool = new Client(this);
+}
+
+
+Network::~Network()
+{
+    delete m_pool;
+    delete m_donatePool;
+    delete m_backupPool;
+
+    free(m_agent);
+}
+
+
+void Network::connect()
+{
+    m_pool->connect(m_options->url());
+//    LOG_DEBUG("XX %s", m_options->url());
+}
+
+
+void Network::onLoginCredentialsRequired(Client *client)
+{
+    client->login(m_options->user(), m_options->pass(), m_agent);
+}
diff --git a/src/net/Network.h b/src/net/Network.h
new file mode 100644
index 000000000..5ee7c295d
--- /dev/null
+++ b/src/net/Network.h
@@ -0,0 +1,56 @@
+/* XMRig
+ * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
+ * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
+ * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
+ * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
+ * Copyright 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/>.
+ */
+
+#ifndef __NETWORK_H__
+#define __NETWORK_H__
+
+
+#include "interfaces/IClientListener.h"
+
+
+class Options;
+
+
+class Network : public IClientListener
+{
+public:
+  Network(const Options *options);
+  ~Network();
+
+  void connect();
+
+  static char *userAgent();
+
+protected:
+  void onLoginCredentialsRequired(Client *client) override;
+
+private:
+  char *m_agent;
+  Client *m_backupPool;
+  Client *m_donatePool;
+  Client *m_pool;
+  const Options *m_options;
+};
+
+
+#endif /* __NETWORK_H__ */
diff --git a/src/net/Network_win.cpp b/src/net/Network_win.cpp
new file mode 100644
index 000000000..432ea71ee
--- /dev/null
+++ b/src/net/Network_win.cpp
@@ -0,0 +1,64 @@
+/* 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 <uv.h>
+#include <windows.h>
+
+
+#include "net/Network.h"
+#include "version.h"
+
+
+static inline OSVERSIONINFOEX winOsVersion()
+{
+    typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO);
+    OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0};
+
+    HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
+    if (ntdll ) {
+        RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(GetProcAddress(ntdll, "RtlGetVersion"));
+
+        if (pRtlGetVersion) {
+            pRtlGetVersion((LPOSVERSIONINFO) &result);
+        }
+    }
+
+    return result;
+}
+
+
+char *Network::userAgent()
+{
+    const auto osver = winOsVersion();
+
+    char *buf = static_cast<char*>(malloc(128));
+
+#   ifdef __GNUC__
+    snprintf(buf, 128, "%s/%s (Windows NT %lu.%lu; Win64; x64) libuv/%s gcc/%d.%d.%d", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion, uv_version_string(), __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
+#   else
+    snprintf(buf, 128, "%s/%s (Windows NT %lu.%lu; Win64; x64) libuv/%s", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion, uv_version_string());
+#   endif
+
+    return buf;
+}
diff --git a/src/net/Url.cpp b/src/net/Url.cpp
new file mode 100644
index 000000000..f54b0b92c
--- /dev/null
+++ b/src/net/Url.cpp
@@ -0,0 +1,93 @@
+/* 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 <string.h>
+#include <stdlib.h>
+
+
+#include "net/Url.h"
+
+
+/**
+ * @brief Parse url.
+ *
+ * Valid urls:
+ * example.com
+ * example.com:3333
+ * stratum+tcp://example.com
+ * stratum+tcp://example.com:3333
+ *
+ * @param url
+ */
+Url::Url(const char *url) :
+    m_host(nullptr),
+    m_port(3333)
+{
+    const char *p = strstr(url, "://");
+    const char *base = url;
+
+    if (p) {
+        if (strncasecmp(url, "stratum+tcp://", 14)) {
+            return;
+        }
+
+        base = url + 14;
+    }
+
+    if (!strlen(base) || *base == '/') {
+        return;
+    }
+
+    char *port = strchr(base, ':');
+    if (!port) {
+        m_host = strdup(base);
+        return;
+    }
+
+    const size_t size = port++ - base + 1;
+    m_host = static_cast<char*>(malloc(size));
+    memcpy(m_host, base, size - 1);
+    m_host[size - 1] = '\0';
+
+    m_port = strtol(port, nullptr, 10);
+}
+
+
+Url::Url(const char *host, uint16_t port) :
+    m_port(port)
+{
+    m_host = strdup(host);
+}
+
+
+Url::~Url()
+{
+    free(m_host);
+}
+
+
+bool Url::isNicehash() const
+{
+    return isValid() && strstr(m_host, ".nicehash.com");
+}
diff --git a/src/net/Url.h b/src/net/Url.h
new file mode 100644
index 000000000..a0e2d48d9
--- /dev/null
+++ b/src/net/Url.h
@@ -0,0 +1,49 @@
+/* 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/>.
+ */
+
+#ifndef __URL_H__
+#define __URL_H__
+
+
+#include <stdint.h>
+
+
+class Url
+{
+public:
+    Url(const char *url);
+    Url(const char *host, uint16_t port);
+    ~Url();
+
+    bool isNicehash() const;
+
+    inline bool isValid() const     { return m_host && m_port > 0; }
+    inline const char *host() const { return m_host; }
+    inline uint16_t port() const    { return m_port; }
+
+private:
+    char *m_host;
+    uint16_t m_port;
+};
+
+#endif /* __URL_H__ */
diff --git a/version.h b/src/version.h
similarity index 92%
rename from version.h
rename to src/version.h
index 330d96975..d7bde178a 100644
--- a/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   "0.8.3"
+#define APP_VERSION   "1.0.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  0
-#define APP_VER_MINOR  8
-#define APP_VER_BUILD  3
+#define APP_VER_MAJOR  1
+#define APP_VER_MINOR  0
+#define APP_VER_BUILD  0
 #define APP_VER_REV    0
 
 #endif /* __VERSION_H__ */
diff --git a/src/xmrig.cpp b/src/xmrig.cpp
new file mode 100644
index 000000000..4b4afcd28
--- /dev/null
+++ b/src/xmrig.cpp
@@ -0,0 +1,31 @@
+/* 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 "App.h"
+
+
+int main(int argc, char **argv) {
+    auto app = new App(argc, argv);
+
+    return app->exec();
+}
diff --git a/utils/applog.c b/utils/applog.c
deleted file mode 100644
index e0043c865..000000000
--- a/utils/applog.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 "xmrig.h"
-#include "applog.h"
-#include "threads.h"
-#include <sys/time.h>
-#include <string.h>
-
-#ifdef WIN32
-# include "compat/winansi.h"
-#endif
-
-#include "options.h"
-
-
-MUTEX applog_mutex;
-
-
-void applog_init()
-{
-    MUTEX_INIT(applog_mutex);
-}
-
-
-void applog(int prio, const char *fmt, ...)
-{
-    if (opt_background) {
-        return;
-    }
-
-    va_list ap;
-    va_start(ap, fmt);
-
-    struct tm tm;
-    struct tm *tm_p;
-    time_t now = time(NULL);
-
-    MUTEX_LOCK(applog_mutex);
-    tm_p = localtime(&now);
-    memcpy(&tm, tm_p, sizeof(tm));
-    MUTEX_UNLOCK(applog_mutex);
-
-    const char* color = "";
-
-    if (opt_colors) {
-        switch (prio) {
-            case LOG_ERR:     color = CL_RED; break;
-            case LOG_WARNING: color = CL_YLW; break;
-            case LOG_NOTICE:  color = CL_WHT; break;
-            case LOG_INFO:    color = ""; break;
-            case LOG_DEBUG:   color = CL_GRY; break;
-
-            case LOG_BLUE:
-                prio = LOG_NOTICE;
-                color = CL_CYN;
-                break;
-
-            case LOG_GREEN:
-                prio = LOG_NOTICE;
-                color = CL_LGR;
-                break;
-        }
-    }
-
-    const int len = 64 + strlen(fmt) + 2;
-    char *f       = alloca(len);
-
-    sprintf(f, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
-            tm.tm_year + 1900,
-            tm.tm_mon + 1,
-            tm.tm_mday,
-            tm.tm_hour,
-            tm.tm_min,
-            tm.tm_sec,
-            color,
-            fmt,
-            opt_colors ? CL_N : ""
-        );
-
-    MUTEX_LOCK(applog_mutex);
-    vfprintf(stderr, f, ap);
-    fflush(stderr);
-    MUTEX_UNLOCK(applog_mutex);
-
-    va_end(ap);
-}
-
-
-void applog_notime(int prio, const char *fmt, ...)
-{
-    if (opt_background) {
-        return;
-    }
-
-    va_list ap;
-    va_start(ap, fmt);
-
-    const char* color = "";
-
-    if (opt_colors) {
-        switch (prio) {
-            case LOG_ERR:     color = CL_RED; break;
-            case LOG_WARNING: color = CL_LYL; break;
-            case LOG_NOTICE:  color = CL_WHT; break;
-            case LOG_INFO:    color = ""; break;
-            case LOG_DEBUG:   color = CL_GRY; break;
-
-            case LOG_BLUE:
-                prio = LOG_NOTICE;
-                color = CL_CYN;
-                break;
-        }
-    }
-
-    const int len = 64 + strlen(fmt) + 2;
-    char *f       = alloca(len);
-
-    sprintf(f, "%s%s%s\n",
-            color,
-            fmt,
-            opt_colors ? CL_N : ""
-        );
-
-    MUTEX_LOCK(applog_mutex);
-    vfprintf(stderr, f, ap);
-    fflush(stderr);
-    MUTEX_UNLOCK(applog_mutex);
-
-    va_end(ap);
-}
diff --git a/utils/applog.h b/utils/applog.h
deleted file mode 100644
index 24a732265..000000000
--- a/utils/applog.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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/>.
- */
-
-#ifndef __APPLOG_H__
-#define __APPLOG_H__
-
-enum {
-    LOG_ERR,
-    LOG_WARNING,
-    LOG_NOTICE,
-    LOG_INFO,
-    LOG_DEBUG,
-    LOG_BLUE = 0x10,
-    LOG_GREEN
-};
-
-#define CL_N    "\x1B[0m"
-#define CL_RED  "\x1B[31m"
-#define CL_GRN  "\x1B[32m"
-#define CL_YLW  "\x1B[33m"
-#define CL_BLU  "\x1B[34m"
-#define CL_MAG  "\x1B[35m"
-#define CL_CYN  "\x1B[36m"
-
-#define CL_BLK  "\x1B[22;30m" /* black */
-#define CL_RD2  "\x1B[22;31m" /* red */
-#define CL_GR2  "\x1B[22;32m" /* green */
-#define CL_BRW  "\x1B[22;33m" /* brown */
-#define CL_BL2  "\x1B[22;34m" /* blue */
-#define CL_MA2  "\x1B[22;35m" /* magenta */
-#define CL_CY2  "\x1B[22;36m" /* cyan */
-#define CL_SIL  "\x1B[22;37m" /* gray */
-
-#ifdef WIN32
-#define CL_GRY  "\x1B[01;30m" /* dark gray */
-#else
-#define CL_GRY  "\x1B[90m"    /* dark gray selectable in putty */
-#endif
-#define CL_LRD  "\x1B[01;31m" /* light red */
-#define CL_LGR  "\x1B[01;32m" /* light green */
-#define CL_LYL  "\x1B[01;33m" /* light yellow */
-#define CL_LBL  "\x1B[01;34m" /* light blue */
-#define CL_LMA  "\x1B[01;35m" /* light magenta */
-#define CL_LCY  "\x1B[01;36m" /* light cyan */
-
-#define CL_WHT  "\x1B[01;37m" /* white */
-
-#define OPT_COLOR(color, text) (opt_colors ? (color text CL_N) : text)
-
-
-void applog_init();
-void applog(int prio, const char *fmt, ...);
-void applog_notime(int prio, const char *fmt, ...);
-
-#endif /* __APPLOG_H__ */

From 7deee3240b09e88a26f82c6318ffce2b5c8627fe Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Tue, 6 Jun 2017 06:05:17 +0300
Subject: [PATCH 09/56] Handle jsonrpc errors.

---
 src/net/Client.cpp | 40 ++++++++++++++++++++++++++++++++++++----
 src/net/Client.h   |  5 +++++
 2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index cb77ebadd..8b80cd25a 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -22,9 +22,6 @@
  */
 
 
-#include <jansson.h>
-
-
 #include "Console.h"
 #include "interfaces/IClientListener.h"
 #include "net/Client.h"
@@ -34,6 +31,8 @@
 Client::Client(IClientListener *listener) :
     m_host(nullptr),
     m_listener(listener),
+    m_retries(0),
+    m_sequence(1),
     m_recvBufPos(0),
     m_state(UnconnectedState),
     m_port(0),
@@ -96,9 +95,11 @@ void Client::disconnect()
 
 void Client::login(const char *user, const char *pass, const char *agent)
 {
+    m_sequence = 1;
+
     const size_t size = 96 + strlen(user) + strlen(pass) + strlen(agent);
     char *req = static_cast<char*>(malloc(size));
-    snprintf(req, size, "{\"method\":\"login\",\"params\":{\"login\":\"%s\",\"pass\":\"%s\",\"agent\":\"%s\"},\"id\":1}\n", user, pass, agent);
+    snprintf(req, size, "{\"id\":%llu,\"jsonrpc\":\"2.0\",\"method\":\"login\",\"params\":{\"login\":\"%s\",\"pass\":\"%s\",\"agent\":\"%s\"}}\n", m_sequence, user, pass, agent);
 
     send(req);
 }
@@ -117,6 +118,7 @@ void Client::send(char *data)
         return;
     }
 
+    m_sequence++;
     uv_buf_t buf = uv_buf_init(data, strlen(data));
 
     uv_write_t *req = static_cast<uv_write_t*>(malloc(sizeof(uv_write_t)));
@@ -195,6 +197,36 @@ void Client::parse(char *line, size_t len)
         LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_host, m_port, err.text);
         return;
     }
+
+    const json_t *id = json_object_get(val, "id");
+    if (json_is_integer(id)) {
+        parseResponse(json_integer_value(id), json_object_get(val, "result"), json_object_get(val, "error"));
+    }
+    else {
+        parseNotification(json_string_value(json_object_get(val, "method")), json_object_get(val, "params"));
+    }
+
+    json_decref(val);
+}
+
+
+void Client::parseNotification(const char *method, const json_t *params)
+{
+
+}
+
+
+void Client::parseResponse(int64_t id, const json_t *result, const json_t *error)
+{
+    if (json_is_object(error)) {
+        LOG_ERR("[%s:%u] error: \"%s\", code: %lld", m_host, m_port, json_string_value(json_object_get(error, "message")), json_integer_value(json_object_get(error, "code")));
+
+        if (id == 1) {
+            close();
+        }
+
+        return;
+    }
 }
 
 
diff --git a/src/net/Client.h b/src/net/Client.h
index 181ea6419..89167affd 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -25,6 +25,7 @@
 #define __CLIENT_H__
 
 
+#include <jansson.h>
 #include <uv.h>
 
 
@@ -61,6 +62,8 @@ private:
     void close();
     void connect(struct sockaddr *addr);
     void parse(char *line, size_t len);
+    void parseNotification(const char *method, const json_t *params);
+    void parseResponse(int64_t id, const json_t *result, const json_t *error);
     void setState(SocketState state);
 
     static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
@@ -73,6 +76,8 @@ private:
 
     char *m_host;
     IClientListener *m_listener;
+    int64_t m_retries;
+    int64_t m_sequence;
     size_t m_recvBufPos;
     SocketState m_state;
     struct addrinfo m_hints;

From 26b82063329fd23d53851edf0776810daaf0fc6d Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Tue, 6 Jun 2017 06:35:17 +0300
Subject: [PATCH 10/56] Basic login parse.

---
 src/net/Client.cpp | 30 ++++++++++++++++++++++++++++++
 src/net/Client.h   |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index 8b80cd25a..53b2504bf 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -136,6 +136,21 @@ void Client::send(char *data)
 }
 
 
+bool Client::parseLogin(const json_t *result, int *code)
+{
+    const char *id = json_string_value(json_object_get(result, "id"));
+    if (!id || strlen(id) >= sizeof(m_rpcId)) {
+        *code = 1;
+        return false;
+    }
+
+    memset(m_rpcId, 0, sizeof(m_rpcId));
+    memcpy(m_rpcId, id, strlen(id));
+
+    return true;
+}
+
+
 int Client::resolve(const char *host)
 {
     setState(HostLookupState);
@@ -227,6 +242,21 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
 
         return;
     }
+
+    if (!json_is_object(result)) {
+        return;
+    }
+
+    if (id == 1) {
+        int code = -1;
+        if (!parseLogin(result, &code)) {
+            LOG_ERR("[%s:%u] login error code: %d", m_host, m_port, code);
+            return close();
+        }
+
+        return;
+    }
+
 }
 
 
diff --git a/src/net/Client.h b/src/net/Client.h
index 89167affd..7db3ae3f4 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -58,6 +58,7 @@ public:
 private:
     constexpr static size_t kRecvBufSize = 4096;
 
+    bool parseLogin(const json_t *result, int *code);
     int resolve(const char *host);
     void close();
     void connect(struct sockaddr *addr);
@@ -75,6 +76,7 @@ private:
     static Client *getClient(void *data);
 
     char *m_host;
+    char m_rpcId[64];
     IClientListener *m_listener;
     int64_t m_retries;
     int64_t m_sequence;

From 1ecee56eb62745aa298caefa318e5362e524e232 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Tue, 6 Jun 2017 20:43:52 +0300
Subject: [PATCH 11/56] Add Job class.

---
 CMakeLists.txt     |   2 +
 src/net/Client.cpp |  32 ++++++++-
 src/net/Client.h   |   1 +
 src/net/Job.cpp    | 158 +++++++++++++++++++++++++++++++++++++++++++++
 src/net/Job.h      |  57 ++++++++++++++++
 5 files changed, 249 insertions(+), 1 deletion(-)
 create mode 100644 src/net/Job.cpp
 create mode 100644 src/net/Job.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1f485e11c..dc3feb367 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,6 +5,7 @@ set(HEADERS
     src/App.h
     src/interfaces/IClientListener.h
     src/net/Client.h
+    src/net/Job.h
     src/net/Network.h
     src/net/Url.h
     src/Options.h
@@ -15,6 +16,7 @@ set(HEADERS
 set(SOURCES
     src/App.cpp
     src/net/Client.cpp
+    src/net/Job.cpp
     src/net/Network.cpp
     src/net/Url.cpp
     src/Options.cpp
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index 53b2504bf..ee2c68732 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -25,6 +25,7 @@
 #include "Console.h"
 #include "interfaces/IClientListener.h"
 #include "net/Client.h"
+#include "net/Job.h"
 #include "net/Url.h"
 
 
@@ -136,6 +137,35 @@ void Client::send(char *data)
 }
 
 
+bool Client::parseJob(const json_t *params, int *code)
+{
+    if (!json_is_object(params)) {
+        *code = 2;
+        return false;
+    }
+
+    Job job;
+    if (!job.setId(json_string_value(json_object_get(params, "job_id")))) {
+        *code = 3;
+        return false;
+    }
+
+    if (!job.setBlob(json_string_value(json_object_get(params, "blob")))) {
+        *code = 4;
+        return false;
+    }
+
+    if (!job.setTarget(json_string_value(json_object_get(params, "target")))) {
+        *code = 5;
+        return false;
+    }
+
+           LOG_NOTICE("PARSE JOB %d %lld %lld", job.size(), job.target(), job.diff());
+
+    return true;
+}
+
+
 bool Client::parseLogin(const json_t *result, int *code)
 {
     const char *id = json_string_value(json_object_get(result, "id"));
@@ -147,7 +177,7 @@ bool Client::parseLogin(const json_t *result, int *code)
     memset(m_rpcId, 0, sizeof(m_rpcId));
     memcpy(m_rpcId, id, strlen(id));
 
-    return true;
+    return parseJob(json_object_get(result, "job"), code);
 }
 
 
diff --git a/src/net/Client.h b/src/net/Client.h
index 7db3ae3f4..2eecb0449 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -58,6 +58,7 @@ public:
 private:
     constexpr static size_t kRecvBufSize = 4096;
 
+    bool parseJob(const json_t *params, int *code);
     bool parseLogin(const json_t *result, int *code);
     int resolve(const char *host);
     void close();
diff --git a/src/net/Job.cpp b/src/net/Job.cpp
new file mode 100644
index 000000000..aeb466850
--- /dev/null
+++ b/src/net/Job.cpp
@@ -0,0 +1,158 @@
+/* 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 <string.h>
+//#include <stdlib.h>
+
+
+#include "net/Job.h"
+#include "Console.h"
+
+
+static inline unsigned char hf_hex2bin(char c, bool &err)
+{
+    if (c >= '0' && c <= '9') {
+        return c - '0';
+    }
+    else if (c >= 'a' && c <= 'f') {
+        return c - 'a' + 0xA;
+    }
+    else if (c >= 'A' && c <= 'F') {
+        return c - 'A' + 0xA;
+    }
+
+    err = true;
+    return 0;
+}
+
+
+static inline char hf_bin2hex(unsigned char c)
+{
+    if (c <= 0x9) {
+        return '0' + c;
+    }
+
+    return 'a' - 0xA + c;
+}
+
+
+Job::Job() :
+    m_size(0),
+    m_diff(0),
+    m_target(0)
+{
+}
+
+
+bool Job::setBlob(const char *blob)
+{
+    if (!blob) {
+        return false;
+    }
+
+    m_size = strlen(blob);
+    if (m_size % 2 != 0) {
+        return false;
+    }
+
+    m_size /= 2;
+    if (m_size < 76 || m_size >= sizeof(m_blob)) {
+        return false;
+    }
+
+    return fromHex(blob, m_size * 2, m_blob);
+}
+
+
+bool Job::setId(const char *id)
+{
+    if (!id || strlen(id) >= sizeof(m_id)) {
+        return false;
+    }
+
+    memset(m_id, 0, sizeof(m_id));
+    memcpy(m_id, id, strlen(id));
+    return true;
+}
+
+
+bool Job::setTarget(const char *target)
+{
+    if (!target) {
+        return false;
+    }
+
+    const size_t len = strlen(target);
+
+    if (len <= 8) {
+        uint32_t tmp = 0;
+        char str[8];
+        memcpy(str, target, len);
+
+        if (!fromHex(str, 8, reinterpret_cast<unsigned char*>(&tmp)) || tmp == 0) {
+            return false;
+        }
+
+        m_target = 0xFFFFFFFFFFFFFFFFULL / (0xFFFFFFFFULL / static_cast<uint64_t>(tmp));
+    }
+    else if (len <= 16) {
+        m_target = 0;
+        char str[16];
+        memcpy(str, target, len);
+
+        if (!fromHex(str, 16, reinterpret_cast<unsigned char*>(&m_target)) || m_target == 0) {
+            return false;
+        }
+    }
+    else {
+        return false;
+    }
+
+
+    m_diff = toDiff(m_target);
+    return true;
+}
+
+
+bool Job::fromHex(const char* in, unsigned int len, unsigned char* out)
+{
+    bool error = false;
+    for (unsigned int i = 0; i < len; i += 2) {
+        out[i / 2] = (hf_hex2bin(in[i], error) << 4) | hf_hex2bin(in[i + 1], error);
+
+        if (error) {
+            return false;
+        }
+    }
+    return true;
+}
+
+
+void Job::toHex(const unsigned char* in, unsigned int len, char* out)
+{
+    for (unsigned int i = 0; i < len; i++) {
+        out[i * 2] = hf_bin2hex((in[i] & 0xF0) >> 4);
+        out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F);
+    }
+}
diff --git a/src/net/Job.h b/src/net/Job.h
new file mode 100644
index 000000000..d213ec34a
--- /dev/null
+++ b/src/net/Job.h
@@ -0,0 +1,57 @@
+/* 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/>.
+ */
+
+#ifndef __JOB_H__
+#define __JOB_H__
+
+
+#include <stdint.h>
+
+
+class Job
+{
+public:
+    Job();
+    bool setBlob(const char *blob);
+    bool setId(const char *id);
+    bool setTarget(const char *target);
+
+    inline const uint8_t *blob() const { return m_blob; }
+    inline const char *id() const      { return m_id; }
+    inline uint32_t size() const       { return m_size; }
+    inline uint32_t diff() const       { return m_diff; }
+    inline uint64_t target() const     { return m_target; }
+
+    static bool fromHex(const char* in, unsigned int len, unsigned char* out);
+    static void toHex(const unsigned char* in, unsigned int len, char* out);
+    inline static uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
+
+private:
+    char m_id[64]      __attribute__((aligned(16)));
+    uint8_t m_blob[84] __attribute__((aligned(16))); // 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;
+    uint64_t m_diff;
+    uint64_t m_target;
+};
+
+#endif /* __JOB_H__ */

From 4c06d8b08054f0a460a4749f6ef931ec233d1d66 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 7 Jun 2017 01:19:59 +0300
Subject: [PATCH 12/56] Handle job notification.

---
 src/interfaces/IClientListener.h |  3 +++
 src/net/Client.cpp               | 19 +++++++++++++++++--
 src/net/Client.h                 |  4 ++++
 src/net/Network.cpp              | 11 +++++++++++
 src/net/Network.h                |  2 ++
 5 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/src/interfaces/IClientListener.h b/src/interfaces/IClientListener.h
index 26ff10aab..8a2a439f0 100644
--- a/src/interfaces/IClientListener.h
+++ b/src/interfaces/IClientListener.h
@@ -26,6 +26,7 @@
 
 
 class Client;
+class Job;
 
 
 class IClientListener
@@ -33,7 +34,9 @@ class IClientListener
 public:
     virtual ~IClientListener() {}
 
+    virtual void onJobReceived(Client *client, const Job &job) = 0;
     virtual void onLoginCredentialsRequired(Client *client) = 0;
+    virtual void onLoginSuccess(Client *client) = 0;
 };
 
 
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index ee2c68732..296acf64e 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -25,7 +25,6 @@
 #include "Console.h"
 #include "interfaces/IClientListener.h"
 #include "net/Client.h"
-#include "net/Job.h"
 #include "net/Url.h"
 
 
@@ -160,8 +159,9 @@ bool Client::parseJob(const json_t *params, int *code)
         return false;
     }
 
-           LOG_NOTICE("PARSE JOB %d %lld %lld", job.size(), job.target(), job.diff());
+    m_job = job;
 
+    LOG_DEBUG("[%s:%u] job: \"%s\", diff: %lld", m_host, m_port, job.id(), job.diff());
     return true;
 }
 
@@ -257,7 +257,20 @@ void Client::parse(char *line, size_t len)
 
 void Client::parseNotification(const char *method, const json_t *params)
 {
+    if (!method) {
+        return;
+    }
 
+    if (strcmp(method, "job") == 0) {
+        int code = -1;
+        if (parseJob(params, &code)) {
+            m_listener->onJobReceived(this, m_job);
+        }
+
+        return;
+    }
+
+    LOG_WARN("[%s:%u] unsupported method: \"%s\"", m_host, m_port, method);
 }
 
 
@@ -284,6 +297,8 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
             return close();
         }
 
+        m_listener->onLoginSuccess(this);
+        m_listener->onJobReceived(this, m_job);
         return;
     }
 
diff --git a/src/net/Client.h b/src/net/Client.h
index 2eecb0449..309078ded 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -29,6 +29,9 @@
 #include <uv.h>
 
 
+#include "net/Job.h"
+
+
 class Url;
 class IClientListener;
 
@@ -81,6 +84,7 @@ private:
     IClientListener *m_listener;
     int64_t m_retries;
     int64_t m_sequence;
+    Job m_job;
     size_t m_recvBufPos;
     SocketState m_state;
     struct addrinfo m_hints;
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index 91b626211..f87c41d57 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -59,7 +59,18 @@ void Network::connect()
 }
 
 
+void Network::onJobReceived(Client *client, const Job &job)
+{
+
+}
+
+
 void Network::onLoginCredentialsRequired(Client *client)
 {
     client->login(m_options->user(), m_options->pass(), m_agent);
 }
+
+
+void Network::onLoginSuccess(Client *client)
+{
+}
diff --git a/src/net/Network.h b/src/net/Network.h
index 5ee7c295d..87e319090 100644
--- a/src/net/Network.h
+++ b/src/net/Network.h
@@ -42,7 +42,9 @@ public:
   static char *userAgent();
 
 protected:
+  void onJobReceived(Client *client, const Job &job) override;
   void onLoginCredentialsRequired(Client *client) override;
+  void onLoginSuccess(Client *client) override;
 
 private:
   char *m_agent;

From b8cc1136a4dae5a842f52bba9a21358868c72bb9 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 7 Jun 2017 02:46:52 +0300
Subject: [PATCH 13/56] More flexible pools configuration.

---
 src/App.cpp         |  1 -
 src/Options.cpp     |  2 +-
 src/Options.h       |  9 +++++----
 src/donate.h        | 16 +++++++++++++++-
 src/net/Client.cpp  | 37 +++++++++++++++++++------------------
 src/net/Client.h    |  7 +++++--
 src/net/Network.cpp | 39 +++++++++++++++++++++++++++++----------
 src/net/Network.h   | 12 +++++++++---
 8 files changed, 83 insertions(+), 40 deletions(-)

diff --git a/src/App.cpp b/src/App.cpp
index ce9d2b2cd..a82eb88cd 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -48,7 +48,6 @@ App::App(int argc, char **argv)
 {
     Console::init();
     m_options = Options::parse(argc, argv);
-
     m_network = new Network(m_options);
 }
 
diff --git a/src/Options.cpp b/src/Options.cpp
index 5a8551c41..331db8434 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -128,7 +128,7 @@ Options::Options(int argc, char **argv) :
     m_user(nullptr),
     m_algo(0),
     m_algoVariant(0),
-    m_donateLevel(DONATE_LEVEL),
+    m_donateLevel(kDonateLevel),
     m_maxCpuUsage(75),
     m_retries(5),
     m_retryPause(5),
diff --git a/src/Options.h b/src/Options.h
index eccfbcff3..421d19f4c 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -51,10 +51,11 @@ public:
     static inline Options* i() { return m_self; }
     static Options *parse(int argc, char **argv);
 
-    inline bool isReady() const     { return m_ready; }
-    inline const char *pass() const { return m_pass; }
-    inline const char *user() const { return m_user; }
-    inline Url *url() const         { return m_url; }
+    inline bool isReady() const         { return m_ready; }
+    inline const char *pass() const     { return m_pass; }
+    inline const char *user() const     { return m_user; }
+    inline const Url *backupUrl() const { return m_backupUrl; }
+    inline const Url *url() const       { return m_url; }
 
 private:
     Options(int argc, char **argv);
diff --git a/src/donate.h b/src/donate.h
index 4fc607872..3a0009486 100644
--- a/src/donate.h
+++ b/src/donate.h
@@ -24,6 +24,20 @@
 #ifndef __DONATE_H__
 #define __DONATE_H__
 
-#define DONATE_LEVEL 5
+
+/*
+ * Dev donation.
+ *
+ * Percentage of your hashing power that you want to donate to the developer, can be 0 if you don't want to do that.
+ * Example of how it works for the default setting of 1:
+ * You miner will mine into your usual pool for 99 minutes, then switch to the developer's pool for 1 minute.
+ * Switching is instant, and only happens after a successful connection, so you never loose any hashes.
+ *
+ * If you plan on changing this setting to 0 please consider making a one off donation to my wallet:
+ * XMR: 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD
+ * BTC: 1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT
+ */
+constexpr const int kDonateLevel = 5;
+
 
 #endif /* __DONATE_H__ */
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index 296acf64e..a8a4f5d57 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -28,9 +28,10 @@
 #include "net/Url.h"
 
 
-Client::Client(IClientListener *listener) :
+Client::Client(int id, IClientListener *listener) :
     m_host(nullptr),
     m_listener(listener),
+    m_id(id),
     m_retries(0),
     m_sequence(1),
     m_recvBufPos(0),
@@ -59,20 +60,9 @@ Client::~Client()
 }
 
 
-/**
- * @brief Connect to server.
- *
- * @param host
- * @param port
- */
-void Client::connect(const char *host, uint16_t port)
+void Client::connect()
 {
-    m_host = strdup(host);
-    m_port = port;
-
-    LOG_DEBUG("[%s:%u] connect", m_host, m_port);
-
-    resolve(host);
+    resolve(m_host);
 }
 
 
@@ -83,7 +73,8 @@ void Client::connect(const char *host, uint16_t port)
  */
 void Client::connect(const Url *url)
 {
-    connect(url->host(), url->port());
+    setUrl(url);
+    resolve(m_host);
 }
 
 
@@ -136,6 +127,14 @@ void Client::send(char *data)
 }
 
 
+void Client::setUrl(const Url *url)
+{
+    free(m_host);
+    m_host = strdup(url->host());
+    m_port = url->port();
+}
+
+
 bool Client::parseJob(const json_t *params, int *code)
 {
     if (!json_is_object(params)) {
@@ -335,6 +334,8 @@ void Client::onClose(uv_handle_t *handle)
     client->m_stream = nullptr;
     client->m_socket = nullptr;
     client->setState(UnconnectedState);
+
+    LOG_NOTICE("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
 }
 
 
@@ -344,6 +345,7 @@ void Client::onConnect(uv_connect_t *req, int status)
     if (status < 0) {
         LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_host, client->m_port, uv_strerror(status));
         free(req);
+        client->close();
         return;
     }
 
@@ -366,8 +368,7 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
             LOG_ERR("[%s:%u] read error: \"%s\"", client->m_host, client->m_port, uv_strerror(nread));
         }
 
-        client->close();
-        return;
+        return client->close();;
     }
 
     client->m_recvBufPos += nread;
@@ -404,7 +405,7 @@ void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
     auto client = getClient(req->data);
     if (status < 0) {
         LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_host, client->m_port, uv_strerror(status));
-        return;
+        return client->close();;
     }
 
     client->connect(res->ai_addr);
diff --git a/src/net/Client.h b/src/net/Client.h
index 309078ded..8df215599 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -47,15 +47,17 @@ public:
         ClosingState
     };
 
-    Client(IClientListener *listener);
+    Client(int id, IClientListener *listener);
     ~Client();
 
-    void connect(const char *host, uint16_t port);
+    void connect();
     void connect(const Url *url);
     void disconnect();
     void login(const char *user, const char *pass, const char *agent);
     void send(char *data);
+    void setUrl(const Url *url);
 
+    inline int id() const            { return m_id; }
     inline SocketState state() const { return m_state; }
 
 private:
@@ -82,6 +84,7 @@ private:
     char *m_host;
     char m_rpcId[64];
     IClientListener *m_listener;
+    int m_id;
     int64_t m_retries;
     int64_t m_sequence;
     Job m_job;
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index f87c41d57..1f0a55e95 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -23,30 +23,37 @@
 
 
 #include <uv.h>
+#include <memory>
 
 
 #include "Console.h"
 #include "net/Client.h"
 #include "net/Network.h"
+#include "net/Url.h"
 #include "Options.h"
 
 
 Network::Network(const Options *options) :
-    m_backupPool(nullptr),
-    m_donatePool(nullptr),
-    m_pool(nullptr),
-    m_options(options)
+    m_donate(false),
+    m_options(options),
+    m_pool(1)
 {
+    m_pools.reserve(2);
     m_agent = userAgent();
-    m_pool = new Client(this);
+
+    std::unique_ptr<Url> url(new Url("donate.xmrig.com", 443));
+
+    addPool(url.get());
+    addPool(m_options->url());
+    addPool(m_options->backupUrl());
 }
 
 
 Network::~Network()
 {
-    delete m_pool;
-    delete m_donatePool;
-    delete m_backupPool;
+    for (auto client : m_pools) {
+        delete client;
+    }
 
     free(m_agent);
 }
@@ -54,8 +61,7 @@ Network::~Network()
 
 void Network::connect()
 {
-    m_pool->connect(m_options->url());
-//    LOG_DEBUG("XX %s", m_options->url());
+    m_pools.at(m_pool)->connect();
 }
 
 
@@ -74,3 +80,16 @@ void Network::onLoginCredentialsRequired(Client *client)
 void Network::onLoginSuccess(Client *client)
 {
 }
+
+
+void Network::addPool(const Url *url)
+{
+    if (!url) {
+        return;
+    }
+
+    Client *client = new Client(m_pools.size(), this);
+    client->setUrl(url);
+
+    m_pools.push_back(client);
+}
diff --git a/src/net/Network.h b/src/net/Network.h
index 87e319090..2b7cf2082 100644
--- a/src/net/Network.h
+++ b/src/net/Network.h
@@ -25,10 +25,14 @@
 #define __NETWORK_H__
 
 
+#include <vector>
+
+
 #include "interfaces/IClientListener.h"
 
 
 class Options;
+class Url;
 
 
 class Network : public IClientListener
@@ -47,11 +51,13 @@ protected:
   void onLoginSuccess(Client *client) override;
 
 private:
+  void addPool(const Url *url);
+
+  bool m_donate;
   char *m_agent;
-  Client *m_backupPool;
-  Client *m_donatePool;
-  Client *m_pool;
   const Options *m_options;
+  int m_pool;
+  std::vector<Client*> m_pools;
 };
 
 

From c29dc8bcf4d28b3aab4d9dc91ba3333c34b9a06d Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 7 Jun 2017 04:19:32 +0300
Subject: [PATCH 14/56] Implemented reconnect.

---
 src/Options.cpp                  |  2 +-
 src/Options.h                    |  1 +
 src/interfaces/IClientListener.h |  1 +
 src/net/Client.cpp               | 25 ++++++++++++++++++++++---
 src/net/Client.h                 | 10 +++++++---
 src/net/Network.cpp              |  7 +++++++
 src/net/Network.h                |  1 +
 7 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/src/Options.cpp b/src/Options.cpp
index 331db8434..c996c755b 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -131,7 +131,7 @@ Options::Options(int argc, char **argv) :
     m_donateLevel(kDonateLevel),
     m_maxCpuUsage(75),
     m_retries(5),
-    m_retryPause(5),
+    m_retryPause(2),
     m_threads(0),
     m_affinity(-1L),
     m_backupUrl(nullptr),
diff --git a/src/Options.h b/src/Options.h
index 421d19f4c..05efbcee6 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -56,6 +56,7 @@ public:
     inline const char *user() const     { return m_user; }
     inline const Url *backupUrl() const { return m_backupUrl; }
     inline const Url *url() const       { return m_url; }
+    inline int retryPause() const       { return m_retryPause; }
 
 private:
     Options(int argc, char **argv);
diff --git a/src/interfaces/IClientListener.h b/src/interfaces/IClientListener.h
index 8a2a439f0..73a855161 100644
--- a/src/interfaces/IClientListener.h
+++ b/src/interfaces/IClientListener.h
@@ -34,6 +34,7 @@ class IClientListener
 public:
     virtual ~IClientListener() {}
 
+    virtual void onClose(Client *client, int failures);
     virtual void onJobReceived(Client *client, const Job &job) = 0;
     virtual void onLoginCredentialsRequired(Client *client) = 0;
     virtual void onLoginSuccess(Client *client) = 0;
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index a8a4f5d57..6ae63b912 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -32,7 +32,8 @@ Client::Client(int id, IClientListener *listener) :
     m_host(nullptr),
     m_listener(listener),
     m_id(id),
-    m_retries(0),
+    m_retryPause(2000),
+    m_failures(0),
     m_sequence(1),
     m_recvBufPos(0),
     m_state(UnconnectedState),
@@ -49,6 +50,9 @@ Client::Client(int id, IClientListener *listener) :
 
     m_recvBuf.base = static_cast<char*>(malloc(kRecvBufSize));
     m_recvBuf.len  = kRecvBufSize;
+
+    m_retriesTimer.data = this;
+    uv_timer_init(uv_default_loop(), &m_retriesTimer);
 }
 
 
@@ -80,6 +84,8 @@ void Client::connect(const Url *url)
 
 void Client::disconnect()
 {
+    m_failures = -1;
+
     close();
 }
 
@@ -296,11 +302,24 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
             return close();
         }
 
+        m_failures = 0;
         m_listener->onLoginSuccess(this);
         m_listener->onJobReceived(this, m_job);
         return;
     }
+}
 
+
+void Client::reconnect()
+{
+    if (m_failures == -1) {
+        return m_listener->onClose(this, -1);
+    }
+
+    m_failures++;
+    m_listener->onClose(this, m_failures);
+
+    uv_timer_start(&m_retriesTimer, [](uv_timer_t *handle) { getClient(handle->data)->connect(); }, m_retryPause, 0);
 }
 
 
@@ -335,7 +354,7 @@ void Client::onClose(uv_handle_t *handle)
     client->m_socket = nullptr;
     client->setState(UnconnectedState);
 
-    LOG_NOTICE("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
+    client->reconnect();
 }
 
 
@@ -405,7 +424,7 @@ void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
     auto client = getClient(req->data);
     if (status < 0) {
         LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_host, client->m_port, uv_strerror(status));
-        return client->close();;
+        return client->reconnect();;
     }
 
     client->connect(res->ai_addr);
diff --git a/src/net/Client.h b/src/net/Client.h
index 8df215599..a1e9997a1 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -57,8 +57,9 @@ public:
     void send(char *data);
     void setUrl(const Url *url);
 
-    inline int id() const            { return m_id; }
-    inline SocketState state() const { return m_state; }
+    inline int id() const               { return m_id; }
+    inline SocketState state() const    { return m_state; }
+    inline void setRetryPause(int ms)   { m_retryPause = ms; }
 
 private:
     constexpr static size_t kRecvBufSize = 4096;
@@ -71,6 +72,7 @@ private:
     void parse(char *line, size_t len);
     void parseNotification(const char *method, const json_t *params);
     void parseResponse(int64_t id, const json_t *result, const json_t *error);
+    void reconnect();
     void setState(SocketState state);
 
     static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
@@ -85,7 +87,8 @@ private:
     char m_rpcId[64];
     IClientListener *m_listener;
     int m_id;
-    int64_t m_retries;
+    int m_retryPause;
+    int64_t m_failures;
     int64_t m_sequence;
     Job m_job;
     size_t m_recvBufPos;
@@ -96,6 +99,7 @@ private:
     uv_getaddrinfo_t m_resolver;
     uv_stream_t *m_stream;
     uv_tcp_t *m_socket;
+    uv_timer_t m_retriesTimer;
 };
 
 
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index 1f0a55e95..101c6b793 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -65,6 +65,12 @@ void Network::connect()
 }
 
 
+void Network::onClose(Client *client, int failures)
+{
+    LOG_DEBUG("CLOSE %d %d", client->id(), failures);
+}
+
+
 void Network::onJobReceived(Client *client, const Job &job)
 {
 
@@ -90,6 +96,7 @@ void Network::addPool(const Url *url)
 
     Client *client = new Client(m_pools.size(), this);
     client->setUrl(url);
+    client->setRetryPause(m_options->retryPause() * 1000);
 
     m_pools.push_back(client);
 }
diff --git a/src/net/Network.h b/src/net/Network.h
index 2b7cf2082..89787012f 100644
--- a/src/net/Network.h
+++ b/src/net/Network.h
@@ -46,6 +46,7 @@ public:
   static char *userAgent();
 
 protected:
+  void onClose(Client *client, int failures) override;
   void onJobReceived(Client *client, const Job &job) override;
   void onLoginCredentialsRequired(Client *client) override;
   void onLoginSuccess(Client *client) override;

From 5f1f9016493084ab6104fd26d582317d119fa8dc Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 7 Jun 2017 06:48:00 +0300
Subject: [PATCH 15/56] Add support for keepAlive.

---
 src/Options.cpp     |  4 ++--
 src/Options.h       |  3 ++-
 src/net/Client.cpp  | 43 +++++++++++++++++++++++++++++++++++--------
 src/net/Client.h    | 15 ++++++++++++---
 src/net/Network.cpp |  3 ++-
 5 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/src/Options.cpp b/src/Options.cpp
index c996c755b..2df634413 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -120,7 +120,7 @@ Options::Options(int argc, char **argv) :
     m_background(false),
     m_colors(true),
     m_doubleHash(false),
-    m_keepalive(false),
+    m_keepAlive(false),
     m_nicehash(false),
     m_ready(false),
     m_safe(false),
@@ -277,7 +277,7 @@ bool Options::parseArg(int key, char *arg)
         break;
 
     case 'k': /* --keepalive */
-        m_keepalive = true;
+        m_keepAlive = true;
         break;
 
     case 'V': /* --version */
diff --git a/src/Options.h b/src/Options.h
index 05efbcee6..227659f79 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -52,6 +52,7 @@ public:
     static Options *parse(int argc, char **argv);
 
     inline bool isReady() const         { return m_ready; }
+    inline bool keepAlive() const       { return m_keepAlive; }
     inline const char *pass() const     { return m_pass; }
     inline const char *user() const     { return m_user; }
     inline const Url *backupUrl() const { return m_backupUrl; }
@@ -75,7 +76,7 @@ private:
     bool m_background;
     bool m_colors;
     bool m_doubleHash;
-    bool m_keepalive;
+    bool m_keepAlive;
     bool m_nicehash;
     bool m_ready;
     bool m_safe;
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index 6ae63b912..fbfe17f8d 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -29,6 +29,7 @@
 
 
 Client::Client(int id, IClientListener *listener) :
+    m_keepAlive(false),
     m_host(nullptr),
     m_listener(listener),
     m_id(id),
@@ -41,7 +42,7 @@ Client::Client(int id, IClientListener *listener) :
     m_stream(nullptr),
     m_socket(nullptr)
 {
-    m_resolver.data = this;
+    m_resolver.data = m_responseTimer.data = m_retriesTimer.data = m_keepAliveTimer.data = this;
 
     m_hints.ai_family   = PF_INET;
     m_hints.ai_socktype = SOCK_STREAM;
@@ -51,8 +52,10 @@ Client::Client(int id, IClientListener *listener) :
     m_recvBuf.base = static_cast<char*>(malloc(kRecvBufSize));
     m_recvBuf.len  = kRecvBufSize;
 
-    m_retriesTimer.data = this;
-    uv_timer_init(uv_default_loop(), &m_retriesTimer);
+    auto loop = uv_default_loop();
+    uv_timer_init(loop, &m_retriesTimer);
+    uv_timer_init(loop, &m_responseTimer);
+    uv_timer_init(loop, &m_keepAliveTimer);
 }
 
 
@@ -122,14 +125,11 @@ void Client::send(char *data)
     req->data = buf.base;
 
     uv_write(req, m_stream, &buf, 1, [](uv_write_t *req, int status) {
-        if (status) {
-            auto client = getClient(req->data);
-            LOG_ERR("[%s:%u] write error: \"%s\"", client->m_host, client->m_port, uv_strerror(status));
-        }
-
         free(req->data);
         free(req);
     });
+
+    uv_timer_start(&m_responseTimer, [](uv_timer_t* handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0);
 }
 
 
@@ -236,6 +236,8 @@ void Client::connect(struct sockaddr *addr)
 
 void Client::parse(char *line, size_t len)
 {
+    startTimeout();
+
     line[len - 1] = '\0';
 
     LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_host, m_port, len, line);
@@ -310,8 +312,22 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
 }
 
 
+void Client::ping()
+{
+    char *req = static_cast<char*>(malloc(128));
+    snprintf(req, 128, "{\"id\":%lld,\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId);
+
+    send(req);
+}
+
+
 void Client::reconnect()
 {
+    uv_timer_stop(&m_responseTimer);
+    if (m_keepAlive) {
+        uv_timer_stop(&m_keepAliveTimer);
+    }
+
     if (m_failures == -1) {
         return m_listener->onClose(this, -1);
     }
@@ -335,6 +351,17 @@ void Client::setState(SocketState state)
 }
 
 
+void Client::startTimeout()
+{
+    uv_timer_stop(&m_responseTimer);
+    if (!m_keepAlive) {
+        return;
+    }
+
+    uv_timer_start(&m_keepAliveTimer, [](uv_timer_t *handle) { getClient(handle->data)->ping(); }, kKeepAliveTimeout, 0);
+}
+
+
 void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
 {
     auto client = getClient(handle->data);
diff --git a/src/net/Client.h b/src/net/Client.h
index a1e9997a1..7dbdf21fe 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -47,6 +47,9 @@ public:
         ClosingState
     };
 
+    constexpr static int kResponseTimeout  = 15 * 1000;
+    constexpr static int kKeepAliveTimeout = 60 * 1000;
+
     Client(int id, IClientListener *listener);
     ~Client();
 
@@ -57,9 +60,10 @@ public:
     void send(char *data);
     void setUrl(const Url *url);
 
-    inline int id() const               { return m_id; }
-    inline SocketState state() const    { return m_state; }
-    inline void setRetryPause(int ms)   { m_retryPause = ms; }
+    inline int id() const                    { return m_id; }
+    inline SocketState state() const         { return m_state; }
+    inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; }
+    inline void setRetryPause(int ms)        { m_retryPause = ms; }
 
 private:
     constexpr static size_t kRecvBufSize = 4096;
@@ -72,8 +76,10 @@ private:
     void parse(char *line, size_t len);
     void parseNotification(const char *method, const json_t *params);
     void parseResponse(int64_t id, const json_t *result, const json_t *error);
+    void ping();
     void reconnect();
     void setState(SocketState state);
+    void startTimeout();
 
     static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
     static void onClose(uv_handle_t *handle);
@@ -83,6 +89,7 @@ private:
 
     static Client *getClient(void *data);
 
+    bool m_keepAlive;
     char *m_host;
     char m_rpcId[64];
     IClientListener *m_listener;
@@ -99,6 +106,8 @@ private:
     uv_getaddrinfo_t m_resolver;
     uv_stream_t *m_stream;
     uv_tcp_t *m_socket;
+    uv_timer_t m_keepAliveTimer;
+    uv_timer_t m_responseTimer;
     uv_timer_t m_retriesTimer;
 };
 
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index 101c6b793..a69341674 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -41,7 +41,7 @@ Network::Network(const Options *options) :
     m_pools.reserve(2);
     m_agent = userAgent();
 
-    std::unique_ptr<Url> url(new Url("donate.xmrig.com", 443));
+    auto url = std::make_unique<Url>("donate.xmrig.com", 443);
 
     addPool(url.get());
     addPool(m_options->url());
@@ -97,6 +97,7 @@ void Network::addPool(const Url *url)
     Client *client = new Client(m_pools.size(), this);
     client->setUrl(url);
     client->setRetryPause(m_options->retryPause() * 1000);
+    client->setKeepAlive(m_options->keepAlive());
 
     m_pools.push_back(client);
 }

From 387524e1c56c7d62d0ce33b8673182ec8f5a86f1 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 7 Jun 2017 07:34:14 +0300
Subject: [PATCH 16/56] Fix for error notification.

---
 src/net/Client.cpp | 9 +++++++--
 src/net/Client.h   | 2 +-
 src/net/Job.cpp    | 1 -
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index fbfe17f8d..72f179c26 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -255,15 +255,20 @@ void Client::parse(char *line, size_t len)
         parseResponse(json_integer_value(id), json_object_get(val, "result"), json_object_get(val, "error"));
     }
     else {
-        parseNotification(json_string_value(json_object_get(val, "method")), json_object_get(val, "params"));
+        parseNotification(json_string_value(json_object_get(val, "method")), json_object_get(val, "params"), json_object_get(val, "error"));
     }
 
     json_decref(val);
 }
 
 
-void Client::parseNotification(const char *method, const json_t *params)
+void Client::parseNotification(const char *method, const json_t *params, const json_t *error)
 {
+    if (json_is_object(error)) {
+        LOG_ERR("[%s:%u] error: \"%s\", code: %lld", m_host, m_port, json_string_value(json_object_get(error, "message")), json_integer_value(json_object_get(error, "code")));
+        return;
+    }
+
     if (!method) {
         return;
     }
diff --git a/src/net/Client.h b/src/net/Client.h
index 7dbdf21fe..62bb41966 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -74,7 +74,7 @@ private:
     void close();
     void connect(struct sockaddr *addr);
     void parse(char *line, size_t len);
-    void parseNotification(const char *method, const json_t *params);
+    void parseNotification(const char *method, const json_t *params, const json_t *error);
     void parseResponse(int64_t id, const json_t *result, const json_t *error);
     void ping();
     void reconnect();
diff --git a/src/net/Job.cpp b/src/net/Job.cpp
index aeb466850..65feabb7b 100644
--- a/src/net/Job.cpp
+++ b/src/net/Job.cpp
@@ -129,7 +129,6 @@ bool Job::setTarget(const char *target)
         return false;
     }
 
-
     m_diff = toDiff(m_target);
     return true;
 }

From c31ea003994fa6a60ee59e52ba5f29554173e6b4 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 7 Jun 2017 09:07:31 +0300
Subject: [PATCH 17/56] Basic failover support.

---
 src/Console.h       |  6 ++++--
 src/Options.cpp     |  2 +-
 src/Options.h       |  1 +
 src/net/Client.cpp  |  2 +-
 src/net/Client.h    |  2 ++
 src/net/Network.cpp | 35 ++++++++++++++++++++++++++++++++---
 6 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/src/Console.h b/src/Console.h
index a02e37612..73e047061 100644
--- a/src/Console.h
+++ b/src/Console.h
@@ -71,11 +71,13 @@ private:
 #define LOG_INFO(x, ...)   Console::i()->message(Console::INFO,    x, ##__VA_ARGS__)
 
 #ifdef APP_DEBUG
-#   define LOG_DEBUG(x, ...)     Console::i()->message(Console::DEBUG,   x, ##__VA_ARGS__)
-#   define LOG_DEBUG_ERR(x, ...) Console::i()->message(Console::ERR,     x, ##__VA_ARGS__)
+#   define LOG_DEBUG(x, ...)      Console::i()->message(Console::DEBUG,   x, ##__VA_ARGS__)
+#   define LOG_DEBUG_ERR(x, ...)  Console::i()->message(Console::ERR,     x, ##__VA_ARGS__)
+#   define LOG_DEBUG_WARN(x, ...) Console::i()->message(Console::WARNING, x, ##__VA_ARGS__)
 #else
 #   define LOG_DEBUG(x, ...)
 #   define LOG_DEBUG_ERR(x, ...)
+#   define LOG_DEBUG_WARN(x, ...)
 #endif
 
 #endif /* __CONSOLE_H__ */
diff --git a/src/Options.cpp b/src/Options.cpp
index 2df634413..c09de032f 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -131,7 +131,7 @@ Options::Options(int argc, char **argv) :
     m_donateLevel(kDonateLevel),
     m_maxCpuUsage(75),
     m_retries(5),
-    m_retryPause(2),
+    m_retryPause(5),
     m_threads(0),
     m_affinity(-1L),
     m_backupUrl(nullptr),
diff --git a/src/Options.h b/src/Options.h
index 227659f79..b2b1966df 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -57,6 +57,7 @@ public:
     inline const char *user() const     { return m_user; }
     inline const Url *backupUrl() const { return m_backupUrl; }
     inline const Url *url() const       { return m_url; }
+    inline int retries() const          { return m_retries; }
     inline int retryPause() const       { return m_retryPause; }
 
 private:
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index 72f179c26..38e7df25f 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -33,7 +33,7 @@ Client::Client(int id, IClientListener *listener) :
     m_host(nullptr),
     m_listener(listener),
     m_id(id),
-    m_retryPause(2000),
+    m_retryPause(5000),
     m_failures(0),
     m_sequence(1),
     m_recvBufPos(0),
diff --git a/src/net/Client.h b/src/net/Client.h
index 62bb41966..6110488d0 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -60,8 +60,10 @@ public:
     void send(char *data);
     void setUrl(const Url *url);
 
+    inline const char *host() const          { return m_host; }
     inline int id() const                    { return m_id; }
     inline SocketState state() const         { return m_state; }
+    inline uint16_t port() const             { return m_port; }
     inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; }
     inline void setRetryPause(int ms)        { m_retryPause = ms; }
 
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index a69341674..692cfa7ad 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -36,7 +36,7 @@
 Network::Network(const Options *options) :
     m_donate(false),
     m_options(options),
-    m_pool(1)
+    m_pool(0)
 {
     m_pools.reserve(2);
     m_agent = userAgent();
@@ -61,13 +61,25 @@ Network::~Network()
 
 void Network::connect()
 {
-    m_pools.at(m_pool)->connect();
+    m_pools.at(1)->connect();
 }
 
 
 void Network::onClose(Client *client, int failures)
 {
-    LOG_DEBUG("CLOSE %d %d", client->id(), failures);
+    const int id = client->id();
+    if (id == 0 && failures == -1) {
+        m_donate = false;
+        return;
+    }
+
+    if (m_pool == id) {
+        m_pool = 0;
+    }
+
+    if (id == 1 && m_pools.size() > 2 && failures == m_options->retries()) {
+        m_pools.at(2)->connect();
+    }
 }
 
 
@@ -85,6 +97,23 @@ void Network::onLoginCredentialsRequired(Client *client)
 
 void Network::onLoginSuccess(Client *client)
 {
+    const int id = client->id();
+    if (id == 0) {
+        m_donate = true;
+        return;
+    }
+
+    if (id == 2 && m_pool) { // primary pool is already active
+        m_pools.at(2)->disconnect();
+        return;
+    }
+
+    LOG_NOTICE("use pool: \"%s:%d\"", client->host(), client->port());
+    m_pool = id;
+
+    if (m_pool == 1 && m_pools.size() > 2) { // try disconnect from backup pool
+        m_pools.at(2)->disconnect();
+    }
 }
 
 

From 1cf5ad5212b6837227a5c0ce99db0cfc3e67db8d Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 7 Jun 2017 22:34:23 +0300
Subject: [PATCH 18/56] Implemented switch to donate pool.

---
 CMakeLists.txt      |  2 +-
 src/Options.h       |  1 +
 src/net/Client.cpp  |  6 +++-
 src/net/Network.cpp | 71 +++++++++++++++++++++++++++++++++++++--------
 src/net/Network.h   |  6 ++++
 src/net/Url.cpp     |  7 +++++
 src/net/Url.h       |  1 +
 7 files changed, 80 insertions(+), 14 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index dc3feb367..82641462b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,7 +50,7 @@ if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
     set(CMAKE_BUILD_TYPE Release)
 endif()
 
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions")
 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate")
diff --git a/src/Options.h b/src/Options.h
index b2b1966df..16733ccab 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -57,6 +57,7 @@ public:
     inline const char *user() const     { return m_user; }
     inline const Url *backupUrl() const { return m_backupUrl; }
     inline const Url *url() const       { return m_url; }
+    inline int donateLevel() const      { return m_donateLevel; }
     inline int retries() const          { return m_retries; }
     inline int retryPause() const       { return m_retryPause; }
 
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index 38e7df25f..8fdf09e98 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -129,12 +129,16 @@ void Client::send(char *data)
         free(req);
     });
 
-    uv_timer_start(&m_responseTimer, [](uv_timer_t* handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0);
+    uv_timer_start(&m_responseTimer, [](uv_timer_t *handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0);
 }
 
 
 void Client::setUrl(const Url *url)
 {
+    if (!url || !url->isValid()) {
+        return;
+    }
+
     free(m_host);
     m_host = strdup(url->host());
     m_port = url->port();
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index 692cfa7ad..d513fddae 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -22,7 +22,6 @@
  */
 
 
-#include <uv.h>
 #include <memory>
 
 
@@ -41,11 +40,12 @@ Network::Network(const Options *options) :
     m_pools.reserve(2);
     m_agent = userAgent();
 
-    auto url = std::make_unique<Url>("donate.xmrig.com", 443);
-
-    addPool(url.get());
+    addPool(std::make_unique<Url>().get());
     addPool(m_options->url());
     addPool(m_options->backupUrl());
+
+    m_timer.data = this;
+    uv_timer_init(uv_default_loop(), &m_timer);
 }
 
 
@@ -61,15 +61,22 @@ Network::~Network()
 
 void Network::connect()
 {
-    m_pools.at(1)->connect();
+    m_pools[1]->connect();
+
+    if (m_options->donateLevel()) {
+        uv_timer_start(&m_timer, Network::onTimer, (100 - m_options->donateLevel()) * 60 * 1000, 0);
+    }
 }
 
 
 void Network::onClose(Client *client, int failures)
 {
     const int id = client->id();
-    if (id == 0 && failures == -1) {
-        m_donate = false;
+    if (id == 0) {
+        if (failures == -1) {
+            stopDonate();
+        }
+
         return;
     }
 
@@ -78,7 +85,7 @@ void Network::onClose(Client *client, int failures)
     }
 
     if (id == 1 && m_pools.size() > 2 && failures == m_options->retries()) {
-        m_pools.at(2)->connect();
+        m_pools[2]->connect();
     }
 }
 
@@ -99,12 +106,11 @@ void Network::onLoginSuccess(Client *client)
 {
     const int id = client->id();
     if (id == 0) {
-        m_donate = true;
-        return;
+        return startDonate();
     }
 
     if (id == 2 && m_pool) { // primary pool is already active
-        m_pools.at(2)->disconnect();
+        m_pools[2]->disconnect();
         return;
     }
 
@@ -112,7 +118,7 @@ void Network::onLoginSuccess(Client *client)
     m_pool = id;
 
     if (m_pool == 1 && m_pools.size() > 2) { // try disconnect from backup pool
-        m_pools.at(2)->disconnect();
+        m_pools[2]->disconnect();
     }
 }
 
@@ -130,3 +136,44 @@ void Network::addPool(const Url *url)
 
     m_pools.push_back(client);
 }
+
+
+void Network::startDonate()
+{
+    if (m_donate) {
+        return;
+    }
+
+    LOG_NOTICE("dev donate started");
+
+    m_donate = true;
+}
+
+
+void Network::stopDonate()
+{
+    if (!m_donate) {
+        return;
+    }
+
+    LOG_NOTICE("dev donate finished");
+
+    m_donate = false;
+}
+
+
+void Network::onTimer(uv_timer_t *handle)
+{
+    auto net = static_cast<Network*>(handle->data);
+
+    if (!net->m_donate) {
+        auto url = std::make_unique<Url>("donate.xmrig.com", 443);
+        net->m_pools[0]->connect(url.get());
+
+        uv_timer_start(&net->m_timer, Network::onTimer, net->m_options->donateLevel() * 60 * 1000, 0);
+        return;
+    }
+
+    net->m_pools[0]->disconnect();
+    uv_timer_start(&net->m_timer, Network::onTimer, (100 - net->m_options->donateLevel()) * 60 * 1000, 0);
+}
diff --git a/src/net/Network.h b/src/net/Network.h
index 89787012f..c8191a6ea 100644
--- a/src/net/Network.h
+++ b/src/net/Network.h
@@ -26,6 +26,7 @@
 
 
 #include <vector>
+#include <uv.h>
 
 
 #include "interfaces/IClientListener.h"
@@ -53,12 +54,17 @@ protected:
 
 private:
   void addPool(const Url *url);
+  void startDonate();
+  void stopDonate();
+
+  static void onTimer(uv_timer_t *handle);
 
   bool m_donate;
   char *m_agent;
   const Options *m_options;
   int m_pool;
   std::vector<Client*> m_pools;
+  uv_timer_t m_timer;
 };
 
 
diff --git a/src/net/Url.cpp b/src/net/Url.cpp
index f54b0b92c..4e1dfd9fe 100644
--- a/src/net/Url.cpp
+++ b/src/net/Url.cpp
@@ -29,6 +29,13 @@
 #include "net/Url.h"
 
 
+Url::Url() :
+    m_host(nullptr),
+    m_port(3333)
+{
+}
+
+
 /**
  * @brief Parse url.
  *
diff --git a/src/net/Url.h b/src/net/Url.h
index a0e2d48d9..7d44501d2 100644
--- a/src/net/Url.h
+++ b/src/net/Url.h
@@ -31,6 +31,7 @@
 class Url
 {
 public:
+    Url();
     Url(const char *url);
     Url(const char *host, uint16_t port);
     ~Url();

From 0556fd664c64af910db490b06ce3d4ae349a9d49 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Thu, 8 Jun 2017 00:10:26 +0300
Subject: [PATCH 19/56] Add Cpu class.

---
 CMakeLists.txt                      |  20 +++++-
 cpu.c                               | 100 ----------------------------
 src/App.cpp                         |  20 +-----
 cpu.h => src/Cpu.cpp                |  29 --------
 src/Cpu.h                           |  62 +++++++++++++++++
 cpu_stub.c => src/Cpu_stub.cpp      |  46 ++++++++-----
 unix/cpu_unix.c => src/Cpu_unix.cpp |  36 ----------
 win/cpu_win.c => src/Cpu_win.cpp    |  16 ++---
 8 files changed, 119 insertions(+), 210 deletions(-)
 delete mode 100644 cpu.c
 rename cpu.h => src/Cpu.cpp (66%)
 create mode 100644 src/Cpu.h
 rename cpu_stub.c => src/Cpu_stub.cpp (79%)
 rename unix/cpu_unix.c => src/Cpu_unix.cpp (60%)
 rename win/cpu_win.c => src/Cpu_win.cpp (84%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 82641462b..e863e7399 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,9 @@
 cmake_minimum_required(VERSION 3.0)
 project(xmrig)
 
+option(WITH_LIBCPUID "Use Libcpuid" ON)
+option(WITH_AEON     "CryptoNight-Lite support" ON)
+
 set(HEADERS
     src/App.h
     src/interfaces/IClientListener.h
@@ -10,6 +13,7 @@ set(HEADERS
     src/net/Url.h
     src/Options.h
     src/Console.h
+    src/Cpu.h
     src/version.h
    )
 
@@ -29,12 +33,13 @@ if (WIN32)
         res/app.rc
         src/3rdparty/winansi.cpp
         src/3rdparty/winansi.h
+        src/Cpu_win.cpp
         src/net/Network_win.cpp
         )
 
     set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
 else()
-    set(SOURCES_OS unix/cpu_unix.c unix/memory_unix.c unix/xmrig_unix.c)
+    set(SOURCES_OS src/Cpu_unix.cpp)
     set(EXTRA_LIBS pthread)
 endif()
 
@@ -60,6 +65,17 @@ if (WIN32)
     set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
 endif()
 
+if (WITH_LIBCPUID)
+#    add_subdirectory(compat/libcpuid)
+
+#    include_directories(compat/libcpuid)
+#    set(CPUID_LIB cpuid)
+#    set(SOURCES_CPUID cpu.c)
+else()
+    add_definitions(/DXMRIG_NO_LIBCPUID)
+    set(SOURCES_CPUID src/Cpu_stub.cpp)
+endif()
+
 include_directories(src)
 include_directories(src/3rdparty)
 include_directories(src/3rdparty/jansson)
@@ -67,5 +83,5 @@ include_directories(${UV_INCLUDE_DIR})
 
 add_subdirectory(src/3rdparty/jansson)
 
-add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS})
+add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID})
 target_link_libraries(xmrig jansson ${UV_LIBRARIES} ${EXTRA_LIBS})
diff --git a/cpu.c b/cpu.c
deleted file mode 100644
index 2f6ef8b6f..000000000
--- a/cpu.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <cpuid.h>
-#include <string.h>
-#include <stdbool.h>
-#include <math.h>
-
-#ifndef BUILD_TEST
-#   include <libcpuid.h>
-#endif
-
-#include "cpu.h"
-
-
-#ifndef BUILD_TEST
-void cpu_init_common() {
-    struct cpu_raw_data_t raw = { 0 };
-    struct cpu_id_t data = { 0 };
-
-    cpuid_get_raw_data(&raw);
-    cpu_identify(&raw, &data);
-
-    strncpy(cpu_info.brand, data.brand_str, sizeof(cpu_info.brand) - 1);
-
-    cpu_info.total_logical_cpus = data.total_logical_cpus;
-    cpu_info.sockets            = data.total_logical_cpus / data.num_logical_cpus;
-    cpu_info.total_cores        = data.num_cores * cpu_info.sockets;
-    cpu_info.l3_cache           = data.l3_cache > 0 ? data.l3_cache * cpu_info.sockets : 0;
-
-    // Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97
-    if (data.vendor == VENDOR_AMD && data.l3_cache <= 0 && data.l2_assoc == 16 && data.ext_family >= 21) {
-        cpu_info.l2_cache = data.l2_cache * (cpu_info.total_cores / 2) * cpu_info.sockets;
-    }
-    else {
-        cpu_info.l2_cache = data.l2_cache > 0 ? data.l2_cache * cpu_info.total_cores * cpu_info.sockets : 0;
-    }
-
-
-#   ifdef __x86_64__
-    cpu_info.flags |= CPU_FLAG_X86_64;
-#   endif
-
-    if (data.flags[CPU_FEATURE_AES]) {
-        cpu_info.flags |= CPU_FLAG_AES;
-    }
-
-    if (data.flags[CPU_FEATURE_BMI2]) {
-        cpu_info.flags |= CPU_FLAG_BMI2;
-    }
-}
-#endif
-
-
-int get_optimal_threads_count(int algo, bool double_hash, int max_cpu_usage) {
-    if (cpu_info.total_logical_cpus == 1) {
-        return 1;
-    }
-
-    int cache = cpu_info.l3_cache ? cpu_info.l3_cache : cpu_info.l2_cache;
-    int count = 0;
-    const int size = (algo ? 1024 : 2048) * (double_hash ? 2 : 1);
-
-    if (cache) {
-        count = cache / size;
-    }
-    else {
-        count = cpu_info.total_logical_cpus / 2;
-    }
-
-    if (count > cpu_info.total_logical_cpus) {
-        count = cpu_info.total_logical_cpus;
-    }
-
-    if (((float) count / cpu_info.total_logical_cpus * 100) > max_cpu_usage) {
-        count = ceil((float) cpu_info.total_logical_cpus * (max_cpu_usage / 100.0));
-    }
-
-    return count < 1 ? 1 : count;
-}
diff --git a/src/App.cpp b/src/App.cpp
index a82eb88cd..3269f80ef 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -27,26 +27,19 @@
 
 #include "App.h"
 #include "Console.h"
+#include "Cpu.h"
 #include "net/Client.h"
 #include "net/Network.h"
 #include "Options.h"
 #include "version.h"
 
 
-Client *client;
-uv_timer_t timer_req;
-
-
-void timer_cb(uv_timer_t* handle) {
-    LOG_DEBUG("TIMER");
-
-    client->disconnect();
-}
-
 
 App::App(int argc, char **argv)
 {
     Console::init();
+    Cpu::init();
+
     m_options = Options::parse(argc, argv);
     m_network = new Network(m_options);
 }
@@ -69,13 +62,6 @@ App::exec()
 
     m_network->connect();
 
-//    uv_timer_init(uv_default_loop(), &timer_req);
-//    uv_timer_start(&timer_req, timer_cb, 5000, 5000);
-
-
-//    client = new Client();
-//    client->connect("192.168.2.34", 3333);
-
     const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
     uv_loop_close(uv_default_loop());
 
diff --git a/cpu.h b/src/Cpu.cpp
similarity index 66%
rename from cpu.h
rename to src/Cpu.cpp
index 419192bf8..8140cd5f1 100644
--- a/cpu.h
+++ b/src/Cpu.cpp
@@ -21,33 +21,4 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __CPU_H__
-#define __CPU_H__
 
-#include <stdbool.h>
-
-struct cpu_info {
-    int total_cores;
-    int total_logical_cpus;
-    int flags;
-    int sockets;
-    int l2_cache;
-    int l3_cache;
-    char brand[64];
-};
-
-extern struct cpu_info cpu_info;
-
-
-enum cpu_flags {
-    CPU_FLAG_X86_64 = 1,
-    CPU_FLAG_AES    = 2,
-    CPU_FLAG_BMI2   = 4
-};
-
-
-void cpu_init();
-int get_optimal_threads_count(int algo, bool double_hash, int max_cpu_usage);
-int affine_to_cpu_mask(int id, unsigned long mask);
-
-#endif /* __CPU_H__ */
diff --git a/src/Cpu.h b/src/Cpu.h
new file mode 100644
index 000000000..7d9e64504
--- /dev/null
+++ b/src/Cpu.h
@@ -0,0 +1,62 @@
+/* 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/>.
+ */
+
+#ifndef __CPU_H__
+#define __CPU_H__
+
+
+class Cpu
+{
+public:
+    enum Flags {
+        X86_64 = 1,
+        AES    = 2,
+        BMI2   = 4
+    };
+
+    static int optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage);
+    static void init();
+    static void setAffinity(int id, unsigned long mask);
+
+    static inline bool hasAES()       { return m_flags & AES; }
+    static inline const char *brand() { return m_brand; }
+    static inline int cores()         { return m_totalCores; }
+    static inline int l2()            { return m_l2_cache; }
+    static inline int l3()            { return m_l3_cache; }
+    static inline int sockets()       { return m_sockets; }
+    static inline int threads()       { return m_totalThreads; }
+
+private:
+    static void initCommon();
+
+    static char m_brand[64];
+    static int m_flags;
+    static int m_l2_cache;
+    static int m_l3_cache;
+    static int m_sockets;
+    static int m_totalCores;
+    static int m_totalThreads;
+};
+
+
+#endif /* __CPU_H__ */
diff --git a/cpu_stub.c b/src/Cpu_stub.cpp
similarity index 79%
rename from cpu_stub.c
rename to src/Cpu_stub.cpp
index 83d5efc36..a04bce26b 100644
--- a/cpu_stub.c
+++ b/src/Cpu_stub.cpp
@@ -21,10 +21,12 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+
 #include <cpuid.h>
 #include <string.h>
-#include <stdbool.h>
-#include "cpu.h"
+
+
+#include "Cpu.h"
 
 
 #define VENDOR_ID                  (0)
@@ -52,7 +54,7 @@ static inline void cpuid(int level, int output[4]) {
 }
 
 
-static void cpu_brand_string(char* s) {
+static inline void cpu_brand_string(char* s) {
     int cpu_info[4] = { 0 };
     cpuid(VENDOR_ID, cpu_info);
 
@@ -66,7 +68,7 @@ static void cpu_brand_string(char* s) {
 }
 
 
-static bool has_aes_ni()
+static inline bool has_aes_ni()
 {
     int cpu_info[4] = { 0 };
     cpuid(PROCESSOR_INFO, cpu_info);
@@ -75,7 +77,7 @@ static bool has_aes_ni()
 }
 
 
-static bool has_bmi2() {
+static inline bool has_bmi2() {
     int cpu_info[4] = { 0 };
     cpuid(EXTENDED_FEATURES, cpu_info);
 
@@ -83,25 +85,35 @@ static bool has_bmi2() {
 }
 
 
-void cpu_init_common() {
-    cpu_info.sockets = 1;
-    cpu_brand_string(cpu_info.brand);
+char Cpu::m_brand[64]   = { 0 };
+int Cpu::m_flags        = 0;
+int Cpu::m_l2_cache     = 0;
+int Cpu::m_l3_cache     = 0;
+int Cpu::m_sockets      = 1;
+int Cpu::m_totalCores   = 0;
+int Cpu::m_totalThreads = 0;
+
+
+int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
+{
+    int count = m_totalThreads / 2;
+    return count < 1 ? 1 : count;
+}
+
+
+void Cpu::initCommon()
+{
+    cpu_brand_string(m_brand);
 
 #   ifdef __x86_64__
-    cpu_info.flags |= CPU_FLAG_X86_64;
+    m_flags |= X86_64;
 #   endif
 
     if (has_aes_ni()) {
-        cpu_info.flags |= CPU_FLAG_AES;
+        m_flags |= AES;
     }
 
     if (has_bmi2()) {
-        cpu_info.flags |= CPU_FLAG_BMI2;
+        m_flags |= BMI2;
     }
 }
-
-
-int get_optimal_threads_count(int algo, bool double_hash, int max_cpu_usage) {
-    int count = cpu_info.total_logical_cpus / 2;
-    return count < 1 ? 1 : count;
-}
diff --git a/unix/cpu_unix.c b/src/Cpu_unix.cpp
similarity index 60%
rename from unix/cpu_unix.c
rename to src/Cpu_unix.cpp
index 05b859b22..8140cd5f1 100644
--- a/unix/cpu_unix.c
+++ b/src/Cpu_unix.cpp
@@ -21,40 +21,4 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <unistd.h>
-#include <sched.h>
-#include <pthread.h>
 
-#include "cpu.h"
-
-
-struct cpu_info cpu_info = { 0 };
-void cpu_init_common();
-
-
-void cpu_init() {
-#   ifdef XMRIG_NO_LIBCPUID
-    cpu_info.total_logical_cpus = sysconf(_SC_NPROCESSORS_CONF);
-#   endif
-
-    cpu_init_common();
-}
-
-
-int affine_to_cpu_mask(int id, unsigned long mask)
-{
-    cpu_set_t set;
-    CPU_ZERO(&set);
-
-    for (unsigned i = 0; i < cpu_info.total_logical_cpus; i++) {
-        if (mask & (1UL << i)) {
-            CPU_SET(i, &set);
-        }
-    }
-
-    if (id == -1) {
-        sched_setaffinity(0, sizeof(&set), &set);
-    } else {
-        pthread_setaffinity_np(pthread_self(), sizeof(&set), &set);
-    }
-}
diff --git a/win/cpu_win.c b/src/Cpu_win.cpp
similarity index 84%
rename from win/cpu_win.c
rename to src/Cpu_win.cpp
index 6b5cc7fad..fe4ea0ba4 100644
--- a/win/cpu_win.c
+++ b/src/Cpu_win.cpp
@@ -21,29 +21,27 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+
 #include <windows.h>
-#include <stdbool.h>
-
-#include "cpu.h"
 
 
-struct cpu_info cpu_info = { 0 };
-void cpu_init_common();
+#include "Cpu.h"
 
 
-void cpu_init() {
+void Cpu::init()
+{
 #   ifdef XMRIG_NO_LIBCPUID
     SYSTEM_INFO sysinfo;
     GetSystemInfo(&sysinfo);
 
-    cpu_info.total_logical_cpus = sysinfo.dwNumberOfProcessors;
+    m_totalThreads = sysinfo.dwNumberOfProcessors;
 #   endif
 
-    cpu_init_common();
+    initCommon();
 }
 
 
-int affine_to_cpu_mask(int id, unsigned long mask)
+void Cpu::setAffinity(int id, unsigned long mask)
 {
     if (id == -1) {
         SetProcessAffinityMask(GetCurrentProcess(), mask);

From 9797f4945628c5fb2cafbf5b40a016b347476d22 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Thu, 8 Jun 2017 01:16:45 +0300
Subject: [PATCH 20/56] Add Summary.

---
 CMakeLists.txt                   |   2 +
 src/App.cpp                      |   3 +
 src/Cpu.h                        |   1 +
 src/Options.h                    |   1 +
 src/Summary.cpp                  |  85 ++++++++++++++++++++++
 utils/summary.h => src/Summary.h |   8 +-
 utils/summary.c                  | 121 -------------------------------
 7 files changed, 99 insertions(+), 122 deletions(-)
 create mode 100644 src/Summary.cpp
 rename utils/summary.h => src/Summary.h (95%)
 delete mode 100644 utils/summary.c

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e863e7399..662006233 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,6 +14,7 @@ set(HEADERS
     src/Options.h
     src/Console.h
     src/Cpu.h
+    src/Summary.h
     src/version.h
    )
 
@@ -25,6 +26,7 @@ set(SOURCES
     src/net/Url.cpp
     src/Options.cpp
     src/Console.cpp
+    src/Summary.cpp
     src/xmrig.cpp
    )
 
diff --git a/src/App.cpp b/src/App.cpp
index 3269f80ef..e7cf1aa46 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -31,6 +31,7 @@
 #include "net/Client.h"
 #include "net/Network.h"
 #include "Options.h"
+#include "Summary.h"
 #include "version.h"
 
 
@@ -60,6 +61,8 @@ App::exec()
         return 0;
     }
 
+    Summary::print();
+
     m_network->connect();
 
     const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
diff --git a/src/Cpu.h b/src/Cpu.h
index 7d9e64504..292c6c6c3 100644
--- a/src/Cpu.h
+++ b/src/Cpu.h
@@ -39,6 +39,7 @@ public:
     static void setAffinity(int id, unsigned long mask);
 
     static inline bool hasAES()       { return m_flags & AES; }
+    static inline bool isX64()        { return m_flags & X86_64; }
     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/Options.h b/src/Options.h
index 16733ccab..0c1dcc6eb 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -51,6 +51,7 @@ public:
     static inline Options* i() { return m_self; }
     static Options *parse(int argc, char **argv);
 
+    inline bool colors() const          { return m_colors; }
     inline bool isReady() const         { return m_ready; }
     inline bool keepAlive() const       { return m_keepAlive; }
     inline const char *pass() const     { return m_pass; }
diff --git a/src/Summary.cpp b/src/Summary.cpp
new file mode 100644
index 000000000..4e047360b
--- /dev/null
+++ b/src/Summary.cpp
@@ -0,0 +1,85 @@
+/* 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 <uv.h>
+
+
+#include "Summary.h"
+#include "Console.h"
+#include "Cpu.h"
+#include "Options.h"
+#include "version.h"
+
+
+
+static void print_versions()
+{
+    char *buf = static_cast<char*>(malloc(16));
+
+#   ifdef __GNUC__
+    snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
+#   else
+    buf[0] = '\0';
+#   endif
+
+
+    if (Options::i()->colors()) {
+        Console::i()->text("\x1B[01;32m * \x1B[01;37mVERSIONS:     \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s", APP_VERSION, uv_version_string(), buf);
+    } else {
+        Console::i()->text(" * VERSIONS:     XMRig/%s libuv/%s%s", APP_VERSION, uv_version_string(), buf);
+    }
+
+    free(buf);
+}
+
+
+static void print_cpu()
+{
+    if (Options::i()->colors()) {
+        Console::i()->text("\x1B[01;32m * \x1B[01;37mCPU:          %s (%d) %sx64 %sAES-NI",
+                           Cpu::brand(),
+                           Cpu::sockets(),
+                           Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-",
+                           Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-");
+#       ifndef XMRIG_NO_LIBCPUID
+        Console::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3:    %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
+#       endif
+    }
+    else {
+        Console::i()->text(" * CPU:          %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-");
+#       ifndef XMRIG_NO_LIBCPUID
+        Console::i()->text(" * CPU L2/L3:    %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
+#       endif
+    }
+}
+
+
+void Summary::print()
+{
+    print_versions();
+    print_cpu();
+}
+
+
+
diff --git a/utils/summary.h b/src/Summary.h
similarity index 95%
rename from utils/summary.h
rename to src/Summary.h
index 628c53044..3f64fd60c 100644
--- a/utils/summary.h
+++ b/src/Summary.h
@@ -24,6 +24,12 @@
 #ifndef __SUMMARY_H__
 #define __SUMMARY_H__
 
-void print_summary();
+
+class Summary
+{
+public:
+    static void print();
+};
+
 
 #endif /* __SUMMARY_H__ */
diff --git a/utils/summary.c b/utils/summary.c
deleted file mode 100644
index 65912bb0b..000000000
--- a/utils/summary.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 "options.h"
-#include "applog.h"
-#include "version.h"
-#include "persistent_memory.h"
-#include "cpu.h"
-
-
-static void print_memory() {
-    const char *t1 = (persistent_memory_flags & MEMORY_HUGEPAGES_AVAILABLE) ? OPT_COLOR(CL_LGR, "available") : OPT_COLOR(CL_LRD, "unavailable");
-    const char *t2 = (persistent_memory_flags & MEMORY_HUGEPAGES_ENABLED)   ? OPT_COLOR(CL_LGR, "enabled")   : OPT_COLOR(CL_LRD, "disabled");
-
-    if (opt_colors) {
-        applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "HUGE PAGES:   %s, %s", t1, t2);
-    }
-    else {
-        applog_notime(LOG_INFO, " * HUGE PAGES:   %s, %s", t1, t2);
-    }
-}
-
-
-static void print_cpu() {
-    const char *t1 = (cpu_info.flags & CPU_FLAG_X86_64) ? OPT_COLOR(CL_LGR, "x86_64") : OPT_COLOR(CL_LRD, "-x86_64");
-    const char *t2 = (cpu_info.flags & CPU_FLAG_AES)    ? OPT_COLOR(CL_LGR, "AES-NI") : OPT_COLOR(CL_LRD, "-AES-NI");
-
-    if (opt_colors) {
-        applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "CPU:          %s (%d)", cpu_info.brand, cpu_info.sockets);
-    }
-    else {
-        applog_notime(LOG_INFO, " * CPU:          %s (%d)", cpu_info.brand, cpu_info.sockets);
-    }
-
- #   ifndef XMRIG_NO_LIBCPUID
-    if (opt_colors) {
-        applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "CPU L2/L3:    %.1f MB/%.1f MB", cpu_info.l2_cache / 1024.0, cpu_info.l3_cache / 1024.0);
-    }
-    else {
-        applog_notime(LOG_INFO, " * CPU L2/L3:    %.1f MB/%.1f MB", cpu_info.l2_cache / 1024.0, cpu_info.l3_cache / 1024.0);
-    }
- #  endif
-
-    if (opt_colors) {
-        applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "CPU FEATURES: %s %s", t1, t2);
-    }
-    else {
-        applog_notime(LOG_INFO, " * CPU FEATURES: %s %s", t1, t2);
-    }
-}
-
-
-static void print_threads() {
-    const char *extra = "";
-    if (opt_nicehash) {
-        extra = ", nicehash";
-    }
-
-    if (opt_colors) {
-        applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "THREADS:      " CL_WHT "%d" CL_WHT ", av=%d, %s, donate=%d%%%s", opt_n_threads, opt_algo_variant, get_current_algo_name(), opt_donate_level, extra);
-    }
-    else {
-        applog_notime(LOG_INFO, " * THREADS:      %d, av=%d, %s, donate=%d%%%s", opt_n_threads, opt_algo_variant, get_current_algo_name(), opt_donate_level, extra);
-    }
-}
-
-
-static void print_stratum() {
-    if (opt_colors) {
-        applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "STRATUM URL:  " CL_LCY "%s", opt_url);
-
-        if (opt_backup_url) {
-            applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "FAILOVER URL: " CL_LCY "%s", opt_backup_url);
-        }
-        else {
-            applog_notime(LOG_INFO, CL_LGR " * " CL_WHT "FAILOVER URL: " CL_LRD "none");
-        }
-    }
-    else {
-        applog_notime(LOG_INFO, " * STRATUM URL:  %s", opt_url);
-        applog_notime(LOG_INFO, " * FAILOVER URL: %s", opt_backup_url ? opt_backup_url : "none");
-    }
-}
-
-
-void print_summary() {
-    if (opt_colors) {
-        applog_notime(LOG_INFO, CL_LGR " * " CL_WHT APP_NAME " " APP_VERSION "   " CL_LCY APP_SITE);
-    }
-    else {
-        applog_notime(LOG_INFO, " * " APP_NAME " " APP_VERSION "   " APP_SITE);
-    }
-
-    print_memory();
-    print_cpu();
-    print_threads();
-    print_stratum();
-}
-
-
-

From b11f95d2481d68b777605c096c1a46db7bd70b71 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Thu, 8 Jun 2017 01:51:24 +0300
Subject: [PATCH 21/56] Restore libcpuid support.

---
 CMakeLists.txt                                |  10 +-
 .../3rdparty}/libcpuid/CMakeLists.txt         |  14 +-
 .../3rdparty}/libcpuid/amd_code_t.h           |   0
 {compat => src/3rdparty}/libcpuid/asm-bits.c  |   0
 {compat => src/3rdparty}/libcpuid/asm-bits.h  |   0
 .../3rdparty}/libcpuid/cpuid_main.c           | 337 +++++++++++++++++-
 .../3rdparty}/libcpuid/intel_code_t.h         |   0
 {compat => src/3rdparty}/libcpuid/libcpuid.h  |   0
 .../3rdparty}/libcpuid/libcpuid_constants.h   |   0
 .../3rdparty}/libcpuid/libcpuid_internal.h    |  42 +++
 .../3rdparty}/libcpuid/libcpuid_types.h       |   0
 .../3rdparty}/libcpuid/libcpuid_util.c        |   0
 .../3rdparty}/libcpuid/libcpuid_util.h        |   2 -
 {compat => src/3rdparty}/libcpuid/recog_amd.c |  23 +-
 {compat => src/3rdparty}/libcpuid/recog_amd.h |   0
 .../3rdparty}/libcpuid/recog_intel.c          |  25 +-
 .../3rdparty}/libcpuid/recog_intel.h          |   0
 src/Cpu.cpp                                   |  81 +++++
 src/Summary.cpp                               |   3 +-
 19 files changed, 478 insertions(+), 59 deletions(-)
 rename {compat => src/3rdparty}/libcpuid/CMakeLists.txt (68%)
 rename {compat => src/3rdparty}/libcpuid/amd_code_t.h (100%)
 rename {compat => src/3rdparty}/libcpuid/asm-bits.c (100%)
 rename {compat => src/3rdparty}/libcpuid/asm-bits.h (100%)
 rename {compat => src/3rdparty}/libcpuid/cpuid_main.c (55%)
 rename {compat => src/3rdparty}/libcpuid/intel_code_t.h (100%)
 rename {compat => src/3rdparty}/libcpuid/libcpuid.h (100%)
 rename {compat => src/3rdparty}/libcpuid/libcpuid_constants.h (100%)
 rename {compat => src/3rdparty}/libcpuid/libcpuid_internal.h (66%)
 rename {compat => src/3rdparty}/libcpuid/libcpuid_types.h (100%)
 rename {compat => src/3rdparty}/libcpuid/libcpuid_util.c (100%)
 rename {compat => src/3rdparty}/libcpuid/libcpuid_util.h (98%)
 rename {compat => src/3rdparty}/libcpuid/recog_amd.c (98%)
 rename {compat => src/3rdparty}/libcpuid/recog_amd.h (100%)
 rename {compat => src/3rdparty}/libcpuid/recog_intel.c (98%)
 rename {compat => src/3rdparty}/libcpuid/recog_intel.h (100%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 662006233..11a6d1bcc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -68,11 +68,11 @@ if (WIN32)
 endif()
 
 if (WITH_LIBCPUID)
-#    add_subdirectory(compat/libcpuid)
+    add_subdirectory(src/3rdparty/libcpuid)
 
-#    include_directories(compat/libcpuid)
-#    set(CPUID_LIB cpuid)
-#    set(SOURCES_CPUID cpu.c)
+    include_directories(src/3rdparty/libcpuid)
+    set(CPUID_LIB cpuid)
+    set(SOURCES_CPUID src/Cpu.cpp)
 else()
     add_definitions(/DXMRIG_NO_LIBCPUID)
     set(SOURCES_CPUID src/Cpu_stub.cpp)
@@ -86,4 +86,4 @@ include_directories(${UV_INCLUDE_DIR})
 add_subdirectory(src/3rdparty/jansson)
 
 add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID})
-target_link_libraries(xmrig jansson ${UV_LIBRARIES} ${EXTRA_LIBS})
+target_link_libraries(xmrig jansson ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB})
diff --git a/compat/libcpuid/CMakeLists.txt b/src/3rdparty/libcpuid/CMakeLists.txt
similarity index 68%
rename from compat/libcpuid/CMakeLists.txt
rename to src/3rdparty/libcpuid/CMakeLists.txt
index 5c37492ab..ef541cc30 100644
--- a/compat/libcpuid/CMakeLists.txt
+++ b/src/3rdparty/libcpuid/CMakeLists.txt
@@ -3,17 +3,19 @@ project (cpuid C)
 
 add_definitions(/DVERSION="0.4.0")
 
+set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os")
+
 set(HEADERS
     libcpuid.h
     libcpuid_types.h
     libcpuid_constants.h
     libcpuid_internal.h
-amd_code_t.h
-intel_code_t.h
-recog_amd.h
-recog_intel.h
-asm-bits.h
-libcpuid_util.h
+    amd_code_t.h
+    intel_code_t.h
+    recog_amd.h
+    recog_intel.h
+    asm-bits.h
+    libcpuid_util.h
     )
 
 set(SOURCES
diff --git a/compat/libcpuid/amd_code_t.h b/src/3rdparty/libcpuid/amd_code_t.h
similarity index 100%
rename from compat/libcpuid/amd_code_t.h
rename to src/3rdparty/libcpuid/amd_code_t.h
diff --git a/compat/libcpuid/asm-bits.c b/src/3rdparty/libcpuid/asm-bits.c
similarity index 100%
rename from compat/libcpuid/asm-bits.c
rename to src/3rdparty/libcpuid/asm-bits.c
diff --git a/compat/libcpuid/asm-bits.h b/src/3rdparty/libcpuid/asm-bits.h
similarity index 100%
rename from compat/libcpuid/asm-bits.h
rename to src/3rdparty/libcpuid/asm-bits.h
diff --git a/compat/libcpuid/cpuid_main.c b/src/3rdparty/libcpuid/cpuid_main.c
similarity index 55%
rename from compat/libcpuid/cpuid_main.c
rename to src/3rdparty/libcpuid/cpuid_main.c
index 64c4198b4..504c0af8f 100644
--- a/compat/libcpuid/cpuid_main.c
+++ b/src/3rdparty/libcpuid/cpuid_main.c
@@ -117,7 +117,7 @@ static int get_total_cpus(void)
 #if defined linux || defined __linux__ || defined __sun
 #include <sys/sysinfo.h>
 #include <unistd.h>
-
+ 
 static int get_total_cpus(void)
 {
 	return sysconf(_SC_NPROCESSORS_ONLN);
@@ -302,7 +302,7 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
 		data->ext_model = data->model + (xmodel << 4);
 	}
 	ext = raw->ext_cpuid[0][0] - 0x8000000;
-
+	
 	/* obtain the brand string, if present: */
 	if (ext >= 4) {
 		for (i = 0; i < 3; i++)
@@ -401,6 +401,107 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data)
 	return set_error(ERR_OK);
 }
 
+int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
+{
+	int i;
+	FILE *f;
+	
+	if (!strcmp(filename, ""))
+		f = stdout;
+	else
+		f = fopen(filename, "wt");
+	if (!f) return set_error(ERR_OPEN);
+	
+	fprintf(f, "version=%s\n", VERSION);
+	for (i = 0; i < MAX_CPUID_LEVEL; i++)
+		fprintf(f, "basic_cpuid[%d]=%08x %08x %08x %08x\n", i,
+			data->basic_cpuid[i][0], data->basic_cpuid[i][1],
+			data->basic_cpuid[i][2], data->basic_cpuid[i][3]);
+	for (i = 0; i < MAX_EXT_CPUID_LEVEL; i++)
+		fprintf(f, "ext_cpuid[%d]=%08x %08x %08x %08x\n", i,
+			data->ext_cpuid[i][0], data->ext_cpuid[i][1],
+			data->ext_cpuid[i][2], data->ext_cpuid[i][3]);
+	for (i = 0; i < MAX_INTELFN4_LEVEL; i++)
+		fprintf(f, "intel_fn4[%d]=%08x %08x %08x %08x\n", i,
+			data->intel_fn4[i][0], data->intel_fn4[i][1],
+			data->intel_fn4[i][2], data->intel_fn4[i][3]);
+	for (i = 0; i < MAX_INTELFN11_LEVEL; i++)
+		fprintf(f, "intel_fn11[%d]=%08x %08x %08x %08x\n", i,
+			data->intel_fn11[i][0], data->intel_fn11[i][1],
+			data->intel_fn11[i][2], data->intel_fn11[i][3]);
+	for (i = 0; i < MAX_INTELFN12H_LEVEL; i++)
+		fprintf(f, "intel_fn12h[%d]=%08x %08x %08x %08x\n", i,
+			data->intel_fn12h[i][0], data->intel_fn12h[i][1],
+			data->intel_fn12h[i][2], data->intel_fn12h[i][3]);
+	for (i = 0; i < MAX_INTELFN14H_LEVEL; i++)
+		fprintf(f, "intel_fn14h[%d]=%08x %08x %08x %08x\n", i,
+			data->intel_fn14h[i][0], data->intel_fn14h[i][1],
+			data->intel_fn14h[i][2], data->intel_fn14h[i][3]);
+	
+	if (strcmp(filename, ""))
+		fclose(f);
+	return set_error(ERR_OK);
+}
+
+int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
+{
+	int i, len;
+	char line[100];
+	char token[100];
+	char *value;
+	int syntax;
+	int cur_line = 0;
+	int recognized;
+	FILE *f;
+	
+	raw_data_t_constructor(data);
+	
+	if (!strcmp(filename, ""))
+		f = stdin;
+	else
+		f = fopen(filename, "rt");
+	if (!f) return set_error(ERR_OPEN);
+	while (fgets(line, sizeof(line), f)) {
+		++cur_line;
+		len = (int) strlen(line);
+		if (len < 2) continue;
+		if (line[len - 1] == '\n')
+			line[--len] = '\0';
+		for (i = 0; i < len && line[i] != '='; i++)
+		if (i >= len && i < 1 && len - i - 1 <= 0) {
+			fclose(f);
+			return set_error(ERR_BADFMT);
+		}
+		strncpy(token, line, i);
+		token[i] = '\0';
+		value = &line[i + 1];
+		/* try to recognize the line */
+		recognized = 0;
+		if (!strcmp(token, "version") || !strcmp(token, "build_date")) {
+			recognized = 1;
+		}
+		syntax = 1;
+		syntax = syntax && parse_token("basic_cpuid", token, value, data->basic_cpuid,   MAX_CPUID_LEVEL, &recognized);
+		syntax = syntax && parse_token("ext_cpuid", token, value, data->ext_cpuid,       MAX_EXT_CPUID_LEVEL, &recognized);
+		syntax = syntax && parse_token("intel_fn4", token, value, data->intel_fn4,       MAX_INTELFN4_LEVEL, &recognized);
+		syntax = syntax && parse_token("intel_fn11", token, value, data->intel_fn11,     MAX_INTELFN11_LEVEL, &recognized);
+		syntax = syntax && parse_token("intel_fn12h", token, value, data->intel_fn12h,   MAX_INTELFN12H_LEVEL, &recognized);
+		syntax = syntax && parse_token("intel_fn14h", token, value, data->intel_fn14h,   MAX_INTELFN14H_LEVEL, &recognized);
+		if (!syntax) {
+			warnf("Error: %s:%d: Syntax error\n", filename, cur_line);
+			fclose(f);
+			return set_error(ERR_BADFMT);
+		}
+		if (!recognized) {
+			warnf("Warning: %s:%d not understood!\n", filename, cur_line);
+		}
+	}
+	
+	if (strcmp(filename, ""))
+		fclose(f);
+	return set_error(ERR_OK);
+}
+
 int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
 {
 	int r;
@@ -432,7 +533,239 @@ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
 	return cpu_ident_internal(raw, data, &throwaway);
 }
 
+const char* cpu_feature_str(cpu_feature_t feature)
+{
+	const struct { cpu_feature_t feature; const char* name; }
+	matchtable[] = {
+		{ CPU_FEATURE_FPU, "fpu" },
+		{ CPU_FEATURE_VME, "vme" },
+		{ CPU_FEATURE_DE, "de" },
+		{ CPU_FEATURE_PSE, "pse" },
+		{ CPU_FEATURE_TSC, "tsc" },
+		{ CPU_FEATURE_MSR, "msr" },
+		{ CPU_FEATURE_PAE, "pae" },
+		{ CPU_FEATURE_MCE, "mce" },
+		{ CPU_FEATURE_CX8, "cx8" },
+		{ CPU_FEATURE_APIC, "apic" },
+		{ CPU_FEATURE_MTRR, "mtrr" },
+		{ CPU_FEATURE_SEP, "sep" },
+		{ CPU_FEATURE_PGE, "pge" },
+		{ CPU_FEATURE_MCA, "mca" },
+		{ CPU_FEATURE_CMOV, "cmov" },
+		{ CPU_FEATURE_PAT, "pat" },
+		{ CPU_FEATURE_PSE36, "pse36" },
+		{ CPU_FEATURE_PN, "pn" },
+		{ CPU_FEATURE_CLFLUSH, "clflush" },
+		{ CPU_FEATURE_DTS, "dts" },
+		{ CPU_FEATURE_ACPI, "acpi" },
+		{ CPU_FEATURE_MMX, "mmx" },
+		{ CPU_FEATURE_FXSR, "fxsr" },
+		{ CPU_FEATURE_SSE, "sse" },
+		{ CPU_FEATURE_SSE2, "sse2" },
+		{ CPU_FEATURE_SS, "ss" },
+		{ CPU_FEATURE_HT, "ht" },
+		{ CPU_FEATURE_TM, "tm" },
+		{ CPU_FEATURE_IA64, "ia64" },
+		{ CPU_FEATURE_PBE, "pbe" },
+		{ CPU_FEATURE_PNI, "pni" },
+		{ CPU_FEATURE_PCLMUL, "pclmul" },
+		{ CPU_FEATURE_DTS64, "dts64" },
+		{ CPU_FEATURE_MONITOR, "monitor" },
+		{ CPU_FEATURE_DS_CPL, "ds_cpl" },
+		{ CPU_FEATURE_VMX, "vmx" },
+		{ CPU_FEATURE_SMX, "smx" },
+		{ CPU_FEATURE_EST, "est" },
+		{ CPU_FEATURE_TM2, "tm2" },
+		{ CPU_FEATURE_SSSE3, "ssse3" },
+		{ CPU_FEATURE_CID, "cid" },
+		{ CPU_FEATURE_CX16, "cx16" },
+		{ CPU_FEATURE_XTPR, "xtpr" },
+		{ CPU_FEATURE_PDCM, "pdcm" },
+		{ CPU_FEATURE_DCA, "dca" },
+		{ CPU_FEATURE_SSE4_1, "sse4_1" },
+		{ CPU_FEATURE_SSE4_2, "sse4_2" },
+		{ CPU_FEATURE_SYSCALL, "syscall" },
+		{ CPU_FEATURE_XD, "xd" },
+		{ CPU_FEATURE_X2APIC, "x2apic"},
+		{ CPU_FEATURE_MOVBE, "movbe" },
+		{ CPU_FEATURE_POPCNT, "popcnt" },
+		{ CPU_FEATURE_AES, "aes" },
+		{ CPU_FEATURE_XSAVE, "xsave" },
+		{ CPU_FEATURE_OSXSAVE, "osxsave" },
+		{ CPU_FEATURE_AVX, "avx" },
+		{ CPU_FEATURE_MMXEXT, "mmxext" },
+		{ CPU_FEATURE_3DNOW, "3dnow" },
+		{ CPU_FEATURE_3DNOWEXT, "3dnowext" },
+		{ CPU_FEATURE_NX, "nx" },
+		{ CPU_FEATURE_FXSR_OPT, "fxsr_opt" },
+		{ CPU_FEATURE_RDTSCP, "rdtscp" },
+		{ CPU_FEATURE_LM, "lm" },
+		{ CPU_FEATURE_LAHF_LM, "lahf_lm" },
+		{ CPU_FEATURE_CMP_LEGACY, "cmp_legacy" },
+		{ CPU_FEATURE_SVM, "svm" },
+		{ CPU_FEATURE_SSE4A, "sse4a" },
+		{ CPU_FEATURE_MISALIGNSSE, "misalignsse" },
+		{ CPU_FEATURE_ABM, "abm" },
+		{ CPU_FEATURE_3DNOWPREFETCH, "3dnowprefetch" },
+		{ CPU_FEATURE_OSVW, "osvw" },
+		{ CPU_FEATURE_IBS, "ibs" },
+		{ CPU_FEATURE_SSE5, "sse5" },
+		{ CPU_FEATURE_SKINIT, "skinit" },
+		{ CPU_FEATURE_WDT, "wdt" },
+		{ CPU_FEATURE_TS, "ts" },
+		{ CPU_FEATURE_FID, "fid" },
+		{ CPU_FEATURE_VID, "vid" },
+		{ CPU_FEATURE_TTP, "ttp" },
+		{ CPU_FEATURE_TM_AMD, "tm_amd" },
+		{ CPU_FEATURE_STC, "stc" },
+		{ CPU_FEATURE_100MHZSTEPS, "100mhzsteps" },
+		{ CPU_FEATURE_HWPSTATE, "hwpstate" },
+		{ CPU_FEATURE_CONSTANT_TSC, "constant_tsc" },
+		{ CPU_FEATURE_XOP, "xop" },
+		{ CPU_FEATURE_FMA3, "fma3" },
+		{ CPU_FEATURE_FMA4, "fma4" },
+		{ CPU_FEATURE_TBM, "tbm" },
+		{ CPU_FEATURE_F16C, "f16c" },
+		{ CPU_FEATURE_RDRAND, "rdrand" },
+		{ CPU_FEATURE_CPB, "cpb" },
+		{ CPU_FEATURE_APERFMPERF, "aperfmperf" },
+		{ CPU_FEATURE_PFI, "pfi" },
+		{ CPU_FEATURE_PA, "pa" },
+		{ CPU_FEATURE_AVX2, "avx2" },
+		{ CPU_FEATURE_BMI1, "bmi1" },
+		{ CPU_FEATURE_BMI2, "bmi2" },
+		{ CPU_FEATURE_HLE, "hle" },
+		{ CPU_FEATURE_RTM, "rtm" },
+		{ CPU_FEATURE_AVX512F, "avx512f" },
+		{ CPU_FEATURE_AVX512DQ, "avx512dq" },
+		{ CPU_FEATURE_AVX512PF, "avx512pf" },
+		{ CPU_FEATURE_AVX512ER, "avx512er" },
+		{ CPU_FEATURE_AVX512CD, "avx512cd" },
+		{ CPU_FEATURE_SHA_NI, "sha_ni" },
+		{ CPU_FEATURE_AVX512BW, "avx512bw" },
+		{ CPU_FEATURE_AVX512VL, "avx512vl" },
+		{ CPU_FEATURE_SGX, "sgx" },
+		{ CPU_FEATURE_RDSEED, "rdseed" },
+		{ CPU_FEATURE_ADX, "adx" },
+	};
+	unsigned i, n = COUNT_OF(matchtable);
+	if (n != NUM_CPU_FEATURES) {
+		warnf("Warning: incomplete library, feature matchtable size differs from the actual number of features.\n");
+	}
+	for (i = 0; i < n; i++)
+		if (matchtable[i].feature == feature)
+			return matchtable[i].name;
+	return "";
+}
+
+const char* cpuid_error(void)
+{
+	const struct { cpu_error_t error; const char *description; }
+	matchtable[] = {
+		{ ERR_OK       , "No error"},
+		{ ERR_NO_CPUID , "CPUID instruction is not supported"},
+		{ ERR_NO_RDTSC , "RDTSC instruction is not supported"},
+		{ ERR_NO_MEM   , "Memory allocation failed"},
+		{ ERR_OPEN     , "File open operation failed"},
+		{ ERR_BADFMT   , "Bad file format"},
+		{ ERR_NOT_IMP  , "Not implemented"},
+		{ ERR_CPU_UNKN , "Unsupported processor"},
+		{ ERR_NO_RDMSR , "RDMSR instruction is not supported"},
+		{ ERR_NO_DRIVER, "RDMSR driver error (generic)"},
+		{ ERR_NO_PERMS , "No permissions to install RDMSR driver"},
+		{ ERR_EXTRACT  , "Cannot extract RDMSR driver (read only media?)"},
+		{ ERR_HANDLE   , "Bad handle"},
+		{ ERR_INVMSR   , "Invalid MSR"},
+		{ ERR_INVCNB   , "Invalid core number"},
+		{ ERR_HANDLE_R , "Error on handle read"},
+		{ ERR_INVRANGE , "Invalid given range"},
+	};
+	unsigned i;
+	for (i = 0; i < COUNT_OF(matchtable); i++)
+		if (_libcpiud_errno == matchtable[i].error)
+			return matchtable[i].description;
+	return "Unknown error";
+}
+
+
 const char* cpuid_lib_version(void)
 {
 	return VERSION;
 }
+
+libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t new_fn)
+{
+	libcpuid_warn_fn_t ret = _warn_fun;
+	_warn_fun = new_fn;
+	return ret;
+}
+
+void cpuid_set_verbosiness_level(int level)
+{
+	_current_verboselevel = level;
+}
+
+cpu_vendor_t cpuid_get_vendor(void)
+{
+	static cpu_vendor_t vendor = VENDOR_UNKNOWN;
+	uint32_t raw_vendor[4];
+	char vendor_str[VENDOR_STR_MAX];
+
+	if(vendor == VENDOR_UNKNOWN) {
+		if (!cpuid_present())
+			set_error(ERR_NO_CPUID);
+		else {
+			cpu_exec_cpuid(0, raw_vendor);
+			vendor = cpuid_vendor_identify(raw_vendor, vendor_str);
+		}
+	}
+	return vendor;
+}
+
+void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list)
+{
+	switch (vendor) {
+		case VENDOR_INTEL:
+			cpuid_get_list_intel(list);
+			break;
+		case VENDOR_AMD:
+			cpuid_get_list_amd(list);
+			break;
+		case VENDOR_CYRIX:
+			make_list_from_string("Cx486,Cx5x86,6x86,6x86MX,M II,MediaGX,MediaGXi,MediaGXm", list);
+			break;
+		case VENDOR_NEXGEN:
+			make_list_from_string("Nx586", list);
+			break;
+		case VENDOR_TRANSMETA:
+			make_list_from_string("Crusoe,Efficeon", list);
+			break;
+		case VENDOR_UMC:
+			make_list_from_string("UMC x86 CPU", list);
+			break;
+		case VENDOR_CENTAUR:
+			make_list_from_string("VIA C3,VIA C7,VIA Nano", list);
+			break;
+		case VENDOR_RISE:
+			make_list_from_string("Rise mP6", list);
+			break;
+		case VENDOR_SIS:
+			make_list_from_string("SiS mP6", list);
+			break;
+		case VENDOR_NSC:
+			make_list_from_string("Geode GXm,Geode GXLV,Geode GX1,Geode GX2", list);
+			break;
+		default:
+			warnf("Unknown vendor passed to cpuid_get_cpu_list()\n");
+			break;
+ 	}
+}
+
+void cpuid_free_cpu_list(struct cpu_list_t* list)
+{
+	int i;
+	if (list->num_entries <= 0) return;
+	for (i = 0; i < list->num_entries; i++)
+		free(list->names[i]);
+	free(list->names);
+}
diff --git a/compat/libcpuid/intel_code_t.h b/src/3rdparty/libcpuid/intel_code_t.h
similarity index 100%
rename from compat/libcpuid/intel_code_t.h
rename to src/3rdparty/libcpuid/intel_code_t.h
diff --git a/compat/libcpuid/libcpuid.h b/src/3rdparty/libcpuid/libcpuid.h
similarity index 100%
rename from compat/libcpuid/libcpuid.h
rename to src/3rdparty/libcpuid/libcpuid.h
diff --git a/compat/libcpuid/libcpuid_constants.h b/src/3rdparty/libcpuid/libcpuid_constants.h
similarity index 100%
rename from compat/libcpuid/libcpuid_constants.h
rename to src/3rdparty/libcpuid/libcpuid_constants.h
diff --git a/compat/libcpuid/libcpuid_internal.h b/src/3rdparty/libcpuid/libcpuid_internal.h
similarity index 66%
rename from compat/libcpuid/libcpuid_internal.h
rename to src/3rdparty/libcpuid/libcpuid_internal.h
index 7f3671da6..038aa2092 100644
--- a/compat/libcpuid/libcpuid_internal.h
+++ b/src/3rdparty/libcpuid/libcpuid_internal.h
@@ -58,6 +58,48 @@ struct internal_id_info_t {
 	int score; // detection (matchtable) score
 };
 
+#define LBIT(x) (((long long) 1) << x)
+
+enum _common_bits_t {
+	_M_                     = LBIT(  0 ),
+	MOBILE_                 = LBIT(  1 ),
+	_MP_                    = LBIT(  2 ),
+};
+
+// additional detection bits for Intel CPUs:
+enum _intel_bits_t {
+	PENTIUM_                = LBIT( 10 ),
+	CELERON_                = LBIT( 11 ),
+	CORE_                   = LBIT( 12 ),
+	_I_                     = LBIT( 13 ),
+	_3                      = LBIT( 14 ),
+	_5                      = LBIT( 15 ),
+	_7                      = LBIT( 16 ),
+	XEON_                   = LBIT( 17 ),
+	ATOM_                   = LBIT( 18 ),
+};
+typedef enum _intel_bits_t intel_bits_t;
+
+enum _amd_bits_t {
+	ATHLON_      = LBIT( 10 ),
+	_XP_         = LBIT( 11 ),
+	DURON_       = LBIT( 12 ),
+	SEMPRON_     = LBIT( 13 ),
+	OPTERON_     = LBIT( 14 ),
+	TURION_      = LBIT( 15 ),
+	_LV_         = LBIT( 16 ),
+	_64_         = LBIT( 17 ),
+	_X2          = LBIT( 18 ),
+	_X3          = LBIT( 19 ),
+	_X4          = LBIT( 20 ),
+	_X6          = LBIT( 21 ),
+	_FX          = LBIT( 22 ),
+	_APU_        = LBIT( 23 ),
+};
+typedef enum _amd_bits_t amd_bits_t;
+
+
+
 int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data, 
 		       struct internal_id_info_t* internal);
 
diff --git a/compat/libcpuid/libcpuid_types.h b/src/3rdparty/libcpuid/libcpuid_types.h
similarity index 100%
rename from compat/libcpuid/libcpuid_types.h
rename to src/3rdparty/libcpuid/libcpuid_types.h
diff --git a/compat/libcpuid/libcpuid_util.c b/src/3rdparty/libcpuid/libcpuid_util.c
similarity index 100%
rename from compat/libcpuid/libcpuid_util.c
rename to src/3rdparty/libcpuid/libcpuid_util.c
diff --git a/compat/libcpuid/libcpuid_util.h b/src/3rdparty/libcpuid/libcpuid_util.h
similarity index 98%
rename from compat/libcpuid/libcpuid_util.h
rename to src/3rdparty/libcpuid/libcpuid_util.h
index aba63f1a9..c3b53933e 100644
--- a/compat/libcpuid/libcpuid_util.h
+++ b/src/3rdparty/libcpuid/libcpuid_util.h
@@ -28,8 +28,6 @@
 
 #define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
 
-#define LBIT(x) (((long long) 1) << x)
-
 struct feature_map_t {
 	unsigned bit;
 	cpu_feature_t feature;
diff --git a/compat/libcpuid/recog_amd.c b/src/3rdparty/libcpuid/recog_amd.c
similarity index 98%
rename from compat/libcpuid/recog_amd.c
rename to src/3rdparty/libcpuid/recog_amd.c
index b735c4005..3867aa8c6 100644
--- a/compat/libcpuid/recog_amd.c
+++ b/src/3rdparty/libcpuid/recog_amd.c
@@ -44,26 +44,6 @@ struct amd_code_and_bits_t {
 	uint64_t bits;
 };
 
-enum _amd_bits_t {
-	ATHLON_      = LBIT(  0 ),
-	_XP_         = LBIT(  1 ),
-	_M_          = LBIT(  2 ),
-	_MP_         = LBIT(  3 ),
-	MOBILE_      = LBIT(  4 ),
-	DURON_       = LBIT(  5 ),
-	SEMPRON_     = LBIT(  6 ),
-	OPTERON_     = LBIT(  7 ),
-	TURION_      = LBIT(  8 ),
-	_LV_         = LBIT(  9 ),
-	_64_         = LBIT( 10 ),
-	_X2          = LBIT( 11 ),
-	_X3          = LBIT( 12 ),
-	_X4          = LBIT( 13 ),
-	_X6          = LBIT( 14 ),
-	_FX          = LBIT( 15 ),
-};
-typedef enum _amd_bits_t amd_bits_t;
-
 enum _amd_model_codes_t {
 	// Only for Ryzen CPUs:
 	_1400,
@@ -469,11 +449,12 @@ static struct amd_code_and_bits_t decode_amd_codename_part1(const char *bs)
 	if (strstr(bs, "XP")) bits |= _XP_;
 	if (strstr(bs, "XP-M")) bits |= _M_;
 	if (strstr(bs, "(LV)")) bits |= _LV_;
+	if (strstr(bs, " APU ")) bits |= _APU_;
 
 	if (match_pattern(bs, "C-##")) code = FUSION_C;
 	if (match_pattern(bs, "E-###")) code = FUSION_E;
 	if (match_pattern(bs, "Z-##")) code = FUSION_Z;
-	if (match_pattern(bs, "E#-####") || match_pattern(bs, "A#-####")) code = FUSION_EA;
+	if (match_pattern(bs, "[EA]#-####")) code = FUSION_EA;
 
 	result.code = code;
 	result.bits = bits;
diff --git a/compat/libcpuid/recog_amd.h b/src/3rdparty/libcpuid/recog_amd.h
similarity index 100%
rename from compat/libcpuid/recog_amd.h
rename to src/3rdparty/libcpuid/recog_amd.h
diff --git a/compat/libcpuid/recog_intel.c b/src/3rdparty/libcpuid/recog_intel.c
similarity index 98%
rename from compat/libcpuid/recog_intel.c
rename to src/3rdparty/libcpuid/recog_intel.c
index 1d6c6a840..5e6c03b0e 100644
--- a/compat/libcpuid/recog_intel.c
+++ b/src/3rdparty/libcpuid/recog_intel.c
@@ -59,23 +59,6 @@ enum _intel_model_t {
 };
 typedef enum _intel_model_t intel_model_t;
 
-enum _intel_bits_t {
-	PENTIUM_                = LBIT(  0 ),
-	CELERON_                = LBIT(  1 ),
-	MOBILE_                 = LBIT(  2 ),
-	CORE_                   = LBIT(  3 ),
-	_I_                     = LBIT(  4 ),
-	_M_                     = LBIT(  5 ),
-	_3                      = LBIT(  6 ),
-	_5                      = LBIT(  7 ),
-	_7                      = LBIT(  8 ),
-	XEON_                   = LBIT(  9 ),
-	_MP                     = LBIT( 10 ),
-	ATOM_                   = LBIT( 11 ),
-	
-};
-typedef enum _intel_bits_t intel_bits_t;
-
 const struct match_entry_t cpudb_intel[] = {
 	{ -1, -1, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Unknown Intel CPU"       },
 	
@@ -158,11 +141,11 @@ const struct match_entry_t cpudb_intel[] = {
 	{ 15,  0, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Foster)"           },
 	{ 15,  1, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Foster)"           },
 	{ 15,  2, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Prestonia)"        },
-	{ 15,  2, -1, 15, -1,   1,    -1,    -1, NC, XEON_|_MP     ,     0, "Xeon (Gallatin)"         },
+	{ 15,  2, -1, 15, -1,   1,    -1,    -1, NC, XEON_|_MP_    ,     0, "Xeon (Gallatin)"         },
 	{ 15,  3, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Nocona)"           },
 	{ 15,  4, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Nocona)"           },
 	{ 15,  4, -1, 15, -1,   1,    -1,    -1, IRWIN, XEON_      ,     0, "Xeon (Irwindale)"        },
-	{ 15,  4, -1, 15, -1,   1,    -1,    -1, NC, XEON_|_MP     ,     0, "Xeon (Cranford)"         },
+	{ 15,  4, -1, 15, -1,   1,    -1,    -1, NC, XEON_|_MP_    ,     0, "Xeon (Cranford)"         },
 	{ 15,  4, -1, 15, -1,   1,    -1,    -1, POTOMAC, XEON_    ,     0, "Xeon (Potomac)"          },
 	{ 15,  6, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Dempsey)"          },
 	
@@ -668,7 +651,7 @@ static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data)
 	
 	const struct { uint64_t bit; const char* search; } bit_matchtable[] = {
 		{ XEON_, "Xeon" },
-		{ _MP, " MP" },
+		{ _MP_, " MP" },
 		{ ATOM_, "Atom(TM) CPU" },
 		{ MOBILE_, "Mobile" },
 		{ CELERON_, "Celeron" },
@@ -710,7 +693,7 @@ static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data)
 			/* restrict by family, since later Xeons also have L3 ... */
 			code = IRWIN;
 	}
-	if (match_all(bits, XEON_ + _MP) && data->l3_cache > 0)
+	if (match_all(bits, XEON_ + _MP_) && data->l3_cache > 0)
 		code = POTOMAC;
 	if (code == CORE_SOLO) {
 		s = strstr(bs, "CPU");
diff --git a/compat/libcpuid/recog_intel.h b/src/3rdparty/libcpuid/recog_intel.h
similarity index 100%
rename from compat/libcpuid/recog_intel.h
rename to src/3rdparty/libcpuid/recog_intel.h
diff --git a/src/Cpu.cpp b/src/Cpu.cpp
index 8140cd5f1..53d81e588 100644
--- a/src/Cpu.cpp
+++ b/src/Cpu.cpp
@@ -22,3 +22,84 @@
  */
 
 
+#include <libcpuid.h>
+#include <math.h>
+#include <string.h>
+
+#include "Cpu.h"
+
+
+char Cpu::m_brand[64]   = { 0 };
+int Cpu::m_flags        = 0;
+int Cpu::m_l2_cache     = 0;
+int Cpu::m_l3_cache     = 0;
+int Cpu::m_sockets      = 1;
+int Cpu::m_totalCores   = 0;
+int Cpu::m_totalThreads = 0;
+
+
+int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
+{
+    if (m_totalThreads == 1) {
+        return 1;
+    }
+
+    int cache = m_l3_cache ? m_l3_cache : m_l2_cache;
+    int count = 0;
+    const int size = (algo ? 1024 : 2048) * (doubleHash ? 2 : 1);
+
+    if (cache) {
+        count = cache / size;
+    }
+    else {
+        count = m_totalThreads / 2;
+    }
+
+    if (count > m_totalThreads) {
+        count = m_totalThreads;
+    }
+
+    if (((float) count / m_totalThreads * 100) > maxCpuUsage) {
+        count = ceil((float) m_totalThreads * (maxCpuUsage / 100.0));
+    }
+
+    return count < 1 ? 1 : count;
+}
+
+
+void Cpu::initCommon()
+{
+    struct cpu_raw_data_t raw = { 0 };
+    struct cpu_id_t data = { 0 };
+
+    cpuid_get_raw_data(&raw);
+    cpu_identify(&raw, &data);
+
+    strncpy(m_brand, data.brand_str, sizeof(m_brand) - 1);
+
+    m_totalThreads = data.total_logical_cpus;
+    m_sockets = m_totalThreads / data.num_logical_cpus;
+    m_totalCores = data.num_cores *m_sockets;
+
+    m_l3_cache = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0;
+
+    // Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97
+    if (data.vendor == VENDOR_AMD && data.l3_cache <= 0 && data.l2_assoc == 16 && data.ext_family >= 21) {
+        m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets;
+    }
+    else {
+        m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0;
+    }
+
+#   ifdef __x86_64__
+    m_flags |= X86_64;
+#   endif
+
+    if (data.flags[CPU_FEATURE_AES]) {
+        m_flags |= AES;
+    }
+
+    if (data.flags[CPU_FEATURE_BMI2]) {
+        m_flags |= BMI2;
+    }
+}
diff --git a/src/Summary.cpp b/src/Summary.cpp
index 4e047360b..38f1b1c55 100644
--- a/src/Summary.cpp
+++ b/src/Summary.cpp
@@ -25,14 +25,13 @@
 #include <uv.h>
 
 
-#include "Summary.h"
 #include "Console.h"
 #include "Cpu.h"
 #include "Options.h"
+#include "Summary.h"
 #include "version.h"
 
 
-
 static void print_versions()
 {
     char *buf = static_cast<char*>(malloc(16));

From da02e9a3a2811fd74fa2ea2bdd8e606c02c3b1a3 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Thu, 8 Jun 2017 04:16:55 +0300
Subject: [PATCH 22/56] Reduce libcpuid size.

---
 src/3rdparty/libcpuid/cpuid_main.c    | 438 ++----------------------
 src/3rdparty/libcpuid/libcpuid.h      | 473 --------------------------
 src/3rdparty/libcpuid/libcpuid_util.c | 125 -------
 src/3rdparty/libcpuid/libcpuid_util.h |  20 --
 src/3rdparty/libcpuid/recog_amd.c     | 361 --------------------
 src/3rdparty/libcpuid/recog_amd.h     |   1 -
 src/3rdparty/libcpuid/recog_intel.c   | 376 --------------------
 src/3rdparty/libcpuid/recog_intel.h   |   1 -
 8 files changed, 28 insertions(+), 1767 deletions(-)

diff --git a/src/3rdparty/libcpuid/cpuid_main.c b/src/3rdparty/libcpuid/cpuid_main.c
index 504c0af8f..f22c7dd69 100644
--- a/src/3rdparty/libcpuid/cpuid_main.c
+++ b/src/3rdparty/libcpuid/cpuid_main.c
@@ -46,11 +46,6 @@ int set_error(cpu_error_t err)
 	return (int) err;
 }
 
-static void raw_data_t_constructor(struct cpu_raw_data_t* raw)
-{
-	memset(raw, 0, sizeof(struct cpu_raw_data_t));
-}
-
 static void cpu_id_t_constructor(struct cpu_id_t* id)
 {
 	memset(id, 0, sizeof(struct cpu_id_t));
@@ -60,29 +55,6 @@ static void cpu_id_t_constructor(struct cpu_id_t* id)
 	id->sse_size = -1;
 }
 
-static int parse_token(const char* expected_token, const char *token,
-                        const char *value, uint32_t array[][4], int limit, int *recognized)
-{
-	char format[32];
-	int veax, vebx, vecx, vedx;
-	int index;
-
-	if (*recognized) return 1; /* already recognized */
-	if (strncmp(token, expected_token, strlen(expected_token))) return 1; /* not what we search for */
-	sprintf(format, "%s[%%d]", expected_token);
-	*recognized = 1;
-	if (1 == sscanf(token, format, &index) && index >=0 && index < limit) {
-		if (4 == sscanf(value, "%x%x%x%x", &veax, &vebx, &vecx, &vedx)) {
-			array[index][0] = veax;
-			array[index][1] = vebx;
-			array[index][2] = vecx;
-			array[index][3] = vedx;
-			return 1;
-		}
-	}
-	return 0;
-}
-
 /* get_total_cpus() system specific code: uses OS routines to determine total number of CPUs */
 #ifdef __APPLE__
 #include <unistd.h>
@@ -249,42 +221,42 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
 
 static cpu_vendor_t cpuid_vendor_identify(const uint32_t *raw_vendor, char *vendor_str)
 {
-	int i;
-	cpu_vendor_t vendor = VENDOR_UNKNOWN;
-	const struct { cpu_vendor_t vendor; char match[16]; }
-	matchtable[NUM_CPU_VENDORS] = {
-		/* source: http://www.sandpile.org/ia32/cpuid.htm */
-		{ VENDOR_INTEL		, "GenuineIntel" },
-		{ VENDOR_AMD		, "AuthenticAMD" },
-		{ VENDOR_CYRIX		, "CyrixInstead" },
-		{ VENDOR_NEXGEN		, "NexGenDriven" },
-		{ VENDOR_TRANSMETA	, "GenuineTMx86" },
-		{ VENDOR_UMC		, "UMC UMC UMC " },
-		{ VENDOR_CENTAUR	, "CentaurHauls" },
-		{ VENDOR_RISE		, "RiseRiseRise" },
-		{ VENDOR_SIS		, "SiS SiS SiS " },
-		{ VENDOR_NSC		, "Geode by NSC" },
-	};
+    int i;
+    cpu_vendor_t vendor = VENDOR_UNKNOWN;
+    const struct { cpu_vendor_t vendor; char match[16]; }
+    matchtable[NUM_CPU_VENDORS] = {
+        /* source: http://www.sandpile.org/ia32/cpuid.htm */
+        { VENDOR_INTEL		, "GenuineIntel" },
+        { VENDOR_AMD		, "AuthenticAMD" },
+        { VENDOR_CYRIX		, "CyrixInstead" },
+        { VENDOR_NEXGEN		, "NexGenDriven" },
+        { VENDOR_TRANSMETA	, "GenuineTMx86" },
+        { VENDOR_UMC		, "UMC UMC UMC " },
+        { VENDOR_CENTAUR	, "CentaurHauls" },
+        { VENDOR_RISE		, "RiseRiseRise" },
+        { VENDOR_SIS		, "SiS SiS SiS " },
+        { VENDOR_NSC		, "Geode by NSC" },
+    };
 
-	memcpy(vendor_str + 0, &raw_vendor[1], 4);
-	memcpy(vendor_str + 4, &raw_vendor[3], 4);
-	memcpy(vendor_str + 8, &raw_vendor[2], 4);
-	vendor_str[12] = 0;
+    memcpy(vendor_str + 0, &raw_vendor[1], 4);
+    memcpy(vendor_str + 4, &raw_vendor[3], 4);
+    memcpy(vendor_str + 8, &raw_vendor[2], 4);
+    vendor_str[12] = 0;
 
-	/* Determine vendor: */
-	for (i = 0; i < NUM_CPU_VENDORS; i++)
-		if (!strcmp(vendor_str, matchtable[i].match)) {
-			vendor = matchtable[i].vendor;
-			break;
-		}
-	return vendor;
+    /* Determine vendor: */
+    for (i = 0; i < NUM_CPU_VENDORS; i++)
+        if (!strcmp(vendor_str, matchtable[i].match)) {
+            vendor = matchtable[i].vendor;
+            break;
+        }
+    return vendor;
 }
 
 static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
 {
 	int i, j, basic, xmodel, xfamily, ext;
 	char brandstr[64] = {0};
-	data->vendor = cpuid_vendor_identify(raw->basic_cpuid[0], data->vendor_str);
+    data->vendor = cpuid_vendor_identify(raw->basic_cpuid[0], data->vendor_str);
 
 	if (data->vendor == VENDOR_UNKNOWN)
 		return set_error(ERR_CPU_UNKN);
@@ -320,27 +292,6 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
 	return set_error(ERR_OK);
 }
 
-static void make_list_from_string(const char* csv, struct cpu_list_t* list)
-{
-	int i, n, l, last;
-	l = (int) strlen(csv);
-	n = 0;
-	for (i = 0; i < l; i++) if (csv[i] == ',') n++;
-	n++;
-	list->num_entries = n;
-	list->names = (char**) malloc(sizeof(char*) * n);
-	last = -1;
-	n = 0;
-	for (i = 0; i <= l; i++) if (i == l || csv[i] == ',') {
-		list->names[n] = (char*) malloc(i - last);
-		memcpy(list->names[n], &csv[last + 1], i - last - 1);
-		list->names[n][i - last - 1] = '\0';
-		n++;
-		last = i;
-	}
-}
-
-
 /* Interface: */
 
 int cpuid_get_total_cpus(void)
@@ -401,107 +352,6 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data)
 	return set_error(ERR_OK);
 }
 
-int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
-{
-	int i;
-	FILE *f;
-	
-	if (!strcmp(filename, ""))
-		f = stdout;
-	else
-		f = fopen(filename, "wt");
-	if (!f) return set_error(ERR_OPEN);
-	
-	fprintf(f, "version=%s\n", VERSION);
-	for (i = 0; i < MAX_CPUID_LEVEL; i++)
-		fprintf(f, "basic_cpuid[%d]=%08x %08x %08x %08x\n", i,
-			data->basic_cpuid[i][0], data->basic_cpuid[i][1],
-			data->basic_cpuid[i][2], data->basic_cpuid[i][3]);
-	for (i = 0; i < MAX_EXT_CPUID_LEVEL; i++)
-		fprintf(f, "ext_cpuid[%d]=%08x %08x %08x %08x\n", i,
-			data->ext_cpuid[i][0], data->ext_cpuid[i][1],
-			data->ext_cpuid[i][2], data->ext_cpuid[i][3]);
-	for (i = 0; i < MAX_INTELFN4_LEVEL; i++)
-		fprintf(f, "intel_fn4[%d]=%08x %08x %08x %08x\n", i,
-			data->intel_fn4[i][0], data->intel_fn4[i][1],
-			data->intel_fn4[i][2], data->intel_fn4[i][3]);
-	for (i = 0; i < MAX_INTELFN11_LEVEL; i++)
-		fprintf(f, "intel_fn11[%d]=%08x %08x %08x %08x\n", i,
-			data->intel_fn11[i][0], data->intel_fn11[i][1],
-			data->intel_fn11[i][2], data->intel_fn11[i][3]);
-	for (i = 0; i < MAX_INTELFN12H_LEVEL; i++)
-		fprintf(f, "intel_fn12h[%d]=%08x %08x %08x %08x\n", i,
-			data->intel_fn12h[i][0], data->intel_fn12h[i][1],
-			data->intel_fn12h[i][2], data->intel_fn12h[i][3]);
-	for (i = 0; i < MAX_INTELFN14H_LEVEL; i++)
-		fprintf(f, "intel_fn14h[%d]=%08x %08x %08x %08x\n", i,
-			data->intel_fn14h[i][0], data->intel_fn14h[i][1],
-			data->intel_fn14h[i][2], data->intel_fn14h[i][3]);
-	
-	if (strcmp(filename, ""))
-		fclose(f);
-	return set_error(ERR_OK);
-}
-
-int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
-{
-	int i, len;
-	char line[100];
-	char token[100];
-	char *value;
-	int syntax;
-	int cur_line = 0;
-	int recognized;
-	FILE *f;
-	
-	raw_data_t_constructor(data);
-	
-	if (!strcmp(filename, ""))
-		f = stdin;
-	else
-		f = fopen(filename, "rt");
-	if (!f) return set_error(ERR_OPEN);
-	while (fgets(line, sizeof(line), f)) {
-		++cur_line;
-		len = (int) strlen(line);
-		if (len < 2) continue;
-		if (line[len - 1] == '\n')
-			line[--len] = '\0';
-		for (i = 0; i < len && line[i] != '='; i++)
-		if (i >= len && i < 1 && len - i - 1 <= 0) {
-			fclose(f);
-			return set_error(ERR_BADFMT);
-		}
-		strncpy(token, line, i);
-		token[i] = '\0';
-		value = &line[i + 1];
-		/* try to recognize the line */
-		recognized = 0;
-		if (!strcmp(token, "version") || !strcmp(token, "build_date")) {
-			recognized = 1;
-		}
-		syntax = 1;
-		syntax = syntax && parse_token("basic_cpuid", token, value, data->basic_cpuid,   MAX_CPUID_LEVEL, &recognized);
-		syntax = syntax && parse_token("ext_cpuid", token, value, data->ext_cpuid,       MAX_EXT_CPUID_LEVEL, &recognized);
-		syntax = syntax && parse_token("intel_fn4", token, value, data->intel_fn4,       MAX_INTELFN4_LEVEL, &recognized);
-		syntax = syntax && parse_token("intel_fn11", token, value, data->intel_fn11,     MAX_INTELFN11_LEVEL, &recognized);
-		syntax = syntax && parse_token("intel_fn12h", token, value, data->intel_fn12h,   MAX_INTELFN12H_LEVEL, &recognized);
-		syntax = syntax && parse_token("intel_fn14h", token, value, data->intel_fn14h,   MAX_INTELFN14H_LEVEL, &recognized);
-		if (!syntax) {
-			warnf("Error: %s:%d: Syntax error\n", filename, cur_line);
-			fclose(f);
-			return set_error(ERR_BADFMT);
-		}
-		if (!recognized) {
-			warnf("Warning: %s:%d not understood!\n", filename, cur_line);
-		}
-	}
-	
-	if (strcmp(filename, ""))
-		fclose(f);
-	return set_error(ERR_OK);
-}
-
 int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
 {
 	int r;
@@ -533,239 +383,7 @@ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
 	return cpu_ident_internal(raw, data, &throwaway);
 }
 
-const char* cpu_feature_str(cpu_feature_t feature)
-{
-	const struct { cpu_feature_t feature; const char* name; }
-	matchtable[] = {
-		{ CPU_FEATURE_FPU, "fpu" },
-		{ CPU_FEATURE_VME, "vme" },
-		{ CPU_FEATURE_DE, "de" },
-		{ CPU_FEATURE_PSE, "pse" },
-		{ CPU_FEATURE_TSC, "tsc" },
-		{ CPU_FEATURE_MSR, "msr" },
-		{ CPU_FEATURE_PAE, "pae" },
-		{ CPU_FEATURE_MCE, "mce" },
-		{ CPU_FEATURE_CX8, "cx8" },
-		{ CPU_FEATURE_APIC, "apic" },
-		{ CPU_FEATURE_MTRR, "mtrr" },
-		{ CPU_FEATURE_SEP, "sep" },
-		{ CPU_FEATURE_PGE, "pge" },
-		{ CPU_FEATURE_MCA, "mca" },
-		{ CPU_FEATURE_CMOV, "cmov" },
-		{ CPU_FEATURE_PAT, "pat" },
-		{ CPU_FEATURE_PSE36, "pse36" },
-		{ CPU_FEATURE_PN, "pn" },
-		{ CPU_FEATURE_CLFLUSH, "clflush" },
-		{ CPU_FEATURE_DTS, "dts" },
-		{ CPU_FEATURE_ACPI, "acpi" },
-		{ CPU_FEATURE_MMX, "mmx" },
-		{ CPU_FEATURE_FXSR, "fxsr" },
-		{ CPU_FEATURE_SSE, "sse" },
-		{ CPU_FEATURE_SSE2, "sse2" },
-		{ CPU_FEATURE_SS, "ss" },
-		{ CPU_FEATURE_HT, "ht" },
-		{ CPU_FEATURE_TM, "tm" },
-		{ CPU_FEATURE_IA64, "ia64" },
-		{ CPU_FEATURE_PBE, "pbe" },
-		{ CPU_FEATURE_PNI, "pni" },
-		{ CPU_FEATURE_PCLMUL, "pclmul" },
-		{ CPU_FEATURE_DTS64, "dts64" },
-		{ CPU_FEATURE_MONITOR, "monitor" },
-		{ CPU_FEATURE_DS_CPL, "ds_cpl" },
-		{ CPU_FEATURE_VMX, "vmx" },
-		{ CPU_FEATURE_SMX, "smx" },
-		{ CPU_FEATURE_EST, "est" },
-		{ CPU_FEATURE_TM2, "tm2" },
-		{ CPU_FEATURE_SSSE3, "ssse3" },
-		{ CPU_FEATURE_CID, "cid" },
-		{ CPU_FEATURE_CX16, "cx16" },
-		{ CPU_FEATURE_XTPR, "xtpr" },
-		{ CPU_FEATURE_PDCM, "pdcm" },
-		{ CPU_FEATURE_DCA, "dca" },
-		{ CPU_FEATURE_SSE4_1, "sse4_1" },
-		{ CPU_FEATURE_SSE4_2, "sse4_2" },
-		{ CPU_FEATURE_SYSCALL, "syscall" },
-		{ CPU_FEATURE_XD, "xd" },
-		{ CPU_FEATURE_X2APIC, "x2apic"},
-		{ CPU_FEATURE_MOVBE, "movbe" },
-		{ CPU_FEATURE_POPCNT, "popcnt" },
-		{ CPU_FEATURE_AES, "aes" },
-		{ CPU_FEATURE_XSAVE, "xsave" },
-		{ CPU_FEATURE_OSXSAVE, "osxsave" },
-		{ CPU_FEATURE_AVX, "avx" },
-		{ CPU_FEATURE_MMXEXT, "mmxext" },
-		{ CPU_FEATURE_3DNOW, "3dnow" },
-		{ CPU_FEATURE_3DNOWEXT, "3dnowext" },
-		{ CPU_FEATURE_NX, "nx" },
-		{ CPU_FEATURE_FXSR_OPT, "fxsr_opt" },
-		{ CPU_FEATURE_RDTSCP, "rdtscp" },
-		{ CPU_FEATURE_LM, "lm" },
-		{ CPU_FEATURE_LAHF_LM, "lahf_lm" },
-		{ CPU_FEATURE_CMP_LEGACY, "cmp_legacy" },
-		{ CPU_FEATURE_SVM, "svm" },
-		{ CPU_FEATURE_SSE4A, "sse4a" },
-		{ CPU_FEATURE_MISALIGNSSE, "misalignsse" },
-		{ CPU_FEATURE_ABM, "abm" },
-		{ CPU_FEATURE_3DNOWPREFETCH, "3dnowprefetch" },
-		{ CPU_FEATURE_OSVW, "osvw" },
-		{ CPU_FEATURE_IBS, "ibs" },
-		{ CPU_FEATURE_SSE5, "sse5" },
-		{ CPU_FEATURE_SKINIT, "skinit" },
-		{ CPU_FEATURE_WDT, "wdt" },
-		{ CPU_FEATURE_TS, "ts" },
-		{ CPU_FEATURE_FID, "fid" },
-		{ CPU_FEATURE_VID, "vid" },
-		{ CPU_FEATURE_TTP, "ttp" },
-		{ CPU_FEATURE_TM_AMD, "tm_amd" },
-		{ CPU_FEATURE_STC, "stc" },
-		{ CPU_FEATURE_100MHZSTEPS, "100mhzsteps" },
-		{ CPU_FEATURE_HWPSTATE, "hwpstate" },
-		{ CPU_FEATURE_CONSTANT_TSC, "constant_tsc" },
-		{ CPU_FEATURE_XOP, "xop" },
-		{ CPU_FEATURE_FMA3, "fma3" },
-		{ CPU_FEATURE_FMA4, "fma4" },
-		{ CPU_FEATURE_TBM, "tbm" },
-		{ CPU_FEATURE_F16C, "f16c" },
-		{ CPU_FEATURE_RDRAND, "rdrand" },
-		{ CPU_FEATURE_CPB, "cpb" },
-		{ CPU_FEATURE_APERFMPERF, "aperfmperf" },
-		{ CPU_FEATURE_PFI, "pfi" },
-		{ CPU_FEATURE_PA, "pa" },
-		{ CPU_FEATURE_AVX2, "avx2" },
-		{ CPU_FEATURE_BMI1, "bmi1" },
-		{ CPU_FEATURE_BMI2, "bmi2" },
-		{ CPU_FEATURE_HLE, "hle" },
-		{ CPU_FEATURE_RTM, "rtm" },
-		{ CPU_FEATURE_AVX512F, "avx512f" },
-		{ CPU_FEATURE_AVX512DQ, "avx512dq" },
-		{ CPU_FEATURE_AVX512PF, "avx512pf" },
-		{ CPU_FEATURE_AVX512ER, "avx512er" },
-		{ CPU_FEATURE_AVX512CD, "avx512cd" },
-		{ CPU_FEATURE_SHA_NI, "sha_ni" },
-		{ CPU_FEATURE_AVX512BW, "avx512bw" },
-		{ CPU_FEATURE_AVX512VL, "avx512vl" },
-		{ CPU_FEATURE_SGX, "sgx" },
-		{ CPU_FEATURE_RDSEED, "rdseed" },
-		{ CPU_FEATURE_ADX, "adx" },
-	};
-	unsigned i, n = COUNT_OF(matchtable);
-	if (n != NUM_CPU_FEATURES) {
-		warnf("Warning: incomplete library, feature matchtable size differs from the actual number of features.\n");
-	}
-	for (i = 0; i < n; i++)
-		if (matchtable[i].feature == feature)
-			return matchtable[i].name;
-	return "";
-}
-
-const char* cpuid_error(void)
-{
-	const struct { cpu_error_t error; const char *description; }
-	matchtable[] = {
-		{ ERR_OK       , "No error"},
-		{ ERR_NO_CPUID , "CPUID instruction is not supported"},
-		{ ERR_NO_RDTSC , "RDTSC instruction is not supported"},
-		{ ERR_NO_MEM   , "Memory allocation failed"},
-		{ ERR_OPEN     , "File open operation failed"},
-		{ ERR_BADFMT   , "Bad file format"},
-		{ ERR_NOT_IMP  , "Not implemented"},
-		{ ERR_CPU_UNKN , "Unsupported processor"},
-		{ ERR_NO_RDMSR , "RDMSR instruction is not supported"},
-		{ ERR_NO_DRIVER, "RDMSR driver error (generic)"},
-		{ ERR_NO_PERMS , "No permissions to install RDMSR driver"},
-		{ ERR_EXTRACT  , "Cannot extract RDMSR driver (read only media?)"},
-		{ ERR_HANDLE   , "Bad handle"},
-		{ ERR_INVMSR   , "Invalid MSR"},
-		{ ERR_INVCNB   , "Invalid core number"},
-		{ ERR_HANDLE_R , "Error on handle read"},
-		{ ERR_INVRANGE , "Invalid given range"},
-	};
-	unsigned i;
-	for (i = 0; i < COUNT_OF(matchtable); i++)
-		if (_libcpiud_errno == matchtable[i].error)
-			return matchtable[i].description;
-	return "Unknown error";
-}
-
-
 const char* cpuid_lib_version(void)
 {
 	return VERSION;
 }
-
-libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t new_fn)
-{
-	libcpuid_warn_fn_t ret = _warn_fun;
-	_warn_fun = new_fn;
-	return ret;
-}
-
-void cpuid_set_verbosiness_level(int level)
-{
-	_current_verboselevel = level;
-}
-
-cpu_vendor_t cpuid_get_vendor(void)
-{
-	static cpu_vendor_t vendor = VENDOR_UNKNOWN;
-	uint32_t raw_vendor[4];
-	char vendor_str[VENDOR_STR_MAX];
-
-	if(vendor == VENDOR_UNKNOWN) {
-		if (!cpuid_present())
-			set_error(ERR_NO_CPUID);
-		else {
-			cpu_exec_cpuid(0, raw_vendor);
-			vendor = cpuid_vendor_identify(raw_vendor, vendor_str);
-		}
-	}
-	return vendor;
-}
-
-void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list)
-{
-	switch (vendor) {
-		case VENDOR_INTEL:
-			cpuid_get_list_intel(list);
-			break;
-		case VENDOR_AMD:
-			cpuid_get_list_amd(list);
-			break;
-		case VENDOR_CYRIX:
-			make_list_from_string("Cx486,Cx5x86,6x86,6x86MX,M II,MediaGX,MediaGXi,MediaGXm", list);
-			break;
-		case VENDOR_NEXGEN:
-			make_list_from_string("Nx586", list);
-			break;
-		case VENDOR_TRANSMETA:
-			make_list_from_string("Crusoe,Efficeon", list);
-			break;
-		case VENDOR_UMC:
-			make_list_from_string("UMC x86 CPU", list);
-			break;
-		case VENDOR_CENTAUR:
-			make_list_from_string("VIA C3,VIA C7,VIA Nano", list);
-			break;
-		case VENDOR_RISE:
-			make_list_from_string("Rise mP6", list);
-			break;
-		case VENDOR_SIS:
-			make_list_from_string("SiS mP6", list);
-			break;
-		case VENDOR_NSC:
-			make_list_from_string("Geode GXm,Geode GXLV,Geode GX1,Geode GX2", list);
-			break;
-		default:
-			warnf("Unknown vendor passed to cpuid_get_cpu_list()\n");
-			break;
- 	}
-}
-
-void cpuid_free_cpu_list(struct cpu_list_t* list)
-{
-	int i;
-	if (list->num_entries <= 0) return;
-	for (i = 0; i < list->num_entries; i++)
-		free(list->names[i]);
-	free(list->names);
-}
diff --git a/src/3rdparty/libcpuid/libcpuid.h b/src/3rdparty/libcpuid/libcpuid.h
index f99c0fe55..c44990c31 100644
--- a/src/3rdparty/libcpuid/libcpuid.h
+++ b/src/3rdparty/libcpuid/libcpuid.h
@@ -610,39 +610,6 @@ void cpu_exec_cpuid_ext(uint32_t* regs);
  */
 int cpuid_get_raw_data(struct cpu_raw_data_t* data);
 
-/**
- * @brief Writes the raw CPUID data to a text file
- * @param data - a pointer to cpu_raw_data_t structure
- * @param filename - the path of the file, where the serialized data should be
- *                   written. If empty, stdout will be used.
- * @note This is intended primarily for debugging. On some processor, which is
- *       not currently supported or not completely recognized by cpu_identify,
- *       one can still successfully get the raw data and write it to a file.
- *       libcpuid developers can later import this file and debug the detection
- *       code as if running on the actual hardware.
- *       The file is simple text format of "something=value" pairs. Version info
- *       is also written, but the format is not intended to be neither backward-
- *       nor forward compatible.
- * @returns zero if successful, and some negative number on error.
- *          The error message can be obtained by calling \ref cpuid_error.
- *          @see cpu_error_t
- */
-int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename);
-
-/**
- * @brief Reads raw CPUID data from file
- * @param data - a pointer to cpu_raw_data_t structure. The deserialized data will
- *               be written here.
- * @param filename - the path of the file, containing the serialized raw data.
- *                   If empty, stdin will be used.
- * @note This function may fail, if the file is created by different version of
- *       the library. Also, see the notes on cpuid_serialize_raw_data.
- * @returns zero if successful, and some negative number on error.
- *          The error message can be obtained by calling \ref cpuid_error.
- *          @see cpu_error_t
-*/
-int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename);
-
 /**
  * @brief Identifies the CPU
  * @param raw - Input - a pointer to the raw CPUID data, which is obtained
@@ -668,222 +635,6 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
  */
 int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
 
-/**
- * @brief Returns the short textual representation of a CPU flag
- * @param feature - the feature, whose textual representation is wanted.
- * @returns a constant string like "fpu", "tsc", "sse2", etc.
- * @note the names of the returned flags are compatible with those from
- *       /proc/cpuinfo in Linux, with the exception of `tm_amd'
- */
-const char* cpu_feature_str(cpu_feature_t feature);
-
-/**
- * @brief Returns textual description of the last error
- *
- * libcpuid stores an `errno'-style error status, whose description
- * can be obtained with this function.
- * @note This function is not thread-safe
- * @see cpu_error_t
- */
-const char* cpuid_error(void);
-
-/**
- * @brief Executes RDTSC
- *
- * The RDTSC (ReaD Time Stamp Counter) instruction gives access to an
- * internal 64-bit counter, which usually increments at each clock cycle.
- * This can be used for various timing routines, and as a very precise
- * clock source. It is set to zero on system startup. Beware that may not
- * increment at the same frequency as the CPU. Consecutive calls of RDTSC
- * are, however, guaranteed to return monotonically-increasing values.
- *
- * @param result - a pointer to a 64-bit unsigned integer, where the TSC value
- *                 will be stored
- *
- * @note  If 100% compatibility is a concern, you must first check if the
- * RDTSC instruction is present (if it is not, your program will crash
- * with "invalid opcode" exception). Only some very old processors (i486,
- * early AMD K5 and some Cyrix CPUs) lack that instruction - they should
- * have become exceedingly rare these days. To verify RDTSC presence,
- * run cpu_identify() and check flags[CPU_FEATURE_TSC].
- *
- * @note The monotonically increasing nature of the TSC may be violated
- * on SMP systems, if their TSC clocks run at different rate. If the OS
- * doesn't account for that, the TSC drift may become arbitrary large.
- */
-void cpu_rdtsc(uint64_t* result);
-
-/**
- * @brief Store TSC and timing info
- *
- * This function stores the current TSC value and current
- * time info from a precise OS-specific clock source in the cpu_mark_t
- * structure. The sys_clock field contains time with microsecond resolution.
- * The values can later be used to measure time intervals, number of clocks,
- * FPU frequency, etc.
- * @see cpu_rdtsc
- *
- * @param mark [out] - a pointer to a cpu_mark_t structure
- */
-void cpu_tsc_mark(struct cpu_mark_t* mark);
-
-/**
- * @brief Calculate TSC and timing difference
- *
- * @param mark - input/output: a pointer to a cpu_mark_t sturcture, which has
- *               already been initialized by cpu_tsc_mark. The difference in
- *               TSC and time will be written here.
- *
- * This function calculates the TSC and time difference, by obtaining the
- * current TSC and timing values and subtracting the contents of the `mark'
- * structure from them. Results are written in the same structure.
- *
- * Example:
- * @code
- * ...
- * struct cpu_mark_t mark;
- * cpu_tsc_mark(&mark);
- * foo();
- * cpu_tsc_unmark(&mark);
- * printf("Foo finished. Executed in %llu cycles and %llu usecs\n",
- *        mark.tsc, mark.sys_clock);
- * ...
- * @endcode
- */
-void cpu_tsc_unmark(struct cpu_mark_t* mark);
-
-/**
- * @brief Calculates the CPU clock
- *
- * @param mark - pointer to a cpu_mark_t structure, which has been initialized
- *   with cpu_tsc_mark and later `stopped' with cpu_tsc_unmark.
- *
- * @note For reliable results, the marked time interval should be at least about
- * 10 ms.
- *
- * @returns the CPU clock frequency, in MHz. Due to measurement error, it will
- * differ from the true value in a few least-significant bits. Accuracy depends
- * on the timing interval - the more, the better. If the timing interval is
- * insufficient, the result is -1. Also, see the comment on cpu_clock_measure
- * for additional issues and pitfalls in using RDTSC for CPU frequency
- * measurements.
- */
-int cpu_clock_by_mark(struct cpu_mark_t* mark);
-
-/**
- * @brief Returns the CPU clock, as reported by the OS
- *
- * This function uses OS-specific functions to obtain the CPU clock. It may
- * differ from the true clock for several reasons:<br><br>
- *
- * i) The CPU might be in some power saving state, while the OS reports its
- *    full-power frequency, or vice-versa.<br>
- * ii) In some cases you can raise or lower the CPU frequency with overclocking
- *     utilities and the OS will not notice.
- *
- * @returns the CPU clock frequency in MHz. If the OS is not (yet) supported
- * or lacks the necessary reporting machinery, the return value is -1
- */
-int cpu_clock_by_os(void);
-
-/**
- * @brief Measure the CPU clock frequency
- *
- * @param millis - How much time to waste in the busy-wait cycle. In millisecs.
- *                 Useful values 10 - 1000
- * @param quad_check - Do a more thorough measurement if nonzero
- *                     (see the explanation).
- *
- * The function performs a busy-wait cycle for the given time and calculates
- * the CPU frequency by the difference of the TSC values. The accuracy of the
- * calculation depends on the length of the busy-wait cycle: more is better,
- * but 100ms should be enough for most purposes.
- *
- * While this will calculate the CPU frequency correctly in most cases, there are
- * several reasons why it might be incorrect:<br>
- *
- * i) RDTSC doesn't guarantee it will run at the same clock as the CPU.
- *    Apparently there aren't CPUs at the moment, but still, there's no
- *    guarantee.<br>
- * ii) The CPU might be in a low-frequency power saving mode, and the CPU
- *     might be switched to higher frequency at any time. If this happens
- *     during the measurement, the result can be anywhere between the
- *     low and high frequencies. Also, if you're interested in the
- *     high frequency value only, this function might return the low one
- *     instead.<br>
- * iii) On SMP systems exhibiting TSC drift (see \ref cpu_rdtsc)
- *
- * the quad_check option will run four consecutive measurements and
- * then return the average of the two most-consistent results. The total
- * runtime of the function will still be `millis' - consider using
- * a bit more time for the timing interval.
- *
- * Finally, for benchmarking / CPU intensive applications, the best strategy is
- * to use the cpu_tsc_mark() / cpu_tsc_unmark() / cpu_clock_by_mark() method.
- * Begin by mark()-ing about one second after application startup (allowing the
- * power-saving manager to kick in and rise the frequency during that time),
- * then unmark() just before application finishing. The result will most
- * acurately represent at what frequency your app was running.
- *
- * @returns the CPU clock frequency in MHz (within some measurement error
- * margin). If RDTSC is not supported, the result is -1.
- */
-int cpu_clock_measure(int millis, int quad_check);
-
-/**
- * @brief Measure the CPU clock frequency using instruction-counting
- *
- * @param millis - how much time to allocate for each run, in milliseconds
- * @param runs - how many runs to perform
- *
- * The function performs a busy-wait cycle using a known number of "heavy" (SSE)
- * instructions. These instructions run at (more or less guaranteed) 1 IPC rate,
- * so by running a busy loop for a fixed amount of time, and measuring the
- * amount of instructions done, the CPU clock is accurately measured.
- *
- * Of course, this function is still affected by the power-saving schemes, so
- * the warnings as of cpu_clock_measure() still apply. However, this function is
- * immune to problems with detection, related to the Intel Nehalem's "Turbo"
- * mode, where the internal clock is raised, but the RDTSC rate is unaffected.
- *
- * The function will run for about (millis * runs) milliseconds.
- * You can make only a single busy-wait run (runs == 1); however, this can
- * be affected by task scheduling (which will break the counting), so allowing
- * more than one run is recommended. As run length is not imperative for
- * accurate readings (e.g., 50ms is sufficient), you can afford a lot of short
- * runs, e.g. 10 runs of 50ms or 20 runs of 25ms.
- *
- * Recommended values - millis = 50, runs = 4. For more robustness,
- * increase the number of runs.
- * 
- * NOTE: on Bulldozer and later CPUs, the busy-wait cycle runs at 1.4 IPC, thus
- * the results are skewed. This is corrected internally by dividing the resulting
- * value by 1.4.
- * However, this only occurs if the thread is executed on a single CMT
- * module - if there are other threads competing for resources, the results are
- * unpredictable. Make sure you run cpu_clock_by_ic() on a CPU that is free from
- * competing threads, or if there are such threads, they shouldn't exceed the
- * number of modules. On a Bulldozer X8, that means 4 threads.
- *
- * @returns the CPU clock frequency in MHz (within some measurement error
- * margin). If SSE is not supported, the result is -1. If the input parameters
- * are incorrect, or some other internal fault is detected, the result is -2.
- */
-int cpu_clock_by_ic(int millis, int runs);
-
-/**
- * @brief Get the CPU clock frequency (all-in-one method)
- *
- * This is an all-in-one method for getting the CPU clock frequency.
- * It tries to use the OS for that. If the OS doesn't have this info, it
- * uses cpu_clock_measure with 200ms time interval and quadruple checking.
- *
- * @returns the CPU clock frequency in MHz. If every possible method fails,
- * the result is -1.
- */
-int cpu_clock(void);
-
-
 /**
  * @brief The return value of cpuid_get_epc().
  * @details
@@ -916,230 +667,6 @@ struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw);
  */
 const char* cpuid_lib_version(void);
 
-typedef void (*libcpuid_warn_fn_t) (const char *msg);
-/**
- * @brief Sets the warning print function
- *
- * In some cases, the internal libcpuid machinery would like to emit useful
- * debug warnings. By default, these warnings are written to stderr. However,
- * you can set a custom function that will receive those warnings.
- *
- * @param warn_fun - the warning function you want to set. If NULL, warnings
- *                   are disabled. The function takes const char* argument.
- *
- * @returns the current warning function. You can use the return value to
- * keep the previous warning function and restore it at your discretion.
- */
-libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t warn_fun);
-
-/**
- * @brief Sets the verbosiness level
- *
- * When the verbosiness level is above zero, some functions might print
- * diagnostic information about what are they doing. The higher the level is,
- * the more detail is printed. Level zero is guaranteed to omit all such
- * output. The output is written using the same machinery as the warnings,
- * @see cpuid_set_warn_function()
- *
- * @param level the desired verbosiness level. Useful values 0..2 inclusive
- */
-void cpuid_set_verbosiness_level(int level);
-
-
-/**
- * @brief Obtains the CPU vendor from CPUID from the current CPU
- * @note The result is cached.
- * @returns VENDOR_UNKNOWN if failed, otherwise the CPU vendor type.
- *          @see cpu_vendor_t
- */
-cpu_vendor_t cpuid_get_vendor(void);
-
-/**
- * @brief a structure that holds a list of processor names
- */
-struct cpu_list_t {
-	/** Number of entries in the list */
-	int num_entries;
-	/** Pointers to names. There will be num_entries of them */
-	char **names;
-};
-
-/**
- * @brief Gets a list of all known CPU names from a specific vendor.
- *
- * This function compiles a list of all known CPU (code)names
- * (i.e. the possible values of cpu_id_t::cpu_codename) for the given vendor.
- *
- * There are about 100 entries for Intel and AMD, and a few for the other
- * vendors. The list is written out in approximate chronological introduction
- * order of the parts.
- *
- * @param vendor the vendor to be queried
- * @param list [out] the resulting list will be written here.
- * NOTE: As the memory is dynamically allocated, be sure to call
- *       cpuid_free_cpu_list() after you're done with the data
- * @see cpu_list_t
- */
-void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list);
-
-/**
- * @brief Frees a CPU list
- *
- * This function deletes all the memory associated with a CPU list, as obtained
- * by cpuid_get_cpu_list()
- *
- * @param list - the list to be free()'d.
- */
-void cpuid_free_cpu_list(struct cpu_list_t* list);
-
-struct msr_driver_t;
-/**
- * @brief Starts/opens a driver, needed to read MSRs (Model Specific Registers)
- *
- * On systems that support it, this function will create a temporary
- * system driver, that has privileges to execute the RDMSR instruction.
- * After the driver is created, you can read MSRs by calling \ref cpu_rdmsr
- *
- * @returns a handle to the driver on success, and NULL on error.
- *          The error message can be obtained by calling \ref cpuid_error.
- *          @see cpu_error_t
- */
-struct msr_driver_t* cpu_msr_driver_open(void);
-
-/**
- * @brief Similar to \ref cpu_msr_driver_open, but accept one parameter
- *
- * This function works on certain operating systems (GNU/Linux, FreeBSD)
- *
- * @param core_num specify the core number for MSR.
- *          The first core number is 0.
- *          The last core number is \ref cpuid_get_total_cpus - 1.
- *
- * @returns a handle to the driver on success, and NULL on error.
- *          The error message can be obtained by calling \ref cpuid_error.
- *          @see cpu_error_t
- */
-struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num);
-
-/**
- * @brief Reads a Model-Specific Register (MSR)
- *
- * If the CPU has MSRs (as indicated by the CPU_FEATURE_MSR flag), you can
- * read a MSR with the given index by calling this function.
- *
- * There are several prerequisites you must do before reading MSRs:
- * 1) You must ensure the CPU has RDMSR. Check the CPU_FEATURE_MSR flag
- *    in cpu_id_t::flags
- * 2) You must ensure that the CPU implements the specific MSR you intend to
- *    read.
- * 3) You must open a MSR-reader driver. RDMSR is a privileged instruction and
- *    needs ring-0 access in order to work. This temporary driver is created
- *    by calling \ref cpu_msr_driver_open
- *
- * @param handle - a handle to the MSR reader driver, as created by
- *                 cpu_msr_driver_open
- * @param msr_index - the numeric ID of the MSR you want to read
- * @param result - a pointer to a 64-bit integer, where the MSR value is stored
- *
- * @returns zero if successful, and some negative number on error.
- *          The error message can be obtained by calling \ref cpuid_error.
- *          @see cpu_error_t
- */
-int cpu_rdmsr(struct msr_driver_t* handle, uint32_t msr_index, uint64_t* result);
-
-
-typedef enum {
-	INFO_MPERF,                /*!< Maximum performance frequency clock. This
-                                    is a counter, which increments as a
-                                    proportion of the actual processor speed. */
-	INFO_APERF,                /*!< Actual performance frequency clock. This
-                                    accumulates the core clock counts when the
-                                    core is active. */
-	INFO_MIN_MULTIPLIER,       /*!< Minimum CPU:FSB ratio for this CPU,
-                                    multiplied by 100. */
-	INFO_CUR_MULTIPLIER,       /*!< Current CPU:FSB ratio, multiplied by 100.
-                                    e.g., a CPU:FSB value of 18.5 reads as
-                                    "1850". */
-	INFO_MAX_MULTIPLIER,       /*!< Maximum CPU:FSB ratio for this CPU,
-                                    multiplied by 100. */
-	INFO_TEMPERATURE,          /*!< The current core temperature in Celsius. */
-	INFO_THROTTLING,           /*!< 1 if the current logical processor is
-                                    throttling. 0 if it is running normally. */
-	INFO_VOLTAGE,              /*!< The current core voltage in Volt,
-	                            multiplied by 100. */
-	INFO_BCLK,                 /*!< See \ref INFO_BUS_CLOCK. */
-	INFO_BUS_CLOCK,            /*!< The main bus clock in MHz,
-	                            e.g., FSB/QPI/DMI/HT base clock,
-	                            multiplied by 100. */
-} cpu_msrinfo_request_t;
-
-/**
- * @brief Similar to \ref cpu_rdmsr, but extract a range of bits
- *
- * @param handle - a handle to the MSR reader driver, as created by
- *                 cpu_msr_driver_open
- * @param msr_index - the numeric ID of the MSR you want to read
- * @param highbit - the high bit in range, must be inferior to 64
- * @param lowbit - the low bit in range, must be equal or superior to 0
- * @param result - a pointer to a 64-bit integer, where the MSR value is stored
- *
- * @returns zero if successful, and some negative number on error.
- *          The error message can be obtained by calling \ref cpuid_error.
- *          @see cpu_error_t
- */
-int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit,
-                    uint8_t lowbit, uint64_t* result);
-
-/**
- * @brief Reads extended CPU information from Model-Specific Registers.
- * @param handle - a handle to an open MSR driver, @see cpu_msr_driver_open
- * @param which - which info field should be returned. A list of
- *                available information entities is listed in the
- *                cpu_msrinfo_request_t enum.
- * @retval - if the requested information is available for the current
- *           processor model, the respective value is returned.
- *           if no information is available, or the CPU doesn't support
- *           the query, the special value CPU_INVALID_VALUE is returned
- * @note This function is not MT-safe. If you intend to call it from multiple
- *       threads, guard it through a mutex or a similar primitive.
- */
-int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which);
-#define CPU_INVALID_VALUE 0x3fffffff
-
-/**
- * @brief Writes the raw MSR data to a text file
- * @param data - a pointer to msr_driver_t structure
- * @param filename - the path of the file, where the serialized data should be
- *                   written. If empty, stdout will be used.
- * @note This is intended primarily for debugging. On some processor, which is
- *       not currently supported or not completely recognized by cpu_identify,
- *       one can still successfully get the raw data and write it to a file.
- *       libcpuid developers can later import this file and debug the detection
- *       code as if running on the actual hardware.
- *       The file is simple text format of "something=value" pairs. Version info
- *       is also written, but the format is not intended to be neither backward-
- *       nor forward compatible.
- * @returns zero if successful, and some negative number on error.
- *          The error message can be obtained by calling \ref cpuid_error.
- *          @see cpu_error_t
- */
-int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename);
-
-/**
- * @brief Closes an open MSR driver
- *
- * This function unloads the MSR driver opened by cpu_msr_driver_open and
- * frees any resources associated with it.
- *
- * @param handle - a handle to the MSR reader driver, as created by
- *                 cpu_msr_driver_open
- *
- * @returns zero if successful, and some negative number on error.
- *          The error message can be obtained by calling \ref cpuid_error.
- *          @see cpu_error_t
- */
-int cpu_msr_driver_close(struct msr_driver_t* handle);
-
 #ifdef __cplusplus
 }; /* extern "C" */
 #endif
diff --git a/src/3rdparty/libcpuid/libcpuid_util.c b/src/3rdparty/libcpuid/libcpuid_util.c
index 4de1871a4..440b3724e 100644
--- a/src/3rdparty/libcpuid/libcpuid_util.c
+++ b/src/3rdparty/libcpuid/libcpuid_util.c
@@ -32,8 +32,6 @@
 #include "libcpuid.h"
 #include "libcpuid_util.h"
 
-int _current_verboselevel;
-
 void match_features(const struct feature_map_t* matchtable, int count, uint32_t reg, struct cpu_id_t* data)
 {
 	int i;
@@ -42,118 +40,6 @@ void match_features(const struct feature_map_t* matchtable, int count, uint32_t
 			data->flags[matchtable[i].feature] = 1;
 }
 
-static void default_warn(const char *msg)
-{
-	fprintf(stderr, "%s", msg);
-}
-
-libcpuid_warn_fn_t _warn_fun = default_warn;
-
-#if defined(_MSC_VER)
-#	define vsnprintf _vsnprintf
-#endif
-void warnf(const char* format, ...)
-{
-	char buff[1024];
-	va_list va;
-	if (!_warn_fun) return;
-	va_start(va, format);
-	vsnprintf(buff, sizeof(buff), format, va);
-	va_end(va);
-	_warn_fun(buff);
-}
-
-void debugf(int verboselevel, const char* format, ...)
-{
-	char buff[1024];
-	va_list va;
-	if (verboselevel > _current_verboselevel) return;
-	va_start(va, format);
-	vsnprintf(buff, sizeof(buff), format, va);
-	va_end(va);
-	_warn_fun(buff);
-}
-
-static int popcount64(uint64_t mask)
-{
-	int num_set_bits = 0;
-	
-	while (mask) {
-		mask &= mask - 1;
-		num_set_bits++;
-	}
-	
-	return num_set_bits;
-}
-
-static int score(const struct match_entry_t* entry, const struct cpu_id_t* data,
-                 int brand_code, uint64_t bits, int model_code)
-{
-	int res = 0;
-	if (entry->family	== data->family    ) res += 2;
-	if (entry->model	== data->model     ) res += 2;
-	if (entry->stepping	== data->stepping  ) res += 2;
-	if (entry->ext_family	== data->ext_family) res += 2;
-	if (entry->ext_model	== data->ext_model ) res += 2;
-	if (entry->ncores	== data->num_cores ) res += 2;
-	if (entry->l2cache	== data->l2_cache  ) res += 1;
-	if (entry->l3cache	== data->l3_cache  ) res += 1;
-	if (entry->brand_code   == brand_code  ) res += 2;
-	if (entry->model_code   == model_code  ) res += 2;
-	
-	res += popcount64(entry->model_bits & bits) * 2;
-	return res;
-}
-
-int match_cpu_codename(const struct match_entry_t* matchtable, int count,
-                       struct cpu_id_t* data, int brand_code, uint64_t bits,
-                       int model_code)
-{
-	int bestscore = -1;
-	int bestindex = 0;
-	int i, t;
-	
-	debugf(3, "Matching cpu f:%d, m:%d, s:%d, xf:%d, xm:%d, ncore:%d, l2:%d, bcode:%d, bits:%llu, code:%d\n",
-		data->family, data->model, data->stepping, data->ext_family,
-		data->ext_model, data->num_cores, data->l2_cache, brand_code, (unsigned long long) bits, model_code);
-	
-	for (i = 0; i < count; i++) {
-		t = score(&matchtable[i], data, brand_code, bits, model_code);
-		debugf(3, "Entry %d, `%s', score %d\n", i, matchtable[i].name, t);
-		if (t > bestscore) {
-			debugf(2, "Entry `%s' selected - best score so far (%d)\n", matchtable[i].name, t);
-			bestscore = t;
-			bestindex = i;
-		}
-	}
-	strcpy(data->cpu_codename, matchtable[bestindex].name);
-	return bestscore;
-}
-
-void generic_get_cpu_list(const struct match_entry_t* matchtable, int count,
-                          struct cpu_list_t* list)
-{
-	int i, j, n, good;
-	n = 0;
-	list->names = (char**) malloc(sizeof(char*) * count);
-	for (i = 0; i < count; i++) {
-		if (strstr(matchtable[i].name, "Unknown")) continue;
-		good = 1;
-		for (j = n - 1; j >= 0; j--)
-			if (!strcmp(list->names[j], matchtable[i].name)) {
-				good = 0;
-				break;
-			}
-		if (!good) continue;
-#if defined(_MSC_VER)
-		list->names[n++] = _strdup(matchtable[i].name);
-#else
-		list->names[n++] = strdup(matchtable[i].name);
-#endif
-	}
-	list->num_entries = n;
-}
-
 static int xmatch_entry(char c, const char* p)
 {
 	int i, j;
@@ -205,14 +91,3 @@ int match_all(uint64_t bits, uint64_t mask)
 {
 	return (bits & mask) == mask;
 }
-
-void debug_print_lbits(int debuglevel, uint64_t mask)
-{
-	int i, first = 0;
-	for (i = 0; i < 64; i++) if (mask & (((uint64_t) 1) << i)) {
-		if (first) first = 0;
-		else debugf(2, " + ");
-		debugf(2, "LBIT(%d)", i);
-	}
-	debugf(2, "\n");
-}
diff --git a/src/3rdparty/libcpuid/libcpuid_util.h b/src/3rdparty/libcpuid/libcpuid_util.h
index c3b53933e..0c8200e86 100644
--- a/src/3rdparty/libcpuid/libcpuid_util.h
+++ b/src/3rdparty/libcpuid/libcpuid_util.h
@@ -48,20 +48,6 @@ struct match_entry_t {
 int match_cpu_codename(const struct match_entry_t* matchtable, int count,
                        struct cpu_id_t* data, int brand_code, uint64_t bits,
                        int model_code);
-
-void warnf(const char* format, ...)
-#ifdef __GNUC__
-__attribute__((format(printf, 1, 2)))
-#endif
-;
-void debugf(int verboselevel, const char* format, ...)
-#ifdef __GNUC__
-__attribute__((format(printf, 2, 3)))
-#endif
-;
-void generic_get_cpu_list(const struct match_entry_t* matchtable, int count,
-                          struct cpu_list_t* list);
-
 /*
  * Seek for a pattern in `haystack'.
  * Pattern may be an fixed string, or contain the special metacharacters
@@ -84,15 +70,9 @@ struct cpu_id_t* get_cached_cpuid(void);
 /* returns true if all bits of mask are present in `bits'. */
 int match_all(uint64_t bits, uint64_t mask);
 
-/* print what bits a mask consists of */
-void debug_print_lbits(int debuglevel, uint64_t mask);
-
 /*
  * Sets the current errno
  */
 int set_error(cpu_error_t err);
 
-extern libcpuid_warn_fn_t _warn_fun;
-extern int _current_verboselevel;
-
 #endif /* __LIBCPUID_UTIL_H__ */
diff --git a/src/3rdparty/libcpuid/recog_amd.c b/src/3rdparty/libcpuid/recog_amd.c
index 3867aa8c6..352d733b8 100644
--- a/src/3rdparty/libcpuid/recog_amd.c
+++ b/src/3rdparty/libcpuid/recog_amd.c
@@ -51,237 +51,6 @@ enum _amd_model_codes_t {
 	_1600,
 };
 
-
-const struct match_entry_t cpudb_amd[] = {
-	{ -1, -1, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown AMD CPU"               },
-	
-	/* 486 and the likes */
-	{  4, -1, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown AMD 486"               },
-	{  4,  3, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "AMD 486DX2"                    },
-	{  4,  7, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "AMD 486DX2WB"                  },
-	{  4,  8, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "AMD 486DX4"                    },
-	{  4,  9, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "AMD 486DX4WB"                  },
-	
-	/* Pentia clones */
-	{  5, -1, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown AMD 586"               },
-	{  5,  0, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "K5"                            },
-	{  5,  1, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "K5"                            },
-	{  5,  2, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "K5"                            },
-	{  5,  3, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "K5"                            },
-	
-	/* The K6 */
-	{  5,  6, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "K6"                            },
-	{  5,  7, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "K6"                            },
-	
-	{  5,  8, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "K6-2"                          },
-	{  5,  9, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "K6-III"                        },
-	{  5, 10, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown K6"                    },
-	{  5, 11, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown K6"                    },
-	{  5, 12, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown K6"                    },
-	{  5, 13, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "K6-2+"                         },
-	
-	/* Athlon et al. */
-	{  6,  1, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Athlon (Slot-A)"               },
-	{  6,  2, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Athlon (Slot-A)"               },
-	{  6,  3, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Duron (Spitfire)"              },
-	{  6,  4, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Athlon (ThunderBird)"          },
-	
-	{  6,  6, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown Athlon"                },
-	{  6,  6, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_             ,     0, "Athlon (Palomino)"             },
-	{  6,  6, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_|_MP_        ,     0, "Athlon MP (Palomino)"          },
-	{  6,  6, -1, -1,   -1,   1,    -1,    -1, NC, DURON_              ,     0, "Duron (Palomino)"              },
-	{  6,  6, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_|_XP_        ,     0, "Athlon XP"                     },
-	
-	{  6,  7, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown Athlon XP"             },
-	{  6,  7, -1, -1,   -1,   1,    -1,    -1, NC, DURON_              ,     0, "Duron (Morgan)"                },
-	
-	{  6,  8, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Athlon XP"                     },
-	{  6,  8, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_             ,     0, "Athlon XP (Thoroughbred)"      },
-	{  6,  8, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_|_XP_        ,     0, "Athlon XP (Thoroughbred)"      },
-	{  6,  8, -1, -1,   -1,   1,    -1,    -1, NC, DURON_              ,     0, "Duron (Applebred)"             },
-	{  6,  8, -1, -1,   -1,   1,    -1,    -1, NC, SEMPRON_            ,     0, "Sempron (Thoroughbred)"        },
-	{  6,  8, -1, -1,   -1,   1,   128,    -1, NC, SEMPRON_            ,     0, "Sempron (Thoroughbred)"        },
-	{  6,  8, -1, -1,   -1,   1,   256,    -1, NC, SEMPRON_            ,     0, "Sempron (Thoroughbred)"        },
-	{  6,  8, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_|_MP_        ,     0, "Athlon MP (Thoroughbred)"      },
-	{  6,  8, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_|_XP_|_M_    ,     0, "Mobile Athlon (T-Bred)"        },
-	{  6,  8, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_|_XP_|_M_|_LV_,    0, "Mobile Athlon (T-Bred)"        },
-	
-	{  6, 10, -1, -1,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Athlon XP (Barton)"            },
-	{  6, 10, -1, -1,   -1,   1,   512,    -1, NC, ATHLON_|_XP_        ,     0, "Athlon XP (Barton)"            },
-	{  6, 10, -1, -1,   -1,   1,   512,    -1, NC, SEMPRON_            ,     0, "Sempron (Barton)"              },
-	{  6, 10, -1, -1,   -1,   1,   256,    -1, NC, SEMPRON_            ,     0, "Sempron (Thorton)"             },
-	{  6, 10, -1, -1,   -1,   1,   256,    -1, NC, ATHLON_|_XP_        ,     0, "Athlon XP (Thorton)"           },
-	{  6, 10, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_|_MP_        ,     0, "Athlon MP (Barton)"            },
-	{  6, 10, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_|_XP_|_M_    ,     0, "Mobile Athlon (Barton)"        },
-	{  6, 10, -1, -1,   -1,   1,    -1,    -1, NC, ATHLON_|_XP_|_M_|_LV_,    0, "Mobile Athlon (Barton)"        },
-	
-	/* K8 Architecture */
-	{ 15, -1, -1, 15,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown K8"                    },
-	{ 15, -1, -1, 16,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown K9"                    },
-	
-	{ 15, -1, -1, 15,   -1,   1,    -1,    -1, NC, 0                   ,     0, "Unknown A64"                   },
-	{ 15, -1, -1, 15,   -1,   1,    -1,    -1, NC, OPTERON_            ,     0, "Opteron"                       },
-	{ 15, -1, -1, 15,   -1,   2,    -1,    -1, NC, OPTERON_|_X2        ,     0, "Opteron (Dual Core)"           },
-	{ 15,  3, -1, 15,   -1,   1,    -1,    -1, NC, OPTERON_            ,     0, "Opteron"                       },
-	{ 15,  3, -1, 15,   -1,   2,    -1,    -1, NC, OPTERON_|_X2        ,     0, "Opteron (Dual Core)"           },
-	{ 15, -1, -1, 15,   -1,   1,   512,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (512K)"              },
-	{ 15, -1, -1, 15,   -1,   1,  1024,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (1024K)"             },
-	{ 15, -1, -1, 15,   -1,   1,    -1,    -1, NC, ATHLON_|_FX         ,     0, "Athlon FX"                     },
-	{ 15, -1, -1, 15,   -1,   1,    -1,    -1, NC, ATHLON_|_64_|_FX    ,     0, "Athlon 64 FX"                  },
-	{ 15,  3, -1, 15,   35,   2,    -1,    -1, NC, ATHLON_|_64_|_FX    ,     0, "Athlon 64 FX X2 (Toledo)"      },
-	{ 15, -1, -1, 15,   -1,   2,   512,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon 64 X2 (512K)"           },
-	{ 15, -1, -1, 15,   -1,   2,  1024,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon 64 X2 (1024K)"          },
-	{ 15, -1, -1, 15,   -1,   1,   512,    -1, NC, TURION_|_64_        ,     0, "Turion 64 (512K)"              },
-	{ 15, -1, -1, 15,   -1,   1,  1024,    -1, NC, TURION_|_64_        ,     0, "Turion 64 (1024K)"             },
-	{ 15, -1, -1, 15,   -1,   2,   512,    -1, NC, TURION_|_X2         ,     0, "Turion 64 X2 (512K)"           },
-	{ 15, -1, -1, 15,   -1,   2,  1024,    -1, NC, TURION_|_X2         ,     0, "Turion 64 X2 (1024K)"          },
-	{ 15, -1, -1, 15,   -1,   1,   128,    -1, NC, SEMPRON_            ,     0, "A64 Sempron (128K)"            },
-	{ 15, -1, -1, 15,   -1,   1,   256,    -1, NC, SEMPRON_            ,     0, "A64 Sempron (256K)"            },
-	{ 15, -1, -1, 15,   -1,   1,   512,    -1, NC, SEMPRON_            ,     0, "A64 Sempron (512K)"            },
-	{ 15, -1, -1, 15, 0x4f,   1,   512,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (Orleans/512K)"      },
-	{ 15, -1, -1, 15, 0x5f,   1,   512,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (Orleans/512K)"      },
-	{ 15, -1, -1, 15, 0x2f,   1,   512,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (Venice/512K)"       },
-	{ 15, -1, -1, 15, 0x2c,   1,   512,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (Venice/512K)"       },
-	{ 15, -1, -1, 15, 0x1f,   1,   512,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (Winchester/512K)"   },
-	{ 15, -1, -1, 15, 0x0c,   1,   512,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (Newcastle/512K)"    },
-	{ 15, -1, -1, 15, 0x27,   1,   512,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (San Diego/512K)"    },
-	{ 15, -1, -1, 15, 0x37,   1,   512,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (San Diego/512K)"    },
-	{ 15, -1, -1, 15, 0x04,   1,   512,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (ClawHammer/512K)"   },
-	
-	{ 15, -1, -1, 15, 0x5f,   1,  1024,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (Orleans/1024K)"     },
-	{ 15, -1, -1, 15, 0x27,   1,  1024,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (San Diego/1024K)"   },
-	{ 15, -1, -1, 15, 0x04,   1,  1024,    -1, NC, ATHLON_|_64_        ,     0, "Athlon 64 (ClawHammer/1024K)"  },
-	
-	{ 15, -1, -1, 15, 0x4b,   2,   256,    -1, NC, SEMPRON_            ,     0, "Athlon 64 X2 (Windsor/256K)"   },
-	
-	{ 15, -1, -1, 15, 0x23,   2,   512,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon 64 X2 (Toledo/512K)"    },
-	{ 15, -1, -1, 15, 0x4b,   2,   512,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon 64 X2 (Windsor/512K)"   },
-	{ 15, -1, -1, 15, 0x43,   2,   512,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon 64 X2 (Windsor/512K)"   },
-	{ 15, -1, -1, 15, 0x6b,   2,   512,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon 64 X2 (Brisbane/512K)"  },
-	{ 15, -1, -1, 15, 0x2b,   2,   512,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon 64 X2 (Manchester/512K)"},
-	
-	{ 15, -1, -1, 15, 0x23,   2,  1024,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon 64 X2 (Toledo/1024K)"   },
-	{ 15, -1, -1, 15, 0x43,   2,  1024,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon 64 X2 (Windsor/1024K)"  },
-	
-	{ 15, -1, -1, 15, 0x08,   1,   128,    -1, NC, MOBILE_|SEMPRON_    ,     0, "Mobile Sempron 64 (Dublin/128K)"},
-	{ 15, -1, -1, 15, 0x08,   1,   256,    -1, NC, MOBILE_|SEMPRON_    ,     0, "Mobile Sempron 64 (Dublin/256K)"},
-	{ 15, -1, -1, 15, 0x0c,   1,   256,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Paris)"            },
-	{ 15, -1, -1, 15, 0x1c,   1,   128,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Palermo/128K)"     },
-	{ 15, -1, -1, 15, 0x1c,   1,   256,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Palermo/256K)"     },
-	{ 15, -1, -1, 15, 0x1c,   1,   128,    -1, NC, MOBILE_| SEMPRON_   ,     0, "Mobile Sempron 64 (Sonora/128K)"},
-	{ 15, -1, -1, 15, 0x1c,   1,   256,    -1, NC, MOBILE_| SEMPRON_   ,     0, "Mobile Sempron 64 (Sonora/256K)"},
-	{ 15, -1, -1, 15, 0x2c,   1,   128,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Palermo/128K)"     },
-	{ 15, -1, -1, 15, 0x2c,   1,   256,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Palermo/256K)"     },
-	{ 15, -1, -1, 15, 0x2c,   1,   128,    -1, NC, MOBILE_| SEMPRON_   ,     0, "Mobile Sempron 64 (Albany/128K)"},
-	{ 15, -1, -1, 15, 0x2c,   1,   256,    -1, NC, MOBILE_| SEMPRON_   ,     0, "Mobile Sempron 64 (Albany/256K)"},
-	{ 15, -1, -1, 15, 0x2f,   1,   128,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Palermo/128K)"     },
-	{ 15, -1, -1, 15, 0x2f,   1,   256,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Palermo/256K)"     },
-	{ 15, -1, -1, 15, 0x4f,   1,   128,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Manila/128K)"      },
-	{ 15, -1, -1, 15, 0x4f,   1,   256,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Manila/256K)"      },
-	{ 15, -1, -1, 15, 0x5f,   1,   128,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Manila/128K)"      },
-	{ 15, -1, -1, 15, 0x5f,   1,   256,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Manila/256K)"      },
-	{ 15, -1, -1, 15, 0x6b,   2,   256,    -1, NC, SEMPRON_            ,     0, "Sempron 64 Dual (Sherman/256K)"},
-	{ 15, -1, -1, 15, 0x6b,   2,   512,    -1, NC, SEMPRON_            ,     0, "Sempron 64 Dual (Sherman/512K)"},
-	{ 15, -1, -1, 15, 0x7f,   1,   256,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Sparta/256K)"      },
-	{ 15, -1, -1, 15, 0x7f,   1,   512,    -1, NC, SEMPRON_            ,     0, "Sempron 64 (Sparta/512K)"      },
-	{ 15, -1, -1, 15, 0x4c,   1,   256,    -1, NC, MOBILE_| SEMPRON_   ,     0, "Mobile Sempron 64 (Keene/256K)"},
-	{ 15, -1, -1, 15, 0x4c,   1,   512,    -1, NC, MOBILE_| SEMPRON_   ,     0, "Mobile Sempron 64 (Keene/512K)"},
-	{ 15, -1, -1, 15,   -1,   2,    -1,    -1, NC, SEMPRON_            ,     0, "Sempron Dual Core"             },
-	
-	{ 15, -1, -1, 15, 0x24,   1,   512,    -1, NC, TURION_|_64_        ,     0, "Turion 64 (Lancaster/512K)"    },
-	{ 15, -1, -1, 15, 0x24,   1,  1024,    -1, NC, TURION_|_64_        ,     0, "Turion 64 (Lancaster/1024K)"   },
-	{ 15, -1, -1, 15, 0x48,   2,   256,    -1, NC, TURION_|_X2         ,     0, "Turion X2 (Taylor)"            },
-	{ 15, -1, -1, 15, 0x48,   2,   512,    -1, NC, TURION_|_X2         ,     0, "Turion X2 (Trinidad)"          },
-	{ 15, -1, -1, 15, 0x4c,   1,   512,    -1, NC, TURION_|_64_        ,     0, "Turion 64 (Richmond)"          },
-	{ 15, -1, -1, 15, 0x68,   2,   256,    -1, NC, TURION_|_X2         ,     0, "Turion X2 (Tyler/256K)"        },
-	{ 15, -1, -1, 15, 0x68,   2,   512,    -1, NC, TURION_|_X2         ,     0, "Turion X2 (Tyler/512K)"        },
-	{ 15, -1, -1, 17,    3,   2,   512,    -1, NC, TURION_|_X2         ,     0, "Turion X2 (Griffin/512K)"      },
-	{ 15, -1, -1, 17,    3,   2,  1024,    -1, NC, TURION_|_X2         ,     0, "Turion X2 (Griffin/1024K)"     },
-
-	/* K10 Architecture (2007) */
-	{ 15, -1, -1, 16,   -1,   1,    -1,    -1, PHENOM, 0               ,     0, "Unknown AMD Phenom"            },
-	{ 15,  2, -1, 16,   -1,   1,    -1,    -1, PHENOM, 0               ,     0, "Phenom"                        },
-	{ 15,  2, -1, 16,   -1,   3,    -1,    -1, PHENOM, 0               ,     0, "Phenom X3 (Toliman)"           },
-	{ 15,  2, -1, 16,   -1,   4,    -1,    -1, PHENOM, 0               ,     0, "Phenom X4 (Agena)"             },
-	{ 15,  2, -1, 16,   -1,   3,   512,    -1, PHENOM, 0               ,     0, "Phenom X3 (Toliman/256K)"      },
-	{ 15,  2, -1, 16,   -1,   3,   512,    -1, PHENOM, 0               ,     0, "Phenom X3 (Toliman/512K)"      },
-	{ 15,  2, -1, 16,   -1,   4,   128,    -1, PHENOM, 0               ,     0, "Phenom X4 (Agena/128K)"        },
-	{ 15,  2, -1, 16,   -1,   4,   256,    -1, PHENOM, 0               ,     0, "Phenom X4 (Agena/256K)"        },
-	{ 15,  2, -1, 16,   -1,   4,   512,    -1, PHENOM,  0              ,     0, "Phenom X4 (Agena/512K)"        },
-	{ 15,  2, -1, 16,   -1,   2,   512,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon X2 (Kuma)"              },
-	/* Phenom II derivates: */
-	{ 15,  4, -1, 16,   -1,   4,    -1,    -1, NC, 0                   ,     0, "Phenom (Deneb-based)"          },
-	{ 15,  4, -1, 16,   -1,   1,  1024,    -1, NC, SEMPRON_            ,     0, "Sempron (Sargas)"              },
-	{ 15,  4, -1, 16,   -1,   2,   512,    -1, PHENOM2, 0              ,     0, "Phenom II X2 (Callisto)"       },
-	{ 15,  4, -1, 16,   -1,   3,   512,    -1, PHENOM2, 0              ,     0, "Phenom II X3 (Heka)"           },
-	{ 15,  4, -1, 16,   -1,   4,   512,    -1, PHENOM2, 0              ,     0, "Phenom II X4"                  },
-	{ 15,  4, -1, 16,    4,   4,   512,    -1, PHENOM2, 0              ,     0, "Phenom II X4 (Deneb)"          },
-	{ 15,  5, -1, 16,    5,   4,   512,    -1, PHENOM2, 0              ,     0, "Phenom II X4 (Deneb)"          },
-	{ 15,  4, -1, 16,   10,   4,   512,    -1, PHENOM2, 0              ,     0, "Phenom II X4 (Zosma)"          },
-	{ 15,  4, -1, 16,   10,   6,   512,    -1, PHENOM2, 0              ,     0, "Phenom II X6 (Thuban)"         },
-	/* Athlon II derivates: */
-	{ 15,  6, -1, 16,    6,   2,   512,    -1, NC, ATHLON_|_X2         ,     0, "Athlon II (Champlain)"         },
-	{ 15,  6, -1, 16,    6,   2,   512,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon II X2 (Regor)"          },
-	{ 15,  6, -1, 16,    6,   2,  1024,    -1, NC, ATHLON_|_64_|_X2    ,     0, "Athlon II X2 (Regor)"          },
-	{ 15,  5, -1, 16,    5,   3,   512,    -1, NC, ATHLON_|_64_|_X3    ,     0, "Athlon II X3 (Rana)"           },
-	{ 15,  5, -1, 16,    5,   4,   512,    -1, NC, ATHLON_|_64_|_X4    ,     0, "Athlon II X4 (Propus)"         },
-	/* Llano APUs (2011): */
-	{ 15,  1, -1, 18,    1,   2,    -1,    -1, FUSION_EA, 0            ,     0, "Llano X2"                      },
-	{ 15,  1, -1, 18,    1,   3,    -1,    -1, FUSION_EA, 0            ,     0, "Llano X3"                      },
-	{ 15,  1, -1, 18,    1,   4,    -1,    -1, FUSION_EA, 0            ,     0, "Llano X4"                      },
-
-	/* Family 14h: Bobcat Architecture (2011) */
-	{ 15,  2, -1, 20,   -1,   1,    -1,    -1, FUSION_C, 0             ,     0, "Brazos Ontario"                },
-	{ 15,  2, -1, 20,   -1,   2,    -1,    -1, FUSION_C, 0             ,     0, "Brazos Ontario (Dual-core)"    },
-	{ 15,  1, -1, 20,   -1,   1,    -1,    -1, FUSION_E, 0             ,     0, "Brazos Zacate"                 },
-	{ 15,  1, -1, 20,   -1,   2,    -1,    -1, FUSION_E, 0             ,     0, "Brazos Zacate (Dual-core)"     },
-	{ 15,  2, -1, 20,   -1,   2,    -1,    -1, FUSION_Z, 0             ,     0, "Brazos Desna (Dual-core)"      },
-
-	/* Family 15h: Bulldozer Architecture (2011) */
-	{ 15, -1, -1, 21,    0,   4,    -1,    -1, NC, 0                   ,     0, "Bulldozer X2"                  },
-	{ 15, -1, -1, 21,    1,   4,    -1,    -1, NC, 0                   ,     0, "Bulldozer X2"                  },
-	{ 15, -1, -1, 21,    1,   6,    -1,    -1, NC, 0                   ,     0, "Bulldozer X3"                  },
-	{ 15, -1, -1, 21,    1,   8,    -1,    -1, NC, 0                   ,     0, "Bulldozer X4"                  },
-	/* 2nd-gen, Piledriver core (2012): */
-	{ 15, -1, -1, 21,    2,   4,    -1,    -1, NC, 0                   ,     0, "Vishera X2"                    },
-	{ 15, -1, -1, 21,    2,   6,    -1,    -1, NC, 0                   ,     0, "Vishera X3"                    },
-	{ 15, -1, -1, 21,    2,   8,    -1,    -1, NC, 0                   ,     0, "Vishera X4"                    },
-	{ 15,  0, -1, 21,   16,   2,    -1,    -1, FUSION_A, 0             ,     0, "Trinity X2"                    },
-	{ 15,  0, -1, 21,   16,   4,    -1,    -1, FUSION_A, 0             ,     0, "Trinity X4"                    },
-	{ 15,  3, -1, 21,   19,   2,    -1,    -1, FUSION_A, 0             ,     0, "Richland X2"                   },
-	{ 15,  3, -1, 21,   19,   4,    -1,    -1, FUSION_A, 0             ,     0, "Richland X4"                   },
-	/* 3rd-gen, Steamroller core (2014): */
-	{ 15,  0, -1, 21,   48,   2,    -1,    -1, FUSION_A, 0             ,     0, "Kaveri X2"                     },
-	{ 15,  0, -1, 21,   48,   4,    -1,    -1, FUSION_A, 0             ,     0, "Kaveri X4"                     },
-	{ 15,  8, -1, 21,   56,   4,    -1,    -1, FUSION_A, 0             ,     0, "Godavari X4"                   },
-	/* 4th-gen, Excavator core (2015): */
-	{ 15,  1, -1, 21,   96,   2,    -1,    -1, FUSION_A, 0             ,     0, "Carrizo X2"                    },
-	{ 15,  1, -1, 21,   96,   4,    -1,    -1, FUSION_A, 0             ,     0, "Carrizo X4"                    },
-	{ 15,  5, -1, 21,  101,   2,    -1,    -1, FUSION_A, 0             ,     0, "Bristol Ridge X2"              },
-	{ 15,  5, -1, 21,  101,   4,    -1,    -1, FUSION_A, 0             ,     0, "Bristol Ridge X4"              },
-	{ 15,  0, -1, 21,  112,   2,    -1,    -1, FUSION_A, 0             ,     0, "Stoney Ridge X2"               },
-	{ 15,  0, -1, 21,  112,   2,    -1,    -1, FUSION_E, 0             ,     0, "Stoney Ridge X2"               },
-
-	/* Family 16h: Jaguar Architecture (2013) */
-	{ 15,  0, -1, 22,    0,   2,    -1,    -1, FUSION_A, 0             ,     0, "Kabini X2"                     },
-	{ 15,  0, -1, 22,    0,   4,    -1,    -1, FUSION_A, 0             ,     0, "Kabini X4"                     },
-	/* 2nd-gen, Puma core (2013): */
-	{ 15,  0, -1, 22,   48,   2,    -1,    -1, FUSION_E, 0             ,     0, "Mullins X2"                    },
-	{ 15,  0, -1, 22,   48,   4,    -1,    -1, FUSION_A, 0             ,     0, "Mullins X4"                    },
-
-	/* Family 17h: Zen Architecture (2017) */
-	{ 15, -1, -1, 23,    1,   8,    -1,    -1, NC, 0                   ,     0, "Ryzen 7"                       },
-	{ 15, -1, -1, 23,    1,   6,    -1,    -1, NC, 0                   , _1600, "Ryzen 5"                       },
-	{ 15, -1, -1, 23,    1,   4,    -1,    -1, NC, 0                   , _1500, "Ryzen 5"                       },
-	{ 15, -1, -1, 23,    1,   4,    -1,    -1, NC, 0                   , _1400, "Ryzen 5"                       },
-	{ 15, -1, -1, 23,    1,   4,    -1,    -1, NC, 0                   ,     0, "Ryzen 3"                       },
-	//{ 15, -1, -1, 23,    1,   4,    -1,    -1, NC, 0                   ,     0, "Raven Ridge"                   }, //TBA
-
-	/* Newer Opterons: */
-	{ 15,  9, -1, 22,    9,   8,    -1,    -1, NC, OPTERON_            ,     0, "Magny-Cours Opteron"           },
-};
-
-
 static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
 {
 	const struct feature_map_t matchtable_edx81[] = {
@@ -391,140 +160,10 @@ static void decode_amd_number_of_cores(struct cpu_raw_data_t* raw, struct cpu_id
 	}
 }
 
-static int amd_has_turion_modelname(const char *bs)
-{
-	/* We search for something like TL-60. Ahh, I miss regexes...*/
-	int i, l, k;
-	char code[3] = {0};
-	const char* codes[] = { "ML", "MT", "MK", "TK", "TL", "RM", "ZM", "" };
-	l = (int) strlen(bs);
-	for (i = 3; i < l - 2; i++) {
-		if (bs[i] == '-' &&
-		    isupper(bs[i-1]) && isupper(bs[i-2]) && !isupper(bs[i-3]) &&
-		    isdigit(bs[i+1]) && isdigit(bs[i+2]) && !isdigit(bs[i+3]))
-		{
-			code[0] = bs[i-2];
-			code[1] = bs[i-1];
-			for (k = 0; codes[k][0]; k++)
-				if (!strcmp(codes[k], code)) return 1;
-		}
-	}
-	return 0;
-}
-
-static struct amd_code_and_bits_t decode_amd_codename_part1(const char *bs)
-{
-	amd_code_t code = NC;
-	uint64_t bits = 0;
-	struct amd_code_and_bits_t result;
-
-	if (strstr(bs, "Dual Core") ||
-	    strstr(bs, "Dual-Core") ||
-	    strstr(bs, " X2 "))
-		bits |= _X2;
-	if (strstr(bs, " X4 ")) bits |= _X4;
-	if (strstr(bs, " X3 ")) bits |= _X3;
-	if (strstr(bs, "Opteron")) bits |= OPTERON_;
-	if (strstr(bs, "Phenom")) {
-		code = (strstr(bs, "II")) ? PHENOM2 : PHENOM;
-	}
-	if (amd_has_turion_modelname(bs)) {
-		bits |= TURION_;
-	}
-	if (strstr(bs, "Athlon(tm)")) bits |= ATHLON_;
-	if (strstr(bs, "Sempron(tm)")) bits |= SEMPRON_;
-	if (strstr(bs, "Duron")) bits |= DURON_;
-	if (strstr(bs, " 64 ")) bits |= _64_;
-	if (strstr(bs, " FX")) bits |= _FX;
-	if (strstr(bs, " MP")) bits |= _MP_;
-	if (strstr(bs, "Athlon(tm) 64") || strstr(bs, "Athlon(tm) II X") || match_pattern(bs, "Athlon(tm) X#")) {
-		bits |= ATHLON_ | _64_;
-	}
-	if (strstr(bs, "Turion")) bits |= TURION_;
-	
-	if (strstr(bs, "mobile") || strstr(bs, "Mobile")) {
-		bits |= MOBILE_;
-	}
-	
-	if (strstr(bs, "XP")) bits |= _XP_;
-	if (strstr(bs, "XP-M")) bits |= _M_;
-	if (strstr(bs, "(LV)")) bits |= _LV_;
-	if (strstr(bs, " APU ")) bits |= _APU_;
-
-	if (match_pattern(bs, "C-##")) code = FUSION_C;
-	if (match_pattern(bs, "E-###")) code = FUSION_E;
-	if (match_pattern(bs, "Z-##")) code = FUSION_Z;
-	if (match_pattern(bs, "[EA]#-####")) code = FUSION_EA;
-
-	result.code = code;
-	result.bits = bits;
-	return result;
-}
-
-static int decode_amd_ryzen_model_code(const char* bs)
-{
-	const struct {
-		int model_code;
-		const char* match_str;
-	} patterns[] = {
-		{ _1600, "1600" },
-		{ _1500, "1500" },
-		{ _1400, "1400" },
-	};
-	int i;
-
-	for (i = 0; i < COUNT_OF(patterns); i++)
-		if (strstr(bs, patterns[i].match_str))
-			return patterns[i].model_code;
-	//
-	return 0;
-}
-
-static void decode_amd_codename(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
-{
-	struct amd_code_and_bits_t code_and_bits = decode_amd_codename_part1(data->brand_str);
-	int i = 0;
-	char* code_str = NULL;
-	int model_code;
-
-	for (i = 0; i < COUNT_OF(amd_code_str); i++) {
-		if (code_and_bits.code == amd_code_str[i].code) {
-			code_str = amd_code_str[i].str;
-			break;
-		}
-	}
-	if (/*code == ATHLON_64_X2*/ match_all(code_and_bits.bits, ATHLON_|_64_|_X2) && data->l2_cache < 512) {
-		code_and_bits.bits &= ~(ATHLON_ | _64_);
-		code_and_bits.bits |= SEMPRON_;
-	}
-	if (code_str)
-		debugf(2, "Detected AMD brand code: %d (%s)\n", code_and_bits.code, code_str);
-	else
-		debugf(2, "Detected AMD brand code: %d\n", code_and_bits.code);
-
-	if (code_and_bits.bits) {
-		debugf(2, "Detected AMD bits: ");
-		debug_print_lbits(2, code_and_bits.bits);
-	}
-	// is it Ryzen? if so, we need to detect discern between the four-core 1400/1500 (Ryzen 5) and the four-core Ryzen 3:
-	model_code = (data->ext_family == 23) ? decode_amd_ryzen_model_code(data->brand_str) : 0;
-
-	internal->code.amd = code_and_bits.code;
-	internal->bits = code_and_bits.bits;
-	internal->score = match_cpu_codename(cpudb_amd, COUNT_OF(cpudb_amd), data, code_and_bits.code,
-	                                     code_and_bits.bits, model_code);
-}
-
 int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
 {
 	load_amd_features(raw, data);
 	decode_amd_cache_info(raw, data);
 	decode_amd_number_of_cores(raw, data);
-	decode_amd_codename(raw, data, internal);
 	return 0;
 }
-
-void cpuid_get_list_amd(struct cpu_list_t* list)
-{
-	generic_get_cpu_list(cpudb_amd, COUNT_OF(cpudb_amd), list);
-}
diff --git a/src/3rdparty/libcpuid/recog_amd.h b/src/3rdparty/libcpuid/recog_amd.h
index 34e895983..19f839ba2 100644
--- a/src/3rdparty/libcpuid/recog_amd.h
+++ b/src/3rdparty/libcpuid/recog_amd.h
@@ -27,6 +27,5 @@
 #define __RECOG_AMD_H__
 
 int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal);
-void cpuid_get_list_amd(struct cpu_list_t* list);
 
 #endif /* __RECOG_AMD_H__ */
diff --git a/src/3rdparty/libcpuid/recog_intel.c b/src/3rdparty/libcpuid/recog_intel.c
index 5e6c03b0e..5467c19f0 100644
--- a/src/3rdparty/libcpuid/recog_intel.c
+++ b/src/3rdparty/libcpuid/recog_intel.c
@@ -59,291 +59,6 @@ enum _intel_model_t {
 };
 typedef enum _intel_model_t intel_model_t;
 
-const struct match_entry_t cpudb_intel[] = {
-	{ -1, -1, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Unknown Intel CPU"       },
-	
-	/* i486 */
-	{  4, -1, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Unknown i486"            },
-	{  4,  0, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "i486 DX-25/33"           },
-	{  4,  1, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "i486 DX-50"              },
-	{  4,  2, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "i486 SX"                 },
-	{  4,  3, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "i486 DX2"                },
-	{  4,  4, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "i486 SL"                 },
-	{  4,  5, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "i486 SX2"                },
-	{  4,  7, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "i486 DX2 WriteBack"      },
-	{  4,  8, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "i486 DX4"                },
-	{  4,  9, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "i486 DX4 WriteBack"      },
-	
-	/* All Pentia:
-	   Pentium 1 */
-	{  5, -1, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Unknown Pentium"         },
-	{  5,  0, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium A-Step"          },
-	{  5,  1, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium 1 (0.8u)"        },
-	{  5,  2, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium 1 (0.35u)"       },
-	{  5,  3, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium OverDrive"       },
-	{  5,  4, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium 1 (0.35u)"       },
-	{  5,  7, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium 1 (0.35u)"       },
-	{  5,  8, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium MMX (0.25u)"     },
-	
-	/* Pentium 2 / 3 / M / Conroe / whatsnext - all P6 based. */
-	{  6, -1, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Unknown P6"              },
-	{  6,  0, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium Pro"             },
-	{  6,  1, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium Pro"             },
-	{  6,  3, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium II (Klamath)"    },
-	{  6,  5, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium II (Deschutes)"  },
-	{  6,  5, -1, -1, -1,   1,    -1,    -1, NC, MOBILE_|PENTIUM_,   0, "Mobile Pentium II (Tonga)"},
-	{  6,  6, -1, -1, -1,   1,    -1,    -1, NC,0              ,     0, "Pentium II (Dixon)"      },
-	
-	{  6,  3, -1, -1, -1,   1,    -1,    -1, NC, XEON_         ,     0, "P-II Xeon (Klamath)"     },
-	{  6,  5, -1, -1, -1,   1,    -1,    -1, NC, XEON_         ,     0, "P-II Xeon (Drake)"       },
-	{  6,  6, -1, -1, -1,   1,    -1,    -1, NC, XEON_         ,     0, "P-II Xeon (Dixon)"       },
-		
-	{  6,  5, -1, -1, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-II Celeron (Covington)" },
-	{  6,  6, -1, -1, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-II Celeron (Mendocino)" },
-	
-	/* -------------------------------------------------- */
-	
-	{  6,  7, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium III (Katmai)"    },
-	{  6,  8, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium III (Coppermine)"},
-	{  6, 10, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium III (Coppermine)"},
-	{  6, 11, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium III (Tualatin)"  },
-	
-	{  6,  7, -1, -1, -1,   1,    -1,    -1, NC, XEON_         ,     0, "P-III Xeon (Tanner)"     },
-	{  6,  8, -1, -1, -1,   1,    -1,    -1, NC, XEON_         ,     0, "P-III Xeon (Cascades)"   },
-	{  6, 10, -1, -1, -1,   1,    -1,    -1, NC, XEON_         ,     0, "P-III Xeon (Cascades)"   },
-	{  6, 11, -1, -1, -1,   1,    -1,    -1, NC, XEON_         ,     0, "P-III Xeon (Tualatin)"   },
-	
-	{  6,  7, -1, -1, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-III Celeron (Katmai)"     },
-	{  6,  8, -1, -1, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-III Celeron (Coppermine)" },
-	{  6, 10, -1, -1, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-III Celeron (Coppermine)" },
-	{  6, 11, -1, -1, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-III Celeron (Tualatin)"   },
-	
-	/* Netburst based (Pentium 4 and later)
-	   classic P4s */
-	{ 15, -1, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Unknown Pentium 4"       },
-	{ 15, -1, -1, 15, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "Unknown P-4 Celeron"     },
-	{ 15, -1, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Unknown Xeon"            },
-	
-	{ 15,  0, -1, 15, -1,   1,    -1,    -1, NC, PENTIUM_      ,     0, "Pentium 4 (Willamette)"  },
-	{ 15,  1, -1, 15, -1,   1,    -1,    -1, NC, PENTIUM_      ,     0, "Pentium 4 (Willamette)"  },
-	{ 15,  2, -1, 15, -1,   1,    -1,    -1, NC, PENTIUM_      ,     0, "Pentium 4 (Northwood)"   },
-	{ 15,  3, -1, 15, -1,   1,    -1,    -1, NC, PENTIUM_      ,     0, "Pentium 4 (Prescott)"    },
-	{ 15,  4, -1, 15, -1,   1,    -1,    -1, NC, PENTIUM_      ,     0, "Pentium 4 (Prescott)"    },
-	{ 15,  6, -1, 15, -1,   1,    -1,    -1, NC, PENTIUM_      ,     0, "Pentium 4 (Cedar Mill)"  },
-	{ 15,  0, -1, 15, -1,   1,    -1,    -1, NC, MOBILE_|PENTIUM_,   0, "Mobile P-4 (Willamette)" },
-	{ 15,  1, -1, 15, -1,   1,    -1,    -1, NC, MOBILE_|PENTIUM_,   0, "Mobile P-4 (Willamette)" },
-	{ 15,  2, -1, 15, -1,   1,    -1,    -1, NC, MOBILE_|PENTIUM_,   0, "Mobile P-4 (Northwood)"  },
-	{ 15,  3, -1, 15, -1,   1,    -1,    -1, NC, MOBILE_|PENTIUM_,   0, "Mobile P-4 (Prescott)"   },
-	{ 15,  4, -1, 15, -1,   1,    -1,    -1, NC, MOBILE_|PENTIUM_,   0, "Mobile P-4 (Prescott)"   },
-	{ 15,  6, -1, 15, -1,   1,    -1,    -1, NC, MOBILE_|PENTIUM_,   0, "Mobile P-4 (Cedar Mill)" },
-	
-	/* server CPUs */
-	{ 15,  0, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Foster)"           },
-	{ 15,  1, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Foster)"           },
-	{ 15,  2, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Prestonia)"        },
-	{ 15,  2, -1, 15, -1,   1,    -1,    -1, NC, XEON_|_MP_    ,     0, "Xeon (Gallatin)"         },
-	{ 15,  3, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Nocona)"           },
-	{ 15,  4, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Nocona)"           },
-	{ 15,  4, -1, 15, -1,   1,    -1,    -1, IRWIN, XEON_      ,     0, "Xeon (Irwindale)"        },
-	{ 15,  4, -1, 15, -1,   1,    -1,    -1, NC, XEON_|_MP_    ,     0, "Xeon (Cranford)"         },
-	{ 15,  4, -1, 15, -1,   1,    -1,    -1, POTOMAC, XEON_    ,     0, "Xeon (Potomac)"          },
-	{ 15,  6, -1, 15, -1,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon (Dempsey)"          },
-	
-	/* Pentium Ds */
-	{ 15,  4,  4, 15, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium D (SmithField)"  },
-	{ 15,  4, -1, 15, -1,   1,    -1,    -1, PENTIUM_D, 0      ,     0, "Pentium D (SmithField)"  },
-	{ 15,  4,  7, 15, -1,   1,    -1,    -1, NC, 0             ,     0, "Pentium D (SmithField)"  },
-	{ 15,  6, -1, 15, -1,   1,    -1,    -1, PENTIUM_D, 0      ,     0, "Pentium D (Presler)"     },
-
-	/* Celeron and Celeron Ds */
-	{ 15,  1, -1, 15, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-4 Celeron (Willamette)"   },
-	{ 15,  2, -1, 15, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-4 Celeron (Northwood)"    },
-	{ 15,  3, -1, 15, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-4 Celeron D (Prescott)"   },
-	{ 15,  4, -1, 15, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-4 Celeron D (Prescott)"   },
-	{ 15,  6, -1, 15, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "P-4 Celeron D (Cedar Mill)" },
-	
-	/* -------------------------------------------------- */
-	/* Intel Core microarchitecture - P6-based */
-	
-	{  6,  9, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Unknown Pentium M"          },
-	{  6,  9, -1, -1, -1,   1,    -1,    -1, PENTIUM_M, 0      ,     0, "Unknown Pentium M"          },
-	{  6,  9, -1, -1, -1,   1,    -1,    -1, NC, PENTIUM_      ,     0, "Pentium M (Banias)"         },
-	{  6,  9, -1, -1, -1,   1,    -1,    -1, PENTIUM_M, 0      ,     0, "Pentium M (Banias)"         },
-	{  6,  9, -1, -1, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "Celeron M"                  },
-	{  6, 13, -1, -1, -1,   1,    -1,    -1, NC, PENTIUM_      ,     0, "Pentium M (Dothan)"         },
-	{  6, 13, -1, -1, -1,   1,    -1,    -1, PENTIUM_M, 0      ,     0, "Pentium M (Dothan)"         },
-	{  6, 13, -1, -1, -1,   1,    -1,    -1, NC, CELERON_      ,     0, "Celeron M"                  },
-	
-	{  6, 12, -1, -1, -1,  -1,    -1,    -1, NC, ATOM_         ,     0, "Unknown Atom"               },
-	{  6, 12, -1, -1, -1,  -1,    -1,    -1, DIAMONDVILLE,ATOM_,     0, "Atom (Diamondville)"        },
-	{  6, 12, -1, -1, -1,  -1,    -1,    -1, SILVERTHORNE,ATOM_,     0, "Atom (Silverthorne)"        },
-	{  6, 12, -1, -1, -1,  -1,    -1,    -1, CEDARVIEW, ATOM_  ,     0, "Atom (Cedarview)"           },
-	{  6,  6, -1, -1, -1,  -1,    -1,    -1, CEDARVIEW, ATOM_  ,     0, "Atom (Cedarview)"           },
-	{  6, 12, -1, -1, -1,  -1,    -1,    -1, PINEVIEW, ATOM_   ,     0, "Atom (Pineview)"            },
-	
-	/* -------------------------------------------------- */
-	
-	{  6, 14, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Unknown Yonah"             },
-	{  6, 14, -1, -1, -1,   1,    -1,    -1, CORE_SOLO, 0      ,     0, "Yonah (Core Solo)"         },
-	{  6, 14, -1, -1, -1,   2,    -1,    -1, CORE_DUO, 0       ,     0, "Yonah (Core Duo)"          },
-	{  6, 14, -1, -1, -1,   1,    -1,    -1, CORE_SOLO, MOBILE_,     0, "Yonah (Core Solo)"         },
-	{  6, 14, -1, -1, -1,   2,    -1,    -1, CORE_DUO , MOBILE_,     0, "Yonah (Core Duo)"          },
-	{  6, 14, -1, -1, -1,   1,    -1,    -1, CORE_SOLO, 0      ,     0, "Yonah (Core Solo)"         },
-	
-	{  6, 15, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Unknown Core 2"            },
-	{  6, 15, -1, -1, -1,   2,  4096,    -1, CORE_DUO, 0       ,     0, "Conroe (Core 2 Duo)"       },
-	{  6, 15, -1, -1, -1,   2,  1024,    -1, CORE_DUO, 0       ,     0, "Conroe (Core 2 Duo) 1024K" },
-	{  6, 15, -1, -1, -1,   2,   512,    -1, CORE_DUO, 0       ,     0, "Conroe (Core 2 Duo) 512K"  },
-	{  6, 15, -1, -1, -1,   4,    -1,    -1, QUAD_CORE, 0      ,     0, "Kentsfield (Core 2 Quad)"  },
-	{  6, 15, -1, -1, -1,   4,  4096,    -1, QUAD_CORE, 0      ,     0, "Kentsfield (Core 2 Quad)"  },
-	{  6, 15, -1, -1, -1, 400,    -1,    -1, MORE_THAN_QUADCORE, 0,  0, "More than quad-core"       },
-	{  6, 15, -1, -1, -1,   2,  2048,    -1, CORE_DUO, 0       ,     0, "Allendale (Core 2 Duo)"    },
-	{  6, 15, -1, -1, -1,   2,    -1,    -1, MOBILE_CORE_DUO, 0,     0, "Merom (Core 2 Duo)"        },
-	{  6, 15, -1, -1, -1,   2,  2048,    -1, MEROM, 0          ,     0, "Merom (Core 2 Duo) 2048K"  },
-	{  6, 15, -1, -1, -1,   2,  4096,    -1, MEROM, 0          ,     0, "Merom (Core 2 Duo) 4096K"  },
-	
-	{  6, 15, -1, -1, 15,   1,    -1,    -1, NC, CELERON_      ,     0, "Conroe-L (Celeron)"        },
-	{  6,  6, -1, -1, 22,   1,    -1,    -1, NC, CELERON_      ,     0, "Conroe-L (Celeron)"        },
-	{  6, 15, -1, -1, 15,   2,    -1,    -1, NC, CELERON_      ,     0, "Conroe-L (Allendale)"      },
-	{  6,  6, -1, -1, 22,   2,    -1,    -1, NC, CELERON_      ,     0, "Conroe-L (Allendale)"      },
-	
-	
-	{  6,  6, -1, -1, 22,   1,    -1,    -1, NC, 0             ,     0, "Unknown Core ?"           },
-	{  6,  7, -1, -1, 23,   1,    -1,    -1, NC, 0             ,     0, "Unknown Core ?"           },
-	{  6,  6, -1, -1, 22, 400,    -1,    -1, MORE_THAN_QUADCORE, 0,  0, "More than quad-core"      },
-	{  6,  7, -1, -1, 23, 400,    -1,    -1, MORE_THAN_QUADCORE, 0,  0, "More than quad-core"      },
-	
-	{  6,  7, -1, -1, 23,   1,    -1,    -1, CORE_SOLO         , 0,  0, "Unknown Core 45nm"        },
-	{  6,  7, -1, -1, 23,   1,    -1,    -1, CORE_DUO          , 0,  0, "Unknown Core 45nm"        },
-	{  6,  7, -1, -1, 23,   2,  1024,    -1, WOLFDALE          , 0,  0, "Celeron Wolfdale 1M"      },
-	{  6,  7, -1, -1, 23,   2,  2048,    -1, WOLFDALE          , 0,  0, "Wolfdale (Core 2 Duo) 2M" },
-	{  6,  7, -1, -1, 23,   2,  3072,    -1, WOLFDALE          , 0,  0, "Wolfdale (Core 2 Duo) 3M" },
-	{  6,  7, -1, -1, 23,   2,  6144,    -1, WOLFDALE          , 0,  0, "Wolfdale (Core 2 Duo) 6M" },
-	{  6,  7, -1, -1, 23,   1,    -1,    -1, MOBILE_CORE_DUO   , 0,  0, "Penryn (Core 2 Duo)"      },
-	{  6,  7, -1, -1, 23,   2,  1024,    -1, PENRYN            , 0,  0, "Penryn (Core 2 Duo)"      },
-	{  6,  7, -1, -1, 23,   2,  3072,    -1, PENRYN            , 0,  0, "Penryn (Core 2 Duo) 3M"   },
-	{  6,  7, -1, -1, 23,   2,  6144,    -1, PENRYN            , 0,  0, "Penryn (Core 2 Duo) 6M"   },
-	{  6,  7, -1, -1, 23,   4,  2048,    -1, NC                , 0,  0, "Yorkfield (Core 2 Quad) 2M"},
-	{  6,  7, -1, -1, 23,   4,  3072,    -1, NC                , 0,  0, "Yorkfield (Core 2 Quad) 3M"},
-	{  6,  7, -1, -1, 23,   4,  6144,    -1, NC                , 0,  0, "Yorkfield (Core 2 Quad) 6M"},
-	
-	/* Core microarchitecture-based Xeons: */
-	{  6, 14, -1, -1, 14,   1,    -1,    -1, NC, XEON_         ,     0, "Xeon LV"                  },
-	{  6, 15, -1, -1, 15,   2,  4096,    -1, NC, XEON_         , _5100, "Xeon (Woodcrest)"         },
-	{  6, 15, -1, -1, 15,   2,  2048,    -1, NC, XEON_         , _3000, "Xeon (Conroe/2M)"         },
-	{  6, 15, -1, -1, 15,   2,  4096,    -1, NC, XEON_         , _3000, "Xeon (Conroe/4M)"         },
-	{  6, 15, -1, -1, 15,   4,  4096,    -1, NC, XEON_         , X3200, "Xeon (Kentsfield)"        },
-	{  6, 15, -1, -1, 15,   4,  4096,    -1, NC, XEON_         , _5300, "Xeon (Clovertown)"        },
-	{  6,  7, -1, -1, 23,   2,  6144,    -1, NC, XEON_         , _3100, "Xeon (Wolfdale)"          },
-	{  6,  7, -1, -1, 23,   2,  6144,    -1, NC, XEON_         , _5200, "Xeon (Wolfdale DP)"       },
-	{  6,  7, -1, -1, 23,   4,  6144,    -1, NC, XEON_         , _5400, "Xeon (Harpertown)"        },
-	{  6,  7, -1, -1, 23,   4,  3072,    -1, NC, XEON_         , X3300, "Xeon (Yorkfield/3M)"      },
-	{  6,  7, -1, -1, 23,   4,  6144,    -1, NC, XEON_         , X3300, "Xeon (Yorkfield/6M)"      },
-
-	/* Nehalem CPUs (45nm): */
-	{  6, 10, -1, -1, 26,   4,    -1,    -1, GAINESTOWN, XEON_ ,     0, "Gainestown (Xeon)"        },
-	{  6, 10, -1, -1, 26,   4,    -1,  4096, GAINESTOWN, XEON_ ,     0, "Gainestown 4M (Xeon)"     },
-	{  6, 10, -1, -1, 26,   4,    -1,  8192, GAINESTOWN, XEON_ ,     0, "Gainestown 8M (Xeon)"     },
-	{  6, 10, -1, -1, 26,   4,    -1,    -1, NC, XEON_|_7      ,     0, "Bloomfield (Xeon)"        },
-	{  6, 10, -1, -1, 26,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Bloomfield (Core i7)"     },
-	{  6, 10, -1, -1, 30,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Lynnfield (Core i7)"      },
-	{  6,  5, -1, -1, 37,   4,    -1,  8192, NC, CORE_|_I_|_5  ,     0, "Lynnfield (Core i5)"      },
-
-	/* Westmere CPUs (32nm): */
-	{  6,  5, -1, -1, 37,   2,    -1,    -1, NC, 0             ,     0, "Unknown Core i3/i5"       },
-	{  6, 12, -1, -1, 44,  -1,    -1,    -1, WESTMERE, XEON_   ,     0, "Westmere (Xeon)"          },
-	{  6, 12, -1, -1, 44,  -1,    -1, 12288, WESTMERE, XEON_   ,     0, "Gulftown (Xeon)"          },
-	{  6, 12, -1, -1, 44,   4,    -1, 12288, NC, CORE_|_I_|_7  ,     0, "Gulftown (Core i7)"       },
-	{  6,  5, -1, -1, 37,   2,    -1,  4096, NC, CORE_|_I_|_5  ,     0, "Clarkdale (Core i5)"      },
-	{  6,  5, -1, -1, 37,   2,    -1,  4096, NC, CORE_|_I_|_3  ,     0, "Clarkdale (Core i3)"      },
-	{  6,  5, -1, -1, 37,   2,    -1,    -1, NC, PENTIUM_      ,     0, "Arrandale"                },
-	{  6,  5, -1, -1, 37,   2,    -1,  4096, NC, CORE_|_I_|_7  ,     0, "Arrandale (Core i7)"      },
-	{  6,  5, -1, -1, 37,   2,    -1,  3072, NC, CORE_|_I_|_5  ,     0, "Arrandale (Core i5)"      },
-	{  6,  5, -1, -1, 37,   2,    -1,  3072, NC, CORE_|_I_|_3  ,     0, "Arrandale (Core i3)"      },
-
-	/* Sandy Bridge CPUs (32nm): */
-	{  6, 10, -1, -1, 42,  -1,    -1,    -1, NC, 0             ,     0, "Unknown Sandy Bridge"     },
-	{  6, 10, -1, -1, 42,  -1,    -1,    -1, NC, XEON_         ,     0, "Sandy Bridge (Xeon)"      },
-	{  6, 10, -1, -1, 42,  -1,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Sandy Bridge (Core i7)"   },
-	{  6, 10, -1, -1, 42,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Sandy Bridge (Core i7)"   },
-	{  6, 10, -1, -1, 42,   4,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Sandy Bridge (Core i5)"   },
-	{  6, 10, -1, -1, 42,   2,    -1,    -1, NC, CORE_|_I_|_3  ,     0, "Sandy Bridge (Core i3)"   },
-	{  6, 10, -1, -1, 42,   2,    -1,    -1, NC, PENTIUM_      ,     0, "Sandy Bridge (Pentium)"   },
-	{  6, 10, -1, -1, 42,   1,    -1,    -1, NC, CELERON_      ,     0, "Sandy Bridge (Celeron)"   },
-	{  6, 10, -1, -1, 42,   2,    -1,    -1, NC, CELERON_      ,     0, "Sandy Bridge (Celeron)"   },
-	{  6, 13, -1, -1, 45,  -1,    -1,    -1, NC, CORE_|_I_|_3  ,     0, "Sandy Bridge-E"           },
-	{  6, 13, -1, -1, 45,  -1,    -1,    -1, NC, XEON_         ,     0, "Sandy Bridge-E (Xeon)"    },
-
-	/* Ivy Bridge CPUs (22nm): */
-	{  6, 10, -1, -1, 58,  -1,    -1,    -1, NC, XEON_         ,     0, "Ivy Bridge (Xeon)"        },
-	{  6, 10, -1, -1, 58,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Ivy Bridge (Core i7)"     },
-	{  6, 10, -1, -1, 58,   4,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Ivy Bridge (Core i5)"     },
-	{  6, 10, -1, -1, 58,   2,    -1,    -1, NC, CORE_|_I_|_3  ,     0, "Ivy Bridge (Core i3)"     },
-	{  6, 10, -1, -1, 58,   2,    -1,    -1, NC, PENTIUM_      ,     0, "Ivy Bridge (Pentium)"     },
-	{  6, 10, -1, -1, 58,   1,    -1,    -1, NC, CELERON_      ,     0, "Ivy Bridge (Celeron)"     },
-	{  6, 10, -1, -1, 58,   2,    -1,    -1, NC, CELERON_      ,     0, "Ivy Bridge (Celeron)"     },
-	{  6, 14, -1, -1, 62,  -1,    -1,    -1, NC, 0             ,     0, "Ivy Bridge-E"             },
-	
-	/* Haswell CPUs (22nm): */
-	{  6, 12, -1, -1, 60,  -1,    -1,    -1, NC, XEON_         ,     0, "Haswell (Xeon)"           },
-	{  6, 12, -1, -1, 60,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Haswell (Core i7)"        },
-	{  6,  5, -1, -1, 69,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Haswell (Core i7)"        },
-	{  6,  6, -1, -1, 70,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Haswell (Core i7)"        },
-	{  6, 12, -1, -1, 60,   4,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Haswell (Core i5)"        },
-	{  6,  5, -1, -1, 69,   4,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Haswell (Core i5)"        },
-	{  6, 12, -1, -1, 60,   2,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Haswell (Core i5)"        },
-	{  6,  5, -1, -1, 69,   2,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Haswell (Core i5)"        },
-	{  6, 12, -1, -1, 60,   2,    -1,    -1, NC, CORE_|_I_|_3  ,     0, "Haswell (Core i3)"        },
-	{  6,  5, -1, -1, 69,   2,    -1,    -1, NC, CORE_|_I_|_3  ,     0, "Haswell (Core i3)"        },
-	{  6, 12, -1, -1, 60,   2,    -1,    -1, NC, PENTIUM_      ,     0, "Haswell (Pentium)"        },
-	{  6, 12, -1, -1, 60,   2,    -1,    -1, NC, CELERON_      ,     0, "Haswell (Celeron)"        },
-	{  6, 12, -1, -1, 60,   1,    -1,    -1, NC, CELERON_      ,     0, "Haswell (Celeron)"        },
-	{  6, 15, -1, -1, 63,  -1,    -1,    -1, NC, 0             ,     0, "Haswell-E"                },
-
-	/* Broadwell CPUs (14nm): */
-	{  6,  7, -1, -1, 71,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Broadwell (Core i7)"      },
-	{  6,  7, -1, -1, 71,   4,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Broadwell (Core i5)"      },
-	{  6, 13, -1, -1, 61,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Broadwell-U (Core i7)"    },
-	{  6, 13, -1, -1, 61,   2,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Broadwell-U (Core i7)"    },
-	{  6, 13, -1, -1, 61,   2,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Broadwell-U (Core i5)"    },
-	{  6, 13, -1, -1, 61,   2,    -1,    -1, NC, CORE_|_I_|_3  ,     0, "Broadwell-U (Core i3)"    },
-	{  6, 13, -1, -1, 61,   2,    -1,    -1, NC, PENTIUM_      ,     0, "Broadwell-U (Pentium)"    },
-	{  6, 13, -1, -1, 61,   2,    -1,    -1, NC, CELERON_      ,     0, "Broadwell-U (Celeron)"    },
-	{  6, 13, -1, -1, 61,   2,    -1,    -1, NA, 0             ,     0, "Broadwell-U (Core M)"     },
-	{  6, 15, -1, -1, 79,  -1,    -1,    -1, NC, XEON_         ,     0, "Broadwell-E (Xeon)"       },
-	{  6, 15, -1, -1, 79,   2,    -1,    -1, NC, CORE_|_I_|_3  ,     0, "Broadwell-E (Core i3)"    },
-	{  6, 15, -1, -1, 79,   2,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Broadwell-E (Core i5)"    },
-	{  6, 15, -1, -1, 79,   4,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Broadwell-E (Core i5)"    },
-	{  6, 15, -1, -1, 79,   2,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Broadwell-E (Core i7)"    },
-	{  6, 15, -1, -1, 79,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Broadwell-E (Core i7)"    },
-
-	/* Skylake CPUs (14nm): */
-	{  6, 14, -1, -1, 94,  -1,    -1,    -1, NC, XEON_         ,     0, "Skylake (Xeon)"           },
-	{  6, 14, -1, -1, 94,   4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Skylake (Core i7)"        },
-	{  6, 14, -1, -1, 94,   4,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Skylake (Core i5)"        },
-	{  6, 14, -1, -1, 94,   2,    -1,    -1, NC, CORE_|_I_|_3  ,     0, "Skylake (Core i3)"        },
-	{  6, 14, -1, -1, 94,   2,    -1,    -1, NC, PENTIUM_      ,     0, "Skylake (Pentium)"        },
-	{  6, 14, -1, -1, 78,   2,    -1,    -1, NC, PENTIUM_      ,     0, "Skylake (Pentium)"        },
-	{  6, 14, -1, -1, 94,   2,    -1,    -1, NC, CELERON_      ,     0, "Skylake (Celeron)"        },
-	{  6, 14, -1, -1, 78,   2,    -1,    -1, NC, CELERON_      ,     0, "Skylake (Celeron)"        },
-	{  6, 14, -1, -1, 78,   2,    -1,    -1, NC, CORE_|_M_|_7  ,     0, "Skylake (Core m7)"        },
-	{  6, 14, -1, -1, 78,   2,    -1,    -1, NC, CORE_|_M_|_5  ,     0, "Skylake (Core m5)"        },
-	{  6, 14, -1, -1, 78,   2,    -1,    -1, NC, CORE_|_M_|_3  ,     0, "Skylake (Core m3)"        },
-
-	/* Kaby Lake CPUs (14nm): */
-	{  6, 14, -1, -1, 158,  4,    -1,    -1, NC, CORE_|_I_|_7  ,     0, "Kaby Lake (Core i7)"      },
-	{  6, 14, -1, -1, 158,  4,    -1,    -1, NC, CORE_|_I_|_5  ,     0, "Kaby Lake (Core i5)"      },
-	{  6, 14, -1, -1, 158,  2,    -1,    -1, NC, CORE_|_I_|_3  ,     0, "Kaby Lake (Core i3)"      },
-	{  6, 14, -1, -1, 158,  2,    -1,    -1, NC, PENTIUM_      ,     0, "Kaby Lake (Pentium)"      },
-	{  6, 14, -1, -1, 158,  2,    -1,    -1, NC, CELERON_      ,     0, "Kaby Lake (Celeron)"      },
-	{  6, 14, -1, -1, 158,  2,    -1,    -1, NC, CORE_|_M_|_3  ,     0, "Kaby Lake (Core m3)"      },
-
-	/* Itaniums */
-	{  7, -1, -1, -1, -1,   1,    -1,    -1, NC, 0             ,     0, "Itanium"                  },
-	{ 15, -1, -1, 16, -1,   1,    -1,    -1, NC, 0             ,     0, "Itanium 2"                },
-};
-
-
 static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
 {
 	const struct feature_map_t matchtable_edx1[] = {
@@ -558,8 +273,6 @@ static void decode_intel_deterministic_cache_info(struct cpu_raw_data_t* raw,
 		else if (level == 4 && typenumber == 3)
 			type = L4;
 		else {
-			warnf("deterministic_cache: unknown level/typenumber combo (%d/%d), cannot\n", level, typenumber);
-			warnf("deterministic_cache: recognize cache type\n");
 			continue;
 		}
 		ways = ((raw->intel_fn4[ecx][1] >> 22) & 0x3ff) + 1;
@@ -681,7 +394,6 @@ static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data)
 			code = matchtable[i].c;
 			break;
 		}
-	debugf(2, "intel matchtable result is %d\n", code);
 	if (bits & XEON_) {
 		if (match_pattern(bs, "W35##") || match_pattern(bs, "[ELXW]75##"))
 			bits |= _7;
@@ -743,65 +455,6 @@ static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data)
 	return result;
 }
 
-static intel_model_t get_model_code(struct cpu_id_t* data)
-{
-	int i = 0;
-	int l = (int) strlen(data->brand_str);
-	const char *bs = data->brand_str;
-	int mod_flags = 0, model_no = 0, ndigs = 0;
-	/* If the CPU is a Core ix, then just return the model number generation: */
-	if ((i = match_pattern(bs, "Core(TM) i[357]")) != 0) {
-		i += 11;
-		if (i + 4 >= l) return UNKNOWN;
-		if (bs[i] == '2') return _2xxx;
-		if (bs[i] == '3') return _3xxx;
-		return UNKNOWN;
-	}
-	
-	/* For Core2-based Xeons: */
-	while (i < l - 3) {
-		if (bs[i] == 'C' && bs[i+1] == 'P' && bs[i+2] == 'U')
-			break;
-		i++;
-	}
-	if (i >= l - 3) return UNKNOWN;
-	i += 3;
-	while (i < l - 4 && bs[i] == ' ') i++;
-	if (i >= l - 4) return UNKNOWN;
-	while (i < l - 4 && !isdigit(bs[i])) {
-		if (bs[i] >= 'A' && bs[i] <= 'Z')
-			mod_flags |= (1 << (bs[i] - 'A'));
-		i++;
-	}
-	if (i >= l - 4) return UNKNOWN;
-	while (isdigit(bs[i])) {
-		ndigs++;
-		model_no = model_no * 10 + (int) (bs[i] - '0');
-		i++;
-	}
-	if (ndigs != 4) return UNKNOWN;
-#define HAVE(ch, flags) ((flags & (1 << ((int)(ch-'A')))) != 0)
-	switch (model_no / 100) {
-		case 30: return _3000;
-		case 31: return _3100;
-		case 32:
-		{
-			return (HAVE('X', mod_flags)) ? X3200 : _3200;
-		}
-		case 33:
-		{
-			return (HAVE('X', mod_flags)) ? X3300 : _3300;
-		}
-		case 51: return _5100;
-		case 52: return _5200;
-		case 53: return _5300;
-		case 54: return _5400;
-		default:
-			return UNKNOWN;
-	}
-#undef HAVE
-}
-
 static void decode_intel_sgx_features(const struct cpu_raw_data_t* raw, struct cpu_id_t* data)
 {
 	struct cpu_epc_t epc;
@@ -828,13 +481,11 @@ static void decode_intel_sgx_features(const struct cpu_raw_data_t* raw, struct c
 	for (i = 0; i < 1000000; i++) {
 		epc = cpuid_get_epc(i, raw);
 		if (epc.length == 0) {
-			debugf(2, "SGX: epc section request for %d returned null, no more EPC sections.\n", i);
 			data->sgx.num_epc_sections = i;
 			break;
 		}
 	}
 	if (data->sgx.num_epc_sections == -1) {
-		debugf(1, "SGX: warning: seems to be infinitude of EPC sections.\n");
 		data->sgx.num_epc_sections = 1000000;
 	}
 }
@@ -867,9 +518,6 @@ struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw)
 int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
 {
 	intel_code_and_bits_t brand;
-	intel_model_t model_code;
-	int i;
-	char* brand_code_str = NULL;
 
 	load_intel_features(raw, data);
 	if (raw->basic_cpuid[0][0] >= 4) {
@@ -881,38 +529,14 @@ int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, stru
 	decode_intel_number_of_cores(raw, data);
 
 	brand = get_brand_code_and_bits(data);
-	model_code = get_model_code(data);
-	for (i = 0; i < COUNT_OF(intel_bcode_str); i++) {
-		if (brand.code == intel_bcode_str[i].code) {
-			brand_code_str = intel_bcode_str[i].str;
-			break;
-		}
-	}
-	if (brand_code_str)
-		debugf(2, "Detected Intel brand code: %d (%s)\n", brand.code, brand_code_str);
-	else
-		debugf(2, "Detected Intel brand code: %d\n", brand.code);
-	if (brand.bits) {
-		debugf(2, "Detected Intel bits: ");
-		debug_print_lbits(2, brand.bits);
-	}
-	debugf(2, "Detected Intel model code: %d\n", model_code);
 	
 	internal->code.intel = brand.code;
 	internal->bits = brand.bits;
 	
 	if (data->flags[CPU_FEATURE_SGX]) {
-		debugf(2, "SGX seems to be present, decoding...\n");
 		// if SGX is indicated by the CPU, verify its presence:
 		decode_intel_sgx_features(raw, data);
 	}
 
-	internal->score = match_cpu_codename(cpudb_intel, COUNT_OF(cpudb_intel), data,
-		brand.code, brand.bits, model_code);
 	return 0;
 }
-
-void cpuid_get_list_intel(struct cpu_list_t* list)
-{
-	generic_get_cpu_list(cpudb_intel, COUNT_OF(cpudb_intel), list);
-}
diff --git a/src/3rdparty/libcpuid/recog_intel.h b/src/3rdparty/libcpuid/recog_intel.h
index b99c783bf..96676f3be 100644
--- a/src/3rdparty/libcpuid/recog_intel.h
+++ b/src/3rdparty/libcpuid/recog_intel.h
@@ -27,6 +27,5 @@
 #define __RECOG_INTEL_H__
 
 int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal);
-void cpuid_get_list_intel(struct cpu_list_t* list);
 
 #endif /*__RECOG_INTEL_H__*/

From 5a606be8be6ea566569b7efe7e04b831954438ec Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Thu, 8 Jun 2017 04:20:10 +0300
Subject: [PATCH 23/56] Move crypto/*

---
 CMakeLists.txt                          | 25 ++++++++++++++++++++++++-
 {crypto => src/crypto}/c_blake256.c     |  0
 {crypto => src/crypto}/c_blake256.h     |  0
 {crypto => src/crypto}/c_groestl.c      |  0
 {crypto => src/crypto}/c_groestl.h      |  0
 {crypto => src/crypto}/c_jh.c           |  0
 {crypto => src/crypto}/c_jh.h           |  0
 {crypto => src/crypto}/c_keccak.c       |  0
 {crypto => src/crypto}/c_keccak.h       |  0
 {crypto => src/crypto}/c_skein.c        |  0
 {crypto => src/crypto}/c_skein.h        |  0
 {crypto => src/crypto}/groestl_tables.h |  0
 {crypto => src/crypto}/hash.h           |  0
 {crypto => src/crypto}/skein_port.h     |  0
 {crypto => src/crypto}/soft_aes.c       |  0
 15 files changed, 24 insertions(+), 1 deletion(-)
 rename {crypto => src/crypto}/c_blake256.c (100%)
 rename {crypto => src/crypto}/c_blake256.h (100%)
 rename {crypto => src/crypto}/c_groestl.c (100%)
 rename {crypto => src/crypto}/c_groestl.h (100%)
 rename {crypto => src/crypto}/c_jh.c (100%)
 rename {crypto => src/crypto}/c_jh.h (100%)
 rename {crypto => src/crypto}/c_keccak.c (100%)
 rename {crypto => src/crypto}/c_keccak.h (100%)
 rename {crypto => src/crypto}/c_skein.c (100%)
 rename {crypto => src/crypto}/c_skein.h (100%)
 rename {crypto => src/crypto}/groestl_tables.h (100%)
 rename {crypto => src/crypto}/hash.h (100%)
 rename {crypto => src/crypto}/skein_port.h (100%)
 rename {crypto => src/crypto}/soft_aes.c (100%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 11a6d1bcc..936cc9bda 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,6 +18,17 @@ set(HEADERS
     src/version.h
    )
 
+set(HEADERS_CRYPTO
+    src/crypto/c_blake256.h
+    src/crypto/c_groestl.h
+    src/crypto/c_jh.h
+    src/crypto/c_keccak.h
+    src/crypto/c_skein.h
+    src/crypto/groestl_tables.h
+    src/crypto/hash.h
+    src/crypto/skein_port.h
+   )
+
 set(SOURCES
     src/App.cpp
     src/net/Client.cpp
@@ -30,6 +41,15 @@ set(SOURCES
     src/xmrig.cpp
    )
 
+set(SOURCES_CRYPTO
+    src/crypto/c_keccak.c
+    src/crypto/c_groestl.c
+    src/crypto/c_blake256.c
+    src/crypto/c_jh.c
+    src/crypto/c_skein.c
+    src/crypto/soft_aes.c
+   )
+
 if (WIN32)
     set(SOURCES_OS
         res/app.rc
@@ -57,6 +77,9 @@ if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
     set(CMAKE_BUILD_TYPE Release)
 endif()
 
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall")
+set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
+
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions")
 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2")
@@ -85,5 +108,5 @@ include_directories(${UV_INCLUDE_DIR})
 
 add_subdirectory(src/3rdparty/jansson)
 
-add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID})
+add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO})
 target_link_libraries(xmrig jansson ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB})
diff --git a/crypto/c_blake256.c b/src/crypto/c_blake256.c
similarity index 100%
rename from crypto/c_blake256.c
rename to src/crypto/c_blake256.c
diff --git a/crypto/c_blake256.h b/src/crypto/c_blake256.h
similarity index 100%
rename from crypto/c_blake256.h
rename to src/crypto/c_blake256.h
diff --git a/crypto/c_groestl.c b/src/crypto/c_groestl.c
similarity index 100%
rename from crypto/c_groestl.c
rename to src/crypto/c_groestl.c
diff --git a/crypto/c_groestl.h b/src/crypto/c_groestl.h
similarity index 100%
rename from crypto/c_groestl.h
rename to src/crypto/c_groestl.h
diff --git a/crypto/c_jh.c b/src/crypto/c_jh.c
similarity index 100%
rename from crypto/c_jh.c
rename to src/crypto/c_jh.c
diff --git a/crypto/c_jh.h b/src/crypto/c_jh.h
similarity index 100%
rename from crypto/c_jh.h
rename to src/crypto/c_jh.h
diff --git a/crypto/c_keccak.c b/src/crypto/c_keccak.c
similarity index 100%
rename from crypto/c_keccak.c
rename to src/crypto/c_keccak.c
diff --git a/crypto/c_keccak.h b/src/crypto/c_keccak.h
similarity index 100%
rename from crypto/c_keccak.h
rename to src/crypto/c_keccak.h
diff --git a/crypto/c_skein.c b/src/crypto/c_skein.c
similarity index 100%
rename from crypto/c_skein.c
rename to src/crypto/c_skein.c
diff --git a/crypto/c_skein.h b/src/crypto/c_skein.h
similarity index 100%
rename from crypto/c_skein.h
rename to src/crypto/c_skein.h
diff --git a/crypto/groestl_tables.h b/src/crypto/groestl_tables.h
similarity index 100%
rename from crypto/groestl_tables.h
rename to src/crypto/groestl_tables.h
diff --git a/crypto/hash.h b/src/crypto/hash.h
similarity index 100%
rename from crypto/hash.h
rename to src/crypto/hash.h
diff --git a/crypto/skein_port.h b/src/crypto/skein_port.h
similarity index 100%
rename from crypto/skein_port.h
rename to src/crypto/skein_port.h
diff --git a/crypto/soft_aes.c b/src/crypto/soft_aes.c
similarity index 100%
rename from crypto/soft_aes.c
rename to src/crypto/soft_aes.c

From 878e021ff66fe2a8c30a9f0a65da08e476279384 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Thu, 8 Jun 2017 09:47:25 +0300
Subject: [PATCH 24/56] Initial CryptoNight.

---
 CMakeLists.txt             |   4 +
 src/App.cpp                |   6 +
 src/Options.cpp            |   6 +
 src/Options.h              |   5 +
 src/crypto/CryptoNight.cpp | 105 +++++++++++
 src/crypto/CryptoNight.h   |  45 +++++
 src/crypto/CryptoNight_p.h | 349 +++++++++++++++++++++++++++++++++++++
 7 files changed, 520 insertions(+)
 create mode 100644 src/crypto/CryptoNight.cpp
 create mode 100644 src/crypto/CryptoNight.h
 create mode 100644 src/crypto/CryptoNight_p.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 936cc9bda..0d993dda8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,6 +24,8 @@ set(HEADERS_CRYPTO
     src/crypto/c_jh.h
     src/crypto/c_keccak.h
     src/crypto/c_skein.h
+    src/crypto/CryptoNight.h
+    src/crypto/CryptoNight_p.h
     src/crypto/groestl_tables.h
     src/crypto/hash.h
     src/crypto/skein_port.h
@@ -48,6 +50,8 @@ set(SOURCES_CRYPTO
     src/crypto/c_jh.c
     src/crypto/c_skein.c
     src/crypto/soft_aes.c
+    src/crypto/soft_aes.c
+    src/crypto/CryptoNight.cpp
    )
 
 if (WIN32)
diff --git a/src/App.cpp b/src/App.cpp
index e7cf1aa46..6608554c0 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -28,6 +28,7 @@
 #include "App.h"
 #include "Console.h"
 #include "Cpu.h"
+#include "crypto/CryptoNight.h"
 #include "net/Client.h"
 #include "net/Network.h"
 #include "Options.h"
@@ -61,6 +62,11 @@ App::exec()
         return 0;
     }
 
+    if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) {
+        LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName());
+        return 1;
+    }
+
     Summary::print();
 
     m_network->connect();
diff --git a/src/Options.cpp b/src/Options.cpp
index c09de032f..1fbdb1419 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -116,6 +116,12 @@ Options *Options::parse(int argc, char **argv)
 }
 
 
+const char *Options::algoName() const
+{
+    return algo_names[m_algo];
+}
+
+
 Options::Options(int argc, char **argv) :
     m_background(false),
     m_colors(true),
diff --git a/src/Options.h b/src/Options.h
index 0c1dcc6eb..cbad99fa9 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -52,16 +52,21 @@ public:
     static Options *parse(int argc, char **argv);
 
     inline bool colors() const          { return m_colors; }
+    inline bool doubleHash() const      { return m_doubleHash; }
     inline bool isReady() const         { return m_ready; }
     inline bool keepAlive() const       { return m_keepAlive; }
     inline const char *pass() const     { return m_pass; }
     inline const char *user() const     { return m_user; }
     inline const Url *backupUrl() const { return m_backupUrl; }
     inline const Url *url() const       { return m_url; }
+    inline int algo() const             { return m_algo; }
+    inline int algoVariant() const      { return m_algoVariant; }
     inline int donateLevel() const      { return m_donateLevel; }
     inline int retries() const          { return m_retries; }
     inline int retryPause() const       { return m_retryPause; }
 
+    const char *algoName() const;
+
 private:
     Options(int argc, char **argv);
     ~Options();
diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp
new file mode 100644
index 000000000..a96ac7611
--- /dev/null
+++ b/src/crypto/CryptoNight.cpp
@@ -0,0 +1,105 @@
+/* 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 "crypto/CryptoNight.h"
+#include "crypto/CryptoNight_p.h"
+#include "Options.h"
+
+
+const static uint8_t test_input[152] = {
+    0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19,
+    0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9,
+    0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F,
+    0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46,
+    0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02,
+    0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
+    0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
+    0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
+    0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
+    0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01
+};
+
+
+const static uint8_t test_output0[64] = {
+    0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66,
+    0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F,
+    0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
+    0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00
+};
+
+
+#ifndef XMRIG_NO_AEON
+const static uint8_t test_output1[64] = {
+    0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE,
+    0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD,
+    0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
+    0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88,
+};
+
+//void cryptonight_lite_av1_aesni(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
+//void cryptonight_lite_av2_aesni_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
+//void cryptonight_lite_av3_softaes(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
+//void cryptonight_lite_av4_softaes_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
+#endif
+
+
+static inline void cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+    cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
+}
+
+
+void (*cryptonight_hash_ctx)(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = nullptr;
+
+
+static bool self_test(int algo) {
+    if (cryptonight_hash_ctx == NULL) {
+        return false;
+    }
+
+    char output[64];
+
+    struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) _mm_malloc(sizeof(struct cryptonight_ctx), 16);
+    ctx->memory = (uint8_t *) _mm_malloc(MEMORY * 2, 16);
+
+    cryptonight_hash_ctx(test_input, 76, output, ctx);
+
+    _mm_free(ctx->memory);
+    _mm_free(ctx);
+
+#   ifndef XMRIG_NO_AEON
+    if (algo == Options::ALGO_CRYPTONIGHT_LITE) {
+        return memcmp(output, test_output1, (Options::i()->doubleHash() ? 64 : 32)) == 0;
+    }
+#   endif
+
+    return memcmp(output, test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0;
+}
+
+
+bool CryptoNight::init(int algo, int variant)
+{
+    cryptonight_hash_ctx = cryptonight_av1_aesni;
+
+    return self_test(algo);
+}
diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h
new file mode 100644
index 000000000..1c201af38
--- /dev/null
+++ b/src/crypto/CryptoNight.h
@@ -0,0 +1,45 @@
+/* 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/>.
+ */
+
+#ifndef __CRYPTONIGHT_H__
+#define __CRYPTONIGHT_H__
+
+#include <stdint.h>
+
+#define MEMORY      2097152 /* 2 MiB */
+#define MEMORY_LITE 1048576 /* 1 MiB */
+
+struct cryptonight_ctx {
+    uint8_t state0[200] __attribute__((aligned(16)));
+    uint8_t state1[200] __attribute__((aligned(16)));
+    uint8_t* memory     __attribute__((aligned(16)));
+};
+
+
+class CryptoNight
+{
+public:
+    static bool init(int algo, int variant);
+};
+
+#endif /* __CRYPTONIGHT_H__ */
diff --git a/src/crypto/CryptoNight_p.h b/src/crypto/CryptoNight_p.h
new file mode 100644
index 000000000..28ca790d3
--- /dev/null
+++ b/src/crypto/CryptoNight_p.h
@@ -0,0 +1,349 @@
+/* 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/>.
+ */
+
+#ifndef __CRYPTONIGHT_P_H__
+#define __CRYPTONIGHT_P_H__
+
+
+#include <x86intrin.h>
+
+
+#include "crypto/CryptoNight.h"
+
+
+extern "C"
+{
+#include "crypto/c_keccak.h"
+#include "crypto/c_groestl.h"
+#include "crypto/c_blake256.h"
+#include "crypto/c_jh.h"
+#include "crypto/c_skein.h"
+}
+
+
+static inline void do_blake_hash(const void* input, size_t len, char* output) {
+    blake256_hash(reinterpret_cast<uint8_t*>(output), static_cast<const uint8_t*>(input), len);
+}
+
+
+static inline void do_groestl_hash(const void* input, size_t len, char* output) {
+    groestl(static_cast<const uint8_t*>(input), len * 8, reinterpret_cast<uint8_t*>(output));
+}
+
+
+static inline void do_jh_hash(const void* input, size_t len, char* output) {
+    jh_hash(32 * 8, static_cast<const uint8_t*>(input), 8 * len, reinterpret_cast<uint8_t*>(output));
+}
+
+
+static inline void do_skein_hash(const void* input, size_t len, char* output) {
+    skein_hash(8 * 32, static_cast<const uint8_t*>(input), 8 * len, reinterpret_cast<uint8_t*>(output));
+}
+
+
+void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
+
+
+__m128i soft_aesenc(__m128i in, __m128i key);
+__m128i soft_aeskeygenassist(__m128i key, uint8_t rcon);
+
+
+#if defined(__x86_64__)
+#   define EXTRACT64(X) _mm_cvtsi128_si64(X)
+
+static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
+{
+    unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
+    *hi = r >> 64;
+    return (uint64_t) r;
+}
+#elif defined(__i386__)
+#   define HI32(X) \
+    _mm_srli_si128((X), 4)
+
+
+#   define EXTRACT64(X) \
+    ((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
+    ((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
+
+static inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
+    // multiplier   = ab = a * 2^32 + b
+    // multiplicand = cd = c * 2^32 + d
+    // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
+    uint64_t a = multiplier >> 32;
+    uint64_t b = multiplier & 0xFFFFFFFF;
+    uint64_t c = multiplicand >> 32;
+    uint64_t d = multiplicand & 0xFFFFFFFF;
+
+    //uint64_t ac = a * c;
+    uint64_t ad = a * d;
+    //uint64_t bc = b * c;
+    uint64_t bd = b * d;
+
+    uint64_t adbc = ad + (b * c);
+    uint64_t adbc_carry = adbc < ad ? 1 : 0;
+
+    // multiplier * multiplicand = product_hi * 2^64 + product_lo
+    uint64_t product_lo = bd + (adbc << 32);
+    uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
+    *product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
+
+    return product_lo;
+}
+#endif
+
+
+// This will shift and xor tmp1 into itself as 4 32-bit vals such as
+// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
+static inline __m128i sl_xor(__m128i tmp1)
+{
+    __m128i tmp4;
+    tmp4 = _mm_slli_si128(tmp1, 0x04);
+    tmp1 = _mm_xor_si128(tmp1, tmp4);
+    tmp4 = _mm_slli_si128(tmp4, 0x04);
+    tmp1 = _mm_xor_si128(tmp1, tmp4);
+    tmp4 = _mm_slli_si128(tmp4, 0x04);
+    tmp1 = _mm_xor_si128(tmp1, tmp4);
+    return tmp1;
+}
+
+
+template<uint8_t rcon>
+static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2)
+{
+    __m128i xout1 = _mm_aeskeygenassist_si128(*xout2, rcon);
+    xout1  = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
+    *xout0 = sl_xor(*xout0);
+    *xout0 = _mm_xor_si128(*xout0, xout1);
+    xout1  = _mm_aeskeygenassist_si128(*xout0, 0x00);
+    xout1  = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
+    *xout2 = sl_xor(*xout2);
+    *xout2 = _mm_xor_si128(*xout2, xout1);
+}
+
+
+static inline void soft_aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
+{
+    __m128i xout1 = soft_aeskeygenassist(*xout2, rcon);
+    xout1  = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
+    *xout0 = sl_xor(*xout0);
+    *xout0 = _mm_xor_si128(*xout0, xout1);
+    xout1  = soft_aeskeygenassist(*xout0, 0x00);
+    xout1  = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
+    *xout2 = sl_xor(*xout2);
+    *xout2 = _mm_xor_si128(*xout2, xout1);
+}
+
+
+template<bool SOFT_AES>
+static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
+{
+    __m128i xout0 = _mm_load_si128(memory);
+    __m128i xout2 = _mm_load_si128(memory +1 );
+    *k0 = xout0;
+    *k1 = xout2;
+
+    SOFT_AES ? soft_aes_genkey_sub(&xout0, &xout2, 0x01) : aes_genkey_sub<0x01>(&xout0, &xout2);
+    *k2 = xout0;
+    *k3 = xout2;
+
+    SOFT_AES ? soft_aes_genkey_sub(&xout0, &xout2, 0x02) : aes_genkey_sub<0x02>(&xout0, &xout2);
+    *k4 = xout0;
+    *k5 = xout2;
+
+    SOFT_AES ? soft_aes_genkey_sub(&xout0, &xout2, 0x04) : aes_genkey_sub<0x04>(&xout0, &xout2);
+    *k6 = xout0;
+    *k7 = xout2;
+
+    SOFT_AES ? soft_aes_genkey_sub(&xout0, &xout2, 0x08) : aes_genkey_sub<0x08>(&xout0, &xout2);
+    *k8 = xout0;
+    *k9 = xout2;
+}
+
+
+template<bool SOFT_AES>
+static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
+{
+    if (SOFT_AES) {
+        *x0 = soft_aesenc(*x0, key);
+        *x1 = soft_aesenc(*x1, key);
+        *x2 = soft_aesenc(*x2, key);
+        *x3 = soft_aesenc(*x3, key);
+        *x4 = soft_aesenc(*x4, key);
+        *x5 = soft_aesenc(*x5, key);
+        *x6 = soft_aesenc(*x6, key);
+        *x7 = soft_aesenc(*x7, key);
+    }
+    else {
+        *x0 = _mm_aesenc_si128(*x0, key);
+        *x1 = _mm_aesenc_si128(*x1, key);
+        *x2 = _mm_aesenc_si128(*x2, key);
+        *x3 = _mm_aesenc_si128(*x3, key);
+        *x4 = _mm_aesenc_si128(*x4, key);
+        *x5 = _mm_aesenc_si128(*x5, key);
+        *x6 = _mm_aesenc_si128(*x6, key);
+        *x7 = _mm_aesenc_si128(*x7, key);
+    }
+}
+
+
+template<size_t MEM, bool SOFT_AES>
+static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
+{
+    __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
+    __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
+
+    aes_genkey<SOFT_AES>(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
+
+    xin0 = _mm_load_si128(input + 4);
+    xin1 = _mm_load_si128(input + 5);
+    xin2 = _mm_load_si128(input + 6);
+    xin3 = _mm_load_si128(input + 7);
+    xin4 = _mm_load_si128(input + 8);
+    xin5 = _mm_load_si128(input + 9);
+    xin6 = _mm_load_si128(input + 10);
+    xin7 = _mm_load_si128(input + 11);
+
+    for (size_t i = 0; __builtin_expect(i < MEM / sizeof(__m128i), 1); i += 8) {
+        aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
+        aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
+        aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
+        aes_round<SOFT_AES>(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
+        aes_round<SOFT_AES>(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
+        aes_round<SOFT_AES>(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
+        aes_round<SOFT_AES>(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
+        aes_round<SOFT_AES>(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
+        aes_round<SOFT_AES>(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
+        aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
+
+        _mm_store_si128(output + i + 0, xin0);
+        _mm_store_si128(output + i + 1, xin1);
+        _mm_store_si128(output + i + 2, xin2);
+        _mm_store_si128(output + i + 3, xin3);
+        _mm_store_si128(output + i + 4, xin4);
+        _mm_store_si128(output + i + 5, xin5);
+        _mm_store_si128(output + i + 6, xin6);
+        _mm_store_si128(output + i + 7, xin7);
+    }
+}
+
+
+template<size_t MEM, bool SOFT_AES>
+static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
+{
+    __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
+    __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
+
+    aes_genkey<SOFT_AES>(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
+
+    xout0 = _mm_load_si128(output + 4);
+    xout1 = _mm_load_si128(output + 5);
+    xout2 = _mm_load_si128(output + 6);
+    xout3 = _mm_load_si128(output + 7);
+    xout4 = _mm_load_si128(output + 8);
+    xout5 = _mm_load_si128(output + 9);
+    xout6 = _mm_load_si128(output + 10);
+    xout7 = _mm_load_si128(output + 11);
+
+    for (size_t i = 0; __builtin_expect(i < MEM / sizeof(__m128i), 1); i += 8)
+    {
+        xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
+        xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
+        xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
+        xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
+        xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
+        xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
+        xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
+        xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
+
+        aes_round<SOFT_AES>(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
+        aes_round<SOFT_AES>(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
+        aes_round<SOFT_AES>(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
+        aes_round<SOFT_AES>(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
+        aes_round<SOFT_AES>(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
+        aes_round<SOFT_AES>(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
+        aes_round<SOFT_AES>(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
+        aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
+        aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
+        aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
+    }
+
+    _mm_store_si128(output + 4, xout0);
+    _mm_store_si128(output + 5, xout1);
+    _mm_store_si128(output + 6, xout2);
+    _mm_store_si128(output + 7, xout3);
+    _mm_store_si128(output + 8, xout4);
+    _mm_store_si128(output + 9, xout5);
+    _mm_store_si128(output + 10, xout6);
+    _mm_store_si128(output + 11, xout7);
+}
+
+
+template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
+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);
+
+    cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) ctx->state0, (__m128i*) ctx->memory);
+
+    const uint8_t* l0 = ctx->memory;
+    uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
+
+    uint64_t al0 = h0[0] ^ h0[4];
+    uint64_t ah0 = h0[1] ^ h0[5];
+    __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
+
+    uint64_t idx0 = h0[0] ^ h0[4];
+
+    for (size_t i = 0; __builtin_expect(i < ITERATIONS, 1); i++) {
+        __m128i cx;
+        cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
+        cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
+
+        _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
+        idx0 = EXTRACT64(cx);
+        bx0 = cx;
+
+        uint64_t hi, lo, cl, ch;
+        cl = ((uint64_t*) &l0[idx0 & MASK])[0];
+        ch = ((uint64_t*) &l0[idx0 & MASK])[1];
+        lo = _umul128(idx0, cl, &hi);
+
+        al0 += hi;
+        ah0 += lo;
+
+        ((uint64_t*)&l0[idx0 & MASK])[0] = al0;
+        ((uint64_t*)&l0[idx0 & MASK])[1] = ah0;
+
+        ah0 ^= ch;
+        al0 ^= cl;
+        idx0 = al0;
+    }
+
+    cn_implode_scratchpad<MEM, SOFT_AES>((__m128i*) ctx->memory, (__m128i*) ctx->state0);
+
+    keccakf(h0, 24);
+    extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast<char*>(output));
+}
+
+#endif /* __CRYPTONIGHT_P_H__ */

From 8b83a5fe2e9e0dd117077aba5284209a4e314b9a Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Thu, 8 Jun 2017 23:31:42 +0300
Subject: [PATCH 25/56] Implemented CryptoNight with C++ templates.

---
 CMakeLists.txt                |   1 +
 src/Options.cpp               |   4 +
 src/crypto/CryptoNight.cpp    | 141 ++++++++++++++++++++--------------
 src/crypto/CryptoNight.h      |   6 ++
 src/crypto/CryptoNight_p.h    |  96 +++++++++++++++++++++--
 src/crypto/CryptoNight_test.h |  60 +++++++++++++++
 6 files changed, 242 insertions(+), 66 deletions(-)
 create mode 100644 src/crypto/CryptoNight_test.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0d993dda8..5f34e2346 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -26,6 +26,7 @@ set(HEADERS_CRYPTO
     src/crypto/c_skein.h
     src/crypto/CryptoNight.h
     src/crypto/CryptoNight_p.h
+    src/crypto/CryptoNight_test.h
     src/crypto/groestl_tables.h
     src/crypto/hash.h
     src/crypto/skein_port.h
diff --git a/src/Options.cpp b/src/Options.cpp
index 1fbdb1419..11f01d00d 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -178,6 +178,10 @@ Options::Options(int argc, char **argv) :
         m_pass = strdup("x");
     }
 
+    if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) {
+        m_doubleHash = true;
+    }
+
     m_ready = true;
 }
 
diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp
index a96ac7611..b6273dc52 100644
--- a/src/crypto/CryptoNight.cpp
+++ b/src/crypto/CryptoNight.cpp
@@ -24,56 +24,93 @@
 
 #include "crypto/CryptoNight.h"
 #include "crypto/CryptoNight_p.h"
+#include "crypto/CryptoNight_test.h"
 #include "Options.h"
 
 
-const static uint8_t test_input[152] = {
-    0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19,
-    0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9,
-    0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F,
-    0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46,
-    0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02,
-    0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
-    0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
-    0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
-    0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
-    0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01
-};
-
-
-const static uint8_t test_output0[64] = {
-    0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66,
-    0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F,
-    0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
-    0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00
-};
-
-
-#ifndef XMRIG_NO_AEON
-const static uint8_t test_output1[64] = {
-    0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE,
-    0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD,
-    0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
-    0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88,
-};
-
-//void cryptonight_lite_av1_aesni(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-//void cryptonight_lite_av2_aesni_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-//void cryptonight_lite_av3_softaes(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-//void cryptonight_lite_av4_softaes_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-#endif
-
-
-static inline void cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
-    cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
-}
-
-
 void (*cryptonight_hash_ctx)(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = nullptr;
 
 
-static bool self_test(int algo) {
-    if (cryptonight_hash_ctx == NULL) {
+static void cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+    cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
+}
+
+
+static void cryptonight_av2_aesni_double(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+    cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
+}
+
+
+static void cryptonight_av3_softaes(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+    cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx);
+}
+
+
+static void cryptonight_av4_softaes_double(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+    cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx);
+}
+
+
+#ifndef XMRIG_NO_AEON
+static void cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+    cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx);
+}
+
+
+static void cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+    cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx);
+}
+
+
+static void cryptonight_lite_av3_softaes(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+    cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx);
+}
+
+
+static void cryptonight_lite_av4_softaes_double(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+    cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx);
+}
+
+void (*cryptonight_variations[8])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = {
+            cryptonight_av1_aesni,
+            cryptonight_av2_aesni_double,
+            cryptonight_av3_softaes,
+            cryptonight_av4_softaes_double,
+            cryptonight_lite_av1_aesni,
+            cryptonight_lite_av2_aesni_double,
+            cryptonight_lite_av3_softaes,
+            cryptonight_lite_av4_softaes_double
+        };
+#else
+void (*cryptonight_variations[4])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = {
+            cryptonight_av1_aesni,
+            cryptonight_av2_aesni_double,
+            cryptonight_av3_softaes,
+            cryptonight_av4_softaes_double
+        };
+#endif
+
+
+bool CryptoNight::init(int algo, int variant)
+{
+    if (variant < 1 || variant > 4) {
+        return false;
+    }
+
+#   ifndef XMRIG_NO_AEON
+    const int index = algo == Options::ALGO_CRYPTONIGHT_LITE ? (variant + 3) : (variant - 1);
+#   else
+    const int index = variant - 1;
+#   endif
+
+    cryptonight_hash_ctx = cryptonight_variations[index];
+
+    return selfTest(algo);
+}
+
+
+bool CryptoNight::selfTest(int algo) {
+    if (cryptonight_hash_ctx == nullptr) {
         return false;
     }
 
@@ -87,19 +124,5 @@ static bool self_test(int algo) {
     _mm_free(ctx->memory);
     _mm_free(ctx);
 
-#   ifndef XMRIG_NO_AEON
-    if (algo == Options::ALGO_CRYPTONIGHT_LITE) {
-        return memcmp(output, test_output1, (Options::i()->doubleHash() ? 64 : 32)) == 0;
-    }
-#   endif
-
-    return memcmp(output, test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0;
-}
-
-
-bool CryptoNight::init(int algo, int variant)
-{
-    cryptonight_hash_ctx = cryptonight_av1_aesni;
-
-    return self_test(algo);
+    return memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output1 : test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0;
 }
diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h
index 1c201af38..ce1b7ba83 100644
--- a/src/crypto/CryptoNight.h
+++ b/src/crypto/CryptoNight.h
@@ -24,11 +24,14 @@
 #ifndef __CRYPTONIGHT_H__
 #define __CRYPTONIGHT_H__
 
+
 #include <stdint.h>
 
+
 #define MEMORY      2097152 /* 2 MiB */
 #define MEMORY_LITE 1048576 /* 1 MiB */
 
+
 struct cryptonight_ctx {
     uint8_t state0[200] __attribute__((aligned(16)));
     uint8_t state1[200] __attribute__((aligned(16)));
@@ -40,6 +43,9 @@ class CryptoNight
 {
 public:
     static bool init(int algo, int variant);
+
+private:
+    static bool selfTest(int algo);
 };
 
 #endif /* __CRYPTONIGHT_H__ */
diff --git a/src/crypto/CryptoNight_p.h b/src/crypto/CryptoNight_p.h
index 28ca790d3..ed24a510b 100644
--- a/src/crypto/CryptoNight_p.h
+++ b/src/crypto/CryptoNight_p.h
@@ -38,6 +38,9 @@ extern "C"
 #include "crypto/c_blake256.h"
 #include "crypto/c_jh.h"
 #include "crypto/c_skein.h"
+
+__m128i soft_aesenc(__m128i in, __m128i key);
+__m128i soft_aeskeygenassist(__m128i key, uint8_t rcon);
 }
 
 
@@ -64,14 +67,11 @@ static inline void do_skein_hash(const void* input, size_t len, char* output) {
 void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
 
 
-__m128i soft_aesenc(__m128i in, __m128i key);
-__m128i soft_aeskeygenassist(__m128i key, uint8_t rcon);
-
 
 #if defined(__x86_64__)
 #   define EXTRACT64(X) _mm_cvtsi128_si64(X)
 
-static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
+static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
 {
     unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
     *hi = r >> 64;
@@ -86,7 +86,7 @@ static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
     ((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
     ((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
 
-static inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
+static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
     // multiplier   = ab = a * 2^32 + b
     // multiplicand = cd = c * 2^32 + d
     // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
@@ -300,7 +300,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>
-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);
 
@@ -327,7 +327,7 @@ void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restr
         uint64_t hi, lo, cl, ch;
         cl = ((uint64_t*) &l0[idx0 & MASK])[0];
         ch = ((uint64_t*) &l0[idx0 & MASK])[1];
-        lo = _umul128(idx0, cl, &hi);
+        lo = __umul128(idx0, cl, &hi);
 
         al0 += hi;
         ah0 += lo;
@@ -346,4 +346,86 @@ void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restr
     extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast<char*>(output));
 }
 
+
+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)
+{
+    keccak((const uint8_t *) input,        size, ctx->state0, 200);
+    keccak((const uint8_t *) input + size, size, ctx->state1, 200);
+
+    const uint8_t* l0 = ctx->memory;
+    const uint8_t* l1 = ctx->memory + MEMORY;
+    uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
+    uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx->state1);
+
+    cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) h0, (__m128i*) l0);
+    cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) h1, (__m128i*) l1);
+
+    uint64_t al0 = h0[0] ^ h0[4];
+    uint64_t al1 = h1[0] ^ h1[4];
+    uint64_t ah0 = h0[1] ^ h0[5];
+    uint64_t ah1 = h1[1] ^ h1[5];
+
+    __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
+    __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
+
+    uint64_t idx0 = h0[0] ^ h0[4];
+    uint64_t idx1 = h1[0] ^ h1[4];
+
+    for (size_t i = 0; __builtin_expect(i < ITERATIONS, 1); i++) {
+        __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
+        __m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
+
+        cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
+        cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
+
+        _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
+        _mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
+
+        idx0 = EXTRACT64(cx0);
+        idx1 = EXTRACT64(cx1);
+
+        bx0 = cx0;
+        bx1 = cx1;
+
+        uint64_t hi, lo, cl, ch;
+        cl = ((uint64_t*) &l0[idx0 & MASK])[0];
+        ch = ((uint64_t*) &l0[idx0 & MASK])[1];
+        lo = __umul128(idx0, cl, &hi);
+
+        al0 += hi;
+        ah0 += lo;
+
+        ((uint64_t*) &l0[idx0 & MASK])[0] = al0;
+        ((uint64_t*) &l0[idx0 & MASK])[1] = ah0;
+
+        ah0 ^= ch;
+        al0 ^= cl;
+        idx0 = al0;
+
+        cl = ((uint64_t*) &l1[idx1 & MASK])[0];
+        ch = ((uint64_t*) &l1[idx1 & MASK])[1];
+        lo = __umul128(idx1, cl, &hi);
+
+        al1 += hi;
+        ah1 += lo;
+
+        ((uint64_t*) &l1[idx1 & MASK])[0] = al1;
+        ((uint64_t*) &l1[idx1 & MASK])[1] = ah1;
+
+        ah1 ^= ch;
+        al1 ^= cl;
+        idx1 = al1;
+    }
+
+    cn_implode_scratchpad<MEM, SOFT_AES>((__m128i*) l0, (__m128i*) h0);
+    cn_implode_scratchpad<MEM, SOFT_AES>((__m128i*) l1, (__m128i*) h1);
+
+    keccakf(h0, 24);
+    keccakf(h1, 24);
+
+    extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast<char*>(output));
+    extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast<char*>(output) + 32);
+}
+
 #endif /* __CRYPTONIGHT_P_H__ */
diff --git a/src/crypto/CryptoNight_test.h b/src/crypto/CryptoNight_test.h
new file mode 100644
index 000000000..b2985379b
--- /dev/null
+++ b/src/crypto/CryptoNight_test.h
@@ -0,0 +1,60 @@
+/* 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/>.
+ */
+
+#ifndef __CRYPTONIGHT_TEST_H__
+#define __CRYPTONIGHT_TEST_H__
+
+
+const static uint8_t test_input[152] = {
+    0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19,
+    0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9,
+    0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F,
+    0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46,
+    0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02,
+    0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
+    0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
+    0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
+    0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
+    0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01
+};
+
+
+const static uint8_t test_output0[64] = {
+    0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66,
+    0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F,
+    0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
+    0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00
+};
+
+
+#ifndef XMRIG_NO_AEON
+const static uint8_t test_output1[64] = {
+    0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE,
+    0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD,
+    0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
+    0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88,
+};
+#endif
+
+
+#endif /* __CRYPTONIGHT_TEST_H__ */

From 04c5d6d00ad4ebbebebc014417261b41342f20d3 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Fri, 9 Jun 2017 02:47:46 +0300
Subject: [PATCH 26/56] Print threads summary.

---
 .../cryptonight-lite/cryptonight_lite_aesni.h | 256 ------------------
 .../cryptonight_lite_av1_aesni.c              |  77 ------
 .../cryptonight_lite_av2_aesni_double.c       | 111 --------
 .../cryptonight_lite_av3_softaes.c            |  77 ------
 .../cryptonight_lite_av4_softaes_double.c     | 111 --------
 .../cryptonight_lite_softaes.h                | 237 ----------------
 algo/cryptonight/cryptonight.c                | 244 -----------------
 algo/cryptonight/cryptonight.h                |  47 ----
 algo/cryptonight/cryptonight_aesni.h          | 256 ------------------
 algo/cryptonight/cryptonight_av1_aesni.c      |  77 ------
 .../cryptonight_av2_aesni_double.c            | 111 --------
 algo/cryptonight/cryptonight_av3_softaes.c    |  77 ------
 .../cryptonight_av4_softaes_double.c          | 111 --------
 algo/cryptonight/cryptonight_softaes.h        | 237 ----------------
 crypto/hash.c                                 |  24 --
 src/Options.cpp                               |  33 +--
 src/Options.h                                 |   3 +
 src/Summary.cpp                               |  34 ++-
 18 files changed, 51 insertions(+), 2072 deletions(-)
 delete mode 100644 algo/cryptonight-lite/cryptonight_lite_aesni.h
 delete mode 100644 algo/cryptonight-lite/cryptonight_lite_av1_aesni.c
 delete mode 100644 algo/cryptonight-lite/cryptonight_lite_av2_aesni_double.c
 delete mode 100644 algo/cryptonight-lite/cryptonight_lite_av3_softaes.c
 delete mode 100644 algo/cryptonight-lite/cryptonight_lite_av4_softaes_double.c
 delete mode 100644 algo/cryptonight-lite/cryptonight_lite_softaes.h
 delete mode 100644 algo/cryptonight/cryptonight.c
 delete mode 100644 algo/cryptonight/cryptonight.h
 delete mode 100644 algo/cryptonight/cryptonight_aesni.h
 delete mode 100644 algo/cryptonight/cryptonight_av1_aesni.c
 delete mode 100644 algo/cryptonight/cryptonight_av2_aesni_double.c
 delete mode 100644 algo/cryptonight/cryptonight_av3_softaes.c
 delete mode 100644 algo/cryptonight/cryptonight_av4_softaes_double.c
 delete mode 100644 algo/cryptonight/cryptonight_softaes.h
 delete mode 100644 crypto/hash.c

diff --git a/algo/cryptonight-lite/cryptonight_lite_aesni.h b/algo/cryptonight-lite/cryptonight_lite_aesni.h
deleted file mode 100644
index bb528cfb4..000000000
--- a/algo/cryptonight-lite/cryptonight_lite_aesni.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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/>.
- */
-
-#ifndef __CRYPTONIGHT_LITE_AESNI_H__
-#define __CRYPTONIGHT_LITE_AESNI_H__
-
-#include <x86intrin.h>
-
-
-#define aes_genkey_sub(imm8) \
-    __m128i xout1 = _mm_aeskeygenassist_si128(*xout2, (imm8)); \
-    xout1  = _mm_shuffle_epi32(xout1, 0xFF); \
-    *xout0 = sl_xor(*xout0); \
-    *xout0 = _mm_xor_si128(*xout0, xout1); \
-    xout1  = _mm_aeskeygenassist_si128(*xout0, 0x00);\
-    xout1  = _mm_shuffle_epi32(xout1, 0xAA); \
-    *xout2 = sl_xor(*xout2); \
-    *xout2 = _mm_xor_si128(*xout2, xout1); \
-
-
-// This will shift and xor tmp1 into itself as 4 32-bit vals such as
-// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
-static inline __m128i sl_xor(__m128i tmp1)
-{
-    __m128i tmp4;
-    tmp4 = _mm_slli_si128(tmp1, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    tmp4 = _mm_slli_si128(tmp4, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    tmp4 = _mm_slli_si128(tmp4, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    return tmp1;
-}
-
-
-static inline void aes_genkey_sub1(__m128i* xout0, __m128i* xout2)
-{
-   aes_genkey_sub(0x1)
-}
-
-
-static inline void aes_genkey_sub2(__m128i* xout0, __m128i* xout2)
-{
-   aes_genkey_sub(0x2)
-}
-
-
-static inline void aes_genkey_sub4(__m128i* xout0, __m128i* xout2)
-{
-   aes_genkey_sub(0x4)
-}
-
-
-static inline void aes_genkey_sub8(__m128i* xout0, __m128i* xout2)
-{
-   aes_genkey_sub(0x8)
-}
-
-
-static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
-{
-    *x0 = _mm_aesenc_si128(*x0, key);
-    *x1 = _mm_aesenc_si128(*x1, key);
-    *x2 = _mm_aesenc_si128(*x2, key);
-    *x3 = _mm_aesenc_si128(*x3, key);
-    *x4 = _mm_aesenc_si128(*x4, key);
-    *x5 = _mm_aesenc_si128(*x5, key);
-    *x6 = _mm_aesenc_si128(*x6, key);
-    *x7 = _mm_aesenc_si128(*x7, key);
-}
-
-
-static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
-{
-    __m128i xout0 = _mm_load_si128(memory);
-    __m128i xout2 = _mm_load_si128(memory + 1);
-    *k0 = xout0;
-    *k1 = xout2;
-
-     aes_genkey_sub1(&xout0, &xout2);
-    *k2 = xout0;
-    *k3 = xout2;
-
-     aes_genkey_sub2(&xout0, &xout2);
-    *k4 = xout0;
-    *k5 = xout2;
-
-     aes_genkey_sub4(&xout0, &xout2);
-    *k6 = xout0;
-    *k7 = xout2;
-
-     aes_genkey_sub8(&xout0, &xout2);
-    *k8 = xout0;
-    *k9 = xout2;
-}
-
-
-static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
-{
-    // This is more than we have registers, compiler will assign 2 keys on the stack
-    __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
-    __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
-
-    aes_genkey(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
-
-    xin0 = _mm_load_si128(input + 4);
-    xin1 = _mm_load_si128(input + 5);
-    xin2 = _mm_load_si128(input + 6);
-    xin3 = _mm_load_si128(input + 7);
-    xin4 = _mm_load_si128(input + 8);
-    xin5 = _mm_load_si128(input + 9);
-    xin6 = _mm_load_si128(input + 10);
-    xin7 = _mm_load_si128(input + 11);
-
-    for (size_t i = 0; __builtin_expect(i < MEMORY_LITE / sizeof(__m128i), 1); i += 8) {
-        aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-
-        _mm_store_si128(output + i + 0, xin0);
-        _mm_store_si128(output + i + 1, xin1);
-        _mm_store_si128(output + i + 2, xin2);
-        _mm_store_si128(output + i + 3, xin3);
-        _mm_store_si128(output + i + 4, xin4);
-        _mm_store_si128(output + i + 5, xin5);
-        _mm_store_si128(output + i + 6, xin6);
-        _mm_store_si128(output + i + 7, xin7);
-    }
-}
-
-
-static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
-{
-    // This is more than we have registers, compiler will assign 2 keys on the stack
-    __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
-    __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
-
-    aes_genkey(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
-
-    xout0 = _mm_load_si128(output + 4);
-    xout1 = _mm_load_si128(output + 5);
-    xout2 = _mm_load_si128(output + 6);
-    xout3 = _mm_load_si128(output + 7);
-    xout4 = _mm_load_si128(output + 8);
-    xout5 = _mm_load_si128(output + 9);
-    xout6 = _mm_load_si128(output + 10);
-    xout7 = _mm_load_si128(output + 11);
-
-    for (size_t i = 0; __builtin_expect(i < MEMORY_LITE / sizeof(__m128i), 1); i += 8)
-    {
-        xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
-        xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
-        xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
-        xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
-        xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
-        xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
-        xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
-        xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
-
-        aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-    }
-
-    _mm_store_si128(output + 4, xout0);
-    _mm_store_si128(output + 5, xout1);
-    _mm_store_si128(output + 6, xout2);
-    _mm_store_si128(output + 7, xout3);
-    _mm_store_si128(output + 8, xout4);
-    _mm_store_si128(output + 9, xout5);
-    _mm_store_si128(output + 10, xout6);
-    _mm_store_si128(output + 11, xout7);
-}
-
-
-#if defined(__x86_64__)
-#   define EXTRACT64(X) _mm_cvtsi128_si64(X)
-
-static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
-{
-    unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
-    *hi = r >> 64;
-    return (uint64_t) r;
-}
-#elif defined(__i386__)
-#   define HI32(X) \
-    _mm_srli_si128((X), 4)
-
-
-#   define EXTRACT64(X) \
-    ((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
-    ((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
-
-static inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
-    // multiplier   = ab = a * 2^32 + b
-    // multiplicand = cd = c * 2^32 + d
-    // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
-    uint64_t a = multiplier >> 32;
-    uint64_t b = multiplier & 0xFFFFFFFF;
-    uint64_t c = multiplicand >> 32;
-    uint64_t d = multiplicand & 0xFFFFFFFF;
-
-    //uint64_t ac = a * c;
-    uint64_t ad = a * d;
-    //uint64_t bc = b * c;
-    uint64_t bd = b * d;
-
-    uint64_t adbc = ad + (b * c);
-    uint64_t adbc_carry = adbc < ad ? 1 : 0;
-
-    // multiplier * multiplicand = product_hi * 2^64 + product_lo
-    uint64_t product_lo = bd + (adbc << 32);
-    uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
-    *product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
-
-    return product_lo;
-}
-#endif
-
-
-#endif /* __CRYPTONIGHT_LITE_AESNI_H__ */
diff --git a/algo/cryptonight-lite/cryptonight_lite_av1_aesni.c b/algo/cryptonight-lite/cryptonight_lite_av1_aesni.c
deleted file mode 100644
index 80110fb2a..000000000
--- a/algo/cryptonight-lite/cryptonight_lite_av1_aesni.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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 <x86intrin.h>
-#include <string.h>
-
-#include "algo/cryptonight/cryptonight.h"
-#include "cryptonight_lite_aesni.h"
-#include "crypto/c_keccak.h"
-
-
-void cryptonight_lite_av1_aesni(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
-{
-    keccak((const uint8_t *) input, size, ctx->state0, 200);
-
-    cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory);
-
-    const uint8_t* l0 = ctx->memory;
-    uint64_t* h0 = (uint64_t*) ctx->state0;
-
-    uint64_t al0 = h0[0] ^ h0[4];
-    uint64_t ah0 = h0[1] ^ h0[5];
-    __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
-
-    uint64_t idx0 = h0[0] ^ h0[4];
-
-    for (size_t i = 0; __builtin_expect(i < 0x40000, 1); i++) {
-        __m128i cx;
-        cx = _mm_load_si128((__m128i *) &l0[idx0 & 0xFFFF0]);
-        cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
-
-        _mm_store_si128((__m128i *) &l0[idx0 & 0xFFFF0], _mm_xor_si128(bx0, cx));
-        idx0 = EXTRACT64(cx);
-        bx0 = cx;
-
-        uint64_t hi, lo, cl, ch;
-        cl = ((uint64_t*) &l0[idx0 & 0xFFFF0])[0];
-        ch = ((uint64_t*) &l0[idx0 & 0xFFFF0])[1];
-        lo = _umul128(idx0, cl, &hi);
-
-        al0 += hi;
-        ah0 += lo;
-
-        ((uint64_t*)&l0[idx0 & 0xFFFF0])[0] = al0;
-        ((uint64_t*)&l0[idx0 & 0xFFFF0])[1] = ah0;
-
-        ah0 ^= ch;
-        al0 ^= cl;
-        idx0 = al0;
-    }
-
-    cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0);
-
-    keccakf(h0, 24);
-    extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
-}
diff --git a/algo/cryptonight-lite/cryptonight_lite_av2_aesni_double.c b/algo/cryptonight-lite/cryptonight_lite_av2_aesni_double.c
deleted file mode 100644
index 055435c6a..000000000
--- a/algo/cryptonight-lite/cryptonight_lite_av2_aesni_double.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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 <x86intrin.h>
-#include <string.h>
-
-#include "algo/cryptonight/cryptonight.h"
-#include "cryptonight_lite_aesni.h"
-#include "crypto/c_keccak.h"
-
-
-void cryptonight_lite_av2_aesni_double(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);
-
-    const uint8_t* l0 = ctx->memory;
-    const uint8_t* l1 = ctx->memory + MEMORY_LITE;
-    uint64_t* h0 = (uint64_t*) ctx->state0;
-    uint64_t* h1 = (uint64_t*) ctx->state1;
-
-    cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0);
-    cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1);
-
-    uint64_t al0 = h0[0] ^ h0[4];
-    uint64_t al1 = h1[0] ^ h1[4];
-    uint64_t ah0 = h0[1] ^ h0[5];
-    uint64_t ah1 = h1[1] ^ h1[5];
-
-    __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
-    __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
-
-    uint64_t idx0 = h0[0] ^ h0[4];
-    uint64_t idx1 = h1[0] ^ h1[4];
-
-    for (size_t i = 0; __builtin_expect(i < 0x40000, 1); i++) {
-        __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & 0xFFFF0]);
-        __m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & 0xFFFF0]);
-
-        cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
-        cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
-
-        _mm_store_si128((__m128i *) &l0[idx0 & 0xFFFF0], _mm_xor_si128(bx0, cx0));
-        _mm_store_si128((__m128i *) &l1[idx1 & 0xFFFF0], _mm_xor_si128(bx1, cx1));
-
-        idx0 = EXTRACT64(cx0);
-        idx1 = EXTRACT64(cx1);
-
-        bx0 = cx0;
-        bx1 = cx1;
-
-        uint64_t hi, lo, cl, ch;
-        cl = ((uint64_t*) &l0[idx0 & 0xFFFF0])[0];
-        ch = ((uint64_t*) &l0[idx0 & 0xFFFF0])[1];
-        lo = _umul128(idx0, cl, &hi);
-
-        al0 += hi;
-        ah0 += lo;
-
-        ((uint64_t*) &l0[idx0 & 0xFFFF0])[0] = al0;
-        ((uint64_t*) &l0[idx0 & 0xFFFF0])[1] = ah0;
-
-        ah0 ^= ch;
-        al0 ^= cl;
-        idx0 = al0;
-
-        cl = ((uint64_t*) &l1[idx1 & 0xFFFF0])[0];
-        ch = ((uint64_t*) &l1[idx1 & 0xFFFF0])[1];
-        lo = _umul128(idx1, cl, &hi);
-
-        al1 += hi;
-        ah1 += lo;
-
-        ((uint64_t*) &l1[idx1 & 0xFFFF0])[0] = al1;
-        ((uint64_t*) &l1[idx1 & 0xFFFF0])[1] = ah1;
-
-        ah1 ^= ch;
-        al1 ^= cl;
-        idx1 = al1;
-    }
-
-    cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0);
-    cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1);
-
-    keccakf(h0, 24);
-    keccakf(h1, 24);
-
-    extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
-    extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, (char*) output + 32);
-}
diff --git a/algo/cryptonight-lite/cryptonight_lite_av3_softaes.c b/algo/cryptonight-lite/cryptonight_lite_av3_softaes.c
deleted file mode 100644
index 3dec6e335..000000000
--- a/algo/cryptonight-lite/cryptonight_lite_av3_softaes.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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 <x86intrin.h>
-#include <string.h>
-
-#include "algo/cryptonight/cryptonight.h"
-#include "cryptonight_lite_softaes.h"
-#include "crypto/c_keccak.h"
-
-
-void cryptonight_lite_av3_softaes(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
-{
-    keccak((const uint8_t *) input, size, ctx->state0, 200);
-
-    cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory);
-
-    const uint8_t* l0 = ctx->memory;
-    uint64_t* h0 = (uint64_t*) ctx->state0;
-
-    uint64_t al0 = h0[0] ^ h0[4];
-    uint64_t ah0 = h0[1] ^ h0[5];
-    __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
-
-    uint64_t idx0 = h0[0] ^ h0[4];
-
-    for (size_t i = 0; __builtin_expect(i < 0x40000, 1); i++) {
-        __m128i cx;
-        cx = _mm_load_si128((__m128i *)&l0[idx0 & 0xFFFF0]);
-        cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0));
-
-        _mm_store_si128((__m128i *)&l0[idx0 & 0xFFFF0], _mm_xor_si128(bx0, cx));
-        idx0 = EXTRACT64(cx);
-        bx0 = cx;
-
-        uint64_t hi, lo, cl, ch;
-        cl = ((uint64_t*)&l0[idx0 & 0xFFFF0])[0];
-        ch = ((uint64_t*)&l0[idx0 & 0xFFFF0])[1];
-        lo = _umul128(idx0, cl, &hi);
-
-        al0 += hi;
-        ah0 += lo;
-
-        ((uint64_t*)&l0[idx0 & 0xFFFF0])[0] = al0;
-        ((uint64_t*)&l0[idx0 & 0xFFFF0])[1] = ah0;
-
-        ah0 ^= ch;
-        al0 ^= cl;
-        idx0 = al0;
-    }
-
-    cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0);
-
-    keccakf(h0, 24);
-    extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
-}
diff --git a/algo/cryptonight-lite/cryptonight_lite_av4_softaes_double.c b/algo/cryptonight-lite/cryptonight_lite_av4_softaes_double.c
deleted file mode 100644
index 873b8cac0..000000000
--- a/algo/cryptonight-lite/cryptonight_lite_av4_softaes_double.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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 <x86intrin.h>
-#include <string.h>
-
-#include "algo/cryptonight/cryptonight.h"
-#include "cryptonight_lite_softaes.h"
-#include "crypto/c_keccak.h"
-
-
-void cryptonight_lite_av4_softaes_double(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);
-
-    const uint8_t* l0 = ctx->memory;
-    const uint8_t* l1 = ctx->memory + MEMORY_LITE;
-    uint64_t* h0 = (uint64_t*) ctx->state0;
-    uint64_t* h1 = (uint64_t*) ctx->state1;
-
-    cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0);
-    cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1);
-
-    uint64_t al0 = h0[0] ^ h0[4];
-    uint64_t al1 = h1[0] ^ h1[4];
-    uint64_t ah0 = h0[1] ^ h0[5];
-    uint64_t ah1 = h1[1] ^ h1[5];
-
-    __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
-    __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
-
-    uint64_t idx0 = h0[0] ^ h0[4];
-    uint64_t idx1 = h1[0] ^ h1[4];
-
-    for (size_t i = 0; __builtin_expect(i < 0x40000, 1); i++) {
-        __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & 0xFFFF0]);
-        __m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & 0xFFFF0]);
-
-        cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
-        cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
-
-        _mm_store_si128((__m128i *) &l0[idx0 & 0xFFFF0], _mm_xor_si128(bx0, cx0));
-        _mm_store_si128((__m128i *) &l1[idx1 & 0xFFFF0], _mm_xor_si128(bx1, cx1));
-
-        idx0 = EXTRACT64(cx0);
-        idx1 = EXTRACT64(cx1);
-
-        bx0 = cx0;
-        bx1 = cx1;
-
-        uint64_t hi, lo, cl, ch;
-        cl = ((uint64_t*) &l0[idx0 & 0xFFFF0])[0];
-        ch = ((uint64_t*) &l0[idx0 & 0xFFFF0])[1];
-        lo = _umul128(idx0, cl, &hi);
-
-        al0 += hi;
-        ah0 += lo;
-
-        ((uint64_t*) &l0[idx0 & 0xFFFF0])[0] = al0;
-        ((uint64_t*) &l0[idx0 & 0xFFFF0])[1] = ah0;
-
-        ah0 ^= ch;
-        al0 ^= cl;
-        idx0 = al0;
-
-        cl = ((uint64_t*) &l1[idx1 & 0xFFFF0])[0];
-        ch = ((uint64_t*) &l1[idx1 & 0xFFFF0])[1];
-        lo = _umul128(idx1, cl, &hi);
-
-        al1 += hi;
-        ah1 += lo;
-
-        ((uint64_t*) &l1[idx1 & 0xFFFF0])[0] = al1;
-        ((uint64_t*) &l1[idx1 & 0xFFFF0])[1] = ah1;
-
-        ah1 ^= ch;
-        al1 ^= cl;
-        idx1 = al1;
-    }
-
-    cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0);
-    cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1);
-
-    keccakf(h0, 24);
-    keccakf(h1, 24);
-
-    extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
-    extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, (char*) output + 32);
-}
diff --git a/algo/cryptonight-lite/cryptonight_lite_softaes.h b/algo/cryptonight-lite/cryptonight_lite_softaes.h
deleted file mode 100644
index bab3dcafe..000000000
--- a/algo/cryptonight-lite/cryptonight_lite_softaes.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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/>.
- */
-
-#ifndef __CRYPTONIGHT_LITE_SOFTAES_H__
-#define __CRYPTONIGHT_LITE_SOFTAES_H__
-
-#include <x86intrin.h>
-
-extern __m128i soft_aesenc(__m128i in, __m128i key);
-extern __m128i soft_aeskeygenassist(__m128i key, uint8_t rcon);
-
-
-// This will shift and xor tmp1 into itself as 4 32-bit vals such as
-// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
-static inline __m128i sl_xor(__m128i tmp1)
-{
-    __m128i tmp4;
-    tmp4 = _mm_slli_si128(tmp1, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    tmp4 = _mm_slli_si128(tmp4, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    tmp4 = _mm_slli_si128(tmp4, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    return tmp1;
-}
-
-
-static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
-{
-    __m128i xout1 = soft_aeskeygenassist(*xout2, rcon);
-    xout1  = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
-    *xout0 = sl_xor(*xout0);
-    *xout0 = _mm_xor_si128(*xout0, xout1);
-    xout1  = soft_aeskeygenassist(*xout0, 0x00);
-    xout1  = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
-    *xout2 = sl_xor(*xout2);
-    *xout2 = _mm_xor_si128(*xout2, xout1);
-}
-
-
-static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
-{
-    *x0 = soft_aesenc(*x0, key);
-    *x1 = soft_aesenc(*x1, key);
-    *x2 = soft_aesenc(*x2, key);
-    *x3 = soft_aesenc(*x3, key);
-    *x4 = soft_aesenc(*x4, key);
-    *x5 = soft_aesenc(*x5, key);
-    *x6 = soft_aesenc(*x6, key);
-    *x7 = soft_aesenc(*x7, key);
-}
-
-
-static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
-{
-    __m128i xout0 = _mm_load_si128(memory);
-    __m128i xout2 = _mm_load_si128(memory + 1);
-    *k0 = xout0;
-    *k1 = xout2;
-
-    aes_genkey_sub(&xout0, &xout2, 0x1);
-    *k2 = xout0;
-    *k3 = xout2;
-
-    aes_genkey_sub(&xout0, &xout2, 0x2);
-    *k4 = xout0;
-    *k5 = xout2;
-
-    aes_genkey_sub(&xout0, &xout2, 0x4);
-    *k6 = xout0;
-    *k7 = xout2;
-
-    aes_genkey_sub(&xout0, &xout2, 0x8);
-    *k8 = xout0;
-    *k9 = xout2;
-}
-
-
-static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
-{
-    // This is more than we have registers, compiler will assign 2 keys on the stack
-    __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
-    __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
-
-    aes_genkey(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
-
-    xin0 = _mm_load_si128(input + 4);
-    xin1 = _mm_load_si128(input + 5);
-    xin2 = _mm_load_si128(input + 6);
-    xin3 = _mm_load_si128(input + 7);
-    xin4 = _mm_load_si128(input + 8);
-    xin5 = _mm_load_si128(input + 9);
-    xin6 = _mm_load_si128(input + 10);
-    xin7 = _mm_load_si128(input + 11);
-
-    for (size_t i = 0; i < MEMORY_LITE / sizeof(__m128i); i += 8) {
-        aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-
-        _mm_store_si128(output + i + 0, xin0);
-        _mm_store_si128(output + i + 1, xin1);
-        _mm_store_si128(output + i + 2, xin2);
-        _mm_store_si128(output + i + 3, xin3);
-        _mm_store_si128(output + i + 4, xin4);
-        _mm_store_si128(output + i + 5, xin5);
-        _mm_store_si128(output + i + 6, xin6);
-        _mm_store_si128(output + i + 7, xin7);
-    }
-}
-
-
-static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
-{
-    // This is more than we have registers, compiler will assign 2 keys on the stack
-    __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
-    __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
-
-    aes_genkey(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
-
-    xout0 = _mm_load_si128(output + 4);
-    xout1 = _mm_load_si128(output + 5);
-    xout2 = _mm_load_si128(output + 6);
-    xout3 = _mm_load_si128(output + 7);
-    xout4 = _mm_load_si128(output + 8);
-    xout5 = _mm_load_si128(output + 9);
-    xout6 = _mm_load_si128(output + 10);
-    xout7 = _mm_load_si128(output + 11);
-
-    for (size_t i = 0; __builtin_expect(i < MEMORY_LITE / sizeof(__m128i), 1); i += 8)
-    {
-        xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
-        xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
-        xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
-        xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
-        xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
-        xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
-        xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
-        xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
-
-        aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-    }
-
-    _mm_store_si128(output + 4, xout0);
-    _mm_store_si128(output + 5, xout1);
-    _mm_store_si128(output + 6, xout2);
-    _mm_store_si128(output + 7, xout3);
-    _mm_store_si128(output + 8, xout4);
-    _mm_store_si128(output + 9, xout5);
-    _mm_store_si128(output + 10, xout6);
-    _mm_store_si128(output + 11, xout7);
-}
-
-
-#if defined(__x86_64__)
-#   define EXTRACT64(X) _mm_cvtsi128_si64(X)
-
-static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
-{
-    unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
-    *hi = r >> 64;
-    return (uint64_t) r;
-}
-#elif defined(__i386__)
-#   define HI32(X) \
-    _mm_srli_si128((X), 4)
-
-
-#   define EXTRACT64(X) \
-    ((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
-    ((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
-
-static inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
-    // multiplier   = ab = a * 2^32 + b
-    // multiplicand = cd = c * 2^32 + d
-    // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
-    uint64_t a = multiplier >> 32;
-    uint64_t b = multiplier & 0xFFFFFFFF;
-    uint64_t c = multiplicand >> 32;
-    uint64_t d = multiplicand & 0xFFFFFFFF;
-
-    //uint64_t ac = a * c;
-    uint64_t ad = a * d;
-    //uint64_t bc = b * c;
-    uint64_t bd = b * d;
-
-    uint64_t adbc = ad + (b * c);
-    uint64_t adbc_carry = adbc < ad ? 1 : 0;
-
-    // multiplier * multiplicand = product_hi * 2^64 + product_lo
-    uint64_t product_lo = bd + (adbc << 32);
-    uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
-    *product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
-
-    return product_lo;
-}
-#endif
-
-
-#endif /* __CRYPTONIGHT_LITE_SOFTAES_H__ */
diff --git a/algo/cryptonight/cryptonight.c b/algo/cryptonight/cryptonight.c
deleted file mode 100644
index 730187280..000000000
--- a/algo/cryptonight/cryptonight.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <string.h>
-#include <mm_malloc.h>
-
-#ifndef BUILD_TEST
-#   include "xmrig.h"
-#endif
-
-#include "crypto/c_groestl.h"
-#include "crypto/c_blake256.h"
-#include "crypto/c_jh.h"
-#include "crypto/c_skein.h"
-#include "cryptonight.h"
-#include "options.h"
-
-
-const static char test_input[152] = {
-    0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19,
-    0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9,
-    0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F,
-    0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46,
-    0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02,
-    0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
-    0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
-    0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
-    0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
-    0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01
-};
-
-
-const static char test_output0[64] = {
-    0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66,
-    0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F,
-    0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
-    0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00
-};
-
-
-void cryptonight_av1_aesni(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-void cryptonight_av2_aesni_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-void cryptonight_av3_softaes(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-void cryptonight_av4_softaes_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-
-#ifndef XMRIG_NO_AEON
-const static char test_output1[64] = {
-    0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE,
-    0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD,
-    0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
-    0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88,
-};
-
-void cryptonight_lite_av1_aesni(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-void cryptonight_lite_av2_aesni_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-void cryptonight_lite_av3_softaes(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-void cryptonight_lite_av4_softaes_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
-#endif
-
-void (*cryptonight_hash_ctx)(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx) = NULL;
-
-
-static bool self_test() {
-    if (cryptonight_hash_ctx == NULL) {
-        return false;
-    }
-
-    char output[64];
-
-    struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) _mm_malloc(sizeof(struct cryptonight_ctx), 16);
-    ctx->memory = (uint8_t *) _mm_malloc(MEMORY * 2, 16);
-
-    cryptonight_hash_ctx(test_input, 76, output, ctx);
-
-    _mm_free(ctx->memory);
-    _mm_free(ctx);
-
-#   ifndef XMRIG_NO_AEON
-    if (opt_algo == ALGO_CRYPTONIGHT_LITE) {
-        return memcmp(output, test_output1, (opt_double_hash ? 64 : 32)) == 0;
-    }
-#   endif
-
-    return memcmp(output, test_output0, (opt_double_hash ? 64 : 32)) == 0;
-}
-
-
-#ifndef XMRIG_NO_AEON
-bool cryptonight_lite_init(int variant) {
-    switch (variant) {
-        case AEON_AV1_AESNI:
-            cryptonight_hash_ctx = cryptonight_lite_av1_aesni;
-            break;
-
-        case AEON_AV2_AESNI_DOUBLE:
-            opt_double_hash = true;
-            cryptonight_hash_ctx = cryptonight_lite_av2_aesni_double;
-            break;
-
-        case AEON_AV3_SOFT_AES:
-            cryptonight_hash_ctx = cryptonight_lite_av3_softaes;
-            break;
-
-        case AEON_AV4_SOFT_AES_DOUBLE:
-            opt_double_hash = true;
-            cryptonight_hash_ctx = cryptonight_lite_av4_softaes_double;
-            break;
-
-        default:
-            break;
-    }
-
-    return self_test();
-}
-#endif
-
-
-bool cryptonight_init(int variant)
-{
-#   ifndef XMRIG_NO_AEON
-    if (opt_algo == ALGO_CRYPTONIGHT_LITE) {
-        return cryptonight_lite_init(variant);
-    }
-#   endif
-
-    switch (variant) {
-        case XMR_AV1_AESNI:
-            cryptonight_hash_ctx = cryptonight_av1_aesni;
-            break;
-
-        case XMR_AV2_AESNI_DOUBLE:
-            opt_double_hash = true;
-            cryptonight_hash_ctx = cryptonight_av2_aesni_double;
-            break;
-
-        case XMR_AV3_SOFT_AES:
-            cryptonight_hash_ctx = cryptonight_av3_softaes;
-            break;
-
-        case XMR_AV4_SOFT_AES_DOUBLE:
-            opt_double_hash = true;
-            cryptonight_hash_ctx = cryptonight_av4_softaes_double;
-            break;
-
-        default:
-            break;
-    }
-
-    return self_test();
-}
-
-
-static inline void do_blake_hash(const void* input, size_t len, char* output) {
-    blake256_hash((uint8_t*)output, input, len);
-}
-
-
-static inline void do_groestl_hash(const void* input, size_t len, char* output) {
-    groestl(input, len * 8, (uint8_t*)output);
-}
-
-
-static inline void do_jh_hash(const void* input, size_t len, char* output) {
-    jh_hash(32 * 8, input, 8 * len, (uint8_t*)output);
-}
-
-
-static inline void do_skein_hash(const void* input, size_t len, char* output) {
-    skein_hash(8 * 32, input, 8 * len, (uint8_t*)output);
-}
-
-
-void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
-
-
-#ifndef BUILD_TEST
-int scanhash_cryptonight(int thr_id, uint32_t *hash, uint32_t *restrict blob, size_t blob_size, uint32_t target, uint32_t max_nonce, unsigned long *restrict hashes_done, struct cryptonight_ctx *restrict ctx) {
-    uint32_t *nonceptr = (uint32_t*) (((char*) blob) + 39);
-
-    do {
-        cryptonight_hash_ctx(blob, blob_size, hash, ctx);
-        (*hashes_done)++;
-
-        if (unlikely(hash[7] < target)) {
-            return 1;
-        }
-
-        (*nonceptr)++;
-    } while (likely(((*nonceptr) < max_nonce && !work_restart[thr_id].restart)));
-
-    return 0;
-}
-
-
-int scanhash_cryptonight_double(int thr_id, uint32_t *hash, uint8_t *restrict blob, size_t blob_size, uint32_t target, uint32_t max_nonce, unsigned long *restrict hashes_done, struct cryptonight_ctx *restrict ctx) {
-    int rc = 0;
-    uint32_t *nonceptr0 = (uint32_t*) (((char*) blob) + 39);
-    uint32_t *nonceptr1 = (uint32_t*) (((char*) blob) + 39 + blob_size);
-
-    do {
-        cryptonight_hash_ctx(blob, blob_size, hash, ctx);
-        (*hashes_done) += 2;
-
-        if (unlikely(hash[7] < target)) {
-            return rc |= 1;
-        }
-
-        if (unlikely(hash[15] < target)) {
-            return rc |= 2;
-        }
-
-        if (rc) {
-            break;
-        }
-
-        (*nonceptr0)++;
-        (*nonceptr1)++;
-    } while (likely(((*nonceptr0) < max_nonce && !work_restart[thr_id].restart)));
-
-    return rc;
-}
-#endif
diff --git a/algo/cryptonight/cryptonight.h b/algo/cryptonight/cryptonight.h
deleted file mode 100644
index 0b0170735..000000000
--- a/algo/cryptonight/cryptonight.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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/>.
- */
-
-#ifndef __CRYPTONIGHT_H__
-#define __CRYPTONIGHT_H__
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#define MEMORY      2097152 /* 2 MiB */
-#define MEMORY_LITE 1048576 /* 1 MiB */
-
-struct cryptonight_ctx {
-    uint8_t state0[200] __attribute__((aligned(16)));
-    uint8_t state1[200] __attribute__((aligned(16)));
-    uint8_t* memory     __attribute__((aligned(16)));
-};
-
-
-extern void (* const extra_hashes[4])(const void *, size_t, char *);
-
-bool cryptonight_init(int variant);
-int scanhash_cryptonight(int thr_id, uint32_t *hash, uint32_t *restrict blob, size_t blob_size, uint32_t target, uint32_t max_nonce, unsigned long *restrict hashes_done, struct cryptonight_ctx *restrict ctx);
-int scanhash_cryptonight_double(int thr_id, uint32_t *hash, uint8_t *restrict blob, size_t blob_size, uint32_t target, uint32_t max_nonce, unsigned long *restrict hashes_done, struct cryptonight_ctx *restrict ctx);
-
-#endif /* __CRYPTONIGHT_H__ */
diff --git a/algo/cryptonight/cryptonight_aesni.h b/algo/cryptonight/cryptonight_aesni.h
deleted file mode 100644
index e4d6d42f1..000000000
--- a/algo/cryptonight/cryptonight_aesni.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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/>.
- */
-
-#ifndef __CRYPTONIGHT_AESNI_H__
-#define __CRYPTONIGHT_AESNI_H__
-
-#include <x86intrin.h>
-
-
-#define aes_genkey_sub(imm8) \
-    __m128i xout1 = _mm_aeskeygenassist_si128(*xout2, (imm8)); \
-    xout1  = _mm_shuffle_epi32(xout1, 0xFF); \
-    *xout0 = sl_xor(*xout0); \
-    *xout0 = _mm_xor_si128(*xout0, xout1); \
-    xout1  = _mm_aeskeygenassist_si128(*xout0, 0x00);\
-    xout1  = _mm_shuffle_epi32(xout1, 0xAA); \
-    *xout2 = sl_xor(*xout2); \
-    *xout2 = _mm_xor_si128(*xout2, xout1); \
-
-
-// This will shift and xor tmp1 into itself as 4 32-bit vals such as
-// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
-static inline __m128i sl_xor(__m128i tmp1)
-{
-    __m128i tmp4;
-    tmp4 = _mm_slli_si128(tmp1, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    tmp4 = _mm_slli_si128(tmp4, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    tmp4 = _mm_slli_si128(tmp4, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    return tmp1;
-}
-
-
-static inline void aes_genkey_sub1(__m128i* xout0, __m128i* xout2)
-{
-   aes_genkey_sub(0x1)
-}
-
-
-static inline void aes_genkey_sub2(__m128i* xout0, __m128i* xout2)
-{
-   aes_genkey_sub(0x2)
-}
-
-
-static inline void aes_genkey_sub4(__m128i* xout0, __m128i* xout2)
-{
-   aes_genkey_sub(0x4)
-}
-
-
-static inline void aes_genkey_sub8(__m128i* xout0, __m128i* xout2)
-{
-   aes_genkey_sub(0x8)
-}
-
-
-static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
-{
-    *x0 = _mm_aesenc_si128(*x0, key);
-    *x1 = _mm_aesenc_si128(*x1, key);
-    *x2 = _mm_aesenc_si128(*x2, key);
-    *x3 = _mm_aesenc_si128(*x3, key);
-    *x4 = _mm_aesenc_si128(*x4, key);
-    *x5 = _mm_aesenc_si128(*x5, key);
-    *x6 = _mm_aesenc_si128(*x6, key);
-    *x7 = _mm_aesenc_si128(*x7, key);
-}
-
-
-static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
-{
-    __m128i xout0 = _mm_load_si128(memory);
-    __m128i xout2 = _mm_load_si128(memory + 1);
-    *k0 = xout0;
-    *k1 = xout2;
-
-     aes_genkey_sub1(&xout0, &xout2);
-    *k2 = xout0;
-    *k3 = xout2;
-
-     aes_genkey_sub2(&xout0, &xout2);
-    *k4 = xout0;
-    *k5 = xout2;
-
-     aes_genkey_sub4(&xout0, &xout2);
-    *k6 = xout0;
-    *k7 = xout2;
-
-     aes_genkey_sub8(&xout0, &xout2);
-    *k8 = xout0;
-    *k9 = xout2;
-}
-
-
-static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
-{
-    // This is more than we have registers, compiler will assign 2 keys on the stack
-    __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
-    __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
-
-    aes_genkey(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
-
-    xin0 = _mm_load_si128(input + 4);
-    xin1 = _mm_load_si128(input + 5);
-    xin2 = _mm_load_si128(input + 6);
-    xin3 = _mm_load_si128(input + 7);
-    xin4 = _mm_load_si128(input + 8);
-    xin5 = _mm_load_si128(input + 9);
-    xin6 = _mm_load_si128(input + 10);
-    xin7 = _mm_load_si128(input + 11);
-
-    for (size_t i = 0; __builtin_expect(i < MEMORY / sizeof(__m128i), 1); i += 8) {
-        aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-
-        _mm_store_si128(output + i + 0, xin0);
-        _mm_store_si128(output + i + 1, xin1);
-        _mm_store_si128(output + i + 2, xin2);
-        _mm_store_si128(output + i + 3, xin3);
-        _mm_store_si128(output + i + 4, xin4);
-        _mm_store_si128(output + i + 5, xin5);
-        _mm_store_si128(output + i + 6, xin6);
-        _mm_store_si128(output + i + 7, xin7);
-    }
-}
-
-
-static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
-{
-    // This is more than we have registers, compiler will assign 2 keys on the stack
-    __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
-    __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
-
-    aes_genkey(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
-
-    xout0 = _mm_load_si128(output + 4);
-    xout1 = _mm_load_si128(output + 5);
-    xout2 = _mm_load_si128(output + 6);
-    xout3 = _mm_load_si128(output + 7);
-    xout4 = _mm_load_si128(output + 8);
-    xout5 = _mm_load_si128(output + 9);
-    xout6 = _mm_load_si128(output + 10);
-    xout7 = _mm_load_si128(output + 11);
-
-    for (size_t i = 0; __builtin_expect(i < MEMORY / sizeof(__m128i), 1); i += 8)
-    {
-        xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
-        xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
-        xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
-        xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
-        xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
-        xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
-        xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
-        xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
-
-        aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-    }
-
-    _mm_store_si128(output + 4, xout0);
-    _mm_store_si128(output + 5, xout1);
-    _mm_store_si128(output + 6, xout2);
-    _mm_store_si128(output + 7, xout3);
-    _mm_store_si128(output + 8, xout4);
-    _mm_store_si128(output + 9, xout5);
-    _mm_store_si128(output + 10, xout6);
-    _mm_store_si128(output + 11, xout7);
-}
-
-
-#if defined(__x86_64__)
-#   define EXTRACT64(X) _mm_cvtsi128_si64(X)
-
-static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
-{
-    unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
-    *hi = r >> 64;
-    return (uint64_t) r;
-}
-#elif defined(__i386__)
-#   define HI32(X) \
-    _mm_srli_si128((X), 4)
-
-
-#   define EXTRACT64(X) \
-    ((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
-    ((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
-
-static inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
-    // multiplier   = ab = a * 2^32 + b
-    // multiplicand = cd = c * 2^32 + d
-    // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
-    uint64_t a = multiplier >> 32;
-    uint64_t b = multiplier & 0xFFFFFFFF;
-    uint64_t c = multiplicand >> 32;
-    uint64_t d = multiplicand & 0xFFFFFFFF;
-
-    //uint64_t ac = a * c;
-    uint64_t ad = a * d;
-    //uint64_t bc = b * c;
-    uint64_t bd = b * d;
-
-    uint64_t adbc = ad + (b * c);
-    uint64_t adbc_carry = adbc < ad ? 1 : 0;
-
-    // multiplier * multiplicand = product_hi * 2^64 + product_lo
-    uint64_t product_lo = bd + (adbc << 32);
-    uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
-    *product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
-
-    return product_lo;
-}
-#endif
-
-
-#endif /* __CRYPTONIGHT_AESNI_H__ */
diff --git a/algo/cryptonight/cryptonight_av1_aesni.c b/algo/cryptonight/cryptonight_av1_aesni.c
deleted file mode 100644
index 3f30544e6..000000000
--- a/algo/cryptonight/cryptonight_av1_aesni.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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 <x86intrin.h>
-#include <string.h>
-
-#include "cryptonight.h"
-#include "cryptonight_aesni.h"
-#include "crypto/c_keccak.h"
-
-
-void cryptonight_av1_aesni(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
-{
-    keccak((const uint8_t *) input, size, ctx->state0, 200);
-
-    cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory);
-
-    const uint8_t* l0 = ctx->memory;
-    uint64_t* h0 = (uint64_t*) ctx->state0;
-
-    uint64_t al0 = h0[0] ^ h0[4];
-    uint64_t ah0 = h0[1] ^ h0[5];
-    __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
-
-    uint64_t idx0 = h0[0] ^ h0[4];
-
-    for (size_t i = 0; __builtin_expect(i < 0x80000, 1); i++) {
-        __m128i cx;
-        cx = _mm_load_si128((__m128i *) &l0[idx0 & 0x1FFFF0]);
-        cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
-
-        _mm_store_si128((__m128i *) &l0[idx0 & 0x1FFFF0], _mm_xor_si128(bx0, cx));
-        idx0 = EXTRACT64(cx);
-        bx0 = cx;
-
-        uint64_t hi, lo, cl, ch;
-        cl = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[0];
-        ch = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[1];
-        lo = _umul128(idx0, cl, &hi);
-
-        al0 += hi;
-        ah0 += lo;
-
-        ((uint64_t*)&l0[idx0 & 0x1FFFF0])[0] = al0;
-        ((uint64_t*)&l0[idx0 & 0x1FFFF0])[1] = ah0;
-
-        ah0 ^= ch;
-        al0 ^= cl;
-        idx0 = al0;
-    }
-
-    cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0);
-
-    keccakf(h0, 24);
-    extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
-}
diff --git a/algo/cryptonight/cryptonight_av2_aesni_double.c b/algo/cryptonight/cryptonight_av2_aesni_double.c
deleted file mode 100644
index 779b9bc3f..000000000
--- a/algo/cryptonight/cryptonight_av2_aesni_double.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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 <x86intrin.h>
-#include <string.h>
-
-#include "cryptonight.h"
-#include "cryptonight_aesni.h"
-#include "crypto/c_keccak.h"
-
-
-void cryptonight_av2_aesni_double(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);
-
-    const uint8_t* l0 = ctx->memory;
-    const uint8_t* l1 = ctx->memory + MEMORY;
-    uint64_t* h0 = (uint64_t*) ctx->state0;
-    uint64_t* h1 = (uint64_t*) ctx->state1;
-
-    cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0);
-    cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1);
-
-    uint64_t al0 = h0[0] ^ h0[4];
-    uint64_t al1 = h1[0] ^ h1[4];
-    uint64_t ah0 = h0[1] ^ h0[5];
-    uint64_t ah1 = h1[1] ^ h1[5];
-
-    __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
-    __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
-
-    uint64_t idx0 = h0[0] ^ h0[4];
-    uint64_t idx1 = h1[0] ^ h1[4];
-
-    for (size_t i = 0; __builtin_expect(i < 0x80000, 1); i++) {
-        __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & 0x1FFFF0]);
-        __m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & 0x1FFFF0]);
-
-        cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
-        cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
-
-        _mm_store_si128((__m128i *) &l0[idx0 & 0x1FFFF0], _mm_xor_si128(bx0, cx0));
-        _mm_store_si128((__m128i *) &l1[idx1 & 0x1FFFF0], _mm_xor_si128(bx1, cx1));
-
-        idx0 = EXTRACT64(cx0);
-        idx1 = EXTRACT64(cx1);
-
-        bx0 = cx0;
-        bx1 = cx1;
-
-        uint64_t hi, lo, cl, ch;
-        cl = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[0];
-        ch = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[1];
-        lo = _umul128(idx0, cl, &hi);
-
-        al0 += hi;
-        ah0 += lo;
-
-        ((uint64_t*) &l0[idx0 & 0x1FFFF0])[0] = al0;
-        ((uint64_t*) &l0[idx0 & 0x1FFFF0])[1] = ah0;
-
-        ah0 ^= ch;
-        al0 ^= cl;
-        idx0 = al0;
-
-        cl = ((uint64_t*) &l1[idx1 & 0x1FFFF0])[0];
-        ch = ((uint64_t*) &l1[idx1 & 0x1FFFF0])[1];
-        lo = _umul128(idx1, cl, &hi);
-
-        al1 += hi;
-        ah1 += lo;
-
-        ((uint64_t*) &l1[idx1 & 0x1FFFF0])[0] = al1;
-        ((uint64_t*) &l1[idx1 & 0x1FFFF0])[1] = ah1;
-
-        ah1 ^= ch;
-        al1 ^= cl;
-        idx1 = al1;
-    }
-
-    cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0);
-    cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1);
-
-    keccakf(h0, 24);
-    keccakf(h1, 24);
-
-    extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
-    extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, (char*) output + 32);
-}
diff --git a/algo/cryptonight/cryptonight_av3_softaes.c b/algo/cryptonight/cryptonight_av3_softaes.c
deleted file mode 100644
index 22be894d8..000000000
--- a/algo/cryptonight/cryptonight_av3_softaes.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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 <x86intrin.h>
-#include <string.h>
-
-#include "cryptonight.h"
-#include "cryptonight_softaes.h"
-#include "crypto/c_keccak.h"
-
-
-void cryptonight_av3_softaes(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
-{
-    keccak((const uint8_t *) input, size, ctx->state0, 200);
-
-    cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory);
-
-    const uint8_t* l0 = ctx->memory;
-    uint64_t* h0 = (uint64_t*) ctx->state0;
-
-    uint64_t al0 = h0[0] ^ h0[4];
-    uint64_t ah0 = h0[1] ^ h0[5];
-    __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
-
-    uint64_t idx0 = h0[0] ^ h0[4];
-
-    for (size_t i = 0; __builtin_expect(i < 0x80000, 1); i++) {
-        __m128i cx;
-        cx = _mm_load_si128((__m128i *)&l0[idx0 & 0x1FFFF0]);
-        cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0));
-
-        _mm_store_si128((__m128i *)&l0[idx0 & 0x1FFFF0], _mm_xor_si128(bx0, cx));
-        idx0 = EXTRACT64(cx);
-        bx0 = cx;
-
-        uint64_t hi, lo, cl, ch;
-        cl = ((uint64_t*)&l0[idx0 & 0x1FFFF0])[0];
-        ch = ((uint64_t*)&l0[idx0 & 0x1FFFF0])[1];
-        lo = _umul128(idx0, cl, &hi);
-
-        al0 += hi;
-        ah0 += lo;
-
-        ((uint64_t*)&l0[idx0 & 0x1FFFF0])[0] = al0;
-        ((uint64_t*)&l0[idx0 & 0x1FFFF0])[1] = ah0;
-
-        ah0 ^= ch;
-        al0 ^= cl;
-        idx0 = al0;
-    }
-
-    cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0);
-
-    keccakf(h0, 24);
-    extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
-}
diff --git a/algo/cryptonight/cryptonight_av4_softaes_double.c b/algo/cryptonight/cryptonight_av4_softaes_double.c
deleted file mode 100644
index afd4bebe1..000000000
--- a/algo/cryptonight/cryptonight_av4_softaes_double.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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 <x86intrin.h>
-#include <string.h>
-
-#include "cryptonight.h"
-#include "cryptonight_softaes.h"
-#include "crypto/c_keccak.h"
-
-
-void cryptonight_av4_softaes_double(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);
-
-    const uint8_t* l0 = ctx->memory;
-    const uint8_t* l1 = ctx->memory + MEMORY;
-    uint64_t* h0 = (uint64_t*) ctx->state0;
-    uint64_t* h1 = (uint64_t*) ctx->state1;
-
-    cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0);
-    cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1);
-
-    uint64_t al0 = h0[0] ^ h0[4];
-    uint64_t al1 = h1[0] ^ h1[4];
-    uint64_t ah0 = h0[1] ^ h0[5];
-    uint64_t ah1 = h1[1] ^ h1[5];
-
-    __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
-    __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
-
-    uint64_t idx0 = h0[0] ^ h0[4];
-    uint64_t idx1 = h1[0] ^ h1[4];
-
-    for (size_t i = 0; __builtin_expect(i < 0x80000, 1); i++) {
-        __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & 0x1FFFF0]);
-        __m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & 0x1FFFF0]);
-
-        cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
-        cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
-
-        _mm_store_si128((__m128i *) &l0[idx0 & 0x1FFFF0], _mm_xor_si128(bx0, cx0));
-        _mm_store_si128((__m128i *) &l1[idx1 & 0x1FFFF0], _mm_xor_si128(bx1, cx1));
-
-        idx0 = EXTRACT64(cx0);
-        idx1 = EXTRACT64(cx1);
-
-        bx0 = cx0;
-        bx1 = cx1;
-
-        uint64_t hi, lo, cl, ch;
-        cl = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[0];
-        ch = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[1];
-        lo = _umul128(idx0, cl, &hi);
-
-        al0 += hi;
-        ah0 += lo;
-
-        ((uint64_t*) &l0[idx0 & 0x1FFFF0])[0] = al0;
-        ((uint64_t*) &l0[idx0 & 0x1FFFF0])[1] = ah0;
-
-        ah0 ^= ch;
-        al0 ^= cl;
-        idx0 = al0;
-
-        cl = ((uint64_t*) &l1[idx1 & 0x1FFFF0])[0];
-        ch = ((uint64_t*) &l1[idx1 & 0x1FFFF0])[1];
-        lo = _umul128(idx1, cl, &hi);
-
-        al1 += hi;
-        ah1 += lo;
-
-        ((uint64_t*) &l1[idx1 & 0x1FFFF0])[0] = al1;
-        ((uint64_t*) &l1[idx1 & 0x1FFFF0])[1] = ah1;
-
-        ah1 ^= ch;
-        al1 ^= cl;
-        idx1 = al1;
-    }
-
-    cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0);
-    cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1);
-
-    keccakf(h0, 24);
-    keccakf(h1, 24);
-
-    extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
-    extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, (char*) output + 32);
-}
diff --git a/algo/cryptonight/cryptonight_softaes.h b/algo/cryptonight/cryptonight_softaes.h
deleted file mode 100644
index f12ab8c67..000000000
--- a/algo/cryptonight/cryptonight_softaes.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 2017      fireice-uk  <https://github.com/fireice-uk>
- * 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/>.
- */
-
-#ifndef __CRYPTONIGHT_SOFTAES_H__
-#define __CRYPTONIGHT_SOFTAES_H__
-
-#include <x86intrin.h>
-
-extern __m128i soft_aesenc(__m128i in, __m128i key);
-extern __m128i soft_aeskeygenassist(__m128i key, uint8_t rcon);
-
-
-// This will shift and xor tmp1 into itself as 4 32-bit vals such as
-// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
-static inline __m128i sl_xor(__m128i tmp1)
-{
-    __m128i tmp4;
-    tmp4 = _mm_slli_si128(tmp1, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    tmp4 = _mm_slli_si128(tmp4, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    tmp4 = _mm_slli_si128(tmp4, 0x04);
-    tmp1 = _mm_xor_si128(tmp1, tmp4);
-    return tmp1;
-}
-
-
-static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
-{
-    __m128i xout1 = soft_aeskeygenassist(*xout2, rcon);
-    xout1  = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
-    *xout0 = sl_xor(*xout0);
-    *xout0 = _mm_xor_si128(*xout0, xout1);
-    xout1  = soft_aeskeygenassist(*xout0, 0x00);
-    xout1  = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
-    *xout2 = sl_xor(*xout2);
-    *xout2 = _mm_xor_si128(*xout2, xout1);
-}
-
-
-static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
-{
-    *x0 = soft_aesenc(*x0, key);
-    *x1 = soft_aesenc(*x1, key);
-    *x2 = soft_aesenc(*x2, key);
-    *x3 = soft_aesenc(*x3, key);
-    *x4 = soft_aesenc(*x4, key);
-    *x5 = soft_aesenc(*x5, key);
-    *x6 = soft_aesenc(*x6, key);
-    *x7 = soft_aesenc(*x7, key);
-}
-
-
-static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
-{
-    __m128i xout0 = _mm_load_si128(memory);
-    __m128i xout2 = _mm_load_si128(memory + 1);
-    *k0 = xout0;
-    *k1 = xout2;
-
-    aes_genkey_sub(&xout0, &xout2, 0x1);
-    *k2 = xout0;
-    *k3 = xout2;
-
-    aes_genkey_sub(&xout0, &xout2, 0x2);
-    *k4 = xout0;
-    *k5 = xout2;
-
-    aes_genkey_sub(&xout0, &xout2, 0x4);
-    *k6 = xout0;
-    *k7 = xout2;
-
-    aes_genkey_sub(&xout0, &xout2, 0x8);
-    *k8 = xout0;
-    *k9 = xout2;
-}
-
-
-static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
-{
-    // This is more than we have registers, compiler will assign 2 keys on the stack
-    __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
-    __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
-
-    aes_genkey(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
-
-    xin0 = _mm_load_si128(input + 4);
-    xin1 = _mm_load_si128(input + 5);
-    xin2 = _mm_load_si128(input + 6);
-    xin3 = _mm_load_si128(input + 7);
-    xin4 = _mm_load_si128(input + 8);
-    xin5 = _mm_load_si128(input + 9);
-    xin6 = _mm_load_si128(input + 10);
-    xin7 = _mm_load_si128(input + 11);
-
-    for (size_t i = 0; i < MEMORY / sizeof(__m128i); i += 8) {
-        aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-        aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
-
-        _mm_store_si128(output + i + 0, xin0);
-        _mm_store_si128(output + i + 1, xin1);
-        _mm_store_si128(output + i + 2, xin2);
-        _mm_store_si128(output + i + 3, xin3);
-        _mm_store_si128(output + i + 4, xin4);
-        _mm_store_si128(output + i + 5, xin5);
-        _mm_store_si128(output + i + 6, xin6);
-        _mm_store_si128(output + i + 7, xin7);
-    }
-}
-
-
-static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
-{
-    // This is more than we have registers, compiler will assign 2 keys on the stack
-    __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
-    __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
-
-    aes_genkey(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
-
-    xout0 = _mm_load_si128(output + 4);
-    xout1 = _mm_load_si128(output + 5);
-    xout2 = _mm_load_si128(output + 6);
-    xout3 = _mm_load_si128(output + 7);
-    xout4 = _mm_load_si128(output + 8);
-    xout5 = _mm_load_si128(output + 9);
-    xout6 = _mm_load_si128(output + 10);
-    xout7 = _mm_load_si128(output + 11);
-
-    for (size_t i = 0; __builtin_expect(i < MEMORY / sizeof(__m128i), 1); i += 8)
-    {
-        xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
-        xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
-        xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
-        xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
-        xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
-        xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
-        xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
-        xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
-
-        aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-        aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
-    }
-
-    _mm_store_si128(output + 4, xout0);
-    _mm_store_si128(output + 5, xout1);
-    _mm_store_si128(output + 6, xout2);
-    _mm_store_si128(output + 7, xout3);
-    _mm_store_si128(output + 8, xout4);
-    _mm_store_si128(output + 9, xout5);
-    _mm_store_si128(output + 10, xout6);
-    _mm_store_si128(output + 11, xout7);
-}
-
-
-#if defined(__x86_64__)
-#   define EXTRACT64(X) _mm_cvtsi128_si64(X)
-
-static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
-{
-    unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
-    *hi = r >> 64;
-    return (uint64_t) r;
-}
-#elif defined(__i386__)
-#   define HI32(X) \
-    _mm_srli_si128((X), 4)
-
-
-#   define EXTRACT64(X) \
-    ((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
-    ((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
-
-inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
-    // multiplier   = ab = a * 2^32 + b
-    // multiplicand = cd = c * 2^32 + d
-    // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
-    uint64_t a = multiplier >> 32;
-    uint64_t b = multiplier & 0xFFFFFFFF;
-    uint64_t c = multiplicand >> 32;
-    uint64_t d = multiplicand & 0xFFFFFFFF;
-
-    //uint64_t ac = a * c;
-    uint64_t ad = a * d;
-    //uint64_t bc = b * c;
-    uint64_t bd = b * d;
-
-    uint64_t adbc = ad + (b * c);
-    uint64_t adbc_carry = adbc < ad ? 1 : 0;
-
-    // multiplier * multiplicand = product_hi * 2^64 + product_lo
-    uint64_t product_lo = bd + (adbc << 32);
-    uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
-    *product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
-
-    return product_lo;
-}
-#endif
-
-
-#endif /* __CRYPTONIGHT_SOFTAES_H__ */
diff --git a/crypto/hash.c b/crypto/hash.c
deleted file mode 100644
index f3a16f0c1..000000000
--- a/crypto/hash.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012-2013 The Cryptonote developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "hash-ops.h"
-#include "c_keccak.h"
-
-void hash_permutation(union hash_state *state) {
-  keccakf((uint64_t*)state, 24);
-}
-
-void hash_process(union hash_state *state, const uint8_t *buf, size_t count) {
-  keccak1600(buf, count, (uint8_t*)state);
-}
-
-void cn_fast_hash(const void *data, size_t length, char *hash) {
-  union hash_state state;
-  hash_process(&state, data, length);
-  memcpy(hash, &state, HASH_SIZE);
-}
diff --git a/src/Options.cpp b/src/Options.cpp
index 11f01d00d..3cd3ac5f3 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -28,10 +28,11 @@
 
 
 #include "Console.h"
-#include "Options.h"
-#include "version.h"
+#include "Cpu.h"
 #include "donate.h"
 #include "net/Url.h"
+#include "Options.h"
+#include "version.h"
 
 
 #ifndef ARRAY_SIZE
@@ -198,9 +199,9 @@ Options::~Options()
 
 bool Options::parseArg(int key, char *arg)
 {
-//    char *p;
+    char *p;
     int v;
-//    uint64_t ul;
+    uint64_t ul;
     Url *url;
 
     switch (key) {
@@ -243,7 +244,7 @@ bool Options::parseArg(int key, char *arg)
         break;
 
     case 'r': /* --retries */
-        v = atoi(arg);
+        v = strtol(arg, nullptr, 10);
         if (v < 1 || v > 1000) {
             showUsage(1);
             return false;
@@ -253,7 +254,7 @@ bool Options::parseArg(int key, char *arg)
         break;
 
     case 'R': /* --retry-pause */
-        v = atoi(arg);
+        v = strtol(arg, nullptr, 10);
         if (v < 1 || v > 3600) {
             showUsage(1);
             return false;
@@ -263,7 +264,7 @@ bool Options::parseArg(int key, char *arg)
         break;
 
     case 't': /* --threads */
-        v = atoi(arg);
+        v = strtol(arg, nullptr, 10);
         if (v < 1 || v > 1024) {
             showUsage(1);
             return false;
@@ -273,7 +274,7 @@ bool Options::parseArg(int key, char *arg)
         break;
 
     case 1004: /* --max-cpu-usage */
-        v = atoi(arg);
+        v = strtol(arg, nullptr, 10);
         if (v < 1 || v > 100) {
             showUsage(1);
             return false;
@@ -304,7 +305,7 @@ bool Options::parseArg(int key, char *arg)
         break;
 
     case 'v': /* --av */
-        v = atoi(arg);
+        v = strtol(arg, nullptr, 10);
         if (v < 0 || v > 1000) {
             showUsage(1);
             return false;
@@ -314,13 +315,13 @@ bool Options::parseArg(int key, char *arg)
         break;
 
     case 1020: /* --cpu-affinity */
-//        p  = strstr(arg, "0x");
-//        ul = p ? strtoul(p, NULL, 16) : atol(arg);
-//        if (ul > (1UL << cpu_info.total_logical_cpus) -1) {
-//            ul = -1;
-//        }
+        p  = strstr(arg, "0x");
+        ul = p ? strtoul(p, NULL, 16) : atol(arg);
+        if (ul > (1UL << Cpu::threads()) -1) {
+            ul = -1;
+        }
 
-//        opt_affinity = ul;
+        m_affinity = ul;
         break;
 
     case 1002: /* --no-color */
@@ -328,7 +329,7 @@ bool Options::parseArg(int key, char *arg)
         break;
 
     case 1003: /* --donate-level */
-        v = atoi(arg);
+        v = strtol(arg, nullptr, 10);
         if (v < 1 || v > 99) {
             showUsage(1);
             return false;
diff --git a/src/Options.h b/src/Options.h
index cbad99fa9..e9f4a7437 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -55,6 +55,7 @@ public:
     inline bool doubleHash() const      { return m_doubleHash; }
     inline bool isReady() const         { return m_ready; }
     inline bool keepAlive() const       { return m_keepAlive; }
+    inline bool nicehash() const        { return m_nicehash; }
     inline const char *pass() const     { return m_pass; }
     inline const char *user() const     { return m_user; }
     inline const Url *backupUrl() const { return m_backupUrl; }
@@ -64,6 +65,8 @@ public:
     inline int donateLevel() const      { return m_donateLevel; }
     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; }
 
     const char *algoName() const;
 
diff --git a/src/Summary.cpp b/src/Summary.cpp
index 38f1b1c55..b7e97a0fd 100644
--- a/src/Summary.cpp
+++ b/src/Summary.cpp
@@ -34,7 +34,7 @@
 
 static void print_versions()
 {
-    char *buf = static_cast<char*>(malloc(16));
+    char *buf = static_cast<char*>(alloca(16));
 
 #   ifdef __GNUC__
     snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
@@ -48,8 +48,6 @@ static void print_versions()
     } else {
         Console::i()->text(" * VERSIONS:     XMRig/%s libuv/%s%s", APP_VERSION, uv_version_string(), buf);
     }
-
-    free(buf);
 }
 
 
@@ -74,10 +72,40 @@ static void print_cpu()
 }
 
 
+static void print_threads()
+{
+    char *buf = static_cast<char*>(alloca(32));
+    if (Options::i()->affinity() != -1L) {
+        snprintf(buf, 32, ", affinity=0x%llX", Options::i()->affinity());
+    }
+    else {
+        buf[0] = '\0';
+    }
+
+    if (Options::i()->colors()) {
+        Console::i()->text("\x1B[01;32m * \x1B[01;37mTHREADS:      \x1B[01;36m%d\x1B[01;37m, %s, av=%d, donate=%d%%%s%s",
+                           Options::i()->threads(),
+                           Options::i()->algoName(),
+                           Options::i()->algoVariant(),
+                           Options::i()->donateLevel(),
+                           Options::i()->nicehash() ? ", nicehash" : "", buf);
+    }
+    else {
+        Console::i()->text(" * THREADS:      %d, %s, av=%d, donate=%d%%%s%s",
+                           Options::i()->threads(),
+                           Options::i()->algoName(),
+                           Options::i()->algoVariant(),
+                           Options::i()->donateLevel(),
+                           Options::i()->nicehash() ? ", nicehash" : "", buf);
+    }
+}
+
+
 void Summary::print()
 {
     print_versions();
     print_cpu();
+    print_threads();
 }
 
 

From ef3af1c4fdfe4402c46b4439b04161c5f335b198 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Fri, 9 Jun 2017 03:37:56 +0300
Subject: [PATCH 27/56] Restore autoconf.

---
 src/Options.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 src/Options.h   |  5 +++++
 2 files changed, 52 insertions(+)

diff --git a/src/Options.cpp b/src/Options.cpp
index 3cd3ac5f3..a2702a653 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -179,10 +179,21 @@ Options::Options(int argc, char **argv) :
         m_pass = strdup("x");
     }
 
+    m_algoVariant = getAlgoVariant();
     if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) {
         m_doubleHash = true;
     }
 
+    if (!m_threads) {
+        m_threads = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage);
+    }
+    else if (m_safe) {
+        const int count = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage);
+        if (m_threads > count) {
+            m_threads = count;
+        }
+    }
+
     m_ready = true;
 }
 
@@ -442,3 +453,39 @@ bool Options::setUserpass(const char *userpass)
 
     return true;
 }
+
+
+int Options::getAlgoVariant() const
+{
+#   ifndef XMRIG_NO_AEON
+    if (m_algo == ALGO_CRYPTONIGHT_LITE) {
+        return getAlgoVariantLite();
+    }
+#   endif
+
+    if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) {
+        return Cpu::hasAES() ? AV1_AESNI : AV3_SOFT_AES;
+    }
+
+    if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) {
+        return m_algoVariant + 2;
+    }
+
+    return m_algoVariant;
+}
+
+
+#ifndef XMRIG_NO_AEON
+int Options::getAlgoVariantLite() const
+{
+    if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) {
+        return Cpu::hasAES() ? AV2_AESNI_DOUBLE : AV4_SOFT_AES_DOUBLE;
+    }
+
+    if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) {
+        return m_algoVariant + 2;
+    }
+
+    return m_algoVariant;
+}
+#endif
diff --git a/src/Options.h b/src/Options.h
index e9f4a7437..4955a7f35 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -84,6 +84,11 @@ private:
     bool setAlgo(const char *algo);
     bool setUserpass(const char *userpass);
 
+    int getAlgoVariant() const;
+#   ifndef XMRIG_NO_AEON
+    int getAlgoVariantLite() const;
+#   endif
+
     bool m_background;
     bool m_colors;
     bool m_doubleHash;

From 30642881bf8c6698a4e0773b12627283f4d1197f Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Fri, 9 Jun 2017 15:09:21 +0300
Subject: [PATCH 28/56] Add Mem class.

---
 CMakeLists.txt                      |  9 +++--
 src/App.cpp                         |  2 ++
 src/Mem.cpp                         | 28 ++++++++++++++++
 src/Mem.h                           | 51 +++++++++++++++++++++++++++++
 win/memory_win.c => src/Mem_win.cpp | 44 +++++++++++--------------
 5 files changed, 107 insertions(+), 27 deletions(-)
 create mode 100644 src/Mem.cpp
 create mode 100644 src/Mem.h
 rename win/memory_win.c => src/Mem_win.cpp (79%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5f34e2346..9d43b6392 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,14 +6,15 @@ option(WITH_AEON     "CryptoNight-Lite support" ON)
 
 set(HEADERS
     src/App.h
+    src/Console.h
+    src/Cpu.h
     src/interfaces/IClientListener.h
+    src/Mem.h
     src/net/Client.h
     src/net/Job.h
     src/net/Network.h
     src/net/Url.h
     src/Options.h
-    src/Console.h
-    src/Cpu.h
     src/Summary.h
     src/version.h
    )
@@ -34,12 +35,13 @@ set(HEADERS_CRYPTO
 
 set(SOURCES
     src/App.cpp
+    src/Console.cpp
+    src/Mem.cpp
     src/net/Client.cpp
     src/net/Job.cpp
     src/net/Network.cpp
     src/net/Url.cpp
     src/Options.cpp
-    src/Console.cpp
     src/Summary.cpp
     src/xmrig.cpp
    )
@@ -61,6 +63,7 @@ if (WIN32)
         src/3rdparty/winansi.cpp
         src/3rdparty/winansi.h
         src/Cpu_win.cpp
+        src/Mem_win.cpp
         src/net/Network_win.cpp
         )
 
diff --git a/src/App.cpp b/src/App.cpp
index 6608554c0..b6a0720a7 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -29,6 +29,7 @@
 #include "Console.h"
 #include "Cpu.h"
 #include "crypto/CryptoNight.h"
+#include "Mem.h"
 #include "net/Client.h"
 #include "net/Network.h"
 #include "Options.h"
@@ -67,6 +68,7 @@ App::exec()
         return 1;
     }
 
+    Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash());
     Summary::print();
 
     m_network->connect();
diff --git a/src/Mem.cpp b/src/Mem.cpp
new file mode 100644
index 000000000..b7bf25117
--- /dev/null
+++ b/src/Mem.cpp
@@ -0,0 +1,28 @@
+/* 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 "Mem.h"
+
+
+uint8_t *Mem::m_memory = nullptr;
+int Mem::m_flags    = 0;
diff --git a/src/Mem.h b/src/Mem.h
new file mode 100644
index 000000000..d38417354
--- /dev/null
+++ b/src/Mem.h
@@ -0,0 +1,51 @@
+/* XMRig
+ * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
+ * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
+ * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
+ * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
+ * Copyright 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/>.
+ */
+
+#ifndef __MEM_H__
+#define __MEM_H__
+
+
+#include "crypto/CryptoNight.h"
+
+
+class Mem
+{
+public:
+    enum Flags {
+        HUGEPAGES_AVAILABLE = 1,
+        HUGEPAGES_ENABLED   = 2,
+        LOCK                = 4
+    };
+
+    static bool allocate(int algo, int threads, bool doubleHash);
+    static void release();
+
+    static inline int flags() { return m_flags; }
+
+private:
+    static uint8_t *m_memory __attribute__((aligned(16)));
+    static int m_flags;
+};
+
+
+#endif /* __MEM_H__ */
diff --git a/win/memory_win.c b/src/Mem_win.cpp
similarity index 79%
rename from win/memory_win.c
rename to src/Mem_win.cpp
index 9ff63dade..bab483bbc 100644
--- a/win/memory_win.c
+++ b/src/Mem_win.cpp
@@ -21,20 +21,16 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __MEMORY_H__
-#define __MEMORY_H__
 
+#include <winsock2.h>
 #include <windows.h>
 #include <ntsecapi.h>
 #include <tchar.h>
 
-#include "options.h"
-#include "persistent_memory.h"
-#include "utils/applog.h"
 
-
-char *persistent_memory;
-int persistent_memory_flags = 0;
+#include "Mem.h"
+#include "Console.h"
+#include "Options.h"
 
 
 /*****************************************************************
@@ -122,7 +118,7 @@ static BOOL ObtainLockPagesPrivilege() {
         LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME));
 
         if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) {
-            applog_notime(LOG_WARNING, "Huge pages support was successfully enabled, but reboot required to use it");
+            LOG_DEBUG("Huge pages support was successfully enabled, but reboot required to use it");
             result = TRUE;
         }
 
@@ -143,33 +139,33 @@ static BOOL TrySetLockPagesPrivilege() {
 }
 
 
-const char * persistent_memory_allocate() {
-    const int ratio = (opt_double_hash && opt_algo != ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
-    const int size  = MEMORY * (opt_n_threads * ratio + 1);
+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 (TrySetLockPagesPrivilege()) {
-        persistent_memory_flags |= MEMORY_HUGEPAGES_AVAILABLE;
+        m_flags |= HUGEPAGES_AVAILABLE;
     }
 
-    persistent_memory = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE);
-    if (!persistent_memory) {
-        persistent_memory = _mm_malloc(size, 16);
+    m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE));
+    if (!m_memory) {
+        m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
     }
     else {
-        persistent_memory_flags |= MEMORY_HUGEPAGES_ENABLED;
+        m_flags |= HUGEPAGES_ENABLED;
     }
 
-    return persistent_memory;
+    return true;
 }
 
 
-void persistent_memory_free() {
-    if (persistent_memory_flags & MEMORY_HUGEPAGES_ENABLED) {
-        VirtualFree(persistent_memory, 0, MEM_RELEASE);
+void Mem::release()
+{
+    if (m_flags & HUGEPAGES_ENABLED) {
+        VirtualFree(m_memory, 0, MEM_RELEASE);
     }
     else {
-        _mm_free(persistent_memory);
+        _mm_free(m_memory);
     }
 }
-
-#endif /* __MEMORY_H__ */

From c5fbc1a182637f508b72468d3bf7b93fd79c61ed Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Sat, 10 Jun 2017 00:43:23 +0300
Subject: [PATCH 29/56] Restore persistent memory.

---
 CMakeLists.txt   |  2 +-
 src/Mem.cpp      | 61 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/Mem.h        | 17 ++++++++++++--
 src/Mem_unix.cpp | 26 +++++++++++++++++++++
 src/Mem_win.cpp  |  4 +++-
 5 files changed, 105 insertions(+), 5 deletions(-)
 create mode 100644 src/Mem_unix.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9d43b6392..2442a75af 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -69,7 +69,7 @@ if (WIN32)
 
     set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
 else()
-    set(SOURCES_OS src/Cpu_unix.cpp)
+    set(SOURCES_OS src/Cpu_unix.cpp src/Mem_unix.cpp)
     set(EXTRA_LIBS pthread)
 endif()
 
diff --git a/src/Mem.cpp b/src/Mem.cpp
index b7bf25117..f95540525 100644
--- a/src/Mem.cpp
+++ b/src/Mem.cpp
@@ -21,8 +21,67 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+
+#include <memory.h>
+
+
+#include "crypto/CryptoNight.h"
 #include "Mem.h"
+#include "Options.h"
 
 
+bool Mem::m_doubleHash = false;
+int Mem::m_algo        = 0;
+int Mem::m_flags       = 0;
+int Mem::m_threads     = 0;
+size_t Mem::m_offset   = 0;
 uint8_t *Mem::m_memory = nullptr;
-int Mem::m_flags    = 0;
+
+
+cryptonight_ctx *Mem::create(int algo, int threadId, bool doubleHash)
+{
+#   ifndef XMRIG_NO_AEON
+    if (algo == Options::ALGO_CRYPTONIGHT_LITE) {
+        return createLite(threadId, doubleHash);
+    }
+#   endif
+
+    cryptonight_ctx *ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]);
+
+    const int ratio = doubleHash ? 2 : 1;
+    ctx->memory = &m_memory[MEMORY * (threadId * ratio + 1)];
+
+    return ctx;
+}
+
+
+
+void *Mem::calloc(size_t num, size_t size)
+{
+    void *mem = &m_memory[m_offset];
+    m_offset += (num * size);
+
+    memset(mem, 0, num * size);
+
+    return mem;
+}
+
+
+#ifndef XMRIG_NO_AEON
+cryptonight_ctx *Mem::createLite(int threadId, bool doubleHash) {
+    cryptonight_ctx *ctx;
+
+    if (!doubleHash) {
+        const size_t offset = MEMORY * (threadId + 1);
+
+        ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[offset + MEMORY_LITE]);
+        ctx->memory = &m_memory[offset];
+        return ctx;
+    }
+
+    ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]);
+    ctx->memory = &m_memory[MEMORY * (threadId + 1)];
+
+    return ctx;
+}
+#endif
diff --git a/src/Mem.h b/src/Mem.h
index d38417354..21a9f0f9a 100644
--- a/src/Mem.h
+++ b/src/Mem.h
@@ -25,7 +25,10 @@
 #define __MEM_H__
 
 
-#include "crypto/CryptoNight.h"
+#include <stdint.h>
+
+
+struct cryptonight_ctx;
 
 
 class Mem
@@ -38,13 +41,23 @@ public:
     };
 
     static bool allocate(int algo, int threads, bool doubleHash);
+    static cryptonight_ctx *create(int algo, int threadId, bool doubleHash);
+    static void *calloc(size_t num, size_t size);
     static void release();
 
     static inline int flags() { return m_flags; }
 
 private:
-    static uint8_t *m_memory __attribute__((aligned(16)));
+    static bool m_doubleHash;
+    static int m_algo;
     static int m_flags;
+    static int m_threads;
+    static size_t m_offset;
+    static uint8_t *m_memory __attribute__((aligned(16)));
+
+#   ifndef XMRIG_NO_AEON
+    static cryptonight_ctx *createLite(int threadId, bool doubleHash);
+#   endif
 };
 
 
diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp
new file mode 100644
index 000000000..a0690e79c
--- /dev/null
+++ b/src/Mem_unix.cpp
@@ -0,0 +1,26 @@
+/* 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 "crypto/CryptoNight.h"
+#include "Mem.h"
diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp
index bab483bbc..42114eafa 100644
--- a/src/Mem_win.cpp
+++ b/src/Mem_win.cpp
@@ -26,10 +26,12 @@
 #include <windows.h>
 #include <ntsecapi.h>
 #include <tchar.h>
+#include <mm_malloc.h>
 
 
-#include "Mem.h"
 #include "Console.h"
+#include "crypto/CryptoNight.h"
+#include "Mem.h"
 #include "Options.h"
 
 

From b772349f698f02f02cdc4eff7cd7ef899dd74d64 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Sat, 10 Jun 2017 01:20:54 +0300
Subject: [PATCH 30/56] Add memory summary.

---
 mac/cpu_mac.c       |  47 ----
 mac/memory_mac.c    |  76 -------
 mac/xmrig_mac.c     |  91 --------
 memory.c            |  76 -------
 options.c           | 520 --------------------------------------------
 options.h           |  91 --------
 persistent_memory.h |  50 -----
 src/Mem.h           |  10 +-
 src/Mem_win.cpp     |   6 +-
 src/Summary.cpp     |  14 ++
 unix/memory_unix.c  |  76 -------
 unix/xmrig_unix.c   |  91 --------
 win/xmrig_win.c     |  84 -------
 13 files changed, 23 insertions(+), 1209 deletions(-)
 delete mode 100644 mac/cpu_mac.c
 delete mode 100644 mac/memory_mac.c
 delete mode 100644 mac/xmrig_mac.c
 delete mode 100644 memory.c
 delete mode 100644 options.c
 delete mode 100644 options.h
 delete mode 100644 persistent_memory.h
 delete mode 100644 unix/memory_unix.c
 delete mode 100644 unix/xmrig_unix.c
 delete mode 100644 win/xmrig_win.c

diff --git a/mac/cpu_mac.c b/mac/cpu_mac.c
deleted file mode 100644
index 88bda5419..000000000
--- a/mac/cpu_mac.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <unistd.h>
-#include <sched.h>
-#include <pthread.h>
-
-#include "cpu.h"
-
-
-struct cpu_info cpu_info = { 0 };
-void cpu_init_common();
-
-
-void cpu_init() {
-#   ifdef XMRIG_NO_LIBCPUID
-    cpu_info.total_logical_cpus = sysconf(_SC_NPROCESSORS_CONF);
-#   endif
-    
-    cpu_init_common();
-}
-
-
-int affine_to_cpu_mask(int id, unsigned long mask)
-{
-    return 0;
-}
diff --git a/mac/memory_mac.c b/mac/memory_mac.c
deleted file mode 100644
index 3f5f714cb..000000000
--- a/mac/memory_mac.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <mm_malloc.h>
-#include <sys/mman.h>
-#include <mach/vm_statistics.h>
-
-#include "persistent_memory.h"
-#include "options.h"
-#include "utils/applog.h"
-
-char *persistent_memory;
-int persistent_memory_flags = 0;
-
-
-const char * persistent_memory_allocate() {
-    const int ratio = (opt_double_hash && opt_algo != ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
-    const int size = MEMORY * (opt_n_threads * ratio + 1);
-    persistent_memory_flags |= MEMORY_HUGEPAGES_AVAILABLE;
-    
-    persistent_memory = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
-    
-    if (persistent_memory == MAP_FAILED) {
-        persistent_memory = _mm_malloc(size, 16);
-        return persistent_memory;
-    }
-    
-    persistent_memory_flags |= MEMORY_HUGEPAGES_ENABLED;
-    
-    if (madvise(persistent_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0) {
-        applog(LOG_ERR, "madvise failed");
-    }
-    
-    if (mlock(persistent_memory, size) == 0) {
-        persistent_memory_flags |= MEMORY_LOCK;
-    }
-    
-    return persistent_memory;
-}
-
-
-void persistent_memory_free() {
-    const int size = MEMORY * (opt_n_threads + 1);
-    
-    if (persistent_memory_flags & MEMORY_HUGEPAGES_ENABLED) {
-        if (persistent_memory_flags & MEMORY_LOCK) {
-            munlock(persistent_memory, size);
-        }
-        
-        munmap(persistent_memory, size);
-    }
-    else {
-        _mm_free(persistent_memory);
-    }
-}
diff --git a/mac/xmrig_mac.c b/mac/xmrig_mac.c
deleted file mode 100644
index f7278c6db..000000000
--- a/mac/xmrig_mac.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <signal.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "options.h"
-#include "cpu.h"
-#include "utils/applog.h"
-
-
-static void signal_handler(int sig)
-{
-    switch (sig) {
-        case SIGHUP:
-            applog(LOG_WARNING, "SIGHUP received");
-            break;
-            
-        case SIGINT:
-            applog(LOG_WARNING, "SIGINT received, exiting");
-            proper_exit(0);
-            break;
-            
-        case SIGTERM:
-            applog(LOG_WARNING, "SIGTERM received, exiting");
-            proper_exit(0);
-            break;
-    }
-}
-
-
-void proper_exit(int reason) {
-    exit(reason);
-}
-
-
-void os_specific_init()
-{
-    if (opt_affinity != -1) {
-        affine_to_cpu_mask(-1, opt_affinity);
-    }
-    
-    if (opt_background) {
-        int i = fork();
-        if (i < 0) {
-            exit(1);
-        }
-        
-        if (i > 0) {
-            exit(0);
-        }
-        
-        i = setsid();
-        
-        if (i < 0) {
-            applog(LOG_ERR, "setsid() failed (errno = %d)", errno);
-        }
-        
-        i = chdir("/");
-        if (i < 0) {
-            applog(LOG_ERR, "chdir() failed (errno = %d)", errno);
-        }
-        
-        signal(SIGHUP, signal_handler);
-        signal(SIGTERM, signal_handler);
-    }
-    
-    signal(SIGINT, signal_handler);
-}
diff --git a/memory.c b/memory.c
deleted file mode 100644
index 112f11153..000000000
--- a/memory.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <string.h>
-
-#include "persistent_memory.h"
-#include "algo/cryptonight/cryptonight.h"
-#include "options.h"
-
-static size_t offset = 0;
-
-
-#ifndef XMRIG_NO_AEON
-static void * create_persistent_ctx_lite(int thr_id) {
-    struct cryptonight_ctx *ctx = NULL;
-
-    if (!opt_double_hash) {
-        const size_t offset = MEMORY * (thr_id + 1);
-
-        ctx = (struct cryptonight_ctx *) &persistent_memory[offset + MEMORY_LITE];
-        ctx->memory = (uint8_t*) &persistent_memory[offset];
-        return ctx;
-    }
-
-    ctx = (struct cryptonight_ctx *) &persistent_memory[MEMORY - sizeof(struct cryptonight_ctx) * (thr_id + 1)];
-    ctx->memory = (uint8_t*) &persistent_memory[MEMORY * (thr_id + 1)];
-
-    return ctx;
-}
-#endif
-
-
-void * persistent_calloc(size_t num, size_t size) {
-    void *mem = &persistent_memory[offset];
-    offset += (num * size);
-
-    memset(mem, 0, num * size);
-
-    return mem;
-}
-
-
-void * create_persistent_ctx(int thr_id) {
-#   ifndef XMRIG_NO_AEON
-    if (opt_algo == ALGO_CRYPTONIGHT_LITE) {
-        return create_persistent_ctx_lite(thr_id);
-    }
-#   endif
-
-    struct cryptonight_ctx *ctx = (struct cryptonight_ctx *) &persistent_memory[MEMORY - sizeof(struct cryptonight_ctx) * (thr_id + 1)];
-
-    const int ratio = opt_double_hash ? 2 : 1;
-    ctx->memory = (uint8_t*) &persistent_memory[MEMORY * (thr_id * ratio + 1)];
-
-    return ctx;
-}
diff --git a/options.c b/options.c
deleted file mode 100644
index eb88bcb0f..000000000
--- a/options.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <jansson.h>
-#include <curl/curl.h>
-#include <getopt.h>
-
-#include "version.h"
-#include "utils/applog.h"
-#include "options.h"
-#include "cpu.h"
-#include "donate.h"
-#include "algo/cryptonight/cryptonight.h"
-
-
-int64_t opt_affinity      = -1L;
-int     opt_n_threads     = 0;
-int     opt_algo_variant  = 0;
-int     opt_retries       = 5;
-int     opt_retry_pause   = 5;
-int     opt_donate_level  = DONATE_LEVEL;
-int     opt_max_cpu_usage = 75;
-bool    opt_colors        = true;
-bool    opt_keepalive     = false;
-bool    opt_background    = false;
-bool    opt_double_hash   = false;
-bool    opt_safe          = false;
-bool    opt_nicehash      = false;
-char    *opt_url          = NULL;
-char    *opt_backup_url   = NULL;
-char    *opt_userpass     = NULL;
-char    *opt_user         = NULL;
-char    *opt_pass         = NULL;
-
-enum mining_algo opt_algo = ALGO_CRYPTONIGHT;
-
-
-static char const usage[] = "\
-Usage: " APP_ID " [OPTIONS]\n\
-Options:\n\
-  -a, --algo=ALGO       cryptonight (default) or cryptonight-lite\n\
-  -o, --url=URL         URL of mining server\n\
-  -b, --backup-url=URL  URL of backup mining server\n\
-  -O, --userpass=U:P    username:password pair for mining server\n\
-  -u, --user=USERNAME   username for mining server\n\
-  -p, --pass=PASSWORD   password for mining server\n\
-  -t, --threads=N       number of miner threads\n\
-  -v, --av=N            algorithm variation, 0 auto select\n\
-  -k, --keepalive       send keepalived for prevent timeout (need pool support)\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\
-      --no-color        disable colored output\n\
-      --donate-level=N  donate level, default 5%% (5 minutes in 100 minutes)\n\
-  -B, --background      run the miner in the background\n\
-  -c, --config=FILE     load a JSON-format configuration file\n\
-      --max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
-      --safe            safe adjust threads and av settings for current CPU\n\
-      --nicehash        enable nicehash support\n\
-  -h, --help            display this help and exit\n\
-  -V, --version         output version information and exit\n\
-";
-
-
-static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vb:";
-
-
-static struct option const options[] = {
-    { "algo",          1, NULL, 'a'  },
-    { "av",            1, NULL, 'v'  },
-    { "background",    0, NULL, 'B'  },
-    { "backup-url",    1, NULL, 'b'  },
-    { "config",        1, NULL, 'c'  },
-    { "cpu-affinity",  1, NULL, 1020 },
-    { "donate-level",  1, NULL, 1003 },
-    { "help",          0, NULL, 'h'  },
-    { "keepalive",     0, NULL ,'k'  },
-    { "max-cpu-usage", 1, NULL, 1004 },
-    { "nicehash",      0, NULL, 1006 },
-    { "no-color",      0, NULL, 1002 },
-    { "pass",          1, NULL, 'p'  },
-    { "retries",       1, NULL, 'r'  },
-    { "retry-pause",   1, NULL, 'R'  },
-    { "safe",          0, NULL, 1005 },
-    { "threads",       1, NULL, 't'  },
-    { "url",           1, NULL, 'o'  },
-    { "user",          1, NULL, 'u'  },
-    { "userpass",      1, NULL, 'O'  },
-    { "version",       0, NULL, 'V'  },
-    { 0, 0, 0, 0 }
-};
-
-
-static const char *algo_names[] = {
-    [ALGO_CRYPTONIGHT]      = "cryptonight",
-#   ifndef XMRIG_NO_AEON
-    [ALGO_CRYPTONIGHT_LITE] = "cryptonight-lite"
-#   endif
-};
-
-
-#ifndef XMRIG_NO_AEON
-static int get_cryptonight_lite_variant(int variant) {
-    if (variant <= AEON_AV0_AUTO || variant >= AEON_AV_MAX) {
-        return (cpu_info.flags & CPU_FLAG_AES) ? AEON_AV2_AESNI_DOUBLE : AEON_AV4_SOFT_AES_DOUBLE;
-    }
-
-    if (opt_safe && !(cpu_info.flags & CPU_FLAG_AES) && variant <= AEON_AV2_AESNI_DOUBLE) {
-        return variant + 2;
-    }
-
-    return variant;
-}
-#endif
-
-
-static int get_algo_variant(int algo, int variant) {
-#   ifndef XMRIG_NO_AEON
-    if (algo == ALGO_CRYPTONIGHT_LITE) {
-        return get_cryptonight_lite_variant(variant);
-    }
-#   endif
-
-    if (variant <= XMR_AV0_AUTO || variant >= XMR_AV_MAX) {
-        return (cpu_info.flags & CPU_FLAG_AES) ? XMR_AV1_AESNI : XMR_AV3_SOFT_AES;
-    }
-
-    if (opt_safe && !(cpu_info.flags & CPU_FLAG_AES) && variant <= XMR_AV2_AESNI_DOUBLE) {
-        return variant + 2;
-    }
-
-    return variant;
-}
-
-
-static void parse_config(json_t *config, char *ref);
-static char *parse_url(const char *arg);
-
-
-static void parse_arg(int key, char *arg) {
-    char *p;
-    int v;
-    uint64_t ul;
-
-    switch (key)
-    {
-    case 'a':
-        for (int i = 0; i < ARRAY_SIZE(algo_names); i++) {
-            if (algo_names[i] && !strcmp(arg, algo_names[i])) {
-                opt_algo = i;
-                break;
-            }
-
-#           ifndef XMRIG_NO_AEON
-            if (i == ARRAY_SIZE(algo_names) && !strcmp(arg, "cryptonight-light")) {
-                opt_algo = i = ALGO_CRYPTONIGHT_LITE;
-            }
-#           endif
-
-            if (i == ARRAY_SIZE(algo_names)) {
-                show_usage_and_exit(1);
-            }
-        }
-        break;
-
-    case 'O': /* --userpass */
-        p = strchr(arg, ':');
-        if (!p) {
-            show_usage_and_exit(1);
-        }
-
-        free(opt_userpass);
-        opt_userpass = strdup(arg);
-        free(opt_user);
-        opt_user = calloc(p - arg + 1, 1);
-        strncpy(opt_user, arg, p - arg);
-        free(opt_pass);
-        opt_pass = strdup(p + 1);
-        break;
-
-    case 'o': /* --url */
-        p = parse_url(arg);
-        if (p) {
-            free(opt_url);
-            opt_url = p;
-        }
-        break;
-
-    case 'b': /* --backup-url */
-        p = parse_url(arg);
-        if (p) {
-            free(opt_backup_url);
-            opt_backup_url = p;
-        }
-        break;
-
-    case 'u': /* --user */
-        free(opt_user);
-        opt_user = strdup(arg);
-        break;
-
-    case 'p': /* --pass */
-        free(opt_pass);
-        opt_pass = strdup(arg);
-        break;
-
-    case 'r': /* --retries */
-        v = atoi(arg);
-        if (v < 1 || v > 1000) {
-            show_usage_and_exit(1);
-        }
-
-        opt_retries = v;
-        break;
-
-    case 'R': /* --retry-pause */
-        v = atoi(arg);
-        if (v < 1 || v > 3600) {
-            show_usage_and_exit(1);
-        }
-
-        opt_retry_pause = v;
-        break;
-
-    case 't': /* --threads */
-        v = atoi(arg);
-        if (v < 1 || v > 1024) {
-            show_usage_and_exit(1);
-        }
-
-        opt_n_threads = v;
-        break;
-
-    case 1004: /* --max-cpu-usage */
-        v = atoi(arg);
-        if (v < 1 || v > 100) {
-            show_usage_and_exit(1);
-        }
-
-        opt_max_cpu_usage = v;
-        break;
-
-    case 1005: /* --safe */
-        opt_safe = true;
-        break;
-
-    case 'k': /* --keepalive */
-        opt_keepalive = true;
-        break;
-
-    case 'V': /* --version */
-        show_version_and_exit();
-        break;
-
-    case 'h': /* --help */
-        show_usage_and_exit(0);
-        break;
-
-    case 'c': { /* --config */
-        json_error_t err;
-        json_t *config = json_load_file(arg, 0, &err);
-
-        if (!json_is_object(config)) {
-            if (err.line < 0) {
-                applog(LOG_ERR, "%s\n", err.text);
-            }
-            else {
-                applog(LOG_ERR, "%s:%d: %s\n", arg, err.line, err.text);
-            }
-        } else {
-            parse_config(config, arg);
-            json_decref(config);
-        }
-        break;
-    }
-
-    case 'B': /* --background */
-        opt_background = true;
-        opt_colors = false;
-        break;
-
-    case 'v': /* --av */
-        v = atoi(arg);
-        if (v < 0 || v > 1000) {
-            show_usage_and_exit(1);
-        }
-
-        opt_algo_variant = v;
-        break;
-
-    case 1020: /* --cpu-affinity */
-        p  = strstr(arg, "0x");
-        ul = p ? strtoul(p, NULL, 16) : atol(arg);
-        if (ul > (1UL << cpu_info.total_logical_cpus) -1) {
-            ul = -1;
-        }
-
-        opt_affinity = ul;
-        break;
-
-    case 1002: /* --no-color */
-        opt_colors = false;
-        break;
-
-    case 1003: /* --donate-level */
-        v = atoi(arg);
-        if (v < 1 || v > 99) {
-            show_usage_and_exit(1);
-        }
-
-        opt_donate_level = v;
-        break;
-
-    case 1006: /* --nicehash */
-        opt_nicehash = true;
-        break;
-
-    default:
-        show_usage_and_exit(1);
-    }
-}
-
-
-static void parse_config(json_t *config, char *ref)
-{
-    int i;
-    char buf[16];
-    json_t *val;
-
-    applog(LOG_ERR, ref);
-
-    for (i = 0; i < ARRAY_SIZE(options); i++) {
-        if (!options[i].name) {
-            break;
-        }
-
-        val = json_object_get(config, options[i].name);
-        if (!val) {
-            continue;
-        }
-
-        if (options[i].has_arg && json_is_string(val)) {
-            char *s = strdup(json_string_value(val));
-            if (!s) {
-                break;
-            }
-
-            parse_arg(options[i].val, s);
-            free(s);
-        }
-        else if (options[i].has_arg && json_is_integer(val)) {
-            sprintf(buf, "%d", (int) json_integer_value(val));
-            parse_arg(options[i].val, buf);
-        }
-        else if (options[i].has_arg && json_is_real(val)) {
-            sprintf(buf, "%f", json_real_value(val));
-            parse_arg(options[i].val, buf);
-        }
-        else if (!options[i].has_arg) {
-            if (json_is_true(val)) {
-               parse_arg(options[i].val, "");
-            }
-        }
-        else {
-            applog(LOG_ERR, "JSON option %s invalid", options[i].name);
-        }
-    }
-}
-
-
-static char *parse_url(const char *arg)
-{
-    char *p = strstr(arg, "://");
-    if (p) {
-        if (strncasecmp(arg, "stratum+tcp://", 14)) {
-            show_usage_and_exit(1);
-        }
-
-        return strdup(arg);
-    }
-
-
-    if (!strlen(arg) || *arg == '/') {
-        show_usage_and_exit(1);
-    }
-
-    char *dest = malloc(strlen(arg) + 16);
-    sprintf(dest, "stratum+tcp://%s", arg);
-
-    return dest;
-}
-
-
-/**
- * Parse application command line via getopt.
- */
-void parse_cmdline(int argc, char *argv[]) {
-    opt_user = strdup("x");
-    opt_pass = strdup("x");
-
-    int key;
-
-    while (1) {
-        key = getopt_long(argc, argv, short_options, options, NULL);
-        if (key < 0) {
-            break;
-        }
-
-        parse_arg(key, optarg);
-    }
-
-    if (optind < argc) {
-        fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]);
-        show_usage_and_exit(1);
-    }
-
-    if (!opt_url) {
-        applog_notime(LOG_ERR, "No pool URL supplied. Exiting.\n", argv[0]);
-        proper_exit(1);
-    }
-
-    if (strstr(opt_url, ".nicehash.com:") != NULL) {
-        opt_nicehash = true;
-    }
-
-    if (!opt_userpass) {
-        opt_userpass = malloc(strlen(opt_user) + strlen(opt_pass) + 2);
-        if (!opt_userpass) {
-            proper_exit(1);
-        }
-
-        sprintf(opt_userpass, "%s:%s", opt_user, opt_pass);
-    }
-
-    opt_algo_variant = get_algo_variant(opt_algo, opt_algo_variant);
-
-    if (!cryptonight_init(opt_algo_variant)) {
-        applog(LOG_ERR, "Cryptonight hash self-test failed. This might be caused by bad compiler optimizations.");
-        proper_exit(1);
-    }
-
-    if (!opt_n_threads) {
-        opt_n_threads = get_optimal_threads_count(opt_algo, opt_double_hash, opt_max_cpu_usage);
-    }
-
-    if (opt_safe) {
-        const int count = get_optimal_threads_count(opt_algo, opt_double_hash, opt_max_cpu_usage);
-        if (opt_n_threads > count) {
-            opt_n_threads = count;
-        }
-    }
-}
-
-
-void show_usage_and_exit(int status) {
-    if (status) {
-        fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n");
-    }
-    else {
-        printf(usage);
-    }
-
-    proper_exit(status);
-}
-
-
-void show_version_and_exit(void) {
-    printf(APP_NAME " " APP_VERSION "\n built on " __DATE__
-
-    #ifdef __GNUC__
-    " with GCC");
-    printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
-    #endif
-
-    printf("\n features:"
-    #ifdef __i386__
-    " i386"
-    #endif
-    #ifdef __x86_64__
-    " x86_64"
-    #endif
-    #ifdef __AES__
-    " AES-NI"
-    #endif
-    "\n");
-
-    printf("\n%s\n", curl_version());
-    #ifdef JANSSON_VERSION
-    printf("libjansson/%s\n", JANSSON_VERSION);
-    #endif
-    proper_exit(0);
-}
-
-
-const char* get_current_algo_name(void) {
-    return algo_names[opt_algo];
-}
diff --git a/options.h b/options.h
deleted file mode 100644
index a14aaeeb4..000000000
--- a/options.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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/>.
- */
-
-#ifndef __OPTIONS_H__
-#define __OPTIONS_H__
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#ifndef ARRAY_SIZE
-#   define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-#endif
-
-
-enum mining_algo {
-    ALGO_CRYPTONIGHT,      /* CryptoNight (Monero) */
-    ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */
-};
-
-
-enum xmr_algo_variant {
-    XMR_AV0_AUTO,
-    XMR_AV1_AESNI,
-    XMR_AV2_AESNI_DOUBLE,
-    XMR_AV3_SOFT_AES,
-    XMR_AV4_SOFT_AES_DOUBLE,
-    XMR_AV_MAX
-};
-
-
-#ifndef XMRIG_NO_AEON
-enum aeon_algo_variant {
-    AEON_AV0_AUTO,
-    AEON_AV1_AESNI,
-    AEON_AV2_AESNI_DOUBLE,
-    AEON_AV3_SOFT_AES,
-    AEON_AV4_SOFT_AES_DOUBLE,
-    AEON_AV_MAX
-};
-#endif
-
-
-extern bool opt_colors;
-extern bool opt_keepalive;
-extern bool opt_background;
-extern bool opt_double_hash;
-extern bool opt_safe;
-extern bool opt_nicehash;
-extern char *opt_url;
-extern char *opt_backup_url;
-extern char *opt_userpass;
-extern char *opt_user;
-extern char *opt_pass;
-extern int opt_n_threads;
-extern int opt_algo_variant;
-extern int opt_retry_pause;
-extern int opt_retries;
-extern int opt_donate_level;
-extern int opt_max_cpu_usage;
-extern int64_t opt_affinity;
-extern enum mining_algo opt_algo;
-
-void parse_cmdline(int argc, char *argv[]);
-void show_usage_and_exit(int status);
-void show_version_and_exit(void);
-const char* get_current_algo_name(void);
-
-extern void proper_exit(int reason);
-
-
-#endif /* __OPTIONS_H__ */
diff --git a/persistent_memory.h b/persistent_memory.h
deleted file mode 100644
index 5a6d6ca74..000000000
--- a/persistent_memory.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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/>.
- */
-
-#ifndef __PERSISTENT_MEMORY_H__
-#define __PERSISTENT_MEMORY_H__
-
-#include <stddef.h>
-
-
-enum memory_flags {
-    MEMORY_HUGEPAGES_AVAILABLE = 1,
-    MEMORY_HUGEPAGES_ENABLED   = 2,
-    MEMORY_LOCK                = 4
-};
-
-
-#define MEMORY 2097152
-
-
-extern char *persistent_memory;
-extern int persistent_memory_flags;
-
-
-const char * persistent_memory_allocate();
-void persistent_memory_free();
-void * persistent_calloc(size_t num, size_t size);
-void * create_persistent_ctx(int thr_id);
-
-
-#endif /* __PERSISTENT_MEMORY_H__ */
diff --git a/src/Mem.h b/src/Mem.h
index 21a9f0f9a..ac89c363b 100644
--- a/src/Mem.h
+++ b/src/Mem.h
@@ -35,9 +35,9 @@ class Mem
 {
 public:
     enum Flags {
-        HUGEPAGES_AVAILABLE = 1,
-        HUGEPAGES_ENABLED   = 2,
-        LOCK                = 4
+        HugepagesAvailable = 1,
+        HugepagesEnabled   = 2,
+        Lock               = 4
     };
 
     static bool allocate(int algo, int threads, bool doubleHash);
@@ -45,7 +45,9 @@ public:
     static void *calloc(size_t num, size_t size);
     static void release();
 
-    static inline int flags() { return m_flags; }
+    static inline bool isHugepagesAvailable() { return m_flags & HugepagesAvailable; }
+    static inline bool isHugepagesEnabled()   { return m_flags & HugepagesEnabled; }
+    static inline int flags()                 { return m_flags; }
 
 private:
     static bool m_doubleHash;
diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp
index 42114eafa..18b54ba35 100644
--- a/src/Mem_win.cpp
+++ b/src/Mem_win.cpp
@@ -147,7 +147,7 @@ bool Mem::allocate(int algo, int threads, bool doubleHash)
     const size_t size  = MEMORY * (threads * ratio + 1);
 
     if (TrySetLockPagesPrivilege()) {
-        m_flags |= HUGEPAGES_AVAILABLE;
+        m_flags |= HugepagesAvailable;
     }
 
     m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE));
@@ -155,7 +155,7 @@ bool Mem::allocate(int algo, int threads, bool doubleHash)
         m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
     }
     else {
-        m_flags |= HUGEPAGES_ENABLED;
+        m_flags |= HugepagesEnabled;
     }
 
     return true;
@@ -164,7 +164,7 @@ bool Mem::allocate(int algo, int threads, bool doubleHash)
 
 void Mem::release()
 {
-    if (m_flags & HUGEPAGES_ENABLED) {
+    if (m_flags & HugepagesEnabled) {
         VirtualFree(m_memory, 0, MEM_RELEASE);
     }
     else {
diff --git a/src/Summary.cpp b/src/Summary.cpp
index b7e97a0fd..502747c95 100644
--- a/src/Summary.cpp
+++ b/src/Summary.cpp
@@ -27,6 +27,7 @@
 
 #include "Console.h"
 #include "Cpu.h"
+#include "Mem.h"
 #include "Options.h"
 #include "Summary.h"
 #include "version.h"
@@ -51,6 +52,18 @@ static void print_versions()
 }
 
 
+static void print_memory() {
+    if (Options::i()->colors()) {
+        Console::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES:   %s, %s",
+                           Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable",
+                           Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled");
+    }
+    else {
+        Console::i()->text(" * HUGE PAGES:   %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled");
+    }
+}
+
+
 static void print_cpu()
 {
     if (Options::i()->colors()) {
@@ -104,6 +117,7 @@ static void print_threads()
 void Summary::print()
 {
     print_versions();
+    print_memory();
     print_cpu();
     print_threads();
 }
diff --git a/unix/memory_unix.c b/unix/memory_unix.c
deleted file mode 100644
index 2e794a037..000000000
--- a/unix/memory_unix.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <mm_malloc.h>
-#include <sys/mman.h>
-
-#include "persistent_memory.h"
-#include "options.h"
-#include "utils/applog.h"
-
-
-char *persistent_memory;
-int persistent_memory_flags = 0;
-
-
-const char * persistent_memory_allocate() {
-    const int ratio = (opt_double_hash && opt_algo != ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
-    const int size = MEMORY * (opt_n_threads * ratio + 1);
-    persistent_memory_flags |= MEMORY_HUGEPAGES_AVAILABLE;
-
-    persistent_memory = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0);
-
-    if (persistent_memory == MAP_FAILED) {
-        persistent_memory = _mm_malloc(size, 16);
-        return persistent_memory;
-    }
-
-    persistent_memory_flags |= MEMORY_HUGEPAGES_ENABLED;
-
-    if (madvise(persistent_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0) {
-        applog(LOG_ERR, "madvise failed");
-    }
-
-    if (mlock(persistent_memory, size) == 0) {
-        persistent_memory_flags |= MEMORY_LOCK;
-    }
-
-    return persistent_memory;
-}
-
-
-void persistent_memory_free() {
-    const int size = MEMORY * (opt_n_threads + 1);
-
-    if (persistent_memory_flags & MEMORY_HUGEPAGES_ENABLED) {
-        if (persistent_memory_flags & MEMORY_LOCK) {
-            munlock(persistent_memory, size);
-        }
-
-        munmap(persistent_memory, size);
-    }
-    else {
-        _mm_free(persistent_memory);
-    }
-}
diff --git a/unix/xmrig_unix.c b/unix/xmrig_unix.c
deleted file mode 100644
index cd25934a1..000000000
--- a/unix/xmrig_unix.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <signal.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "options.h"
-#include "cpu.h"
-#include "utils/applog.h"
-
-
-static void signal_handler(int sig)
-{
-    switch (sig) {
-    case SIGHUP:
-        applog(LOG_WARNING, "SIGHUP received");
-        break;
-
-    case SIGINT:
-        applog(LOG_WARNING, "SIGINT received, exiting");
-        proper_exit(0);
-        break;
-
-    case SIGTERM:
-        applog(LOG_WARNING, "SIGTERM received, exiting");
-        proper_exit(0);
-        break;
-    }
-}
-
-
-void proper_exit(int reason) {
-    exit(reason);
-}
-
-
-void os_specific_init()
-{
-    if (opt_affinity != -1) {
-        affine_to_cpu_mask(-1, opt_affinity);
-    }
-
-    if (opt_background) {
-        int i = fork();
-        if (i < 0) {
-            exit(1);
-        }
-
-        if (i > 0) {
-            exit(0);
-        }
-
-        i = setsid();
-
-        if (i < 0) {
-            applog(LOG_ERR, "setsid() failed (errno = %d)", errno);
-        }
-
-        i = chdir("/");
-        if (i < 0) {
-            applog(LOG_ERR, "chdir() failed (errno = %d)", errno);
-        }
-
-        signal(SIGHUP, signal_handler);
-        signal(SIGTERM, signal_handler);
-    }
-
-    signal(SIGINT, signal_handler);
-}
diff --git a/win/xmrig_win.c b/win/xmrig_win.c
deleted file mode 100644
index 96921faab..000000000
--- a/win/xmrig_win.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <windows.h>
-
-#include "options.h"
-#include "cpu.h"
-#include "utils/applog.h"
-
-
-BOOL WINAPI ConsoleHandler(DWORD dwType)
-{
-    switch (dwType) {
-    case CTRL_C_EVENT:
-        applog(LOG_WARNING, "CTRL_C_EVENT received, exiting");
-        proper_exit(0);
-        break;
-
-    case CTRL_BREAK_EVENT:
-        applog(LOG_WARNING, "CTRL_BREAK_EVENT received, exiting");
-        proper_exit(0);
-        break;
-
-    default:
-        return false;
-}
-
-    return true;
-}
-
-
-void proper_exit(int reason) {
-    if (opt_background) {
-        HWND hcon = GetConsoleWindow();
-        if (hcon) {
-            // unhide parent command line windows
-            ShowWindow(hcon, SW_SHOWMINNOACTIVE);
-        }
-    }
-
-    exit(reason);
-}
-
-
-void os_specific_init()
-{
-    if (opt_affinity != -1) {
-        affine_to_cpu_mask(-1, opt_affinity);
-    }
-
-    SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE);
-
-    if (opt_background) {
-        HWND hcon = GetConsoleWindow();
-        if (hcon) {
-            // this method also hide parent command line window
-            ShowWindow(hcon, SW_HIDE);
-        } else {
-            HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
-            CloseHandle(h);
-            FreeConsole();
-        }
-    }
-}

From 29aa4660233977d8437133a981eaaf1bba5735d4 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Sat, 10 Jun 2017 07:05:00 +0300
Subject: [PATCH 31/56] Add IWorker, Handle, SingleWorker, Worker classes.

---
 CMakeLists.txt               | 11 ++++++--
 src/App.cpp                  | 26 +++++++++++++++++++
 src/App.h                    | 13 ++++++++--
 src/Mem.cpp                  | 12 ++++-----
 src/Mem.h                    |  4 +--
 src/Mem_win.cpp              |  4 +++
 src/interfaces/IWorker.h     | 37 ++++++++++++++++++++++++++
 src/workers/Handle.cpp       | 39 ++++++++++++++++++++++++++++
 src/workers/Handle.h         | 50 ++++++++++++++++++++++++++++++++++++
 src/workers/SingleWorker.cpp | 35 +++++++++++++++++++++++++
 src/workers/SingleWorker.h   | 41 +++++++++++++++++++++++++++++
 src/workers/Worker.cpp       | 48 ++++++++++++++++++++++++++++++++++
 src/workers/Worker.h         | 50 ++++++++++++++++++++++++++++++++++++
 13 files changed, 358 insertions(+), 12 deletions(-)
 create mode 100644 src/interfaces/IWorker.h
 create mode 100644 src/workers/Handle.cpp
 create mode 100644 src/workers/Handle.h
 create mode 100644 src/workers/SingleWorker.cpp
 create mode 100644 src/workers/SingleWorker.h
 create mode 100644 src/workers/Worker.cpp
 create mode 100644 src/workers/Worker.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2442a75af..e91fae3c0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,6 +9,7 @@ set(HEADERS
     src/Console.h
     src/Cpu.h
     src/interfaces/IClientListener.h
+    src/interfaces/IWorker.h
     src/Mem.h
     src/net/Client.h
     src/net/Job.h
@@ -16,6 +17,9 @@ set(HEADERS
     src/net/Url.h
     src/Options.h
     src/Summary.h
+    src/workers/Handle.h
+    src/workers/SingleWorker.h
+    src/workers/Worker.h
     src/version.h
    )
 
@@ -43,6 +47,9 @@ set(SOURCES
     src/net/Url.cpp
     src/Options.cpp
     src/Summary.cpp
+    src/workers/Handle.cpp
+    src/workers/SingleWorker.cpp
+    src/workers/Worker.cpp
     src/xmrig.cpp
    )
 
@@ -85,11 +92,11 @@ if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
     set(CMAKE_BUILD_TYPE Release)
 endif()
 
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall -fno-exceptions")
 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions")
-set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
+set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-use -fprofile-correction")
diff --git a/src/App.cpp b/src/App.cpp
index b6a0720a7..943690ec7 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -35,6 +35,8 @@
 #include "Options.h"
 #include "Summary.h"
 #include "version.h"
+#include "workers/Handle.h"
+#include "workers/SingleWorker.h"
 
 
 
@@ -45,6 +47,8 @@ App::App(int argc, char **argv)
 
     m_options = Options::parse(argc, argv);
     m_network = new Network(m_options);
+
+
 }
 
 
@@ -71,6 +75,8 @@ App::exec()
     Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash());
     Summary::print();
 
+    startWorders();
+
     m_network->connect();
 
     const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
@@ -78,3 +84,23 @@ App::exec()
 
     return r;
 }
+
+
+void App::startWorders()
+{
+    for (int i = 0; i < m_options->threads(); ++i) {
+        Handle *handle = new Handle(i);
+        m_workers.push_back(handle);
+        handle->start(App::onWorkerStarted);
+    }
+}
+
+
+void *App::onWorkerStarted(void *arg)
+{
+    auto handle = static_cast<Handle*>(arg);
+    IWorker *worker = new SingleWorker(handle);
+    worker->start();
+
+    return nullptr;
+}
diff --git a/src/App.h b/src/App.h
index a6aef6fa1..25d91890b 100644
--- a/src/App.h
+++ b/src/App.h
@@ -25,8 +25,12 @@
 #define __APP_H__
 
 
-class Options;
+#include <vector>
+
+
+class Handle;
 class Network;
+class Options;
 
 
 class App
@@ -38,8 +42,13 @@ public:
   int exec();
 
 private:
-  Options *m_options;
+  void startWorders();
+
+  static void* onWorkerStarted(void *arg);
+
   Network *m_network;
+  Options *m_options;
+  std::vector<Handle*> m_workers;
 };
 
 
diff --git a/src/Mem.cpp b/src/Mem.cpp
index f95540525..4437c6739 100644
--- a/src/Mem.cpp
+++ b/src/Mem.cpp
@@ -38,17 +38,17 @@ size_t Mem::m_offset   = 0;
 uint8_t *Mem::m_memory = nullptr;
 
 
-cryptonight_ctx *Mem::create(int algo, int threadId, bool doubleHash)
+cryptonight_ctx *Mem::create(int threadId)
 {
 #   ifndef XMRIG_NO_AEON
-    if (algo == Options::ALGO_CRYPTONIGHT_LITE) {
-        return createLite(threadId, doubleHash);
+    if (m_algo == Options::ALGO_CRYPTONIGHT_LITE) {
+        return createLite(threadId);
     }
 #   endif
 
     cryptonight_ctx *ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]);
 
-    const int ratio = doubleHash ? 2 : 1;
+    const int ratio = m_doubleHash ? 2 : 1;
     ctx->memory = &m_memory[MEMORY * (threadId * ratio + 1)];
 
     return ctx;
@@ -68,10 +68,10 @@ void *Mem::calloc(size_t num, size_t size)
 
 
 #ifndef XMRIG_NO_AEON
-cryptonight_ctx *Mem::createLite(int threadId, bool doubleHash) {
+cryptonight_ctx *Mem::createLite(int threadId) {
     cryptonight_ctx *ctx;
 
-    if (!doubleHash) {
+    if (!m_doubleHash) {
         const size_t offset = MEMORY * (threadId + 1);
 
         ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[offset + MEMORY_LITE]);
diff --git a/src/Mem.h b/src/Mem.h
index ac89c363b..9a438a175 100644
--- a/src/Mem.h
+++ b/src/Mem.h
@@ -41,7 +41,7 @@ public:
     };
 
     static bool allocate(int algo, int threads, bool doubleHash);
-    static cryptonight_ctx *create(int algo, int threadId, bool doubleHash);
+    static cryptonight_ctx *create(int threadId);
     static void *calloc(size_t num, size_t size);
     static void release();
 
@@ -58,7 +58,7 @@ private:
     static uint8_t *m_memory __attribute__((aligned(16)));
 
 #   ifndef XMRIG_NO_AEON
-    static cryptonight_ctx *createLite(int threadId, bool doubleHash);
+    static cryptonight_ctx *createLite(int threadId);
 #   endif
 };
 
diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp
index 18b54ba35..f9a7ab3db 100644
--- a/src/Mem_win.cpp
+++ b/src/Mem_win.cpp
@@ -143,6 +143,10 @@ static BOOL TrySetLockPagesPrivilege() {
 
 bool Mem::allocate(int algo, int threads, bool doubleHash)
 {
+    m_algo       = algo;
+    m_threads    = threads;
+    m_doubleHash = doubleHash;
+
     const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
     const size_t size  = MEMORY * (threads * ratio + 1);
 
diff --git a/src/interfaces/IWorker.h b/src/interfaces/IWorker.h
new file mode 100644
index 000000000..f9010a2f3
--- /dev/null
+++ b/src/interfaces/IWorker.h
@@ -0,0 +1,37 @@
+/* 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/>.
+ */
+
+#ifndef __IWORKER_H__
+#define __IWORKER_H__
+
+
+class IWorker
+{
+public:
+    virtual ~IWorker() {}
+
+    virtual void start() = 0;
+};
+
+
+#endif // __IWORKER_H__
diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp
new file mode 100644
index 000000000..6c1f5553b
--- /dev/null
+++ b/src/workers/Handle.cpp
@@ -0,0 +1,39 @@
+/* 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 "workers/Handle.h"
+
+
+Handle::Handle(int id) :
+    m_id(id),
+    m_worker(nullptr)
+{
+}
+
+
+void Handle::start(void *(*callback) (void *))
+{
+    pthread_create(&m_thread, nullptr, callback, this);
+//    m_thread = std::thread([]() {});
+}
diff --git a/src/workers/Handle.h b/src/workers/Handle.h
new file mode 100644
index 000000000..e697a6180
--- /dev/null
+++ b/src/workers/Handle.h
@@ -0,0 +1,50 @@
+/* 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/>.
+ */
+
+#ifndef __HANDLE_H__
+#define __HANDLE_H__
+
+
+#include <pthread.h>
+
+
+class IWorker;
+
+
+class Handle
+{
+public:
+    Handle(int id);
+    void start(void *(*callback) (void *));
+
+    inline int id() const                  { return m_id; }
+    inline void setWorker(IWorker *worker) { m_worker = worker; }
+
+private:
+    int m_id;
+    IWorker *m_worker;
+    pthread_t m_thread;
+};
+
+
+#endif /* __HANDLE_H__ */
diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp
new file mode 100644
index 000000000..d9a8f8a61
--- /dev/null
+++ b/src/workers/SingleWorker.cpp
@@ -0,0 +1,35 @@
+/* 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 <pthread.h>
+
+#include "Console.h"
+#include "workers/SingleWorker.h"
+
+
+SingleWorker::SingleWorker(Handle *handle)
+    : Worker(handle)
+{
+    LOG_WARN("SingleWorker %d", pthread_self());
+}
diff --git a/src/workers/SingleWorker.h b/src/workers/SingleWorker.h
new file mode 100644
index 000000000..830c6f396
--- /dev/null
+++ b/src/workers/SingleWorker.h
@@ -0,0 +1,41 @@
+/* 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/>.
+ */
+
+#ifndef __SINGLEWORKER_H__
+#define __SINGLEWORKER_H__
+
+
+#include "workers/Worker.h"
+
+
+class Handle;
+
+
+class SingleWorker : public Worker
+{
+public:
+    SingleWorker(Handle *handle);
+};
+
+
+#endif /* __SINGLEWORKER_H__ */
diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp
new file mode 100644
index 000000000..3e42d1bda
--- /dev/null
+++ b/src/workers/Worker.cpp
@@ -0,0 +1,48 @@
+/* XMRig
+ * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
+ * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
+ * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
+ * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
+ * Copyright 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 "workers/Handle.h"
+#include "workers/Worker.h"
+#include "Mem.h"
+
+
+Worker::Worker(Handle *handle) :
+    m_handle(handle),
+    m_id(handle->id())
+{
+    m_handle->setWorker(this);
+
+    m_ctx = Mem::create(m_id);
+}
+
+
+Worker::~Worker()
+{
+}
+
+
+void Worker::start()
+{
+
+}
diff --git a/src/workers/Worker.h b/src/workers/Worker.h
new file mode 100644
index 000000000..c24fa5736
--- /dev/null
+++ b/src/workers/Worker.h
@@ -0,0 +1,50 @@
+/* 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/>.
+ */
+
+#ifndef __WORKER_H__
+#define __WORKER_H__
+
+
+#include "interfaces/IWorker.h"
+
+
+struct cryptonight_ctx;
+class Handle;
+
+
+class Worker : public IWorker
+{
+public:
+    Worker(Handle *handle);
+    ~Worker();
+
+    void start() override;
+
+protected:
+    cryptonight_ctx *m_ctx;
+    Handle *m_handle;
+    int m_id;
+};
+
+
+#endif /* __WORKER_H__ */

From f9c244f0aa3a1cf132cfad34b1c79792d63c9162 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Sat, 10 Jun 2017 09:41:08 +0300
Subject: [PATCH 32/56] Add Workers class.

---
 CMakeLists.txt               |  4 +-
 src/App.cpp                  | 25 +------------
 src/App.h                    |  9 -----
 src/workers/Handle.cpp       |  1 -
 src/workers/SingleWorker.cpp |  9 +++++
 src/workers/SingleWorker.h   |  2 +
 src/workers/Worker.cpp       |  6 ---
 src/workers/Worker.h         |  2 -
 src/workers/Workers.cpp      | 72 ++++++++++++++++++++++++++++++++++++
 src/workers/Workers.h        | 50 +++++++++++++++++++++++++
 10 files changed, 138 insertions(+), 42 deletions(-)
 create mode 100644 src/workers/Workers.cpp
 create mode 100644 src/workers/Workers.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e91fae3c0..801b33bb1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,6 +20,7 @@ set(HEADERS
     src/workers/Handle.h
     src/workers/SingleWorker.h
     src/workers/Worker.h
+    src/workers/Workers.h
     src/version.h
    )
 
@@ -50,6 +51,7 @@ set(SOURCES
     src/workers/Handle.cpp
     src/workers/SingleWorker.cpp
     src/workers/Worker.cpp
+    src/workers/Workers.cpp
     src/xmrig.cpp
    )
 
@@ -95,7 +97,7 @@ endif()
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall -fno-exceptions")
 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions -fno-rtti")
 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate")
diff --git a/src/App.cpp b/src/App.cpp
index 943690ec7..1a4f6d069 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -35,8 +35,7 @@
 #include "Options.h"
 #include "Summary.h"
 #include "version.h"
-#include "workers/Handle.h"
-#include "workers/SingleWorker.h"
+#include "workers/Workers.h"
 
 
 
@@ -75,7 +74,7 @@ App::exec()
     Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash());
     Summary::print();
 
-    startWorders();
+    Workers::start(m_options->threads());
 
     m_network->connect();
 
@@ -84,23 +83,3 @@ App::exec()
 
     return r;
 }
-
-
-void App::startWorders()
-{
-    for (int i = 0; i < m_options->threads(); ++i) {
-        Handle *handle = new Handle(i);
-        m_workers.push_back(handle);
-        handle->start(App::onWorkerStarted);
-    }
-}
-
-
-void *App::onWorkerStarted(void *arg)
-{
-    auto handle = static_cast<Handle*>(arg);
-    IWorker *worker = new SingleWorker(handle);
-    worker->start();
-
-    return nullptr;
-}
diff --git a/src/App.h b/src/App.h
index 25d91890b..b2d5e5f00 100644
--- a/src/App.h
+++ b/src/App.h
@@ -25,10 +25,6 @@
 #define __APP_H__
 
 
-#include <vector>
-
-
-class Handle;
 class Network;
 class Options;
 
@@ -42,13 +38,8 @@ public:
   int exec();
 
 private:
-  void startWorders();
-
-  static void* onWorkerStarted(void *arg);
-
   Network *m_network;
   Options *m_options;
-  std::vector<Handle*> m_workers;
 };
 
 
diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp
index 6c1f5553b..527b5d6de 100644
--- a/src/workers/Handle.cpp
+++ b/src/workers/Handle.cpp
@@ -35,5 +35,4 @@ Handle::Handle(int id) :
 void Handle::start(void *(*callback) (void *))
 {
     pthread_create(&m_thread, nullptr, callback, this);
-//    m_thread = std::thread([]() {});
 }
diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp
index d9a8f8a61..95eb41572 100644
--- a/src/workers/SingleWorker.cpp
+++ b/src/workers/SingleWorker.cpp
@@ -22,10 +22,13 @@
  */
 
 
+#include <thread>
 #include <pthread.h>
 
+
 #include "Console.h"
 #include "workers/SingleWorker.h"
+#include "workers/Workers.h"
 
 
 SingleWorker::SingleWorker(Handle *handle)
@@ -33,3 +36,9 @@ SingleWorker::SingleWorker(Handle *handle)
 {
     LOG_WARN("SingleWorker %d", pthread_self());
 }
+
+
+void SingleWorker::start()
+{
+//    Workers::submit();
+}
diff --git a/src/workers/SingleWorker.h b/src/workers/SingleWorker.h
index 830c6f396..1c569d977 100644
--- a/src/workers/SingleWorker.h
+++ b/src/workers/SingleWorker.h
@@ -35,6 +35,8 @@ class SingleWorker : public Worker
 {
 public:
     SingleWorker(Handle *handle);
+
+    void start() override;
 };
 
 
diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp
index 3e42d1bda..24f275e94 100644
--- a/src/workers/Worker.cpp
+++ b/src/workers/Worker.cpp
@@ -40,9 +40,3 @@ Worker::Worker(Handle *handle) :
 Worker::~Worker()
 {
 }
-
-
-void Worker::start()
-{
-
-}
diff --git a/src/workers/Worker.h b/src/workers/Worker.h
index c24fa5736..e68534ae8 100644
--- a/src/workers/Worker.h
+++ b/src/workers/Worker.h
@@ -38,8 +38,6 @@ public:
     Worker(Handle *handle);
     ~Worker();
 
-    void start() override;
-
 protected:
     cryptonight_ctx *m_ctx;
     Handle *m_handle;
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
new file mode 100644
index 000000000..004d49b61
--- /dev/null
+++ b/src/workers/Workers.cpp
@@ -0,0 +1,72 @@
+/* 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 <pthread.h>
+
+
+#include "Console.h"
+#include "workers/Handle.h"
+#include "workers/SingleWorker.h"
+#include "workers/Workers.h"
+
+
+std::vector<Handle*> Workers::m_workers;
+uv_async_t Workers::m_async;
+
+
+void Workers::start(int threads)
+{
+    LOG_NOTICE("start %d", pthread_self());
+
+    uv_async_init(uv_default_loop(), &m_async, Workers::onResult);
+
+    for (int i = 0; i < threads; ++i) {
+        Handle *handle = new Handle(i);
+        m_workers.push_back(handle);
+        handle->start(Workers::onReady);
+    }
+}
+
+
+void Workers::submit()
+{
+    uv_async_send(&m_async);
+}
+
+
+
+void *Workers::onReady(void *arg)
+{
+    auto handle = static_cast<Handle*>(arg);
+    IWorker *worker = new SingleWorker(handle);
+    worker->start();
+
+    return nullptr;
+}
+
+
+
+void Workers::onResult(uv_async_t *handle)
+{
+}
diff --git a/src/workers/Workers.h b/src/workers/Workers.h
new file mode 100644
index 000000000..48485770d
--- /dev/null
+++ b/src/workers/Workers.h
@@ -0,0 +1,50 @@
+/* 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/>.
+ */
+
+#ifndef __WORKERS_H__
+#define __WORKERS_H__
+
+
+#include <vector>
+#include <uv.h>
+
+
+class Handle;
+
+
+class Workers
+{
+public:
+    static void start(int threads);
+    static void submit();
+
+private:
+    static void *onReady(void *arg);
+    static void onResult(uv_async_t *handle);
+
+    static std::vector<Handle*> m_workers;
+    static uv_async_t m_async;
+};
+
+
+#endif /* __WORKERS_H__ */

From bcef4b12ec70d6c039379718d450f3e291f0b0ee Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Sat, 10 Jun 2017 13:32:27 +0300
Subject: [PATCH 33/56] Job flow.

---
 src/net/Client.cpp      |  6 +++++-
 src/net/Client.h        |  2 ++
 src/net/Job.cpp         |  3 ++-
 src/net/Job.h           | 12 ++++++++----
 src/net/Network.cpp     | 27 ++++++++++++++++++++++++++-
 src/net/Network.h       |  2 ++
 src/workers/Workers.cpp |  1 -
 7 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index 8fdf09e98..91f582a00 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -22,6 +22,9 @@
  */
 
 
+#include <utility>
+
+
 #include "Console.h"
 #include "interfaces/IClientListener.h"
 #include "net/Client.h"
@@ -168,7 +171,8 @@ bool Client::parseJob(const json_t *params, int *code)
         return false;
     }
 
-    m_job = job;
+    job.setPoolId(m_id);
+    m_job = std::move(job);
 
     LOG_DEBUG("[%s:%u] job: \"%s\", diff: %lld", m_host, m_port, job.id(), job.diff());
     return true;
diff --git a/src/net/Client.h b/src/net/Client.h
index 6110488d0..b46a8bf07 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -60,7 +60,9 @@ public:
     void send(char *data);
     void setUrl(const Url *url);
 
+    inline bool isReady() const              { return m_state == ConnectedState && m_failures == 0; }
     inline const char *host() const          { return m_host; }
+    inline const Job &job() const            { return m_job; }
     inline int id() const                    { return m_id; }
     inline SocketState state() const         { return m_state; }
     inline uint16_t port() const             { return m_port; }
diff --git a/src/net/Job.cpp b/src/net/Job.cpp
index 65feabb7b..52123485f 100644
--- a/src/net/Job.cpp
+++ b/src/net/Job.cpp
@@ -57,7 +57,8 @@ static inline char hf_bin2hex(unsigned char c)
 }
 
 
-Job::Job() :
+Job::Job(int poolId) :
+    m_poolId(poolId),
     m_size(0),
     m_diff(0),
     m_target(0)
diff --git a/src/net/Job.h b/src/net/Job.h
index d213ec34a..4dc186503 100644
--- a/src/net/Job.h
+++ b/src/net/Job.h
@@ -31,22 +31,26 @@
 class Job
 {
 public:
-    Job();
+    Job(int poolId = -2);
     bool setBlob(const char *blob);
     bool setId(const char *id);
     bool setTarget(const char *target);
 
-    inline const uint8_t *blob() const { return m_blob; }
+    inline bool isValid() const        { return m_size > 0 && m_diff > 0; }
     inline const char *id() const      { return m_id; }
-    inline uint32_t size() const       { return m_size; }
+    inline const uint8_t *blob() const { return m_blob; }
+    inline int poolId() const          { return m_poolId; }
     inline uint32_t diff() const       { return m_diff; }
+    inline uint32_t size() const       { return m_size; }
     inline uint64_t target() const     { return m_target; }
+    inline void setPoolId(int poolId)  { m_poolId = poolId; }
 
     static bool fromHex(const char* in, unsigned int len, unsigned char* out);
     static void toHex(const unsigned char* in, unsigned int len, char* out);
-    inline static uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
+    static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
 
 private:
+    int m_poolId;
     char m_id[64]      __attribute__((aligned(16)));
     uint8_t m_blob[84] __attribute__((aligned(16))); // 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;
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index d513fddae..c6862e3bd 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -35,7 +35,8 @@
 Network::Network(const Options *options) :
     m_donate(false),
     m_options(options),
-    m_pool(0)
+    m_pool(0),
+    m_diff(0)
 {
     m_pools.reserve(2);
     m_agent = userAgent();
@@ -92,7 +93,11 @@ void Network::onClose(Client *client, int failures)
 
 void Network::onJobReceived(Client *client, const Job &job)
 {
+    if (m_donate && client->id() != 0) {
+        return;
+    }
 
+    setJob(client, job);
 }
 
 
@@ -138,6 +143,18 @@ void Network::addPool(const Url *url)
 }
 
 
+void Network::setJob(Client *client, const Job &job)
+{
+    if (m_options->colors()){
+        LOG_INFO("\x1B[01;33mnew job\x1B[0m from \"%s:%d\", diff: %d", client->host(), client->port(), job.diff());
+
+    }
+    else {
+        LOG_INFO("new job from \"%s:%d\", diff: %d", client->host(), client->port(), job.diff());
+    }
+}
+
+
 void Network::startDonate()
 {
     if (m_donate) {
@@ -159,6 +176,14 @@ void Network::stopDonate()
     LOG_NOTICE("dev donate finished");
 
     m_donate = false;
+    if (!m_pool) {
+        return;
+    }
+
+    Client *client = m_pools[m_pool];
+    if (client->isReady()) {
+        setJob(client, client->job());
+    }
 }
 
 
diff --git a/src/net/Network.h b/src/net/Network.h
index c8191a6ea..af1ddbbfd 100644
--- a/src/net/Network.h
+++ b/src/net/Network.h
@@ -54,6 +54,7 @@ protected:
 
 private:
   void addPool(const Url *url);
+  void setJob(Client *client, const Job &job);
   void startDonate();
   void stopDonate();
 
@@ -64,6 +65,7 @@ private:
   const Options *m_options;
   int m_pool;
   std::vector<Client*> m_pools;
+  uint64_t m_diff;
   uv_timer_t m_timer;
 };
 
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
index 004d49b61..b9dbc484a 100644
--- a/src/workers/Workers.cpp
+++ b/src/workers/Workers.cpp
@@ -30,7 +30,6 @@
 #include "workers/SingleWorker.h"
 #include "workers/Workers.h"
 
-
 std::vector<Handle*> Workers::m_workers;
 uv_async_t Workers::m_async;
 

From 3ad11685cca13791ab3daec98e2223454757b20a Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Sun, 11 Jun 2017 06:52:23 +0300
Subject: [PATCH 34/56] Job flow WIP.

---
 CMakeLists.txt               |  2 +-
 src/App.cpp                  |  2 +-
 src/Console.cpp              | 10 +++++-----
 src/Console.h                |  4 ++--
 src/net/Job.h                |  1 +
 src/net/Network.cpp          |  4 ++++
 src/workers/Handle.cpp       |  6 ++++--
 src/workers/Handle.h         | 11 ++++++++---
 src/workers/SingleWorker.cpp | 33 +++++++++++++++++++++++++++++++-
 src/workers/SingleWorker.h   |  6 ++++++
 src/workers/Worker.cpp       | 10 ++++++++--
 src/workers/Worker.h         |  5 +++++
 src/workers/Workers.cpp      | 37 ++++++++++++++++++++++++++++++------
 src/workers/Workers.h        | 20 +++++++++++++++++--
 14 files changed, 126 insertions(+), 25 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 801b33bb1..c22bf1764 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -84,7 +84,7 @@ endif()
 
 add_definitions(/D_GNU_SOURCE)
 add_definitions(/DUNICODE)
-add_definitions(/DAPP_DEBUG)
+#add_definitions(/DAPP_DEBUG)
 
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
 
diff --git a/src/App.cpp b/src/App.cpp
index 1a4f6d069..4078f4b7b 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -74,7 +74,7 @@ App::exec()
     Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash());
     Summary::print();
 
-    Workers::start(m_options->threads());
+    Workers::start(m_options->threads(), m_options->affinity(), m_options->nicehash());
 
     m_network->connect();
 
diff --git a/src/Console.cpp b/src/Console.cpp
index f57a71411..fd4ff4a5a 100644
--- a/src/Console.cpp
+++ b/src/Console.cpp
@@ -97,12 +97,12 @@ void Console::message(Console::Level level, const char* fmt, ...)
             m_colors ? kCL_N : ""
         );
 
-    uv_mutex_lock(&m_mutex);
+    pthread_mutex_lock(&m_mutex);
 
     vfprintf(stdout, buf, ap);
     fflush(stdout);
 
-    uv_mutex_unlock(&m_mutex);
+    pthread_mutex_unlock(&m_mutex);
 
     va_end(ap);
 }
@@ -121,12 +121,12 @@ void Console::text(const char* fmt, ...)
             m_colors ? kCL_N : ""
         );
 
-    uv_mutex_lock(&m_mutex);
+    pthread_mutex_lock(&m_mutex);
 
     vfprintf(stdout, buf, ap);
     fflush(stdout);
 
-    uv_mutex_unlock(&m_mutex);
+    pthread_mutex_unlock(&m_mutex);
 
     va_end(ap);
 }
@@ -135,5 +135,5 @@ void Console::text(const char* fmt, ...)
 Console::Console() :
     m_colors(true)
 {
-    uv_mutex_init(&m_mutex);
+    pthread_mutex_init(&m_mutex, nullptr);
 }
diff --git a/src/Console.h b/src/Console.h
index 73e047061..edd5ae8ca 100644
--- a/src/Console.h
+++ b/src/Console.h
@@ -25,7 +25,7 @@
 #define __CONSOLE_H__
 
 
-#include <uv.h>
+#include <pthread.h>
 
 
 class Console
@@ -61,7 +61,7 @@ private:
 
     static Console *m_self;
     bool m_colors;
-    uv_mutex_t m_mutex;
+    pthread_mutex_t m_mutex;
 };
 
 
diff --git a/src/net/Job.h b/src/net/Job.h
index 4dc186503..4f08e84cf 100644
--- a/src/net/Job.h
+++ b/src/net/Job.h
@@ -40,6 +40,7 @@ public:
     inline const char *id() const      { return m_id; }
     inline const uint8_t *blob() const { return m_blob; }
     inline int poolId() const          { return m_poolId; }
+    inline uint32_t *nonce()           { return reinterpret_cast<uint32_t*>(m_blob + 39); }
     inline uint32_t diff() const       { return m_diff; }
     inline uint32_t size() const       { return m_size; }
     inline uint64_t target() const     { return m_target; }
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index c6862e3bd..02c68fd1b 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -30,6 +30,7 @@
 #include "net/Network.h"
 #include "net/Url.h"
 #include "Options.h"
+#include "workers/Workers.h"
 
 
 Network::Network(const Options *options) :
@@ -83,6 +84,7 @@ void Network::onClose(Client *client, int failures)
 
     if (m_pool == id) {
         m_pool = 0;
+        Workers::pause();
     }
 
     if (id == 1 && m_pools.size() > 2 && failures == m_options->retries()) {
@@ -152,6 +154,8 @@ void Network::setJob(Client *client, const Job &job)
     else {
         LOG_INFO("new job from \"%s:%d\", diff: %d", client->host(), client->port(), job.diff());
     }
+
+    Workers::setJob(job);
 }
 
 
diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp
index 527b5d6de..6e4d78ed0 100644
--- a/src/workers/Handle.cpp
+++ b/src/workers/Handle.cpp
@@ -25,8 +25,10 @@
 #include "workers/Handle.h"
 
 
-Handle::Handle(int id) :
-    m_id(id),
+Handle::Handle(int threadId, int64_t affinity, bool nicehash) :
+    m_nicehash(nicehash),
+    m_threadId(threadId),
+    m_affinity(affinity),
     m_worker(nullptr)
 {
 }
diff --git a/src/workers/Handle.h b/src/workers/Handle.h
index e697a6180..59bd47931 100644
--- a/src/workers/Handle.h
+++ b/src/workers/Handle.h
@@ -26,6 +26,7 @@
 
 
 #include <pthread.h>
+#include <stdint.h>
 
 
 class IWorker;
@@ -34,14 +35,18 @@ class IWorker;
 class Handle
 {
 public:
-    Handle(int id);
+    Handle(int threadId, int64_t affinity, bool nicehash);
     void start(void *(*callback) (void *));
 
-    inline int id() const                  { return m_id; }
+    inline bool nicehash() const           { return m_nicehash; }
+    inline int threadId() const            { return m_threadId; }
+    inline int64_t affinity() const        { return m_affinity; }
     inline void setWorker(IWorker *worker) { m_worker = worker; }
 
 private:
-    int m_id;
+    bool m_nicehash;
+    int m_threadId;
+    int64_t m_affinity;
     IWorker *m_worker;
     pthread_t m_thread;
 };
diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp
index 95eb41572..eacab9411 100644
--- a/src/workers/SingleWorker.cpp
+++ b/src/workers/SingleWorker.cpp
@@ -22,6 +22,7 @@
  */
 
 
+#include <atomic>
 #include <thread>
 #include <pthread.h>
 
@@ -40,5 +41,35 @@ SingleWorker::SingleWorker(Handle *handle)
 
 void SingleWorker::start()
 {
-//    Workers::submit();
+    while (true) {
+        if (Workers::isPaused()) {
+            do {
+                LOG_ERR("SLEEP WAIT FOR WORK");
+                std::this_thread::sleep_for(std::chrono::milliseconds(200));
+            }
+            while (Workers::isPaused());
+
+            consumeJob();
+        }
+
+        while (!Workers::isOutdated(m_sequence)) {
+            LOG_ERR("WORK %lld %lld", Workers::sequence(), m_sequence);
+
+            std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+
+            sched_yield();
+        }
+
+        consumeJob();
+    }
+}
+
+
+
+void SingleWorker::consumeJob()
+{
+    m_job = Workers::job();
+    m_sequence = Workers::sequence();
+
+    LOG_WARN("consumeJob");
 }
diff --git a/src/workers/SingleWorker.h b/src/workers/SingleWorker.h
index 1c569d977..9820172cb 100644
--- a/src/workers/SingleWorker.h
+++ b/src/workers/SingleWorker.h
@@ -25,6 +25,7 @@
 #define __SINGLEWORKER_H__
 
 
+#include "net/Job.h"
 #include "workers/Worker.h"
 
 
@@ -37,6 +38,11 @@ public:
     SingleWorker(Handle *handle);
 
     void start() override;
+
+private:
+    void consumeJob();
+
+    Job m_job;
 };
 
 
diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp
index 24f275e94..1756dbc16 100644
--- a/src/workers/Worker.cpp
+++ b/src/workers/Worker.cpp
@@ -22,17 +22,23 @@
  */
 
 
+#include "Cpu.h"
+#include "Mem.h"
 #include "workers/Handle.h"
 #include "workers/Worker.h"
-#include "Mem.h"
 
 
 Worker::Worker(Handle *handle) :
+    m_nicehash(handle->nicehash()),
     m_handle(handle),
-    m_id(handle->id())
+    m_id(handle->threadId())
 {
     m_handle->setWorker(this);
 
+    if (Cpu::threads() > 1 && m_handle->affinity() != -1L) {
+        Cpu::setAffinity(m_id, m_handle->affinity());
+    }
+
     m_ctx = Mem::create(m_id);
 }
 
diff --git a/src/workers/Worker.h b/src/workers/Worker.h
index e68534ae8..f62083d0b 100644
--- a/src/workers/Worker.h
+++ b/src/workers/Worker.h
@@ -25,6 +25,9 @@
 #define __WORKER_H__
 
 
+#include <stdint.h>
+
+
 #include "interfaces/IWorker.h"
 
 
@@ -39,9 +42,11 @@ public:
     ~Worker();
 
 protected:
+    bool m_nicehash;
     cryptonight_ctx *m_ctx;
     Handle *m_handle;
     int m_id;
+    uint64_t m_sequence;
 };
 
 
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
index b9dbc484a..1916be72e 100644
--- a/src/workers/Workers.cpp
+++ b/src/workers/Workers.cpp
@@ -21,27 +21,52 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-
-#include <pthread.h>
-
-
 #include "Console.h"
 #include "workers/Handle.h"
 #include "workers/SingleWorker.h"
 #include "workers/Workers.h"
 
+
+Job Workers::m_job;
+pthread_rwlock_t Workers::m_rwlock;
+std::atomic<int> Workers::m_paused;
+std::atomic<uint64_t> Workers::m_sequence;
 std::vector<Handle*> Workers::m_workers;
 uv_async_t Workers::m_async;
 
 
-void Workers::start(int threads)
+Job Workers::job()
+{
+    pthread_rwlock_rdlock(&m_rwlock);
+    Job job = m_job;
+    pthread_rwlock_unlock(&m_rwlock);
+
+    return std::move(job);
+}
+
+
+void Workers::setJob(const Job &job)
+{
+    pthread_rwlock_wrlock(&m_rwlock);
+    m_job = job;
+    pthread_rwlock_unlock(&m_rwlock);
+
+    m_sequence++;
+    m_paused = 0;
+}
+
+
+void Workers::start(int threads, int64_t affinity, bool nicehash)
 {
     LOG_NOTICE("start %d", pthread_self());
 
+    m_sequence = 0;
+    m_paused   = 1;
+
     uv_async_init(uv_default_loop(), &m_async, Workers::onResult);
 
     for (int i = 0; i < threads; ++i) {
-        Handle *handle = new Handle(i);
+        Handle *handle = new Handle(i, affinity, nicehash);
         m_workers.push_back(handle);
         handle->start(Workers::onReady);
     }
diff --git a/src/workers/Workers.h b/src/workers/Workers.h
index 48485770d..7d6328cad 100644
--- a/src/workers/Workers.h
+++ b/src/workers/Workers.h
@@ -25,8 +25,13 @@
 #define __WORKERS_H__
 
 
-#include <vector>
+#include <atomic>
+#include <pthread.h>
 #include <uv.h>
+#include <vector>
+
+
+#include "net/Job.h"
 
 
 class Handle;
@@ -35,13 +40,24 @@ class Handle;
 class Workers
 {
 public:
-    static void start(int threads);
+    static Job job();
+    static void setJob(const Job &job);
+    static void start(int threads, int64_t affinity, bool nicehash);
     static void submit();
 
+    static inline bool isOutdated(uint64_t sequence) { return m_sequence.load(std::memory_order_relaxed) != sequence; }
+    static inline bool isPaused()                    { return m_paused.load(std::memory_order_relaxed) == 1; }
+    static inline uint64_t sequence()                { return m_sequence.load(std::memory_order_relaxed); }
+    static inline void pause()                       { m_paused = 1; }
+
 private:
     static void *onReady(void *arg);
     static void onResult(uv_async_t *handle);
 
+    static Job m_job;
+    static pthread_rwlock_t m_rwlock;
+    static std::atomic<int> m_paused;
+    static std::atomic<uint64_t> m_sequence;
     static std::vector<Handle*> m_workers;
     static uv_async_t m_async;
 };

From a0a8711dab60b32340f6f5bd904a1395ebc9c2cb Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Sun, 11 Jun 2017 10:58:46 +0300
Subject: [PATCH 35/56] Add class JobResult.

---
 CMakeLists.txt               |  5 +++--
 src/crypto/CryptoNight.cpp   | 10 +++++++++
 src/crypto/CryptoNight.h     |  5 +++++
 src/net/JobResult.h          | 40 ++++++++++++++++++++++++++++++++++++
 src/workers/Handle.cpp       |  3 ++-
 src/workers/Handle.h         |  4 +++-
 src/workers/SingleWorker.cpp | 21 +++++++++++++------
 src/workers/SingleWorker.h   |  2 ++
 src/workers/Worker.cpp       | 12 ++++++-----
 src/workers/Worker.h         |  3 ++-
 src/workers/Workers.cpp      | 22 ++++++++++++++++----
 src/workers/Workers.h        |  7 +++++--
 12 files changed, 112 insertions(+), 22 deletions(-)
 create mode 100644 src/net/JobResult.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c22bf1764..15c1d35da 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,7 @@ set(HEADERS
     src/Mem.h
     src/net/Client.h
     src/net/Job.h
+    src/net/JobResult.h
     src/net/Network.h
     src/net/Url.h
     src/Options.h
@@ -84,7 +85,7 @@ endif()
 
 add_definitions(/D_GNU_SOURCE)
 add_definitions(/DUNICODE)
-#add_definitions(/DAPP_DEBUG)
+add_definitions(/DAPP_DEBUG)
 
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
 
@@ -99,7 +100,7 @@ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvari
 
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions -fno-rtti")
 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
-#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2")
+#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate")
 #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-use -fprofile-correction")
 
diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp
index b6273dc52..e19e66ca5 100644
--- a/src/crypto/CryptoNight.cpp
+++ b/src/crypto/CryptoNight.cpp
@@ -25,6 +25,8 @@
 #include "crypto/CryptoNight.h"
 #include "crypto/CryptoNight_p.h"
 #include "crypto/CryptoNight_test.h"
+#include "net/Job.h"
+#include "net/JobResult.h"
 #include "Options.h"
 
 
@@ -91,6 +93,14 @@ void (*cryptonight_variations[4])(const void *input, size_t size, void *output,
 #endif
 
 
+bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx)
+{
+    cryptonight_hash_ctx(job.blob(), job.size(), result.result, ctx);
+
+    return *reinterpret_cast<uint64_t*>(result.result + 24) < job.target();
+}
+
+
 bool CryptoNight::init(int algo, int variant)
 {
     if (variant < 1 || variant > 4) {
diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h
index ce1b7ba83..fbb2f9753 100644
--- a/src/crypto/CryptoNight.h
+++ b/src/crypto/CryptoNight.h
@@ -39,9 +39,14 @@ struct cryptonight_ctx {
 };
 
 
+class Job;
+class JobResult;
+
+
 class CryptoNight
 {
 public:
+    static bool hash(const Job &job, JobResult &result, cryptonight_ctx *ctx);
     static bool init(int algo, int variant);
 
 private:
diff --git a/src/net/JobResult.h b/src/net/JobResult.h
new file mode 100644
index 000000000..ba067cdc2
--- /dev/null
+++ b/src/net/JobResult.h
@@ -0,0 +1,40 @@
+/* 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/>.
+ */
+
+#ifndef __JOBRESULT_H__
+#define __JOBRESULT_H__
+
+
+#include <stdint.h>
+
+
+class JobResult
+{
+public:
+    char jobId[64];
+    int poolId;
+    uint32_t nonce;
+    uint8_t result[32];
+};
+
+#endif /* __JOBRESULT_H__ */
diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp
index 6e4d78ed0..76fea5883 100644
--- a/src/workers/Handle.cpp
+++ b/src/workers/Handle.cpp
@@ -25,9 +25,10 @@
 #include "workers/Handle.h"
 
 
-Handle::Handle(int threadId, int64_t affinity, bool nicehash) :
+Handle::Handle(int threadId, int threads, int64_t affinity, bool nicehash) :
     m_nicehash(nicehash),
     m_threadId(threadId),
+    m_threads(threads),
     m_affinity(affinity),
     m_worker(nullptr)
 {
diff --git a/src/workers/Handle.h b/src/workers/Handle.h
index 59bd47931..a8ad84c19 100644
--- a/src/workers/Handle.h
+++ b/src/workers/Handle.h
@@ -35,17 +35,19 @@ class IWorker;
 class Handle
 {
 public:
-    Handle(int threadId, int64_t affinity, bool nicehash);
+    Handle(int threadId, int threads, int64_t affinity, bool nicehash);
     void start(void *(*callback) (void *));
 
     inline bool nicehash() const           { return m_nicehash; }
     inline int threadId() const            { return m_threadId; }
+    inline int threads() const             { return m_threads; }
     inline int64_t affinity() const        { return m_affinity; }
     inline void setWorker(IWorker *worker) { m_worker = worker; }
 
 private:
     bool m_nicehash;
     int m_threadId;
+    int m_threads;
     int64_t m_affinity;
     IWorker *m_worker;
     pthread_t m_thread;
diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp
index eacab9411..c102029c4 100644
--- a/src/workers/SingleWorker.cpp
+++ b/src/workers/SingleWorker.cpp
@@ -24,10 +24,10 @@
 
 #include <atomic>
 #include <thread>
-#include <pthread.h>
 
 
 #include "Console.h"
+#include "crypto/CryptoNight.h"
 #include "workers/SingleWorker.h"
 #include "workers/Workers.h"
 
@@ -35,7 +35,6 @@
 SingleWorker::SingleWorker(Handle *handle)
     : Worker(handle)
 {
-    LOG_WARN("SingleWorker %d", pthread_self());
 }
 
 
@@ -44,7 +43,6 @@ void SingleWorker::start()
     while (true) {
         if (Workers::isPaused()) {
             do {
-                LOG_ERR("SLEEP WAIT FOR WORK");
                 std::this_thread::sleep_for(std::chrono::milliseconds(200));
             }
             while (Workers::isPaused());
@@ -53,9 +51,12 @@ void SingleWorker::start()
         }
 
         while (!Workers::isOutdated(m_sequence)) {
-            LOG_ERR("WORK %lld %lld", Workers::sequence(), m_sequence);
+            m_count++;
+            *m_job.nonce() = ++m_result.nonce;
 
-            std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+            if (CryptoNight::hash(m_job, m_result, m_ctx)) {
+                Workers::submit(m_result);
+            }
 
             sched_yield();
         }
@@ -71,5 +72,13 @@ void SingleWorker::consumeJob()
     m_job = Workers::job();
     m_sequence = Workers::sequence();
 
-    LOG_WARN("consumeJob");
+    memcpy(m_result.jobId, m_job.id(), sizeof(m_result.jobId));
+    m_result.poolId = m_job.poolId();
+
+    if (m_nicehash) {
+        m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_threads * m_id);
+    }
+    else {
+        m_result.nonce = 0xffffffffU / m_threads * m_id;
+    }
 }
diff --git a/src/workers/SingleWorker.h b/src/workers/SingleWorker.h
index 9820172cb..6ba59468a 100644
--- a/src/workers/SingleWorker.h
+++ b/src/workers/SingleWorker.h
@@ -26,6 +26,7 @@
 
 
 #include "net/Job.h"
+#include "net/JobResult.h"
 #include "workers/Worker.h"
 
 
@@ -43,6 +44,7 @@ private:
     void consumeJob();
 
     Job m_job;
+    JobResult m_result;
 };
 
 
diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp
index 1756dbc16..d39ebdc32 100644
--- a/src/workers/Worker.cpp
+++ b/src/workers/Worker.cpp
@@ -30,13 +30,15 @@
 
 Worker::Worker(Handle *handle) :
     m_nicehash(handle->nicehash()),
-    m_handle(handle),
-    m_id(handle->threadId())
+    m_id(handle->threadId()),
+    m_threads(handle->threads()),
+    m_count(0),
+    m_sequence(0)
 {
-    m_handle->setWorker(this);
+    handle->setWorker(this);
 
-    if (Cpu::threads() > 1 && m_handle->affinity() != -1L) {
-        Cpu::setAffinity(m_id, m_handle->affinity());
+    if (Cpu::threads() > 1 && handle->affinity() != -1L) {
+        Cpu::setAffinity(m_id, handle->affinity());
     }
 
     m_ctx = Mem::create(m_id);
diff --git a/src/workers/Worker.h b/src/workers/Worker.h
index f62083d0b..35b55b908 100644
--- a/src/workers/Worker.h
+++ b/src/workers/Worker.h
@@ -44,8 +44,9 @@ public:
 protected:
     bool m_nicehash;
     cryptonight_ctx *m_ctx;
-    Handle *m_handle;
     int m_id;
+    int m_threads;
+    uint64_t m_count;
     uint64_t m_sequence;
 };
 
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
index 1916be72e..1f7b76c6a 100644
--- a/src/workers/Workers.cpp
+++ b/src/workers/Workers.cpp
@@ -21,16 +21,17 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "Console.h"
 #include "workers/Handle.h"
 #include "workers/SingleWorker.h"
 #include "workers/Workers.h"
 
 
 Job Workers::m_job;
+pthread_mutex_t Workers::m_mutex;
 pthread_rwlock_t Workers::m_rwlock;
 std::atomic<int> Workers::m_paused;
 std::atomic<uint64_t> Workers::m_sequence;
+std::list<JobResult> Workers::m_queue;
 std::vector<Handle*> Workers::m_workers;
 uv_async_t Workers::m_async;
 
@@ -58,7 +59,8 @@ void Workers::setJob(const Job &job)
 
 void Workers::start(int threads, int64_t affinity, bool nicehash)
 {
-    LOG_NOTICE("start %d", pthread_self());
+    pthread_mutex_init(&m_mutex, nullptr);
+    pthread_rwlock_init(&m_rwlock, nullptr);
 
     m_sequence = 0;
     m_paused   = 1;
@@ -66,15 +68,19 @@ void Workers::start(int threads, int64_t affinity, bool nicehash)
     uv_async_init(uv_default_loop(), &m_async, Workers::onResult);
 
     for (int i = 0; i < threads; ++i) {
-        Handle *handle = new Handle(i, affinity, nicehash);
+        Handle *handle = new Handle(i, threads, affinity, nicehash);
         m_workers.push_back(handle);
         handle->start(Workers::onReady);
     }
 }
 
 
-void Workers::submit()
+void Workers::submit(const JobResult &result)
 {
+    pthread_mutex_lock(&m_mutex);
+    m_queue.push_back(result);
+    pthread_mutex_unlock(&m_mutex);
+
     uv_async_send(&m_async);
 }
 
@@ -93,4 +99,12 @@ void *Workers::onReady(void *arg)
 
 void Workers::onResult(uv_async_t *handle)
 {
+    std::list<JobResult> results;
+
+    pthread_mutex_lock(&m_mutex);
+    while (!m_queue.empty()) {
+        results.push_back(std::move(m_queue.front()));
+        m_queue.pop_front();
+    }
+    pthread_mutex_unlock(&m_mutex);
 }
diff --git a/src/workers/Workers.h b/src/workers/Workers.h
index 7d6328cad..68bc6f15f 100644
--- a/src/workers/Workers.h
+++ b/src/workers/Workers.h
@@ -26,12 +26,13 @@
 
 
 #include <atomic>
+#include <list>
 #include <pthread.h>
 #include <uv.h>
 #include <vector>
 
-
 #include "net/Job.h"
+#include "net/JobResult.h"
 
 
 class Handle;
@@ -43,7 +44,7 @@ public:
     static Job job();
     static void setJob(const Job &job);
     static void start(int threads, int64_t affinity, bool nicehash);
-    static void submit();
+    static void submit(const JobResult &result);
 
     static inline bool isOutdated(uint64_t sequence) { return m_sequence.load(std::memory_order_relaxed) != sequence; }
     static inline bool isPaused()                    { return m_paused.load(std::memory_order_relaxed) == 1; }
@@ -55,9 +56,11 @@ private:
     static void onResult(uv_async_t *handle);
 
     static Job m_job;
+    static pthread_mutex_t m_mutex;
     static pthread_rwlock_t m_rwlock;
     static std::atomic<int> m_paused;
     static std::atomic<uint64_t> m_sequence;
+    static std::list<JobResult> m_queue;
     static std::vector<Handle*> m_workers;
     static uv_async_t m_async;
 };

From 6774f86fcd217bbdd40d0b0ae14f3579b2867fc4 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Sun, 11 Jun 2017 15:32:15 +0300
Subject: [PATCH 36/56] Implement job result submitting.

---
 CMakeLists.txt                      |  1 +
 src/interfaces/IJobResultListener.h | 41 +++++++++++++++++++++++++++++
 src/net/Client.cpp                  | 20 ++++++++++++++
 src/net/Client.h                    |  4 ++-
 src/net/Network.cpp                 |  9 +++++++
 src/net/Network.h                   |  4 ++-
 src/workers/Workers.cpp             |  8 ++++++
 src/workers/Workers.h               | 11 +++++---
 8 files changed, 92 insertions(+), 6 deletions(-)
 create mode 100644 src/interfaces/IJobResultListener.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 15c1d35da..18e5a06e6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,6 +9,7 @@ set(HEADERS
     src/Console.h
     src/Cpu.h
     src/interfaces/IClientListener.h
+    src/interfaces/IJobResultListener.h
     src/interfaces/IWorker.h
     src/Mem.h
     src/net/Client.h
diff --git a/src/interfaces/IJobResultListener.h b/src/interfaces/IJobResultListener.h
new file mode 100644
index 000000000..483a2062d
--- /dev/null
+++ b/src/interfaces/IJobResultListener.h
@@ -0,0 +1,41 @@
+/* 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/>.
+ */
+
+#ifndef __IJOBRESULTLISTENER_H__
+#define __IJOBRESULTLISTENER_H__
+
+
+class Client;
+class JobResult;
+
+
+class IJobResultListener
+{
+public:
+    virtual ~IJobResultListener() {}
+
+    virtual void onJobResult(const JobResult &result) = 0;
+};
+
+
+#endif // __IJOBRESULTLISTENER_H__
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index 91f582a00..eb776da14 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -28,6 +28,7 @@
 #include "Console.h"
 #include "interfaces/IClientListener.h"
 #include "net/Client.h"
+#include "net/JobResult.h"
 #include "net/Url.h"
 
 
@@ -148,6 +149,25 @@ void Client::setUrl(const Url *url)
 }
 
 
+void Client::submit(const JobResult &result)
+{
+    char *req = static_cast<char*>(malloc(345));
+    char nonce[9];
+    char data[65];
+
+    Job::toHex(reinterpret_cast<const unsigned char*>(&result.nonce), 4, nonce);
+    nonce[8] = '\0';
+
+    Job::toHex(result.result, 32, data);
+    data[64] = '\0';
+
+    snprintf(req, 345, "{\"id\":%llu,\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
+             m_sequence, m_rpcId, result.jobId, nonce, data);
+
+    send(req);
+}
+
+
 bool Client::parseJob(const json_t *params, int *code)
 {
     if (!json_is_object(params)) {
diff --git a/src/net/Client.h b/src/net/Client.h
index b46a8bf07..75c5b2830 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -32,8 +32,9 @@
 #include "net/Job.h"
 
 
-class Url;
 class IClientListener;
+class JobResult;
+class Url;
 
 
 class Client
@@ -59,6 +60,7 @@ public:
     void login(const char *user, const char *pass, const char *agent);
     void send(char *data);
     void setUrl(const Url *url);
+    void submit(const JobResult &result);
 
     inline bool isReady() const              { return m_state == ConnectedState && m_failures == 0; }
     inline const char *host() const          { return m_host; }
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index 02c68fd1b..eef52cd14 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -39,6 +39,8 @@ Network::Network(const Options *options) :
     m_pool(0),
     m_diff(0)
 {
+    Workers::setListener(this);
+
     m_pools.reserve(2);
     m_agent = userAgent();
 
@@ -103,6 +105,13 @@ void Network::onJobReceived(Client *client, const Job &job)
 }
 
 
+void Network::onJobResult(const JobResult &result)
+{
+    LOG_NOTICE("SHARE FOUND");
+    m_pools[result.poolId]->submit(result);
+}
+
+
 void Network::onLoginCredentialsRequired(Client *client)
 {
     client->login(m_options->user(), m_options->pass(), m_agent);
diff --git a/src/net/Network.h b/src/net/Network.h
index af1ddbbfd..d9192c9fe 100644
--- a/src/net/Network.h
+++ b/src/net/Network.h
@@ -30,13 +30,14 @@
 
 
 #include "interfaces/IClientListener.h"
+#include "interfaces/IJobResultListener.h"
 
 
 class Options;
 class Url;
 
 
-class Network : public IClientListener
+class Network : public IClientListener, public IJobResultListener
 {
 public:
   Network(const Options *options);
@@ -49,6 +50,7 @@ public:
 protected:
   void onClose(Client *client, int failures) override;
   void onJobReceived(Client *client, const Job &job) override;
+  void onJobResult(const JobResult &result);
   void onLoginCredentialsRequired(Client *client) override;
   void onLoginSuccess(Client *client) override;
 
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
index 1f7b76c6a..f3a26cd00 100644
--- a/src/workers/Workers.cpp
+++ b/src/workers/Workers.cpp
@@ -21,11 +21,13 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "interfaces/IJobResultListener.h"
 #include "workers/Handle.h"
 #include "workers/SingleWorker.h"
 #include "workers/Workers.h"
 
 
+IJobResultListener *Workers::m_listener = nullptr;
 Job Workers::m_job;
 pthread_mutex_t Workers::m_mutex;
 pthread_rwlock_t Workers::m_rwlock;
@@ -107,4 +109,10 @@ void Workers::onResult(uv_async_t *handle)
         m_queue.pop_front();
     }
     pthread_mutex_unlock(&m_mutex);
+
+    for (auto result : results) {
+        m_listener->onJobResult(result);
+    }
+
+    results.clear();
 }
diff --git a/src/workers/Workers.h b/src/workers/Workers.h
index 68bc6f15f..93913b4ba 100644
--- a/src/workers/Workers.h
+++ b/src/workers/Workers.h
@@ -36,6 +36,7 @@
 
 
 class Handle;
+class IJobResultListener;
 
 
 class Workers
@@ -46,15 +47,17 @@ public:
     static void start(int threads, int64_t affinity, bool nicehash);
     static void submit(const JobResult &result);
 
-    static inline bool isOutdated(uint64_t sequence) { return m_sequence.load(std::memory_order_relaxed) != sequence; }
-    static inline bool isPaused()                    { return m_paused.load(std::memory_order_relaxed) == 1; }
-    static inline uint64_t sequence()                { return m_sequence.load(std::memory_order_relaxed); }
-    static inline void pause()                       { m_paused = 1; }
+    static inline bool isOutdated(uint64_t sequence)             { return m_sequence.load(std::memory_order_relaxed) != sequence; }
+    static inline bool isPaused()                                { return m_paused.load(std::memory_order_relaxed) == 1; }
+    static inline uint64_t sequence()                            { return m_sequence.load(std::memory_order_relaxed); }
+    static inline void pause()                                   { m_paused = 1; }
+    static inline void setListener(IJobResultListener *listener) { m_listener = listener; }
 
 private:
     static void *onReady(void *arg);
     static void onResult(uv_async_t *handle);
 
+    static IJobResultListener *m_listener;
     static Job m_job;
     static pthread_mutex_t m_mutex;
     static pthread_rwlock_t m_rwlock;

From a370b8fd3020e5effa0dac5b2e6f20779c00433c Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Mon, 12 Jun 2017 07:18:14 +0300
Subject: [PATCH 37/56] Add class Telemetry.

---
 CMakeLists.txt                   |   4 +-
 src/interfaces/IClientListener.h |   6 +-
 src/interfaces/IWorker.h         |   7 +-
 src/workers/Handle.h             |   1 +
 src/workers/SingleWorker.cpp     |   4 ++
 src/workers/Telemetry.cpp        | 107 +++++++++++++++++++++++++++++++
 src/workers/Telemetry.h          |  49 ++++++++++++++
 src/workers/Worker.cpp           |  15 +++++
 src/workers/Worker.h             |   8 +++
 src/workers/Workers.cpp          |  40 ++++++++++++
 src/workers/Workers.h            |   5 ++
 11 files changed, 241 insertions(+), 5 deletions(-)
 create mode 100644 src/workers/Telemetry.cpp
 create mode 100644 src/workers/Telemetry.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 18e5a06e6..753ee492e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,6 +21,7 @@ set(HEADERS
     src/Summary.h
     src/workers/Handle.h
     src/workers/SingleWorker.h
+    src/workers/Telemetry.h
     src/workers/Worker.h
     src/workers/Workers.h
     src/version.h
@@ -52,6 +53,7 @@ set(SOURCES
     src/Summary.cpp
     src/workers/Handle.cpp
     src/workers/SingleWorker.cpp
+    src/workers/Telemetry.cpp
     src/workers/Worker.cpp
     src/workers/Workers.cpp
     src/xmrig.cpp
@@ -86,7 +88,7 @@ endif()
 
 add_definitions(/D_GNU_SOURCE)
 add_definitions(/DUNICODE)
-add_definitions(/DAPP_DEBUG)
+#add_definitions(/DAPP_DEBUG)
 
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
 
diff --git a/src/interfaces/IClientListener.h b/src/interfaces/IClientListener.h
index 73a855161..570190359 100644
--- a/src/interfaces/IClientListener.h
+++ b/src/interfaces/IClientListener.h
@@ -34,10 +34,10 @@ class IClientListener
 public:
     virtual ~IClientListener() {}
 
-    virtual void onClose(Client *client, int failures);
+    virtual void onClose(Client *client, int failures)         = 0;
     virtual void onJobReceived(Client *client, const Job &job) = 0;
-    virtual void onLoginCredentialsRequired(Client *client) = 0;
-    virtual void onLoginSuccess(Client *client) = 0;
+    virtual void onLoginCredentialsRequired(Client *client)    = 0;
+    virtual void onLoginSuccess(Client *client)                = 0;
 };
 
 
diff --git a/src/interfaces/IWorker.h b/src/interfaces/IWorker.h
index f9010a2f3..b9b6eb0a0 100644
--- a/src/interfaces/IWorker.h
+++ b/src/interfaces/IWorker.h
@@ -25,12 +25,17 @@
 #define __IWORKER_H__
 
 
+#include <stdint.h>
+
+
 class IWorker
 {
 public:
     virtual ~IWorker() {}
 
-    virtual void start() = 0;
+    virtual uint64_t hashCount() const = 0;
+    virtual uint64_t timestamp() const = 0;
+    virtual void start()               = 0;
 };
 
 
diff --git a/src/workers/Handle.h b/src/workers/Handle.h
index a8ad84c19..6b2b1d37c 100644
--- a/src/workers/Handle.h
+++ b/src/workers/Handle.h
@@ -42,6 +42,7 @@ public:
     inline int threadId() const            { return m_threadId; }
     inline int threads() const             { return m_threads; }
     inline int64_t affinity() const        { return m_affinity; }
+    inline IWorker *worker() const         { return m_worker; }
     inline void setWorker(IWorker *worker) { m_worker = worker; }
 
 private:
diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp
index c102029c4..263f08595 100644
--- a/src/workers/SingleWorker.cpp
+++ b/src/workers/SingleWorker.cpp
@@ -51,6 +51,10 @@ void SingleWorker::start()
         }
 
         while (!Workers::isOutdated(m_sequence)) {
+            if ((m_count & 0xF) == 0) {
+                storeStats();
+            }
+
             m_count++;
             *m_job.nonce() = ++m_result.nonce;
 
diff --git a/src/workers/Telemetry.cpp b/src/workers/Telemetry.cpp
new file mode 100644
index 000000000..b1a36633e
--- /dev/null
+++ b/src/workers/Telemetry.cpp
@@ -0,0 +1,107 @@
+/* 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 <memory.h>
+#include <math.h>
+#include <chrono>
+
+#include "Console.h"
+#include "workers/Telemetry.h"
+
+
+Telemetry::Telemetry(int threads) :
+    m_threads(threads)
+{
+    m_counts     = new uint64_t*[threads];
+    m_timestamps = new uint64_t*[threads];
+    m_top        = new uint32_t[threads];
+
+    for (int i = 0; i < threads; i++) {
+        m_counts[i] = new uint64_t[kBucketSize];
+        m_timestamps[i] = new uint64_t[kBucketSize];
+        m_top[i] = 0;
+
+        memset(m_counts[0], 0, sizeof(uint64_t) * kBucketSize);
+        memset(m_timestamps[0], 0, sizeof(uint64_t) * kBucketSize);
+    }
+}
+
+
+double Telemetry::calc(size_t threadId, size_t ms) const
+{
+    using namespace std::chrono;
+    const uint64_t now = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
+
+    uint64_t earliestHashCount = 0;
+    uint64_t earliestStamp     = 0;
+    uint64_t lastestStamp      = 0;
+    uint64_t lastestHashCnt    = 0;
+    bool haveFullSet           = false;
+
+    for (size_t i = 1; i < kBucketSize; i++) {
+        const size_t idx = (m_top[threadId] - i) & kBucketMask;
+
+        if (m_timestamps[threadId][idx] == 0) {
+            break;
+        }
+
+        if (lastestStamp == 0) {
+            lastestStamp = m_timestamps[threadId][idx];
+            lastestHashCnt = m_counts[threadId][idx];
+        }
+
+        if (now - m_timestamps[threadId][idx] > ms) {
+            haveFullSet = true;
+            break;
+        }
+
+        earliestStamp = m_timestamps[threadId][idx];
+        earliestHashCount = m_counts[threadId][idx];
+    }
+
+    if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) {
+        return nan("");
+    }
+
+    if (lastestStamp - earliestStamp == 0) {
+        return nan("");
+    }
+
+    double hashes, time;
+    hashes = lastestHashCnt - earliestHashCount;
+    time   = lastestStamp - earliestStamp;
+    time  /= 1000.0;
+
+    return hashes / time;
+}
+
+
+void Telemetry::add(size_t threadId, uint64_t count, uint64_t timestamp)
+{
+    const size_t top = m_top[threadId];
+    m_counts[threadId][top]     = count;
+    m_timestamps[threadId][top] = timestamp;
+
+    m_top[threadId] = (top + 1) & kBucketMask;
+}
diff --git a/src/workers/Telemetry.h b/src/workers/Telemetry.h
new file mode 100644
index 000000000..007ba536e
--- /dev/null
+++ b/src/workers/Telemetry.h
@@ -0,0 +1,49 @@
+/* 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/>.
+ */
+
+#ifndef __TELEMETRY_H__
+#define __TELEMETRY_H__
+
+
+#include <stdint.h>
+
+
+class Telemetry
+{
+public:
+    Telemetry(int threads);
+    double calc(size_t threadId, size_t ms) const;
+    void add(size_t threadId, uint64_t count, uint64_t timestamp);
+
+private:
+    constexpr static size_t kBucketSize = 2 << 11;
+    constexpr static size_t kBucketMask = kBucketSize - 1;
+
+    int m_threads;
+    uint32_t* m_top;
+    uint64_t** m_counts;
+    uint64_t** m_timestamps;
+};
+
+
+#endif /* __TELEMETRY_H__ */
diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp
index d39ebdc32..5478bcf78 100644
--- a/src/workers/Worker.cpp
+++ b/src/workers/Worker.cpp
@@ -21,6 +21,9 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <chrono>
+
+#include "Console.h"
 
 #include "Cpu.h"
 #include "Mem.h"
@@ -32,6 +35,8 @@ Worker::Worker(Handle *handle) :
     m_nicehash(handle->nicehash()),
     m_id(handle->threadId()),
     m_threads(handle->threads()),
+    m_hashCount(0),
+    m_timestamp(0),
     m_count(0),
     m_sequence(0)
 {
@@ -48,3 +53,13 @@ Worker::Worker(Handle *handle) :
 Worker::~Worker()
 {
 }
+
+
+void Worker::storeStats()
+{
+    using namespace std::chrono;
+
+    const uint64_t timestamp = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
+    m_hashCount.store(m_count, std::memory_order_relaxed);
+    m_timestamp.store(timestamp, std::memory_order_relaxed);
+}
diff --git a/src/workers/Worker.h b/src/workers/Worker.h
index 35b55b908..84f3ccf87 100644
--- a/src/workers/Worker.h
+++ b/src/workers/Worker.h
@@ -25,6 +25,7 @@
 #define __WORKER_H__
 
 
+#include <atomic>
 #include <stdint.h>
 
 
@@ -41,11 +42,18 @@ public:
     Worker(Handle *handle);
     ~Worker();
 
+    inline uint64_t hashCount() const override { return m_hashCount.load(std::memory_order_relaxed); }
+    inline uint64_t timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); }
+
 protected:
+    void storeStats();
+
     bool m_nicehash;
     cryptonight_ctx *m_ctx;
     int m_id;
     int m_threads;
+    std::atomic<uint64_t> m_hashCount;
+    std::atomic<uint64_t> m_timestamp;
     uint64_t m_count;
     uint64_t m_sequence;
 };
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
index f3a26cd00..832d7da00 100644
--- a/src/workers/Workers.cpp
+++ b/src/workers/Workers.cpp
@@ -21,9 +21,14 @@
  *   along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <cmath>
+
+
+#include "Console.h"
 #include "interfaces/IJobResultListener.h"
 #include "workers/Handle.h"
 #include "workers/SingleWorker.h"
+#include "workers/Telemetry.h"
 #include "workers/Workers.h"
 
 
@@ -35,7 +40,10 @@ std::atomic<int> Workers::m_paused;
 std::atomic<uint64_t> Workers::m_sequence;
 std::list<JobResult> Workers::m_queue;
 std::vector<Handle*> Workers::m_workers;
+Telemetry *Workers::m_telemetry = nullptr;
+uint64_t Workers::m_ticks = 0;
 uv_async_t Workers::m_async;
+uv_timer_t Workers::m_timer;
 
 
 Job Workers::job()
@@ -61,6 +69,8 @@ void Workers::setJob(const Job &job)
 
 void Workers::start(int threads, int64_t affinity, bool nicehash)
 {
+    m_telemetry = new Telemetry(threads);
+
     pthread_mutex_init(&m_mutex, nullptr);
     pthread_rwlock_init(&m_rwlock, nullptr);
 
@@ -68,6 +78,8 @@ void Workers::start(int threads, int64_t affinity, bool nicehash)
     m_paused   = 1;
 
     uv_async_init(uv_default_loop(), &m_async, Workers::onResult);
+    uv_timer_init(uv_default_loop(), &m_timer);
+    uv_timer_start(&m_timer, Workers::onPerfTick, 500, 500);
 
     for (int i = 0; i < threads; ++i) {
         Handle *handle = new Handle(i, threads, affinity, nicehash);
@@ -98,6 +110,34 @@ void *Workers::onReady(void *arg)
 }
 
 
+void Workers::onPerfTick(uv_timer_t *handle)
+{
+    for (Handle *handle : m_workers) {
+        m_telemetry->add(handle->threadId(), handle->worker()->hashCount(), handle->worker()->timestamp());
+    }
+
+    if ((m_ticks++ & 0xF) == 0)  {
+        double hps = 0.0;
+        double telem;
+        bool normal = true;
+
+        for (Handle *handle : m_workers) {
+            telem = m_telemetry->calc(handle->threadId(), 2500);
+            if (!std::isnormal(telem)) {
+                normal = false;
+                break;
+            }
+            else {
+                hps += telem;
+            }
+        }
+
+        if (normal) {
+            LOG_NOTICE("%03.1f H/s", hps);
+        }
+    }
+}
+
 
 void Workers::onResult(uv_async_t *handle)
 {
diff --git a/src/workers/Workers.h b/src/workers/Workers.h
index 93913b4ba..f7a0e43a8 100644
--- a/src/workers/Workers.h
+++ b/src/workers/Workers.h
@@ -37,6 +37,7 @@
 
 class Handle;
 class IJobResultListener;
+class Telemetry;
 
 
 class Workers
@@ -55,6 +56,7 @@ public:
 
 private:
     static void *onReady(void *arg);
+    static void onPerfTick(uv_timer_t *handle);
     static void onResult(uv_async_t *handle);
 
     static IJobResultListener *m_listener;
@@ -65,7 +67,10 @@ private:
     static std::atomic<uint64_t> m_sequence;
     static std::list<JobResult> m_queue;
     static std::vector<Handle*> m_workers;
+    static Telemetry *m_telemetry;
+    static uint64_t m_ticks;
     static uv_async_t m_async;
+    static uv_timer_t m_timer;
 };
 
 

From 3df545cfc56c1af4ae4068f74f0e4f0662f8e8ea Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Mon, 12 Jun 2017 16:19:07 +0300
Subject: [PATCH 38/56] Initial MSVC support.

---
 CMakeLists.txt                                |  34 +-
 src/3rdparty/align.h                          |  33 +
 src/3rdparty/getopt/getopt.h                  | 653 ++++++++++++++++++
 src/3rdparty/jansson/jansson_private_config.h |  28 +-
 src/App.cpp                                   |   2 +-
 src/Console.cpp                               |  12 +-
 src/Console.h                                 |   4 +-
 src/Cpu_stub.cpp                              |  15 +-
 src/Mem.h                                     |   5 +-
 src/Mem_win.cpp                               |   6 +-
 src/Options.cpp                               |  12 +-
 src/Summary.cpp                               |   4 +-
 src/crypto/CryptoNight.h                      |   9 +-
 src/crypto/CryptoNight_p.h                    |  21 +-
 src/net/Job.h                                 |   7 +-
 src/net/Url.cpp                               |   7 +-
 src/workers/Handle.cpp                        |   4 +-
 src/workers/Handle.h                          |   6 +-
 src/workers/SingleWorker.cpp                  |   4 +-
 src/workers/Workers.cpp                       |  66 +-
 src/workers/Workers.h                         |   9 +-
 21 files changed, 845 insertions(+), 96 deletions(-)
 create mode 100644 src/3rdparty/align.h
 create mode 100644 src/3rdparty/getopt/getopt.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 753ee492e..ed96a8c2c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,6 +5,7 @@ option(WITH_LIBCPUID "Use Libcpuid" ON)
 option(WITH_AEON     "CryptoNight-Lite support" ON)
 
 set(HEADERS
+    src/3rdparty/align.h
     src/App.h
     src/Console.h
     src/Cpu.h
@@ -19,12 +20,12 @@ set(HEADERS
     src/net/Url.h
     src/Options.h
     src/Summary.h
+    src/version.h
     src/workers/Handle.h
     src/workers/SingleWorker.h
     src/workers/Telemetry.h
     src/workers/Worker.h
     src/workers/Workers.h
-    src/version.h
    )
 
 set(HEADERS_CRYPTO
@@ -86,7 +87,6 @@ else()
     set(EXTRA_LIBS pthread)
 endif()
 
-add_definitions(/D_GNU_SOURCE)
 add_definitions(/DUNICODE)
 #add_definitions(/DAPP_DEBUG)
 
@@ -98,17 +98,31 @@ if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
     set(CMAKE_BUILD_TYPE Release)
 endif()
 
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall -fno-exceptions")
-set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions -fno-rtti")
-set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
-#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
-#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate")
-#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-use -fprofile-correction")
+# https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
+if (CMAKE_C_COMPILER_ID STREQUAL GNU)
+
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall -fno-exceptions")
+    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
+
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions -fno-rtti")
+    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 
-if (WIN32)
     set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
+
+    add_definitions(/D_GNU_SOURCE)
+
+    #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
+
+elseif (CMAKE_C_COMPILER_ID STREQUAL MSVC)
+
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MT")
+
+elseif (CMAKE_C_COMPILER_ID MATCHES "Clang")
+
+    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -fmerge-all-constants")
+    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -fmerge-all-constants")
+
 endif()
 
 if (WITH_LIBCPUID)
diff --git a/src/3rdparty/align.h b/src/3rdparty/align.h
new file mode 100644
index 000000000..b61179b90
--- /dev/null
+++ b/src/3rdparty/align.h
@@ -0,0 +1,33 @@
+/* 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/>.
+ */
+
+#ifndef __ALIGN_H__
+#define __ALIGN_H__
+
+#ifdef _MSC_VER
+#   define VAR_ALIGN(x, decl) __declspec(align(x)) decl
+#else
+#   define VAR_ALIGN(x, decl) decl __attribute__ ((aligned(x)))
+#endif
+
+#endif /* __ALIGN_H__ */
diff --git a/src/3rdparty/getopt/getopt.h b/src/3rdparty/getopt/getopt.h
new file mode 100644
index 000000000..0cb88895d
--- /dev/null
+++ b/src/3rdparty/getopt/getopt.h
@@ -0,0 +1,653 @@
+#ifndef __GETOPT_H__
+/**
+ * DISCLAIMER
+ * This file is part of the mingw-w64 runtime package.
+ *
+ * The mingw-w64 runtime package and its code is distributed in the hope that it 
+ * will be useful but WITHOUT ANY WARRANTY.  ALL WARRANTIES, EXPRESSED OR 
+ * IMPLIED ARE HEREBY DISCLAIMED.  This includes but is not limited to 
+ * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+ /*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma warning(disable:4996);
+
+#define __GETOPT_H__
+
+/* All the headers include this file. */
+#include <crtdefs.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define	REPLACE_GETOPT		/* use this getopt as the system getopt(3) */
+
+#ifdef REPLACE_GETOPT
+int	opterr = 1;		/* if error message should be printed */
+int	optind = 1;		/* index into parent argv vector */
+int	optopt = '?';		/* character checked for validity */
+#undef	optreset		/* see getopt.h */
+#define	optreset		__mingw_optreset
+int	optreset;		/* reset getopt */
+char    *optarg;		/* argument associated with option */
+#endif
+
+//extern int optind;		/* index of first non-option in argv      */
+//extern int optopt;		/* single option character, as parsed     */
+//extern int opterr;		/* flag to enable built-in diagnostics... */
+//				/* (user may set to zero, to suppress)    */
+//
+//extern char *optarg;		/* pointer to argument of current option  */
+
+#define PRINT_ERROR	((opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE	0x01	/* permute non-options to the end of argv */
+#define FLAG_ALLARGS	0x02	/* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY	0x04	/* operate as getopt_long_only */
+
+/* return values */
+#define	BADCH		(int)'?'
+#define	BADARG		((*options == ':') ? (int)':' : (int)'?')
+#define	INORDER 	(int)1
+
+#ifndef __CYGWIN__
+#define __progname __argv[0]
+#else
+extern char __declspec(dllimport) *__progname;
+#endif
+
+#ifdef __CYGWIN__
+static char EMSG[] = "";
+#else
+#define	EMSG		""
+#endif
+
+static int getopt_internal(int, char * const *, const char *,
+			   const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+			      const struct option *, int *, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1;   /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptchar[] = "unknown option -- %c";
+static const char illoptstring[] = "unknown option -- %s";
+
+static void
+_vwarnx(const char *fmt,va_list ap)
+{
+  (void)fprintf(stderr,"%s: ",__progname);
+  if (fmt != NULL)
+    (void)vfprintf(stderr,fmt,ap);
+  (void)fprintf(stderr,"\n");
+}
+
+static void
+warnx(const char *fmt,...)
+{
+  va_list ap;
+  va_start(ap,fmt);
+  _vwarnx(fmt,ap);
+  va_end(ap);
+}
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+	int c;
+
+	c = a % b;
+	while (c != 0) {
+		a = b;
+		b = c;
+		c = a % b;
+	}
+
+	return (b);
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+	char * const *nargv)
+{
+	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+	char *swap;
+
+	/*
+	 * compute lengths of blocks and number and size of cycles
+	 */
+	nnonopts = panonopt_end - panonopt_start;
+	nopts = opt_end - panonopt_end;
+	ncycle = gcd(nnonopts, nopts);
+	cyclelen = (opt_end - panonopt_start) / ncycle;
+
+	for (i = 0; i < ncycle; i++) {
+		cstart = panonopt_end+i;
+		pos = cstart;
+		for (j = 0; j < cyclelen; j++) {
+			if (pos >= panonopt_end)
+				pos -= nnonopts;
+			else
+				pos += nopts;
+			swap = nargv[pos];
+			/* LINTED const cast */
+			((char **) nargv)[pos] = nargv[cstart];
+			/* LINTED const cast */
+			((char **)nargv)[cstart] = swap;
+		}
+	}
+}
+
+#ifdef REPLACE_GETOPT
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the BSD getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+
+	/*
+	 * We don't pass FLAG_PERMUTE to getopt_internal() since
+	 * the BSD getopt(3) (unlike GNU) has never done this.
+	 *
+	 * Furthermore, since many privileged programs call getopt()
+	 * before dropping privileges it makes sense to keep things
+	 * as simple (and bug-free) as possible.
+	 */
+	return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+#endif /* REPLACE_GETOPT */
+
+//extern int getopt(int nargc, char * const *nargv, const char *options);
+
+#ifdef _BSD_SOURCE
+/*
+ * BSD adds the non-standard `optreset' feature, for reinitialisation
+ * of `getopt' parsing.  We support this feature, for applications which
+ * proclaim their BSD heritage, before including this header; however,
+ * to maintain portability, developers are advised to avoid it.
+ */
+# define optreset  __mingw_optreset
+extern int optreset;
+#endif
+#ifdef __cplusplus
+}
+#endif
+/*
+ * POSIX requires the `getopt' API to be specified in `unistd.h';
+ * thus, `unistd.h' includes this header.  However, we do not want
+ * to expose the `getopt_long' or `getopt_long_only' APIs, when
+ * included in this manner.  Thus, close the standard __GETOPT_H__
+ * declarations block, and open an additional __GETOPT_LONG_H__
+ * specific block, only when *not* __UNISTD_H_SOURCED__, in which
+ * to declare the extended API.
+ */
+#endif /* !defined(__GETOPT_H__) */
+
+#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
+#define __GETOPT_LONG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct option		/* specification for a long form option...	*/
+{
+  const char *name;		/* option name, without leading hyphens */
+  int         has_arg;		/* does it take an argument?		*/
+  int        *flag;		/* where to save its status, or NULL	*/
+  int         val;		/* its associated status value		*/
+};
+
+enum    		/* permitted values for its `has_arg' field...	*/
+{
+  no_argument = 0,      	/* option never takes an argument	*/
+  required_argument,		/* option always requires an argument	*/
+  optional_argument		/* option may take an argument		*/
+};
+
+/*
+ * parse_long_options --
+ *	Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+parse_long_options(char * const *nargv, const char *options,
+	const struct option *long_options, int *idx, int short_too)
+{
+	char *current_argv, *has_equal;
+	size_t current_argv_len;
+	int i, ambiguous, match;
+
+#define IDENTICAL_INTERPRETATION(_x, _y)                                \
+	(long_options[(_x)].has_arg == long_options[(_y)].has_arg &&    \
+	 long_options[(_x)].flag == long_options[(_y)].flag &&          \
+	 long_options[(_x)].val == long_options[(_y)].val)
+
+	current_argv = place;
+	match = -1;
+	ambiguous = 0;
+
+	optind++;
+
+	if ((has_equal = strchr(current_argv, '=')) != NULL) {
+		/* argument found (--option=arg) */
+		current_argv_len = has_equal - current_argv;
+		has_equal++;
+	} else
+		current_argv_len = strlen(current_argv);
+
+	for (i = 0; long_options[i].name; i++) {
+		/* find matching long option */
+		if (strncmp(current_argv, long_options[i].name,
+		    current_argv_len))
+			continue;
+
+		if (strlen(long_options[i].name) == current_argv_len) {
+			/* exact match */
+			match = i;
+			ambiguous = 0;
+			break;
+		}
+		/*
+		 * If this is a known short option, don't allow
+		 * a partial match of a single character.
+		 */
+		if (short_too && current_argv_len == 1)
+			continue;
+
+		if (match == -1)	/* partial match */
+			match = i;
+		else if (!IDENTICAL_INTERPRETATION(i, match))
+			ambiguous = 1;
+	}
+	if (ambiguous) {
+		/* ambiguous abbreviation */
+		if (PRINT_ERROR)
+			warnx(ambig, (int)current_argv_len,
+			     current_argv);
+		optopt = 0;
+		return (BADCH);
+	}
+	if (match != -1) {		/* option found */
+		if (long_options[match].has_arg == no_argument
+		    && has_equal) {
+			if (PRINT_ERROR)
+				warnx(noarg, (int)current_argv_len,
+				     current_argv);
+			/*
+			 * XXX: GNU sets optopt to val regardless of flag
+			 */
+			if (long_options[match].flag == NULL)
+				optopt = long_options[match].val;
+			else
+				optopt = 0;
+			return (BADARG);
+		}
+		if (long_options[match].has_arg == required_argument ||
+		    long_options[match].has_arg == optional_argument) {
+			if (has_equal)
+				optarg = has_equal;
+			else if (long_options[match].has_arg ==
+			    required_argument) {
+				/*
+				 * optional argument doesn't use next nargv
+				 */
+				optarg = nargv[optind++];
+			}
+		}
+		if ((long_options[match].has_arg == required_argument)
+		    && (optarg == NULL)) {
+			/*
+			 * Missing argument; leading ':' indicates no error
+			 * should be generated.
+			 */
+			if (PRINT_ERROR)
+				warnx(recargstring,
+				    current_argv);
+			/*
+			 * XXX: GNU sets optopt to val regardless of flag
+			 */
+			if (long_options[match].flag == NULL)
+				optopt = long_options[match].val;
+			else
+				optopt = 0;
+			--optind;
+			return (BADARG);
+		}
+	} else {			/* unknown option */
+		if (short_too) {
+			--optind;
+			return (-1);
+		}
+		if (PRINT_ERROR)
+			warnx(illoptstring, current_argv);
+		optopt = 0;
+		return (BADCH);
+	}
+	if (idx)
+		*idx = match;
+	if (long_options[match].flag) {
+		*long_options[match].flag = long_options[match].val;
+		return (0);
+	} else
+		return (long_options[match].val);
+#undef IDENTICAL_INTERPRETATION
+}
+
+/*
+ * getopt_internal --
+ *	Parse argc/argv argument vector.  Called by user level routines.
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+	const struct option *long_options, int *idx, int flags)
+{
+	char *oli;				/* option letter list index */
+	int optchar, short_too;
+	static int posixly_correct = -1;
+
+	if (options == NULL)
+		return (-1);
+
+	/*
+	 * XXX Some GNU programs (like cvs) set optind to 0 instead of
+	 * XXX using optreset.  Work around this braindamage.
+	 */
+	if (optind == 0)
+		optind = optreset = 1;
+
+	/*
+	 * Disable GNU extensions if POSIXLY_CORRECT is set or options
+	 * string begins with a '+'.
+	 *
+	 * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
+	 *                 optreset != 0 for GNU compatibility.
+	 */
+	if (posixly_correct == -1 || optreset != 0)
+		posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+	if (*options == '-')
+		flags |= FLAG_ALLARGS;
+	else if (posixly_correct || *options == '+')
+		flags &= ~FLAG_PERMUTE;
+	if (*options == '+' || *options == '-')
+		options++;
+
+	optarg = NULL;
+	if (optreset)
+		nonopt_start = nonopt_end = -1;
+start:
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc) {          /* end of argument vector */
+			place = EMSG;
+			if (nonopt_end != -1) {
+				/* do permutation, if we have to */
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				optind -= nonopt_end - nonopt_start;
+			}
+			else if (nonopt_start != -1) {
+				/*
+				 * If we skipped non-options, set optind
+				 * to the first of them.
+				 */
+				optind = nonopt_start;
+			}
+			nonopt_start = nonopt_end = -1;
+			return (-1);
+		}
+		if (*(place = nargv[optind]) != '-' ||
+		    (place[1] == '\0' && strchr(options, '-') == NULL)) {
+			place = EMSG;		/* found non-option */
+			if (flags & FLAG_ALLARGS) {
+				/*
+				 * GNU extension:
+				 * return non-option as argument to option 1
+				 */
+				optarg = nargv[optind++];
+				return (INORDER);
+			}
+			if (!(flags & FLAG_PERMUTE)) {
+				/*
+				 * If no permutation wanted, stop parsing
+				 * at first non-option.
+				 */
+				return (-1);
+			}
+			/* do permutation */
+			if (nonopt_start == -1)
+				nonopt_start = optind;
+			else if (nonopt_end != -1) {
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				nonopt_start = optind -
+				    (nonopt_end - nonopt_start);
+				nonopt_end = -1;
+			}
+			optind++;
+			/* process next argument */
+			goto start;
+		}
+		if (nonopt_start != -1 && nonopt_end == -1)
+			nonopt_end = optind;
+
+		/*
+		 * If we have "-" do nothing, if "--" we are done.
+		 */
+		if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+			optind++;
+			place = EMSG;
+			/*
+			 * We found an option (--), so if we skipped
+			 * non-options, we have to permute.
+			 */
+			if (nonopt_end != -1) {
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				optind -= nonopt_end - nonopt_start;
+			}
+			nonopt_start = nonopt_end = -1;
+			return (-1);
+		}
+	}
+
+	/*
+	 * Check long options if:
+	 *  1) we were passed some
+	 *  2) the arg is not just "-"
+	 *  3) either the arg starts with -- we are getopt_long_only()
+	 */
+	if (long_options != NULL && place != nargv[optind] &&
+	    (*place == '-' || (flags & FLAG_LONGONLY))) {
+		short_too = 0;
+		if (*place == '-')
+			place++;		/* --foo long option */
+		else if (*place != ':' && strchr(options, *place) != NULL)
+			short_too = 1;		/* could be short option too */
+
+		optchar = parse_long_options(nargv, options, long_options,
+		    idx, short_too);
+		if (optchar != -1) {
+			place = EMSG;
+			return (optchar);
+		}
+	}
+
+	if ((optchar = (int)*place++) == (int)':' ||
+	    (optchar == (int)'-' && *place != '\0') ||
+	    (oli = (char*)strchr(options, optchar)) == NULL) {
+		/*
+		 * If the user specified "-" and  '-' isn't listed in
+		 * options, return -1 (non-option) as per POSIX.
+		 * Otherwise, it is an unknown option character (or ':').
+		 */
+		if (optchar == (int)'-' && *place == '\0')
+			return (-1);
+		if (!*place)
+			++optind;
+		if (PRINT_ERROR)
+			warnx(illoptchar, optchar);
+		optopt = optchar;
+		return (BADCH);
+	}
+	if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+		/* -W long-option */
+		if (*place)			/* no space */
+			/* NOTHING */;
+		else if (++optind >= nargc) {	/* no arg */
+			place = EMSG;
+			if (PRINT_ERROR)
+				warnx(recargchar, optchar);
+			optopt = optchar;
+			return (BADARG);
+		} else				/* white space */
+			place = nargv[optind];
+		optchar = parse_long_options(nargv, options, long_options,
+		    idx, 0);
+		place = EMSG;
+		return (optchar);
+	}
+	if (*++oli != ':') {			/* doesn't take argument */
+		if (!*place)
+			++optind;
+	} else {				/* takes (optional) argument */
+		optarg = NULL;
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (oli[1] != ':') {	/* arg not optional */
+			if (++optind >= nargc) {	/* no arg */
+				place = EMSG;
+				if (PRINT_ERROR)
+					warnx(recargchar, optchar);
+				optopt = optchar;
+				return (BADARG);
+			} else
+				optarg = nargv[optind];
+		}
+		place = EMSG;
+		++optind;
+	}
+	/* dump back option letter */
+	return (optchar);
+}
+
+/*
+ * getopt_long --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx)
+{
+
+	return (getopt_internal(nargc, nargv, options, long_options, idx,
+	    FLAG_PERMUTE));
+}
+
+/*
+ * getopt_long_only --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_long_only(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx)
+{
+
+	return (getopt_internal(nargc, nargv, options, long_options, idx,
+	    FLAG_PERMUTE|FLAG_LONGONLY));
+}
+
+//extern int getopt_long(int nargc, char * const *nargv, const char *options,
+//    const struct option *long_options, int *idx);
+//extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
+//    const struct option *long_options, int *idx);
+/*
+ * Previous MinGW implementation had...
+ */
+#ifndef HAVE_DECL_GETOPT
+/*
+ * ...for the long form API only; keep this for compatibility.
+ */
+# define HAVE_DECL_GETOPT	1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
diff --git a/src/3rdparty/jansson/jansson_private_config.h b/src/3rdparty/jansson/jansson_private_config.h
index 2b17f182f..671993d95 100644
--- a/src/3rdparty/jansson/jansson_private_config.h
+++ b/src/3rdparty/jansson/jansson_private_config.h
@@ -2,7 +2,9 @@
 /* jansson_private_config.h.in.  Generated from configure.ac by autoheader.  */
 
 /* Define to 1 if gcc's __atomic builtins are available */
-#define HAVE_ATOMIC_BUILTINS 1
+#ifndef _MSC_VER
+#   define HAVE_ATOMIC_BUILTINS 1
+#endif
 
 /* Define to 1 if you have the `close' function. */
 #define HAVE_CLOSE 1
@@ -20,7 +22,9 @@
 #define HAVE_GETPID 1
 
 /* Define to 1 if you have the `gettimeofday' function. */
-#define HAVE_GETTIMEOFDAY 1
+#ifndef _MSC_VER
+#   define HAVE_GETTIMEOFDAY 1
+#endif
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
@@ -44,10 +48,14 @@
 #define HAVE_READ 1
 
 /* Define to 1 if you have the <sched.h> header file. */
-#define HAVE_SCHED_H 1
+#ifndef _MSC_VER
+#   define HAVE_SCHED_H 1
+#endif
 
 /* Define to 1 if you have the `sched_yield' function. */
-#define HAVE_SCHED_YIELD 1
+#ifndef _MSC_VER
+#   define HAVE_SCHED_YIELD 1
+#endif
 
 /* Define to 1 if you have the <stdint.h> header file. */
 #define HAVE_STDINT_H 1
@@ -68,19 +76,25 @@
 #define HAVE_SYNC_BUILTINS 1
 
 /* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
+#ifndef _MSC_VER
+#   define HAVE_SYS_PARAM_H 1
+#endif
 
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #define HAVE_SYS_STAT_H 1
 
 /* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
+#ifndef _MSC_VER
+#   define HAVE_SYS_TIME_H 1
+#endif
 
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
 /* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
+#ifndef _MSC_VER
+#   define HAVE_UNISTD_H 1
+#endif
 
 /* Define to 1 if the system has the type 'unsigned long long int'. */
 #define HAVE_UNSIGNED_LONG_LONG_INT 1
diff --git a/src/App.cpp b/src/App.cpp
index 4078f4b7b..b897be8ae 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -60,7 +60,7 @@ App::~App()
 }
 
 
-App::exec()
+int App::exec()
 {
     if (!m_options->isReady()) {
         return 0;
diff --git a/src/Console.cpp b/src/Console.cpp
index fd4ff4a5a..b3b7ed3ea 100644
--- a/src/Console.cpp
+++ b/src/Console.cpp
@@ -22,8 +22,10 @@
  */
 
 
+#include <malloc.h>
 #include <time.h>
 
+
 #ifdef WIN32
 #   include <winsock2.h>
 #   include "3rdparty/winansi.h"
@@ -97,12 +99,12 @@ void Console::message(Console::Level level, const char* fmt, ...)
             m_colors ? kCL_N : ""
         );
 
-    pthread_mutex_lock(&m_mutex);
+    uv_mutex_lock(&m_mutex);
 
     vfprintf(stdout, buf, ap);
     fflush(stdout);
 
-    pthread_mutex_unlock(&m_mutex);
+    uv_mutex_unlock(&m_mutex);
 
     va_end(ap);
 }
@@ -121,12 +123,12 @@ void Console::text(const char* fmt, ...)
             m_colors ? kCL_N : ""
         );
 
-    pthread_mutex_lock(&m_mutex);
+    uv_mutex_lock(&m_mutex);
 
     vfprintf(stdout, buf, ap);
     fflush(stdout);
 
-    pthread_mutex_unlock(&m_mutex);
+    uv_mutex_unlock(&m_mutex);
 
     va_end(ap);
 }
@@ -135,5 +137,5 @@ void Console::text(const char* fmt, ...)
 Console::Console() :
     m_colors(true)
 {
-    pthread_mutex_init(&m_mutex, nullptr);
+    uv_mutex_init(&m_mutex);
 }
diff --git a/src/Console.h b/src/Console.h
index edd5ae8ca..73e047061 100644
--- a/src/Console.h
+++ b/src/Console.h
@@ -25,7 +25,7 @@
 #define __CONSOLE_H__
 
 
-#include <pthread.h>
+#include <uv.h>
 
 
 class Console
@@ -61,7 +61,7 @@ private:
 
     static Console *m_self;
     bool m_colors;
-    pthread_mutex_t m_mutex;
+    uv_mutex_t m_mutex;
 };
 
 
diff --git a/src/Cpu_stub.cpp b/src/Cpu_stub.cpp
index a04bce26b..4bf0ba088 100644
--- a/src/Cpu_stub.cpp
+++ b/src/Cpu_stub.cpp
@@ -22,7 +22,12 @@
  */
 
 
-#include <cpuid.h>
+#ifdef _MSC_VER
+#   include <intrin.h>
+#else
+#   include <cpuid.h>
+#endif
+
 #include <string.h>
 
 
@@ -45,7 +50,7 @@
 
 static inline void cpuid(int level, int output[4]) {
     int a, b, c, d;
-    __cpuid_count(level, 0, a, b, c, d);
+    //__cpuid_count(level, 0, a, b, c, d);
 
     output[0] = a;
     output[1] = b;
@@ -73,7 +78,8 @@ static inline bool has_aes_ni()
     int cpu_info[4] = { 0 };
     cpuid(PROCESSOR_INFO, cpu_info);
 
-    return cpu_info[ECX_Reg] & bit_AES;
+    return false;
+    //return cpu_info[ECX_Reg] & bit_AES;
 }
 
 
@@ -81,7 +87,8 @@ static inline bool has_bmi2() {
     int cpu_info[4] = { 0 };
     cpuid(EXTENDED_FEATURES, cpu_info);
 
-    return cpu_info[EBX_Reg] & bit_BMI2;
+    return false;
+    //return cpu_info[EBX_Reg] & bit_BMI2;
 }
 
 
diff --git a/src/Mem.h b/src/Mem.h
index 9a438a175..89635e332 100644
--- a/src/Mem.h
+++ b/src/Mem.h
@@ -28,6 +28,9 @@
 #include <stdint.h>
 
 
+#include "align.h"
+
+
 struct cryptonight_ctx;
 
 
@@ -55,7 +58,7 @@ private:
     static int m_flags;
     static int m_threads;
     static size_t m_offset;
-    static uint8_t *m_memory __attribute__((aligned(16)));
+    VAR_ALIGN(16, static uint8_t *m_memory);
 
 #   ifndef XMRIG_NO_AEON
     static cryptonight_ctx *createLite(int threadId);
diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp
index f9a7ab3db..c5e606f77 100644
--- a/src/Mem_win.cpp
+++ b/src/Mem_win.cpp
@@ -26,8 +26,12 @@
 #include <windows.h>
 #include <ntsecapi.h>
 #include <tchar.h>
-#include <mm_malloc.h>
 
+#ifdef __GNUC__
+#   include <mm_malloc.h>
+#else
+#   include <malloc.h>
+#endif
 
 #include "Console.h"
 #include "crypto/CryptoNight.h"
diff --git a/src/Options.cpp b/src/Options.cpp
index a2702a653..9ba9acf7f 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -24,8 +24,12 @@
 
 #include <uv.h>
 #include <jansson.h>
-#include <getopt.h>
 
+#ifdef _MSC_VER
+#include "getopt/getopt.h"
+#else
+#include <getopt.h>
+#endif
 
 #include "Console.h"
 #include "Cpu.h"
@@ -387,7 +391,7 @@ void Options::showUsage(int status) const
 
 void Options::showVersion()
 {
-    printf(APP_NAME " " APP_VERSION "\n built on " __DATE__
+ /*   printf(APP_NAME " " APP_VERSION "\n built on " __DATE__)
 
     #ifdef __GNUC__
     " with GCC");
@@ -404,7 +408,7 @@ void Options::showVersion()
     #ifdef __AES__
     " AES-NI"
     #endif
-    "\n");
+    "\n");*/
 
     printf("\nlibuv/%s\n", uv_version_string());
     printf("libjansson/%s\n", JANSSON_VERSION);
@@ -438,7 +442,7 @@ bool Options::setAlgo(const char *algo)
 
 bool Options::setUserpass(const char *userpass)
 {
-    char *p = strchr(userpass, ':');
+    const char *p = strchr(userpass, ':');
     if (!p) {
         showUsage(1);
         return false;
diff --git a/src/Summary.cpp b/src/Summary.cpp
index 502747c95..7d5f920f4 100644
--- a/src/Summary.cpp
+++ b/src/Summary.cpp
@@ -35,7 +35,7 @@
 
 static void print_versions()
 {
-    char *buf = static_cast<char*>(alloca(16));
+    char buf[16];
 
 #   ifdef __GNUC__
     snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
@@ -87,7 +87,7 @@ static void print_cpu()
 
 static void print_threads()
 {
-    char *buf = static_cast<char*>(alloca(32));
+    char buf[32];
     if (Options::i()->affinity() != -1L) {
         snprintf(buf, 32, ", affinity=0x%llX", Options::i()->affinity());
     }
diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h
index fbb2f9753..2ed5dfb20 100644
--- a/src/crypto/CryptoNight.h
+++ b/src/crypto/CryptoNight.h
@@ -28,14 +28,17 @@
 #include <stdint.h>
 
 
+#include "align.h"
+
+
 #define MEMORY      2097152 /* 2 MiB */
 #define MEMORY_LITE 1048576 /* 1 MiB */
 
 
 struct cryptonight_ctx {
-    uint8_t state0[200] __attribute__((aligned(16)));
-    uint8_t state1[200] __attribute__((aligned(16)));
-    uint8_t* memory     __attribute__((aligned(16)));
+    VAR_ALIGN(16, uint8_t state0[200]);
+    VAR_ALIGN(16, uint8_t state1[200]);
+    VAR_ALIGN(16, uint8_t* memory);
 };
 
 
diff --git a/src/crypto/CryptoNight_p.h b/src/crypto/CryptoNight_p.h
index ed24a510b..b44b6616e 100644
--- a/src/crypto/CryptoNight_p.h
+++ b/src/crypto/CryptoNight_p.h
@@ -25,7 +25,12 @@
 #define __CRYPTONIGHT_P_H__
 
 
-#include <x86intrin.h>
+#ifdef __GNUC__
+#   include <x86intrin.h>
+#else
+#   include <intrin.h>
+#   define __restrict__ __restrict
+#endif
 
 
 #include "crypto/CryptoNight.h"
@@ -68,15 +73,19 @@ void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, d
 
 
 
-#if defined(__x86_64__)
+#if defined(__x86_64__) || defined(_WIN64)
 #   define EXTRACT64(X) _mm_cvtsi128_si64(X)
 
+#   ifdef __GNUC__
 static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
 {
     unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
     *hi = r >> 64;
     return (uint64_t) r;
 }
+#   else
+    #define __umul128 _umul128
+#   endif
 #elif defined(__i386__)
 #   define HI32(X) \
     _mm_srli_si128((X), 4)
@@ -224,7 +233,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
     xin6 = _mm_load_si128(input + 10);
     xin7 = _mm_load_si128(input + 11);
 
-    for (size_t i = 0; __builtin_expect(i < MEM / sizeof(__m128i), 1); i += 8) {
+    for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
         aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
         aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
         aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
@@ -265,7 +274,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
     xout6 = _mm_load_si128(output + 10);
     xout7 = _mm_load_si128(output + 11);
 
-    for (size_t i = 0; __builtin_expect(i < MEM / sizeof(__m128i), 1); i += 8)
+    for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
     {
         xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
         xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
@@ -315,7 +324,7 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
 
     uint64_t idx0 = h0[0] ^ h0[4];
 
-    for (size_t i = 0; __builtin_expect(i < ITERATIONS, 1); i++) {
+    for (size_t i = 0; i < ITERATIONS; i++) {
         __m128i cx;
         cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
         cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
@@ -372,7 +381,7 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size,
     uint64_t idx0 = h0[0] ^ h0[4];
     uint64_t idx1 = h1[0] ^ h1[4];
 
-    for (size_t i = 0; __builtin_expect(i < ITERATIONS, 1); i++) {
+    for (size_t i = 0; i < ITERATIONS; i++) {
         __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
         __m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
 
diff --git a/src/net/Job.h b/src/net/Job.h
index 4f08e84cf..9848f1283 100644
--- a/src/net/Job.h
+++ b/src/net/Job.h
@@ -28,6 +28,9 @@
 #include <stdint.h>
 
 
+#include "align.h"
+
+
 class Job
 {
 public:
@@ -52,8 +55,8 @@ public:
 
 private:
     int m_poolId;
-    char m_id[64]      __attribute__((aligned(16)));
-    uint8_t m_blob[84] __attribute__((aligned(16))); // 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, 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;
     uint64_t m_diff;
     uint64_t m_target;
diff --git a/src/net/Url.cpp b/src/net/Url.cpp
index 4e1dfd9fe..d8264c20e 100644
--- a/src/net/Url.cpp
+++ b/src/net/Url.cpp
@@ -29,6 +29,11 @@
 #include "net/Url.h"
 
 
+#ifdef _MSC_VER
+#   define strncasecmp(x,y,z) _strnicmp(x,y,z)
+#endif
+
+
 Url::Url() :
     m_host(nullptr),
     m_port(3333)
@@ -66,7 +71,7 @@ Url::Url(const char *url) :
         return;
     }
 
-    char *port = strchr(base, ':');
+    const char *port = strchr(base, ':');
     if (!port) {
         m_host = strdup(base);
         return;
diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp
index 76fea5883..c97d10b12 100644
--- a/src/workers/Handle.cpp
+++ b/src/workers/Handle.cpp
@@ -35,7 +35,7 @@ Handle::Handle(int threadId, int threads, int64_t affinity, bool nicehash) :
 }
 
 
-void Handle::start(void *(*callback) (void *))
+void Handle::start(void (*callback) (void *))
 {
-    pthread_create(&m_thread, nullptr, callback, this);
+    uv_thread_create(&m_thread, callback, this);
 }
diff --git a/src/workers/Handle.h b/src/workers/Handle.h
index 6b2b1d37c..96a512e37 100644
--- a/src/workers/Handle.h
+++ b/src/workers/Handle.h
@@ -25,8 +25,8 @@
 #define __HANDLE_H__
 
 
-#include <pthread.h>
 #include <stdint.h>
+#include <uv.h>
 
 
 class IWorker;
@@ -36,7 +36,7 @@ class Handle
 {
 public:
     Handle(int threadId, int threads, int64_t affinity, bool nicehash);
-    void start(void *(*callback) (void *));
+    void start(void (*callback) (void *));
 
     inline bool nicehash() const           { return m_nicehash; }
     inline int threadId() const            { return m_threadId; }
@@ -51,7 +51,7 @@ private:
     int m_threads;
     int64_t m_affinity;
     IWorker *m_worker;
-    pthread_t m_thread;
+    uv_thread_t m_thread;
 };
 
 
diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp
index 263f08595..3969e883e 100644
--- a/src/workers/SingleWorker.cpp
+++ b/src/workers/SingleWorker.cpp
@@ -22,11 +22,9 @@
  */
 
 
-#include <atomic>
 #include <thread>
 
 
-#include "Console.h"
 #include "crypto/CryptoNight.h"
 #include "workers/SingleWorker.h"
 #include "workers/Workers.h"
@@ -62,7 +60,7 @@ void SingleWorker::start()
                 Workers::submit(m_result);
             }
 
-            sched_yield();
+//            sched_yield();
         }
 
         consumeJob();
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
index 832d7da00..b3673445b 100644
--- a/src/workers/Workers.cpp
+++ b/src/workers/Workers.cpp
@@ -34,8 +34,6 @@
 
 IJobResultListener *Workers::m_listener = nullptr;
 Job Workers::m_job;
-pthread_mutex_t Workers::m_mutex;
-pthread_rwlock_t Workers::m_rwlock;
 std::atomic<int> Workers::m_paused;
 std::atomic<uint64_t> Workers::m_sequence;
 std::list<JobResult> Workers::m_queue;
@@ -43,14 +41,16 @@ std::vector<Handle*> Workers::m_workers;
 Telemetry *Workers::m_telemetry = nullptr;
 uint64_t Workers::m_ticks = 0;
 uv_async_t Workers::m_async;
+uv_mutex_t Workers::m_mutex;
+uv_rwlock_t Workers::m_rwlock;
 uv_timer_t Workers::m_timer;
 
 
 Job Workers::job()
 {
-    pthread_rwlock_rdlock(&m_rwlock);
+    uv_rwlock_rdlock(&m_rwlock);
     Job job = m_job;
-    pthread_rwlock_unlock(&m_rwlock);
+    uv_rwlock_rdunlock(&m_rwlock);
 
     return std::move(job);
 }
@@ -58,9 +58,9 @@ Job Workers::job()
 
 void Workers::setJob(const Job &job)
 {
-    pthread_rwlock_wrlock(&m_rwlock);
+    uv_rwlock_wrlock(&m_rwlock);
     m_job = job;
-    pthread_rwlock_unlock(&m_rwlock);
+    uv_rwlock_wrunlock(&m_rwlock);
 
     m_sequence++;
     m_paused = 0;
@@ -71,15 +71,15 @@ void Workers::start(int threads, int64_t affinity, bool nicehash)
 {
     m_telemetry = new Telemetry(threads);
 
-    pthread_mutex_init(&m_mutex, nullptr);
-    pthread_rwlock_init(&m_rwlock, nullptr);
+    uv_mutex_init(&m_mutex);
+    uv_rwlock_init(&m_rwlock);
 
     m_sequence = 0;
     m_paused   = 1;
 
     uv_async_init(uv_default_loop(), &m_async, Workers::onResult);
     uv_timer_init(uv_default_loop(), &m_timer);
-    uv_timer_start(&m_timer, Workers::onPerfTick, 500, 500);
+    uv_timer_start(&m_timer, Workers::onTick, 500, 500);
 
     for (int i = 0; i < threads; ++i) {
         Handle *handle = new Handle(i, threads, affinity, nicehash);
@@ -91,26 +91,43 @@ void Workers::start(int threads, int64_t affinity, bool nicehash)
 
 void Workers::submit(const JobResult &result)
 {
-    pthread_mutex_lock(&m_mutex);
+    uv_mutex_lock(&m_mutex);
     m_queue.push_back(result);
-    pthread_mutex_unlock(&m_mutex);
+    uv_mutex_unlock(&m_mutex);
 
     uv_async_send(&m_async);
 }
 
 
 
-void *Workers::onReady(void *arg)
+void Workers::onReady(void *arg)
 {
     auto handle = static_cast<Handle*>(arg);
     IWorker *worker = new SingleWorker(handle);
     worker->start();
-
-    return nullptr;
 }
 
 
-void Workers::onPerfTick(uv_timer_t *handle)
+void Workers::onResult(uv_async_t *handle)
+{
+    std::list<JobResult> results;
+
+    uv_mutex_lock(&m_mutex);
+    while (!m_queue.empty()) {
+        results.push_back(std::move(m_queue.front()));
+        m_queue.pop_front();
+    }
+    uv_mutex_unlock(&m_mutex);
+
+    for (auto result : results) {
+        m_listener->onJobResult(result);
+    }
+
+    results.clear();
+}
+
+
+void Workers::onTick(uv_timer_t *handle)
 {
     for (Handle *handle : m_workers) {
         m_telemetry->add(handle->threadId(), handle->worker()->hashCount(), handle->worker()->timestamp());
@@ -137,22 +154,3 @@ void Workers::onPerfTick(uv_timer_t *handle)
         }
     }
 }
-
-
-void Workers::onResult(uv_async_t *handle)
-{
-    std::list<JobResult> results;
-
-    pthread_mutex_lock(&m_mutex);
-    while (!m_queue.empty()) {
-        results.push_back(std::move(m_queue.front()));
-        m_queue.pop_front();
-    }
-    pthread_mutex_unlock(&m_mutex);
-
-    for (auto result : results) {
-        m_listener->onJobResult(result);
-    }
-
-    results.clear();
-}
diff --git a/src/workers/Workers.h b/src/workers/Workers.h
index f7a0e43a8..5e3981096 100644
--- a/src/workers/Workers.h
+++ b/src/workers/Workers.h
@@ -27,7 +27,6 @@
 
 #include <atomic>
 #include <list>
-#include <pthread.h>
 #include <uv.h>
 #include <vector>
 
@@ -55,14 +54,12 @@ public:
     static inline void setListener(IJobResultListener *listener) { m_listener = listener; }
 
 private:
-    static void *onReady(void *arg);
-    static void onPerfTick(uv_timer_t *handle);
+    static void onReady(void *arg);
     static void onResult(uv_async_t *handle);
+    static void onTick(uv_timer_t *handle);
 
     static IJobResultListener *m_listener;
     static Job m_job;
-    static pthread_mutex_t m_mutex;
-    static pthread_rwlock_t m_rwlock;
     static std::atomic<int> m_paused;
     static std::atomic<uint64_t> m_sequence;
     static std::list<JobResult> m_queue;
@@ -70,6 +67,8 @@ private:
     static Telemetry *m_telemetry;
     static uint64_t m_ticks;
     static uv_async_t m_async;
+    static uv_mutex_t m_mutex;
+    static uv_rwlock_t m_rwlock;
     static uv_timer_t m_timer;
 };
 

From 9580c30d8a6857e89c6b0399a422b958584b290f Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Mon, 12 Jun 2017 16:55:21 +0300
Subject: [PATCH 39/56] Fix cpuid stub for MSVC.

---
 src/Cpu_stub.cpp           | 29 ++++++++++++++++++-----------
 src/crypto/CryptoNight_p.h |  4 ++--
 2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/src/Cpu_stub.cpp b/src/Cpu_stub.cpp
index 4bf0ba088..0b9196eea 100644
--- a/src/Cpu_stub.cpp
+++ b/src/Cpu_stub.cpp
@@ -22,11 +22,14 @@
  */
 
 
-#ifdef _MSC_VER
-#   include <intrin.h>
-#else
-#   include <cpuid.h>
-#endif
+#ifdef _MSC_VER
+#   include <intrin.h>
+
+#   define bit_AES  (1 << 25)
+#   define bit_BMI2 (1 << 8)
+#else
+#   include <cpuid.h>
+#endif
 
 #include <string.h>
 
@@ -48,15 +51,21 @@
 #define EDX_Reg  (3)
 
 
+#ifdef _MSC_VER
+static inline void cpuid(int level, int output[4]) {
+    __cpuid(output, level);
+}
+#else
 static inline void cpuid(int level, int output[4]) {
     int a, b, c, d;
-    //__cpuid_count(level, 0, a, b, c, d);
+    __cpuid_count(level, 0, a, b, c, d);
 
     output[0] = a;
     output[1] = b;
     output[2] = c;
     output[3] = d;
 }
+#endif
 
 
 static inline void cpu_brand_string(char* s) {
@@ -78,8 +87,7 @@ static inline bool has_aes_ni()
     int cpu_info[4] = { 0 };
     cpuid(PROCESSOR_INFO, cpu_info);
 
-    return false;
-    //return cpu_info[ECX_Reg] & bit_AES;
+    return cpu_info[ECX_Reg] & bit_AES;
 }
 
 
@@ -87,8 +95,7 @@ static inline bool has_bmi2() {
     int cpu_info[4] = { 0 };
     cpuid(EXTENDED_FEATURES, cpu_info);
 
-    return false;
-    //return cpu_info[EBX_Reg] & bit_BMI2;
+    return cpu_info[EBX_Reg] & bit_BMI2;
 }
 
 
@@ -112,7 +119,7 @@ void Cpu::initCommon()
 {
     cpu_brand_string(m_brand);
 
-#   ifdef __x86_64__
+#   if defined(__x86_64__) || defined(_M_AMD64)
     m_flags |= X86_64;
 #   endif
 
diff --git a/src/crypto/CryptoNight_p.h b/src/crypto/CryptoNight_p.h
index b44b6616e..8a5268f4e 100644
--- a/src/crypto/CryptoNight_p.h
+++ b/src/crypto/CryptoNight_p.h
@@ -73,7 +73,7 @@ void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, d
 
 
 
-#if defined(__x86_64__) || defined(_WIN64)
+#if defined(__x86_64__) || defined(_M_AMD64)
 #   define EXTRACT64(X) _mm_cvtsi128_si64(X)
 
 #   ifdef __GNUC__
@@ -86,7 +86,7 @@ static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
 #   else
     #define __umul128 _umul128
 #   endif
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(_M_IX86)
 #   define HI32(X) \
     _mm_srli_si128((X), 4)
 

From 42bf85d10b9f77b9fc6853fb29420087d1989cf8 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Tue, 13 Jun 2017 06:31:25 +0300
Subject: [PATCH 40/56] Fixes for MSVC.

---
 src/Options.cpp         | 31 +++++++++++++++++++------------
 src/Summary.cpp         |  4 +++-
 src/net/Network_win.cpp | 18 +++++++++++++-----
 src/version.h           | 16 ++++++++++++++++
 4 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/src/Options.cpp b/src/Options.cpp
index 9ba9acf7f..c38f417bb 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -25,12 +25,14 @@
 #include <uv.h>
 #include <jansson.h>
 
+
 #ifdef _MSC_VER
-#include "getopt/getopt.h"
+#   include "getopt/getopt.h"
 #else
-#include <getopt.h>
+#   include <getopt.h>
 #endif
 
+
 #include "Console.h"
 #include "Cpu.h"
 #include "donate.h"
@@ -391,24 +393,29 @@ void Options::showUsage(int status) const
 
 void Options::showVersion()
 {
- /*   printf(APP_NAME " " APP_VERSION "\n built on " __DATE__)
+    printf(APP_NAME " " APP_VERSION "\n built on " __DATE__
 
-    #ifdef __GNUC__
+#   if defined(__GNUC__)
     " with GCC");
     printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
-    #endif
+#   elif defined(_MSC_VER)
+    " with MSVC");
+    printf(" %d", MSVC_VERSION);
+#   else
+    );
+#   endif
 
     printf("\n features:"
-    #ifdef __i386__
+#   if defined(__i386__) || defined(_M_IX86)
     " i386"
-    #endif
-    #ifdef __x86_64__
+#   elif defined(__x86_64__) || defined(_M_AMD64)
     " x86_64"
-    #endif
-    #ifdef __AES__
+#   endif
+
+#   if defined(__AES__) || defined(_MSC_VER)
     " AES-NI"
-    #endif
-    "\n");*/
+#   endif
+    "\n");
 
     printf("\nlibuv/%s\n", uv_version_string());
     printf("libjansson/%s\n", JANSSON_VERSION);
diff --git a/src/Summary.cpp b/src/Summary.cpp
index 7d5f920f4..8c7d3ea31 100644
--- a/src/Summary.cpp
+++ b/src/Summary.cpp
@@ -37,8 +37,10 @@ static void print_versions()
 {
     char buf[16];
 
-#   ifdef __GNUC__
+#   if defined(__GNUC__)
     snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
+#   elif defined(_MSC_VER)
+    snprintf(buf, 16, " MSVC/%d", MSVC_VERSION);
 #   else
     buf[0] = '\0';
 #   endif
diff --git a/src/net/Network_win.cpp b/src/net/Network_win.cpp
index 432ea71ee..15b358b57 100644
--- a/src/net/Network_win.cpp
+++ b/src/net/Network_win.cpp
@@ -22,7 +22,7 @@
  */
 
 
-#include <uv.h>
+#include <winsock2.h>
 #include <windows.h>
 
 
@@ -51,13 +51,21 @@ static inline OSVERSIONINFOEX winOsVersion()
 char *Network::userAgent()
 {
     const auto osver = winOsVersion();
+    const size_t max = 128;
 
-    char *buf = static_cast<char*>(malloc(128));
+    char *buf = static_cast<char*>(malloc(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)
+    length += snprintf(buf + length, max - length, "; Win64; x64) libuv/%s", uv_version_string());
+#   else
+    length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string());
+#   endif
 
 #   ifdef __GNUC__
-    snprintf(buf, 128, "%s/%s (Windows NT %lu.%lu; Win64; x64) libuv/%s gcc/%d.%d.%d", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion, uv_version_string(), __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
-#   else
-    snprintf(buf, 128, "%s/%s (Windows NT %lu.%lu; Win64; x64) libuv/%s", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion, uv_version_string());
+    length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
+#elif _MSC_VER
+    length += snprintf(buf + length, max - length, " msvc/%d", MSVC_VERSION);
 #   endif
 
     return buf;
diff --git a/src/version.h b/src/version.h
index d7bde178a..326b65672 100644
--- a/src/version.h
+++ b/src/version.h
@@ -37,4 +37,20 @@
 #define APP_VER_BUILD  0
 #define APP_VER_REV    0
 
+#ifdef _MSC_VER
+#   if _MSC_VER == 1910
+#       define MSVC_VERSION 2017
+#   elif _MSC_VER == 1900
+#       define MSVC_VERSION 2015
+#   elif _MSC_VER == 1800
+#       define MSVC_VERSION 2013
+#   elif _MSC_VER == 1700
+#       define MSVC_VERSION 2012
+#   elif _MSC_VER == 1600
+#       define MSVC_VERSION 2010
+#   else
+#       define MSVC_VERSION 0
+#   endif
+#endif
+
 #endif /* __VERSION_H__ */

From de2c351a6616b852824931169add498a7c04a776 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Tue, 13 Jun 2017 10:08:32 +0300
Subject: [PATCH 41/56] Add MSVC optimization options.

---
 CMakeLists.txt | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ed96a8c2c..9badb06da 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -100,7 +100,7 @@ endif()
 
 
 # https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
-if (CMAKE_C_COMPILER_ID STREQUAL GNU)
+if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
 
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall -fno-exceptions")
     set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
@@ -114,11 +114,12 @@ if (CMAKE_C_COMPILER_ID STREQUAL GNU)
 
     #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
 
-elseif (CMAKE_C_COMPILER_ID STREQUAL MSVC)
+elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
 
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MT")
+    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")
 
-elseif (CMAKE_C_COMPILER_ID MATCHES "Clang")
+elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
 
     set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -fmerge-all-constants")
     set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -fmerge-all-constants")

From 827e6119114f8e9d31af31a2501ffe67a97b478f Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Tue, 13 Jun 2017 11:17:40 +0300
Subject: [PATCH 42/56] Fix libcpuid support for MSVC.

---
 src/3rdparty/libcpuid/CMakeLists.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/3rdparty/libcpuid/CMakeLists.txt b/src/3rdparty/libcpuid/CMakeLists.txt
index ef541cc30..51eab1d36 100644
--- a/src/3rdparty/libcpuid/CMakeLists.txt
+++ b/src/3rdparty/libcpuid/CMakeLists.txt
@@ -26,7 +26,13 @@ set(SOURCES
     libcpuid_util.c
    )
 
+if (CMAKE_CL_64)
+    enable_language(ASM_MASM)
+    set(SOURCES_ASM masm-x64.asm)
+endif()
+
 add_library(cpuid STATIC
     ${HEADERS}
     ${SOURCES}
+    ${SOURCES_ASM}
     )

From 2d08f59184981d864cedd1a5c7fb42c464e04416 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Tue, 13 Jun 2017 11:51:49 +0300
Subject: [PATCH 43/56] Remove obsolete source files.

---
 compat.h  |  47 ----
 elist.h   | 274 ---------------------
 stats.c   | 137 -----------
 stats.h   |  37 ---
 stratum.c | 718 ------------------------------------------------------
 stratum.h |  78 ------
 util.c    | 270 --------------------
 util.h    |  43 ----
 xmrig.c   | 677 --------------------------------------------------
 xmrig.h   |  57 -----
 10 files changed, 2338 deletions(-)
 delete mode 100644 compat.h
 delete mode 100644 elist.h
 delete mode 100644 stats.c
 delete mode 100644 stats.h
 delete mode 100644 stratum.c
 delete mode 100644 stratum.h
 delete mode 100644 util.c
 delete mode 100644 util.h
 delete mode 100644 xmrig.c
 delete mode 100644 xmrig.h

diff --git a/compat.h b/compat.h
deleted file mode 100644
index bf488226e..000000000
--- a/compat.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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/>.
- */
-
-#ifndef __COMPAT_H__
-#define __COMPAT_H__
-
-#define unlikely(expr) (__builtin_expect(!!(expr), 0))
-#define likely(expr)   (__builtin_expect(!!(expr), 1))
-
-#ifdef WIN32
-
-#include <windows.h>
-
-#define sleep(secs) Sleep((secs) * 1000)
-
-enum {
-	PRIO_PROCESS		= 0,
-};
-
-static inline int setpriority(int which, int who, int prio)
-{
-	return -!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
-}
-
-#endif /* WIN32 */
-
-#endif /* __COMPAT_H__ */
diff --git a/elist.h b/elist.h
deleted file mode 100644
index a13561843..000000000
--- a/elist.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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/>.
- */
-
-#ifndef _LINUX_LIST_H
-#define _LINUX_LIST_H
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
-	struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
-	struct list_head name = LIST_HEAD_INIT(name)
-
-#define INIT_LIST_HEAD(ptr) do { \
-	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
-			      struct list_head *prev,
-			      struct list_head *next)
-{
-	next->prev = new;
-	new->next = next;
-	new->prev = prev;
-	prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
-	__list_add(new, head, head->next);
-}
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
-	__list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head *prev, struct list_head *next)
-{
-	next->prev = prev;
-	prev->next = next;
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
-	__list_del(entry->prev, entry->next);
-	entry->next = (void *) 0;
-	entry->prev = (void *) 0;
-}
-
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
-{
-	__list_del(entry->prev, entry->next);
-	INIT_LIST_HEAD(entry);
-}
-
-/**
- * list_move - delete from one list and add as another's head
- * @list: the entry to move
- * @head: the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
-{
-        __list_del(list->prev, list->next);
-        list_add(list, head);
-}
-
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @list: the entry to move
- * @head: the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
-				  struct list_head *head)
-{
-        __list_del(list->prev, list->next);
-        list_add_tail(list, head);
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(struct list_head *head)
-{
-	return head->next == head;
-}
-
-static inline void __list_splice(struct list_head *list,
-				 struct list_head *head)
-{
-	struct list_head *first = list->next;
-	struct list_head *last = list->prev;
-	struct list_head *at = head->next;
-
-	first->prev = head;
-	head->next = first;
-
-	last->next = at;
-	at->prev = last;
-}
-
-/**
- * list_splice - join two lists
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice(struct list_head *list, struct list_head *head)
-{
-	if (!list_empty(list))
-		__list_splice(list, head);
-}
-
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * The list at @list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
-				    struct list_head *head)
-{
-	if (!list_empty(list)) {
-		__list_splice(list, head);
-		INIT_LIST_HEAD(list);
-	}
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr:	the &struct list_head pointer.
- * @type:	the type of the struct this is embedded in.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
-	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
-
-/**
- * list_for_each	-	iterate over a list
- * @pos:	the &struct list_head to use as a loop counter.
- * @head:	the head for your list.
- */
-#define list_for_each(pos, head) \
-	for (pos = (head)->next; pos != (head); \
-        	pos = pos->next)
-/**
- * list_for_each_prev	-	iterate over a list backwards
- * @pos:	the &struct list_head to use as a loop counter.
- * @head:	the head for your list.
- */
-#define list_for_each_prev(pos, head) \
-	for (pos = (head)->prev; pos != (head); \
-        	pos = pos->prev)
-
-/**
- * list_for_each_safe	-	iterate over a list safe against removal of list entry
- * @pos:	the &struct list_head to use as a loop counter.
- * @n:		another &struct list_head to use as temporary storage
- * @head:	the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
-	for (pos = (head)->next, n = pos->next; pos != (head); \
-		pos = n, n = pos->next)
-
-/**
- * list_for_each_entry	-	iterate over list of given type
- * @pos:	the type * to use as a loop counter.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_for_each_entry(pos, head, member)				\
-	for (pos = list_entry((head)->next, typeof(*pos), member);	\
-	     &pos->member != (head); 					\
-	     pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos:	the type * to use as a loop counter.
- * @n:		another type * to use as temporary storage
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member)			\
-	for (pos = list_entry((head)->next, typeof(*pos), member),	\
-		n = list_entry(pos->member.next, typeof(*pos), member);	\
-	     &pos->member != (head); 					\
-	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_continue -       iterate over list of given type
- *                      continuing after existing point
- * @pos:        the type * to use as a loop counter.
- * @head:       the head for your list.
- * @member:     the name of the list_struct within the struct.
- */
-#define list_for_each_entry_continue(pos, head, member)			\
-	for (pos = list_entry(pos->member.next, typeof(*pos), member),	\
-		     prefetch(pos->member.next);			\
-	     &pos->member != (head);					\
-	     pos = list_entry(pos->member.next, typeof(*pos), member),	\
-		     prefetch(pos->member.next))
-
-#endif
diff --git a/stats.c b/stats.c
deleted file mode 100644
index ee1316724..000000000
--- a/stats.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <pthread.h>
-#include <sys/time.h>
-#include <stdlib.h>
-
-#include "stats.h"
-#include "options.h"
-#include "utils/applog.h"
-#include "persistent_memory.h"
-
-
-static unsigned long accepted_count = 0L;
-static unsigned long rejected_count = 0L;
-static double *thr_hashrates;
-static double *thr_times;
-static uint32_t target = 0;
-
-pthread_mutex_t stats_lock;
-
-
-static int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y);
-
-
-/**
- * @brief stats_init
- */
-void stats_init() {
-    pthread_mutex_init(&stats_lock, NULL);
-
-    thr_hashrates = (double *) persistent_calloc(opt_n_threads, sizeof(double));
-    thr_times = (double *) persistent_calloc(opt_n_threads, sizeof(double));
-}
-
-
-
-/**
- * @brief stats_set_target
- * @param target
- */
-void stats_set_target(uint32_t new_target)
-{
-    target = new_target;
-
-    applog(LOG_DEBUG, "Pool set diff to %g", ((double) 0xffffffff) / target);
-}
-
-
-/**
- * @brief stats_share_result
- * @param result
- */
-void stats_share_result(bool success)
-{
-    double hashrate = 0.0;
-
-    pthread_mutex_lock(&stats_lock);
-
-    for (int i = 0; i < opt_n_threads; i++) {
-        if (thr_times[i] > 0) {
-            hashrate += thr_hashrates[i] / thr_times[i];
-        }
-    }
-
-    success ? accepted_count++ : rejected_count++;
-    pthread_mutex_unlock(&stats_lock);
-
-    applog(LOG_INFO, "accepted: %lu/%lu (%.2f%%), %.2f H/s at diff %g",
-            accepted_count, accepted_count + rejected_count,
-            100. * accepted_count / (accepted_count + rejected_count), hashrate,
-            (((double) 0xffffffff) / target));
-}
-
-
-void stats_add_hashes(int thr_id, struct timeval *tv_start, unsigned long hashes_done)
-{
-    struct timeval tv_end, diff;
-
-    /* record scanhash elapsed time */
-    gettimeofday(&tv_end, NULL);
-    timeval_subtract(&diff, &tv_end, tv_start);
-
-    if (diff.tv_usec || diff.tv_sec) {
-        pthread_mutex_lock(&stats_lock);
-        thr_hashrates[thr_id] = hashes_done;
-        thr_times[thr_id] = (diff.tv_sec + 1e-6 * diff.tv_usec);
-        pthread_mutex_unlock(&stats_lock);
-    }
-}
-
-
-/* Subtract the `struct timeval' values X and Y,
-   storing the result in RESULT.
-   Return 1 if the difference is negative, otherwise 0.  */
-static int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
-{
-    /* Perform the carry for the later subtraction by updating Y. */
-    if (x->tv_usec < y->tv_usec) {
-        int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
-        y->tv_usec -= 1000000 * nsec;
-        y->tv_sec += nsec;
-    }
-    if (x->tv_usec - y->tv_usec > 1000000) {
-        int nsec = (x->tv_usec - y->tv_usec) / 1000000;
-        y->tv_usec += 1000000 * nsec;
-        y->tv_sec -= nsec;
-    }
-
-    /* Compute the time remaining to wait.
-     * `tv_usec' is certainly positive. */
-    result->tv_sec = x->tv_sec - y->tv_sec;
-    result->tv_usec = x->tv_usec - y->tv_usec;
-
-    /* Return 1 if result is negative. */
-    return x->tv_sec < y->tv_sec;
-}
diff --git a/stats.h b/stats.h
deleted file mode 100644
index 13ec117eb..000000000
--- a/stats.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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/>.
- */
-
-#ifndef __STATS_H__
-#define __STATS_H__
-
-#include <stdbool.h>
-#include <inttypes.h>
-
-
-void stats_init();
-void stats_set_target(uint32_t new_target);
-void stats_share_result(bool success);
-void stats_add_hashes(int thr_id, struct timeval *tv_start, unsigned long hashes_done);
-
-
-#endif /* __STATS_H__ */
diff --git a/stratum.c b/stratum.c
deleted file mode 100644
index 4e9372519..000000000
--- a/stratum.c
+++ /dev/null
@@ -1,718 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <string.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <jansson.h>
-#include <unistd.h>
-
-#if defined(WIN32)
-#   include <winsock2.h>
-#   include <mstcpip.h>
-#else
-#   include <errno.h>
-#   include <netinet/tcp.h>
-#   include <poll.h>
-#endif
-
-#ifdef __APPLE_CC__
-#   include <netinet/in.h>
-#endif
-
-#include "stratum.h"
-#include "version.h"
-#include "stats.h"
-#include "util.h"
-#include "utils/applog.h"
-
-
-#ifdef WIN32
-#   define socket_blocks() (WSAGetLastError() == WSAEWOULDBLOCK)
-#   define poll(fdarray, nfds, timeout) WSAPoll(fdarray, nfds, timeout)
-#   define SHUT_RDWR SD_BOTH
-#else
-#   define socket_blocks() (errno == EAGAIN || errno == EWOULDBLOCK)
-#   define closesocket(x) close((x))
-#endif
-
-#define RBUFSIZE 2048
-#define RECVSIZE (RBUFSIZE - 4)
-
-#define unlikely(expr) (__builtin_expect(!!(expr), 0))
-
-
-static struct work work;
-
-
-static bool send_line(curl_socket_t sock, char *s);
-static bool socket_full(curl_socket_t sock, int timeout);
-static void buffer_append(struct stratum_ctx *sctx, const char *s);
-static bool job(struct stratum_ctx *sctx, json_t *params);
-static int sockopt_keepalive_cb(void *userdata, curl_socket_t fd, curlsocktype purpose);
-static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose, struct curl_sockaddr *addr);
-static int closesocket_cb(void *clientp, curl_socket_t item);
-static bool login_decode(struct stratum_ctx *sctx, const json_t *val);
-static bool job_decode(const json_t *job);
-static bool jobj_binary(const json_t *obj, const char *key, void *buf, size_t buflen);
-
-
-/**
- * @brief stratum_socket_full
- * @param sctx
- * @param timeout
- * @return
- */
-bool stratum_socket_full(struct stratum_ctx *sctx, int timeout)
-{
-    return strlen(sctx->sockbuf) || socket_full(sctx->sock, timeout);
-}
-
-
-/**
- * @brief stratum_send_line
- * @param sctx
- * @param s
- * @return
- */
-bool stratum_send_line(struct stratum_ctx *sctx, char *s)
-{
-    bool ret = false;
-
-    pthread_mutex_lock(&sctx->sock_lock);
-    ret = send_line(sctx->sock, s);
-    pthread_mutex_unlock(&sctx->sock_lock);
-
-    return ret;
-}
-
-
-/**
- * @brief stratum_recv_line
- * @param sctx
- * @return
- */
-char *stratum_recv_line(struct stratum_ctx *sctx)
-{
-    if (!strstr(sctx->sockbuf, "\n")) {
-        bool ret = true;
-        time_t rstart;
-
-        time(&rstart);
-
-        if (!socket_full(sctx->sock, 60)) {
-            applog(LOG_ERR, "stratum_recv_line timed out");
-            return NULL;
-        }
-
-        do {
-            char s[RBUFSIZE];
-            ssize_t n;
-
-            memset(s, 0, RBUFSIZE);
-            n = recv(sctx->sock, s, RECVSIZE, 0);
-            if (!n) {
-                ret = false;
-                break;
-            }
-
-            if (n < 0) {
-                if (!socket_blocks() || !socket_full(sctx->sock, 1)) {
-                    ret = false;
-                    break;
-                }
-            } else {
-                buffer_append(sctx, s);
-            }
-        } while (time(NULL) - rstart < 60 && !strstr(sctx->sockbuf, "\n"));
-
-        if (!ret) {
-            applog(LOG_ERR, "stratum_recv_line failed");
-            return NULL;
-        }
-    }
-
-    ssize_t buflen = strlen(sctx->sockbuf);
-    char *tok = strtok(sctx->sockbuf, "\n");
-
-    if (!tok) {
-        applog(LOG_ERR, "stratum_recv_line failed to parse a newline-terminated string");
-        return NULL;
-    }
-
-    char *sret = strdup(tok);
-    ssize_t len = strlen(sret);
-
-    if (buflen > len + 1) {
-        memmove(sctx->sockbuf, sctx->sockbuf + len + 1, buflen - len + 1);
-    }
-    else {
-        sctx->sockbuf[0] = '\0';
-    }
-
-    return sret;
-}
-
-
-/**
- * @brief stratum_disconnect
- * @param sctx
- */
-void stratum_disconnect(struct stratum_ctx *sctx)
-{
-    pthread_mutex_lock(&sctx->sock_lock);
-
-    sctx->ready = false;
-
-    if (sctx->curl) {
-        curl_easy_cleanup(sctx->curl);
-        sctx->curl = NULL;
-        sctx->sockbuf[0] = '\0';
-    }
-
-    pthread_mutex_unlock(&sctx->sock_lock);
-}
-
-
-/**
- * @brief stratum_handle_method
- * @param sctx
- * @param s
- * @return
- */
-bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
-{
-    bool ret = false;
-    const char *method;
-    json_t *val = json_decode(s);
-
-    if (!val) {
-        return false;
-    }
-
-    if (method = json_string_value(json_object_get(val, "method"))) {
-        if (!strcasecmp(method, "job")) {
-            ret = job(sctx, json_object_get(val, "params"));
-        }
-        else {
-            applog(LOG_WARNING, "Unknown method: \"%s\"", method);
-        }
-    }
-
-    json_decref(val);
-    return ret;
-}
-
-
-/**
- * @brief stratum_handle_response
- * @param buf
- * @return
- */
-bool stratum_handle_response(char *buf) {
-    bool valid = false;
-
-    json_t *val = json_decode(buf);
-    if (!val) {
-       return false;
-    }
-
-    json_t *res_val = json_object_get(val, "result");
-    json_t *err_val = json_object_get(val, "error");
-    json_t *id_val = json_object_get(val, "id");
-
-    if (!id_val || json_is_null(id_val) || !res_val) {
-        const char* message;
-
-        if (json_is_object(err_val) && (message = json_string_value(json_object_get(err_val, "message")))) {
-            applog(LOG_ERR, "error: \"%s\"", message);
-        }
-
-        json_decref(val);
-        return false;
-    }
-
-    json_t *status = json_object_get(res_val, "status");
-
-    if (status && !strcmp(json_string_value(status), "KEEPALIVED") ) {
-        applog(LOG_DEBUG, "Keepalived receveid");
-        json_decref(val);
-        return true;
-    }
-
-    if (status) {
-       valid = !strcmp(json_string_value(status), "OK") && json_is_null(err_val);
-    } else {
-       valid = json_is_null(err_val);
-    }
-
-    stats_share_result(valid);
-    json_decref(val);
-    return true;
-}
-
-
-/**
- * @brief stratum_keepalived
- * @param sctx
- * @return
- */
-bool stratum_keepalived(struct stratum_ctx *sctx)
-{
-    char *s = malloc(128);
-    snprintf(s, 128, "{\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"},\"id\":1}", sctx->id);
-    bool ret = stratum_send_line(sctx, s);
-
-    free(s);
-    return ret;
-}
-
-
-/**
- * @brief stratum_authorize
- * @param sctx
- * @param user
- * @param pass
- * @return
- */
-bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *pass)
-{
-    char *sret;
-
-    char *req = malloc(128 + strlen(user) + strlen(pass));
-    sprintf(req, "{\"method\":\"login\",\"params\":{\"login\":\"%s\",\"pass\":\"%s\",\"agent\":\"%s/%s\"},\"id\":1}", user, pass, APP_NAME, APP_VERSION);
-
-    if (!stratum_send_line(sctx, req)) {
-        free(req);
-        return false;
-    }
-
-    free(req);
-
-    while (1) {
-        sret = stratum_recv_line(sctx);
-        if (!sret) {
-            return false;
-        }
-
-        if (!stratum_handle_method(sctx, sret)) {
-            break;
-        }
-
-        free(sret);
-    }
-
-    json_t *val = json_decode(sret);
-    free(sret);
-
-    if (!val) {
-        return false;
-    }
-
-    json_t *result = json_object_get(val, "result");
-    json_t *error  = json_object_get(val, "error");
-
-    if (!result || json_is_false(result) || (error && !json_is_null(error)))  {
-        const char* message;
-
-        if (json_is_object(error) && (message = json_string_value(json_object_get(error, "message")))) {
-            applog(LOG_ERR, "Stratum authentication failed: \"%s\"", message);
-        }
-        else {
-            applog(LOG_ERR, "Stratum authentication failed");
-        }
-
-        json_decref(val);
-        return false;
-    }
-
-    if (login_decode(sctx, val) && job(sctx, json_object_get(result, "job"))) {
-        pthread_mutex_lock(&sctx->sock_lock);
-        sctx->ready = true;
-        pthread_mutex_unlock(&sctx->sock_lock);
-    }
-
-    json_decref(val);
-    return true;
-}
-
-
-/**
- * @brief stratum_connect
- * @param sctx
- * @param url
- * @return
- */
-bool stratum_connect(struct stratum_ctx *sctx, const char *url)
-{
-    CURL *curl;
-
-    pthread_mutex_lock(&sctx->sock_lock);
-    sctx->ready = false;
-
-    if (sctx->curl) {
-        curl_easy_cleanup(sctx->curl);
-    }
-
-    sctx->curl = curl_easy_init();
-    if (!sctx->curl) {
-        applog(LOG_ERR, "CURL initialization failed");
-        pthread_mutex_unlock(&sctx->sock_lock);
-        return false;
-    }
-
-    curl = sctx->curl;
-    if (!sctx->sockbuf) {
-        sctx->sockbuf = calloc(RBUFSIZE, 1);
-        sctx->sockbuf_size = RBUFSIZE;
-    }
-
-    sctx->sockbuf[0] = '\0';
-    pthread_mutex_unlock(&sctx->sock_lock);
-
-    if (url != sctx->url) {
-        free(sctx->url);
-        sctx->url = strdup(url);
-    }
-
-    free(sctx->curl_url);
-    sctx->curl_url = malloc(strlen(url));
-    sprintf(sctx->curl_url, "http%s/", strstr(url, "://"));
-
-    curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
-    curl_easy_setopt(curl, CURLOPT_URL, sctx->curl_url);
-    curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
-    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
-    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, sctx->curl_err_str);
-    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
-    curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
-    curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb);
-    curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket_grab_cb);
-    curl_easy_setopt(curl, CURLOPT_CLOSESOCKETFUNCTION, closesocket_cb);
-    curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sctx->sock);
-    curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1);
-    curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
-
-    int rc = curl_easy_perform(curl);
-    if (rc) {
-        applog(LOG_ERR, "Stratum connection failed: code: %d, text: %s", rc, sctx->curl_err_str);
-        curl_easy_cleanup(curl);
-        sctx->curl = NULL;
-        return false;
-    }
-
-    return true;
-}
-
-
-/**
- * @brief send_line
- * @param sock
- * @param s
- * @return
- */
-static bool send_line(curl_socket_t sock, char *s)
-{
-    ssize_t len, sent = 0;
-
-    len = strlen(s);
-    s[len++] = '\n';
-
-    while (len > 0) {
-        struct pollfd pfd;
-        pfd.fd = sock;
-        pfd.events = POLLOUT;
-
-        if (poll(&pfd, 1, 0) < 1) {
-            return false;
-        }
-
-        ssize_t n = send(sock, s + sent, len, 0);
-        if (n < 0) {
-            if (!socket_blocks()) {
-                return false;
-            }
-
-            n = 0;
-        }
-
-        sent += n;
-        len -= n;
-    }
-
-    return true;
-}
-
-
-/**
- * @brief socket_full
- * @param sock
- * @param timeout
- * @return
- */
-static bool socket_full(curl_socket_t sock, int timeout)
-{
-    struct pollfd pfd;
-    pfd.fd = sock;
-    pfd.events = POLLIN;
-
-    return poll(&pfd, 1, timeout * 1000) > 0;
-}
-
-
-/**
- * @brief buffer_append
- * @param sctx
- * @param s
- */
-static void buffer_append(struct stratum_ctx *sctx, const char *s)
-{
-    size_t old, new;
-
-    old = strlen(sctx->sockbuf);
-    new = old + strlen(s) + 1;
-
-    if (new >= sctx->sockbuf_size) {
-        sctx->sockbuf_size = new + (RBUFSIZE - (new % RBUFSIZE));
-        sctx->sockbuf = realloc(sctx->sockbuf, sctx->sockbuf_size);
-    }
-
-    strcpy(sctx->sockbuf + old, s);
-}
-
-
-/**
- * @brief job
- * @param sctx
- * @param params
- * @return
- */
-static bool job(struct stratum_ctx *sctx, json_t *params)
-{
-    if (!job_decode(params)) {
-        return false;
-    }
-
-    pthread_mutex_lock(&sctx->work_lock);
-
-    if (sctx->work.target != work.target) {
-        stats_set_target(work.target);
-    }
-
-    memcpy(&sctx->work, &work, sizeof(struct work));
-    pthread_mutex_unlock(&sctx->work_lock);
-
-    return true;
-}
-
-
-/**
- * @brief sockopt_keepalive_cb
- * @param userdata
- * @param fd
- * @param purpose
- * @return
- */
-static int sockopt_keepalive_cb(void *userdata, curl_socket_t fd, curlsocktype purpose)
-{
-    int keepalive = 1;
-    int tcp_keepcnt = 3;
-    int tcp_keepidle = 50;
-    int tcp_keepintvl = 50;
-
-#ifndef WIN32
-    if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)))) {
-        return 1;
-    }
-    
-#   ifdef __linux
-    if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_keepcnt, sizeof(tcp_keepcnt)))) {
-        return 1;
-    }
-    
-    if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle)))) {
-        return 1;
-    }
-    
-    if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl)))) {
-        return 1;
-    }
-#   endif /* __linux */
-    
-#   ifdef __APPLE_CC__
-    if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepintvl, sizeof(tcp_keepintvl)))) {
-        return 1;
-    }
-#   endif /* __APPLE_CC__ */
-#else /* WIN32 */
-    struct tcp_keepalive vals;
-    vals.onoff = 1;
-    vals.keepalivetime = tcp_keepidle * 1000;
-    vals.keepaliveinterval = tcp_keepintvl * 1000;
-    DWORD outputBytes;
-    
-    if (unlikely(WSAIoctl(fd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals), NULL, 0, &outputBytes, NULL, NULL))) {
-        return 1;
-    }
-
-#endif /* WIN32 */
-
-    return 0;
-}
-
-
-static int closesocket_cb(void *clientp, curl_socket_t item) {
-    shutdown(item, SHUT_RDWR);
-    return closesocket(item);
-}
-
-
-/**
- * @brief opensocket_grab_cb
- * @param clientp
- * @param purpose
- * @param addr
- * @return
- */
-static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose, struct curl_sockaddr *addr)
-{
-    curl_socket_t *sock = clientp;
-    *sock = socket(addr->family, addr->socktype, addr->protocol);
-    return *sock;
-}
-
-
-/**
- * @brief login_decode
- * @param sctx
- * @param val
- * @return
- */
-static bool login_decode(struct stratum_ctx *sctx, const json_t *val) {
-    json_t *res = json_object_get(val, "result");
-    if (!res) {
-        applog(LOG_ERR, "JSON invalid result");
-        return false;
-    }
-
-    const char *id = json_string_value(json_object_get(res, "id"));
-    if (!id || strlen(id) >= (sizeof(sctx->id))) {
-        applog(LOG_ERR, "JSON invalid id");
-        return false;
-    }
-
-    memset(&sctx->id, 0, sizeof(sctx->id));
-    memcpy(&sctx->id, id, strlen(id));
-
-    const char *s = json_string_value(json_object_get(res, "status"));
-    if (!s) {
-        applog(LOG_ERR, "JSON invalid status");
-        return false;
-    }
-
-    if (strcmp(s, "OK")) {
-        applog(LOG_ERR, "JSON returned status \"%s\"", s);
-        return false;
-    }
-
-    return true;
-}
-
-
-/**
- * @brief job_decode
- * @param sctx
- * @param job
- * @param work
- * @return
- */
-static bool job_decode(const json_t *job) {
-    const char *job_id = json_string_value(json_object_get(job, "job_id"));
-    if (!job_id || strlen(job_id) >= sizeof(work.job_id)) {
-        applog(LOG_ERR, "JSON invalid job id");
-        return false;
-    }
-
-    const char *blob = json_string_value(json_object_get(job, "blob"));
-    if (!blob) {
-        applog(LOG_ERR, "JSON invalid blob");
-        return false;
-    }
-
-    work.blob_size = strlen(blob);
-    if (work.blob_size % 2 != 0) {
-        applog(LOG_ERR, "JSON invalid blob length");
-        return false;
-    }
-
-    work.blob_size /= 2;
-    if (work.blob_size < 76 || work.blob_size > (sizeof(work.blob))) {
-        applog(LOG_ERR, "JSON invalid blob length");
-        return false;
-    }
-
-    if (!hex2bin((unsigned char *) work.blob, blob, work.blob_size)) {
-        applog(LOG_ERR, "JSON invalid blob");
-        return false;
-    }
-
-    jobj_binary(job, "target", &work.target, 4);
-
-    memset(work.job_id, 0, sizeof(work.job_id));
-    memcpy(work.job_id, job_id, strlen(job_id));
-
-    return true;
-}
-
-
-/**
- * @brief jobj_binary
- * @param obj
- * @param key
- * @param buf
- * @param buflen
- * @return
- */
-static bool jobj_binary(const json_t *obj, const char *key, void *buf, size_t buflen) {
-    const char *hexstr;
-    json_t *tmp;
-
-    tmp = json_object_get(obj, key);
-    if (unlikely(!tmp)) {
-        applog(LOG_ERR, "JSON key '%s' not found", key);
-        return false;
-    }
-
-    hexstr = json_string_value(tmp);
-    if (unlikely(!hexstr)) {
-        applog(LOG_ERR, "JSON key '%s' is not a string", key);
-        return false;
-    }
-
-
-    if (!hex2bin(buf, hexstr, buflen)) {
-        return false;
-    }
-
-    return true;
-}
diff --git a/stratum.h b/stratum.h
deleted file mode 100644
index 483695674..000000000
--- a/stratum.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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/>.
- */
-
-#ifndef __STRATUM_H__
-#define __STRATUM_H__
-
-#include <stdbool.h>
-#include <inttypes.h>
-#include <curl/curl.h>
-
-
-/**
- * 128tx exploit.
- *
- * Max blob size is 84 (75 fixed + 9 variable), aligned to 96.
- * https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk.
- */
-struct work {
-    uint32_t blob[21] __attribute__((aligned(16)));
-    size_t blob_size  __attribute__((aligned(16)));
-    uint32_t target   __attribute__((aligned(16)));
-    uint32_t hash[8]  __attribute__((aligned(16)));
-    char job_id[64]   __attribute__((aligned(16)));
-};
-
-
-struct stratum_ctx {
-    char *url;
-
-    CURL *curl;
-    char *curl_url;
-    char curl_err_str[CURL_ERROR_SIZE];
-    curl_socket_t sock;
-    size_t sockbuf_size;
-    char *sockbuf;
-    pthread_mutex_t sock_lock;
-    bool ready;
-
-    char id[64];
-
-    struct work work;
-    struct work g_work;
-    time_t g_work_time;
-    pthread_mutex_t work_lock;
-};
-
-
-bool stratum_send_line(struct stratum_ctx *sctx, char *s);
-bool stratum_socket_full(struct stratum_ctx *sctx, int timeout);
-char *stratum_recv_line(struct stratum_ctx *sctx);
-bool stratum_connect(struct stratum_ctx *sctx, const char *url);
-void stratum_disconnect(struct stratum_ctx *sctx);
-bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *pass);
-bool stratum_handle_method(struct stratum_ctx *sctx, const char *s);
-bool stratum_handle_response(char *buf);
-bool stratum_keepalived(struct stratum_ctx *sctx);
-
-#endif /* __STRATUM_H__ */
diff --git a/util.c b/util.c
deleted file mode 100644
index 3dfec485f..000000000
--- a/util.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <string.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <pthread.h>
-
-#include "util.h"
-#include "elist.h"
-#include "utils/applog.h"
-
-
-struct tq_ent {
-    void *data;
-    struct list_head q_node;
-};
-
-
-struct thread_q {
-    struct list_head q;
-    bool frozen;
-    pthread_mutex_t mutex;
-    pthread_cond_t cond;
-};
-
-
-json_t *json_decode(const char *s)
-{
-    json_error_t err;
-    json_t *val = json_loads(s, 0, &err);
-
-    if (!val) {
-        applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text);
-    }
-
-    return val;
-}
-
-
-/**
- * @brief bin2hex
- * @param p
- * @param len
- * @return
- */
-char *bin2hex(const unsigned char *p, size_t len)
-{
-    char *s = malloc((len * 2) + 1);
-    if (!s) {
-        return NULL;
-    }
-
-    for (int i = 0; i < len; i++) {
-        sprintf(s + (i * 2), "%02x", (unsigned int) p[i]);
-    }
-
-    return s;
-}
-
-
-/**
- * @brief hex2bin
- * @param p
- * @param hexstr
- * @param len
- * @return
- */
-bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
-{
-    char hex_byte[3];
-    char *ep;
-
-    hex_byte[2] = '\0';
-
-    while (*hexstr && len) {
-        if (!hexstr[1]) {
-            applog(LOG_ERR, "hex2bin str truncated");
-            return false;
-        }
-
-        hex_byte[0] = hexstr[0];
-        hex_byte[1] = hexstr[1];
-        *p = (unsigned char) strtol(hex_byte, &ep, 16);
-        if (*ep) {
-            applog(LOG_ERR, "hex2bin failed on '%s'", hex_byte);
-            return false;
-        }
-
-        p++;
-        hexstr += 2;
-        len--;
-    }
-
-    return (len == 0 && *hexstr == 0) ? true : false;
-}
-
-
-/**
- * @brief tq_new
- * @return
- */
-struct thread_q *tq_new(void)
-{
-    struct thread_q *tq;
-
-    tq = calloc(1, sizeof(*tq));
-    if (!tq)
-        return NULL;
-
-    INIT_LIST_HEAD(&tq->q);
-    pthread_mutex_init(&tq->mutex, NULL);
-    pthread_cond_init(&tq->cond, NULL);
-
-    return tq;
-}
-
-
-/**
- * @brief tq_free
- * @param tq
- */
-void tq_free(struct thread_q *tq)
-{
-    struct tq_ent *ent, *iter;
-
-    if (!tq)
-        return;
-
-    list_for_each_entry_safe(ent, iter, &tq->q, q_node) {
-        list_del(&ent->q_node);
-        free(ent);
-    }
-
-    pthread_cond_destroy(&tq->cond);
-    pthread_mutex_destroy(&tq->mutex);
-
-    memset(tq, 0, sizeof(*tq)); /* poison */
-    free(tq);
-}
-
-
-/**
- * @brief tq_freezethaw
- * @param tq
- * @param frozen
- */
-static void tq_freezethaw(struct thread_q *tq, bool frozen)
-{
-    pthread_mutex_lock(&tq->mutex);
-
-    tq->frozen = frozen;
-
-    pthread_cond_signal(&tq->cond);
-    pthread_mutex_unlock(&tq->mutex);
-}
-
-
-/**
- * @brief tq_freeze
- * @param tq
- */
-void tq_freeze(struct thread_q *tq)
-{
-    tq_freezethaw(tq, true);
-}
-
-
-/**
- * @brief tq_thaw
- * @param tq
- */
-void tq_thaw(struct thread_q *tq)
-{
-    tq_freezethaw(tq, false);
-}
-
-
-/**
- * @brief tq_push
- * @param tq
- * @param data
- * @return
- */
-bool tq_push(struct thread_q *tq, void *data)
-{
-    struct tq_ent *ent;
-    bool rc = true;
-
-    ent = calloc(1, sizeof(*ent));
-    if (!ent)
-        return false;
-
-    ent->data = data;
-    INIT_LIST_HEAD(&ent->q_node);
-
-    pthread_mutex_lock(&tq->mutex);
-
-    if (!tq->frozen) {
-        list_add_tail(&ent->q_node, &tq->q);
-    } else {
-        free(ent);
-        rc = false;
-    }
-
-    pthread_cond_signal(&tq->cond);
-    pthread_mutex_unlock(&tq->mutex);
-
-    return rc;
-}
-
-
-/**
- * @brief tq_pop
- * @param tq
- * @param abstime
- * @return
- */
-void *tq_pop(struct thread_q *tq, const struct timespec *abstime)
-{
-    struct tq_ent *ent;
-    void *rval = NULL;
-    int rc;
-
-    pthread_mutex_lock(&tq->mutex);
-
-    if (!list_empty(&tq->q))
-        goto pop;
-
-    if (abstime)
-        rc = pthread_cond_timedwait(&tq->cond, &tq->mutex, abstime);
-    else
-        rc = pthread_cond_wait(&tq->cond, &tq->mutex);
-    if (rc)
-        goto out;
-    if (list_empty(&tq->q))
-        goto out;
-
-pop:
-    ent = list_entry(tq->q.next, struct tq_ent, q_node);
-    rval = ent->data;
-
-    list_del(&ent->q_node);
-    free(ent);
-
-out:
-    pthread_mutex_unlock(&tq->mutex);
-    return rval;
-}
diff --git a/util.h b/util.h
deleted file mode 100644
index 47ab8904b..000000000
--- a/util.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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/>.
- */
-
-#ifndef __UTIL_H__
-#define __UTIL_H__
-
-#include <jansson.h>
-
-
-json_t *json_decode(const char *s);
-
-char *bin2hex(const unsigned char *p, size_t len);
-bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
-
-struct thread_q *tq_new(void);
-void tq_free(struct thread_q *tq);
-bool tq_push(struct thread_q *tq, void *data);
-void *tq_pop(struct thread_q *tq, const struct timespec *abstime);
-void tq_freeze(struct thread_q *tq);
-void tq_thaw(struct thread_q *tq);
-
-
-#endif /* __UTIL_H__ */
diff --git a/xmrig.c b/xmrig.c
deleted file mode 100644
index 7b14933b1..000000000
--- a/xmrig.c
+++ /dev/null
@@ -1,677 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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 <string.h>
-#include <unistd.h>
-#include <jansson.h>
-#include <sys/time.h>
-
-#ifdef WIN32
-#   include <winsock2.h>
-#   include <windows.h>
-#endif
-
-#include <jansson.h>
-#include <curl/curl.h>
-#include <pthread.h>
-
-#include "compat.h"
-#include "xmrig.h"
-#include "algo/cryptonight/cryptonight.h"
-#include "options.h"
-#include "cpu.h"
-#include "persistent_memory.h"
-#include "stratum.h"
-#include "stats.h"
-#include "util.h"
-#include "utils/summary.h"
-#include "utils/applog.h"
-
-#define LP_SCANTIME  60
-#define JSON_BUF_LEN 345
-
-
-struct workio_cmd {
-    struct thr_info *thr;
-    struct work *work;
-};
-
-
-struct thr_info *thr_info;
-static int work_thr_id = -1;
-static int timer_thr_id = -1;
-static int stratum_thr_id = -1;
-struct work_restart *work_restart = NULL;
-static struct stratum_ctx *stratum_ctx = NULL;
-static bool backup_active = false;
-static bool g_want_donate = false;
-
-
-static void workio_cmd_free(struct workio_cmd *wc);
-
-
-/**
- * @brief work_copy
- * @param dest
- * @param src
- */
-static inline void work_copy(struct work *dest, const struct work *src) {
-    memcpy(dest, src, sizeof(struct work));
-}
-
-
-/**
- * @brief restart_threads
- */
-static inline void restart_threads(void) {
-    for (int i = 0; i < opt_n_threads; i++) {
-        work_restart[i].restart = 1;
-    }
-}
-
-
-/**
- * @brief gen_workify
- * @param sctx
- * @param work
- */
-static inline void gen_workify(struct stratum_ctx *sctx) {
-    pthread_mutex_lock(&stratum_ctx->work_lock);
-
-    if (stratum_ctx->work.job_id && (!stratum_ctx->g_work_time || strcmp(stratum_ctx->work.job_id, stratum_ctx->g_work.job_id))) {
-        memcpy(&sctx->g_work, &sctx->work, sizeof(struct work));
-        time(&stratum_ctx->g_work_time);
-
-        pthread_mutex_unlock(&stratum_ctx->work_lock);
-
-        applog(LOG_DEBUG, "Stratum detected new block");
-        restart_threads();
-
-        return;
-    }
-
-    pthread_mutex_unlock(&stratum_ctx->work_lock);
-}
-
-
-/**
- * @brief submit_upstream_work
- * @param work
- * @return
- */
-static bool submit_upstream_work(struct work *work) {
-    char s[JSON_BUF_LEN];
-
-    /* pass if the previous hash is not the current previous hash */
-    if (memcmp(work->blob + 1, stratum_ctx->g_work.blob + 1, 32)) {
-        return true;
-    }
-
-    char *noncestr = bin2hex(((const unsigned char*) work->blob) + 39, 4);
-    char *hashhex  = bin2hex((const unsigned char *) work->hash, 32);
-
-    snprintf(s, JSON_BUF_LEN,
-            "{\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"},\"id\":1}",
-            stratum_ctx->id, work->job_id, noncestr, hashhex);
-
-    free(hashhex);
-    free(noncestr);
-
-    if (unlikely(!stratum_send_line(stratum_ctx, s))) {
-        return false;
-    }
-
-    return true;
-}
-
-
-
-/**
- * @brief workio_cmd_free
- * @param wc
- */
-static void workio_cmd_free(struct workio_cmd *wc) {
-    if (!wc) {
-        return;
-    }
-
-    free(wc->work);
-
-    memset(wc, 0, sizeof(*wc)); /* poison */
-    free(wc);
-}
-
-
-/**
- * @brief workio_submit_work
- * @param wc
- * @param curl
- * @return
- */
-static bool workio_submit_work(struct workio_cmd *wc) {
-    while (!submit_upstream_work(wc->work)) {
-        sleep(opt_retry_pause);
-    }
-
-    return true;
-}
-
-
-/**
- * @brief workio_thread
- * @param userdata
- * @return
- */
-static void *workio_thread(void *userdata) {
-    struct thr_info *mythr = userdata;
-    bool ok = true;
-
-    while (ok) {
-        struct workio_cmd *wc;
-
-        /* wait for workio_cmd sent to us, on our queue */
-        wc = tq_pop(mythr->q, NULL );
-        if (!wc) {
-            ok = false;
-            break;
-        }
-
-        workio_submit_work(wc);
-        workio_cmd_free(wc);
-    }
-
-    tq_freeze(mythr->q);
-
-    return NULL ;
-}
-
-
-/**
- * @brief submit_work
- * @param thr
- * @param work_in
- * @return
- */
-static bool submit_work(struct thr_info *thr, const struct work *work_in) {
-    struct workio_cmd *wc;
-
-    /* fill out work request message */
-    wc = calloc(1, sizeof(*wc));
-    wc->work = malloc(sizeof(*work_in));
-
-    if (likely(wc->work)) {
-        wc->thr = thr;
-        work_copy(wc->work, work_in);
-
-        if (likely(tq_push(thr_info[work_thr_id].q, wc))) {
-            return true;
-        }
-    }
-
-    workio_cmd_free(wc);
-    return false;
-}
-
-
-static bool should_pause(int thr_id) {
-    bool ret = false;
-
-    pthread_mutex_lock(&stratum_ctx->sock_lock);
-
-    if (!stratum_ctx->ready) {
-        ret = true;
-    }
-
-    pthread_mutex_unlock(&stratum_ctx->sock_lock);
-
-    return ret;
-}
-
-
-/**
- * @brief miner_thread
- * @param userdata
- * @return
- */
-static void *miner_thread(void *userdata) {
-    struct thr_info *mythr = userdata;
-    const int thr_id = mythr->id;
-    struct work work = { { 0 } };
-    uint32_t max_nonce;
-    uint32_t end_nonce = 0xffffffffU / opt_n_threads * (thr_id + 1) - 0x20;
-
-    struct cryptonight_ctx *persistentctx = (struct cryptonight_ctx *) create_persistent_ctx(thr_id);
-
-    if (cpu_info.total_logical_cpus > 1 && opt_affinity != -1L) {
-        affine_to_cpu_mask(thr_id, (unsigned long) opt_affinity);
-    }
-
-    uint32_t *nonceptr = NULL;
-    uint32_t hash[8] __attribute__((aligned(32)));
-
-    while (1) {
-        if (should_pause(thr_id)) {
-            sleep(1);
-            continue;
-        }
-
-        pthread_mutex_lock(&stratum_ctx->work_lock);
-
-        if (memcmp(work.job_id, stratum_ctx->g_work.job_id, 64)) {
-            work_copy(&work, &stratum_ctx->g_work);
-            nonceptr = (uint32_t*) (((char*) work.blob) + 39);
-
-            if (opt_nicehash) {
-                end_nonce = (*nonceptr & 0xff000000U) + (0xffffffU / opt_n_threads * (thr_id + 1) - 0x20);
-                *nonceptr = (*nonceptr & 0xff000000U) + (0xffffffU / opt_n_threads * thr_id);
-            }
-            else {
-                *nonceptr = 0xffffffffU / opt_n_threads * thr_id;
-            }
-        }
-
-        pthread_mutex_unlock(&stratum_ctx->work_lock);
-
-        work_restart[thr_id].restart = 0;
-
-        if (*nonceptr + LP_SCANTIME > end_nonce) {
-            max_nonce = end_nonce;
-        } else {
-            max_nonce = *nonceptr + LP_SCANTIME;
-        }
-
-        unsigned long hashes_done = 0;
-
-        struct timeval tv_start;
-        gettimeofday(&tv_start, NULL);
-
-        /* scan nonces for a proof-of-work hash */
-        const int rc = scanhash_cryptonight(thr_id, hash, work.blob, work.blob_size, work.target, max_nonce, &hashes_done, persistentctx);
-        stats_add_hashes(thr_id, &tv_start, hashes_done);
-
-        if (!rc) {
-            continue;
-        }
-
-        memcpy(work.hash, hash, 32);
-        submit_work(mythr, &work);
-        ++(*nonceptr);
-    }
-
-    tq_freeze(mythr->q);
-    return NULL;
-}
-
-
-/**
- * @brief miner_thread_double
- * @param userdata
- * @return
- */
-static void *miner_thread_double(void *userdata) {
-    struct thr_info *mythr = userdata;
-    const int thr_id = mythr->id;
-    struct work work = { { 0 } };
-    uint32_t max_nonce;
-    uint32_t end_nonce = 0xffffffffU / opt_n_threads * (thr_id + 1) - 0x20;
-
-    struct cryptonight_ctx *persistentctx = (struct cryptonight_ctx *) create_persistent_ctx(thr_id);
-
-    if (cpu_info.total_logical_cpus > 1 && opt_affinity != -1L) {
-        affine_to_cpu_mask(thr_id, (unsigned long) opt_affinity);
-    }
-
-    uint32_t *nonceptr0 = NULL;
-    uint32_t *nonceptr1 = NULL;
-    uint8_t double_hash[64];
-    uint8_t double_blob[sizeof(work.blob) * 2];
-
-    while (1) {
-        if (should_pause(thr_id)) {
-            sleep(1);
-            continue;
-        }
-
-        pthread_mutex_lock(&stratum_ctx->work_lock);
-
-        if (memcmp(work.job_id, stratum_ctx->g_work.job_id, 64)) {
-            work_copy(&work, &stratum_ctx->g_work);
-
-            memcpy(double_blob,                  work.blob, work.blob_size);
-            memcpy(double_blob + work.blob_size, work.blob, work.blob_size);
-
-            nonceptr0 = (uint32_t*) (((char*) double_blob) + 39);
-            nonceptr1 = (uint32_t*) (((char*) double_blob) + 39 + work.blob_size);
-
-            if (opt_nicehash) {
-                end_nonce = (*nonceptr0 & 0xff000000U) + (0xffffffU / (opt_n_threads * 2) * (thr_id + 1) - 0x20);
-                *nonceptr0 = (*nonceptr0 & 0xff000000U) + (0xffffffU / (opt_n_threads * 2) * thr_id);
-                *nonceptr1 = (*nonceptr1 & 0xff000000U) + (0xffffffU / (opt_n_threads * 2) * (thr_id + opt_n_threads));
-            }
-            else {
-                *nonceptr0 = 0xffffffffU / (opt_n_threads * 2) * thr_id;
-                *nonceptr1 = 0xffffffffU / (opt_n_threads * 2) * (thr_id + opt_n_threads);
-            }
-        }
-
-        pthread_mutex_unlock(&stratum_ctx->work_lock);
-
-        work_restart[thr_id].restart = 0;
-
-        if (*nonceptr0 + (LP_SCANTIME / 2) > end_nonce) {
-            max_nonce = end_nonce;
-        } else {
-            max_nonce = *nonceptr0 + (LP_SCANTIME / 2);
-        }
-
-        unsigned long hashes_done = 0;
-
-        struct timeval tv_start;
-        gettimeofday(&tv_start, NULL);
-
-        /* scan nonces for a proof-of-work hash */
-        const int rc = scanhash_cryptonight_double(thr_id, (uint32_t *) double_hash, double_blob, work.blob_size, work.target, max_nonce, &hashes_done, persistentctx);
-        stats_add_hashes(thr_id, &tv_start, hashes_done);
-
-        if (!rc) {
-            continue;
-        }
-
-        if (rc & 1) {
-            memcpy(work.hash, double_hash, 32);
-            memcpy(work.blob, double_blob, work.blob_size);
-            submit_work(mythr, &work);
-        }
-
-        if (rc & 2) {
-            memcpy(work.hash, double_hash + 32, 32);
-            memcpy(work.blob, double_blob + work.blob_size, work.blob_size);
-            submit_work(mythr, &work);
-        }
-
-        ++(*nonceptr0);
-        ++(*nonceptr1);
-    }
-
-    tq_freeze(mythr->q);
-    return NULL;
-}
-
-
-
-/**
- * @brief stratum_thread
- * @param userdata
- * @return
- */
-static void *timer_thread(void *userdata) {
-    const int max_user_time  = 100 - opt_donate_level;
-    int user_time_remaning   = max_user_time;
-    int donate_time_remaning = 0;
-
-
-    while (1) {
-        sleep(60);
-
-        if (user_time_remaning > 0) {
-            if (--user_time_remaning == 0) {
-                g_want_donate = true;
-
-                donate_time_remaning = opt_donate_level;
-                stratum_disconnect(stratum_ctx);
-                continue;
-            }
-        }
-
-        if (donate_time_remaning > 0) {
-            if (--donate_time_remaning == 0) {
-                g_want_donate = false;
-
-                user_time_remaning = max_user_time;
-                stratum_disconnect(stratum_ctx);
-                continue;
-            }
-        }
-    }
-}
-
-
-static void switch_stratum() {
-    static bool want_donate = false;
-
-    if (g_want_donate && !want_donate) {
-        stratum_ctx->url = opt_algo == ALGO_CRYPTONIGHT ? "stratum+tcp://donate.xmrig.com:443" : "stratum+tcp://donate.xmrig.com:3333";
-        applog(LOG_NOTICE, "Switching to dev pool");
-        want_donate = true;
-    }
-
-    if (!g_want_donate && want_donate) {
-        stratum_ctx->url = backup_active ? opt_backup_url : opt_url;
-        applog(LOG_NOTICE, "Switching to user pool: \"%s\"", stratum_ctx->url);
-        want_donate = false;
-    }
-}
-
-
-
-/**
- * @brief stratum_thread
- * @param userdata
- * @return
- */
-static void *stratum_thread(void *userdata) {
-    char *s;
-
-    stratum_ctx->url   = opt_url;
-    stratum_ctx->ready = false;
-
-    while (1) {
-        int failures = 0;
-        switch_stratum();
-
-        while (!stratum_ctx->curl) {
-            pthread_mutex_lock(&stratum_ctx->work_lock);
-            stratum_ctx->g_work_time = 0;
-            pthread_mutex_unlock(&stratum_ctx->work_lock);
-
-            restart_threads();
-            switch_stratum();
-
-            if (!stratum_connect(stratum_ctx, stratum_ctx->url) || !stratum_authorize(stratum_ctx, opt_user, opt_pass)) {
-                stratum_disconnect(stratum_ctx);
-                failures++;
-
-                if (failures > opt_retries && opt_backup_url) {
-                    failures = 0;
-
-                    backup_active = !backup_active;
-                    stratum_ctx->url = backup_active ? opt_backup_url : opt_url;
-                    sleep(opt_retry_pause);
-
-                    applog(LOG_WARNING, "Switch to: \"%s\"", stratum_ctx->url);
-                    continue;
-                }
-
-                applog(LOG_ERR, "...retry after %d seconds", opt_retry_pause);
-                sleep(opt_retry_pause);
-            }
-        }
-
-        gen_workify(stratum_ctx);
-
-        if (opt_keepalive && !stratum_socket_full(stratum_ctx, 90)) {
-            stratum_keepalived(stratum_ctx);
-        }
-
-        if (!stratum_socket_full(stratum_ctx, 300)) {
-            applog(LOG_ERR, "Stratum connection timed out");
-            s = NULL;
-        } else {
-            s = stratum_recv_line(stratum_ctx);
-        }
-
-        if (!s) {
-            stratum_disconnect(stratum_ctx);
-            applog(LOG_ERR, "Stratum connection interrupted");
-            continue;
-        }
-
-        if (!stratum_handle_method(stratum_ctx, s)) {
-            stratum_handle_response(s);
-        }
-
-        free(s);
-    }
-
-    return NULL ;
-}
-
-
-/**
- * @brief start work I/O thread
- * @return
- */
-static bool start_workio() {
-    work_thr_id = opt_n_threads;
-
-    struct thr_info *thr = &thr_info[work_thr_id];
-    thr->id = work_thr_id;
-    thr->q = tq_new();
-
-    if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, workio_thread, thr))) {
-        return false;
-    }
-
-    return true;
-}
-
-
-/**
- * @brief start_stratum
- * @return
- */
-static bool start_stratum() {
-    stratum_thr_id = opt_n_threads + 1;
-
-    stratum_ctx = persistent_calloc(1, sizeof(struct stratum_ctx));
-    pthread_mutex_init(&stratum_ctx->work_lock, NULL);
-    pthread_mutex_init(&stratum_ctx->sock_lock, NULL);
-
-    struct thr_info *thr = &thr_info[stratum_thr_id];
-    thr->id = stratum_thr_id;
-    thr->q = tq_new();
-
-    if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, stratum_thread, thr))) {
-        return false;
-    }
-
-     tq_push(thr_info[stratum_thr_id].q, strdup(opt_url));
-     return true;
-}
-
-
-/**
- * @brief start_timer
- * @return
- */
-static bool start_timer() {
-    timer_thr_id = opt_n_threads + 2;
-
-    if (opt_donate_level < 1) {
-        return true;
-    }
-
-    struct thr_info *thr = &thr_info[timer_thr_id];
-    thr->id = timer_thr_id;
-    thr->q = tq_new();
-
-    if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, timer_thread, thr))) {
-        return false;
-    }
-
-    return true;
-}
-
-
-/**
- * @brief start_mining
- * @return
- */
-static bool start_mining() {
-    for (int i = 0; i < opt_n_threads; i++) {
-        struct thr_info *thr = &thr_info[i];
-
-        thr->id = i;
-        thr->q = tq_new();
-
-        if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, opt_double_hash ? miner_thread_double : miner_thread, thr))) {
-            applog(LOG_ERR, "thread %d create failed", i);
-            return false;
-        }
-    }
-
-    return true;
-}
-
-
-/**
- * @brief main
- * @param argc
- * @param argv
- * @return
- */
-int main(int argc, char *argv[]) {
-    applog_init();
-    cpu_init();
-    parse_cmdline(argc, argv);
-    persistent_memory_allocate();
-    print_summary();
-
-    stats_init();
-    os_specific_init();
-
-    work_restart = persistent_calloc(opt_n_threads, sizeof(*work_restart));
-    thr_info     = persistent_calloc(opt_n_threads + 3, sizeof(struct thr_info));
-
-    if (!start_workio()) {
-        applog(LOG_ERR, "workio thread create failed");
-        return 1;
-    }
-
-    if (!start_stratum()) {
-        applog(LOG_ERR, "stratum thread create failed");
-        return 1;
-    }
-
-    start_timer();
-
-    if (!start_mining()) {
-        return 1;
-    }
-
-    pthread_join(thr_info[work_thr_id].pth, NULL);
-    applog(LOG_INFO, "workio thread dead, exiting.");
-    persistent_memory_free();
-    return 0;
-}
-
diff --git a/xmrig.h b/xmrig.h
deleted file mode 100644
index 08091367e..000000000
--- a/xmrig.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* XMRig
- * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
- * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
- * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
- * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
- * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
- * Copyright 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/>.
- */
-
-#ifndef __XMRIG_H__
-#define __XMRIG_H__
-
-#include <stdbool.h>
-#include <inttypes.h>
-#include <jansson.h>
-#include <curl/curl.h>
-#include <pthread.h>
-
-#define unlikely(expr) (__builtin_expect(!!(expr), 0))
-#define likely(expr)   (__builtin_expect(!!(expr), 1))
-
-
-struct thr_info {
-    int id;
-    pthread_t pth;
-    struct thread_q *q;
-};
-
-
-struct work_restart {
-    volatile unsigned long restart;
-    char padding[128 - sizeof(unsigned long)];
-};
-
-
-struct work;
-
-
-extern struct thr_info *thr_info;
-extern struct work_restart *work_restart;
-extern void os_specific_init();
-
-#endif /* __XMRIG_H__ */

From 8c2951db2df884f7e91e377241db22f15f43d2b6 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Tue, 13 Jun 2017 13:20:15 +0300
Subject: [PATCH 44/56] Add signal handlers.

---
 CMakeLists.txt  |  1 +
 src/App.cpp     | 55 ++++++++++++++++++++++++++++++++++++++++++-------
 src/App.h       | 11 ++++++++++
 src/App_win.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++
 src/Cpu.cpp     |  2 +-
 src/Options.h   |  1 +
 6 files changed, 114 insertions(+), 8 deletions(-)
 create mode 100644 src/App_win.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9badb06da..e1dd51caf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -76,6 +76,7 @@ if (WIN32)
         res/app.rc
         src/3rdparty/winansi.cpp
         src/3rdparty/winansi.h
+        src/App_win.cpp
         src/Cpu_win.cpp
         src/Mem_win.cpp
         src/net/Network_win.cpp
diff --git a/src/App.cpp b/src/App.cpp
index b897be8ae..06e512b6e 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -30,7 +30,6 @@
 #include "Cpu.h"
 #include "crypto/CryptoNight.h"
 #include "Mem.h"
-#include "net/Client.h"
 #include "net/Network.h"
 #include "Options.h"
 #include "Summary.h"
@@ -38,25 +37,28 @@
 #include "workers/Workers.h"
 
 
+App *App::m_self = nullptr;
 
-App::App(int argc, char **argv)
+
+
+App::App(int argc, char **argv) :
+    m_network(nullptr),
+    m_options(nullptr)
 {
+    m_self = this;
+
     Console::init();
     Cpu::init();
 
     m_options = Options::parse(argc, argv);
     m_network = new Network(m_options);
 
-
+    uv_signal_init(uv_default_loop(), &m_signal);
 }
 
 
 App::~App()
 {
-    LOG_DEBUG("~APP");
-
-    free(m_network);
-    free(m_options);
 }
 
 
@@ -71,6 +73,12 @@ int App::exec()
         return 1;
     }
 
+    uv_signal_start(&m_signal, App::onSignal, SIGHUP);
+    uv_signal_start(&m_signal, App::onSignal, SIGTERM);
+    uv_signal_start(&m_signal, App::onSignal, SIGINT);
+
+    background();
+
     Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash());
     Summary::print();
 
@@ -81,5 +89,38 @@ int App::exec()
     const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
     uv_loop_close(uv_default_loop());
 
+    free(m_network);
+    free(m_options);
+
     return r;
 }
+
+
+void App::close()
+{
+    uv_stop(uv_default_loop());
+}
+
+
+void App::onSignal(uv_signal_t *handle, int signum)
+{
+    switch (signum)
+    {
+    case SIGHUP:
+        LOG_WARN("SIGHUP received, exiting");
+        break;
+
+    case SIGTERM:
+        LOG_WARN("SIGTERM received, exiting");
+        break;
+
+    case SIGINT:
+        LOG_WARN("SIGINT received, exiting");
+        break;
+
+    default:
+        break;
+    }
+
+    m_self->close();
+}
diff --git a/src/App.h b/src/App.h
index b2d5e5f00..99eac4329 100644
--- a/src/App.h
+++ b/src/App.h
@@ -25,6 +25,9 @@
 #define __APP_H__
 
 
+#include <uv.h>
+
+
 class Network;
 class Options;
 
@@ -38,8 +41,16 @@ public:
   int exec();
 
 private:
+  void background();
+  void close();
+
+  static void onSignal(uv_signal_t *handle, int signum);
+
+  static App *m_self;
+
   Network *m_network;
   Options *m_options;
+  uv_signal_t m_signal;
 };
 
 
diff --git a/src/App_win.cpp b/src/App_win.cpp
new file mode 100644
index 000000000..895f3bdfc
--- /dev/null
+++ b/src/App_win.cpp
@@ -0,0 +1,52 @@
+/* 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 <winsock2.h>
+#include <windows.h>
+
+
+#include "App.h"
+#include "Options.h"
+#include "Cpu.h"
+
+
+void App::background()
+{
+    if (m_options->affinity() != -1L) {
+        Cpu::setAffinity(-1, m_options->affinity());
+    }
+
+    if (!m_options->background()) {
+        return;
+    }
+
+    HWND hcon = GetConsoleWindow();
+    if (hcon) {
+        ShowWindow(hcon, SW_HIDE);
+    } else {
+        HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
+        CloseHandle(h);
+        FreeConsole();
+    }
+}
diff --git a/src/Cpu.cpp b/src/Cpu.cpp
index 53d81e588..2f0a11950 100644
--- a/src/Cpu.cpp
+++ b/src/Cpu.cpp
@@ -91,7 +91,7 @@ void Cpu::initCommon()
         m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0;
     }
 
-#   ifdef __x86_64__
+#   if defined(__x86_64__) || defined(_M_AMD64)
     m_flags |= X86_64;
 #   endif
 
diff --git a/src/Options.h b/src/Options.h
index 4955a7f35..d8d6e4ae5 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -51,6 +51,7 @@ public:
     static inline Options* i() { return m_self; }
     static Options *parse(int argc, char **argv);
 
+    inline bool background() const      { return m_background; }
     inline bool colors() const          { return m_colors; }
     inline bool doubleHash() const      { return m_doubleHash; }
     inline bool isReady() const         { return m_ready; }

From 981e043ada1f75878519466ea3cf617a4a89429f Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Tue, 13 Jun 2017 19:58:31 +0300
Subject: [PATCH 45/56] Add DoubleWorker class.

---
 CMakeLists.txt               |  4 +-
 src/App.cpp                  |  2 +-
 src/Mem.h                    |  2 +
 src/crypto/CryptoNight.cpp   | 20 +++++---
 src/crypto/CryptoNight.h     |  1 +
 src/net/Job.h                |  3 +-
 src/net/JobResult.h          |  7 +++
 src/workers/DoubleWorker.cpp | 97 ++++++++++++++++++++++++++++++++++++
 src/workers/DoubleWorker.h   | 55 ++++++++++++++++++++
 src/workers/SingleWorker.cpp |  2 +-
 src/workers/Worker.cpp       |  2 -
 src/workers/Workers.cpp      | 15 ++++--
 src/workers/Workers.h        |  2 +-
 13 files changed, 195 insertions(+), 17 deletions(-)
 create mode 100644 src/workers/DoubleWorker.cpp
 create mode 100644 src/workers/DoubleWorker.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e1dd51caf..d2fb52623 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,6 +21,7 @@ set(HEADERS
     src/Options.h
     src/Summary.h
     src/version.h
+    src/workers/DoubleWorker.h
     src/workers/Handle.h
     src/workers/SingleWorker.h
     src/workers/Telemetry.h
@@ -52,6 +53,7 @@ set(SOURCES
     src/net/Url.cpp
     src/Options.cpp
     src/Summary.cpp
+    src/workers/DoubleWorker.cpp
     src/workers/Handle.cpp
     src/workers/SingleWorker.cpp
     src/workers/Telemetry.cpp
@@ -113,7 +115,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
 
     add_definitions(/D_GNU_SOURCE)
 
-    #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
+    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
 
 elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
 
diff --git a/src/App.cpp b/src/App.cpp
index 06e512b6e..a92883c1b 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -82,7 +82,7 @@ int App::exec()
     Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash());
     Summary::print();
 
-    Workers::start(m_options->threads(), m_options->affinity(), m_options->nicehash());
+    Workers::start(m_options->affinity(), m_options->nicehash());
 
     m_network->connect();
 
diff --git a/src/Mem.h b/src/Mem.h
index 89635e332..4198d8a2a 100644
--- a/src/Mem.h
+++ b/src/Mem.h
@@ -48,9 +48,11 @@ public:
     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 int flags()                 { return m_flags; }
+    static inline int threads()               { return m_threads; }
 
 private:
     static bool m_doubleHash;
diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp
index e19e66ca5..a463c9f97 100644
--- a/src/crypto/CryptoNight.cpp
+++ b/src/crypto/CryptoNight.cpp
@@ -38,38 +38,38 @@ static void cryptonight_av1_aesni(const void *input, size_t size, void *output,
 }
 
 
-static void cryptonight_av2_aesni_double(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+static void cryptonight_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
     cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
 }
 
 
-static void cryptonight_av3_softaes(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+static void cryptonight_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
     cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx);
 }
 
 
-static void cryptonight_av4_softaes_double(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+static void cryptonight_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
     cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx);
 }
 
 
 #ifndef XMRIG_NO_AEON
-static void cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+static void cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
     cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx);
 }
 
 
-static void cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+static void cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
     cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx);
 }
 
 
-static void cryptonight_lite_av3_softaes(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+static void cryptonight_lite_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
     cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx);
 }
 
 
-static void cryptonight_lite_av4_softaes_double(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
+static void cryptonight_lite_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
     cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx);
 }
 
@@ -119,6 +119,12 @@ bool CryptoNight::init(int algo, int variant)
 }
 
 
+void CryptoNight::hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx)
+{
+    cryptonight_hash_ctx(input, size, output, ctx);
+}
+
+
 bool CryptoNight::selfTest(int algo) {
     if (cryptonight_hash_ctx == nullptr) {
         return false;
diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h
index 2ed5dfb20..294127303 100644
--- a/src/crypto/CryptoNight.h
+++ b/src/crypto/CryptoNight.h
@@ -51,6 +51,7 @@ class CryptoNight
 public:
     static bool hash(const Job &job, JobResult &result, cryptonight_ctx *ctx);
     static bool init(int algo, int variant);
+    static void hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx);
 
 private:
     static bool selfTest(int algo);
diff --git a/src/net/Job.h b/src/net/Job.h
index 9848f1283..262465fca 100644
--- a/src/net/Job.h
+++ b/src/net/Job.h
@@ -50,8 +50,9 @@ public:
     inline void setPoolId(int poolId)  { m_poolId = poolId; }
 
     static bool fromHex(const char* in, unsigned int len, unsigned char* out);
-    static void toHex(const unsigned char* in, unsigned int len, char* out);
+    static inline uint32_t *nonce(uint8_t *blob)   { return reinterpret_cast<uint32_t*>(blob + 39); }
     static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
+    static void toHex(const unsigned char* in, unsigned int len, char* out);
 
 private:
     int m_poolId;
diff --git a/src/net/JobResult.h b/src/net/JobResult.h
index ba067cdc2..55ebdbd20 100644
--- a/src/net/JobResult.h
+++ b/src/net/JobResult.h
@@ -31,6 +31,13 @@
 class JobResult
 {
 public:
+    inline JobResult() : poolId(0), nonce(0) {}
+    inline JobResult(int poolId, const char *jobId, uint32_t nonce, const uint8_t *result) : poolId(poolId), nonce(nonce)
+    {
+        memcpy(this->jobId, jobId, sizeof(this->jobId));
+        memcpy(this->result, result, sizeof(this->result));
+    }
+
     char jobId[64];
     int poolId;
     uint32_t nonce;
diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp
new file mode 100644
index 000000000..f7a56dbf5
--- /dev/null
+++ b/src/workers/DoubleWorker.cpp
@@ -0,0 +1,97 @@
+/* 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 <thread>
+
+
+#include "crypto/CryptoNight.h"
+#include "workers/DoubleWorker.h"
+#include "workers/Workers.h"
+
+
+DoubleWorker::DoubleWorker(Handle *handle)
+    : Worker(handle),
+    m_nonce1(0),
+    m_nonce2(0)
+{
+}
+
+
+void DoubleWorker::start()
+{
+    while (true) {
+        if (Workers::isPaused()) {
+            do {
+                std::this_thread::sleep_for(std::chrono::milliseconds(200));
+            }
+            while (Workers::isPaused());
+
+            consumeJob();
+        }
+
+        while (!Workers::isOutdated(m_sequence)) {
+            if ((m_count & 0xF) == 0) {
+                storeStats();
+            }
+
+            m_count += 2;
+            *Job::nonce(m_blob)                = ++m_nonce1;
+            *Job::nonce(m_blob + m_job.size()) = ++m_nonce2;
+
+            CryptoNight::hash(m_blob, m_job.size(), m_hash, m_ctx);
+
+            if (*reinterpret_cast<uint64_t*>(m_hash + 24) < m_job.target()) {
+                Workers::submit(JobResult(m_job.poolId(), m_job.id(), m_nonce1, m_hash));
+            }
+
+            if (*reinterpret_cast<uint64_t*>(m_hash + 32 + 24) < m_job.target()) {
+                Workers::submit(JobResult(m_job.poolId(), m_job.id(), m_nonce2, m_hash + 32));
+            }
+
+            std::this_thread::yield();
+        }
+
+        consumeJob();
+    }
+}
+
+
+
+void DoubleWorker::consumeJob()
+{
+    m_job = Workers::job();
+    m_sequence = Workers::sequence();
+
+    memcpy(m_blob,                m_job.blob(), m_job.size());
+    memcpy(m_blob + m_job.size(), m_job.blob(), m_job.size());
+
+    if (m_nicehash) {
+        m_nonce1 = (*Job::nonce(m_blob)                & 0xff000000U) + (0xffffffU / (m_threads * 2) * m_id);
+        m_nonce2 = (*Job::nonce(m_blob + m_job.size()) & 0xff000000U) + (0xffffffU / (m_threads * 2) * (m_id + m_threads));
+    }
+    else {
+        m_nonce1 = 0xffffffffU / (m_threads * 2) * m_id;
+        m_nonce2 = 0xffffffffU / (m_threads * 2) * (m_id + m_threads);
+    }
+}
diff --git a/src/workers/DoubleWorker.h b/src/workers/DoubleWorker.h
new file mode 100644
index 000000000..d062dac0c
--- /dev/null
+++ b/src/workers/DoubleWorker.h
@@ -0,0 +1,55 @@
+/* XMRig
+ * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
+ * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
+ * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
+ * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
+ * Copyright 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/>.
+ */
+
+#ifndef __DOUBLEWORKER_H__
+#define __DOUBLEWORKER_H__
+
+
+#include "align.h"
+#include "net/Job.h"
+#include "net/JobResult.h"
+#include "workers/Worker.h"
+
+
+class Handle;
+
+
+class DoubleWorker : public Worker
+{
+public:
+    DoubleWorker(Handle *handle);
+
+    void start() override;
+
+private:
+    void consumeJob();
+
+    Job m_job;
+    uint32_t m_nonce1;
+    uint32_t m_nonce2;
+    uint8_t m_hash[64];
+    uint8_t	m_blob[84 * 2];
+};
+
+
+#endif /* __SINGLEWORKER_H__ */
diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp
index 3969e883e..9c56b7d8f 100644
--- a/src/workers/SingleWorker.cpp
+++ b/src/workers/SingleWorker.cpp
@@ -60,7 +60,7 @@ void SingleWorker::start()
                 Workers::submit(m_result);
             }
 
-//            sched_yield();
+            std::this_thread::yield();
         }
 
         consumeJob();
diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp
index 5478bcf78..1cede65fe 100644
--- a/src/workers/Worker.cpp
+++ b/src/workers/Worker.cpp
@@ -40,8 +40,6 @@ Worker::Worker(Handle *handle) :
     m_count(0),
     m_sequence(0)
 {
-    handle->setWorker(this);
-
     if (Cpu::threads() > 1 && handle->affinity() != -1L) {
         Cpu::setAffinity(m_id, handle->affinity());
     }
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
index b3673445b..27453fdb2 100644
--- a/src/workers/Workers.cpp
+++ b/src/workers/Workers.cpp
@@ -26,6 +26,8 @@
 
 #include "Console.h"
 #include "interfaces/IJobResultListener.h"
+#include "Mem.h"
+#include "workers/DoubleWorker.h"
 #include "workers/Handle.h"
 #include "workers/SingleWorker.h"
 #include "workers/Telemetry.h"
@@ -67,8 +69,9 @@ void Workers::setJob(const Job &job)
 }
 
 
-void Workers::start(int threads, int64_t affinity, bool nicehash)
+void Workers::start(int64_t affinity, bool nicehash)
 {
+    const int threads = Mem::threads();
     m_telemetry = new Telemetry(threads);
 
     uv_mutex_init(&m_mutex);
@@ -103,8 +106,14 @@ void Workers::submit(const JobResult &result)
 void Workers::onReady(void *arg)
 {
     auto handle = static_cast<Handle*>(arg);
-    IWorker *worker = new SingleWorker(handle);
-    worker->start();
+    if (Mem::isDoubleHash()) {
+        handle->setWorker(new DoubleWorker(handle));
+    }
+    else {
+        handle->setWorker(new SingleWorker(handle));
+    }
+
+    handle->worker()->start();
 }
 
 
diff --git a/src/workers/Workers.h b/src/workers/Workers.h
index 5e3981096..6cf17de4b 100644
--- a/src/workers/Workers.h
+++ b/src/workers/Workers.h
@@ -44,7 +44,7 @@ class Workers
 public:
     static Job job();
     static void setJob(const Job &job);
-    static void start(int threads, int64_t affinity, bool nicehash);
+    static void start(int64_t affinity, bool nicehash);
     static void submit(const JobResult &result);
 
     static inline bool isOutdated(uint64_t sequence)             { return m_sequence.load(std::memory_order_relaxed) != sequence; }

From 7c8a9677a1f835ff04015d0eb59a6080e1e56613 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Tue, 13 Jun 2017 20:03:43 +0300
Subject: [PATCH 46/56] Fix crash.

---
 src/crypto/CryptoNight_p.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/crypto/CryptoNight_p.h b/src/crypto/CryptoNight_p.h
index 8a5268f4e..fa2fa93a8 100644
--- a/src/crypto/CryptoNight_p.h
+++ b/src/crypto/CryptoNight_p.h
@@ -363,7 +363,7 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size,
     keccak((const uint8_t *) input + size, size, ctx->state1, 200);
 
     const uint8_t* l0 = ctx->memory;
-    const uint8_t* l1 = ctx->memory + MEMORY;
+    const uint8_t* l1 = ctx->memory + MEM;
     uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
     uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx->state1);
 

From 8ebb659cd66a1da3d35186c9c49ab795597ecf73 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 14 Jun 2017 09:03:03 +0300
Subject: [PATCH 47/56] Fix AEON donate port.

---
 src/net/Network.cpp          | 2 +-
 src/workers/DoubleWorker.cpp | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index eef52cd14..448f1ebb3 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -205,7 +205,7 @@ void Network::onTimer(uv_timer_t *handle)
     auto net = static_cast<Network*>(handle->data);
 
     if (!net->m_donate) {
-        auto url = std::make_unique<Url>("donate.xmrig.com", 443);
+        auto url = std::make_unique<Url>("donate.xmrig.com", net->m_options->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443);
         net->m_pools[0]->connect(url.get());
 
         uv_timer_start(&net->m_timer, Network::onTimer, net->m_options->donateLevel() * 60 * 1000, 0);
diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp
index f7a56dbf5..41b9aec79 100644
--- a/src/workers/DoubleWorker.cpp
+++ b/src/workers/DoubleWorker.cpp
@@ -77,7 +77,6 @@ void DoubleWorker::start()
 }
 
 
-
 void DoubleWorker::consumeJob()
 {
     m_job = Workers::job();

From 5af169fd7b453c86cbfbba09099a641b4ac96e1d Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 14 Jun 2017 16:11:01 +0300
Subject: [PATCH 48/56] Fix linux build.

---
 cmake/FindUV.cmake       |  2 +-
 src/App.cpp              |  3 ++
 src/App_unix.cpp         | 66 ++++++++++++++++++++++++++++++++++++++++
 src/Console.cpp          |  4 +++
 src/Cpu_unix.cpp         | 35 +++++++++++++++++++++
 src/Mem_unix.cpp         | 56 ++++++++++++++++++++++++++++++++++
 src/Options.cpp          |  3 +-
 src/crypto/CryptoNight.h |  1 +
 src/net/JobResult.h      |  1 +
 src/net/Network_unix.cpp | 50 ++++++++++++++++++++++++++++++
 src/net/Network_win.cpp  |  2 +-
 11 files changed, 220 insertions(+), 3 deletions(-)
 create mode 100644 src/App_unix.cpp
 create mode 100644 src/net/Network_unix.cpp

diff --git a/cmake/FindUV.cmake b/cmake/FindUV.cmake
index c8a95e7ad..e3c22d28d 100644
--- a/cmake/FindUV.cmake
+++ b/cmake/FindUV.cmake
@@ -1,5 +1,5 @@
 find_path(UV_INCLUDE_DIR NAMES uv.h)
-find_library(UV_LIBRARY NAMES libuv)
+find_library(UV_LIBRARY NAMES uv libuv)
 
 set(UV_LIBRARIES ${UV_LIBRARY})
 set(UV_INCLUDE_DIRS ${UV_INCLUDE_DIR})
diff --git a/src/App.cpp b/src/App.cpp
index a92883c1b..8f6ed1489 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -22,6 +22,7 @@
  */
 
 
+#include <stdlib.h>
 #include <uv.h>
 
 
@@ -92,6 +93,8 @@ int App::exec()
     free(m_network);
     free(m_options);
 
+    Mem::release();
+
     return r;
 }
 
diff --git a/src/App_unix.cpp b/src/App_unix.cpp
new file mode 100644
index 000000000..d001acb24
--- /dev/null
+++ b/src/App_unix.cpp
@@ -0,0 +1,66 @@
+/* XMRig
+ * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
+ * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
+ * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
+ * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
+ * Copyright 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 <signal.h>
+#include <errno.h>
+#include <unistd.h>
+
+
+#include "App.h"
+#include "Console.h"
+#include "Cpu.h"
+#include "Options.h"
+
+
+void App::background()
+{
+    if (m_options->affinity() != -1L) {
+        Cpu::setAffinity(-1, m_options->affinity());
+    }
+
+    if (!m_options->background()) {
+        return;
+    }
+
+    int i = fork();
+    if (i < 0) {
+        exit(1);
+    }
+
+    if (i > 0) {
+        exit(0);
+    }
+
+    i = setsid();
+
+    if (i < 0) {
+        LOG_ERR("setsid() failed (errno = %d)", errno);
+    }
+
+    i = chdir("/");
+    if (i < 0) {
+        LOG_ERR("chdir() failed (errno = %d)", errno);
+    }
+}
diff --git a/src/Console.cpp b/src/Console.cpp
index b3b7ed3ea..5df744dbc 100644
--- a/src/Console.cpp
+++ b/src/Console.cpp
@@ -23,9 +23,13 @@
 
 
 #include <malloc.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
 #include <time.h>
 
 
+
 #ifdef WIN32
 #   include <winsock2.h>
 #   include "3rdparty/winansi.h"
diff --git a/src/Cpu_unix.cpp b/src/Cpu_unix.cpp
index 8140cd5f1..1b7c6b0a8 100644
--- a/src/Cpu_unix.cpp
+++ b/src/Cpu_unix.cpp
@@ -22,3 +22,38 @@
  */
 
 
+#include <pthread.h>
+#include <sched.h>
+#include <unistd.h>
+
+
+#include "Cpu.h"
+
+
+void Cpu::init()
+{
+#   ifdef XMRIG_NO_LIBCPUID
+    m_totalThreads = sysconf(_SC_NPROCESSORS_CONF);
+#   endif
+
+    initCommon();
+}
+
+
+void Cpu::setAffinity(int id, unsigned long mask)
+{
+    cpu_set_t set;
+    CPU_ZERO(&set);
+
+    for (int i = 0; i < m_totalThreads; i++) {
+        if (mask & (1UL << i)) {
+            CPU_SET(i, &set);
+        }
+    }
+
+    if (id == -1) {
+        sched_setaffinity(0, sizeof(&set), &set);
+    } else {
+        pthread_setaffinity_np(pthread_self(), sizeof(&set), &set);
+    }
+}
diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp
index a0690e79c..231b48fc4 100644
--- a/src/Mem_unix.cpp
+++ b/src/Mem_unix.cpp
@@ -22,5 +22,61 @@
  */
 
 
+#include <stdlib.h>
+#include <mm_malloc.h>
+#include <sys/mman.h>
+
+
 #include "crypto/CryptoNight.h"
 #include "Mem.h"
+#include "Options.h"
+#include "Console.h"
+
+
+bool Mem::allocate(int algo, int threads, bool doubleHash)
+{
+    m_algo       = algo;
+    m_threads    = threads;
+    m_doubleHash = doubleHash;
+
+    const int ratio   = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
+    const size_t size = MEMORY * (threads * ratio + 1);
+
+    m_flags |= HugepagesAvailable;
+
+    m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0));
+
+    if (m_memory == MAP_FAILED) {
+        m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
+        return true;
+    }
+
+    m_flags |= HugepagesEnabled;
+
+    if (madvise(m_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0) {
+        LOG_ERR("madvise failed");
+    }
+
+    if (mlock(m_memory, size) == 0) {
+        m_flags |= Lock;
+    }
+
+    return true;
+}
+
+
+void Mem::release()
+{
+    const int size = MEMORY * (m_threads + 1);
+
+    if (m_flags & HugepagesEnabled) {
+        if (m_flags & Lock) {
+            munlock(m_memory, size);
+        }
+
+        munmap(m_memory, size);
+    }
+    else {
+        _mm_free(m_memory);
+    }
+}
diff --git a/src/Options.cpp b/src/Options.cpp
index c38f417bb..8a8a31748 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -22,8 +22,9 @@
  */
 
 
-#include <uv.h>
 #include <jansson.h>
+#include <string.h>
+#include <uv.h>
 
 
 #ifdef _MSC_VER
diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h
index 294127303..64fc0fd1a 100644
--- a/src/crypto/CryptoNight.h
+++ b/src/crypto/CryptoNight.h
@@ -25,6 +25,7 @@
 #define __CRYPTONIGHT_H__
 
 
+#include <stddef.h>
 #include <stdint.h>
 
 
diff --git a/src/net/JobResult.h b/src/net/JobResult.h
index 55ebdbd20..87e3a645a 100644
--- a/src/net/JobResult.h
+++ b/src/net/JobResult.h
@@ -25,6 +25,7 @@
 #define __JOBRESULT_H__
 
 
+#include <memory.h>
 #include <stdint.h>
 
 
diff --git a/src/net/Network_unix.cpp b/src/net/Network_unix.cpp
new file mode 100644
index 000000000..546d1b8a2
--- /dev/null
+++ b/src/net/Network_unix.cpp
@@ -0,0 +1,50 @@
+/* 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 "net/Network.h"
+#include "version.h"
+
+
+char *Network::userAgent()
+{
+    const size_t max = 128;
+
+    char *buf = static_cast<char*>(malloc(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 __GNUC__
+    length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
+#   endif
+
+    return buf;
+}
diff --git a/src/net/Network_win.cpp b/src/net/Network_win.cpp
index 15b358b57..6ae5e3223 100644
--- a/src/net/Network_win.cpp
+++ b/src/net/Network_win.cpp
@@ -64,7 +64,7 @@ char *Network::userAgent()
 
 #   ifdef __GNUC__
     length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
-#elif _MSC_VER
+#   elif _MSC_VER
     length += snprintf(buf + length, max - length, " msvc/%d", MSVC_VERSION);
 #   endif
 

From 33d752bcaaa1452ce49ca62ae1de19cabaf4df5c Mon Sep 17 00:00:00 2001
From: xmrig <support@xmrig.com>
Date: Wed, 14 Jun 2017 16:18:13 +0300
Subject: [PATCH 49/56] Update README.md

---
 README.md | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index fb3f44e2a..241a1eeab 100644
--- a/README.md
+++ b/README.md
@@ -73,7 +73,7 @@ Since version 0.8.0.
 ## Build
 ### Ubuntu (Debian-based distros)
 ```
-sudo apt-get install git build-essential cmake libcurl4-openssl-dev
+sudo apt-get install git build-essential cmake libuv1-dev
 git clone https://github.com/xmrig/xmrig.git
 cd xmrig
 mkdir build
@@ -81,6 +81,16 @@ cd build
 cmake .. -DCMAKE_BUILD_TYPE=Release
 make
 ```
+#### gcc 7.1
+```
+sudo add-apt-repository ppa:jonathonf/gcc-7.1
+sudo apt-get update
+apt-get install gcc-7 g++-7
+```
+When run cmake manually specify C and C++ compiler:
+```
+cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/bin/gcc-7 -DCMAKE_CXX_COMPILER=/usr/bin/g++-7
+```
 
 ### Windows
 It's complicated, you need [MSYS2](http://www.msys2.org/), custom libcurl build, and of course CMake too.

From babc48f76758f82ed46114dd0e85f2eb96363509 Mon Sep 17 00:00:00 2001
From: xmrig <support@xmrig.com>
Date: Wed, 14 Jun 2017 16:42:00 +0300
Subject: [PATCH 50/56] Update README.md

---
 README.md | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 241a1eeab..1f22ed137 100644
--- a/README.md
+++ b/README.md
@@ -93,8 +93,9 @@ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/bin/gcc-7 -DCMAKE_CX
 ```
 
 ### Windows
-It's complicated, you need [MSYS2](http://www.msys2.org/), custom libcurl build, and of course CMake too.
+There two options Microsoft Visual Studio 2015+ or [MSYS2](http://www.msys2.org/) both required [libuv](https://github.com/libuv/libuv) build and cmake.
 
+#### MSYS2
 Necessary MSYS2 packages:
 ```
 pacman -Sy
@@ -103,13 +104,15 @@ pacman -S make
 pacman -S mingw-w64-x86_64-cmake
 pacman -S mingw-w64-x86_64-pkg-config
 ```
-Configure options for libcurl:
+CMake build:
 ```
-./configure --disable-shared --enable-optimize --enable-threaded-resolver --disable-libcurl-option --disable-ares --disable-rt --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-manual --disable-ipv6 --disable-sspi --disable-crypto-auth --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --without-zlib --without-winssl --without-ssl --without-libssh2 --without-nghttp2 --disable-cookies --without-ca-bundle --without-librtmp
+cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DUV_INCLUDE_DIR="c:\<path>\libuv\include" -DUV_LIBRARY="c:\<path>\libuv\.libs\libuv.a"
+make
 ```
-CMake options:
+
+#### Microsoft Visual Studio
 ```
-cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCURL_INCLUDE_DIR="c:\<path>\curl-7.53.1\include" -DCURL_LIBRARY="c:\<path>\curl-7.53.1\lib\.libs"
+`cmake .. -G "Visual Studio 14 2015 Win64" -T v140_xp -DCMAKE_BUILD_TYPE=Release -DUV_INCLUDE_DIR=c:\<path>\libuv\include -DUV_LIBRARY=c:\<path>\libuv\Release\lib\libuv.lib`
 ```
 
 ### Optional features

From e3689ccb1a2c52479ffea29eca5d7017d45f13f1 Mon Sep 17 00:00:00 2001
From: xmrig <support@xmrig.com>
Date: Wed, 14 Jun 2017 16:49:47 +0300
Subject: [PATCH 51/56] Move build instructions to Wiki

---
 README.md | 51 +--------------------------------------------------
 1 file changed, 1 insertion(+), 50 deletions(-)

diff --git a/README.md b/README.md
index 1f22ed137..70485e0a6 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of
 * [Download](#download)
 * [Usage](#usage)
 * [Algorithm variations](#algorithm-variations)
-* [Build](#build)
+* [Build](https://github.com/xmrig/xmrig/wiki/Build)
 * [Common Issues](#common-issues)
 * [Other information](#other-information)
 * [Donations](#donations)
@@ -70,55 +70,6 @@ Since version 0.8.0.
 * `--av=3` Software AES implementation.
 * `--av=4` Lower power mode (double hash) of `3`.
 
-## Build
-### Ubuntu (Debian-based distros)
-```
-sudo apt-get install git build-essential cmake libuv1-dev
-git clone https://github.com/xmrig/xmrig.git
-cd xmrig
-mkdir build
-cd build
-cmake .. -DCMAKE_BUILD_TYPE=Release
-make
-```
-#### gcc 7.1
-```
-sudo add-apt-repository ppa:jonathonf/gcc-7.1
-sudo apt-get update
-apt-get install gcc-7 g++-7
-```
-When run cmake manually specify C and C++ compiler:
-```
-cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/bin/gcc-7 -DCMAKE_CXX_COMPILER=/usr/bin/g++-7
-```
-
-### Windows
-There two options Microsoft Visual Studio 2015+ or [MSYS2](http://www.msys2.org/) both required [libuv](https://github.com/libuv/libuv) build and cmake.
-
-#### MSYS2
-Necessary MSYS2 packages:
-```
-pacman -Sy
-pacman -S mingw-w64-x86_64-gcc
-pacman -S make
-pacman -S mingw-w64-x86_64-cmake
-pacman -S mingw-w64-x86_64-pkg-config
-```
-CMake build:
-```
-cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DUV_INCLUDE_DIR="c:\<path>\libuv\include" -DUV_LIBRARY="c:\<path>\libuv\.libs\libuv.a"
-make
-```
-
-#### Microsoft Visual Studio
-```
-`cmake .. -G "Visual Studio 14 2015 Win64" -T v140_xp -DCMAKE_BUILD_TYPE=Release -DUV_INCLUDE_DIR=c:\<path>\libuv\include -DUV_LIBRARY=c:\<path>\libuv\Release\lib\libuv.lib`
-```
-
-### Optional features
-`-DWITH_LIBCPUID=OFF` Disable libcpuid. Auto configuration of CPU after this will be very limited.
-`-DWITH_AEON=OFF` Disable CryptoNight-Lite support.
-
 ## Common Issues
 ### HUGE PAGES unavailable
 * Run XMRig as Administrator.

From 599117abde895a67d677f496473bb19503d8a793 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 14 Jun 2017 19:13:02 +0300
Subject: [PATCH 52/56] Prepare for OS X.

---
 CMakeLists.txt          | 24 ++++++++++++++++++++----
 src/net/Network_mac.cpp | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 4 deletions(-)
 create mode 100644 src/net/Network_mac.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d2fb52623..d846fd987 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -85,8 +85,21 @@ if (WIN32)
         )
 
     set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
+elseif (APPLE)
+    set(SOURCES_OS
+        src/App_unix.cpp
+        src/Cpu_unix.cpp
+        src/Mem_unix.cpp
+        src/net/Network_mac.cpp
+        )
 else()
-    set(SOURCES_OS src/Cpu_unix.cpp src/Mem_unix.cpp)
+    set(SOURCES_OS
+        src/App_unix.cpp
+        src/Cpu_unix.cpp
+        src/Mem_unix.cpp
+        src/net/Network_unix.cpp
+        )
+
     set(EXTRA_LIBS pthread)
 endif()
 
@@ -105,17 +118,17 @@ endif()
 # https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
 if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
 
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall -fno-exceptions")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall")
     set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions -fno-rtti")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -std=c++14 -fno-exceptions -fno-rtti")
     set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
 
     set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
 
     add_definitions(/D_GNU_SOURCE)
 
-    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
+    #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
 
 elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
 
@@ -124,7 +137,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
 
 elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
 
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall")
     set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -fmerge-all-constants")
+
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -std=c++14 -fno-exceptions -fno-rtti")
     set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -fmerge-all-constants")
 
 endif()
diff --git a/src/net/Network_mac.cpp b/src/net/Network_mac.cpp
new file mode 100644
index 000000000..79b58c516
--- /dev/null
+++ b/src/net/Network_mac.cpp
@@ -0,0 +1,40 @@
+/* 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 "net/Network.h"
+#include "version.h"
+
+
+char *Network::userAgent()
+{
+    const size_t max = 128;
+
+    char *buf = static_cast<char*>(malloc(max));
+    snprintf(buf, max, "%s/%s", APP_NAME, APP_VERSION);
+
+    return buf;
+}

From 1bf428f8da1836b9b10440be71114b78ffa80445 Mon Sep 17 00:00:00 2001
From: Admin <admin@mac-admin.local>
Date: Wed, 14 Jun 2017 20:37:59 +0300
Subject: [PATCH 53/56] Initial OS X support

---
 CMakeLists.txt          | 4 ++--
 src/Console.cpp         | 1 -
 src/Mem_unix.cpp        | 4 ++++
 src/Options.cpp         | 4 +++-
 src/Summary.cpp         | 4 +++-
 src/net/Network.h       | 2 +-
 src/workers/Workers.cpp | 6 ++++--
 7 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d846fd987..126c95805 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -138,10 +138,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
 elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
 
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall")
-    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -fmerge-all-constants")
+    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
 
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -std=c++14 -fno-exceptions -fno-rtti")
-    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -fmerge-all-constants")
+    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
 
 endif()
 
diff --git a/src/Console.cpp b/src/Console.cpp
index 5df744dbc..2ce56ee19 100644
--- a/src/Console.cpp
+++ b/src/Console.cpp
@@ -22,7 +22,6 @@
  */
 
 
-#include <malloc.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp
index 231b48fc4..eb3f9af64 100644
--- a/src/Mem_unix.cpp
+++ b/src/Mem_unix.cpp
@@ -44,7 +44,11 @@ bool Mem::allocate(int algo, int threads, bool doubleHash)
 
     m_flags |= HugepagesAvailable;
 
+#   if defined(__APPLE__)
+    m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0));
+#   else
     m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0));
+#   endif
 
     if (m_memory == MAP_FAILED) {
         m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
diff --git a/src/Options.cpp b/src/Options.cpp
index 8a8a31748..111543eca 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -396,7 +396,9 @@ void Options::showVersion()
 {
     printf(APP_NAME " " APP_VERSION "\n built on " __DATE__
 
-#   if defined(__GNUC__)
+#   if defined(__clang__)
+    " with clang " __clang_version__);
+#   elif defined(__GNUC__)
     " with GCC");
     printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
 #   elif defined(_MSC_VER)
diff --git a/src/Summary.cpp b/src/Summary.cpp
index 8c7d3ea31..8db808933 100644
--- a/src/Summary.cpp
+++ b/src/Summary.cpp
@@ -37,7 +37,9 @@ static void print_versions()
 {
     char buf[16];
 
-#   if defined(__GNUC__)
+#   if defined(__clang__)
+    snprintf(buf, 16, " clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__);
+#   elif defined(__GNUC__)
     snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
 #   elif defined(_MSC_VER)
     snprintf(buf, 16, " MSVC/%d", MSVC_VERSION);
diff --git a/src/net/Network.h b/src/net/Network.h
index d9192c9fe..2859abc8f 100644
--- a/src/net/Network.h
+++ b/src/net/Network.h
@@ -50,7 +50,7 @@ public:
 protected:
   void onClose(Client *client, int failures) override;
   void onJobReceived(Client *client, const Job &job) override;
-  void onJobResult(const JobResult &result);
+  void onJobResult(const JobResult &result) override;
   void onLoginCredentialsRequired(Client *client) override;
   void onLoginSuccess(Client *client) override;
 
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
index 27453fdb2..b512d282f 100644
--- a/src/workers/Workers.cpp
+++ b/src/workers/Workers.cpp
@@ -54,7 +54,7 @@ Job Workers::job()
     Job job = m_job;
     uv_rwlock_rdunlock(&m_rwlock);
 
-    return std::move(job);
+    return job;
 }
 
 
@@ -139,7 +139,9 @@ void Workers::onResult(uv_async_t *handle)
 void Workers::onTick(uv_timer_t *handle)
 {
     for (Handle *handle : m_workers) {
-        m_telemetry->add(handle->threadId(), handle->worker()->hashCount(), handle->worker()->timestamp());
+        if (handle->worker()) {
+            m_telemetry->add(handle->threadId(), handle->worker()->hashCount(), handle->worker()->timestamp());
+        }
     }
 
     if ((m_ticks++ & 0xF) == 0)  {

From 555eee8236d0476e7eed132cf3474f1ba1532175 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 14 Jun 2017 20:51:47 +0300
Subject: [PATCH 54/56] Add Cpu_mac.cpp

---
 CMakeLists.txt  |  2 +-
 src/Cpu_mac.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 src/Cpu_mac.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 126c95805..92b075ebd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -88,7 +88,7 @@ if (WIN32)
 elseif (APPLE)
     set(SOURCES_OS
         src/App_unix.cpp
-        src/Cpu_unix.cpp
+        src/Cpu_mac.cpp
         src/Mem_unix.cpp
         src/net/Network_mac.cpp
         )
diff --git a/src/Cpu_mac.cpp b/src/Cpu_mac.cpp
new file mode 100644
index 000000000..1b7c6b0a8
--- /dev/null
+++ b/src/Cpu_mac.cpp
@@ -0,0 +1,59 @@
+/* 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 <pthread.h>
+#include <sched.h>
+#include <unistd.h>
+
+
+#include "Cpu.h"
+
+
+void Cpu::init()
+{
+#   ifdef XMRIG_NO_LIBCPUID
+    m_totalThreads = sysconf(_SC_NPROCESSORS_CONF);
+#   endif
+
+    initCommon();
+}
+
+
+void Cpu::setAffinity(int id, unsigned long mask)
+{
+    cpu_set_t set;
+    CPU_ZERO(&set);
+
+    for (int i = 0; i < m_totalThreads; i++) {
+        if (mask & (1UL << i)) {
+            CPU_SET(i, &set);
+        }
+    }
+
+    if (id == -1) {
+        sched_setaffinity(0, sizeof(&set), &set);
+    } else {
+        pthread_setaffinity_np(pthread_self(), sizeof(&set), &set);
+    }
+}

From faf14f5e5a030545ccc3e66f995551427d6c897b Mon Sep 17 00:00:00 2001
From: Admin <admin@mac-admin.local>
Date: Wed, 14 Jun 2017 21:13:04 +0300
Subject: [PATCH 55/56] Fixes for OS X.

---
 src/Cpu_mac.cpp         | 14 --------------
 src/Cpu_unix.cpp        |  4 ++++
 src/net/Network_mac.cpp |  3 +--
 3 files changed, 5 insertions(+), 16 deletions(-)

diff --git a/src/Cpu_mac.cpp b/src/Cpu_mac.cpp
index 1b7c6b0a8..3b6c44001 100644
--- a/src/Cpu_mac.cpp
+++ b/src/Cpu_mac.cpp
@@ -42,18 +42,4 @@ void Cpu::init()
 
 void Cpu::setAffinity(int id, unsigned long mask)
 {
-    cpu_set_t set;
-    CPU_ZERO(&set);
-
-    for (int i = 0; i < m_totalThreads; i++) {
-        if (mask & (1UL << i)) {
-            CPU_SET(i, &set);
-        }
-    }
-
-    if (id == -1) {
-        sched_setaffinity(0, sizeof(&set), &set);
-    } else {
-        pthread_setaffinity_np(pthread_self(), sizeof(&set), &set);
-    }
 }
diff --git a/src/Cpu_unix.cpp b/src/Cpu_unix.cpp
index 1b7c6b0a8..cddf54f1f 100644
--- a/src/Cpu_unix.cpp
+++ b/src/Cpu_unix.cpp
@@ -42,6 +42,10 @@ void Cpu::init()
 
 void Cpu::setAffinity(int id, unsigned long mask)
 {
+    if (id == -1) {
+        return;
+    }
+    
     cpu_set_t set;
     CPU_ZERO(&set);
 
diff --git a/src/net/Network_mac.cpp b/src/net/Network_mac.cpp
index 79b58c516..c3c42a3e5 100644
--- a/src/net/Network_mac.cpp
+++ b/src/net/Network_mac.cpp
@@ -24,7 +24,6 @@
 
 #include <stdlib.h>
 
-
 #include "net/Network.h"
 #include "version.h"
 
@@ -34,7 +33,7 @@ char *Network::userAgent()
     const size_t max = 128;
 
     char *buf = static_cast<char*>(malloc(max));
-    snprintf(buf, max, "%s/%s", APP_NAME, APP_VERSION);
+    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;
 }

From 1587fb27d2311e0658bf48b8b926c4b3e1549188 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 14 Jun 2017 21:33:20 +0300
Subject: [PATCH 56/56] Fixes.

---
 CMakeLists.txt   | 1 +
 src/Cpu_unix.cpp | 4 ----
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 92b075ebd..9bce386cf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -84,6 +84,7 @@ if (WIN32)
         src/net/Network_win.cpp
         )
 
+    add_definitions(/DWIN32)
     set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
 elseif (APPLE)
     set(SOURCES_OS
diff --git a/src/Cpu_unix.cpp b/src/Cpu_unix.cpp
index cddf54f1f..1b7c6b0a8 100644
--- a/src/Cpu_unix.cpp
+++ b/src/Cpu_unix.cpp
@@ -42,10 +42,6 @@ void Cpu::init()
 
 void Cpu::setAffinity(int id, unsigned long mask)
 {
-    if (id == -1) {
-        return;
-    }
-    
     cpu_set_t set;
     CPU_ZERO(&set);