diff --git a/src/backend/cpu/interfaces/ICpuInfo.h b/src/backend/cpu/interfaces/ICpuInfo.h index e9d795cec..ff8776a59 100644 --- a/src/backend/cpu/interfaces/ICpuInfo.h +++ b/src/backend/cpu/interfaces/ICpuInfo.h @@ -29,6 +29,10 @@ #ifdef XMRIG_FEATURE_HWLOC using hwloc_const_bitmap_t = const struct hwloc_bitmap_s *; using hwloc_topology_t = struct hwloc_topology *; +#define MEMBIND_SUCCESS 1 +#define MEMBIND_FAIL_SUPP -1 +#define MEMBIND_FAIL_NODE -2 +#define MEMBIND_FAIL_BIND -3 #endif @@ -124,7 +128,7 @@ public: virtual uint32_t model() const = 0; # ifdef XMRIG_FEATURE_HWLOC - virtual bool membind(hwloc_const_bitmap_t nodeset) = 0; + virtual int8_t membind(hwloc_const_bitmap_t nodeset) = 0; virtual const std::vector &nodeset() const = 0; virtual hwloc_topology_t topology() const = 0; # endif diff --git a/src/backend/cpu/platform/HwlocCpuInfo.cpp b/src/backend/cpu/platform/HwlocCpuInfo.cpp index f6137c31e..20e2a8e2f 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.cpp +++ b/src/backend/cpu/platform/HwlocCpuInfo.cpp @@ -23,6 +23,7 @@ #include #include +#include #include @@ -191,16 +192,25 @@ xmrig::HwlocCpuInfo::~HwlocCpuInfo() } -bool xmrig::HwlocCpuInfo::membind(hwloc_const_bitmap_t nodeset) +int8_t xmrig::HwlocCpuInfo::membind(hwloc_const_bitmap_t nodeset) { if (!hwloc_topology_get_support(m_topology)->membind->set_thisthread_membind) { - return false; + return MEMBIND_FAIL_SUPP; } # if HWLOC_API_VERSION >= 0x20000 - return hwloc_set_membind(m_topology, nodeset, HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_THREAD | HWLOC_MEMBIND_BYNODESET) >= 0; + int rv = hwloc_set_membind(m_topology, nodeset, HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_THREAD | HWLOC_MEMBIND_BYNODESET); + int error = errno; + + if (rv < 0) { + LOG_WARN("hwloc_set_membind() error: \"%s\"\n", strerror(error)); + return MEMBIND_FAIL_BIND; + } + + return MEMBIND_SUCCESS; # else - return hwloc_set_membind_nodeset(m_topology, nodeset, HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_THREAD) >= 0; + return (hwloc_set_membind_nodeset(m_topology, nodeset, HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_THREAD) >= 0) + ? MEMBIND_SUCCESS : MEMBIND_FAIL_BIND; # endif } diff --git a/src/backend/cpu/platform/HwlocCpuInfo.h b/src/backend/cpu/platform/HwlocCpuInfo.h index a08ea33ef..9ef1d01b4 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.h +++ b/src/backend/cpu/platform/HwlocCpuInfo.h @@ -38,7 +38,7 @@ public: ~HwlocCpuInfo() override; protected: - bool membind(hwloc_const_bitmap_t nodeset) override; + int8_t membind(hwloc_const_bitmap_t nodeset) override; CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override; inline const char *backend() const override { return m_backend; } diff --git a/src/crypto/common/VirtualMemory_hwloc.cpp b/src/crypto/common/VirtualMemory_hwloc.cpp index 21b0bd46c..78f71722e 100644 --- a/src/crypto/common/VirtualMemory_hwloc.cpp +++ b/src/crypto/common/VirtualMemory_hwloc.cpp @@ -34,8 +34,13 @@ uint32_t xmrig::VirtualMemory::bindToNUMANode(int64_t affinity) auto pu = hwloc_get_pu_obj_by_os_index(Cpu::info()->topology(), static_cast(affinity)); - if (pu == nullptr || !Cpu::info()->membind(pu->nodeset)) { - LOG_WARN("CPU #%02" PRId64 " warning: \"can't bind memory\"", affinity); + if (pu == nullptr) { + LOG_WARN("CPU #%02" PRId64 " warning: \"can't bind memory: hwloc_get_pu_obj_by_os_index() failed\"", affinity); + + return 0; + } + if (Cpu::info()->membind(pu->nodeset) < 0) { + LOG_WARN("CPU #%02" PRId64 " warning: \"can't bind memory: Cpu::info()->membind() failed\"", affinity); return 0; } diff --git a/src/crypto/rx/RxNUMAStorage.cpp b/src/crypto/rx/RxNUMAStorage.cpp index cc66d76e5..016716fb9 100644 --- a/src/crypto/rx/RxNUMAStorage.cpp +++ b/src/crypto/rx/RxNUMAStorage.cpp @@ -42,20 +42,20 @@ constexpr size_t oneMiB = 1024 * 1024; static std::mutex mutex; -static bool bindToNUMANode(uint32_t nodeId) +static int8_t bindToNUMANode(uint32_t nodeId) { auto node = hwloc_get_numanode_obj_by_os_index(Cpu::info()->topology(), nodeId); if (!node) { - return false; + return MEMBIND_FAIL_NODE; } - if (Cpu::info()->membind(node->nodeset)) { + if (Cpu::info()->membind(node->nodeset) > 0) { Platform::setThreadAffinity(static_cast(hwloc_bitmap_first(node->cpuset))); - return true; + return MEMBIND_SUCCESS; } - return false; + return MEMBIND_FAIL_BIND; } @@ -210,10 +210,20 @@ private: static void allocate(RxNUMAStoragePrivate *d_ptr, uint32_t nodeId, bool hugePages, bool oneGbPages) { const uint64_t ts = Chrono::steadyMSecs(); + const int8_t br = bindToNUMANode(nodeId); - if (!bindToNUMANode(nodeId)) { - printSkipped(nodeId, "can't bind memory"); - + if (br < 0) { + switch (br) { + case MEMBIND_FAIL_SUPP: + printSkipped(nodeId, "can't bind memory: hwloc_topology_get_support() failed"); + break; + case MEMBIND_FAIL_NODE: + printSkipped(nodeId, "can't bind memory: hwloc_get_numanode_obj_by_os_index() failed"); + break; + case MEMBIND_FAIL_BIND: + printSkipped(nodeId, "can't bind memory: Cpu::info()->membind() failed"); + break; + } return; }