diff --git a/src/3rdparty/argon2/CMakeLists.txt b/src/3rdparty/argon2/CMakeLists.txt index 0217382af..2f1fc0a90 100644 --- a/src/3rdparty/argon2/CMakeLists.txt +++ b/src/3rdparty/argon2/CMakeLists.txt @@ -17,7 +17,7 @@ set(ARGON2_SOURCES set(ARGON2_X86_64_ENABLED ON) set(ARGON2_X86_64_LIBS argon2-sse2 argon2-ssse3 argon2-xop argon2-avx2 argon2-avx512f) -set(ARGON2_X86_64_SOURCES arch/x86_64/lib/argon2-arch.c arch/x86_64/lib/cpu-flags.c) +set(ARGON2_X86_64_SOURCES arch/x86_64/lib/argon2-arch.c) if (CMAKE_C_COMPILER_ID MATCHES MSVC) function(add_feature_impl FEATURE MSVC_FLAG DEF) diff --git a/src/3rdparty/argon2/arch/x86_64/lib/argon2-arch.c b/src/3rdparty/argon2/arch/x86_64/lib/argon2-arch.c index 48d2a77e1..b5f0b5e2c 100644 --- a/src/3rdparty/argon2/arch/x86_64/lib/argon2-arch.c +++ b/src/3rdparty/argon2/arch/x86_64/lib/argon2-arch.c @@ -4,7 +4,6 @@ #include "impl-select.h" -#include "cpu-flags.h" #include "argon2-sse2.h" #include "argon2-ssse3.h" #include "argon2-xop.h" @@ -26,7 +25,7 @@ void fill_segment_default(const argon2_instance_t *instance, void argon2_get_impl_list(argon2_impl_list *list) { static const argon2_impl IMPLS[] = { - { "x86_64", NULL, fill_segment_default }, + { "x86_64", NULL, fill_segment_default }, { "SSE2", xmrig_ar2_check_sse2, xmrig_ar2_fill_segment_sse2 }, { "SSSE3", xmrig_ar2_check_ssse3, xmrig_ar2_fill_segment_ssse3 }, { "XOP", xmrig_ar2_check_xop, xmrig_ar2_fill_segment_xop }, @@ -34,8 +33,6 @@ void argon2_get_impl_list(argon2_impl_list *list) { "AVX-512F", xmrig_ar2_check_avx512f, xmrig_ar2_fill_segment_avx512f }, }; - cpu_flags_get(); - list->count = sizeof(IMPLS) / sizeof(IMPLS[0]); list->entries = IMPLS; } diff --git a/src/3rdparty/argon2/arch/x86_64/lib/argon2-avx2.c b/src/3rdparty/argon2/arch/x86_64/lib/argon2-avx2.c index 976fd4711..c8bf56f52 100644 --- a/src/3rdparty/argon2/arch/x86_64/lib/argon2-avx2.c +++ b/src/3rdparty/argon2/arch/x86_64/lib/argon2-avx2.c @@ -9,8 +9,6 @@ # include #endif -#include "cpu-flags.h" - #define r16 (_mm256_setr_epi8( \ 2, 3, 4, 5, 6, 7, 0, 1, \ 10, 11, 12, 13, 14, 15, 8, 9, \ @@ -325,10 +323,9 @@ void xmrig_ar2_fill_segment_avx2(const argon2_instance_t *instance, argon2_posit } } -int xmrig_ar2_check_avx2(void) -{ - return cpu_flags_have_avx2(); -} + +extern int cpu_flags_has_avx2(void); +int xmrig_ar2_check_avx2(void) { return cpu_flags_has_avx2(); } #else diff --git a/src/3rdparty/argon2/arch/x86_64/lib/argon2-avx512f.c b/src/3rdparty/argon2/arch/x86_64/lib/argon2-avx512f.c index 994f35022..f9df1b875 100644 --- a/src/3rdparty/argon2/arch/x86_64/lib/argon2-avx512f.c +++ b/src/3rdparty/argon2/arch/x86_64/lib/argon2-avx512f.c @@ -10,8 +10,6 @@ # include #endif -#include "cpu-flags.h" - #define ror64(x, n) _mm512_ror_epi64((x), (n)) static __m512i f(__m512i x, __m512i y) @@ -310,10 +308,8 @@ void xmrig_ar2_fill_segment_avx512f(const argon2_instance_t *instance, argon2_po } } -int xmrig_ar2_check_avx512f(void) -{ - return cpu_flags_have_avx512f(); -} +extern int cpu_flags_has_avx512f(void); +int xmrig_ar2_check_avx512f(void) { return cpu_flags_has_avx512f(); } #else diff --git a/src/3rdparty/argon2/arch/x86_64/lib/argon2-sse2.c b/src/3rdparty/argon2/arch/x86_64/lib/argon2-sse2.c index 1e992b54e..099f851f8 100644 --- a/src/3rdparty/argon2/arch/x86_64/lib/argon2-sse2.c +++ b/src/3rdparty/argon2/arch/x86_64/lib/argon2-sse2.c @@ -7,8 +7,6 @@ # include #endif -#include "cpu-flags.h" - #define ror64_16(x) \ _mm_shufflehi_epi16( \ _mm_shufflelo_epi16((x), _MM_SHUFFLE(0, 3, 2, 1)), \ @@ -107,10 +105,8 @@ void xmrig_ar2_fill_segment_sse2(const argon2_instance_t *instance, argon2_posit fill_segment_128(instance, position); } -int xmrig_ar2_check_sse2(void) -{ - return cpu_flags_have_sse2(); -} +extern int cpu_flags_has_sse2(void); +int xmrig_ar2_check_sse2(void) { return cpu_flags_has_sse2(); } #else diff --git a/src/3rdparty/argon2/arch/x86_64/lib/argon2-ssse3.c b/src/3rdparty/argon2/arch/x86_64/lib/argon2-ssse3.c index b848e3ebe..58a022ca6 100644 --- a/src/3rdparty/argon2/arch/x86_64/lib/argon2-ssse3.c +++ b/src/3rdparty/argon2/arch/x86_64/lib/argon2-ssse3.c @@ -9,8 +9,6 @@ # include #endif -#include "cpu-flags.h" - #define r16 (_mm_setr_epi8( \ 2, 3, 4, 5, 6, 7, 0, 1, \ 10, 11, 12, 13, 14, 15, 8, 9)) @@ -119,10 +117,8 @@ void xmrig_ar2_fill_segment_ssse3(const argon2_instance_t *instance, argon2_posi fill_segment_128(instance, position); } -int xmrig_ar2_check_ssse3(void) -{ - return cpu_flags_have_ssse3(); -} +extern int cpu_flags_has_ssse3(void); +int xmrig_ar2_check_ssse3(void) { return cpu_flags_has_ssse3(); } #else diff --git a/src/3rdparty/argon2/arch/x86_64/lib/argon2-xop.c b/src/3rdparty/argon2/arch/x86_64/lib/argon2-xop.c index 2e8b965b5..6fc6aa4b2 100644 --- a/src/3rdparty/argon2/arch/x86_64/lib/argon2-xop.c +++ b/src/3rdparty/argon2/arch/x86_64/lib/argon2-xop.c @@ -9,8 +9,6 @@ # include #endif -#include "cpu-flags.h" - #define ror64(x, c) _mm_roti_epi64((x), -(c)) static __m128i f(__m128i x, __m128i y) @@ -107,10 +105,8 @@ void xmrig_ar2_fill_segment_xop(const argon2_instance_t *instance, argon2_positi fill_segment_128(instance, position); } -int xmrig_ar2_check_xop(void) -{ - return cpu_flags_have_xop(); -} +extern int cpu_flags_has_xop(void); +int xmrig_ar2_check_xop(void) { return cpu_flags_has_xop(); } #else diff --git a/src/3rdparty/argon2/arch/x86_64/lib/cpu-flags.c b/src/3rdparty/argon2/arch/x86_64/lib/cpu-flags.c deleted file mode 100644 index cd13cb015..000000000 --- a/src/3rdparty/argon2/arch/x86_64/lib/cpu-flags.c +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include - - -#include "cpu-flags.h" - -#include - -#ifdef _MSC_VER -# include -#else -# include -#endif - -#ifndef bit_OSXSAVE -# define bit_OSXSAVE (1 << 27) -#endif - -#ifndef bit_SSE2 -# define bit_SSE2 (1 << 26) -#endif - -#ifndef bit_SSSE3 -# define bit_SSSE3 (1 << 9) -#endif - -#ifndef bit_AVX2 -# define bit_AVX2 (1 << 5) -#endif - -#ifndef bit_AVX512F -# define bit_AVX512F (1 << 16) -#endif - -#ifndef bit_XOP -# define bit_XOP (1 << 11) -#endif - -#define PROCESSOR_INFO (1) -#define EXTENDED_FEATURES (7) - -#define EAX_Reg (0) -#define EBX_Reg (1) -#define ECX_Reg (2) -#define EDX_Reg (3) - - -enum { - X86_64_FEATURE_SSE2 = (1 << 0), - X86_64_FEATURE_SSSE3 = (1 << 1), - X86_64_FEATURE_XOP = (1 << 2), - X86_64_FEATURE_AVX2 = (1 << 3), - X86_64_FEATURE_AVX512F = (1 << 4), -}; - -static unsigned int cpu_flags; - - -static inline void cpuid(uint32_t level, int32_t output[4]) -{ -# ifdef _MSC_VER - __cpuid(output, (int) level); -# else - __cpuid_count(level, 0, output[0], output[1], output[2], output[3]); -# endif -} - - -static bool has_feature(uint32_t level, uint32_t reg, int32_t bit) -{ - int32_t cpu_info[4] = { 0 }; - cpuid(level, cpu_info); - - return (cpu_info[reg] & bit) != 0; -} - - -void cpu_flags_get(void) -{ - if (has_feature(PROCESSOR_INFO, EDX_Reg, bit_SSE2)) { - cpu_flags |= X86_64_FEATURE_SSE2; - } - - if (has_feature(PROCESSOR_INFO, ECX_Reg, bit_SSSE3)) { - cpu_flags |= X86_64_FEATURE_SSSE3; - } - - if (!has_feature(PROCESSOR_INFO, ECX_Reg, bit_OSXSAVE)) { - return; - } - - if (has_feature(EXTENDED_FEATURES, EBX_Reg, bit_AVX2)) { - cpu_flags |= X86_64_FEATURE_AVX2; - } - - if (has_feature(EXTENDED_FEATURES, EBX_Reg, bit_AVX512F)) { - cpu_flags |= X86_64_FEATURE_AVX512F; - } - - if (has_feature(0x80000001, ECX_Reg, bit_XOP)) { - cpu_flags |= X86_64_FEATURE_XOP; - } -} - -int cpu_flags_have_sse2(void) -{ - return cpu_flags & X86_64_FEATURE_SSE2; -} - -int cpu_flags_have_ssse3(void) -{ - return cpu_flags & X86_64_FEATURE_SSSE3; -} - -int cpu_flags_have_xop(void) -{ - return cpu_flags & X86_64_FEATURE_XOP; -} - -int cpu_flags_have_avx2(void) -{ - return cpu_flags & X86_64_FEATURE_AVX2; -} - -int cpu_flags_have_avx512f(void) -{ - return cpu_flags & X86_64_FEATURE_AVX512F; -} - diff --git a/src/3rdparty/argon2/arch/x86_64/lib/cpu-flags.h b/src/3rdparty/argon2/arch/x86_64/lib/cpu-flags.h deleted file mode 100644 index b546a8ba1..000000000 --- a/src/3rdparty/argon2/arch/x86_64/lib/cpu-flags.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef ARGON2_CPU_FLAGS_H -#define ARGON2_CPU_FLAGS_H - -void cpu_flags_get(void); - -int cpu_flags_have_sse2(void); -int cpu_flags_have_ssse3(void); -int cpu_flags_have_xop(void); -int cpu_flags_have_avx2(void); -int cpu_flags_have_avx512f(void); - -#endif // ARGON2_CPU_FLAGS_H diff --git a/src/3rdparty/argon2/lib/impl-select.c b/src/3rdparty/argon2/lib/impl-select.c index aa5d9911e..bc7d14383 100644 --- a/src/3rdparty/argon2/lib/impl-select.c +++ b/src/3rdparty/argon2/lib/impl-select.c @@ -2,79 +2,81 @@ #include #include "impl-select.h" - #include "3rdparty/argon2.h" -#define BENCH_SAMPLES 1024 + +extern uint64_t uv_hrtime(void); + + +#define BENCH_SAMPLES 1024U #define BENCH_MEM_BLOCKS 512 -static argon2_impl selected_argon_impl = { - "default", NULL, fill_segment_default -}; + +#ifdef _MSC_VER +# define strcasecmp _stricmp +#endif + + +static argon2_impl selected_argon_impl = { "default", NULL, fill_segment_default }; + /* the benchmark routine is not thread-safe, so we can use a global var here: */ static block memory[BENCH_MEM_BLOCKS]; -static uint64_t benchmark_impl(const argon2_impl *impl) { - clock_t time; - unsigned int i; - uint64_t bench; - argon2_instance_t instance; - argon2_position_t pos; +static uint64_t benchmark_impl(const argon2_impl *impl) { memset(memory, 0, sizeof(memory)); - instance.version = ARGON2_VERSION_NUMBER; - instance.memory = memory; - instance.passes = 1; - instance.memory_blocks = BENCH_MEM_BLOCKS; + argon2_instance_t instance; + instance.version = ARGON2_VERSION_NUMBER; + instance.memory = memory; + instance.passes = 1; + instance.memory_blocks = BENCH_MEM_BLOCKS; instance.segment_length = BENCH_MEM_BLOCKS / ARGON2_SYNC_POINTS; - instance.lane_length = instance.segment_length * ARGON2_SYNC_POINTS; - instance.lanes = 1; - instance.threads = 1; - instance.type = Argon2_i; + instance.lane_length = instance.segment_length * ARGON2_SYNC_POINTS; + instance.lanes = 1; + instance.threads = 1; + instance.type = Argon2_id; - pos.lane = 0; - pos.pass = 0; - pos.slice = 0; - pos.index = 0; + argon2_position_t pos; + pos.lane = 0; + pos.pass = 0; + pos.slice = 0; + pos.index = 0; /* warm-up cache: */ impl->fill_segment(&instance, pos); /* OK, now measure: */ - bench = 0; - time = clock(); - for (i = 0; i < BENCH_SAMPLES; i++) { + const uint64_t time = uv_hrtime(); + + for (uint32_t i = 0; i < BENCH_SAMPLES; i++) { impl->fill_segment(&instance, pos); } - time = clock() - time; - bench = (uint64_t)time; - return bench; + + return uv_hrtime() - time; } + void argon2_select_impl() { argon2_impl_list impls; - unsigned int i; const argon2_impl *best_impl = NULL; uint64_t best_bench = UINT_MAX; argon2_get_impl_list(&impls); - for (i = 0; i < impls.count; i++) { + for (uint32_t i = 0; i < impls.count; i++) { const argon2_impl *impl = &impls.entries[i]; - uint64_t bench; if (impl->check != NULL && !impl->check()) { continue; } - bench = benchmark_impl(impl); - + const uint64_t bench = benchmark_impl(impl); if (bench < best_bench) { best_bench = bench; - best_impl = impl; + best_impl = impl; } } @@ -83,11 +85,13 @@ void argon2_select_impl() } } + void xmrig_ar2_fill_segment(const argon2_instance_t *instance, argon2_position_t position) { selected_argon_impl.fill_segment(instance, position); } + const char *argon2_get_impl_name() { return selected_argon_impl.name; @@ -97,14 +101,12 @@ const char *argon2_get_impl_name() int argon2_select_impl_by_name(const char *name) { argon2_impl_list impls; - unsigned int i; - argon2_get_impl_list(&impls); - for (i = 0; i < impls.count; i++) { + for (uint32_t i = 0; i < impls.count; i++) { const argon2_impl *impl = &impls.entries[i]; - if (strcmp(impl->name, name) == 0) { + if (strcasecmp(impl->name, name) == 0) { selected_argon_impl = *impl; return 1; diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index bd8e0ad11..45a968a64 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -277,19 +277,7 @@ void xmrig::CpuBackend::prepare(const Job &nextJob) # ifdef XMRIG_ALGO_ARGON2 const xmrig::Algorithm::Family f = nextJob.algorithm().family(); if ((f == Algorithm::ARGON2) || (f == Algorithm::RANDOM_X)) { - - xmrig::String impl = d_ptr->controller->config()->cpu().argon2Impl(); - - if (impl.isEmpty()) { - if (xmrig::Cpu::info()->hasAVX2()) { - impl = "AVX2"; - } - else if (xmrig::Cpu::info()->isX64()) { - impl = "SSE2"; - } - } - - if (argon2::Impl::select(impl)) { + if (argon2::Impl::select(d_ptr->controller->config()->cpu().argon2Impl())) { LOG_INFO("%s use " WHITE_BOLD("argon2") " implementation " CSI "1;%dm" "%s", tag, argon2::Impl::name() == "default" ? 33 : 32, diff --git a/src/backend/cpu/platform/BasicCpuInfo.cpp b/src/backend/cpu/platform/BasicCpuInfo.cpp index 2d2367fbb..eb0429805 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.cpp +++ b/src/backend/cpu/platform/BasicCpuInfo.cpp @@ -59,7 +59,6 @@ namespace xmrig { static const std::array flagNames = { "aes", "avx2", "avx512f", "bmi2", "osxsave", "pdpe1gb", "sse2", "ssse3", "xop" }; static const std::array msrNames = { "none", "ryzen", "intel", "custom" }; -std::bitset BasicCpuInfo::m_flags; static inline void cpuid(uint32_t level, int32_t output[4]) @@ -134,6 +133,21 @@ static inline bool has_xop() { return has_feature(0x80000001, } // namespace xmrig +#ifdef XMRIG_ALGO_ARGON2 +extern "C" { + + +int cpu_flags_has_avx2() { return xmrig::has_avx2(); } +int cpu_flags_has_avx512f() { return xmrig::has_avx512f(); } +int cpu_flags_has_sse2() { return xmrig::has_sse2(); } +int cpu_flags_has_ssse3() { return xmrig::has_ssse3(); } +int cpu_flags_has_xop() { return xmrig::has_xop(); } + + +} +#endif + + xmrig::BasicCpuInfo::BasicCpuInfo() : m_threads(std::thread::hardware_concurrency()) { diff --git a/src/backend/cpu/platform/BasicCpuInfo.h b/src/backend/cpu/platform/BasicCpuInfo.h index 4d0fa745d..ea478dbf1 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.h +++ b/src/backend/cpu/platform/BasicCpuInfo.h @@ -67,10 +67,9 @@ protected: Vendor m_vendor = VENDOR_UNKNOWN; private: - static std::bitset m_flags; - Assembly m_assembly = Assembly::NONE; MsrMod m_msrMod = MSR_MOD_NONE; + std::bitset m_flags; }; diff --git a/src/backend/cpu/platform/BasicCpuInfo_arm.cpp b/src/backend/cpu/platform/BasicCpuInfo_arm.cpp index 9191a2b72..653304c8f 100644 --- a/src/backend/cpu/platform/BasicCpuInfo_arm.cpp +++ b/src/backend/cpu/platform/BasicCpuInfo_arm.cpp @@ -37,9 +37,6 @@ #include "3rdparty/rapidjson/document.h" -std::bitset xmrig::BasicCpuInfo::m_flags; - - xmrig::BasicCpuInfo::BasicCpuInfo() : m_threads(std::thread::hardware_concurrency()) { diff --git a/src/crypto/argon2/Impl.cpp b/src/crypto/argon2/Impl.cpp index d0f267f95..02084a57d 100644 --- a/src/crypto/argon2/Impl.cpp +++ b/src/crypto/argon2/Impl.cpp @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2020 SChernykh + * Copyright 2016-2020 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,10 +39,39 @@ static String implName; } // namespace xmrig -bool xmrig::argon2::Impl::select(const String &nameHint) +extern "C" { + + +extern int xmrig_ar2_check_avx512f(); +extern int xmrig_ar2_check_avx2(); +extern int xmrig_ar2_check_ssse3(); +extern int xmrig_ar2_check_sse2(); + + +} + + +bool xmrig::argon2::Impl::select(const String &nameHint, bool benchmark) { if (!selected) { - if (nameHint.isEmpty() || argon2_select_impl_by_name(nameHint) == 0) { + auto hint = nameHint; + + if (hint.isEmpty() && !benchmark) { + if (xmrig_ar2_check_avx512f()) { + hint = "AVX-512F"; + } + else if (xmrig_ar2_check_avx2()) { + hint = "AVX2"; + } + else if (xmrig_ar2_check_ssse3()) { + hint = "SSSE3"; + } + else if (xmrig_ar2_check_sse2()) { + hint = "SSE2"; + } + } + + if (hint.isEmpty() || argon2_select_impl_by_name(hint) == 0) { argon2_select_impl(); } diff --git a/src/crypto/argon2/Impl.h b/src/crypto/argon2/Impl.h index 006dbd35f..aaedec028 100644 --- a/src/crypto/argon2/Impl.h +++ b/src/crypto/argon2/Impl.h @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2020 SChernykh + * Copyright 2016-2020 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,7 +38,7 @@ namespace argon2 { class Impl { public: - static bool select(const String &nameHint); + static bool select(const String &nameHint, bool benchmark = false); static const String &name(); };