1
0
mirror of https://github.com/xmrig/xmrig.git synced 2025-12-07 07:55:04 -05:00

Compare commits

...

29 Commits

Author SHA1 Message Date
XMRig
6e4a5a6d94 v6.24.0 2025-06-23 07:44:53 +07:00
XMRig
273133aa63 Merge branch 'dev' 2025-06-23 07:44:05 +07:00
xmrig
c69e30c9a0 Update CHANGELOG.md 2025-06-23 05:39:26 +07:00
XMRig
6a690ba1e9 More DNS cleanup. 2025-06-20 23:45:53 +07:00
XMRig
545aef0937 v6.24.0-dev 2025-06-20 08:34:58 +07:00
xmrig
9fa66d3242 Merge pull request #3678 from xmrig/dns_ip_version
Improved IPv6 support.
2025-06-20 08:33:50 +07:00
XMRig
ec286c7fef Improved IPv6 support. 2025-06-20 07:39:52 +07:00
xmrig
e28d663d80 Merge pull request #3677 from SChernykh/dev
Tweaked autoconfig for AMD CPUs with < 2 MB L3 cache per thread, again (hopefully the last time)
2025-06-19 18:07:54 +07:00
SChernykh
aba1ad8cfc Tweaked autoconfig for AMD CPUs with < 2 MB L3 cache per thread, again (hopefully the last time) 2025-06-19 12:58:31 +02:00
xmrig
bf44ed52e9 Merge pull request #3674 from benthetechguy/armhf
cflags: Add lax-vector-conversions on ARMv7
2025-06-19 04:46:02 +07:00
Ben Westover
762c435fa8 cflags: Add lax-vector-conversions on ARMv7
lax-vector-conversions is enabled in the CXXFLAGS but not CFLAGS for ARMv7.
This commit adds it to CFLAGS which fixes the ARMv7 build (Fixes: #3673).
2025-06-18 16:38:05 -04:00
xmrig
48faf0a11b Merge pull request #3671 from SChernykh/dev
Hwloc: fixed detection of L2 cache size for some complex NUMA topologies
2025-06-17 18:52:43 +07:00
SChernykh
d125d22d27 Hwloc: fixed detection of L2 cache size for some complex NUMA topologies 2025-06-17 13:49:02 +02:00
XMRig
9f3591ae0d v6.23.1-dev 2025-06-16 21:29:17 +07:00
XMRig
6bbbcc71f1 Merge branch 'master' into dev 2025-06-16 21:28:48 +07:00
XMRig
e5a7a69cc0 v6.23.0 2025-06-16 21:00:42 +07:00
XMRig
f354b85a7b Merge branch 'dev' 2025-06-16 21:00:12 +07:00
xmrig
5ed8d79574 Update CHANGELOG.md 2025-06-16 20:46:33 +07:00
XMRig
fc395a5800 Update ARM CPUs database. 2025-06-16 19:54:08 +07:00
XMRig
9138690126 v6.23.0-dev 2025-06-16 02:05:43 +07:00
XMRig
d58061c903 Add detection for _aligned_malloc. 2025-06-15 20:06:19 +07:00
XMRig
3b863cf88f Fixed __umul128 for MSVC ARM64. 2025-06-15 04:58:03 +07:00
XMRig
9c7468df64 Fixed user agent string. 2025-06-15 00:21:23 +07:00
xmrig
a18fa269a6 Merge pull request #3666 from SChernykh/dev
Better detection of aligned malloc functions
2025-06-14 23:09:05 +07:00
SChernykh
bcc5581535 Better detection of aligned malloc functions 2025-06-14 18:00:27 +02:00
XMRig
dba336aa04 Update hwloc for MSVC. 2025-06-14 22:11:33 +07:00
XMRig
3ff41f7c94 Fixed UTF-8 paths support for the config file with Clang compiler on Windows ARM64. 2025-06-14 15:38:25 +07:00
XMRig
faa3d55123 Remove deprecated -Ofast for Clang. 2025-06-13 21:53:03 +07:00
XMRig
9e7cf69ac3 Detect CPU name and AES instructions on Windows ARM64. 2025-06-13 21:02:10 +07:00
50 changed files with 1118 additions and 663 deletions

View File

@@ -1,3 +1,13 @@
# v6.24.0
- [#3671](https://github.com/xmrig/xmrig/pull/3671) Fixed detection of L2 cache size for some complex NUMA topologies.
- [#3674](https://github.com/xmrig/xmrig/pull/3674) Fixed ARMv7 build.
- [#3677](https://github.com/xmrig/xmrig/pull/3677) Fixed auto-config for AMD CPUs with less than 2 MB L3 cache per thread.
- [#3678](https://github.com/xmrig/xmrig/pull/3678) Improved IPv6 support: the new default settings use IPv6 equally with IPv4.
# v6.23.0
- [#3668](https://github.com/xmrig/xmrig/issues/3668) Added support for Windows ARM64.
- [#3665](https://github.com/xmrig/xmrig/pull/3665) Tweaked auto-config for AMD CPUs with < 2 MB L3 cache per thread.
# v6.22.3
- [#3605](https://github.com/xmrig/xmrig/pull/3605) CUDA backend: added missing RandomX dataset update.
- [#3646](https://github.com/xmrig/xmrig/pull/3646) Optimized auto-config for AMD CPUs with less than 2 MB L3 cache per thread.

View File

@@ -51,7 +51,7 @@ if (ARM_TARGET AND ARM_TARGET GREATER 6)
message(STATUS "Use ARM_TARGET=${ARM_TARGET} (${CMAKE_SYSTEM_PROCESSOR})")
if (ARM_TARGET EQUAL 8)
if (ARM_TARGET EQUAL 8 AND (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang))
CHECK_CXX_COMPILER_FLAG(-march=armv8-a+crypto XMRIG_ARM_CRYPTO)
if (XMRIG_ARM_CRYPTO)

View File

@@ -26,7 +26,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARM8_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARM8_CXX_FLAGS} -flax-vector-conversions")
elseif (ARM_TARGET EQUAL 7)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfpu=neon")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfpu=neon -flax-vector-conversions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mfpu=neon -flax-vector-conversions")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
@@ -63,10 +63,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -funroll-loops -fmerge-all-constants")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexceptions -fno-rtti -Wno-missing-braces")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexceptions -fno-rtti")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -funroll-loops -fmerge-all-constants")
if (ARM_TARGET EQUAL 8)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARM8_CXX_FLAGS}")
@@ -84,10 +84,9 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
endif()
endif()
if (BUILD_STATIC OR WIN32)
if ((WIN32 AND ARM_TARGET) OR BUILD_STATIC)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
endif()
endif()
if (NOT WIN32)

View File

@@ -1,4 +1,18 @@
if (WITH_RANDOMX)
include(CheckSymbolExists)
if (WIN32)
check_symbol_exists(_aligned_malloc "stdlib.h" HAVE_ALIGNED_MALLOC)
if (HAVE_ALIGNED_MALLOC)
add_compile_definitions(HAVE_ALIGNED_MALLOC)
endif()
else()
check_symbol_exists(posix_memalign "stdlib.h" HAVE_POSIX_MEMALIGN)
if (HAVE_POSIX_MEMALIGN)
add_compile_definitions(HAVE_POSIX_MEMALIGN)
endif()
endif()
add_definitions(/DXMRIG_ALGO_RANDOMX)
set(WITH_ARGON2 ON)

View File

@@ -1,5 +1,5 @@
Copyright © 2009 CNRS
Copyright © 2009-2024 Inria. All rights reserved.
Copyright © 2009-2025 Inria. All rights reserved.
Copyright © 2009-2013 Université Bordeaux
Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
Copyright © 2020 Hewlett Packard Enterprise. All rights reserved.
@@ -17,6 +17,52 @@ bug fixes (and other actions) for each version of hwloc since version
0.9.
Version 2.12.1
--------------
* Add hwloc-calc's --default-nodes option to hwloc-bind and hwloc-info.
* Improve the --best-memattr "default" fallback, try to use "default"
memory nodes, and add verbose messages and warnings if some
performance info are incomplete or missing.
Thanks to Antoine Morvan for the report.
* Fix CPU and memory binding on different locations,
thanks to Antoine Morvan for the report.
* Add HWLOC_LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY and enable it by
default in hwloc-calc --local-memory for finding local NUMA nodes
that do not exactly match input locations.
Thanks to Antoine Morvan for the report.
* Fix a possible crash in the x86 backend when Qemu is configured to
expose multicore/thread CPUs that are actually single-core/thread.
Thanks to Georg Pfuetzenreuter.
Version 2.12.0
--------------
* Add hwloc_topology_get_default_nodeset() for the set of default
NUMA nodes.
- hwloc-calc now has --default-nodes option.
* Rework oneAPI LevelZero support to use zesInit() and avoid the need
to set ZES_ENABLE_SYSMAN=1 in the environment.
- zesDriverGetDeviceByUuidExp() is now required in the L0 runtime.
- ZES/Sysman variants were added in hwloc/levelzero.h to specifically
handle ZES/Sysman device handles.
* Fix the locality of AMD GPU partitions, thanks to Edgar Leon for
reporting and debugging the issue.
* Better detect Cray Slingshot NICs, thanks to Edgar Leon.
* Add support for Die objects and Module groups on Windows.
* Only filter-out Dies that are identical to their Packages
when it applies to all Dies.
* Improve hwloc-calc to handle CPU-less NUMA nodes or platforms with
heterogeneous memory without requiring --nodeset-output.
* hwloc-calc now accepts counting/listing cpukinds and memory tiers
with -N and -I cpukind/memorytier.
* The systemd-dbus-api output of hwloc-calc has changed, and
--nodeset-output-format was added, to support NUMA node outputs.
Thanks to Pierre Neyron.
* Update NVLink bandwidth and CUDA capabilities up to NVIDIA Blackwell.
* Fix some NUMA syscalls on Linux for platforms with old libc headers.
* Some minor fixes in distances.
Version 2.11.2
--------------
* Add missing CPU info attrs on aarch64 on Linux.

View File

@@ -8,8 +8,8 @@
# Please update HWLOC_VERSION* in contrib/windows/hwloc_config.h too.
major=2
minor=11
release=2
minor=12
release=1
# greek is used for alpha or beta release tags. If it is non-empty,
# it will be appended to the version number. It does not have to be
@@ -22,7 +22,7 @@ greek=
# The date when this release was created
date="Sep 26, 2024"
date="May 12, 2025"
# If snapshot=1, then use the value from snapshot_version as the
# entire hwloc version (i.e., ignore major, minor, release, and
@@ -41,6 +41,6 @@ snapshot_version=${major}.${minor}.${release}${greek}-git
# 2. Version numbers are described in the Libtool current:revision:age
# format.
libhwloc_so_version=23:1:8
libhwloc_so_version=25:0:10
# Please also update the <TargetName> lines in contrib/windows/libhwloc.vcxproj

View File

@@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2025 Inria. All rights reserved.
* Copyright © 2009-2012 Université Bordeaux
* Copyright © 2009-2020 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@@ -112,7 +112,7 @@ extern "C" {
* Two stable releases of the same series usually have the same ::HWLOC_API_VERSION
* even if their HWLOC_VERSION are different.
*/
#define HWLOC_API_VERSION 0x00020b00
#define HWLOC_API_VERSION 0x00020c00
/** \brief Indicate at runtime which hwloc API version was used at build time.
*
@@ -346,9 +346,10 @@ typedef enum {
*
* Some operating systems (e.g. Linux) may expose a single die per package
* even if the hardware does not support dies at all. To avoid showing
* such non-existing dies, the corresponding hwloc backend may filter them out.
* such non-existing dies, hwloc will filter them out if all of them are
* identical to packages.
* This is functionally equivalent to ::HWLOC_TYPE_FILTER_KEEP_STRUCTURE
* being enforced.
* being enforced for Dies versus Packages.
*/
HWLOC_OBJ_TYPE_MAX /**< \private Sentinel value */
@@ -1047,7 +1048,7 @@ HWLOC_DECLSPEC const char * hwloc_obj_type_string (hwloc_obj_type_t type) __hwlo
* If \p size is 0, \p string may safely be \c NULL.
*
* \return the number of characters that were actually written if not truncating,
* or that would have been written (not including the ending \\0).
* or that would have been written (not including the ending \c \0).
*/
HWLOC_DECLSPEC int hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_t size,
hwloc_obj_t obj,
@@ -1062,7 +1063,7 @@ HWLOC_DECLSPEC int hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_
* If \p size is 0, \p string may safely be \c NULL.
*
* \return the number of characters that were actually written if not truncating,
* or that would have been written (not including the ending \\0).
* or that would have been written (not including the ending \c \0).
*/
HWLOC_DECLSPEC int hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_t size,
hwloc_obj_t obj, const char * __hwloc_restrict separator,
@@ -2002,7 +2003,7 @@ HWLOC_DECLSPEC int hwloc_topology_set_xml(hwloc_topology_t __hwloc_restrict topo
* a file, as with hwloc_topology_set_xml()).
*
* Gather topology information from the XML memory buffer given at
* \p buffer and of length \p size (including an ending \0).
* \p buffer and of length \p size (including an ending \c \0).
* This buffer may have been filled earlier with
* hwloc_topology_export_xmlbuffer() in hwloc/export.h.
*

View File

@@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2025 Inria. All rights reserved.
* Copyright © 2009-2012 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@@ -11,10 +11,10 @@
#ifndef HWLOC_CONFIG_H
#define HWLOC_CONFIG_H
#define HWLOC_VERSION "2.11.2"
#define HWLOC_VERSION "2.12.1"
#define HWLOC_VERSION_MAJOR 2
#define HWLOC_VERSION_MINOR 11
#define HWLOC_VERSION_RELEASE 2
#define HWLOC_VERSION_MINOR 12
#define HWLOC_VERSION_RELEASE 1
#define HWLOC_VERSION_GREEK ""
#define __hwloc_restrict

View File

@@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2023 Inria. All rights reserved.
* Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2012 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@@ -113,51 +113,88 @@ HWLOC_DECLSPEC int hwloc_bitmap_copy(hwloc_bitmap_t dst, hwloc_const_bitmap_t sr
* Bitmap/String Conversion
*/
/** \brief Stringify a bitmap.
/** \brief Stringify a bitmap in the default hwloc format.
*
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
*
* Print the bits set inside a bitmap as a comma-separated list of hexadecimal 32-bit blocks.
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as <tt>"0xffffffff,0x00000006,0x00000002"</tt>.
*
* Up to \p buflen characters may be written in buffer \p buf.
*
* If \p buflen is 0, \p buf may safely be \c NULL.
*
* \return the number of characters that were actually written if not truncating,
* or that would have been written (not including the ending \\0).
* or that would have been written (not including the ending \c \0).
* \return -1 on error.
*/
HWLOC_DECLSPEC int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
/** \brief Stringify a bitmap into a newly allocated string.
/** \brief Stringify a bitmap into a newly allocated string in the default hwloc format.
*
* \return 0 on success, -1 on error.
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
*
* Print the bits set inside a bitmap as a comma-separated list of hexadecimal 32-bit blocks.
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as <tt>"0xffffffff,0x00000006,0x00000002"</tt>.
*
* \return the number of characters that were written (not including the ending \c \0).
* \return -1 on error, for instance with \p errno set to \c ENOMEM on failure to allocate the output string.
*/
HWLOC_DECLSPEC int hwloc_bitmap_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
/** \brief Parse a bitmap string and stores it in bitmap \p bitmap.
/** \brief Parse a bitmap string as the default hwloc format and stores it in bitmap \p bitmap.
*
* <b>Note that if the bitmap is a CPU or nodeset, the input string must contain physical indexes.</b>
*
* The input string should be a comma-separared list of hexadecimal 32-bit blocks.
* String <tt>"0xffffffff,0x6,0x2"</tt> is parsed as a bitmap containing all bits between 64 and 95,
* and bits 33, 34 and 1.
*
* \return 0 on success, -1 on error.
*/
HWLOC_DECLSPEC int hwloc_bitmap_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
/** \brief Stringify a bitmap in the list format.
*
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
*
* Lists are comma-separated indexes or ranges.
* Ranges are dash separated indexes.
* The last range may not have an ending indexes if the bitmap is infinitely set.
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as <tt>"1,33-34,64-95"</tt>.
* The last range may not have an ending index if the bitmap is infinitely set.
*
* Up to \p buflen characters may be written in buffer \p buf.
*
* If \p buflen is 0, \p buf may safely be \c NULL.
*
* \return the number of characters that were actually written if not truncating,
* or that would have been written (not including the ending \\0).
* or that would have been written (not including the ending \c \0).
* \return -1 on error.
*/
HWLOC_DECLSPEC int hwloc_bitmap_list_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
/** \brief Stringify a bitmap into a newly allocated list string.
*
* \return 0 on success, -1 on error.
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
*
* Lists are comma-separated indexes or ranges.
* Ranges are dash separated indexes.
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as <tt>"1,33-34,64-95"</tt>.
* The last range may not have an ending index if the bitmap is infinitely set.
*
* \return the number of characters that were written (not including the ending \c \0).
* \return -1 on error, for instance with \p errno set to \c ENOMEM on failure to allocate the output string.
*/
HWLOC_DECLSPEC int hwloc_bitmap_list_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
/** \brief Parse a list string and stores it in bitmap \p bitmap.
*
* <b>Note that if the bitmap is a CPU or nodeset, the input string must contain physical indexes.</b>
*
* Lists are comma-separated indexes or ranges.
* Ranges are dash separated indexes.
* String <tt>"1,33-34,64-95"</tt> is parsed as a bitmap containing bits 1, 33, 34, and all from 64 to 95.
* The last range may not have an ending index if the bitmap is infinitely set.
*
* \return 0 on success, -1 on error.
*/
@@ -165,25 +202,43 @@ HWLOC_DECLSPEC int hwloc_bitmap_list_sscanf(hwloc_bitmap_t bitmap, const char *
/** \brief Stringify a bitmap in the taskset-specific format.
*
* The taskset command manipulates bitmap strings that contain a single
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
*
* The taskset program manipulates bitmap strings that contain a single
* (possible very long) hexadecimal number starting with 0x.
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as </tt>"0xffffffff0000000600000002"</tt>.
*
* Up to \p buflen characters may be written in buffer \p buf.
*
* If \p buflen is 0, \p buf may safely be \c NULL.
*
* \return the number of characters that were actually written if not truncating,
* or that would have been written (not including the ending \\0).
* or that would have been written (not including the ending \c \0).
* \return -1 on error.
*/
HWLOC_DECLSPEC int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
/** \brief Stringify a bitmap into a newly allocated taskset-specific string.
*
* \return 0 on success, -1 on error.
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
*
* The taskset program manipulates bitmap strings that contain a single
* (possible very long) hexadecimal number starting with 0x.
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as <tt>"0xffffffff0000000600000002"</tt>.
*
* \return the number of characters that were written (not including the ending \c \0).
* \return -1 on error, for instance with \p errno set to \c ENOMEM on failure to allocate the output string.
*/
HWLOC_DECLSPEC int hwloc_bitmap_taskset_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
/** \brief Parse a taskset-specific bitmap string and stores it in bitmap \p bitmap.
*
* <b>Note that if the bitmap is a CPU or nodeset, the input string must contain physical indexes.</b>
*
* The taskset program manipulates bitmap strings that contain a single
* (possible very long) hexadecimal number starting with 0x.
* String <tt>"0xffffffff0000000600000002"</tt> is parsed as a bitmap containing all bits between 64 and 95,
* and bits 33, 34 and 1.
*
* \return 0 on success, -1 on error.
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2013-2023 Inria. All rights reserved.
* Copyright © 2013-2024 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
@@ -258,7 +258,7 @@ HWLOC_DECLSPEC int hwloc_topology_diff_export_xml(hwloc_topology_diff_t diff, co
/** \brief Load a list of topology differences from a XML buffer.
*
* Build a list of differences from the XML memory buffer given
* at \p xmlbuffer and of length \p buflen (including an ending \0).
* at \p xmlbuffer and of length \p buflen (including an ending \c \0).
* This buffer may have been filled earlier with
* hwloc_topology_diff_export_xmlbuffer().
*
@@ -284,7 +284,7 @@ HWLOC_DECLSPEC int hwloc_topology_diff_load_xmlbuffer(const char *xmlbuffer, int
* that contains the reference topology.
* This attribute is given back when reading the diff from XML.
*
* The returned buffer ends with a \0 that is included in the returned
* The returned buffer ends with a \c \0 that is included in the returned
* length.
*
* \return 0 on success, -1 on error.

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2010-2024 Inria. All rights reserved.
* Copyright © 2010-2025 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
@@ -227,17 +227,24 @@ enum hwloc_distances_transform_e {
HWLOC_DISTANCES_TRANSFORM_LINKS = 1,
/** \brief Merge switches with multiple ports into a single object.
* This currently only applies to NVSwitches where GPUs seem connected to different
* separate switch ports in the NVLinkBandwidth matrix. This transformation will
* replace all of them with the same port connected to all GPUs.
* Other ports are removed by applying ::HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL internally.
*
* This currently only applies to NVSwitches where GPUs seem connected
* to different switch ports. Switch ports must be objects with subtype
* "NVSwitch" as in the NVLinkBandwidth matrix.
*
* This transformation will replace all ports with only the first one,
* now connected to all GPUs. Other ports are removed by applying
* ::HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL internally.
* \hideinitializer
*/
HWLOC_DISTANCES_TRANSFORM_MERGE_SWITCH_PORTS = 2,
/** \brief Apply a transitive closure to the matrix to connect objects across switches.
* This currently only applies to GPUs and NVSwitches in the NVLinkBandwidth matrix.
* All pairs of GPUs will be reported as directly connected.
*
* All pairs of GPUs will be reported as directly connected instead GPUs being
* only connected to switches.
*
* Switch ports must be objects with subtype "NVSwitch" as in the NVLinkBandwidth matrix.
* \hideinitializer
*/
HWLOC_DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE = 3

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Inria. All rights reserved.
* Copyright © 2021-2024 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
@@ -32,7 +32,8 @@ extern "C" {
/** \defgroup hwlocality_levelzero Interoperability with the oneAPI Level Zero interface.
*
* This interface offers ways to retrieve topology information about
* devices managed by the Level Zero API.
* devices managed by the Level Zero API, both for main Core devices (ZE API)
* and the Sysman devices (ZES API).
*
* @{
*/
@@ -44,9 +45,68 @@ extern "C" {
* the Level Zero device \p device.
*
* Topology \p topology and device \p device must match the local machine.
* The Level Zero library must have been initialized with zeInit().
* I/O devices detection and the Level Zero component are not needed in the
* topology.
*
* The function only returns the locality of the device.
* If more information about the device is needed, OS objects should
* be used instead, see hwloc_levelzero_get_device_osdev().
*
* This function is currently only implemented in a meaningful way for
* Linux; other systems will simply get a full cpuset.
*
* \return 0 on success.
* \return -1 on error, for instance if device information could not be found.
*
* \note zeDevicePciGetPropertiesExt() must be supported, or the entire machine
* locality will be returned.
*/
static __hwloc_inline int
hwloc_levelzero_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
ze_device_handle_t device, hwloc_cpuset_t set)
{
#ifdef HWLOC_LINUX_SYS
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
#define HWLOC_LEVELZERO_DEVICE_SYSFS_PATH_MAX 128
char path[HWLOC_LEVELZERO_DEVICE_SYSFS_PATH_MAX];
ze_pci_ext_properties_t pci;
ze_result_t res;
if (!hwloc_topology_is_thissystem(topology)) {
errno = EINVAL;
return -1;
}
pci.stype = ZE_STRUCTURE_TYPE_PCI_EXT_PROPERTIES;
pci.pNext = NULL;
res = zeDevicePciGetPropertiesExt(device, &pci);
if (res != ZE_RESULT_SUCCESS) {
errno = EINVAL;
return -1;
}
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/local_cpus",
pci.address.domain, pci.address.bus, pci.address.device, pci.address.function);
if (hwloc_linux_read_path_as_cpumask(path, set) < 0
|| hwloc_bitmap_iszero(set))
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
#else
/* Non-Linux systems simply get a full cpuset */
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
#endif
return 0;
}
/** \brief Get the CPU set of logical processors that are physically
* close to the Level Zero Sysman device \p device
*
* Store in \p set the CPU-set describing the locality of
* the Level Zero device \p device.
*
* Topology \p topology and device \p device must match the local machine.
* The Level Zero library must have been initialized with Sysman enabled
* (by calling zesInit(0) if supported,
* or by setting ZES_ENABLE_SYSMAN=1 in the environment).
* with zesInit().
* I/O devices detection and the Level Zero component are not needed in the
* topology.
*
@@ -61,15 +121,14 @@ extern "C" {
* \return -1 on error, for instance if device information could not be found.
*/
static __hwloc_inline int
hwloc_levelzero_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
ze_device_handle_t device, hwloc_cpuset_t set)
hwloc_levelzero_get_sysman_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
zes_device_handle_t device, hwloc_cpuset_t set)
{
#ifdef HWLOC_LINUX_SYS
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
#define HWLOC_LEVELZERO_DEVICE_SYSFS_PATH_MAX 128
char path[HWLOC_LEVELZERO_DEVICE_SYSFS_PATH_MAX];
zes_pci_properties_t pci;
zes_device_handle_t sdevice = device;
ze_result_t res;
if (!hwloc_topology_is_thissystem(topology)) {
@@ -77,7 +136,7 @@ hwloc_levelzero_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_un
return -1;
}
res = zesDevicePciGetProperties(sdevice, &pci);
res = zesDevicePciGetProperties(device, &pci);
if (res != ZE_RESULT_SUCCESS) {
errno = EINVAL;
return -1;
@@ -102,17 +161,90 @@ hwloc_levelzero_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_un
* \return \c NULL if none could be found.
*
* Topology \p topology and device \p dv_ind must match the local machine.
* The Level Zero library must have been initialized with zeInit().
* I/O devices detection and the Level Zero component must be enabled in the
* topology. If not, the locality of the object may still be found using
* hwloc_levelzero_get_device_cpuset().
*
* \note If the input ZE device is actually a subdevice, then its parent
* (root device) is actually translated, i.e. the main hwloc OS device
* is returned instead of one of its children.
*
* \note The corresponding hwloc PCI device may be found by looking
* at the result parent pointer (unless PCI devices are filtered out).
*
* \note zeDevicePciGetPropertiesExt() must be supported.
*/
static __hwloc_inline hwloc_obj_t
hwloc_levelzero_get_device_osdev(hwloc_topology_t topology, ze_device_handle_t device)
{
ze_pci_ext_properties_t pci;
ze_result_t res;
hwloc_obj_t osdev;
if (!hwloc_topology_is_thissystem(topology)) {
errno = EINVAL;
return NULL;
}
pci.stype = ZE_STRUCTURE_TYPE_PCI_EXT_PROPERTIES;
pci.pNext = NULL;
res = zeDevicePciGetPropertiesExt(device, &pci);
if (res != ZE_RESULT_SUCCESS) {
errno = EINVAL;
return NULL;
}
osdev = NULL;
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
hwloc_obj_t pcidev;
if (strncmp(osdev->name, "ze", 2))
continue;
pcidev = osdev;
while (pcidev && pcidev->type != HWLOC_OBJ_PCI_DEVICE)
pcidev = pcidev->parent;
if (!pcidev)
continue;
if (pcidev
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
&& pcidev->attr->pcidev.domain == pci.address.domain
&& pcidev->attr->pcidev.bus == pci.address.bus
&& pcidev->attr->pcidev.dev == pci.address.device
&& pcidev->attr->pcidev.func == pci.address.function)
return osdev;
/* FIXME: when we'll have serialnumber, try it in case PCI is filtered-out */
}
return NULL;
}
/** \brief Get the hwloc OS device object corresponding to Level Zero Sysman device
* \p device.
*
* \return The hwloc OS device object that describes the given Level Zero device \p device.
* \return \c NULL if none could be found.
*
* Topology \p topology and device \p dv_ind must match the local machine.
* The Level Zero library must have been initialized with Sysman enabled
* with zesInit().
* I/O devices detection and the Level Zero component must be enabled in the
* topology. If not, the locality of the object may still be found using
* hwloc_levelzero_get_device_cpuset().
*
* \note If the input ZES device is actually a subdevice, then its parent
* (root device) is actually translated, i.e. the main hwloc OS device
* is returned instead of one of its children.
*
* \note The corresponding hwloc PCI device may be found by looking
* at the result parent pointer (unless PCI devices are filtered out).
*/
static __hwloc_inline hwloc_obj_t
hwloc_levelzero_get_device_osdev(hwloc_topology_t topology, ze_device_handle_t device)
hwloc_levelzero_get_sysman_device_osdev(hwloc_topology_t topology, zes_device_handle_t device)
{
zes_device_handle_t sdevice = device;
zes_pci_properties_t pci;
ze_result_t res;
hwloc_obj_t osdev;
@@ -122,20 +254,25 @@ hwloc_levelzero_get_device_osdev(hwloc_topology_t topology, ze_device_handle_t d
return NULL;
}
res = zesDevicePciGetProperties(sdevice, &pci);
res = zesDevicePciGetProperties(device, &pci);
if (res != ZE_RESULT_SUCCESS) {
/* L0 was likely initialized without sysman, don't bother */
errno = EINVAL;
return NULL;
}
osdev = NULL;
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
hwloc_obj_t pcidev = osdev->parent;
hwloc_obj_t pcidev;
if (strncmp(osdev->name, "ze", 2))
continue;
pcidev = osdev;
while (pcidev && pcidev->type != HWLOC_OBJ_PCI_DEVICE)
pcidev = pcidev->parent;
if (!pcidev)
continue;
if (pcidev
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
&& pcidev->attr->pcidev.domain == pci.address.domain

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2019-2024 Inria. All rights reserved.
* Copyright © 2019-2025 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
@@ -58,6 +58,11 @@ extern "C" {
* an easy way to distinguish NUMA nodes of different kinds, as explained
* in \ref heteromem.
*
* Beside tiers, hwloc defines a set of "default" nodes where normal memory
* allocations should be made from (see hwloc_topology_get_default_nodeset()).
* This is also useful for dividing the machine into a set of non-overlapping
* NUMA domains, for instance for binding tasks per domain.
*
* \sa An example is available in doc/examples/memory-attributes.c in the source tree.
*
* \note The API also supports specific objects as initiator,
@@ -245,6 +250,16 @@ enum hwloc_local_numanode_flag_e {
*/
HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY = (1UL<<1),
/** \breif Select NUMA nodes whose locality intersects the given cpuset.
* This includes larger and smaller localities as well as localities
* that are partially included.
* For instance, if the locality is one core of both packages, a NUMA node
* local to one package is neither larger nor smaller than this locality,
* but it intersects it.
* \hideinitializer
*/
HWLOC_LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY = (1UL<<3),
/** \brief Select all NUMA nodes in the topology.
* The initiator \p initiator is ignored.
* \hideinitializer
@@ -290,7 +305,57 @@ hwloc_get_local_numanode_objs(hwloc_topology_t topology,
hwloc_obj_t *nodes,
unsigned long flags);
/** \brief Return the set of default NUMA nodes
*
* In machines with heterogeneous memory, some NUMA nodes are considered
* the default ones, i.e. where basic allocations should be made from.
* These are usually DRAM nodes.
*
* Other nodes may be reserved for specific use (I/O device memory, e.g. GPU memory),
* small but high performance (HBM), large but slow memory (NVM), etc.
* Buffers should usually not be allocated from there unless explicitly required.
*
* This function fills \p nodeset with the bits of NUMA nodes considered default.
*
* It is guaranteed that these nodes have non-intersecting CPU sets,
* i.e. cores may not have multiple local NUMA nodes anymore.
* Hence this may be used to iterate over the platform divided into separate
* NUMA localities, for instance for binding one task per NUMA domain.
*
* Any core that had some local NUMA node(s) in the initial topology should
* still have one in the default nodeset. Corner cases where this would be
* wrong consist in asymmetric platforms with missing DRAM nodes, or topologies
* that were already restricted to less NUMA nodes.
*
* The returned nodeset may be passed to hwloc_topology_restrict() with
* ::HWLOC_RESTRICT_FLAG_BYNODESET to remove all non-default nodes from
* the topology. The resulting topology will be easier to use when iterating
* over (now homogeneous) NUMA nodes.
*
* The heuristics for finding default nodes relies on memory tiers and subtypes
* (see \ref heteromem) as well as the assumption that hardware vendors list
* default nodes first in hardware tables.
*
* \p flags must be \c 0 for now.
*
* \return 0 on success.
* \return -1 on error.
*
* \note The returned nodeset usually contains all nodes from a single memory
* tier, likely the DRAM one.
*
* \note The returned nodeset is included in the list of available nodes
* returned by hwloc_topology_get_topology_nodeset(). It is strictly smaller
* if the machine has heterogeneous memory.
*
* \note The heuristics may return a suboptimal set of nodes if hwloc could
* not guess memory types and/or if some default nodes were removed earlier
* from the topology (e.g. with hwloc_topology_restrict()).
*/
HWLOC_DECLSPEC int
hwloc_topology_get_default_nodeset(hwloc_topology_t topology,
hwloc_nodeset_t nodeset,
unsigned long flags);
/** \brief Return an attribute value for a specific target NUMA node.
*

View File

@@ -26,7 +26,7 @@ struct hwloc_backend;
/** \defgroup hwlocality_disc_components Components and Plugins: Discovery components
/** \defgroup hwlocality_disc_components Components and Plugins: Discovery components and backends
*
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
*
@@ -90,18 +90,6 @@ struct hwloc_disc_component {
struct hwloc_disc_component * next;
};
/** @} */
/** \defgroup hwlocality_disc_backends Components and Plugins: Discovery backends
*
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
*
* @{
*/
/** \brief Discovery phase */
typedef enum hwloc_disc_phase_e {
/** \brief xml or synthetic, platform-specific components such as bgq.
@@ -313,6 +301,64 @@ struct hwloc_component {
void * data;
};
/** \brief Make sure that plugins can lookup core symbols.
*
* This is a sanity check to avoid lazy-lookup failures when libhwloc
* is loaded within a plugin, and later tries to load its own plugins.
* This may fail (and abort the program) if libhwloc symbols are in a
* private namespace.
*
* \return 0 on success.
* \return -1 if the plugin cannot be successfully loaded. The caller
* plugin init() callback should return a negative error code as well.
*
* Plugins should call this function in their init() callback to avoid
* later crashes if lazy symbol resolution is used by the upper layer that
* loaded hwloc (e.g. OpenCL implementations using dlopen with RTLD_LAZY).
*
* \note The build system must define HWLOC_INSIDE_PLUGIN if and only if
* building the caller as a plugin.
*
* \note This function should remain inline so plugins can call it even
* when they cannot find libhwloc symbols.
*/
static __hwloc_inline int
hwloc_plugin_check_namespace(const char *pluginname __hwloc_attribute_unused, const char *symbol __hwloc_attribute_unused)
{
#ifdef HWLOC_INSIDE_PLUGIN
void *sym;
#ifdef HWLOC_HAVE_LTDL
lt_dlhandle handle = lt_dlopen(NULL);
#else
void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
#endif
if (!handle)
/* cannot check, assume things will work */
return 0;
#ifdef HWLOC_HAVE_LTDL
sym = lt_dlsym(handle, symbol);
lt_dlclose(handle);
#else
sym = dlsym(handle, symbol);
dlclose(handle);
#endif
if (!sym) {
static int verboseenv_checked = 0;
static int verboseenv_value = 0;
if (!verboseenv_checked) {
const char *verboseenv = getenv("HWLOC_PLUGINS_VERBOSE");
verboseenv_value = verboseenv ? atoi(verboseenv) : 0;
verboseenv_checked = 1;
}
if (verboseenv_value)
fprintf(stderr, "Plugin `%s' disabling itself because it cannot find the `%s' core symbol.\n",
pluginname, symbol);
return -1;
}
#endif /* HWLOC_INSIDE_PLUGIN */
return 0;
}
/** @} */
@@ -422,64 +468,6 @@ HWLOC_DECLSPEC int hwloc_obj_add_children_sets(hwloc_obj_t obj);
*/
HWLOC_DECLSPEC int hwloc_topology_reconnect(hwloc_topology_t topology, unsigned long flags __hwloc_attribute_unused);
/** \brief Make sure that plugins can lookup core symbols.
*
* This is a sanity check to avoid lazy-lookup failures when libhwloc
* is loaded within a plugin, and later tries to load its own plugins.
* This may fail (and abort the program) if libhwloc symbols are in a
* private namespace.
*
* \return 0 on success.
* \return -1 if the plugin cannot be successfully loaded. The caller
* plugin init() callback should return a negative error code as well.
*
* Plugins should call this function in their init() callback to avoid
* later crashes if lazy symbol resolution is used by the upper layer that
* loaded hwloc (e.g. OpenCL implementations using dlopen with RTLD_LAZY).
*
* \note The build system must define HWLOC_INSIDE_PLUGIN if and only if
* building the caller as a plugin.
*
* \note This function should remain inline so plugins can call it even
* when they cannot find libhwloc symbols.
*/
static __hwloc_inline int
hwloc_plugin_check_namespace(const char *pluginname __hwloc_attribute_unused, const char *symbol __hwloc_attribute_unused)
{
#ifdef HWLOC_INSIDE_PLUGIN
void *sym;
#ifdef HWLOC_HAVE_LTDL
lt_dlhandle handle = lt_dlopen(NULL);
#else
void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
#endif
if (!handle)
/* cannot check, assume things will work */
return 0;
#ifdef HWLOC_HAVE_LTDL
sym = lt_dlsym(handle, symbol);
lt_dlclose(handle);
#else
sym = dlsym(handle, symbol);
dlclose(handle);
#endif
if (!sym) {
static int verboseenv_checked = 0;
static int verboseenv_value = 0;
if (!verboseenv_checked) {
const char *verboseenv = getenv("HWLOC_PLUGINS_VERBOSE");
verboseenv_value = verboseenv ? atoi(verboseenv) : 0;
verboseenv_checked = 1;
}
if (verboseenv_value)
fprintf(stderr, "Plugin `%s' disabling itself because it cannot find the `%s' core symbol.\n",
pluginname, symbol);
return -1;
}
#endif /* HWLOC_INSIDE_PLUGIN */
return 0;
}
/** @} */

View File

@@ -1,6 +1,6 @@
/*
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* Copyright © 2010-2024 Inria. All rights reserved.
* Copyright © 2010-2025 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
@@ -409,8 +409,10 @@ extern "C" {
#define hwloc_local_numanode_flag_e HWLOC_NAME(local_numanode_flag_e)
#define HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY HWLOC_NAME_CAPS(LOCAL_NUMANODE_FLAG_LARGER_LOCALITY)
#define HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY HWLOC_NAME_CAPS(LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY)
#define HWLOC_LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY HWLOC_NAME_CAPS(LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY)
#define HWLOC_LOCAL_NUMANODE_FLAG_ALL HWLOC_NAME_CAPS(LOCAL_NUMANODE_FLAG_ALL)
#define hwloc_get_local_numanode_objs HWLOC_NAME(get_local_numanode_objs)
#define hwloc_topology_get_default_nodeset HWLOC_NAME(topology_get_default_nodeset)
#define hwloc_memattr_get_name HWLOC_NAME(memattr_get_name)
#define hwloc_memattr_get_flags HWLOC_NAME(memattr_get_flags)
@@ -599,7 +601,9 @@ extern "C" {
/* levelzero.h */
#define hwloc_levelzero_get_device_cpuset HWLOC_NAME(levelzero_get_device_cpuset)
#define hwloc_levelzero_get_sysman_device_cpuset HWLOC_NAME(levelzero_get_sysman_device_cpuset)
#define hwloc_levelzero_get_device_osdev HWLOC_NAME(levelzero_get_device_osdev)
#define hwloc_levelzero_get_sysman_device_osdev HWLOC_NAME(levelzero_get_sysman_device_osdev)
/* gl.h */
@@ -813,6 +817,8 @@ extern "C" {
#define hwloc_topology_setup_defaults HWLOC_NAME(topology_setup_defaults)
#define hwloc_topology_clear HWLOC_NAME(topology_clear)
#define hwloc__reconnect HWLOC_NAME(_reconnect)
#define hwloc__attach_memory_object HWLOC_NAME(insert_memory_object)
#define hwloc_get_obj_by_type_and_gp_index HWLOC_NAME(get_obj_by_type_and_gp_index)

View File

@@ -1,6 +1,6 @@
/*
* Copyright © 2009, 2011, 2012 CNRS. All rights reserved.
* Copyright © 2009-2020 Inria. All rights reserved.
* Copyright © 2009-2021 Inria. All rights reserved.
* Copyright © 2009, 2011, 2012, 2015 Université Bordeaux. All rights reserved.
* Copyright © 2009-2020 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
@@ -17,10 +17,6 @@
#define HWLOC_HAVE_MSVC_CPUIDEX 1
/* #undef HAVE_MKSTEMP */
#define HWLOC_HAVE_X86_CPUID 1
/* Define to 1 if the system has the type `CACHE_DESCRIPTOR'. */
#define HAVE_CACHE_DESCRIPTOR 0
@@ -132,7 +128,8 @@
#define HAVE_DECL__SC_PAGE_SIZE 0
/* Define to 1 if you have the <dirent.h> header file. */
/* #undef HAVE_DIRENT_H */
/* #define HAVE_DIRENT_H 1 */
#undef HAVE_DIRENT_H
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
@@ -285,7 +282,7 @@
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strncasecmp' function. */
/* #undef HAVE_STRNCASECMP */
#define HAVE_STRNCASECMP 1
/* Define to '1' if sysctl is present and usable */
/* #undef HAVE_SYSCTL */
@@ -326,7 +323,8 @@
/* #undef HAVE_UNAME */
/* Define to 1 if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
/* #define HAVE_UNISTD_H 1 */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `uselocale' function. */
/* #undef HAVE_USELOCALE */
@@ -661,7 +659,7 @@
#define hwloc_pid_t HANDLE
/* Define this to either strncasecmp or strncmp */
/* #undef hwloc_strncasecmp */
#define hwloc_strncasecmp strncasecmp
/* Define this to the thread ID type */
#define hwloc_thread_t HANDLE

View File

@@ -186,7 +186,7 @@ hwloc_ffsl_from_ffs32(unsigned long x)
/**
* flsl helpers.
*/
#ifdef __GNUC_____
#ifdef __GNUC__
# if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))
# define hwloc_flsl(x) ((x) ? (8*sizeof(long) - __builtin_clzl(x)) : 0)

View File

@@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2023 Inria. All rights reserved.
* Copyright © 2009-2025 Inria. All rights reserved.
* Copyright © 2009-2012, 2020 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
*
@@ -302,6 +302,9 @@ extern void hwloc__reorder_children(hwloc_obj_t parent);
extern void hwloc_topology_setup_defaults(struct hwloc_topology *topology);
extern void hwloc_topology_clear(struct hwloc_topology *topology);
#define _HWLOC_RECONNECT_FLAG_KEEPSTRUCTURE (1UL<<0)
extern int hwloc__reconnect(struct hwloc_topology *topology, unsigned long flags);
/* insert memory object as memory child of normal parent */
extern struct hwloc_obj * hwloc__attach_memory_object(struct hwloc_topology *topology, hwloc_obj_t parent,
hwloc_obj_t obj, const char *reason);

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2010-2024 Inria. All rights reserved.
* Copyright © 2010-2025 Inria. All rights reserved.
* Copyright © 2011-2012 Université Bordeaux
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@@ -699,7 +699,7 @@ hwloc_distances_add_commit(hwloc_topology_t topology,
}
/* in case we added some groups, see if we need to reconnect */
hwloc_topology_reconnect(topology, 0);
hwloc__reconnect(topology, 0);
return 0;
@@ -1387,19 +1387,12 @@ static __hwloc_inline int is_nvswitch(hwloc_obj_t obj)
}
static int
hwloc__distances_transform_merge_switch_ports(hwloc_topology_t topology,
struct hwloc_distances_s *distances)
hwloc__distances_transform_merge_switch_ports(struct hwloc_distances_s *distances)
{
struct hwloc_internal_distances_s *dist = hwloc__internal_distances_from_public(topology, distances);
hwloc_obj_t *objs = distances->objs;
hwloc_uint64_t *values = distances->values;
unsigned first, i, j, nbobjs = distances->nbobjs;
if (strcmp(dist->name, "NVLinkBandwidth")) {
errno = EINVAL;
return -1;
}
/* find the first port */
first = (unsigned) -1;
for(i=0; i<nbobjs; i++)
@@ -1435,20 +1428,13 @@ hwloc__distances_transform_merge_switch_ports(hwloc_topology_t topology,
}
static int
hwloc__distances_transform_transitive_closure(hwloc_topology_t topology,
struct hwloc_distances_s *distances)
hwloc__distances_transform_transitive_closure(struct hwloc_distances_s *distances)
{
struct hwloc_internal_distances_s *dist = hwloc__internal_distances_from_public(topology, distances);
hwloc_obj_t *objs = distances->objs;
hwloc_uint64_t *values = distances->values;
unsigned nbobjs = distances->nbobjs;
unsigned i, j, k;
if (strcmp(dist->name, "NVLinkBandwidth")) {
errno = EINVAL;
return -1;
}
for(i=0; i<nbobjs; i++) {
hwloc_uint64_t bw_i2sw = 0;
if (is_nvswitch(objs[i]))
@@ -1467,8 +1453,8 @@ hwloc__distances_transform_transitive_closure(hwloc_topology_t topology,
if (is_nvswitch(objs[k]))
bw_sw2j += values[k*nbobjs+j];
/* bandwidth from i to j is now min(i2sw,sw2j) */
values[i*nbobjs+j] = bw_i2sw > bw_sw2j ? bw_sw2j : bw_i2sw;
/* bandwidth from i to j now gets indirect bandwidth too, min(i2sw,sw2j) */
values[i*nbobjs+j] += bw_i2sw > bw_sw2j ? bw_sw2j : bw_i2sw;
}
}
@@ -1476,7 +1462,7 @@ hwloc__distances_transform_transitive_closure(hwloc_topology_t topology,
}
int
hwloc_distances_transform(hwloc_topology_t topology,
hwloc_distances_transform(hwloc_topology_t topology __hwloc_attribute_unused,
struct hwloc_distances_s *distances,
enum hwloc_distances_transform_e transform,
void *transform_attr,
@@ -1495,13 +1481,13 @@ hwloc_distances_transform(hwloc_topology_t topology,
case HWLOC_DISTANCES_TRANSFORM_MERGE_SWITCH_PORTS:
{
int err;
err = hwloc__distances_transform_merge_switch_ports(topology, distances);
err = hwloc__distances_transform_merge_switch_ports(distances);
if (!err)
err = hwloc__distances_transform_remove_null(distances);
return err;
}
case HWLOC_DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE:
return hwloc__distances_transform_transitive_closure(topology, distances);
return hwloc__distances_transform_transitive_closure(distances);
default:
errno = EINVAL;
return -1;

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2020-2024 Inria. All rights reserved.
* Copyright © 2020-2025 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
@@ -1158,6 +1158,8 @@ match_local_obj_cpuset(hwloc_obj_t node, hwloc_cpuset_t cpuset, unsigned long fl
{
if (flags & HWLOC_LOCAL_NUMANODE_FLAG_ALL)
return 1;
if (flags & HWLOC_LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY)
return hwloc_bitmap_intersects(node->cpuset, cpuset);
if ((flags & HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY)
&& hwloc_bitmap_isincluded(cpuset, node->cpuset))
return 1;
@@ -1180,6 +1182,7 @@ hwloc_get_local_numanode_objs(hwloc_topology_t topology,
if (flags & ~(HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY
|HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY
|HWLOC_LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY
| HWLOC_LOCAL_NUMANODE_FLAG_ALL)) {
errno = EINVAL;
return -1;
@@ -1226,6 +1229,93 @@ hwloc_get_local_numanode_objs(hwloc_topology_t topology,
return 0;
}
static int compare_nodes_by_os_index(const void *_a, const void *_b)
{
const hwloc_obj_t * a = _a, * b = _b;
return (*a)->os_index - (*b)->os_index;
}
int
hwloc_topology_get_default_nodeset(hwloc_topology_t topology,
hwloc_nodeset_t nodeset,
unsigned long flags)
{
hwloc_obj_t *nodes;
hwloc_bitmap_t remainingcpuset;
unsigned nrnodes, i;
const char *first_subtype;
if (flags) {
errno = EINVAL;
goto out;
}
remainingcpuset = hwloc_bitmap_dup(topology->levels[0][0]->cpuset);
if (!remainingcpuset)
goto out;
nrnodes = topology->slevels[HWLOC_SLEVEL_NUMANODE].nbobjs;
nodes = malloc(nrnodes * sizeof(*nodes));
if (!nodes)
goto out_with_remainingcpuset;
memcpy(nodes, topology->slevels[HWLOC_SLEVEL_NUMANODE].objs, nrnodes * sizeof(*nodes));
qsort(nodes, nrnodes, sizeof(*nodes), compare_nodes_by_os_index);
hwloc_bitmap_zero(nodeset);
/* always take the first node (FIXME: except if unexpected subtype?) */
first_subtype = nodes[0]->subtype;
hwloc_bitmap_set(nodeset, nodes[0]->os_index);
hwloc_bitmap_andnot(remainingcpuset, remainingcpuset, nodes[0]->cpuset);
/* use all non-intersecting nodes with same subtype */
for(i=1; i<nrnodes; i++) {
/* check same or no subtype */
if (first_subtype) {
if (!nodes[i]->subtype || strcmp(first_subtype, nodes[i]->subtype))
continue;
} else if (nodes[i]->subtype) {
continue;
}
/* take non-overlapping nodes */
if (hwloc_bitmap_isincluded(nodes[i]->cpuset, remainingcpuset) /* can be empty */) {
hwloc_bitmap_set(nodeset, nodes[i]->os_index);
hwloc_bitmap_andnot(remainingcpuset, remainingcpuset, nodes[i]->cpuset);
}
/* more needed? */
if (hwloc_bitmap_iszero(remainingcpuset))
goto done;
}
/* find more nodes to cover the entire topology cpuset.
* only take what's necessary: first nodes, non-empty */
for(i=1; i<nrnodes; i++) {
/* already taken? */
if (hwloc_bitmap_isset(nodeset, i))
continue;
/* take non-overlapping nodes, except empty */
if (hwloc_bitmap_isincluded(nodes[i]->cpuset, remainingcpuset)
&& !hwloc_bitmap_iszero(nodes[i]->cpuset)) {
hwloc_bitmap_set(nodeset, nodes[i]->os_index);
hwloc_bitmap_andnot(remainingcpuset, remainingcpuset, nodes[i]->cpuset);
}
/* more needed? */
if (hwloc_bitmap_iszero(remainingcpuset))
goto done;
}
done:
free(nodes);
hwloc_bitmap_free(remainingcpuset);
return 0;
out_with_remainingcpuset:
hwloc_bitmap_free(remainingcpuset);
out:
return -1;
}
/**************************************
* Using memattrs to identify HBM/DRAM
@@ -1433,10 +1523,15 @@ hwloc__group_memory_tiers(hwloc_topology_t topology,
}
}
/* Sort nodes.
* We could also sort by the existing subtype.
* KNL is the only case where subtypes are set in backends, but we set memattrs as well there.
* Also HWLOC_MEMTIERS_REFRESH would be a special value to ignore existing subtypes.
/* Sort nodes by tier type and bandwidth.
*
* We could also use the existing subtype but it's not clear it'd be better.
* For NVIDIA GPU, "GPUMemory" is set in the Linux backend, and used above to set tier type anyway.
* For KNL, the Linux backend sets subtypes and memattrs, sorting by memattrs already works fine.
* Existing subtypes could have been imported from XML, usually mostly OK except maybe SPM (fallback for I don't know)?
* An envvar (or HWLOC_MEMTIERS_REFRESH special value?) could be passed to ignore existing subtypes,
* but "GPUMemory" wouldn't be available anymore, we'd have to use something else like "PCIBusId",
* but that one might not always be specific to GPU-backed NUMA nodes?
*/
hwloc_debug("Sorting memory node infos...\n");
qsort(nodeinfos, n, sizeof(*nodeinfos), compare_node_infos_by_type_and_bw);

View File

@@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2025 Inria. All rights reserved.
* Copyright © 2009-2012, 2020 Université Bordeaux
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@@ -56,6 +56,9 @@ typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
RelationCache,
RelationProcessorPackage,
RelationGroup,
RelationProcessorDie,
RelationNumaNodeEx, /* only used to *request* extended numa info only, but included in RelationAll, never returned on output */
RelationProcessorModule,
RelationAll = 0xffff
} LOGICAL_PROCESSOR_RELATIONSHIP;
#else /* HAVE_LOGICAL_PROCESSOR_RELATIONSHIP */
@@ -64,6 +67,11 @@ typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
# define RelationGroup 4
# define RelationAll 0xffff
# endif /* HAVE_RELATIONPROCESSORPACKAGE */
# ifndef HAVE_RELATIONPROCESSORDIE
# define RelationProcessorDie 5
# define RelationNumaNodeEx 6
# define RelationProcessorModule 7
# endif
#endif /* HAVE_LOGICAL_PROCESSOR_RELATIONSHIP */
#ifndef HAVE_GROUP_AFFINITY
@@ -366,7 +374,7 @@ hwloc_win_get_processor_groups(void)
hwloc_debug("found %lu windows processor groups\n", nr_processor_groups);
if (nr_processor_groups > 1 && SIZEOF_VOID_P == 4) {
if (HWLOC_SHOW_ALL_ERRORS())
if (HWLOC_SHOW_CRITICAL_ERRORS())
fprintf(stderr, "hwloc/windows: multiple processor groups found on 32bits Windows, topology may be invalid/incomplete.\n");
}
@@ -1068,6 +1076,7 @@ hwloc_look_windows(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
id = HWLOC_UNKNOWN_INDEX;
switch (procInfo->Relationship) {
case RelationNumaNodeEx: /* only used on input anyway */
case RelationNumaNode:
type = HWLOC_OBJ_NUMANODE;
/* Starting with Windows 11 and Server 2022, the GroupCount field is valid and >=1
@@ -1090,6 +1099,16 @@ hwloc_look_windows(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
num = procInfo->Processor.GroupCount;
GroupMask = procInfo->Processor.GroupMask;
break;
case RelationProcessorDie:
type = HWLOC_OBJ_DIE;
num = procInfo->Processor.GroupCount;
GroupMask = procInfo->Processor.GroupMask;
break;
case RelationProcessorModule:
type = HWLOC_OBJ_GROUP;
num = procInfo->Processor.GroupCount;
GroupMask = procInfo->Processor.GroupMask;
break;
case RelationCache:
type = (procInfo->Cache.Type == CacheInstruction ? HWLOC_OBJ_L1ICACHE : HWLOC_OBJ_L1CACHE) + procInfo->Cache.Level - 1;
/* GroupCount added approximately with NumaNode.GroupCount above */
@@ -1211,6 +1230,19 @@ hwloc_look_windows(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
continue;
}
break;
case HWLOC_OBJ_GROUP:
switch (procInfo->Relationship) {
case RelationGroup:
obj->attr->group.kind = HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP;
break;
case RelationProcessorModule:
obj->attr->group.kind = HWLOC_GROUP_KIND_INTEL_MODULE;
obj->subtype = strdup("Module");
break;
default:
obj->attr->group.kind = HWLOC_GROUP_KIND_WINDOWS_RELATIONSHIP_UNKNOWN;
}
break;
default:
break;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2010-2024 Inria. All rights reserved.
* Copyright © 2010-2025 Inria. All rights reserved.
* Copyright © 2010-2013 Université Bordeaux
* Copyright © 2010-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@@ -653,7 +653,13 @@ static void look_proc(struct hwloc_backend *backend, struct procinfo *infos, uns
cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump);
infos->apicid = ebx >> 24;
if (edx & (1 << 28)) {
legacy_max_log_proc = 1 << hwloc_flsl(((ebx >> 16) & 0xff) - 1);
unsigned ebx_16_23 = (ebx >> 16) & 0xff;
if (ebx_16_23) {
legacy_max_log_proc = 1 << hwloc_flsl(ebx_16_23 - 1);
} else {
hwloc_debug("HTT bit set in CPUID 0x01.edx, but legacy_max_proc = 0 in ebx, assuming legacy_max_log_proc = 1\n");
legacy_max_log_proc = 1;
}
} else {
hwloc_debug("HTT bit not set in CPUID 0x01.edx, assuming legacy_max_log_proc = 1\n");
legacy_max_log_proc = 1;
@@ -1742,7 +1748,7 @@ hwloc_x86_discover(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
if (topology->levels[0][0]->cpuset) {
/* somebody else discovered things, reconnect levels so that we can look at them */
hwloc_topology_reconnect(topology, 0);
hwloc__reconnect(topology, 0);
if (topology->nb_levels == 2 && topology->level_nbobjects[1] == data->nbprocs) {
/* only PUs were discovered, as much as we would, complete the topology with everything else */
alreadypus = 1;

View File

@@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2025 Inria. All rights reserved.
* Copyright © 2009-2011, 2020 Université Bordeaux
* Copyright © 2009-2018 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@@ -415,6 +415,20 @@ hwloc__xml_import_object_attr(struct hwloc_topology *topology,
}
}
else if (!strcmp(name, "numanode_type")) {
switch (obj->type) {
case HWLOC_OBJ_NUMANODE: {
/* ignored for now, here for possible forward compat */
break;
}
default:
if (hwloc__xml_verbose())
fprintf(stderr, "%s: ignoring numanode_type attribute for non-NUMA object\n",
state->global->msgprefix);
break;
}
}
else if (data->version_major < 2) {
/************************
* deprecated from 1.x
@@ -876,14 +890,19 @@ hwloc__xml_import_object(hwloc_topology_t topology,
/* deal with possible future type */
obj->type = HWLOC_OBJ_GROUP;
obj->attr->group.kind = HWLOC_GROUP_KIND_LINUX_CLUSTER;
} else if (!strcasecmp(attrvalue, "MemCache")) {
}
#if 0
/* reenable if there's ever a future type that should be ignored without being an error */
else if (!strcasecmp(attrvalue, "MemCache")) {
/* ignore possible future type */
obj->type = _HWLOC_OBJ_FUTURE;
ignored = 1;
if (hwloc__xml_verbose())
fprintf(stderr, "%s: %s object not-supported, will be ignored\n",
state->global->msgprefix, attrvalue);
} else {
}
#endif
else {
if (hwloc__xml_verbose())
fprintf(stderr, "%s: unrecognized object type string %s\n",
state->global->msgprefix, attrvalue);
@@ -958,22 +977,22 @@ hwloc__xml_import_object(hwloc_topology_t topology,
if (hwloc__obj_type_is_normal(obj->type)) {
if (!hwloc__obj_type_is_normal(parent->type)) {
if (hwloc__xml_verbose())
fprintf(stderr, "normal object %s cannot be child of non-normal parent %s\n",
hwloc_obj_type_string(obj->type), hwloc_obj_type_string(parent->type));
fprintf(stderr, "%s: normal object %s cannot be child of non-normal parent %s\n",
state->global->msgprefix, hwloc_obj_type_string(obj->type), hwloc_obj_type_string(parent->type));
goto error_with_object;
}
} else if (hwloc__obj_type_is_memory(obj->type)) {
if (hwloc__obj_type_is_io(parent->type) || HWLOC_OBJ_MISC == parent->type) {
if (hwloc__xml_verbose())
fprintf(stderr, "Memory object %s cannot be child of non-normal-or-memory parent %s\n",
hwloc_obj_type_string(obj->type), hwloc_obj_type_string(parent->type));
fprintf(stderr, "%s: Memory object %s cannot be child of non-normal-or-memory parent %s\n",
state->global->msgprefix, hwloc_obj_type_string(obj->type), hwloc_obj_type_string(parent->type));
goto error_with_object;
}
} else if (hwloc__obj_type_is_io(obj->type)) {
if (hwloc__obj_type_is_memory(parent->type) || HWLOC_OBJ_MISC == parent->type) {
if (hwloc__xml_verbose())
fprintf(stderr, "I/O object %s cannot be child of non-normal-or-I/O parent %s\n",
hwloc_obj_type_string(obj->type), hwloc_obj_type_string(parent->type));
fprintf(stderr, "%s: I/O object %s cannot be child of non-normal-or-I/O parent %s\n",
state->global->msgprefix, hwloc_obj_type_string(obj->type), hwloc_obj_type_string(parent->type));
goto error_with_object;
}
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2023 Inria. All rights reserved.
* Copyright © 2009-2025 Inria. All rights reserved.
* Copyright © 2009-2012, 2020 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* Copyright © 2022 IBM Corporation. All rights reserved.
@@ -54,56 +54,6 @@
#endif
#ifdef HWLOC_HAVE_LEVELZERO
/*
* Define ZES_ENABLE_SYSMAN=1 early so that the LevelZero backend gets Sysman enabled.
*
* Only if the levelzero was enabled in this build so that we don't enable sysman
* for external levelzero users when hwloc doesn't need it. If somebody ever loads
* an external levelzero plugin in a hwloc library built without levelzero (unlikely),
* he may have to manually set ZES_ENABLE_SYSMAN=1.
*
* Use the constructor if supported and/or the Windows DllMain callback.
* Do it in the main hwloc library instead of the levelzero component because
* the latter could be loaded later as a plugin.
*
* L0 seems to be using getenv() to check this variable on Windows
* (at least in the Intel Compute-Runtime of March 2021),
* but setenv() doesn't seem to exist on Windows, hence use putenv() to set the variable.
*
* For the record, Get/SetEnvironmentVariable() is not exactly the same as getenv/putenv():
* - getenv() doesn't see what was set with SetEnvironmentVariable()
* - GetEnvironmentVariable() doesn't see putenv() in cygwin (while it does in MSVC and MinGW).
* Hence, if L0 ever switches from getenv() to GetEnvironmentVariable(),
* it will break in cygwin, we'll have to use both putenv() and SetEnvironmentVariable().
* Hopefully L0 will provide a way to enable Sysman without env vars before it happens.
*/
#if HWLOC_HAVE_ATTRIBUTE_CONSTRUCTOR
static void hwloc_constructor(void) __attribute__((constructor));
static void hwloc_constructor(void)
{
if (!getenv("ZES_ENABLE_SYSMAN"))
#ifdef HWLOC_WIN_SYS
putenv("ZES_ENABLE_SYSMAN=1");
#else
setenv("ZES_ENABLE_SYSMAN", "1", 1);
#endif
}
#endif
#ifdef HWLOC_WIN_SYS
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH) {
if (!getenv("ZES_ENABLE_SYSMAN"))
/* Windows does not have a setenv, so use putenv. */
putenv((char *) "ZES_ENABLE_SYSMAN=1");
}
return TRUE;
}
#endif
#endif /* HWLOC_HAVE_LEVELZERO */
unsigned hwloc_get_api_version(void)
{
return HWLOC_API_VERSION;
@@ -179,7 +129,7 @@ static void report_insert_error(hwloc_obj_t new, hwloc_obj_t old, const char *ms
report_insert_error_format_obj(oldstr, sizeof(oldstr), old);
fprintf(stderr, "****************************************************************************\n");
fprintf(stderr, "* hwloc %s received invalid information from the operating system.\n", HWLOC_VERSION);
fprintf(stderr, "* hwloc %s received invalid information.\n", HWLOC_VERSION);
fprintf(stderr, "*\n");
fprintf(stderr, "* Failed with error: %s\n", msg);
fprintf(stderr, "* while inserting %s\n", newstr);
@@ -1966,6 +1916,51 @@ static void hwloc_set_group_depth(hwloc_topology_t topology);
static void hwloc_connect_children(hwloc_obj_t parent);
static int hwloc_connect_levels(hwloc_topology_t topology);
static int hwloc_connect_special_levels(hwloc_topology_t topology);
static int hwloc_filter_levels_keep_structure(hwloc_topology_t topology);
/* reconnect children and levels,
* and optionnally merged identical levels while keeping structure.
*/
int
hwloc__reconnect(struct hwloc_topology *topology, unsigned long flags)
{
int merged_levels = 0;
if (topology->modified) {
hwloc_connect_children(topology->levels[0][0]);
if (hwloc_connect_levels(topology) < 0)
return -1;
}
if (flags & _HWLOC_RECONNECT_FLAG_KEEPSTRUCTURE) {
merged_levels = hwloc_filter_levels_keep_structure(topology);
/* If > 0, we merged some levels,
* some child+parent special children list may have been merged,
* hence specials level might need reordering,
* So reconnect special levels only here at the end.
*/
}
if (topology->modified || merged_levels) {
if (hwloc_connect_special_levels(topology) < 0)
return -1;
}
topology->modified = 0;
return 0;
}
int
hwloc_topology_reconnect(struct hwloc_topology *topology, unsigned long flags)
{
if (flags) {
errno = EINVAL;
return -1;
}
return hwloc__reconnect(topology, 0);
}
hwloc_obj_t
hwloc_topology_insert_group_object(struct hwloc_topology *topology, hwloc_obj_t obj)
@@ -2058,7 +2053,10 @@ hwloc_topology_insert_group_object(struct hwloc_topology *topology, hwloc_obj_t
/* properly inserted */
hwloc_obj_add_children_sets(res);
if (hwloc_topology_reconnect(topology, 0) < 0)
/* reconnect levels.
* no need to filter levels keep_structure because groups are either auto-merged
* or have the dont_merge attribute */
if (hwloc__reconnect(topology, 0) < 0)
return NULL;
/* Compute group total_memory. */
@@ -2550,26 +2548,13 @@ hwloc_compare_levels_structure(hwloc_topology_t topology, unsigned i)
return 0;
}
/* return > 0 if any level was removed.
* performs its own reconnect internally if needed
*/
/* return > 0 if any level was removed. */
static int
hwloc_filter_levels_keep_structure(hwloc_topology_t topology)
{
unsigned i, j;
int res = 0;
if (topology->modified) {
/* WARNING: hwloc_topology_reconnect() is duplicated partially here
* and at the end of this function:
* - we need normal levels before merging.
* - and we'll need to update special levels after merging.
*/
hwloc_connect_children(topology->levels[0][0]);
if (hwloc_connect_levels(topology) < 0)
return -1;
}
/* start from the bottom since we'll remove intermediate levels */
for(i=topology->nb_levels-1; i>0; i--) {
int replacechild = 0, replaceparent = 0;
@@ -2591,9 +2576,15 @@ hwloc_filter_levels_keep_structure(hwloc_topology_t topology)
if (type1 == HWLOC_OBJ_GROUP && hwloc_dont_merge_group_level(topology, i))
replacechild = 0;
}
if (!replacechild && !replaceparent)
if (!replacechild && !replaceparent) {
/* always merge Die into Package when levels are identical */
if (type1 == HWLOC_OBJ_PACKAGE && type2 == HWLOC_OBJ_DIE)
replacechild = 1;
}
if (!replacechild && !replaceparent) {
/* no ignoring */
continue;
}
/* Decide which one to actually replace */
if (replaceparent && replacechild) {
/* If both may be replaced, look at obj_type_priority */
@@ -2736,20 +2727,6 @@ hwloc_filter_levels_keep_structure(hwloc_topology_t topology)
}
}
if (res > 0 || topology-> modified) {
/* WARNING: hwloc_topology_reconnect() is duplicated partially here
* and at the beginning of this function.
* If we merged some levels, some child+parent special children lisst
* may have been merged, hence specials level might need reordering,
* So reconnect special levels only here at the end
* (it's not needed at the beginning of this function).
*/
if (hwloc_connect_special_levels(topology) < 0)
return -1;
topology->modified = 0;
}
return 0;
}
@@ -3278,33 +3255,6 @@ hwloc_connect_levels(hwloc_topology_t topology)
return 0;
}
int
hwloc_topology_reconnect(struct hwloc_topology *topology, unsigned long flags)
{
/* WARNING: when updating this function, the replicated code must
* also be updated inside hwloc_filter_levels_keep_structure()
*/
if (flags) {
errno = EINVAL;
return -1;
}
if (!topology->modified)
return 0;
hwloc_connect_children(topology->levels[0][0]);
if (hwloc_connect_levels(topology) < 0)
return -1;
if (hwloc_connect_special_levels(topology) < 0)
return -1;
topology->modified = 0;
return 0;
}
/* for regression testing, make sure the order of io devices
* doesn't change with the dentry order in the filesystem
*
@@ -3561,32 +3511,13 @@ hwloc_discover(struct hwloc_topology *topology,
hwloc_debug_print_objects(0, topology->levels[0][0]);
}
/* see if we should ignore the root now that we know how many children it has */
if (!hwloc_filter_check_keep_object(topology, topology->levels[0][0])
&& topology->levels[0][0]->first_child && !topology->levels[0][0]->first_child->next_sibling) {
hwloc_obj_t oldroot = topology->levels[0][0];
hwloc_obj_t newroot = oldroot->first_child;
/* switch to the new root */
newroot->parent = NULL;
topology->levels[0][0] = newroot;
/* move oldroot memory/io/misc children before newroot children */
if (oldroot->memory_first_child)
prepend_siblings_list(&newroot->memory_first_child, oldroot->memory_first_child, newroot);
if (oldroot->io_first_child)
prepend_siblings_list(&newroot->io_first_child, oldroot->io_first_child, newroot);
if (oldroot->misc_first_child)
prepend_siblings_list(&newroot->misc_first_child, oldroot->misc_first_child, newroot);
/* destroy oldroot and use the new one */
hwloc_free_unlinked_object(oldroot);
}
/*
* All object cpusets and nodesets are properly set now.
*/
/* Now connect handy pointers to make remaining discovery easier. */
hwloc_debug("%s", "\nOk, finished tweaking, now connect\n");
if (hwloc_topology_reconnect(topology, 0) < 0)
if (hwloc__reconnect(topology, 0) < 0)
return -1;
hwloc_debug_print_objects(0, topology->levels[0][0]);
@@ -3642,12 +3573,12 @@ hwloc_discover(struct hwloc_topology *topology,
}
hwloc_debug_print_objects(0, topology->levels[0][0]);
/* reconnect all (new groups might have appears, IO added, etc),
* and (now that everything was added) remove identical levels while keeping structure
*/
hwloc_debug("%s", "\nRemoving levels with HWLOC_TYPE_FILTER_KEEP_STRUCTURE\n");
if (hwloc_filter_levels_keep_structure(topology) < 0)
if (hwloc__reconnect(topology, _HWLOC_RECONNECT_FLAG_KEEPSTRUCTURE) < 0)
return -1;
/* takes care of reconnecting children/levels internally,
* because it needs normal levels.
* and it's often needed below because of Groups inserted for I/Os anyway */
hwloc_debug_print_objects(0, topology->levels[0][0]);
/* accumulate children memory in total_memory fields (only once parent is set) */
@@ -4494,7 +4425,7 @@ hwloc_topology_restrict(struct hwloc_topology *topology, hwloc_const_bitmap_t se
hwloc_bitmap_free(droppedcpuset);
hwloc_bitmap_free(droppednodeset);
if (hwloc_filter_levels_keep_structure(topology) < 0) /* takes care of reconnecting internally */
if (hwloc__reconnect(topology, _HWLOC_RECONNECT_FLAG_KEEPSTRUCTURE) < 0)
goto out;
/* some objects may have disappeared and sets were modified,
@@ -5116,6 +5047,8 @@ hwloc_topology_check(struct hwloc_topology *topology)
unsigned i;
int j, depth;
assert(!topology->modified);
/* make sure we can use ranges to check types */
/* hwloc__obj_type_is_{,d,i}cache() want cache types to be ordered like this */

View File

@@ -18,10 +18,15 @@
#include "backend/cpu/platform/BasicCpuInfo.h"
#include <Windows.h>
void xmrig::BasicCpuInfo::init_arm()
{
# if __ARM_FEATURE_CRYPTO
m_flags.set(FLAG_AES, true); // FIXME
# endif
DWORD size = sizeof(m_brand) - 1;
const char *subkey = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
RegGetValueA(HKEY_LOCAL_MACHINE, subkey, "ProcessorNameString", RRF_RT_REG_SZ, nullptr, m_brand, &size);
m_flags.set(FLAG_AES, IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE));
}

View File

@@ -311,17 +311,17 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith
uint32_t intensity = algorithm.maxIntensity() == 1 ? 0 : 1;
if (cache->attr->cache.depth == 3) {
for (size_t i = 0; i < cache->arity; ++i) {
hwloc_obj_t l2 = cache->children[i];
auto process_L2 = [&L2, &L2_associativity, L3_exclusive, this, &extra, scratchpad](hwloc_obj_t l2) {
if (!hwloc_obj_type_is_cache(l2->type) || l2->attr == nullptr) {
continue;
return;
}
L2 += l2->attr->cache.size;
L2_associativity = l2->attr->cache.associativity;
if (L3_exclusive) {
if (vendor() == VENDOR_AMD) {
if ((vendor() == VENDOR_AMD) && ((arch() == ARCH_ZEN4) || (arch() == ARCH_ZEN5))) {
// Use extra L2 only on newer CPUs because older CPUs (Zen 3 and older) don't benefit from it.
// For some reason, AMD CPUs can use only half of the exclusive L2/L3 cache combo efficiently
extra += std::min<size_t>(l2->attr->cache.size / 2, scratchpad);
}
@@ -329,6 +329,18 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith
extra += scratchpad;
}
}
};
for (size_t i = 0; i < cache->arity; ++i) {
hwloc_obj_t ch = cache->children[i];
if (ch->type == HWLOC_OBJ_GROUP) {
for (size_t j = 0; j < ch->arity; ++j) {
process_L2(ch->children[j]);
}
}
else {
process_L2(ch);
}
}
}

View File

@@ -1,7 +1,7 @@
/* XMRig
* Copyright (c) 2018 Riku Voipio <riku.voipio@iki.fi>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 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
@@ -98,8 +98,11 @@ static const id_part arm_part[] = {
{ 0xd0e, "Cortex-A76AE" },
{ 0xd13, "Cortex-R52" },
{ 0xd15, "Cortex-R82" },
{ 0xd16, "Cortex-R52+" },
{ 0xd20, "Cortex-M23" },
{ 0xd21, "Cortex-M33" },
{ 0xd22, "Cortex-M55" },
{ 0xd23, "Cortex-M85" },
{ 0xd40, "Neoverse-V1" },
{ 0xd41, "Cortex-A78" },
{ 0xd42, "Cortex-A78AE" },
@@ -115,6 +118,17 @@ static const id_part arm_part[] = {
{ 0xd4d, "Cortex-A715" },
{ 0xd4e, "Cortex-X3" },
{ 0xd4f, "Neoverse-V2" },
{ 0xd80, "Cortex-A520" },
{ 0xd81, "Cortex-A720" },
{ 0xd82, "Cortex-X4" },
{ 0xd83, "Neoverse-V3AE" },
{ 0xd84, "Neoverse-V3" },
{ 0xd85, "Cortex-X925" },
{ 0xd87, "Cortex-A725" },
{ 0xd88, "Cortex-A520AE" },
{ 0xd89, "Cortex-A720AE" },
{ 0xd8e, "Neoverse-N3" },
{ 0xd8f, "Cortex-A320" },
{ -1, nullptr }
};
@@ -154,6 +168,7 @@ static const id_part apm_part[] = {
};
static const id_part qcom_part[] = {
{ 0x001, "Oryon" },
{ 0x00f, "Scorpion" },
{ 0x02d, "Scorpion" },
{ 0x04d, "Krait" },
@@ -194,6 +209,22 @@ static const id_part marvell_part[] = {
{ -1, nullptr }
};
static const id_part apple_part[] = {
{ 0x022, "M1" },
{ 0x023, "M1" },
{ 0x024, "M1-Pro" },
{ 0x025, "M1-Pro" },
{ 0x028, "M1-Max" },
{ 0x029, "M1-Max" },
{ 0x032, "M2" },
{ 0x033, "M2" },
{ 0x034, "M2-Pro" },
{ 0x035, "M2-Pro" },
{ 0x038, "M2-Max" },
{ 0x039, "M2-Max" },
{ -1, nullptr }
};
static const id_part faraday_part[] = {
{ 0x526, "FA526" },
{ 0x626, "FA626" },
@@ -227,47 +258,40 @@ static const id_part intel_part[] = {
static const struct id_part fujitsu_part[] = {
{ 0x001, "A64FX" },
{ 0x003, "MONAKA" },
{ -1, nullptr }
};
static const id_part hisi_part[] = {
{ 0xd01, "Kunpeng-920" }, /* aka tsv110 */
{ 0xd01, "TaiShan-v110" }, /* used in Kunpeng-920 SoC */
{ 0xd02, "TaiShan-v120" }, /* used in Kirin 990A and 9000S SoCs */
{ 0xd40, "Cortex-A76" }, /* HiSilicon uses this ID though advertises A76 */
{ 0xd41, "Cortex-A77" }, /* HiSilicon uses this ID though advertises A77 */
{ -1, nullptr }
};
static const id_part apple_part[] = {
{ 0x022, "M1" },
{ 0x023, "M1" },
{ 0x024, "M1-Pro" },
{ 0x025, "M1-Pro" },
{ 0x028, "M1-Max" },
{ 0x029, "M1-Max" },
{ 0x032, "M2" },
{ 0x033, "M2" },
{ 0x034, "M2-Pro" },
{ 0x035, "M2-Pro" },
{ 0x038, "M2-Max" },
{ 0x039, "M2-Max" },
{ -1, nullptr }
};
static const struct id_part ft_part[] = {
{ 0x660, "FTC660" },
{ 0x661, "FTC661" },
{ 0x662, "FTC662" },
{ 0x663, "FTC663" },
{ -1, nullptr }
};
static const struct id_part ampere_part[] = {
{ 0xac3, "Ampere-1" },
{ 0xac4, "Ampere-1a" },
{ -1, nullptr }
};
static const struct id_part ft_part[] = {
{ 0x303, "FTC310" },
{ 0x660, "FTC660" },
{ 0x661, "FTC661" },
{ 0x662, "FTC662" },
{ 0x663, "FTC663" },
{ 0x664, "FTC664" },
{ 0x862, "FTC862" },
{ -1, nullptr }
};
static const struct id_part ms_part[] = {
{ 0xd49, "Azure-Cobalt-100" },
{ -1, nullptr }
};
static const hw_impl hw_implementer[] = {
{ 0x41, arm_part, "ARM" },
@@ -276,7 +300,7 @@ static const hw_impl hw_implementer[] = {
{ 0x44, dec_part, "DEC" },
{ 0x46, fujitsu_part, "FUJITSU" },
{ 0x48, hisi_part, "HiSilicon" },
{ 0x4e, nvidia_part, "Nvidia" },
{ 0x4e, nvidia_part, "NVIDIA" },
{ 0x50, apm_part, "APM" },
{ 0x51, qcom_part, "Qualcomm" },
{ 0x53, samsung_part, "Samsung" },
@@ -284,6 +308,7 @@ static const hw_impl hw_implementer[] = {
{ 0x61, apple_part, "Apple" },
{ 0x66, faraday_part, "Faraday" },
{ 0x69, intel_part, "Intel" },
{ 0x6d, ms_part, "Microsoft" },
{ 0x70, ft_part, "Phytium" },
{ 0xc0, ampere_part, "Ampere" }
};

View File

@@ -39,7 +39,7 @@
namespace xmrig {
#if defined(_MSC_VER) || (defined(__GNUC__) && !defined(__clang__))
#if defined(_MSC_VER) || defined(__GNUC__)
static std::wstring toUtf16(const char *str)
{
const int size = static_cast<int>(strlen(str));
@@ -56,13 +56,13 @@ static std::wstring toUtf16(const char *str)
#endif
#if defined(_MSC_VER)
#if defined(_MSC_VER) || defined(_LIBCPP_HAS_OPEN_WITH_WCHAR)
# define OPEN_IFS(name) \
std::ifstream ifs(toUtf16(name), std::ios_base::in | std::ios_base::binary); \
std::ifstream ifs(toUtf16(name).c_str(), std::ios_base::in | std::ios_base::binary);\
if (!ifs.is_open()) { \
return false; \
}
#elif defined(__GNUC__) && !defined(__clang__)
#elif defined(__GNUC__)
# define OPEN_IFS(name) \
const int fd = _wopen(toUtf16(name).c_str(), _O_RDONLY | _O_BINARY); \
if (fd == -1) { \
@@ -98,12 +98,12 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc)
using namespace rapidjson;
constexpr const std::ios_base::openmode mode = std::ios_base::out | std::ios_base::binary | std::ios_base::trunc;
# if defined(_MSC_VER)
std::ofstream ofs(toUtf16(fileName), mode);
# if defined(_MSC_VER) || defined(_LIBCPP_HAS_OPEN_WITH_WCHAR)
std::ofstream ofs(toUtf16(fileName).c_str(), mode);
if (!ofs.is_open()) {
return false;
}
# elif defined(__GNUC__) && !defined(__clang__)
# elif defined(__GNUC__)
const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_CREAT | _O_TRUNC, _S_IWRITE);
if (fd == -1) {
return false;

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -53,13 +53,21 @@ char *xmrig::Platform::createUserAgent()
char *buf = new char[max]();
int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion);
# if defined(__x86_64__) || defined(_M_AMD64)
length += snprintf(buf + length, max - length, "; Win64; x64) libuv/%s", uv_version_string());
# if defined(XMRIG_64_BIT)
length += snprintf(buf + length, max - length, "; Win64; "
# if defined(XMRIG_ARM)
"arm64"
# else
"x64"
# endif
") libuv/%s", uv_version_string());
# else
length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string());
# endif
# ifdef __GNUC__
# ifdef __clang__
snprintf(buf + length, max - length, " clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__);
# elif defined(__GNUC__)
snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# elif _MSC_VER
snprintf(buf + length, max - length, " msvc/%d", MSVC_VERSION);

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -18,14 +18,12 @@
#include <cstdio>
#ifdef _MSC_VER
# include "getopt/getopt.h"
#else
# include <getopt.h>
#endif
#include "base/kernel/config/BaseTransform.h"
#include "base/io/json/JsonChain.h"
#include "base/io/log/Log.h"
@@ -37,7 +35,6 @@
#include "base/net/stratum/Pools.h"
#include "core/config/Config_platform.h"
#ifdef XMRIG_FEATURE_TLS
# include "base/net/tls/TlsConfig.h"
#endif
@@ -48,7 +45,7 @@ void xmrig::BaseTransform::load(JsonChain &chain, Process *process, IConfigTrans
using namespace rapidjson;
int key = 0;
int argc = process->arguments().argc();
const int argc = process->arguments().argc();
char **argv = process->arguments().argv();
Document doc(kObjectType);
@@ -262,7 +259,8 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
case IConfig::DaemonKey: /* --daemon */
case IConfig::SubmitToOriginKey: /* --submit-to-origin */
case IConfig::VerboseKey: /* --verbose */
case IConfig::DnsIPv6Key: /* --dns-ipv6 */
case IConfig::DnsIPv4Key: /* --ipv4 */
case IConfig::DnsIPv6Key: /* --ipv6 */
return transformBoolean(doc, key, true);
case IConfig::ColorKey: /* --no-color */
@@ -323,8 +321,11 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b
case IConfig::NoTitleKey: /* --no-title */
return set(doc, BaseConfig::kTitle, enable);
case IConfig::DnsIPv6Key: /* --dns-ipv6 */
return set(doc, DnsConfig::kField, DnsConfig::kIPv6, enable);
case IConfig::DnsIPv4Key: /* --ipv4 */
return set(doc, DnsConfig::kField, DnsConfig::kIPv, 4);
case IConfig::DnsIPv6Key: /* --ipv6 */
return set(doc, DnsConfig::kField, DnsConfig::kIPv, 6);
default:
break;

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -16,9 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_ICONFIG_H
#define XMRIG_ICONFIG_H
#pragma once
#include "3rdparty/rapidjson/fwd.h"
@@ -82,7 +80,8 @@ public:
HugePageSizeKey = 1050,
PauseOnActiveKey = 1051,
SubmitToOriginKey = 1052,
DnsIPv6Key = 1053,
DnsIPv4Key = '4',
DnsIPv6Key = '6',
DnsTtlKey = 1054,
SpendSecretKey = 1055,
DaemonZMQPortKey = 1056,
@@ -177,7 +176,4 @@ public:
};
} /* namespace xmrig */
#endif // XMRIG_ICONFIG_H
} // namespace xmrig

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -16,21 +16,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_IDNSBACKEND_H
#define XMRIG_IDNSBACKEND_H
#pragma once
#include "base/tools/Object.h"
#include <memory>
namespace xmrig {
class DnsConfig;
class DnsRecords;
class DnsRequest;
class IDnsListener;
class String;
@@ -43,12 +38,8 @@ public:
IDnsBackend() = default;
virtual ~IDnsBackend() = default;
virtual const DnsRecords &records() const = 0;
virtual std::shared_ptr<DnsRequest> resolve(const String &host, IDnsListener *listener, uint64_t ttl) = 0;
virtual void resolve(const String &host, const std::weak_ptr<IDnsListener> &listener, const DnsConfig &config) = 0;
};
} /* namespace xmrig */
#endif // XMRIG_IDNSBACKEND_H
} // namespace xmrig

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -18,6 +18,7 @@
#include "base/net/dns/Dns.h"
#include "base/net/dns/DnsRequest.h"
#include "base/net/dns/DnsUvBackend.h"
@@ -31,11 +32,15 @@ std::map<String, std::shared_ptr<IDnsBackend> > Dns::m_backends;
} // namespace xmrig
std::shared_ptr<xmrig::DnsRequest> xmrig::Dns::resolve(const String &host, IDnsListener *listener, uint64_t ttl)
std::shared_ptr<xmrig::DnsRequest> xmrig::Dns::resolve(const String &host, IDnsListener *listener)
{
auto req = std::make_shared<DnsRequest>(listener);
if (m_backends.find(host) == m_backends.end()) {
m_backends.insert({ host, std::make_shared<DnsUvBackend>() });
}
return m_backends.at(host)->resolve(host, listener, ttl == 0 ? m_config.ttl() : ttl);
m_backends.at(host)->resolve(host, req, m_config);
return req;
}

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -43,7 +43,7 @@ public:
inline static const DnsConfig &config() { return m_config; }
inline static void set(const DnsConfig &config) { m_config = config; }
static std::shared_ptr<DnsRequest> resolve(const String &host, IDnsListener *listener, uint64_t ttl = 0);
static std::shared_ptr<DnsRequest> resolve(const String &host, IDnsListener *listener);
private:
static DnsConfig m_config;

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -20,15 +20,15 @@
#include "3rdparty/rapidjson/document.h"
#include "base/io/json/Json.h"
#include <algorithm>
#include <uv.h>
namespace xmrig {
const char *DnsConfig::kField = "dns";
const char *DnsConfig::kIPv6 = "ipv6";
const char *DnsConfig::kIPv = "ip_version";
const char *DnsConfig::kTTL = "ttl";
@@ -37,11 +37,29 @@ const char *DnsConfig::kTTL = "ttl";
xmrig::DnsConfig::DnsConfig(const rapidjson::Value &value)
{
m_ipv6 = Json::getBool(value, kIPv6, m_ipv6);
const uint32_t ipv = Json::getUint(value, kIPv, m_ipv);
if (ipv == 0 || ipv == 4 || ipv == 6) {
m_ipv = ipv;
}
m_ttl = std::max(Json::getUint(value, kTTL, m_ttl), 1U);
}
int xmrig::DnsConfig::ai_family() const
{
if (m_ipv == 4) {
return AF_INET;
}
if (m_ipv == 6) {
return AF_INET6;
}
return AF_UNSPEC;
}
rapidjson::Value xmrig::DnsConfig::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
@@ -49,7 +67,7 @@ rapidjson::Value xmrig::DnsConfig::toJSON(rapidjson::Document &doc) const
auto &allocator = doc.GetAllocator();
Value obj(kObjectType);
obj.AddMember(StringRef(kIPv6), m_ipv6, allocator);
obj.AddMember(StringRef(kIPv), m_ipv, allocator);
obj.AddMember(StringRef(kTTL), m_ttl, allocator);
return obj;

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -16,9 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_DNSCONFIG_H
#define XMRIG_DNSCONFIG_H
#pragma once
#include "3rdparty/rapidjson/fwd.h"
@@ -30,25 +28,22 @@ class DnsConfig
{
public:
static const char *kField;
static const char *kIPv6;
static const char *kIPv;
static const char *kTTL;
DnsConfig() = default;
DnsConfig(const rapidjson::Value &value);
inline bool isIPv6() const { return m_ipv6; }
inline uint32_t ipv() const { return m_ipv; }
inline uint32_t ttl() const { return m_ttl * 1000U; }
int ai_family() const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
private:
bool m_ipv6 = false;
uint32_t m_ttl = 30U;
uint32_t m_ipv = 0U;
};
} /* namespace xmrig */
#endif /* XMRIG_DNSCONFIG_H */
} // namespace xmrig

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -16,19 +16,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <uv.h>
#include "base/net/dns/DnsRecord.h"
xmrig::DnsRecord::DnsRecord(const addrinfo *addr) :
m_type(addr->ai_family == AF_INET6 ? AAAA : (addr->ai_family == AF_INET ? A : Unknown))
xmrig::DnsRecord::DnsRecord(const addrinfo *addr)
{
static_assert(sizeof(m_data) >= sizeof(sockaddr_in6), "Not enough storage for IPv6 address.");
memcpy(m_data, addr->ai_addr, m_type == AAAA ? sizeof(sockaddr_in6) : sizeof(sockaddr_in));
memcpy(m_data, addr->ai_addr, addr->ai_family == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in));
}
@@ -44,7 +41,7 @@ xmrig::String xmrig::DnsRecord::ip() const
{
char *buf = nullptr;
if (m_type == AAAA) {
if (reinterpret_cast<const sockaddr &>(m_data).sa_family == AF_INET6) {
buf = new char[45]();
uv_ip6_name(reinterpret_cast<const sockaddr_in6*>(m_data), buf, 45);
}

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -16,14 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_DNSRECORD_H
#define XMRIG_DNSRECORD_H
#pragma once
struct addrinfo;
struct sockaddr;
#include "base/tools/String.h"
@@ -33,28 +30,15 @@ namespace xmrig {
class DnsRecord
{
public:
enum Type : uint32_t {
Unknown,
A,
AAAA
};
DnsRecord() {}
DnsRecord(const addrinfo *addr);
const sockaddr *addr(uint16_t port = 0) const;
String ip() const;
inline bool isValid() const { return m_type != Unknown; }
inline Type type() const { return m_type; }
private:
mutable uint8_t m_data[28]{};
const Type m_type = Unknown;
};
} /* namespace xmrig */
#endif /* XMRIG_DNSRECORD_H */
} // namespace xmrig

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -18,90 +18,96 @@
#include <uv.h>
#include "base/net/dns/DnsRecords.h"
#include "base/net/dns/Dns.h"
const xmrig::DnsRecord &xmrig::DnsRecords::get(DnsRecord::Type prefered) const
namespace {
static size_t dns_records_count(const addrinfo *res, int &ai_family)
{
static const DnsRecord defaultRecord;
if (isEmpty()) {
return defaultRecord;
}
const size_t ipv4 = m_ipv4.size();
const size_t ipv6 = m_ipv6.size();
if (ipv6 && (prefered == DnsRecord::AAAA || Dns::config().isIPv6() || !ipv4)) {
return m_ipv6[ipv6 == 1 ? 0 : static_cast<size_t>(rand()) % ipv6]; // NOLINT(concurrency-mt-unsafe, cert-msc30-c, cert-msc50-cpp)
}
if (ipv4) {
return m_ipv4[ipv4 == 1 ? 0 : static_cast<size_t>(rand()) % ipv4]; // NOLINT(concurrency-mt-unsafe, cert-msc30-c, cert-msc50-cpp)
}
return defaultRecord;
}
size_t xmrig::DnsRecords::count(DnsRecord::Type type) const
{
if (type == DnsRecord::A) {
return m_ipv4.size();
}
if (type == DnsRecord::AAAA) {
return m_ipv6.size();
}
return m_ipv4.size() + m_ipv6.size();
}
void xmrig::DnsRecords::clear()
{
m_ipv4.clear();
m_ipv6.clear();
}
void xmrig::DnsRecords::parse(addrinfo *res)
{
clear();
addrinfo *ptr = res;
size_t ipv4 = 0;
size_t ipv6 = 0;
while (ptr != nullptr) {
if (ptr->ai_family == AF_INET) {
while (res != nullptr) {
if (res->ai_family == AF_INET) {
++ipv4;
}
else if (ptr->ai_family == AF_INET6) {
if (res->ai_family == AF_INET6) {
++ipv6;
}
ptr = ptr->ai_next;
res = res->ai_next;
}
if (ipv4 == 0 && ipv6 == 0) {
if (ai_family == AF_INET6 && !ipv6) {
ai_family = AF_INET;
}
switch (ai_family) {
case AF_UNSPEC:
return ipv4 + ipv6;
case AF_INET:
return ipv4;
case AF_INET6:
return ipv6;
default:
break;
}
return 0;
}
} // namespace
xmrig::DnsRecords::DnsRecords(const addrinfo *res, int ai_family)
{
size_t size = dns_records_count(res, ai_family);
if (!size) {
return;
}
m_ipv4.reserve(ipv4);
m_ipv6.reserve(ipv6);
m_records.reserve(size);
ptr = res;
while (ptr != nullptr) {
if (ptr->ai_family == AF_INET) {
m_ipv4.emplace_back(ptr);
}
else if (ptr->ai_family == AF_INET6) {
m_ipv6.emplace_back(ptr);
if (ai_family == AF_UNSPEC) {
while (res != nullptr) {
if (res->ai_family == AF_INET || res->ai_family == AF_INET6) {
m_records.emplace_back(res);
}
ptr = ptr->ai_next;
res = res->ai_next;
};
} else {
while (res != nullptr) {
if (res->ai_family == ai_family) {
m_records.emplace_back(res);
}
res = res->ai_next;
};
}
size = m_records.size();
if (size > 1) {
m_index = static_cast<size_t>(rand()) % size; // NOLINT(concurrency-mt-unsafe, cert-msc30-c, cert-msc50-cpp)
}
}
const xmrig::DnsRecord &xmrig::DnsRecords::get() const
{
static const DnsRecord defaultRecord;
const size_t size = m_records.size();
if (size > 0) {
return m_records[m_index++ % size];
}
return defaultRecord;
}

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -16,9 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_DNSRECORDS_H
#define XMRIG_DNSRECORDS_H
#pragma once
#include "base/net/dns/DnsRecord.h"
@@ -29,20 +27,19 @@ namespace xmrig {
class DnsRecords
{
public:
inline bool isEmpty() const { return m_ipv4.empty() && m_ipv6.empty(); }
DnsRecords() = default;
DnsRecords(const addrinfo *res, int ai_family);
const DnsRecord &get(DnsRecord::Type prefered = DnsRecord::Unknown) const;
size_t count(DnsRecord::Type type = DnsRecord::Unknown) const;
void clear();
void parse(addrinfo *res);
inline bool isEmpty() const { return m_records.empty(); }
inline const std::vector<DnsRecord> &records() const { return m_records; }
inline size_t size() const { return m_records.size(); }
const DnsRecord &get() const;
private:
std::vector<DnsRecord> m_ipv4;
std::vector<DnsRecord> m_ipv6;
mutable size_t m_index = 0;
std::vector<DnsRecord> m_records;
};
} /* namespace xmrig */
#endif /* XMRIG_DNSRECORDS_H */
} // namespace xmrig

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -16,35 +16,30 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_DNSREQUEST_H
#define XMRIG_DNSREQUEST_H
#pragma once
#include "base/tools/Object.h"
#include <cstdint>
#include "base/kernel/interfaces/IDnsListener.h"
namespace xmrig {
class IDnsListener;
class DnsRequest
class DnsRequest : public IDnsListener
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(DnsRequest)
DnsRequest(IDnsListener *listener) : listener(listener) {}
~DnsRequest() = default;
inline DnsRequest(IDnsListener *listener) : m_listener(listener) {}
~DnsRequest() override = default;
IDnsListener *listener;
protected:
inline void onResolved(const DnsRecords &records, int status, const char *error) override {
m_listener->onResolved(records, status, error);
}
private:
IDnsListener *m_listener;
};
} /* namespace xmrig */
#endif /* XMRIG_DNSREQUEST_H */
} // namespace xmrig

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -16,13 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <uv.h>
#include "base/net/dns/DnsUvBackend.h"
#include "base/kernel/interfaces/IDnsListener.h"
#include "base/net/dns/DnsRequest.h"
#include "base/net/dns/DnsConfig.h"
#include "base/tools/Chrono.h"
@@ -73,21 +71,23 @@ xmrig::DnsUvBackend::~DnsUvBackend()
}
std::shared_ptr<xmrig::DnsRequest> xmrig::DnsUvBackend::resolve(const String &host, IDnsListener *listener, uint64_t ttl)
void xmrig::DnsUvBackend::resolve(const String &host, const std::weak_ptr<IDnsListener> &listener, const DnsConfig &config)
{
auto req = std::make_shared<DnsRequest>(listener);
m_queue.emplace_back(listener);
if (Chrono::currentMSecsSinceEpoch() - m_ts <= ttl && !m_records.isEmpty()) {
req->listener->onResolved(m_records, 0, nullptr);
} else {
m_queue.emplace(req);
if (Chrono::currentMSecsSinceEpoch() - m_ts <= config.ttl()) {
return notify();
}
if (m_queue.size() == 1 && !resolve(host)) {
done();
if (m_req) {
return;
}
return req;
m_ai_family = config.ai_family();
if (!resolve(host)) {
notify();
}
}
@@ -102,44 +102,46 @@ bool xmrig::DnsUvBackend::resolve(const String &host)
}
void xmrig::DnsUvBackend::done()
void xmrig::DnsUvBackend::notify()
{
const char *error = m_status < 0 ? uv_strerror(m_status) : nullptr;
while (!m_queue.empty()) {
auto req = std::move(m_queue.front()).lock();
if (req) {
req->listener->onResolved(m_records, m_status, error);
}
m_queue.pop();
for (const auto &l : m_queue) {
auto listener = l.lock();
if (listener) {
listener->onResolved(m_records, m_status, error);
}
}
m_queue.clear();
m_req.reset();
}
void xmrig::DnsUvBackend::onResolved(int status, addrinfo *res)
{
m_status = status;
m_ts = Chrono::currentMSecsSinceEpoch();
if ((m_status = status) < 0) {
return done();
if (m_status < 0) {
m_records = {};
return notify();
}
m_records.parse(res);
m_records = { res, m_ai_family };
if (m_records.isEmpty()) {
m_status = UV_EAI_NONAME;
}
done();
notify();
}
void xmrig::DnsUvBackend::onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res)
{
auto backend = getStorage().get(req->data);
auto *backend = getStorage().get(req->data);
if (backend) {
backend->onResolved(status, res);
}

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -16,16 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_DNSUVBACKEND_H
#define XMRIG_DNSUVBACKEND_H
#pragma once
#include "base/kernel/interfaces/IDnsBackend.h"
#include "base/net/dns/DnsRecords.h"
#include "base/net/tools/Storage.h"
#include <queue>
#include <deque>
using uv_getaddrinfo_t = struct uv_getaddrinfo_s;
@@ -43,20 +40,19 @@ public:
~DnsUvBackend() override;
protected:
inline const DnsRecords &records() const override { return m_records; }
std::shared_ptr<DnsRequest> resolve(const String &host, IDnsListener *listener, uint64_t ttl) override;
void resolve(const String &host, const std::weak_ptr<IDnsListener> &listener, const DnsConfig &config) override;
private:
bool resolve(const String &host);
void done();
void notify();
void onResolved(int status, addrinfo *res);
static void onResolved(uv_getaddrinfo_t *req, int status, addrinfo *res);
DnsRecords m_records;
int m_ai_family = 0;
int m_status = 0;
std::queue<std::weak_ptr<DnsRequest> > m_queue;
std::deque<std::weak_ptr<IDnsListener>> m_queue;
std::shared_ptr<uv_getaddrinfo_t> m_req;
uint64_t m_ts = 0;
uintptr_t m_key;
@@ -66,7 +62,4 @@ private:
};
} /* namespace xmrig */
#endif /* XMRIG_DNSUVBACKEND_H */
} // namespace xmrig

View File

@@ -23,15 +23,22 @@
#pragma once
#include <cstdint>
#ifdef XMRIG_64_BIT
# ifdef _MSC_VER
#if defined(XMRIG_64_BIT)
# if defined(_MSC_VER)
# include <intrin.h>
# if defined(XMRIG_ARM)
#pragma intrinsic(__umulh)
static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t *high) {
*high = __umulh(a, b);
return a * b;
}
# else
# pragma intrinsic(_umul128)
# define __umul128 _umul128
# elif defined __GNUC__
# endif
# elif defined(__GNUC__)
static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
{
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;

View File

@@ -93,7 +93,7 @@
"dhparam": null
},
"dns": {
"ipv6": false,
"ip_version": 0,
"ttl": 30
},
"user-agent": null,

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -16,9 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CONFIG_PLATFORM_H
#define XMRIG_CONFIG_PLATFORM_H
#pragma once
#ifdef _MSC_VER
# include "getopt/getopt.h"
@@ -28,13 +26,12 @@
#include "base/kernel/interfaces/IConfig.h"
#include "version.h"
namespace xmrig {
static const char short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:Sx:";
static const char short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:Sx:46";
static const option options[] = {
@@ -99,7 +96,8 @@ static const option options[] = {
{ "no-title", 0, nullptr, IConfig::NoTitleKey },
{ "pause-on-battery", 0, nullptr, IConfig::PauseOnBatteryKey },
{ "pause-on-active", 1, nullptr, IConfig::PauseOnActiveKey },
{ "dns-ipv6", 0, nullptr, IConfig::DnsIPv6Key },
{ "ipv4", 0, nullptr, IConfig::DnsIPv4Key },
{ "ipv6", 0, nullptr, IConfig::DnsIPv6Key },
{ "dns-ttl", 1, nullptr, IConfig::DnsTtlKey },
{ "spend-secret-key", 1, nullptr, IConfig::SpendSecretKey },
# ifdef XMRIG_FEATURE_BENCHMARK
@@ -169,6 +167,3 @@ static const option options[] = {
} // namespace xmrig
#endif /* XMRIG_CONFIG_PLATFORM_H */

View File

@@ -4,8 +4,8 @@
* Copyright (c) 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright (c) 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright (c) 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright (c) 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -21,13 +21,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_USAGE_H
#define XMRIG_USAGE_H
#pragma once
#include "version.h"
#include <string>
@@ -59,7 +56,8 @@ static inline const std::string &usage()
u += " --tls-fingerprint=HEX pool TLS certificate fingerprint for strict certificate pinning\n";
# endif
u += " --dns-ipv6 prefer IPv6 records from DNS responses\n";
u += " -4, --ipv4 resolve names to IPv4 addresses\n";
u += " -6, --ipv6 resolve names to IPv6 addresses\n";
u += " --dns-ttl=N N seconds (default: 30) TTL for internal DNS cache\n";
# ifdef XMRIG_FEATURE_HTTP
@@ -205,6 +203,4 @@ static inline const std::string &usage()
}
} /* namespace xmrig */
#endif /* XMRIG_USAGE_H */
} // namespace xmrig

View File

@@ -200,7 +200,18 @@ typedef union{
int i32[4];
} vec_u;
#ifdef HAVE_POSIX_MEMALIGN
inline void* rx_aligned_alloc(size_t size, size_t align) {
void* p;
if (posix_memalign(&p, align, size) == 0)
return p;
return 0;
};
#else
# define rx_aligned_alloc(a, b) malloc(a)
#endif
#define rx_aligned_free(a) free(a)
#define rx_prefetch_nta(x)
#define rx_prefetch_t0(x)
@@ -392,7 +403,7 @@ FORCE_INLINE rx_vec_f128 rx_cvt_packed_int_vec_f128(const void* addr) {
typedef uint8x16_t rx_vec_i128;
typedef float64x2_t rx_vec_f128;
#if !defined(XMRIG_OS_WIN) // FIXME
#ifdef HAVE_POSIX_MEMALIGN
inline void* rx_aligned_alloc(size_t size, size_t align) {
void* p;
if (posix_memalign(&p, align, size) == 0)
@@ -400,11 +411,14 @@ inline void* rx_aligned_alloc(size_t size, size_t align) {
return 0;
};
# define rx_aligned_free(a) free(a)
#elif defined(HAVE_ALIGNED_MALLOC)
# define rx_aligned_alloc(a, b) _aligned_malloc(a, b)
# define rx_aligned_free(a) _aligned_free(a)
#else
# define rx_aligned_alloc(a, b) malloc(a)
#endif
# define rx_aligned_free(a) free(a)
#endif
inline void rx_prefetch_nta(void* ptr) {
asm volatile ("prfm pldl1strm, [%0]\n" : : "r" (ptr));
@@ -546,8 +560,23 @@ typedef union {
rx_vec_i128 i;
} rx_vec_f128;
#ifdef HAVE_POSIX_MEMALIGN
inline void* rx_aligned_alloc(size_t size, size_t align) {
void* p;
if (posix_memalign(&p, align, size) == 0)
return p;
return 0;
};
# define rx_aligned_free(a) free(a)
#elif defined(HAVE_ALIGNED_MALLOC)
# define rx_aligned_alloc(a, b) _aligned_malloc(a, b)
# define rx_aligned_free(a) _aligned_free(a)
#else
# define rx_aligned_alloc(a, b) malloc(a)
# define rx_aligned_free(a) free(a)
#endif
#define rx_prefetch_nta(x)
#define rx_prefetch_t0(x)

View File

@@ -1,8 +1,8 @@
/* XMRig
* Copyright (c) 2000-2002 Alan Cox <alan@redhat.com>
* Copyright (c) 2005-2020 Jean Delvare <jdelvare@suse.de>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/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
@@ -88,7 +88,6 @@ bool xmrig::DmiReader::decode(uint8_t *buf)
}
uint8_t *data = buf;
int i = 0;
while (data + 4 <= buf + m_size) {
dmi_header h{};
@@ -97,7 +96,6 @@ bool xmrig::DmiReader::decode(uint8_t *buf)
if (h.length < 4 || h.type == 127) {
break;
}
i++;
uint8_t *next = data + h.length;
while (static_cast<uint32_t>(next - buf + 1) < m_size && (next[0] != 0 || next[1] != 0)) {

View File

@@ -22,15 +22,15 @@
#define APP_ID "xmrig"
#define APP_NAME "XMRig"
#define APP_DESC "XMRig miner"
#define APP_VERSION "6.22.4-dev"
#define APP_VERSION "6.24.0"
#define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2025 xmrig.com"
#define APP_KIND "miner"
#define APP_VER_MAJOR 6
#define APP_VER_MINOR 22
#define APP_VER_PATCH 4
#define APP_VER_MINOR 24
#define APP_VER_PATCH 0
#ifdef _MSC_VER
# if (_MSC_VER >= 1930)