mirror of
https://github.com/xmrig/xmrig.git
synced 2025-12-09 08:42:40 -05:00
Compare commits
51 Commits
4188ec6d75
...
evo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e13d78315 | ||
|
|
b8191cef2b | ||
|
|
6f0291bfde | ||
|
|
6f3187049a | ||
|
|
4fec1b0aed | ||
|
|
d862ba853f | ||
|
|
9a4558561f | ||
|
|
f99554858b | ||
|
|
571bc798f4 | ||
|
|
8d043dadec | ||
|
|
1438672fe5 | ||
|
|
f6dbe32c86 | ||
|
|
4948a8c354 | ||
|
|
637c023d06 | ||
|
|
ce0b879542 | ||
|
|
f006ec0b68 | ||
|
|
04e5ff0349 | ||
|
|
9ad1c02430 | ||
|
|
61c263af6e | ||
|
|
fe0ed9eaae | ||
|
|
d8f39ebef3 | ||
|
|
07d53fb77e | ||
|
|
3ded8e6734 | ||
|
|
774f630e14 | ||
|
|
d6a1c98314 | ||
|
|
75283445fd | ||
|
|
45084cb718 | ||
|
|
bc150fec04 | ||
|
|
9a0cd68ea5 | ||
|
|
603eb261c5 | ||
|
|
de97f3492e | ||
|
|
8a167cb2a7 | ||
|
|
d0953a507c | ||
|
|
fe8e198106 | ||
|
|
dfc3b4632a | ||
|
|
6106bf30de | ||
|
|
3ab07fe8c1 | ||
|
|
824ba24134 | ||
|
|
d7a6aaadea | ||
|
|
26819f01e1 | ||
|
|
d94f6e9c3a | ||
|
|
28312236fd | ||
|
|
dbc53c5d46 | ||
|
|
a7e20ea5de | ||
|
|
bb9e35f5d2 | ||
|
|
cb2ec2316a | ||
|
|
e3b5bfeb36 | ||
|
|
cac1e4aa5e | ||
|
|
e1f0737a59 | ||
|
|
5c6c1299c8 | ||
|
|
4f90075ea0 |
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -17,9 +17,6 @@ Steps to reproduce the behavior.
|
|||||||
A clear and concise description of what you expected to happen.
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
**Required data**
|
**Required data**
|
||||||
- XMRig version
|
|
||||||
- Either the exact link to a release you downloaded from https://github.com/xmrig/xmrig/releases
|
|
||||||
- Or the exact command lines that you used to build XMRig
|
|
||||||
- Miner log as text or screenshot
|
- Miner log as text or screenshot
|
||||||
- Config file or command line (without wallets)
|
- Config file or command line (without wallets)
|
||||||
- OS: [e.g. Windows]
|
- OS: [e.g. Windows]
|
||||||
|
|||||||
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[submodule "src/base"]
|
||||||
|
path = src/base
|
||||||
|
url = https://github.com/xmrig/base.git
|
||||||
|
branch = master
|
||||||
93
CHANGELOG.md
93
CHANGELOG.md
@@ -1,96 +1,3 @@
|
|||||||
# v6.22.2
|
|
||||||
- [#3569](https://github.com/xmrig/xmrig/pull/3569) Fixed corrupted API output in some rare conditions.
|
|
||||||
- [#3571](https://github.com/xmrig/xmrig/pull/3571) Fixed number of threads on the new Intel Core Ultra CPUs.
|
|
||||||
|
|
||||||
# v6.22.1
|
|
||||||
- [#3531](https://github.com/xmrig/xmrig/pull/3531) Always reset nonce on RandomX dataset change.
|
|
||||||
- [#3534](https://github.com/xmrig/xmrig/pull/3534) Fixed threads auto-config on Zen5.
|
|
||||||
- [#3535](https://github.com/xmrig/xmrig/pull/3535) RandomX: tweaks for Zen5.
|
|
||||||
- [#3539](https://github.com/xmrig/xmrig/pull/3539) Added Zen5 to `randomx_boost.sh`.
|
|
||||||
- [#3540](https://github.com/xmrig/xmrig/pull/3540) Detect AMD engineering samples in `randomx_boost.sh`.
|
|
||||||
|
|
||||||
# v6.22.0
|
|
||||||
- [#2411](https://github.com/xmrig/xmrig/pull/2411) Added support for [Yada](https://yadacoin.io/) (`rx/yada` algorithm).
|
|
||||||
- [#3492](https://github.com/xmrig/xmrig/pull/3492) Fixed `--background` option on Unix systems.
|
|
||||||
- [#3518](https://github.com/xmrig/xmrig/pull/3518) Possible fix for corrupted API output in rare cases.
|
|
||||||
- [#3522](https://github.com/xmrig/xmrig/pull/3522) Removed `rx/keva` algorithm.
|
|
||||||
- [#3525](https://github.com/xmrig/xmrig/pull/3525) Added Zen5 detection.
|
|
||||||
- [#3528](https://github.com/xmrig/xmrig/pull/3528) Added `rx/yada` OpenCL support.
|
|
||||||
|
|
||||||
# v6.21.3
|
|
||||||
- [#3462](https://github.com/xmrig/xmrig/pull/3462) RandomX: correct memcpy size for JIT initialization.
|
|
||||||
|
|
||||||
# v6.21.2
|
|
||||||
- The dependencies of all prebuilt releases have been updated. Support for old Ubuntu releases has been dropped.
|
|
||||||
- [#2800](https://github.com/xmrig/xmrig/issues/2800) Fixed donation with GhostRider algorithm for builds without KawPow algorithm.
|
|
||||||
- [#3436](https://github.com/xmrig/xmrig/pull/3436) Fixed, the file log writer was not thread-safe.
|
|
||||||
- [#3450](https://github.com/xmrig/xmrig/pull/3450) Fixed RandomX crash when compiled with fortify_source.
|
|
||||||
|
|
||||||
# v6.21.1
|
|
||||||
- [#3391](https://github.com/xmrig/xmrig/pull/3391) Added support for townforge (monero fork using randomx).
|
|
||||||
- [#3399](https://github.com/xmrig/xmrig/pull/3399) Fixed Zephyr mining (OpenCL).
|
|
||||||
- [#3420](https://github.com/xmrig/xmrig/pull/3420) Fixed segfault in HTTP API rebind.
|
|
||||||
|
|
||||||
# v6.21.0
|
|
||||||
- [#3302](https://github.com/xmrig/xmrig/pull/3302) [#3312](https://github.com/xmrig/xmrig/pull/3312) Enabled keepalive for Windows (>= Vista).
|
|
||||||
- [#3320](https://github.com/xmrig/xmrig/pull/3320) Added "built for OS/architecture/bits" to "ABOUT".
|
|
||||||
- [#3339](https://github.com/xmrig/xmrig/pull/3339) Added SNI option for TLS connections.
|
|
||||||
- [#3342](https://github.com/xmrig/xmrig/pull/3342) Update `cn_main_loop.asm`.
|
|
||||||
- [#3346](https://github.com/xmrig/xmrig/pull/3346) ARM64 JIT: don't use `x18` register.
|
|
||||||
- [#3348](https://github.com/xmrig/xmrig/pull/3348) Update to latest `sse2neon.h`.
|
|
||||||
- [#3356](https://github.com/xmrig/xmrig/pull/3356) Updated pricing record size for **Zephyr** solo mining.
|
|
||||||
- [#3358](https://github.com/xmrig/xmrig/pull/3358) **Zephyr** solo mining: handle multiple outputs.
|
|
||||||
|
|
||||||
# v6.20.0
|
|
||||||
- Added new ARM CPU names.
|
|
||||||
- [#2394](https://github.com/xmrig/xmrig/pull/2394) Added new CMake options `ARM_V8` and `ARM_V7`.
|
|
||||||
- [#2830](https://github.com/xmrig/xmrig/pull/2830) Added API rebind polling.
|
|
||||||
- [#2927](https://github.com/xmrig/xmrig/pull/2927) Fixed compatibility with hwloc 1.11.x.
|
|
||||||
- [#3060](https://github.com/xmrig/xmrig/pull/3060) Added x86 to `README.md`.
|
|
||||||
- [#3236](https://github.com/xmrig/xmrig/pull/3236) Fixed: receive CUDA loader error on Linux too.
|
|
||||||
- [#3290](https://github.com/xmrig/xmrig/pull/3290) Added [Zephyr](https://www.zephyrprotocol.com/) coin support for solo mining.
|
|
||||||
|
|
||||||
# v6.19.3
|
|
||||||
- [#3245](https://github.com/xmrig/xmrig/issues/3245) Improved algorithm negotiation for donation rounds by sending extra information about current mining job.
|
|
||||||
- [#3254](https://github.com/xmrig/xmrig/pull/3254) Tweaked auto-tuning for Intel CPUs.
|
|
||||||
- [#3271](https://github.com/xmrig/xmrig/pull/3271) RandomX: optimized program generation.
|
|
||||||
- [#3273](https://github.com/xmrig/xmrig/pull/3273) RandomX: fixed undefined behavior.
|
|
||||||
- [#3275](https://github.com/xmrig/xmrig/pull/3275) RandomX: fixed `jccErratum` list.
|
|
||||||
- [#3280](https://github.com/xmrig/xmrig/pull/3280) Updated example scripts.
|
|
||||||
|
|
||||||
# v6.19.2
|
|
||||||
- [#3230](https://github.com/xmrig/xmrig/pull/3230) Fixed parsing of `TX_EXTRA_MERGE_MINING_TAG`.
|
|
||||||
- [#3232](https://github.com/xmrig/xmrig/pull/3232) Added new `X-Hash-Difficulty` HTTP header.
|
|
||||||
- [#3240](https://github.com/xmrig/xmrig/pull/3240) Improved .cmd files when run by shortcuts on another drive.
|
|
||||||
- [#3241](https://github.com/xmrig/xmrig/pull/3241) Added view tag calculation (fixes Wownero solo mining issue).
|
|
||||||
|
|
||||||
# v6.19.1
|
|
||||||
- Resolved deprecated methods warnings with OpenSSL 3.0.
|
|
||||||
- [#3213](https://github.com/xmrig/xmrig/pull/3213) Fixed build with 32-bit clang 15.
|
|
||||||
- [#3218](https://github.com/xmrig/xmrig/pull/3218) Fixed: `--randomx-wrmsr=-1` worked only on Intel.
|
|
||||||
- [#3228](https://github.com/xmrig/xmrig/pull/3228) Fixed build with gcc 13.
|
|
||||||
|
|
||||||
# v6.19.0
|
|
||||||
- [#3144](https://github.com/xmrig/xmrig/pull/3144) Update to latest `sse2neon.h`.
|
|
||||||
- [#3161](https://github.com/xmrig/xmrig/pull/3161) MSVC build: enabled parallel compilation.
|
|
||||||
- [#3163](https://github.com/xmrig/xmrig/pull/3163) Improved Zen 3 MSR mod.
|
|
||||||
- [#3176](https://github.com/xmrig/xmrig/pull/3176) Update cmake required version to 3.1.
|
|
||||||
- [#3182](https://github.com/xmrig/xmrig/pull/3182) DragonflyBSD compilation fixes.
|
|
||||||
- [#3196](https://github.com/xmrig/xmrig/pull/3196) Show IP address for failed connections.
|
|
||||||
- [#3185](https://github.com/xmrig/xmrig/issues/3185) Fixed macOS DMI reader.
|
|
||||||
- [#3198](https://github.com/xmrig/xmrig/pull/3198) Fixed broken RandomX light mode mining.
|
|
||||||
- [#3202](https://github.com/xmrig/xmrig/pull/3202) Solo mining: added job timeout (default is 15 seconds).
|
|
||||||
|
|
||||||
# v6.18.1
|
|
||||||
- [#3129](https://github.com/xmrig/xmrig/pull/3129) Fix: protectRX flushed CPU cache only on MacOS/iOS.
|
|
||||||
- [#3126](https://github.com/xmrig/xmrig/pull/3126) Don't reset when pool sends the same job blob.
|
|
||||||
- [#3120](https://github.com/xmrig/xmrig/pull/3120) RandomX: optimized `CFROUND` elimination.
|
|
||||||
- [#3109](https://github.com/xmrig/xmrig/pull/3109) RandomX: added Blake2 AVX2 version.
|
|
||||||
- [#3082](https://github.com/xmrig/xmrig/pull/3082) Fixed GCC 12 warnings.
|
|
||||||
- [#3075](https://github.com/xmrig/xmrig/pull/3075) Recognize `armv7ve` as valid ARMv7 target.
|
|
||||||
- [#3132](https://github.com/xmrig/xmrig/pull/3132) RandomX: added MSR mod for Zen 4.
|
|
||||||
- [#3134](https://github.com/xmrig/xmrig/pull/3134) Added Zen4 to `randomx_boost.sh`.
|
|
||||||
|
|
||||||
# v6.18.0
|
# v6.18.0
|
||||||
- [#3067](https://github.com/xmrig/xmrig/pull/3067) Monero v15 network upgrade support and more house keeping.
|
- [#3067](https://github.com/xmrig/xmrig/pull/3067) Monero v15 network upgrade support and more house keeping.
|
||||||
- Removed deprecated AstroBWTv1 and v2.
|
- Removed deprecated AstroBWTv1 and v2.
|
||||||
|
|||||||
6
CHANGELOG_NEXT.md
Normal file
6
CHANGELOG_NEXT.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# v7.0.0
|
||||||
|
- `src/base` is now a git submodule for the [base](https://github.com/xmrig/base) project, build instructions require slight update.
|
||||||
|
- Removed config option `background` (only command line available). Switching to background now happens on a very early stage before any I/O.
|
||||||
|
|
||||||
|
# Previous versions
|
||||||
|
[doc/CHANGELOG_OLD.md](doc/CHANGELOG_OLD.md)
|
||||||
154
CMakeLists.txt
154
CMakeLists.txt
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
project(xmrig)
|
project(xmrig)
|
||||||
|
|
||||||
option(WITH_HWLOC "Enable hwloc support" ON)
|
option(WITH_HWLOC "Enable hwloc support" ON)
|
||||||
@@ -32,29 +32,31 @@ option(WITH_VAES "Enable VAES instructions for Cryptonight" ON)
|
|||||||
option(WITH_BENCHMARK "Enable builtin RandomX benchmark and stress test" ON)
|
option(WITH_BENCHMARK "Enable builtin RandomX benchmark and stress test" ON)
|
||||||
option(WITH_SECURE_JIT "Enable secure access to JIT memory" OFF)
|
option(WITH_SECURE_JIT "Enable secure access to JIT memory" OFF)
|
||||||
option(WITH_DMI "Enable DMI/SMBIOS reader" ON)
|
option(WITH_DMI "Enable DMI/SMBIOS reader" ON)
|
||||||
option(WITH_BUNDLED_FMT "Force use of bundled fmt library" ON)
|
|
||||||
|
|
||||||
option(BUILD_STATIC "Build static binary" OFF)
|
option(BUILD_STATIC "Build static binary" OFF)
|
||||||
option(ARM_V8 "Force ARMv8 (64 bit) architecture, use with caution if automatic detection fails, but you sure it may work" OFF)
|
option(ARM_TARGET "Force use specific ARM target 8 or 7" 0)
|
||||||
option(ARM_V7 "Force ARMv7 (32 bit) architecture, use with caution if automatic detection fails, but you sure it may work" OFF)
|
|
||||||
option(HWLOC_DEBUG "Enable hwloc debug helpers and log" OFF)
|
option(HWLOC_DEBUG "Enable hwloc debug helpers and log" OFF)
|
||||||
|
|
||||||
|
add_definitions(-DXMRIG_MINER_PROJECT)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
set(WITH_SODIUM OFF)
|
||||||
|
set(WITH_CRYPTONOTE ON)
|
||||||
|
set(WITH_CRYPTO_OPS ON)
|
||||||
|
set(WITH_COM OFF)
|
||||||
|
set(WITH_EVENTS OFF)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/src/base/cmake" "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
set(LIBS base)
|
||||||
|
|
||||||
include (CheckIncludeFile)
|
include(base)
|
||||||
include (cmake/cpu.cmake)
|
add_subdirectory(src/base)
|
||||||
include (cmake/os.cmake)
|
|
||||||
include (src/base/base.cmake)
|
include(src/backend/backend.cmake)
|
||||||
include (src/backend/backend.cmake)
|
|
||||||
|
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
"${HEADERS_BASE}"
|
|
||||||
"${HEADERS_BASE_HTTP}"
|
|
||||||
"${HEADERS_BACKEND}"
|
"${HEADERS_BACKEND}"
|
||||||
src/App.h
|
src/backend/common/interfaces/IMemoryPool.h
|
||||||
src/core/config/Config_default.h
|
src/core/config/Config_default.h
|
||||||
src/core/config/Config_platform.h
|
src/core/config/Config_platform.h
|
||||||
src/core/config/Config.h
|
src/core/config/Config.h
|
||||||
@@ -63,17 +65,6 @@ set(HEADERS
|
|||||||
src/core/Controller.h
|
src/core/Controller.h
|
||||||
src/core/Miner.h
|
src/core/Miner.h
|
||||||
src/core/Taskbar.h
|
src/core/Taskbar.h
|
||||||
src/net/interfaces/IJobResultListener.h
|
|
||||||
src/net/JobResult.h
|
|
||||||
src/net/JobResults.h
|
|
||||||
src/net/Network.h
|
|
||||||
src/net/strategies/DonateStrategy.h
|
|
||||||
src/Summary.h
|
|
||||||
src/version.h
|
|
||||||
)
|
|
||||||
|
|
||||||
set(HEADERS_CRYPTO
|
|
||||||
src/backend/common/interfaces/IMemoryPool.h
|
|
||||||
src/crypto/cn/asm/CryptonightR_template.h
|
src/crypto/cn/asm/CryptonightR_template.h
|
||||||
src/crypto/cn/c_blake256.h
|
src/crypto/cn/c_blake256.h
|
||||||
src/crypto/cn/c_groestl.h
|
src/crypto/cn/c_groestl.h
|
||||||
@@ -94,32 +85,29 @@ set(HEADERS_CRYPTO
|
|||||||
src/crypto/common/Nonce.h
|
src/crypto/common/Nonce.h
|
||||||
src/crypto/common/portable/mm_malloc.h
|
src/crypto/common/portable/mm_malloc.h
|
||||||
src/crypto/common/VirtualMemory.h
|
src/crypto/common/VirtualMemory.h
|
||||||
|
src/MinerApp.h
|
||||||
|
src/net/interfaces/IJobResultListener.h
|
||||||
|
src/net/JobResult.h
|
||||||
|
src/net/JobResults.h
|
||||||
|
src/net/Network.h
|
||||||
|
src/net/strategies/DonateStrategy.h
|
||||||
|
src/Summary.h
|
||||||
|
src/version.h
|
||||||
)
|
)
|
||||||
|
|
||||||
if (XMRIG_ARM)
|
if (XMRIG_ARM)
|
||||||
set(HEADERS_CRYPTO "${HEADERS_CRYPTO}" src/crypto/cn/CryptoNight_arm.h)
|
list(APPEND HEADERS src/crypto/cn/CryptoNight_arm.h)
|
||||||
else()
|
else()
|
||||||
set(HEADERS_CRYPTO "${HEADERS_CRYPTO}" src/crypto/cn/CryptoNight_x86.h)
|
list(APPEND HEADERS src/crypto/cn/CryptoNight_x86.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
"${SOURCES_BASE}"
|
|
||||||
"${SOURCES_BASE_HTTP}"
|
|
||||||
"${SOURCES_BACKEND}"
|
"${SOURCES_BACKEND}"
|
||||||
src/App.cpp
|
|
||||||
src/core/config/Config.cpp
|
src/core/config/Config.cpp
|
||||||
src/core/config/ConfigTransform.cpp
|
src/core/config/ConfigTransform.cpp
|
||||||
src/core/Controller.cpp
|
src/core/Controller.cpp
|
||||||
src/core/Miner.cpp
|
src/core/Miner.cpp
|
||||||
src/core/Taskbar.cpp
|
src/core/Taskbar.cpp
|
||||||
src/net/JobResults.cpp
|
|
||||||
src/net/Network.cpp
|
|
||||||
src/net/strategies/DonateStrategy.cpp
|
|
||||||
src/Summary.cpp
|
|
||||||
src/xmrig.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
set(SOURCES_CRYPTO
|
|
||||||
src/crypto/cn/c_blake256.c
|
src/crypto/cn/c_blake256.c
|
||||||
src/crypto/cn/c_groestl.c
|
src/crypto/cn/c_groestl.c
|
||||||
src/crypto/cn/c_jh.c
|
src/crypto/cn/c_jh.c
|
||||||
@@ -130,6 +118,12 @@ set(SOURCES_CRYPTO
|
|||||||
src/crypto/common/MemoryPool.cpp
|
src/crypto/common/MemoryPool.cpp
|
||||||
src/crypto/common/Nonce.cpp
|
src/crypto/common/Nonce.cpp
|
||||||
src/crypto/common/VirtualMemory.cpp
|
src/crypto/common/VirtualMemory.cpp
|
||||||
|
src/MinerApp.cpp
|
||||||
|
src/net/JobResults.cpp
|
||||||
|
src/net/Network.cpp
|
||||||
|
src/net/strategies/DonateStrategy.cpp
|
||||||
|
src/Summary.cpp
|
||||||
|
src/xmrig.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (CMAKE_C_COMPILER_ID MATCHES GNU)
|
if (CMAKE_C_COMPILER_ID MATCHES GNU)
|
||||||
@@ -138,108 +132,58 @@ endif()
|
|||||||
|
|
||||||
if (WITH_VAES)
|
if (WITH_VAES)
|
||||||
add_definitions(-DXMRIG_VAES)
|
add_definitions(-DXMRIG_VAES)
|
||||||
set(HEADERS_CRYPTO "${HEADERS_CRYPTO}" src/crypto/cn/CryptoNight_x86_vaes.h)
|
list(APPEND HEADERS src/crypto/cn/CryptoNight_x86_vaes.h)
|
||||||
set(SOURCES_CRYPTO "${SOURCES_CRYPTO}" src/crypto/cn/CryptoNight_x86_vaes.cpp)
|
list(APPEND SOURCES src/crypto/cn/CryptoNight_x86_vaes.cpp)
|
||||||
if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES Clang)
|
if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES Clang)
|
||||||
set_source_files_properties(src/crypto/cn/CryptoNight_x86_vaes.cpp PROPERTIES COMPILE_FLAGS "-Ofast -fno-tree-vectorize -mavx2 -mvaes")
|
set_source_files_properties(src/crypto/cn/CryptoNight_x86_vaes.cpp PROPERTIES COMPILE_FLAGS "-Ofast -fno-tree-vectorize -mavx2 -mvaes")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_HWLOC)
|
if (WITH_HWLOC)
|
||||||
list(APPEND HEADERS_CRYPTO
|
list(APPEND HEADERS
|
||||||
src/crypto/common/NUMAMemoryPool.h
|
src/crypto/common/NUMAMemoryPool.h
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES
|
||||||
src/crypto/common/NUMAMemoryPool.cpp
|
src/crypto/common/NUMAMemoryPool.cpp
|
||||||
src/crypto/common/VirtualMemory_hwloc.cpp
|
src/crypto/common/VirtualMemory_hwloc.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (XMRIG_OS_WIN)
|
if (XMRIG_OS_WIN)
|
||||||
list(APPEND SOURCES_OS
|
list(APPEND SOURCES
|
||||||
res/app.rc
|
res/app.rc
|
||||||
src/App_win.cpp
|
|
||||||
src/crypto/common/VirtualMemory_win.cpp
|
src/crypto/common/VirtualMemory_win.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv dbghelp)
|
|
||||||
elseif (XMRIG_OS_APPLE)
|
|
||||||
list(APPEND SOURCES_OS
|
|
||||||
src/App_unix.cpp
|
|
||||||
src/crypto/common/VirtualMemory_unix.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(IOKIT_LIBRARY IOKit)
|
|
||||||
find_library(CORESERVICES_LIBRARY CoreServices)
|
|
||||||
set(EXTRA_LIBS ${IOKIT_LIBRARY} ${CORESERVICES_LIBRARY})
|
|
||||||
else()
|
else()
|
||||||
list(APPEND SOURCES_OS
|
list(APPEND SOURCES src/crypto/common/VirtualMemory_unix.cpp)
|
||||||
src/App_unix.cpp
|
|
||||||
src/crypto/common/VirtualMemory_unix.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
if (XMRIG_OS_ANDROID)
|
if (XMRIG_OS_LINUX AND NOT XMRIG_OS_ANDROID)
|
||||||
set(EXTRA_LIBS pthread rt dl log)
|
list(APPEND SOURCES
|
||||||
elseif (XMRIG_OS_LINUX)
|
|
||||||
list(APPEND SOURCES_OS
|
|
||||||
src/crypto/common/LinuxMemory.h
|
src/crypto/common/LinuxMemory.h
|
||||||
src/crypto/common/LinuxMemory.cpp
|
src/crypto/common/LinuxMemory.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(EXTRA_LIBS pthread rt dl)
|
|
||||||
elseif (XMRIG_OS_FREEBSD)
|
|
||||||
set(EXTRA_LIBS kvm pthread)
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(-DXMRIG_MINER_PROJECT -DXMRIG_JSON_SINGLE_LINE_ARRAY)
|
include_directories(src)
|
||||||
add_definitions(-D__STDC_FORMAT_MACROS -DUNICODE -D_FILE_OFFSET_BITS=64)
|
include_directories(src/3rdparty)
|
||||||
|
|
||||||
find_package(UV REQUIRED)
|
include(randomx)
|
||||||
|
include(argon2)
|
||||||
include(cmake/flags.cmake)
|
include(kawpow)
|
||||||
include(cmake/fmt.cmake)
|
include(ghostrider)
|
||||||
include(cmake/randomx.cmake)
|
include(asm)
|
||||||
include(cmake/argon2.cmake)
|
|
||||||
include(cmake/kawpow.cmake)
|
|
||||||
include(cmake/ghostrider.cmake)
|
|
||||||
include(cmake/OpenSSL.cmake)
|
|
||||||
include(cmake/asm.cmake)
|
|
||||||
|
|
||||||
if (WITH_CN_LITE)
|
|
||||||
add_definitions(/DXMRIG_ALGO_CN_LITE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_CN_HEAVY)
|
|
||||||
add_definitions(/DXMRIG_ALGO_CN_HEAVY)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_CN_PICO)
|
|
||||||
add_definitions(/DXMRIG_ALGO_CN_PICO)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_CN_FEMTO)
|
|
||||||
add_definitions(/DXMRIG_ALGO_CN_FEMTO)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_EMBEDDED_CONFIG)
|
if (WITH_EMBEDDED_CONFIG)
|
||||||
add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG)
|
add_definitions(-DXMRIG_FEATURE_EMBEDDED_CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(src/hw/api/api.cmake)
|
include(src/hw/api/api.cmake)
|
||||||
include(src/hw/dmi/dmi.cmake)
|
include(src/hw/dmi/dmi.cmake)
|
||||||
|
|
||||||
include_directories(src)
|
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
|
||||||
include_directories(src/3rdparty/CL)
|
target_link_libraries(${CMAKE_PROJECT_NAME} ${LIBS})
|
||||||
include_directories(${UV_INCLUDE_DIR})
|
|
||||||
|
|
||||||
if (WITH_DEBUG_LOG)
|
|
||||||
add_definitions(/DAPP_DEBUG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES})
|
|
||||||
target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB} ${ARGON2_LIBRARY} ${ETHASH_LIBRARY} ${GHOSTRIDER_LIBRARY} ${FMT_LIBRARY})
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/bin/WinRing0/WinRing0x64.sys" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/bin/WinRing0/WinRing0x64.sys" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
XMRig is a high performance, open source, cross platform RandomX, KawPow, CryptoNight and [GhostRider](https://github.com/xmrig/xmrig/tree/master/src/crypto/ghostrider#readme) unified CPU/GPU miner and [RandomX benchmark](https://xmrig.com/benchmark). Official binaries are available for Windows, Linux, macOS and FreeBSD.
|
XMRig is a high performance, open source, cross platform RandomX, KawPow, CryptoNight and [GhostRider](https://github.com/xmrig/xmrig/tree/master/src/crypto/ghostrider#readme) unified CPU/GPU miner and [RandomX benchmark](https://xmrig.com/benchmark). Official binaries are available for Windows, Linux, macOS and FreeBSD.
|
||||||
|
|
||||||
## Mining backends
|
## Mining backends
|
||||||
- **CPU** (x86/x64/ARMv7/ARMv8)
|
- **CPU** (x64/ARMv7/ARMv8)
|
||||||
- **OpenCL** for AMD GPUs.
|
- **OpenCL** for AMD GPUs.
|
||||||
- **CUDA** for NVIDIA GPUs via external [CUDA plugin](https://github.com/xmrig/xmrig-cuda).
|
- **CUDA** for NVIDIA GPUs via external [CUDA plugin](https://github.com/xmrig/xmrig-cuda).
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
find_path(
|
|
||||||
HWLOC_INCLUDE_DIR
|
|
||||||
NAMES hwloc.h
|
|
||||||
PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS"
|
|
||||||
PATH_SUFFIXES "include"
|
|
||||||
NO_DEFAULT_PATH
|
|
||||||
)
|
|
||||||
|
|
||||||
find_path(HWLOC_INCLUDE_DIR NAMES hwloc.h)
|
|
||||||
|
|
||||||
find_library(
|
|
||||||
HWLOC_LIBRARY
|
|
||||||
NAMES hwloc.a hwloc libhwloc
|
|
||||||
PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS"
|
|
||||||
PATH_SUFFIXES "lib"
|
|
||||||
NO_DEFAULT_PATH
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(HWLOC_LIBRARY NAMES hwloc.a hwloc libhwloc)
|
|
||||||
|
|
||||||
set(HWLOC_LIBRARIES ${HWLOC_LIBRARY})
|
|
||||||
set(HWLOC_INCLUDE_DIRS ${HWLOC_INCLUDE_DIR})
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(HWLOC DEFAULT_MSG HWLOC_LIBRARY HWLOC_INCLUDE_DIR)
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
find_path(
|
|
||||||
UV_INCLUDE_DIR
|
|
||||||
NAMES uv.h
|
|
||||||
PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS"
|
|
||||||
PATH_SUFFIXES "include"
|
|
||||||
NO_DEFAULT_PATH
|
|
||||||
)
|
|
||||||
|
|
||||||
find_path(UV_INCLUDE_DIR NAMES uv.h)
|
|
||||||
|
|
||||||
find_library(
|
|
||||||
UV_LIBRARY
|
|
||||||
NAMES libuv.a uv libuv
|
|
||||||
PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS"
|
|
||||||
PATH_SUFFIXES "lib"
|
|
||||||
NO_DEFAULT_PATH
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(UV_LIBRARY NAMES libuv.a uv libuv)
|
|
||||||
|
|
||||||
set(UV_LIBRARIES ${UV_LIBRARY})
|
|
||||||
set(UV_INCLUDE_DIRS ${UV_INCLUDE_DIR})
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(UV DEFAULT_MSG UV_LIBRARY UV_INCLUDE_DIR)
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
if (WITH_TLS)
|
|
||||||
set(OPENSSL_ROOT_DIR ${XMRIG_DEPS})
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
set(OPENSSL_USE_STATIC_LIBS TRUE)
|
|
||||||
set(OPENSSL_MSVC_STATIC_RT TRUE)
|
|
||||||
|
|
||||||
set(EXTRA_LIBS ${EXTRA_LIBS} crypt32)
|
|
||||||
elseif (APPLE)
|
|
||||||
set(OPENSSL_USE_STATIC_LIBS TRUE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (BUILD_STATIC)
|
|
||||||
set(OPENSSL_USE_STATIC_LIBS TRUE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
find_package(OpenSSL)
|
|
||||||
|
|
||||||
if (OPENSSL_FOUND)
|
|
||||||
set(TLS_SOURCES
|
|
||||||
src/base/net/stratum/Tls.cpp
|
|
||||||
src/base/net/stratum/Tls.h
|
|
||||||
src/base/net/tls/ServerTls.cpp
|
|
||||||
src/base/net/tls/ServerTls.h
|
|
||||||
src/base/net/tls/TlsConfig.cpp
|
|
||||||
src/base/net/tls/TlsConfig.h
|
|
||||||
src/base/net/tls/TlsContext.cpp
|
|
||||||
src/base/net/tls/TlsContext.h
|
|
||||||
src/base/net/tls/TlsGen.cpp
|
|
||||||
src/base/net/tls/TlsGen.h
|
|
||||||
)
|
|
||||||
|
|
||||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
|
||||||
|
|
||||||
if (WITH_HTTP)
|
|
||||||
set(TLS_SOURCES ${TLS_SOURCES}
|
|
||||||
src/base/net/https/HttpsClient.cpp
|
|
||||||
src/base/net/https/HttpsClient.h
|
|
||||||
src/base/net/https/HttpsContext.cpp
|
|
||||||
src/base/net/https/HttpsContext.h
|
|
||||||
src/base/net/https/HttpsServer.cpp
|
|
||||||
src/base/net/https/HttpsServer.h
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_definitions(/DXMRIG_FEATURE_TLS)
|
|
||||||
else()
|
|
||||||
set(TLS_SOURCES "")
|
|
||||||
set(OPENSSL_LIBRARIES "")
|
|
||||||
remove_definitions(/DXMRIG_FEATURE_TLS)
|
|
||||||
|
|
||||||
if (WITH_HTTP)
|
|
||||||
set(TLS_SOURCES ${TLS_SOURCES}
|
|
||||||
src/base/net/http/HttpServer.cpp
|
|
||||||
src/base/net/http/HttpServer.h
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_PROJECT_NAME "${CMAKE_PROJECT_NAME}-notls")
|
|
||||||
endif()
|
|
||||||
@@ -1,18 +1,13 @@
|
|||||||
if (WITH_ARGON2)
|
if (WITH_ARGON2)
|
||||||
add_definitions(/DXMRIG_ALGO_ARGON2)
|
list(APPEND HEADERS
|
||||||
|
|
||||||
list(APPEND HEADERS_CRYPTO
|
|
||||||
src/crypto/argon2/Hash.h
|
src/crypto/argon2/Hash.h
|
||||||
src/crypto/argon2/Impl.h
|
src/crypto/argon2/Impl.h
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES
|
||||||
src/crypto/argon2/Impl.cpp
|
src/crypto/argon2/Impl.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(src/3rdparty/argon2)
|
add_subdirectory(src/3rdparty/argon2)
|
||||||
set(ARGON2_LIBRARY argon2)
|
list(APPEND LIBS argon2)
|
||||||
else()
|
|
||||||
remove_definitions(/DXMRIG_ALGO_ARGON2)
|
|
||||||
set(ARGON2_LIBRARY "")
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -36,17 +36,16 @@ if (WITH_ASM AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(${XMRIG_ASM_LIBRARY} STATIC ${XMRIG_ASM_FILES})
|
add_library(${XMRIG_ASM_LIBRARY} STATIC ${XMRIG_ASM_FILES})
|
||||||
set(XMRIG_ASM_SOURCES
|
list(APPEND HEADERS src/crypto/common/Assembly.h)
|
||||||
src/crypto/common/Assembly.h
|
|
||||||
|
list(APPEND SOURCES
|
||||||
src/crypto/common/Assembly.cpp
|
src/crypto/common/Assembly.cpp
|
||||||
src/crypto/cn/r/CryptonightR_gen.cpp
|
src/crypto/cn/r/CryptonightR_gen.cpp
|
||||||
)
|
)
|
||||||
set_property(TARGET ${XMRIG_ASM_LIBRARY} PROPERTY LINKER_LANGUAGE C)
|
set_property(TARGET ${XMRIG_ASM_LIBRARY} PROPERTY LINKER_LANGUAGE C)
|
||||||
|
|
||||||
add_definitions(/DXMRIG_FEATURE_ASM)
|
list(APPEND LIBS ${XMRIG_ASM_LIBRARY})
|
||||||
|
add_definitions(-DXMRIG_FEATURE_ASM)
|
||||||
else()
|
else()
|
||||||
set(XMRIG_ASM_SOURCES "")
|
set(WITH_ASM OFF)
|
||||||
set(XMRIG_ASM_LIBRARY "")
|
|
||||||
|
|
||||||
remove_definitions(/DXMRIG_FEATURE_ASM)
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(XMRIG_64_BIT ON)
|
|
||||||
add_definitions(-DXMRIG_64_BIT)
|
|
||||||
else()
|
|
||||||
set(XMRIG_64_BIT OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT CMAKE_SYSTEM_PROCESSOR)
|
|
||||||
message(WARNING "CMAKE_SYSTEM_PROCESSOR not defined")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
|
||||||
set(VAES_SUPPORTED ON)
|
|
||||||
else()
|
|
||||||
CHECK_CXX_COMPILER_FLAG("-mavx2 -mvaes" VAES_SUPPORTED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT VAES_SUPPORTED)
|
|
||||||
set(WITH_VAES OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (XMRIG_64_BIT AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64)$")
|
|
||||||
add_definitions(-DRAPIDJSON_SSE2)
|
|
||||||
else()
|
|
||||||
set(WITH_SSE4_1 OFF)
|
|
||||||
set(WITH_AVX2 OFF)
|
|
||||||
set(WITH_VAES OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ARM_V8)
|
|
||||||
set(ARM_TARGET 8)
|
|
||||||
elseif (ARM_V7)
|
|
||||||
set(ARM_TARGET 7)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT ARM_TARGET)
|
|
||||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|armv8-a)$")
|
|
||||||
set(ARM_TARGET 8)
|
|
||||||
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7|armv7f|armv7s|armv7k|armv7-a|armv7l|armv7ve)$")
|
|
||||||
set(ARM_TARGET 7)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ARM_TARGET AND ARM_TARGET GREATER 6)
|
|
||||||
set(XMRIG_ARM ON)
|
|
||||||
add_definitions(-DXMRIG_ARM=${ARM_TARGET})
|
|
||||||
|
|
||||||
message(STATUS "Use ARM_TARGET=${ARM_TARGET} (${CMAKE_SYSTEM_PROCESSOR})")
|
|
||||||
|
|
||||||
if (ARM_TARGET EQUAL 8)
|
|
||||||
CHECK_CXX_COMPILER_FLAG(-march=armv8-a+crypto XMRIG_ARM_CRYPTO)
|
|
||||||
|
|
||||||
if (XMRIG_ARM_CRYPTO)
|
|
||||||
add_definitions(-DXMRIG_ARM_CRYPTO)
|
|
||||||
set(ARM8_CXX_FLAGS "-march=armv8-a+crypto")
|
|
||||||
else()
|
|
||||||
set(ARM8_CXX_FLAGS "-march=armv8-a")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_SSE4_1)
|
|
||||||
add_definitions(-DXMRIG_FEATURE_SSE4_1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_AVX2)
|
|
||||||
add_definitions(-DXMRIG_FEATURE_AVX2)
|
|
||||||
endif()
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
|
||||||
add_definitions(-DNDEBUG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(CheckSymbolExists)
|
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-strict-aliasing")
|
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast")
|
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexceptions -fno-rtti -Wno-strict-aliasing -Wno-class-memaccess")
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s")
|
|
||||||
|
|
||||||
if (ARM_TARGET EQUAL 8)
|
|
||||||
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_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mfpu=neon -flax-vector-conversions")
|
|
||||||
else()
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
|
|
||||||
|
|
||||||
add_definitions(-DHAVE_ROTR)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
|
||||||
else()
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -Wl,--large-address-aware")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (BUILD_STATIC)
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_definitions(-D_GNU_SOURCE -DHAVE_BUILTIN_CLEAR_CACHE)
|
|
||||||
|
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
|
||||||
set(CMAKE_C_FLAGS_RELEASE "/MP /MT /O2 /Oi /DNDEBUG /GL")
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "/MP /MT /O2 /Oi /DNDEBUG /GL")
|
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MP /Ob1 /Zi /DRELWITHDEBINFO")
|
|
||||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MP /Ob1 /Zi /DRELWITHDEBINFO")
|
|
||||||
|
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -DNOMINMAX -DHAVE_ROTR)
|
|
||||||
|
|
||||||
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_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")
|
|
||||||
|
|
||||||
if (ARM_TARGET EQUAL 8)
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARM8_CXX_FLAGS}")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARM8_CXX_FLAGS}")
|
|
||||||
elseif (ARM_TARGET EQUAL 7)
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}")
|
|
||||||
else()
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
|
|
||||||
|
|
||||||
check_symbol_exists("_rotr" "x86intrin.h" HAVE_ROTR)
|
|
||||||
if (HAVE_ROTR)
|
|
||||||
add_definitions(-DHAVE_ROTR)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (BUILD_STATIC)
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT WIN32)
|
|
||||||
check_symbol_exists("__builtin___clear_cache" "stdlib.h" HAVE_BUILTIN_CLEAR_CACHE)
|
|
||||||
if (HAVE_BUILTIN_CLEAR_CACHE)
|
|
||||||
add_definitions(-DHAVE_BUILTIN_CLEAR_CACHE)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: © 2023 Jean-Pierre De Jesus DIAZ <me@jeandudey.tech>
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
|
|
||||||
if(WITH_BUNDLED_FMT)
|
|
||||||
add_library(fmt INTERFACE)
|
|
||||||
target_sources(fmt INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src/3rdparty/fmt/format.cc)
|
|
||||||
target_include_directories(fmt INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src/3rdparty/fmt)
|
|
||||||
else()
|
|
||||||
set(FMT_LIBRARY fmt)
|
|
||||||
find_package(fmt REQUIRED)
|
|
||||||
set(FMT_LIBRARY fmt::fmt)
|
|
||||||
endif()
|
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
if (WITH_GHOSTRIDER)
|
if (WITH_GHOSTRIDER)
|
||||||
add_definitions(/DXMRIG_ALGO_GHOSTRIDER)
|
|
||||||
add_subdirectory(src/crypto/ghostrider)
|
add_subdirectory(src/crypto/ghostrider)
|
||||||
set(GHOSTRIDER_LIBRARY ghostrider)
|
list(APPEND LIBS ghostrider)
|
||||||
else()
|
|
||||||
remove_definitions(/DXMRIG_ALGO_GHOSTRIDER)
|
|
||||||
set(GHOSTRIDER_LIBRARY "")
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,19 +1,14 @@
|
|||||||
if (WITH_KAWPOW)
|
if (WITH_KAWPOW)
|
||||||
add_definitions(/DXMRIG_ALGO_KAWPOW)
|
list(APPEND HEADERS
|
||||||
|
|
||||||
list(APPEND HEADERS_CRYPTO
|
|
||||||
src/crypto/kawpow/KPCache.h
|
src/crypto/kawpow/KPCache.h
|
||||||
src/crypto/kawpow/KPHash.h
|
src/crypto/kawpow/KPHash.h
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES
|
||||||
src/crypto/kawpow/KPCache.cpp
|
src/crypto/kawpow/KPCache.cpp
|
||||||
src/crypto/kawpow/KPHash.cpp
|
src/crypto/kawpow/KPHash.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(src/3rdparty/libethash)
|
add_subdirectory(src/base/3rdparty/libethash)
|
||||||
set(ETHASH_LIBRARY ethash)
|
list(INSERT LIBS 0 ethash)
|
||||||
else()
|
|
||||||
remove_definitions(/DXMRIG_ALGO_KAWPOW)
|
|
||||||
set(ETHASH_LIBRARY "")
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
if (WIN32)
|
|
||||||
set(XMRIG_OS_WIN ON)
|
|
||||||
elseif (APPLE)
|
|
||||||
set(XMRIG_OS_APPLE ON)
|
|
||||||
|
|
||||||
if (IOS OR CMAKE_SYSTEM_NAME STREQUAL iOS)
|
|
||||||
set(XMRIG_OS_IOS ON)
|
|
||||||
else()
|
|
||||||
set(XMRIG_OS_MACOS ON)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(XMRIG_OS_UNIX ON)
|
|
||||||
|
|
||||||
if (ANDROID OR CMAKE_SYSTEM_NAME MATCHES "Android")
|
|
||||||
set(XMRIG_OS_ANDROID ON)
|
|
||||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
|
||||||
set(XMRIG_OS_LINUX ON)
|
|
||||||
elseif(CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL DragonFly)
|
|
||||||
set(XMRIG_OS_FREEBSD ON)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
if (XMRIG_OS_WIN)
|
|
||||||
add_definitions(-DWIN32 -DXMRIG_OS_WIN)
|
|
||||||
elseif(XMRIG_OS_APPLE)
|
|
||||||
add_definitions(-DXMRIG_OS_APPLE)
|
|
||||||
|
|
||||||
if (XMRIG_OS_IOS)
|
|
||||||
add_definitions(-DXMRIG_OS_IOS)
|
|
||||||
else()
|
|
||||||
add_definitions(-DXMRIG_OS_MACOS)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (XMRIG_ARM)
|
|
||||||
set(WITH_SECURE_JIT ON)
|
|
||||||
endif()
|
|
||||||
elseif(XMRIG_OS_UNIX)
|
|
||||||
add_definitions(-DXMRIG_OS_UNIX)
|
|
||||||
|
|
||||||
if (XMRIG_OS_ANDROID)
|
|
||||||
add_definitions(-DXMRIG_OS_ANDROID)
|
|
||||||
elseif (XMRIG_OS_LINUX)
|
|
||||||
add_definitions(-DXMRIG_OS_LINUX)
|
|
||||||
elseif (XMRIG_OS_FREEBSD)
|
|
||||||
add_definitions(-DXMRIG_OS_FREEBSD)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_SECURE_JIT)
|
|
||||||
add_definitions(-DXMRIG_SECURE_JIT)
|
|
||||||
endif()
|
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
if (WITH_RANDOMX)
|
if (WITH_RANDOMX)
|
||||||
add_definitions(/DXMRIG_ALGO_RANDOMX)
|
list(APPEND HEADERS
|
||||||
set(WITH_ARGON2 ON)
|
|
||||||
|
|
||||||
list(APPEND HEADERS_CRYPTO
|
|
||||||
src/crypto/rx/Rx.h
|
src/crypto/rx/Rx.h
|
||||||
src/crypto/rx/RxAlgo.h
|
src/crypto/rx/RxAlgo.h
|
||||||
src/crypto/rx/RxBasicStorage.h
|
src/crypto/rx/RxBasicStorage.h
|
||||||
@@ -14,7 +11,7 @@ if (WITH_RANDOMX)
|
|||||||
src/crypto/rx/RxVm.h
|
src/crypto/rx/RxVm.h
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES
|
||||||
src/crypto/randomx/aes_hash.cpp
|
src/crypto/randomx/aes_hash.cpp
|
||||||
src/crypto/randomx/allocator.cpp
|
src/crypto/randomx/allocator.cpp
|
||||||
src/crypto/randomx/blake2_generator.cpp
|
src/crypto/randomx/blake2_generator.cpp
|
||||||
@@ -44,19 +41,19 @@ if (WITH_RANDOMX)
|
|||||||
|
|
||||||
if (WITH_ASM AND CMAKE_C_COMPILER_ID MATCHES MSVC)
|
if (WITH_ASM AND CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||||
enable_language(ASM_MASM)
|
enable_language(ASM_MASM)
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES
|
||||||
src/crypto/randomx/jit_compiler_x86_static.asm
|
src/crypto/randomx/jit_compiler_x86_static.asm
|
||||||
src/crypto/randomx/jit_compiler_x86.cpp
|
src/crypto/randomx/jit_compiler_x86.cpp
|
||||||
)
|
)
|
||||||
elseif (WITH_ASM AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
elseif (WITH_ASM AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES
|
||||||
src/crypto/randomx/jit_compiler_x86_static.S
|
src/crypto/randomx/jit_compiler_x86_static.S
|
||||||
src/crypto/randomx/jit_compiler_x86.cpp
|
src/crypto/randomx/jit_compiler_x86.cpp
|
||||||
)
|
)
|
||||||
# cheat because cmake and ccache hate each other
|
# cheat because cmake and ccache hate each other
|
||||||
set_property(SOURCE src/crypto/randomx/jit_compiler_x86_static.S PROPERTY LANGUAGE C)
|
set_property(SOURCE src/crypto/randomx/jit_compiler_x86_static.S PROPERTY LANGUAGE C)
|
||||||
elseif (XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
elseif (XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES
|
||||||
src/crypto/randomx/jit_compiler_a64_static.S
|
src/crypto/randomx/jit_compiler_a64_static.S
|
||||||
src/crypto/randomx/jit_compiler_a64.cpp
|
src/crypto/randomx/jit_compiler_a64.cpp
|
||||||
)
|
)
|
||||||
@@ -67,13 +64,11 @@ if (WITH_RANDOMX)
|
|||||||
set_property(SOURCE src/crypto/randomx/jit_compiler_a64_static.S PROPERTY LANGUAGE C)
|
set_property(SOURCE src/crypto/randomx/jit_compiler_a64_static.S PROPERTY LANGUAGE C)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES src/crypto/randomx/jit_compiler_fallback.cpp)
|
||||||
src/crypto/randomx/jit_compiler_fallback.cpp
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_SSE4_1)
|
if (WITH_SSE4_1)
|
||||||
list(APPEND SOURCES_CRYPTO src/crypto/randomx/blake2/blake2b_sse41.c)
|
list(APPEND SOURCES src/crypto/randomx/blake2/blake2b_sse41.c)
|
||||||
|
|
||||||
if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES Clang)
|
if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES Clang)
|
||||||
set_source_files_properties(src/crypto/randomx/blake2/blake2b_sse41.c PROPERTIES COMPILE_FLAGS "-Ofast -msse4.1")
|
set_source_files_properties(src/crypto/randomx/blake2/blake2b_sse41.c PROPERTIES COMPILE_FLAGS "-Ofast -msse4.1")
|
||||||
@@ -81,7 +76,7 @@ if (WITH_RANDOMX)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_AVX2)
|
if (WITH_AVX2)
|
||||||
list(APPEND SOURCES_CRYPTO src/crypto/randomx/blake2/avx2/blake2b_avx2.c)
|
list(APPEND SOURCES src/crypto/randomx/blake2/avx2/blake2b_avx2.c)
|
||||||
|
|
||||||
if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES Clang)
|
if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES Clang)
|
||||||
set_source_files_properties(src/crypto/randomx/blake2/avx2/blake2b_avx2.c PROPERTIES COMPILE_FLAGS "-Ofast -mavx2")
|
set_source_files_properties(src/crypto/randomx/blake2/avx2/blake2b_avx2.c PROPERTIES COMPILE_FLAGS "-Ofast -mavx2")
|
||||||
@@ -93,56 +88,49 @@ if (WITH_RANDOMX)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_HWLOC)
|
if (WITH_HWLOC)
|
||||||
list(APPEND HEADERS_CRYPTO
|
list(APPEND HEADERS src/crypto/rx/RxNUMAStorage.h)
|
||||||
src/crypto/rx/RxNUMAStorage.h
|
list(APPEND SOURCES src/crypto/rx/RxNUMAStorage.cpp)
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND SOURCES_CRYPTO
|
|
||||||
src/crypto/rx/RxNUMAStorage.cpp
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_MSR AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8 AND (XMRIG_OS_WIN OR XMRIG_OS_LINUX))
|
if (WITH_MSR AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8 AND (XMRIG_OS_WIN OR XMRIG_OS_LINUX))
|
||||||
add_definitions(/DXMRIG_FEATURE_MSR)
|
add_definitions(-DXMRIG_FEATURE_MSR -DXMRIG_FIX_RYZEN)
|
||||||
add_definitions(/DXMRIG_FIX_RYZEN)
|
|
||||||
message("-- WITH_MSR=ON")
|
|
||||||
|
|
||||||
if (XMRIG_OS_WIN)
|
if (XMRIG_OS_WIN)
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES
|
||||||
src/crypto/rx/RxFix_win.cpp
|
src/crypto/rx/RxFix_win.cpp
|
||||||
src/hw/msr/Msr_win.cpp
|
src/hw/msr/Msr_win.cpp
|
||||||
)
|
)
|
||||||
elseif (XMRIG_OS_LINUX)
|
elseif (XMRIG_OS_LINUX)
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES
|
||||||
src/crypto/rx/RxFix_linux.cpp
|
src/crypto/rx/RxFix_linux.cpp
|
||||||
src/hw/msr/Msr_linux.cpp
|
src/hw/msr/Msr_linux.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND HEADERS_CRYPTO
|
list(APPEND HEADERS
|
||||||
src/crypto/rx/RxFix.h
|
src/crypto/rx/RxFix.h
|
||||||
src/crypto/rx/RxMsr.h
|
src/crypto/rx/RxMsr.h
|
||||||
src/hw/msr/Msr.h
|
src/hw/msr/Msr.h
|
||||||
src/hw/msr/MsrItem.h
|
src/hw/msr/MsrItem.h
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND SOURCES_CRYPTO
|
list(APPEND SOURCES
|
||||||
src/crypto/rx/RxMsr.cpp
|
src/crypto/rx/RxMsr.cpp
|
||||||
src/hw/msr/Msr.cpp
|
src/hw/msr/Msr.cpp
|
||||||
src/hw/msr/MsrItem.cpp
|
src/hw/msr/MsrItem.cpp
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
remove_definitions(/DXMRIG_FEATURE_MSR)
|
set(WITH_MSR OFF)
|
||||||
remove_definitions(/DXMRIG_FIX_RYZEN)
|
|
||||||
message("-- WITH_MSR=OFF")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_PROFILING)
|
if (WITH_PROFILING)
|
||||||
add_definitions(/DXMRIG_FEATURE_PROFILING)
|
add_definitions(-DXMRIG_FEATURE_PROFILING)
|
||||||
|
|
||||||
list(APPEND HEADERS_CRYPTO src/crypto/rx/Profiler.h)
|
list(APPEND HEADERS src/crypto/rx/Profiler.h)
|
||||||
list(APPEND SOURCES_CRYPTO src/crypto/rx/Profiler.cpp)
|
list(APPEND SOURCES src/crypto/rx/Profiler.cpp)
|
||||||
endif()
|
endif()
|
||||||
else()
|
|
||||||
remove_definitions(/DXMRIG_ALGO_RANDOMX)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
message(STATUS "WITH_MSR \t= ${WITH_MSR}")
|
||||||
|
message(STATUS "WITH_PROFILING \t= ${WITH_PROFILING}")
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ Option `coin` useful for pools without [algorithm negotiation](https://xmrig.com
|
|||||||
| Name | Memory | Version | Description | Notes |
|
| Name | Memory | Version | Description | Notes |
|
||||||
|------|--------|---------|-------------|-------|
|
|------|--------|---------|-------------|-------|
|
||||||
| `kawpow` | - | 6.0.0+ | KawPow (Ravencoin) | GPU only |
|
| `kawpow` | - | 6.0.0+ | KawPow (Ravencoin) | GPU only |
|
||||||
|
| `rx/keva` | 1 MB | 5.9.0+ | RandomKEVA (RandomX variant for Keva). | |
|
||||||
| `astrobwt` | 20 MB | 5.8.0+ | AstroBWT (Dero). | |
|
| `astrobwt` | 20 MB | 5.8.0+ | AstroBWT (Dero). | |
|
||||||
| `cn-pico/tlo` | 256 KB | 5.5.0+ | CryptoNight-Pico (Talleo). | |
|
| `cn-pico/tlo` | 256 KB | 5.5.0+ | CryptoNight-Pico (Talleo). | |
|
||||||
| `rx/sfx` | 2 MB | 5.4.0+ | RandomSFX (RandomX variant for Safex). | |
|
| `rx/sfx` | 2 MB | 5.4.0+ | RandomSFX (RandomX variant for Safex). | |
|
||||||
|
|||||||
@@ -256,7 +256,7 @@
|
|||||||
|
|
||||||
# v2.8.0
|
# v2.8.0
|
||||||
- **[#753](https://github.com/xmrig/xmrig/issues/753) Added new algorithm [CryptoNight variant 2](https://github.com/xmrig/xmrig/issues/753) for Monero fork, thanks [@SChernykh](https://github.com/SChernykh).**
|
- **[#753](https://github.com/xmrig/xmrig/issues/753) Added new algorithm [CryptoNight variant 2](https://github.com/xmrig/xmrig/issues/753) for Monero fork, thanks [@SChernykh](https://github.com/SChernykh).**
|
||||||
- Added global and per thread option `"asm"` and command line equivalent.
|
- Added global and per thread option `"asm"` and and command line equivalent.
|
||||||
- **[#758](https://github.com/xmrig/xmrig/issues/758) Added SSL/TLS support for secure connections to pools.**
|
- **[#758](https://github.com/xmrig/xmrig/issues/758) Added SSL/TLS support for secure connections to pools.**
|
||||||
- Added per pool options `"tls"` and `"tls-fingerprint"` and command line equivalents.
|
- Added per pool options `"tls"` and `"tls-fingerprint"` and command line equivalents.
|
||||||
- [#767](https://github.com/xmrig/xmrig/issues/767) Added config autosave feature, same with GPU miners.
|
- [#767](https://github.com/xmrig/xmrig/issues/767) Added config autosave feature, same with GPU miners.
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ VS_VERSION_INFO VERSIONINFO
|
|||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "000004b0"
|
BLOCK "000004b0"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", APP_SITE
|
VALUE "CompanyName", APP_DOMAIN
|
||||||
VALUE "FileDescription", APP_DESC
|
VALUE "FileDescription", APP_DESC
|
||||||
VALUE "FileVersion", APP_VERSION
|
VALUE "FileVersion", APP_VERSION
|
||||||
VALUE "LegalCopyright", APP_COPYRIGHT
|
VALUE "LegalCopyright", APP_COPYRIGHT
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@echo off
|
@echo off
|
||||||
cd /d "%~dp0"
|
cd %~dp0
|
||||||
xmrig.exe --bench=10M --submit
|
xmrig.exe --bench=10M --submit
|
||||||
pause
|
pause
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@echo off
|
@echo off
|
||||||
cd /d "%~dp0"
|
cd %~dp0
|
||||||
xmrig.exe --bench=1M --submit
|
xmrig.exe --bench=1M --submit
|
||||||
pause
|
pause
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
HWLOC_VERSION_MAJOR="2"
|
HWLOC_VERSION_MAJOR="2"
|
||||||
HWLOC_VERSION_MINOR="11"
|
HWLOC_VERSION_MINOR="7"
|
||||||
HWLOC_VERSION_PATCH="2"
|
HWLOC_VERSION_PATCH="1"
|
||||||
|
|
||||||
HWLOC_VERSION="${HWLOC_VERSION_MAJOR}.${HWLOC_VERSION_MINOR}.${HWLOC_VERSION_PATCH}"
|
HWLOC_VERSION="${HWLOC_VERSION_MAJOR}.${HWLOC_VERSION_MINOR}.${HWLOC_VERSION_PATCH}"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
HWLOC_VERSION="1.11.13"
|
HWLOC_VERSION="1.11.13"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
LIBRESSL_VERSION="3.5.2"
|
LIBRESSL_VERSION="3.5.2"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
OPENSSL_VERSION="1.1.1u"
|
OPENSSL_VERSION="1.1.1o"
|
||||||
|
|
||||||
mkdir -p deps
|
mkdir -p deps
|
||||||
mkdir -p deps/include
|
mkdir -p deps/include
|
||||||
@@ -8,7 +8,7 @@ mkdir -p deps/lib
|
|||||||
|
|
||||||
mkdir -p build && cd build
|
mkdir -p build && cd build
|
||||||
|
|
||||||
wget https://openssl.org/source/old/1.1.1/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz
|
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz
|
||||||
tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
|
tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
|
||||||
|
|
||||||
cd openssl-${OPENSSL_VERSION}
|
cd openssl-${OPENSSL_VERSION}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
OPENSSL_VERSION="3.0.15"
|
OPENSSL_VERSION="3.0.3"
|
||||||
|
|
||||||
mkdir -p deps
|
mkdir -p deps
|
||||||
mkdir -p deps/include
|
mkdir -p deps/include
|
||||||
@@ -8,7 +8,7 @@ mkdir -p deps/lib
|
|||||||
|
|
||||||
mkdir -p build && cd build
|
mkdir -p build && cd build
|
||||||
|
|
||||||
wget https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_VERSION}/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz
|
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz
|
||||||
tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
|
tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
|
||||||
|
|
||||||
cd openssl-${OPENSSL_VERSION}
|
cd openssl-${OPENSSL_VERSION}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
UV_VERSION="1.49.2"
|
UV_VERSION="1.44.1"
|
||||||
|
|
||||||
mkdir -p deps
|
mkdir -p deps
|
||||||
mkdir -p deps/include
|
mkdir -p deps/include
|
||||||
@@ -8,10 +8,10 @@ mkdir -p deps/lib
|
|||||||
|
|
||||||
mkdir -p build && cd build
|
mkdir -p build && cd build
|
||||||
|
|
||||||
wget https://dist.libuv.org/dist/v${UV_VERSION}/libuv-v${UV_VERSION}.tar.gz -O v${UV_VERSION}.tar.gz
|
wget https://github.com/libuv/libuv/archive/v${UV_VERSION}.tar.gz -O v${UV_VERSION}.tar.gz
|
||||||
tar -xzf v${UV_VERSION}.tar.gz
|
tar -xzf v${UV_VERSION}.tar.gz
|
||||||
|
|
||||||
cd libuv-v${UV_VERSION}
|
cd libuv-${UV_VERSION}
|
||||||
sh autogen.sh
|
sh autogen.sh
|
||||||
./configure --disable-shared
|
./configure --disable-shared
|
||||||
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
|
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
./build.uv.sh
|
./build.uv.sh
|
||||||
./build.hwloc.sh
|
./build.hwloc.sh
|
||||||
./build.openssl3.sh
|
./build.openssl.sh
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
# https://xmrig.com/docs/miner/hugepages#onegb-huge-pages
|
# https://xmrig.com/docs/miner/hugepages#onegb-huge-pages
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ function rx()
|
|||||||
'randomx_constants_monero.h',
|
'randomx_constants_monero.h',
|
||||||
'randomx_constants_wow.h',
|
'randomx_constants_wow.h',
|
||||||
'randomx_constants_arqma.h',
|
'randomx_constants_arqma.h',
|
||||||
|
'randomx_constants_keva.h',
|
||||||
'randomx_constants_graft.h',
|
'randomx_constants_graft.h',
|
||||||
'aes.cl',
|
'aes.cl',
|
||||||
'blake2b.cl',
|
'blake2b.cl',
|
||||||
|
|||||||
@@ -15,6 +15,6 @@
|
|||||||
:: Choose pools outside of top 5 to help Monero network be more decentralized!
|
:: Choose pools outside of top 5 to help Monero network be more decentralized!
|
||||||
:: Smaller pools also often have smaller fees/payout limits.
|
:: Smaller pools also often have smaller fees/payout limits.
|
||||||
|
|
||||||
cd /d "%~dp0"
|
cd %~dp0
|
||||||
xmrig.exe -o xmrpool.eu:3333 -u 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD -p x
|
xmrig.exe -o pool.hashvault.pro:3333 -u 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD -p x
|
||||||
pause
|
pause
|
||||||
|
|||||||
@@ -8,34 +8,16 @@ else
|
|||||||
modprobe msr allow_writes=on
|
modprobe msr allow_writes=on
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if grep -E 'AMD Ryzen|AMD EPYC|AuthenticAMD' /proc/cpuinfo > /dev/null;
|
if grep -E 'AMD Ryzen|AMD EPYC' /proc/cpuinfo > /dev/null;
|
||||||
then
|
then
|
||||||
if grep "cpu family[[:space:]]\{1,\}:[[:space:]]25" /proc/cpuinfo > /dev/null;
|
if grep "cpu family[[:space:]]:[[:space:]]25" /proc/cpuinfo > /dev/null;
|
||||||
then
|
then
|
||||||
if grep "model[[:space:]]\{1,\}:[[:space:]]97" /proc/cpuinfo > /dev/null;
|
echo "Detected Zen3 CPU"
|
||||||
then
|
wrmsr -a 0xc0011020 0x4480000000000
|
||||||
echo "Detected Zen4 CPU"
|
wrmsr -a 0xc0011021 0x1c000200000040
|
||||||
wrmsr -a 0xc0011020 0x4400000000000
|
wrmsr -a 0xc0011022 0xc000000401500000
|
||||||
wrmsr -a 0xc0011021 0x4000000000040
|
wrmsr -a 0xc001102b 0x2000cc14
|
||||||
wrmsr -a 0xc0011022 0x8680000401570000
|
echo "MSR register values for Zen3 applied"
|
||||||
wrmsr -a 0xc001102b 0x2040cc10
|
|
||||||
echo "MSR register values for Zen4 applied"
|
|
||||||
else
|
|
||||||
echo "Detected Zen3 CPU"
|
|
||||||
wrmsr -a 0xc0011020 0x4480000000000
|
|
||||||
wrmsr -a 0xc0011021 0x1c000200000040
|
|
||||||
wrmsr -a 0xc0011022 0xc000000401570000
|
|
||||||
wrmsr -a 0xc001102b 0x2000cc10
|
|
||||||
echo "MSR register values for Zen3 applied"
|
|
||||||
fi
|
|
||||||
elif grep "cpu family[[:space:]]\{1,\}:[[:space:]]26" /proc/cpuinfo > /dev/null;
|
|
||||||
then
|
|
||||||
echo "Detected Zen5 CPU"
|
|
||||||
wrmsr -a 0xc0011020 0x4400000000000
|
|
||||||
wrmsr -a 0xc0011021 0x4000000000040
|
|
||||||
wrmsr -a 0xc0011022 0x8680000401570000
|
|
||||||
wrmsr -a 0xc001102b 0x2040cc10
|
|
||||||
echo "MSR register values for Zen5 applied"
|
|
||||||
else
|
else
|
||||||
echo "Detected Zen1/Zen2 CPU"
|
echo "Detected Zen1/Zen2 CPU"
|
||||||
wrmsr -a 0xc0011020 0
|
wrmsr -a 0xc0011020 0
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
:: Choose pools outside of top 5 to help Raptoreum network be more decentralized!
|
:: Choose pools outside of top 5 to help Raptoreum network be more decentralized!
|
||||||
:: Smaller pools also often have smaller fees/payout limits.
|
:: Smaller pools also often have smaller fees/payout limits.
|
||||||
|
|
||||||
cd /d "%~dp0"
|
cd %~dp0
|
||||||
:: Use this command line to connect to non-SSL port
|
:: Use this command line to connect to non-SSL port
|
||||||
xmrig.exe -a gr -o raptoreumemporium.com:3008 -u WALLET_ADDRESS -p x
|
xmrig.exe -a gr -o raptoreumemporium.com:3008 -u WALLET_ADDRESS -p x
|
||||||
:: Or use this command line to connect to an SSL port
|
:: Or use this command line to connect to an SSL port
|
||||||
|
|||||||
@@ -11,6 +11,6 @@
|
|||||||
:: Mining solo is the best way to help Monero network be more decentralized!
|
:: Mining solo is the best way to help Monero network be more decentralized!
|
||||||
:: But you will only get a payout when you find a block which can take more than a year for a single low-end PC.
|
:: But you will only get a payout when you find a block which can take more than a year for a single low-end PC.
|
||||||
|
|
||||||
cd /d "%~dp0"
|
cd %~dp0
|
||||||
xmrig.exe -o YOUR_NODE_IP:18081 -a rx/0 -u 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD --daemon
|
xmrig.exe -o node.xmr.to:18081 -a rx/0 -u 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD --daemon
|
||||||
pause
|
pause
|
||||||
|
|||||||
2
src/3rdparty/argon2/CMakeLists.txt
vendored
2
src/3rdparty/argon2/CMakeLists.txt
vendored
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
project(argon2 C)
|
project(argon2 C)
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|||||||
2
src/3rdparty/cl.h
vendored
2
src/3rdparty/cl.h
vendored
@@ -29,7 +29,7 @@
|
|||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
# include <OpenCL/cl.h>
|
# include <OpenCL/cl.h>
|
||||||
#else
|
#else
|
||||||
# include <CL/cl.h>
|
# include "3rdparty/CL/cl.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
25
src/3rdparty/epee/LICENSE.txt
vendored
25
src/3rdparty/epee/LICENSE.txt
vendored
@@ -1,25 +0,0 @@
|
|||||||
Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the Andrey N. Sabelnikov nor the
|
|
||||||
names of its contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL Andrey N. Sabelnikov BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
1
src/3rdparty/epee/README.md
vendored
1
src/3rdparty/epee/README.md
vendored
@@ -1 +0,0 @@
|
|||||||
epee - is a small library of helpers, wrappers, tools and so on, used to make my life easier.
|
|
||||||
176
src/3rdparty/epee/span.h
vendored
176
src/3rdparty/epee/span.h
vendored
@@ -1,176 +0,0 @@
|
|||||||
// Copyright (c) 2017-2020, The Monero Project
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other
|
|
||||||
// materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
|
||||||
// used to endorse or promote products derived from this software without specific
|
|
||||||
// prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
||||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace epee
|
|
||||||
{
|
|
||||||
/*!
|
|
||||||
\brief Non-owning sequence of data. Does not deep copy
|
|
||||||
|
|
||||||
Inspired by `gsl::span` and/or `boost::iterator_range`. This class is
|
|
||||||
intended to be used as a parameter type for functions that need to take a
|
|
||||||
writable or read-only sequence of data. Most common cases are `span<char>`
|
|
||||||
and `span<std::uint8_t>`. Using as a class member is only recommended if
|
|
||||||
clearly documented as not doing a deep-copy. C-arrays are easily convertible
|
|
||||||
to this type.
|
|
||||||
|
|
||||||
\note Conversion from C string literal to `span<const char>` will include
|
|
||||||
the NULL-terminator.
|
|
||||||
\note Never allows derived-to-base pointer conversion; an array of derived
|
|
||||||
types is not an array of base types.
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
class span
|
|
||||||
{
|
|
||||||
template<typename U>
|
|
||||||
static constexpr bool safe_conversion() noexcept
|
|
||||||
{
|
|
||||||
// Allow exact matches or `T*` -> `const T*`.
|
|
||||||
using with_const = typename std::add_const<U>::type;
|
|
||||||
return std::is_same<T, U>() ||
|
|
||||||
(std::is_const<T>() && std::is_same<T, with_const>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = T;
|
|
||||||
using size_type = std::size_t;
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using pointer = T*;
|
|
||||||
using const_pointer = const T*;
|
|
||||||
using reference = T&;
|
|
||||||
using const_reference = const T&;
|
|
||||||
using iterator = pointer;
|
|
||||||
using const_iterator = const_pointer;
|
|
||||||
|
|
||||||
constexpr span() noexcept : ptr(nullptr), len(0) {}
|
|
||||||
constexpr span(std::nullptr_t) noexcept : span() {}
|
|
||||||
|
|
||||||
//! Prevent derived-to-base conversions; invalid in this context.
|
|
||||||
template<typename U, typename = typename std::enable_if<safe_conversion<U>()>::type>
|
|
||||||
constexpr span(U* const src_ptr, const std::size_t count) noexcept
|
|
||||||
: ptr(src_ptr), len(count) {}
|
|
||||||
|
|
||||||
//! Conversion from C-array. Prevents common bugs with sizeof + arrays.
|
|
||||||
template<std::size_t N>
|
|
||||||
constexpr span(T (&src)[N]) noexcept : span(src, N) {}
|
|
||||||
|
|
||||||
constexpr span(const span&) noexcept = default;
|
|
||||||
span& operator=(const span&) noexcept = default;
|
|
||||||
|
|
||||||
/*! Try to remove `amount` elements from beginning of span.
|
|
||||||
\return Number of elements removed. */
|
|
||||||
std::size_t remove_prefix(std::size_t amount) noexcept
|
|
||||||
{
|
|
||||||
amount = std::min(len, amount);
|
|
||||||
ptr += amount;
|
|
||||||
len -= amount;
|
|
||||||
return amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr iterator begin() const noexcept { return ptr; }
|
|
||||||
constexpr const_iterator cbegin() const noexcept { return ptr; }
|
|
||||||
|
|
||||||
constexpr iterator end() const noexcept { return begin() + size(); }
|
|
||||||
constexpr const_iterator cend() const noexcept { return cbegin() + size(); }
|
|
||||||
|
|
||||||
constexpr bool empty() const noexcept { return size() == 0; }
|
|
||||||
constexpr pointer data() const noexcept { return ptr; }
|
|
||||||
constexpr std::size_t size() const noexcept { return len; }
|
|
||||||
constexpr std::size_t size_bytes() const noexcept { return size() * sizeof(value_type); }
|
|
||||||
|
|
||||||
T &operator[](size_t idx) noexcept { return ptr[idx]; }
|
|
||||||
const T &operator[](size_t idx) const noexcept { return ptr[idx]; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
T* ptr;
|
|
||||||
std::size_t len;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \return `span<const T::value_type>` from a STL compatible `src`.
|
|
||||||
template<typename T>
|
|
||||||
constexpr span<const typename T::value_type> to_span(const T& src)
|
|
||||||
{
|
|
||||||
// compiler provides diagnostic if size() is not size_t.
|
|
||||||
return {src.data(), src.size()};
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \return `span<T::value_type>` from a STL compatible `src`.
|
|
||||||
template<typename T>
|
|
||||||
constexpr span<typename T::value_type> to_mut_span(T& src)
|
|
||||||
{
|
|
||||||
// compiler provides diagnostic if size() is not size_t.
|
|
||||||
return {src.data(), src.size()};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr bool has_padding() noexcept
|
|
||||||
{
|
|
||||||
return !std::is_standard_layout<T>() || alignof(T) != 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \return Cast data from `src` as `span<const std::uint8_t>`.
|
|
||||||
template<typename T>
|
|
||||||
span<const std::uint8_t> to_byte_span(const span<const T> src) noexcept
|
|
||||||
{
|
|
||||||
static_assert(!has_padding<T>(), "source type may have padding");
|
|
||||||
return {reinterpret_cast<const std::uint8_t*>(src.data()), src.size_bytes()};
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \return `span<const std::uint8_t>` which represents the bytes at `&src`.
|
|
||||||
template<typename T>
|
|
||||||
span<const std::uint8_t> as_byte_span(const T& src) noexcept
|
|
||||||
{
|
|
||||||
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
|
|
||||||
static_assert(!has_padding<T>(), "source type may have padding");
|
|
||||||
return {reinterpret_cast<const std::uint8_t*>(std::addressof(src)), sizeof(T)};
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \return `span<std::uint8_t>` which represents the bytes at `&src`.
|
|
||||||
template<typename T>
|
|
||||||
span<std::uint8_t> as_mut_byte_span(T& src) noexcept
|
|
||||||
{
|
|
||||||
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
|
|
||||||
static_assert(!has_padding<T>(), "source type may have padding");
|
|
||||||
return {reinterpret_cast<std::uint8_t*>(std::addressof(src)), sizeof(T)};
|
|
||||||
}
|
|
||||||
|
|
||||||
//! make a span from a std::string
|
|
||||||
template<typename T>
|
|
||||||
span<const T> strspan(const std::string &s) noexcept
|
|
||||||
{
|
|
||||||
static_assert(std::is_same<T, char>() || std::is_same<T, unsigned char>() || std::is_same<T, int8_t>() || std::is_same<T, uint8_t>(), "Unexpected type");
|
|
||||||
return {reinterpret_cast<const T*>(s.data()), s.size()};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
27
src/3rdparty/fmt/fmt/LICENSE.rst
vendored
27
src/3rdparty/fmt/fmt/LICENSE.rst
vendored
@@ -1,27 +0,0 @@
|
|||||||
Copyright (c) 2012 - present, Victor Zverovich
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
--- Optional exception to the license ---
|
|
||||||
|
|
||||||
As an exception, if, as a result of your compiling your source code, portions
|
|
||||||
of this Software are embedded into a machine-executable object form of such
|
|
||||||
source code, you may redistribute such embedded portions in such object form
|
|
||||||
without including the above copyright and permission notices.
|
|
||||||
505
src/3rdparty/fmt/fmt/README.rst
vendored
505
src/3rdparty/fmt/fmt/README.rst
vendored
@@ -1,505 +0,0 @@
|
|||||||
{fmt}
|
|
||||||
=====
|
|
||||||
|
|
||||||
.. image:: https://travis-ci.org/fmtlib/fmt.png?branch=master
|
|
||||||
:target: https://travis-ci.org/fmtlib/fmt
|
|
||||||
|
|
||||||
.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v
|
|
||||||
:target: https://ci.appveyor.com/project/vitaut/fmt
|
|
||||||
|
|
||||||
.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/libfmt.svg
|
|
||||||
:alt: fmt is continuously fuzzed at oss-fuzz
|
|
||||||
:target: https://bugs.chromium.org/p/oss-fuzz/issues/list?\
|
|
||||||
colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20\
|
|
||||||
Summary&q=proj%3Dlibfmt&can=1
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg
|
|
||||||
:alt: Ask questions at StackOverflow with the tag fmt
|
|
||||||
:target: https://stackoverflow.com/questions/tagged/fmt
|
|
||||||
|
|
||||||
**{fmt}** is an open-source formatting library providing a fast and safe
|
|
||||||
alternative to C stdio and C++ iostreams.
|
|
||||||
|
|
||||||
If you like this project, please consider donating to BYSOL,
|
|
||||||
an initiative to help victims of political repressions in Belarus:
|
|
||||||
https://www.facebook.com/donate/759400044849707/108388587646909/.
|
|
||||||
|
|
||||||
`Documentation <https://fmt.dev>`__
|
|
||||||
|
|
||||||
Q&A: ask questions on `StackOverflow with the tag fmt
|
|
||||||
<https://stackoverflow.com/questions/tagged/fmt>`_.
|
|
||||||
|
|
||||||
Try {fmt} in `Compiler Explorer <https://godbolt.org/z/Eq5763>`_.
|
|
||||||
|
|
||||||
Features
|
|
||||||
--------
|
|
||||||
|
|
||||||
* Simple `format API <https://fmt.dev/latest/api.html>`_ with positional arguments
|
|
||||||
for localization
|
|
||||||
* Implementation of `C++20 std::format
|
|
||||||
<https://en.cppreference.com/w/cpp/utility/format>`__
|
|
||||||
* `Format string syntax <https://fmt.dev/latest/syntax.html>`_ similar to Python's
|
|
||||||
`format <https://docs.python.org/3/library/stdtypes.html#str.format>`_
|
|
||||||
* Fast IEEE 754 floating-point formatter with correct rounding, shortness and
|
|
||||||
round-trip guarantees.
|
|
||||||
* Safe `printf implementation
|
|
||||||
<https://fmt.dev/latest/api.html#printf-formatting>`_ including the POSIX
|
|
||||||
extension for positional arguments
|
|
||||||
* Extensibility: `support for user-defined types
|
|
||||||
<https://fmt.dev/latest/api.html#formatting-user-defined-types>`_
|
|
||||||
* High performance: faster than common standard library implementations of
|
|
||||||
``(s)printf``, iostreams, ``to_string`` and ``to_chars``, see `Speed tests`_
|
|
||||||
and `Converting a hundred million integers to strings per second
|
|
||||||
<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_
|
|
||||||
* Small code size both in terms of source code with the minimum configuration
|
|
||||||
consisting of just three files, ``core.h``, ``format.h`` and ``format-inl.h``,
|
|
||||||
and compiled code; see `Compile time and code bloat`_
|
|
||||||
* Reliability: the library has an extensive set of `tests
|
|
||||||
<https://github.com/fmtlib/fmt/tree/master/test>`_ and is `continuously fuzzed
|
|
||||||
<https://bugs.chromium.org/p/oss-fuzz/issues/list?colspec=ID%20Type%20
|
|
||||||
Component%20Status%20Proj%20Reported%20Owner%20Summary&q=proj%3Dlibfmt&can=1>`_
|
|
||||||
* Safety: the library is fully type safe, errors in format strings can be
|
|
||||||
reported at compile time, automatic memory management prevents buffer overflow
|
|
||||||
errors
|
|
||||||
* Ease of use: small self-contained code base, no external dependencies,
|
|
||||||
permissive MIT `license
|
|
||||||
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_
|
|
||||||
* `Portability <https://fmt.dev/latest/index.html#portability>`_ with
|
|
||||||
consistent output across platforms and support for older compilers
|
|
||||||
* Clean warning-free codebase even on high warning levels such as
|
|
||||||
``-Wall -Wextra -pedantic``
|
|
||||||
* Locale-independence by default
|
|
||||||
* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro
|
|
||||||
|
|
||||||
See the `documentation <https://fmt.dev>`_ for more details.
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
**Print to stdout** (`run <https://godbolt.org/z/Tevcjh>`_)
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
#include <fmt/core.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
fmt::print("Hello, world!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
**Format a string** (`run <https://godbolt.org/z/oK8h33>`_)
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
std::string s = fmt::format("The answer is {}.", 42);
|
|
||||||
// s == "The answer is 42."
|
|
||||||
|
|
||||||
**Format a string using positional arguments** (`run <https://godbolt.org/z/Yn7Txe>`_)
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
|
|
||||||
// s == "I'd rather be happy than right."
|
|
||||||
|
|
||||||
**Print chrono durations** (`run <https://godbolt.org/z/K8s4Mc>`_)
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
#include <fmt/chrono.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
using namespace std::literals::chrono_literals;
|
|
||||||
fmt::print("Default format: {} {}\n", 42s, 100ms);
|
|
||||||
fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
|
|
||||||
}
|
|
||||||
|
|
||||||
Output::
|
|
||||||
|
|
||||||
Default format: 42s 100ms
|
|
||||||
strftime-like format: 03:15:30
|
|
||||||
|
|
||||||
**Print a container** (`run <https://godbolt.org/z/MjsY7c>`_)
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <fmt/ranges.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
std::vector<int> v = {1, 2, 3};
|
|
||||||
fmt::print("{}\n", v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Output::
|
|
||||||
|
|
||||||
{1, 2, 3}
|
|
||||||
|
|
||||||
**Check a format string at compile time**
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
std::string s = fmt::format(FMT_STRING("{:d}"), "don't panic");
|
|
||||||
|
|
||||||
This gives a compile-time error because ``d`` is an invalid format specifier for
|
|
||||||
a string.
|
|
||||||
|
|
||||||
**Write a file from a single thread**
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
#include <fmt/os.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
auto out = fmt::output_file("guide.txt");
|
|
||||||
out.print("Don't {}", "Panic");
|
|
||||||
}
|
|
||||||
|
|
||||||
This can be `5 to 9 times faster than fprintf
|
|
||||||
<http://www.zverovich.net/2020/08/04/optimal-file-buffer-size.html>`_.
|
|
||||||
|
|
||||||
**Print with colors and text styles**
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
#include <fmt/color.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold,
|
|
||||||
"Hello, {}!\n", "world");
|
|
||||||
fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) |
|
|
||||||
fmt::emphasis::underline, "Hello, {}!\n", "мир");
|
|
||||||
fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic,
|
|
||||||
"Hello, {}!\n", "世界");
|
|
||||||
}
|
|
||||||
|
|
||||||
Output on a modern terminal:
|
|
||||||
|
|
||||||
.. image:: https://user-images.githubusercontent.com/
|
|
||||||
576385/88485597-d312f600-cf2b-11ea-9cbe-61f535a86e28.png
|
|
||||||
|
|
||||||
Benchmarks
|
|
||||||
----------
|
|
||||||
|
|
||||||
Speed tests
|
|
||||||
~~~~~~~~~~~
|
|
||||||
|
|
||||||
================= ============= ===========
|
|
||||||
Library Method Run Time, s
|
|
||||||
================= ============= ===========
|
|
||||||
libc printf 1.04
|
|
||||||
libc++ std::ostream 3.05
|
|
||||||
{fmt} 6.1.1 fmt::print 0.75
|
|
||||||
Boost Format 1.67 boost::format 7.24
|
|
||||||
Folly Format folly::format 2.23
|
|
||||||
================= ============= ===========
|
|
||||||
|
|
||||||
{fmt} is the fastest of the benchmarked methods, ~35% faster than ``printf``.
|
|
||||||
|
|
||||||
The above results were generated by building ``tinyformat_test.cpp`` on macOS
|
|
||||||
10.14.6 with ``clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT``, and taking the
|
|
||||||
best of three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"``
|
|
||||||
or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for
|
|
||||||
further details refer to the `source
|
|
||||||
<https://github.com/fmtlib/format-benchmark/blob/master/tinyformat_test.cpp>`_.
|
|
||||||
|
|
||||||
{fmt} is up to 10x faster than ``std::ostringstream`` and ``sprintf`` on
|
|
||||||
floating-point formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_)
|
|
||||||
and faster than `double-conversion <https://github.com/google/double-conversion>`_:
|
|
||||||
|
|
||||||
.. image:: https://user-images.githubusercontent.com/576385/
|
|
||||||
69767160-cdaca400-112f-11ea-9fc5-347c9f83caad.png
|
|
||||||
:target: https://fmt.dev/unknown_mac64_clang10.0.html
|
|
||||||
|
|
||||||
Compile time and code bloat
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The script `bloat-test.py
|
|
||||||
<https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py>`_
|
|
||||||
from `format-benchmark <https://github.com/fmtlib/format-benchmark>`_
|
|
||||||
tests compile time and code bloat for nontrivial projects.
|
|
||||||
It generates 100 translation units and uses ``printf()`` or its alternative
|
|
||||||
five times in each to simulate a medium sized project. The resulting
|
|
||||||
executable size and compile time (Apple LLVM version 8.1.0 (clang-802.0.42),
|
|
||||||
macOS Sierra, best of three) is shown in the following tables.
|
|
||||||
|
|
||||||
**Optimized build (-O3)**
|
|
||||||
|
|
||||||
============= =============== ==================== ==================
|
|
||||||
Method Compile Time, s Executable size, KiB Stripped size, KiB
|
|
||||||
============= =============== ==================== ==================
|
|
||||||
printf 2.6 29 26
|
|
||||||
printf+string 16.4 29 26
|
|
||||||
iostreams 31.1 59 55
|
|
||||||
{fmt} 19.0 37 34
|
|
||||||
Boost Format 91.9 226 203
|
|
||||||
Folly Format 115.7 101 88
|
|
||||||
============= =============== ==================== ==================
|
|
||||||
|
|
||||||
As you can see, {fmt} has 60% less overhead in terms of resulting binary code
|
|
||||||
size compared to iostreams and comes pretty close to ``printf``. Boost Format
|
|
||||||
and Folly Format have the largest overheads.
|
|
||||||
|
|
||||||
``printf+string`` is the same as ``printf`` but with extra ``<string>``
|
|
||||||
include to measure the overhead of the latter.
|
|
||||||
|
|
||||||
**Non-optimized build**
|
|
||||||
|
|
||||||
============= =============== ==================== ==================
|
|
||||||
Method Compile Time, s Executable size, KiB Stripped size, KiB
|
|
||||||
============= =============== ==================== ==================
|
|
||||||
printf 2.2 33 30
|
|
||||||
printf+string 16.0 33 30
|
|
||||||
iostreams 28.3 56 52
|
|
||||||
{fmt} 18.2 59 50
|
|
||||||
Boost Format 54.1 365 303
|
|
||||||
Folly Format 79.9 445 430
|
|
||||||
============= =============== ==================== ==================
|
|
||||||
|
|
||||||
``libc``, ``lib(std)c++`` and ``libfmt`` are all linked as shared libraries to
|
|
||||||
compare formatting function overhead only. Boost Format is a
|
|
||||||
header-only library so it doesn't provide any linkage options.
|
|
||||||
|
|
||||||
Running the tests
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Please refer to `Building the library`__ for the instructions on how to build
|
|
||||||
the library and run the unit tests.
|
|
||||||
|
|
||||||
__ https://fmt.dev/latest/usage.html#building-the-library
|
|
||||||
|
|
||||||
Benchmarks reside in a separate repository,
|
|
||||||
`format-benchmarks <https://github.com/fmtlib/format-benchmark>`_,
|
|
||||||
so to run the benchmarks you first need to clone this repository and
|
|
||||||
generate Makefiles with CMake::
|
|
||||||
|
|
||||||
$ git clone --recursive https://github.com/fmtlib/format-benchmark.git
|
|
||||||
$ cd format-benchmark
|
|
||||||
$ cmake .
|
|
||||||
|
|
||||||
Then you can run the speed test::
|
|
||||||
|
|
||||||
$ make speed-test
|
|
||||||
|
|
||||||
or the bloat test::
|
|
||||||
|
|
||||||
$ make bloat-test
|
|
||||||
|
|
||||||
Projects using this library
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
* `0 A.D. <https://play0ad.com/>`_: A free, open-source, cross-platform
|
|
||||||
real-time strategy game
|
|
||||||
|
|
||||||
* `AMPL/MP <https://github.com/ampl/mp>`_:
|
|
||||||
An open-source library for mathematical programming
|
|
||||||
|
|
||||||
* `Aseprite <https://github.com/aseprite/aseprite>`_:
|
|
||||||
Animated sprite editor & pixel art tool
|
|
||||||
|
|
||||||
* `AvioBook <https://www.aviobook.aero/en>`_: A comprehensive aircraft
|
|
||||||
operations suite
|
|
||||||
|
|
||||||
* `Celestia <https://celestia.space/>`_: Real-time 3D visualization of space
|
|
||||||
|
|
||||||
* `Ceph <https://ceph.com/>`_: A scalable distributed storage system
|
|
||||||
|
|
||||||
* `ccache <https://ccache.dev/>`_: A compiler cache
|
|
||||||
|
|
||||||
* `ClickHouse <https://github.com/ClickHouse/ClickHouse>`_: analytical database
|
|
||||||
management system
|
|
||||||
|
|
||||||
* `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater
|
|
||||||
vehicle
|
|
||||||
|
|
||||||
* `Drake <https://drake.mit.edu/>`_: A planning, control, and analysis toolbox
|
|
||||||
for nonlinear dynamical systems (MIT)
|
|
||||||
|
|
||||||
* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus
|
|
||||||
(Lyft)
|
|
||||||
|
|
||||||
* `FiveM <https://fivem.net/>`_: a modification framework for GTA V
|
|
||||||
|
|
||||||
* `Folly <https://github.com/facebook/folly>`_: Facebook open-source library
|
|
||||||
|
|
||||||
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
|
|
||||||
Player vs Player Gaming Network with tweaks
|
|
||||||
|
|
||||||
* `KBEngine <https://github.com/kbengine/kbengine>`_: An open-source MMOG server
|
|
||||||
engine
|
|
||||||
|
|
||||||
* `Keypirinha <https://keypirinha.com/>`_: A semantic launcher for Windows
|
|
||||||
|
|
||||||
* `Kodi <https://kodi.tv/>`_ (formerly xbmc): Home theater software
|
|
||||||
|
|
||||||
* `Knuth <https://kth.cash/>`_: High-performance Bitcoin full-node
|
|
||||||
|
|
||||||
* `Microsoft Verona <https://github.com/microsoft/verona>`_:
|
|
||||||
Research programming language for concurrent ownership
|
|
||||||
|
|
||||||
* `MongoDB <https://mongodb.com/>`_: Distributed document database
|
|
||||||
|
|
||||||
* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to
|
|
||||||
generate randomized datasets
|
|
||||||
|
|
||||||
* `OpenSpace <https://openspaceproject.com/>`_: An open-source
|
|
||||||
astrovisualization framework
|
|
||||||
|
|
||||||
* `PenUltima Online (POL) <https://www.polserver.com/>`_:
|
|
||||||
An MMO server, compatible with most Ultima Online clients
|
|
||||||
|
|
||||||
* `PyTorch <https://github.com/pytorch/pytorch>`_: An open-source machine
|
|
||||||
learning library
|
|
||||||
|
|
||||||
* `quasardb <https://www.quasardb.net/>`_: A distributed, high-performance,
|
|
||||||
associative database
|
|
||||||
|
|
||||||
* `Quill <https://github.com/odygrd/quill>`_: Asynchronous low-latency logging library
|
|
||||||
|
|
||||||
* `QKW <https://github.com/ravijanjam/qkw>`_: Generalizing aliasing to simplify
|
|
||||||
navigation, and executing complex multi-line terminal command sequences
|
|
||||||
|
|
||||||
* `readpe <https://bitbucket.org/sys_dev/readpe>`_: Read Portable Executable
|
|
||||||
|
|
||||||
* `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: A Redis cluster
|
|
||||||
proxy
|
|
||||||
|
|
||||||
* `redpanda <https://vectorized.io/redpanda>`_: A 10x faster Kafka® replacement
|
|
||||||
for mission critical systems written in C++
|
|
||||||
|
|
||||||
* `rpclib <http://rpclib.net/>`_: A modern C++ msgpack-RPC server and client
|
|
||||||
library
|
|
||||||
|
|
||||||
* `Salesforce Analytics Cloud
|
|
||||||
<https://www.salesforce.com/analytics-cloud/overview/>`_:
|
|
||||||
Business intelligence software
|
|
||||||
|
|
||||||
* `Scylla <https://www.scylladb.com/>`_: A Cassandra-compatible NoSQL data store
|
|
||||||
that can handle 1 million transactions per second on a single server
|
|
||||||
|
|
||||||
* `Seastar <http://www.seastar-project.org/>`_: An advanced, open-source C++
|
|
||||||
framework for high-performance server applications on modern hardware
|
|
||||||
|
|
||||||
* `spdlog <https://github.com/gabime/spdlog>`_: Super fast C++ logging library
|
|
||||||
|
|
||||||
* `Stellar <https://www.stellar.org/>`_: Financial platform
|
|
||||||
|
|
||||||
* `Touch Surgery <https://www.touchsurgery.com/>`_: Surgery simulator
|
|
||||||
|
|
||||||
* `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: Open-source
|
|
||||||
MMORPG framework
|
|
||||||
|
|
||||||
* `Windows Terminal <https://github.com/microsoft/terminal>`_: The new Windows
|
|
||||||
Terminal
|
|
||||||
|
|
||||||
`More... <https://github.com/search?q=fmtlib&type=Code>`_
|
|
||||||
|
|
||||||
If you are aware of other projects using this library, please let me know
|
|
||||||
by `email <mailto:victor.zverovich@gmail.com>`_ or by submitting an
|
|
||||||
`issue <https://github.com/fmtlib/fmt/issues>`_.
|
|
||||||
|
|
||||||
Motivation
|
|
||||||
----------
|
|
||||||
|
|
||||||
So why yet another formatting library?
|
|
||||||
|
|
||||||
There are plenty of methods for doing this task, from standard ones like
|
|
||||||
the printf family of function and iostreams to Boost Format and FastFormat
|
|
||||||
libraries. The reason for creating a new library is that every existing
|
|
||||||
solution that I found either had serious issues or didn't provide
|
|
||||||
all the features I needed.
|
|
||||||
|
|
||||||
printf
|
|
||||||
~~~~~~
|
|
||||||
|
|
||||||
The good thing about ``printf`` is that it is pretty fast and readily available
|
|
||||||
being a part of the C standard library. The main drawback is that it
|
|
||||||
doesn't support user-defined types. ``printf`` also has safety issues although
|
|
||||||
they are somewhat mitigated with `__attribute__ ((format (printf, ...))
|
|
||||||
<https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC.
|
|
||||||
There is a POSIX extension that adds positional arguments required for
|
|
||||||
`i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_
|
|
||||||
to ``printf`` but it is not a part of C99 and may not be available on some
|
|
||||||
platforms.
|
|
||||||
|
|
||||||
iostreams
|
|
||||||
~~~~~~~~~
|
|
||||||
|
|
||||||
The main issue with iostreams is best illustrated with an example:
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n";
|
|
||||||
|
|
||||||
which is a lot of typing compared to printf:
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
printf("%.2f\n", 1.23456);
|
|
||||||
|
|
||||||
Matthew Wilson, the author of FastFormat, called this "chevron hell". iostreams
|
|
||||||
don't support positional arguments by design.
|
|
||||||
|
|
||||||
The good part is that iostreams support user-defined types and are safe although
|
|
||||||
error handling is awkward.
|
|
||||||
|
|
||||||
Boost Format
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This is a very powerful library which supports both ``printf``-like format
|
|
||||||
strings and positional arguments. Its main drawback is performance. According to
|
|
||||||
various, benchmarks it is much slower than other methods considered here. Boost
|
|
||||||
Format also has excessive build times and severe code bloat issues (see
|
|
||||||
`Benchmarks`_).
|
|
||||||
|
|
||||||
FastFormat
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
This is an interesting library which is fast, safe and has positional arguments.
|
|
||||||
However, it has significant limitations, citing its author:
|
|
||||||
|
|
||||||
Three features that have no hope of being accommodated within the
|
|
||||||
current design are:
|
|
||||||
|
|
||||||
* Leading zeros (or any other non-space padding)
|
|
||||||
* Octal/hexadecimal encoding
|
|
||||||
* Runtime width/alignment specification
|
|
||||||
|
|
||||||
It is also quite big and has a heavy dependency, STLSoft, which might be too
|
|
||||||
restrictive for using it in some projects.
|
|
||||||
|
|
||||||
Boost Spirit.Karma
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This is not really a formatting library but I decided to include it here for
|
|
||||||
completeness. As iostreams, it suffers from the problem of mixing verbatim text
|
|
||||||
with arguments. The library is pretty fast, but slower on integer formatting
|
|
||||||
than ``fmt::format_to`` with format string compilation on Karma's own benchmark,
|
|
||||||
see `Converting a hundred million integers to strings per second
|
|
||||||
<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_.
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
{fmt} is distributed under the MIT `license
|
|
||||||
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_.
|
|
||||||
|
|
||||||
Documentation License
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
The `Format String Syntax <https://fmt.dev/latest/syntax.html>`_
|
|
||||||
section in the documentation is based on the one from Python `string module
|
|
||||||
documentation <https://docs.python.org/3/library/string.html#module-string>`_.
|
|
||||||
For this reason the documentation is distributed under the Python Software
|
|
||||||
Foundation license available in `doc/python-license.txt
|
|
||||||
<https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_.
|
|
||||||
It only applies if you distribute the documentation of {fmt}.
|
|
||||||
|
|
||||||
Maintainers
|
|
||||||
-----------
|
|
||||||
|
|
||||||
The {fmt} library is maintained by Victor Zverovich (`vitaut
|
|
||||||
<https://github.com/vitaut>`_) and Jonathan Müller (`foonathan
|
|
||||||
<https://github.com/foonathan>`_) with contributions from many other people.
|
|
||||||
See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and
|
|
||||||
`Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names.
|
|
||||||
Let us know if your contribution is not listed or mentioned incorrectly and
|
|
||||||
we'll make it right.
|
|
||||||
1118
src/3rdparty/fmt/fmt/chrono.h
vendored
1118
src/3rdparty/fmt/fmt/chrono.h
vendored
File diff suppressed because it is too large
Load Diff
602
src/3rdparty/fmt/fmt/color.h
vendored
602
src/3rdparty/fmt/fmt/color.h
vendored
@@ -1,602 +0,0 @@
|
|||||||
// Formatting library for C++ - color support
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 - present, Victor Zverovich and fmt contributors
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// For the license information refer to format.h.
|
|
||||||
|
|
||||||
#ifndef FMT_COLOR_H_
|
|
||||||
#define FMT_COLOR_H_
|
|
||||||
|
|
||||||
#include "format.h"
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
enum class color : uint32_t {
|
|
||||||
alice_blue = 0xF0F8FF, // rgb(240,248,255)
|
|
||||||
antique_white = 0xFAEBD7, // rgb(250,235,215)
|
|
||||||
aqua = 0x00FFFF, // rgb(0,255,255)
|
|
||||||
aquamarine = 0x7FFFD4, // rgb(127,255,212)
|
|
||||||
azure = 0xF0FFFF, // rgb(240,255,255)
|
|
||||||
beige = 0xF5F5DC, // rgb(245,245,220)
|
|
||||||
bisque = 0xFFE4C4, // rgb(255,228,196)
|
|
||||||
black = 0x000000, // rgb(0,0,0)
|
|
||||||
blanched_almond = 0xFFEBCD, // rgb(255,235,205)
|
|
||||||
blue = 0x0000FF, // rgb(0,0,255)
|
|
||||||
blue_violet = 0x8A2BE2, // rgb(138,43,226)
|
|
||||||
brown = 0xA52A2A, // rgb(165,42,42)
|
|
||||||
burly_wood = 0xDEB887, // rgb(222,184,135)
|
|
||||||
cadet_blue = 0x5F9EA0, // rgb(95,158,160)
|
|
||||||
chartreuse = 0x7FFF00, // rgb(127,255,0)
|
|
||||||
chocolate = 0xD2691E, // rgb(210,105,30)
|
|
||||||
coral = 0xFF7F50, // rgb(255,127,80)
|
|
||||||
cornflower_blue = 0x6495ED, // rgb(100,149,237)
|
|
||||||
cornsilk = 0xFFF8DC, // rgb(255,248,220)
|
|
||||||
crimson = 0xDC143C, // rgb(220,20,60)
|
|
||||||
cyan = 0x00FFFF, // rgb(0,255,255)
|
|
||||||
dark_blue = 0x00008B, // rgb(0,0,139)
|
|
||||||
dark_cyan = 0x008B8B, // rgb(0,139,139)
|
|
||||||
dark_golden_rod = 0xB8860B, // rgb(184,134,11)
|
|
||||||
dark_gray = 0xA9A9A9, // rgb(169,169,169)
|
|
||||||
dark_green = 0x006400, // rgb(0,100,0)
|
|
||||||
dark_khaki = 0xBDB76B, // rgb(189,183,107)
|
|
||||||
dark_magenta = 0x8B008B, // rgb(139,0,139)
|
|
||||||
dark_olive_green = 0x556B2F, // rgb(85,107,47)
|
|
||||||
dark_orange = 0xFF8C00, // rgb(255,140,0)
|
|
||||||
dark_orchid = 0x9932CC, // rgb(153,50,204)
|
|
||||||
dark_red = 0x8B0000, // rgb(139,0,0)
|
|
||||||
dark_salmon = 0xE9967A, // rgb(233,150,122)
|
|
||||||
dark_sea_green = 0x8FBC8F, // rgb(143,188,143)
|
|
||||||
dark_slate_blue = 0x483D8B, // rgb(72,61,139)
|
|
||||||
dark_slate_gray = 0x2F4F4F, // rgb(47,79,79)
|
|
||||||
dark_turquoise = 0x00CED1, // rgb(0,206,209)
|
|
||||||
dark_violet = 0x9400D3, // rgb(148,0,211)
|
|
||||||
deep_pink = 0xFF1493, // rgb(255,20,147)
|
|
||||||
deep_sky_blue = 0x00BFFF, // rgb(0,191,255)
|
|
||||||
dim_gray = 0x696969, // rgb(105,105,105)
|
|
||||||
dodger_blue = 0x1E90FF, // rgb(30,144,255)
|
|
||||||
fire_brick = 0xB22222, // rgb(178,34,34)
|
|
||||||
floral_white = 0xFFFAF0, // rgb(255,250,240)
|
|
||||||
forest_green = 0x228B22, // rgb(34,139,34)
|
|
||||||
fuchsia = 0xFF00FF, // rgb(255,0,255)
|
|
||||||
gainsboro = 0xDCDCDC, // rgb(220,220,220)
|
|
||||||
ghost_white = 0xF8F8FF, // rgb(248,248,255)
|
|
||||||
gold = 0xFFD700, // rgb(255,215,0)
|
|
||||||
golden_rod = 0xDAA520, // rgb(218,165,32)
|
|
||||||
gray = 0x808080, // rgb(128,128,128)
|
|
||||||
green = 0x008000, // rgb(0,128,0)
|
|
||||||
green_yellow = 0xADFF2F, // rgb(173,255,47)
|
|
||||||
honey_dew = 0xF0FFF0, // rgb(240,255,240)
|
|
||||||
hot_pink = 0xFF69B4, // rgb(255,105,180)
|
|
||||||
indian_red = 0xCD5C5C, // rgb(205,92,92)
|
|
||||||
indigo = 0x4B0082, // rgb(75,0,130)
|
|
||||||
ivory = 0xFFFFF0, // rgb(255,255,240)
|
|
||||||
khaki = 0xF0E68C, // rgb(240,230,140)
|
|
||||||
lavender = 0xE6E6FA, // rgb(230,230,250)
|
|
||||||
lavender_blush = 0xFFF0F5, // rgb(255,240,245)
|
|
||||||
lawn_green = 0x7CFC00, // rgb(124,252,0)
|
|
||||||
lemon_chiffon = 0xFFFACD, // rgb(255,250,205)
|
|
||||||
light_blue = 0xADD8E6, // rgb(173,216,230)
|
|
||||||
light_coral = 0xF08080, // rgb(240,128,128)
|
|
||||||
light_cyan = 0xE0FFFF, // rgb(224,255,255)
|
|
||||||
light_golden_rod_yellow = 0xFAFAD2, // rgb(250,250,210)
|
|
||||||
light_gray = 0xD3D3D3, // rgb(211,211,211)
|
|
||||||
light_green = 0x90EE90, // rgb(144,238,144)
|
|
||||||
light_pink = 0xFFB6C1, // rgb(255,182,193)
|
|
||||||
light_salmon = 0xFFA07A, // rgb(255,160,122)
|
|
||||||
light_sea_green = 0x20B2AA, // rgb(32,178,170)
|
|
||||||
light_sky_blue = 0x87CEFA, // rgb(135,206,250)
|
|
||||||
light_slate_gray = 0x778899, // rgb(119,136,153)
|
|
||||||
light_steel_blue = 0xB0C4DE, // rgb(176,196,222)
|
|
||||||
light_yellow = 0xFFFFE0, // rgb(255,255,224)
|
|
||||||
lime = 0x00FF00, // rgb(0,255,0)
|
|
||||||
lime_green = 0x32CD32, // rgb(50,205,50)
|
|
||||||
linen = 0xFAF0E6, // rgb(250,240,230)
|
|
||||||
magenta = 0xFF00FF, // rgb(255,0,255)
|
|
||||||
maroon = 0x800000, // rgb(128,0,0)
|
|
||||||
medium_aquamarine = 0x66CDAA, // rgb(102,205,170)
|
|
||||||
medium_blue = 0x0000CD, // rgb(0,0,205)
|
|
||||||
medium_orchid = 0xBA55D3, // rgb(186,85,211)
|
|
||||||
medium_purple = 0x9370DB, // rgb(147,112,219)
|
|
||||||
medium_sea_green = 0x3CB371, // rgb(60,179,113)
|
|
||||||
medium_slate_blue = 0x7B68EE, // rgb(123,104,238)
|
|
||||||
medium_spring_green = 0x00FA9A, // rgb(0,250,154)
|
|
||||||
medium_turquoise = 0x48D1CC, // rgb(72,209,204)
|
|
||||||
medium_violet_red = 0xC71585, // rgb(199,21,133)
|
|
||||||
midnight_blue = 0x191970, // rgb(25,25,112)
|
|
||||||
mint_cream = 0xF5FFFA, // rgb(245,255,250)
|
|
||||||
misty_rose = 0xFFE4E1, // rgb(255,228,225)
|
|
||||||
moccasin = 0xFFE4B5, // rgb(255,228,181)
|
|
||||||
navajo_white = 0xFFDEAD, // rgb(255,222,173)
|
|
||||||
navy = 0x000080, // rgb(0,0,128)
|
|
||||||
old_lace = 0xFDF5E6, // rgb(253,245,230)
|
|
||||||
olive = 0x808000, // rgb(128,128,0)
|
|
||||||
olive_drab = 0x6B8E23, // rgb(107,142,35)
|
|
||||||
orange = 0xFFA500, // rgb(255,165,0)
|
|
||||||
orange_red = 0xFF4500, // rgb(255,69,0)
|
|
||||||
orchid = 0xDA70D6, // rgb(218,112,214)
|
|
||||||
pale_golden_rod = 0xEEE8AA, // rgb(238,232,170)
|
|
||||||
pale_green = 0x98FB98, // rgb(152,251,152)
|
|
||||||
pale_turquoise = 0xAFEEEE, // rgb(175,238,238)
|
|
||||||
pale_violet_red = 0xDB7093, // rgb(219,112,147)
|
|
||||||
papaya_whip = 0xFFEFD5, // rgb(255,239,213)
|
|
||||||
peach_puff = 0xFFDAB9, // rgb(255,218,185)
|
|
||||||
peru = 0xCD853F, // rgb(205,133,63)
|
|
||||||
pink = 0xFFC0CB, // rgb(255,192,203)
|
|
||||||
plum = 0xDDA0DD, // rgb(221,160,221)
|
|
||||||
powder_blue = 0xB0E0E6, // rgb(176,224,230)
|
|
||||||
purple = 0x800080, // rgb(128,0,128)
|
|
||||||
rebecca_purple = 0x663399, // rgb(102,51,153)
|
|
||||||
red = 0xFF0000, // rgb(255,0,0)
|
|
||||||
rosy_brown = 0xBC8F8F, // rgb(188,143,143)
|
|
||||||
royal_blue = 0x4169E1, // rgb(65,105,225)
|
|
||||||
saddle_brown = 0x8B4513, // rgb(139,69,19)
|
|
||||||
salmon = 0xFA8072, // rgb(250,128,114)
|
|
||||||
sandy_brown = 0xF4A460, // rgb(244,164,96)
|
|
||||||
sea_green = 0x2E8B57, // rgb(46,139,87)
|
|
||||||
sea_shell = 0xFFF5EE, // rgb(255,245,238)
|
|
||||||
sienna = 0xA0522D, // rgb(160,82,45)
|
|
||||||
silver = 0xC0C0C0, // rgb(192,192,192)
|
|
||||||
sky_blue = 0x87CEEB, // rgb(135,206,235)
|
|
||||||
slate_blue = 0x6A5ACD, // rgb(106,90,205)
|
|
||||||
slate_gray = 0x708090, // rgb(112,128,144)
|
|
||||||
snow = 0xFFFAFA, // rgb(255,250,250)
|
|
||||||
spring_green = 0x00FF7F, // rgb(0,255,127)
|
|
||||||
steel_blue = 0x4682B4, // rgb(70,130,180)
|
|
||||||
tan = 0xD2B48C, // rgb(210,180,140)
|
|
||||||
teal = 0x008080, // rgb(0,128,128)
|
|
||||||
thistle = 0xD8BFD8, // rgb(216,191,216)
|
|
||||||
tomato = 0xFF6347, // rgb(255,99,71)
|
|
||||||
turquoise = 0x40E0D0, // rgb(64,224,208)
|
|
||||||
violet = 0xEE82EE, // rgb(238,130,238)
|
|
||||||
wheat = 0xF5DEB3, // rgb(245,222,179)
|
|
||||||
white = 0xFFFFFF, // rgb(255,255,255)
|
|
||||||
white_smoke = 0xF5F5F5, // rgb(245,245,245)
|
|
||||||
yellow = 0xFFFF00, // rgb(255,255,0)
|
|
||||||
yellow_green = 0x9ACD32 // rgb(154,205,50)
|
|
||||||
}; // enum class color
|
|
||||||
|
|
||||||
enum class terminal_color : uint8_t {
|
|
||||||
black = 30,
|
|
||||||
red,
|
|
||||||
green,
|
|
||||||
yellow,
|
|
||||||
blue,
|
|
||||||
magenta,
|
|
||||||
cyan,
|
|
||||||
white,
|
|
||||||
bright_black = 90,
|
|
||||||
bright_red,
|
|
||||||
bright_green,
|
|
||||||
bright_yellow,
|
|
||||||
bright_blue,
|
|
||||||
bright_magenta,
|
|
||||||
bright_cyan,
|
|
||||||
bright_white
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class emphasis : uint8_t {
|
|
||||||
bold = 1,
|
|
||||||
italic = 1 << 1,
|
|
||||||
underline = 1 << 2,
|
|
||||||
strikethrough = 1 << 3
|
|
||||||
};
|
|
||||||
|
|
||||||
// rgb is a struct for red, green and blue colors.
|
|
||||||
// Using the name "rgb" makes some editors show the color in a tooltip.
|
|
||||||
struct rgb {
|
|
||||||
FMT_CONSTEXPR rgb() : r(0), g(0), b(0) {}
|
|
||||||
FMT_CONSTEXPR rgb(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {}
|
|
||||||
FMT_CONSTEXPR rgb(uint32_t hex)
|
|
||||||
: r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b(hex & 0xFF) {}
|
|
||||||
FMT_CONSTEXPR rgb(color hex)
|
|
||||||
: r((uint32_t(hex) >> 16) & 0xFF),
|
|
||||||
g((uint32_t(hex) >> 8) & 0xFF),
|
|
||||||
b(uint32_t(hex) & 0xFF) {}
|
|
||||||
uint8_t r;
|
|
||||||
uint8_t g;
|
|
||||||
uint8_t b;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
// color is a struct of either a rgb color or a terminal color.
|
|
||||||
struct color_type {
|
|
||||||
FMT_CONSTEXPR color_type() FMT_NOEXCEPT : is_rgb(), value{} {}
|
|
||||||
FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT : is_rgb(true),
|
|
||||||
value{} {
|
|
||||||
value.rgb_color = static_cast<uint32_t>(rgb_color);
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR color_type(rgb rgb_color) FMT_NOEXCEPT : is_rgb(true), value{} {
|
|
||||||
value.rgb_color = (static_cast<uint32_t>(rgb_color.r) << 16) |
|
|
||||||
(static_cast<uint32_t>(rgb_color.g) << 8) | rgb_color.b;
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT : is_rgb(),
|
|
||||||
value{} {
|
|
||||||
value.term_color = static_cast<uint8_t>(term_color);
|
|
||||||
}
|
|
||||||
bool is_rgb;
|
|
||||||
union color_union {
|
|
||||||
uint8_t term_color;
|
|
||||||
uint32_t rgb_color;
|
|
||||||
} value;
|
|
||||||
};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
// Experimental text formatting support.
|
|
||||||
class text_style {
|
|
||||||
public:
|
|
||||||
FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT
|
|
||||||
: set_foreground_color(),
|
|
||||||
set_background_color(),
|
|
||||||
ems(em) {}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) {
|
|
||||||
if (!set_foreground_color) {
|
|
||||||
set_foreground_color = rhs.set_foreground_color;
|
|
||||||
foreground_color = rhs.foreground_color;
|
|
||||||
} else if (rhs.set_foreground_color) {
|
|
||||||
if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
|
|
||||||
FMT_THROW(format_error("can't OR a terminal color"));
|
|
||||||
foreground_color.value.rgb_color |= rhs.foreground_color.value.rgb_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!set_background_color) {
|
|
||||||
set_background_color = rhs.set_background_color;
|
|
||||||
background_color = rhs.background_color;
|
|
||||||
} else if (rhs.set_background_color) {
|
|
||||||
if (!background_color.is_rgb || !rhs.background_color.is_rgb)
|
|
||||||
FMT_THROW(format_error("can't OR a terminal color"));
|
|
||||||
background_color.value.rgb_color |= rhs.background_color.value.rgb_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
ems = static_cast<emphasis>(static_cast<uint8_t>(ems) |
|
|
||||||
static_cast<uint8_t>(rhs.ems));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend FMT_CONSTEXPR text_style operator|(text_style lhs,
|
|
||||||
const text_style& rhs) {
|
|
||||||
return lhs |= rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR text_style& operator&=(const text_style& rhs) {
|
|
||||||
if (!set_foreground_color) {
|
|
||||||
set_foreground_color = rhs.set_foreground_color;
|
|
||||||
foreground_color = rhs.foreground_color;
|
|
||||||
} else if (rhs.set_foreground_color) {
|
|
||||||
if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
|
|
||||||
FMT_THROW(format_error("can't AND a terminal color"));
|
|
||||||
foreground_color.value.rgb_color &= rhs.foreground_color.value.rgb_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!set_background_color) {
|
|
||||||
set_background_color = rhs.set_background_color;
|
|
||||||
background_color = rhs.background_color;
|
|
||||||
} else if (rhs.set_background_color) {
|
|
||||||
if (!background_color.is_rgb || !rhs.background_color.is_rgb)
|
|
||||||
FMT_THROW(format_error("can't AND a terminal color"));
|
|
||||||
background_color.value.rgb_color &= rhs.background_color.value.rgb_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
ems = static_cast<emphasis>(static_cast<uint8_t>(ems) &
|
|
||||||
static_cast<uint8_t>(rhs.ems));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend FMT_CONSTEXPR text_style operator&(text_style lhs,
|
|
||||||
const text_style& rhs) {
|
|
||||||
return lhs &= rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR bool has_foreground() const FMT_NOEXCEPT {
|
|
||||||
return set_foreground_color;
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR bool has_background() const FMT_NOEXCEPT {
|
|
||||||
return set_background_color;
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR bool has_emphasis() const FMT_NOEXCEPT {
|
|
||||||
return static_cast<uint8_t>(ems) != 0;
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR detail::color_type get_foreground() const FMT_NOEXCEPT {
|
|
||||||
FMT_ASSERT(has_foreground(), "no foreground specified for this style");
|
|
||||||
return foreground_color;
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR detail::color_type get_background() const FMT_NOEXCEPT {
|
|
||||||
FMT_ASSERT(has_background(), "no background specified for this style");
|
|
||||||
return background_color;
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR emphasis get_emphasis() const FMT_NOEXCEPT {
|
|
||||||
FMT_ASSERT(has_emphasis(), "no emphasis specified for this style");
|
|
||||||
return ems;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
FMT_CONSTEXPR text_style(bool is_foreground,
|
|
||||||
detail::color_type text_color) FMT_NOEXCEPT
|
|
||||||
: set_foreground_color(),
|
|
||||||
set_background_color(),
|
|
||||||
ems() {
|
|
||||||
if (is_foreground) {
|
|
||||||
foreground_color = text_color;
|
|
||||||
set_foreground_color = true;
|
|
||||||
} else {
|
|
||||||
background_color = text_color;
|
|
||||||
set_background_color = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
friend FMT_CONSTEXPR_DECL text_style fg(detail::color_type foreground)
|
|
||||||
FMT_NOEXCEPT;
|
|
||||||
friend FMT_CONSTEXPR_DECL text_style bg(detail::color_type background)
|
|
||||||
FMT_NOEXCEPT;
|
|
||||||
|
|
||||||
detail::color_type foreground_color;
|
|
||||||
detail::color_type background_color;
|
|
||||||
bool set_foreground_color;
|
|
||||||
bool set_background_color;
|
|
||||||
emphasis ems;
|
|
||||||
};
|
|
||||||
|
|
||||||
FMT_CONSTEXPR text_style fg(detail::color_type foreground) FMT_NOEXCEPT {
|
|
||||||
return text_style(/*is_foreground=*/true, foreground);
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR text_style bg(detail::color_type background) FMT_NOEXCEPT {
|
|
||||||
return text_style(/*is_foreground=*/false, background);
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR text_style operator|(emphasis lhs, emphasis rhs) FMT_NOEXCEPT {
|
|
||||||
return text_style(lhs) | rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template <typename Char> struct ansi_color_escape {
|
|
||||||
FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color,
|
|
||||||
const char* esc) FMT_NOEXCEPT {
|
|
||||||
// If we have a terminal color, we need to output another escape code
|
|
||||||
// sequence.
|
|
||||||
if (!text_color.is_rgb) {
|
|
||||||
bool is_background = esc == detail::data::background_color;
|
|
||||||
uint32_t value = text_color.value.term_color;
|
|
||||||
// Background ASCII codes are the same as the foreground ones but with
|
|
||||||
// 10 more.
|
|
||||||
if (is_background) value += 10u;
|
|
||||||
|
|
||||||
size_t index = 0;
|
|
||||||
buffer[index++] = static_cast<Char>('\x1b');
|
|
||||||
buffer[index++] = static_cast<Char>('[');
|
|
||||||
|
|
||||||
if (value >= 100u) {
|
|
||||||
buffer[index++] = static_cast<Char>('1');
|
|
||||||
value %= 100u;
|
|
||||||
}
|
|
||||||
buffer[index++] = static_cast<Char>('0' + value / 10u);
|
|
||||||
buffer[index++] = static_cast<Char>('0' + value % 10u);
|
|
||||||
|
|
||||||
buffer[index++] = static_cast<Char>('m');
|
|
||||||
buffer[index++] = static_cast<Char>('\0');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
buffer[i] = static_cast<Char>(esc[i]);
|
|
||||||
}
|
|
||||||
rgb color(text_color.value.rgb_color);
|
|
||||||
to_esc(color.r, buffer + 7, ';');
|
|
||||||
to_esc(color.g, buffer + 11, ';');
|
|
||||||
to_esc(color.b, buffer + 15, 'm');
|
|
||||||
buffer[19] = static_cast<Char>(0);
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR ansi_color_escape(emphasis em) FMT_NOEXCEPT {
|
|
||||||
uint8_t em_codes[4] = {};
|
|
||||||
uint8_t em_bits = static_cast<uint8_t>(em);
|
|
||||||
if (em_bits & static_cast<uint8_t>(emphasis::bold)) em_codes[0] = 1;
|
|
||||||
if (em_bits & static_cast<uint8_t>(emphasis::italic)) em_codes[1] = 3;
|
|
||||||
if (em_bits & static_cast<uint8_t>(emphasis::underline)) em_codes[2] = 4;
|
|
||||||
if (em_bits & static_cast<uint8_t>(emphasis::strikethrough))
|
|
||||||
em_codes[3] = 9;
|
|
||||||
|
|
||||||
size_t index = 0;
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
if (!em_codes[i]) continue;
|
|
||||||
buffer[index++] = static_cast<Char>('\x1b');
|
|
||||||
buffer[index++] = static_cast<Char>('[');
|
|
||||||
buffer[index++] = static_cast<Char>('0' + em_codes[i]);
|
|
||||||
buffer[index++] = static_cast<Char>('m');
|
|
||||||
}
|
|
||||||
buffer[index++] = static_cast<Char>(0);
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR operator const Char*() const FMT_NOEXCEPT { return buffer; }
|
|
||||||
|
|
||||||
FMT_CONSTEXPR const Char* begin() const FMT_NOEXCEPT { return buffer; }
|
|
||||||
FMT_CONSTEXPR const Char* end() const FMT_NOEXCEPT {
|
|
||||||
return buffer + std::char_traits<Char>::length(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Char buffer[7u + 3u * 4u + 1u];
|
|
||||||
|
|
||||||
static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,
|
|
||||||
char delimiter) FMT_NOEXCEPT {
|
|
||||||
out[0] = static_cast<Char>('0' + c / 100);
|
|
||||||
out[1] = static_cast<Char>('0' + c / 10 % 10);
|
|
||||||
out[2] = static_cast<Char>('0' + c % 10);
|
|
||||||
out[3] = static_cast<Char>(delimiter);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color(
|
|
||||||
detail::color_type foreground) FMT_NOEXCEPT {
|
|
||||||
return ansi_color_escape<Char>(foreground, detail::data::foreground_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
FMT_CONSTEXPR ansi_color_escape<Char> make_background_color(
|
|
||||||
detail::color_type background) FMT_NOEXCEPT {
|
|
||||||
return ansi_color_escape<Char>(background, detail::data::background_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) FMT_NOEXCEPT {
|
|
||||||
return ansi_color_escape<Char>(em);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
inline void fputs(const Char* chars, FILE* stream) FMT_NOEXCEPT {
|
|
||||||
std::fputs(chars, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT {
|
|
||||||
std::fputws(chars, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT {
|
|
||||||
fputs(detail::data::reset_color, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT {
|
|
||||||
fputs(detail::data::wreset_color, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
inline void reset_color(buffer<Char>& buffer) FMT_NOEXCEPT {
|
|
||||||
const char* begin = data::reset_color;
|
|
||||||
const char* end = begin + sizeof(data::reset_color) - 1;
|
|
||||||
buffer.append(begin, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
void vformat_to(buffer<Char>& buf, const text_style& ts,
|
|
||||||
basic_string_view<Char> format_str,
|
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
|
||||||
bool has_style = false;
|
|
||||||
if (ts.has_emphasis()) {
|
|
||||||
has_style = true;
|
|
||||||
auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
|
|
||||||
buf.append(emphasis.begin(), emphasis.end());
|
|
||||||
}
|
|
||||||
if (ts.has_foreground()) {
|
|
||||||
has_style = true;
|
|
||||||
auto foreground = detail::make_foreground_color<Char>(ts.get_foreground());
|
|
||||||
buf.append(foreground.begin(), foreground.end());
|
|
||||||
}
|
|
||||||
if (ts.has_background()) {
|
|
||||||
has_style = true;
|
|
||||||
auto background = detail::make_background_color<Char>(ts.get_background());
|
|
||||||
buf.append(background.begin(), background.end());
|
|
||||||
}
|
|
||||||
detail::vformat_to(buf, format_str, args);
|
|
||||||
if (has_style) detail::reset_color<Char>(buf);
|
|
||||||
}
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
|
||||||
void vprint(std::FILE* f, const text_style& ts, const S& format,
|
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
|
||||||
basic_memory_buffer<Char> buf;
|
|
||||||
detail::vformat_to(buf, ts, to_string_view(format), args);
|
|
||||||
buf.push_back(Char(0));
|
|
||||||
detail::fputs(buf.data(), f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Formats a string and prints it to the specified file stream using ANSI
|
|
||||||
escape sequences to specify text formatting.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
|
|
||||||
"Elapsed time: {0:.2f} seconds", 1.23);
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename S, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_string<S>::value)>
|
|
||||||
void print(std::FILE* f, const text_style& ts, const S& format_str,
|
|
||||||
const Args&... args) {
|
|
||||||
vprint(f, ts, format_str,
|
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Formats a string and prints it to stdout using ANSI escape sequences to
|
|
||||||
specify text formatting.
|
|
||||||
Example:
|
|
||||||
fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
|
|
||||||
"Elapsed time: {0:.2f} seconds", 1.23);
|
|
||||||
*/
|
|
||||||
template <typename S, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_string<S>::value)>
|
|
||||||
void print(const text_style& ts, const S& format_str, const Args&... args) {
|
|
||||||
return print(stdout, ts, format_str, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
|
||||||
inline std::basic_string<Char> vformat(
|
|
||||||
const text_style& ts, const S& format_str,
|
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
|
||||||
basic_memory_buffer<Char> buf;
|
|
||||||
detail::vformat_to(buf, ts, to_string_view(format_str), args);
|
|
||||||
return fmt::to_string(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Formats arguments and returns the result as a string using ANSI
|
|
||||||
escape sequences to specify text formatting.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
#include <fmt/color.h>
|
|
||||||
std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red),
|
|
||||||
"The answer is {}", 42);
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
|
||||||
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
|
|
||||||
const Args&... args) {
|
|
||||||
return vformat(ts, to_string_view(format_str),
|
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Formats a string with the given text_style and writes the output to ``out``.
|
|
||||||
*/
|
|
||||||
template <typename OutputIt, typename Char,
|
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value)>
|
|
||||||
OutputIt vformat_to(
|
|
||||||
OutputIt out, const text_style& ts, basic_string_view<Char> format_str,
|
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
|
||||||
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
|
|
||||||
detail::vformat_to(buf, ts, format_str, args);
|
|
||||||
return detail::get_iterator(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Formats arguments with the given text_style, writes the result to the output
|
|
||||||
iterator ``out`` and returns the iterator past the end of the output range.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
std::vector<char> out;
|
|
||||||
fmt::format_to(std::back_inserter(out),
|
|
||||||
fmt::emphasis::bold | fg(fmt::color::red), "{}", 42);
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&&
|
|
||||||
detail::is_string<S>::value)>
|
|
||||||
inline OutputIt format_to(OutputIt out, const text_style& ts,
|
|
||||||
const S& format_str, Args&&... args) {
|
|
||||||
return vformat_to(out, ts, to_string_view(format_str),
|
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // FMT_COLOR_H_
|
|
||||||
699
src/3rdparty/fmt/fmt/compile.h
vendored
699
src/3rdparty/fmt/fmt/compile.h
vendored
@@ -1,699 +0,0 @@
|
|||||||
// Formatting library for C++ - experimental format string compilation
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 - present, Victor Zverovich and fmt contributors
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// For the license information refer to format.h.
|
|
||||||
|
|
||||||
#ifndef FMT_COMPILE_H_
|
|
||||||
#define FMT_COMPILE_H_
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "format.h"
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
// A compile-time string which is compiled into fast formatting code.
|
|
||||||
class compiled_string {};
|
|
||||||
|
|
||||||
template <typename S>
|
|
||||||
struct is_compiled_string : std::is_base_of<compiled_string, S> {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Converts a string literal *s* into a format string that will be parsed at
|
|
||||||
compile time and converted into efficient formatting code. Requires C++17
|
|
||||||
``constexpr if`` compiler support.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
// Converts 42 into std::string using the most efficient method and no
|
|
||||||
// runtime format string processing.
|
|
||||||
std::string s = fmt::format(FMT_COMPILE("{}"), 42);
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
#define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::detail::compiled_string)
|
|
||||||
|
|
||||||
template <typename T, typename... Tail>
|
|
||||||
const T& first(const T& value, const Tail&...) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Part of a compiled format string. It can be either literal text or a
|
|
||||||
// replacement field.
|
|
||||||
template <typename Char> struct format_part {
|
|
||||||
enum class kind { arg_index, arg_name, text, replacement };
|
|
||||||
|
|
||||||
struct replacement {
|
|
||||||
arg_ref<Char> arg_id;
|
|
||||||
dynamic_format_specs<Char> specs;
|
|
||||||
};
|
|
||||||
|
|
||||||
kind part_kind;
|
|
||||||
union value {
|
|
||||||
int arg_index;
|
|
||||||
basic_string_view<Char> str;
|
|
||||||
replacement repl;
|
|
||||||
|
|
||||||
FMT_CONSTEXPR value(int index = 0) : arg_index(index) {}
|
|
||||||
FMT_CONSTEXPR value(basic_string_view<Char> s) : str(s) {}
|
|
||||||
FMT_CONSTEXPR value(replacement r) : repl(r) {}
|
|
||||||
} val;
|
|
||||||
// Position past the end of the argument id.
|
|
||||||
const Char* arg_id_end = nullptr;
|
|
||||||
|
|
||||||
FMT_CONSTEXPR format_part(kind k = kind::arg_index, value v = {})
|
|
||||||
: part_kind(k), val(v) {}
|
|
||||||
|
|
||||||
static FMT_CONSTEXPR format_part make_arg_index(int index) {
|
|
||||||
return format_part(kind::arg_index, index);
|
|
||||||
}
|
|
||||||
static FMT_CONSTEXPR format_part make_arg_name(basic_string_view<Char> name) {
|
|
||||||
return format_part(kind::arg_name, name);
|
|
||||||
}
|
|
||||||
static FMT_CONSTEXPR format_part make_text(basic_string_view<Char> text) {
|
|
||||||
return format_part(kind::text, text);
|
|
||||||
}
|
|
||||||
static FMT_CONSTEXPR format_part make_replacement(replacement repl) {
|
|
||||||
return format_part(kind::replacement, repl);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char> struct part_counter {
|
|
||||||
unsigned num_parts = 0;
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) {
|
|
||||||
if (begin != end) ++num_parts;
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR int on_arg_id() { return ++num_parts, 0; }
|
|
||||||
FMT_CONSTEXPR int on_arg_id(int) { return ++num_parts, 0; }
|
|
||||||
FMT_CONSTEXPR int on_arg_id(basic_string_view<Char>) {
|
|
||||||
return ++num_parts, 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_replacement_field(int, const Char*) {}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR const Char* on_format_specs(int, const Char* begin,
|
|
||||||
const Char* end) {
|
|
||||||
// Find the matching brace.
|
|
||||||
unsigned brace_counter = 0;
|
|
||||||
for (; begin != end; ++begin) {
|
|
||||||
if (*begin == '{') {
|
|
||||||
++brace_counter;
|
|
||||||
} else if (*begin == '}') {
|
|
||||||
if (brace_counter == 0u) break;
|
|
||||||
--brace_counter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_error(const char*) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Counts the number of parts in a format string.
|
|
||||||
template <typename Char>
|
|
||||||
FMT_CONSTEXPR unsigned count_parts(basic_string_view<Char> format_str) {
|
|
||||||
part_counter<Char> counter;
|
|
||||||
parse_format_string<true>(format_str, counter);
|
|
||||||
return counter.num_parts;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, typename PartHandler>
|
|
||||||
class format_string_compiler : public error_handler {
|
|
||||||
private:
|
|
||||||
using part = format_part<Char>;
|
|
||||||
|
|
||||||
PartHandler handler_;
|
|
||||||
part part_;
|
|
||||||
basic_string_view<Char> format_str_;
|
|
||||||
basic_format_parse_context<Char> parse_context_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
FMT_CONSTEXPR format_string_compiler(basic_string_view<Char> format_str,
|
|
||||||
PartHandler handler)
|
|
||||||
: handler_(handler),
|
|
||||||
format_str_(format_str),
|
|
||||||
parse_context_(format_str) {}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) {
|
|
||||||
if (begin != end)
|
|
||||||
handler_(part::make_text({begin, to_unsigned(end - begin)}));
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR int on_arg_id() {
|
|
||||||
part_ = part::make_arg_index(parse_context_.next_arg_id());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR int on_arg_id(int id) {
|
|
||||||
parse_context_.check_arg_id(id);
|
|
||||||
part_ = part::make_arg_index(id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR int on_arg_id(basic_string_view<Char> id) {
|
|
||||||
part_ = part::make_arg_name(id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_replacement_field(int, const Char* ptr) {
|
|
||||||
part_.arg_id_end = ptr;
|
|
||||||
handler_(part_);
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR const Char* on_format_specs(int, const Char* begin,
|
|
||||||
const Char* end) {
|
|
||||||
auto repl = typename part::replacement();
|
|
||||||
dynamic_specs_handler<basic_format_parse_context<Char>> handler(
|
|
||||||
repl.specs, parse_context_);
|
|
||||||
auto it = parse_format_specs(begin, end, handler);
|
|
||||||
if (*it != '}') on_error("missing '}' in format string");
|
|
||||||
repl.arg_id = part_.part_kind == part::kind::arg_index
|
|
||||||
? arg_ref<Char>(part_.val.arg_index)
|
|
||||||
: arg_ref<Char>(part_.val.str);
|
|
||||||
auto part = part::make_replacement(repl);
|
|
||||||
part.arg_id_end = begin;
|
|
||||||
handler_(part);
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Compiles a format string and invokes handler(part) for each parsed part.
|
|
||||||
template <bool IS_CONSTEXPR, typename Char, typename PartHandler>
|
|
||||||
FMT_CONSTEXPR void compile_format_string(basic_string_view<Char> format_str,
|
|
||||||
PartHandler handler) {
|
|
||||||
parse_format_string<IS_CONSTEXPR>(
|
|
||||||
format_str,
|
|
||||||
format_string_compiler<Char, PartHandler>(format_str, handler));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename Context, typename Id>
|
|
||||||
void format_arg(
|
|
||||||
basic_format_parse_context<typename Context::char_type>& parse_ctx,
|
|
||||||
Context& ctx, Id arg_id) {
|
|
||||||
ctx.advance_to(visit_format_arg(
|
|
||||||
arg_formatter<OutputIt, typename Context::char_type>(ctx, &parse_ctx),
|
|
||||||
ctx.arg(arg_id)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// vformat_to is defined in a subnamespace to prevent ADL.
|
|
||||||
namespace cf {
|
|
||||||
template <typename Context, typename OutputIt, typename CompiledFormat>
|
|
||||||
auto vformat_to(OutputIt out, CompiledFormat& cf,
|
|
||||||
basic_format_args<Context> args) -> typename Context::iterator {
|
|
||||||
using char_type = typename Context::char_type;
|
|
||||||
basic_format_parse_context<char_type> parse_ctx(
|
|
||||||
to_string_view(cf.format_str_));
|
|
||||||
Context ctx(out, args);
|
|
||||||
|
|
||||||
const auto& parts = cf.parts();
|
|
||||||
for (auto part_it = std::begin(parts); part_it != std::end(parts);
|
|
||||||
++part_it) {
|
|
||||||
const auto& part = *part_it;
|
|
||||||
const auto& value = part.val;
|
|
||||||
|
|
||||||
using format_part_t = format_part<char_type>;
|
|
||||||
switch (part.part_kind) {
|
|
||||||
case format_part_t::kind::text: {
|
|
||||||
const auto text = value.str;
|
|
||||||
auto output = ctx.out();
|
|
||||||
auto&& it = reserve(output, text.size());
|
|
||||||
it = std::copy_n(text.begin(), text.size(), it);
|
|
||||||
ctx.advance_to(output);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case format_part_t::kind::arg_index:
|
|
||||||
advance_to(parse_ctx, part.arg_id_end);
|
|
||||||
detail::format_arg<OutputIt>(parse_ctx, ctx, value.arg_index);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case format_part_t::kind::arg_name:
|
|
||||||
advance_to(parse_ctx, part.arg_id_end);
|
|
||||||
detail::format_arg<OutputIt>(parse_ctx, ctx, value.str);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case format_part_t::kind::replacement: {
|
|
||||||
const auto& arg_id_value = value.repl.arg_id.val;
|
|
||||||
const auto arg = value.repl.arg_id.kind == arg_id_kind::index
|
|
||||||
? ctx.arg(arg_id_value.index)
|
|
||||||
: ctx.arg(arg_id_value.name);
|
|
||||||
|
|
||||||
auto specs = value.repl.specs;
|
|
||||||
|
|
||||||
handle_dynamic_spec<width_checker>(specs.width, specs.width_ref, ctx);
|
|
||||||
handle_dynamic_spec<precision_checker>(specs.precision,
|
|
||||||
specs.precision_ref, ctx);
|
|
||||||
|
|
||||||
error_handler h;
|
|
||||||
numeric_specs_checker<error_handler> checker(h, arg.type());
|
|
||||||
if (specs.align == align::numeric) checker.require_numeric_argument();
|
|
||||||
if (specs.sign != sign::none) checker.check_sign();
|
|
||||||
if (specs.alt) checker.require_numeric_argument();
|
|
||||||
if (specs.precision >= 0) checker.check_precision();
|
|
||||||
|
|
||||||
advance_to(parse_ctx, part.arg_id_end);
|
|
||||||
ctx.advance_to(
|
|
||||||
visit_format_arg(arg_formatter<OutputIt, typename Context::char_type>(
|
|
||||||
ctx, nullptr, &specs),
|
|
||||||
arg));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ctx.out();
|
|
||||||
}
|
|
||||||
} // namespace cf
|
|
||||||
|
|
||||||
struct basic_compiled_format {};
|
|
||||||
|
|
||||||
template <typename S, typename = void>
|
|
||||||
struct compiled_format_base : basic_compiled_format {
|
|
||||||
using char_type = char_t<S>;
|
|
||||||
using parts_container = std::vector<detail::format_part<char_type>>;
|
|
||||||
|
|
||||||
parts_container compiled_parts;
|
|
||||||
|
|
||||||
explicit compiled_format_base(basic_string_view<char_type> format_str) {
|
|
||||||
compile_format_string<false>(format_str,
|
|
||||||
[this](const format_part<char_type>& part) {
|
|
||||||
compiled_parts.push_back(part);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const parts_container& parts() const { return compiled_parts; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, unsigned N> struct format_part_array {
|
|
||||||
format_part<Char> data[N] = {};
|
|
||||||
FMT_CONSTEXPR format_part_array() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, unsigned N>
|
|
||||||
FMT_CONSTEXPR format_part_array<Char, N> compile_to_parts(
|
|
||||||
basic_string_view<Char> format_str) {
|
|
||||||
format_part_array<Char, N> parts;
|
|
||||||
unsigned counter = 0;
|
|
||||||
// This is not a lambda for compatibility with older compilers.
|
|
||||||
struct {
|
|
||||||
format_part<Char>* parts;
|
|
||||||
unsigned* counter;
|
|
||||||
FMT_CONSTEXPR void operator()(const format_part<Char>& part) {
|
|
||||||
parts[(*counter)++] = part;
|
|
||||||
}
|
|
||||||
} collector{parts.data, &counter};
|
|
||||||
compile_format_string<true>(format_str, collector);
|
|
||||||
if (counter < N) {
|
|
||||||
parts.data[counter] =
|
|
||||||
format_part<Char>::make_text(basic_string_view<Char>());
|
|
||||||
}
|
|
||||||
return parts;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> constexpr const T& constexpr_max(const T& a, const T& b) {
|
|
||||||
return (a < b) ? b : a;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S>
|
|
||||||
struct compiled_format_base<S, enable_if_t<is_compile_string<S>::value>>
|
|
||||||
: basic_compiled_format {
|
|
||||||
using char_type = char_t<S>;
|
|
||||||
|
|
||||||
FMT_CONSTEXPR explicit compiled_format_base(basic_string_view<char_type>) {}
|
|
||||||
|
|
||||||
// Workaround for old compilers. Format string compilation will not be
|
|
||||||
// performed there anyway.
|
|
||||||
#if FMT_USE_CONSTEXPR
|
|
||||||
static FMT_CONSTEXPR_DECL const unsigned num_format_parts =
|
|
||||||
constexpr_max(count_parts(to_string_view(S())), 1u);
|
|
||||||
#else
|
|
||||||
static const unsigned num_format_parts = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using parts_container = format_part<char_type>[num_format_parts];
|
|
||||||
|
|
||||||
const parts_container& parts() const {
|
|
||||||
static FMT_CONSTEXPR_DECL const auto compiled_parts =
|
|
||||||
compile_to_parts<char_type, num_format_parts>(
|
|
||||||
detail::to_string_view(S()));
|
|
||||||
return compiled_parts.data;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename S, typename... Args>
|
|
||||||
class compiled_format : private compiled_format_base<S> {
|
|
||||||
public:
|
|
||||||
using typename compiled_format_base<S>::char_type;
|
|
||||||
|
|
||||||
private:
|
|
||||||
basic_string_view<char_type> format_str_;
|
|
||||||
|
|
||||||
template <typename Context, typename OutputIt, typename CompiledFormat>
|
|
||||||
friend auto cf::vformat_to(OutputIt out, CompiledFormat& cf,
|
|
||||||
basic_format_args<Context> args) ->
|
|
||||||
typename Context::iterator;
|
|
||||||
|
|
||||||
public:
|
|
||||||
compiled_format() = delete;
|
|
||||||
explicit constexpr compiled_format(basic_string_view<char_type> format_str)
|
|
||||||
: compiled_format_base<S>(format_str), format_str_(format_str) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __cpp_if_constexpr
|
|
||||||
template <typename... Args> struct type_list {};
|
|
||||||
|
|
||||||
// Returns a reference to the argument at index N from [first, rest...].
|
|
||||||
template <int N, typename T, typename... Args>
|
|
||||||
constexpr const auto& get([[maybe_unused]] const T& first,
|
|
||||||
[[maybe_unused]] const Args&... rest) {
|
|
||||||
static_assert(N < 1 + sizeof...(Args), "index is out of bounds");
|
|
||||||
if constexpr (N == 0)
|
|
||||||
return first;
|
|
||||||
else
|
|
||||||
return get<N - 1>(rest...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int N, typename> struct get_type_impl;
|
|
||||||
|
|
||||||
template <int N, typename... Args> struct get_type_impl<N, type_list<Args...>> {
|
|
||||||
using type = remove_cvref_t<decltype(get<N>(std::declval<Args>()...))>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int N, typename T>
|
|
||||||
using get_type = typename get_type_impl<N, T>::type;
|
|
||||||
|
|
||||||
template <typename T> struct is_compiled_format : std::false_type {};
|
|
||||||
|
|
||||||
template <typename Char> struct text {
|
|
||||||
basic_string_view<Char> data;
|
|
||||||
using char_type = Char;
|
|
||||||
|
|
||||||
template <typename OutputIt, typename... Args>
|
|
||||||
OutputIt format(OutputIt out, const Args&...) const {
|
|
||||||
return write<Char>(out, data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
struct is_compiled_format<text<Char>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
constexpr text<Char> make_text(basic_string_view<Char> s, size_t pos,
|
|
||||||
size_t size) {
|
|
||||||
return {{&s[pos], size}};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char> struct code_unit {
|
|
||||||
Char value;
|
|
||||||
using char_type = Char;
|
|
||||||
|
|
||||||
template <typename OutputIt, typename... Args>
|
|
||||||
OutputIt format(OutputIt out, const Args&...) const {
|
|
||||||
return write<Char>(out, value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
struct is_compiled_format<code_unit<Char>> : std::true_type {};
|
|
||||||
|
|
||||||
// A replacement field that refers to argument N.
|
|
||||||
template <typename Char, typename T, int N> struct field {
|
|
||||||
using char_type = Char;
|
|
||||||
|
|
||||||
template <typename OutputIt, typename... Args>
|
|
||||||
OutputIt format(OutputIt out, const Args&... args) const {
|
|
||||||
// This ensures that the argument type is convertile to `const T&`.
|
|
||||||
const T& arg = get<N>(args...);
|
|
||||||
return write<Char>(out, arg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, typename T, int N>
|
|
||||||
struct is_compiled_format<field<Char, T, N>> : std::true_type {};
|
|
||||||
|
|
||||||
// A replacement field that refers to argument N and has format specifiers.
|
|
||||||
template <typename Char, typename T, int N> struct spec_field {
|
|
||||||
using char_type = Char;
|
|
||||||
mutable formatter<T, Char> fmt;
|
|
||||||
|
|
||||||
template <typename OutputIt, typename... Args>
|
|
||||||
OutputIt format(OutputIt out, const Args&... args) const {
|
|
||||||
// This ensures that the argument type is convertile to `const T&`.
|
|
||||||
const T& arg = get<N>(args...);
|
|
||||||
const auto& vargs =
|
|
||||||
make_format_args<basic_format_context<OutputIt, Char>>(args...);
|
|
||||||
basic_format_context<OutputIt, Char> ctx(out, vargs);
|
|
||||||
return fmt.format(arg, ctx);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, typename T, int N>
|
|
||||||
struct is_compiled_format<spec_field<Char, T, N>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename L, typename R> struct concat {
|
|
||||||
L lhs;
|
|
||||||
R rhs;
|
|
||||||
using char_type = typename L::char_type;
|
|
||||||
|
|
||||||
template <typename OutputIt, typename... Args>
|
|
||||||
OutputIt format(OutputIt out, const Args&... args) const {
|
|
||||||
out = lhs.format(out, args...);
|
|
||||||
return rhs.format(out, args...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename L, typename R>
|
|
||||||
struct is_compiled_format<concat<L, R>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename L, typename R>
|
|
||||||
constexpr concat<L, R> make_concat(L lhs, R rhs) {
|
|
||||||
return {lhs, rhs};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct unknown_format {};
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
constexpr size_t parse_text(basic_string_view<Char> str, size_t pos) {
|
|
||||||
for (size_t size = str.size(); pos != size; ++pos) {
|
|
||||||
if (str[pos] == '{' || str[pos] == '}') break;
|
|
||||||
}
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Args, size_t POS, int ID, typename S>
|
|
||||||
constexpr auto compile_format_string(S format_str);
|
|
||||||
|
|
||||||
template <typename Args, size_t POS, int ID, typename T, typename S>
|
|
||||||
constexpr auto parse_tail(T head, S format_str) {
|
|
||||||
if constexpr (POS !=
|
|
||||||
basic_string_view<typename S::char_type>(format_str).size()) {
|
|
||||||
constexpr auto tail = compile_format_string<Args, POS, ID>(format_str);
|
|
||||||
if constexpr (std::is_same<remove_cvref_t<decltype(tail)>,
|
|
||||||
unknown_format>())
|
|
||||||
return tail;
|
|
||||||
else
|
|
||||||
return make_concat(head, tail);
|
|
||||||
} else {
|
|
||||||
return head;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename Char> struct parse_specs_result {
|
|
||||||
formatter<T, Char> fmt;
|
|
||||||
size_t end;
|
|
||||||
int next_arg_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename Char>
|
|
||||||
constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
|
|
||||||
size_t pos, int arg_id) {
|
|
||||||
str.remove_prefix(pos);
|
|
||||||
auto ctx = basic_format_parse_context<Char>(str, {}, arg_id + 1);
|
|
||||||
auto f = formatter<T, Char>();
|
|
||||||
auto end = f.parse(ctx);
|
|
||||||
return {f, pos + (end - str.data()) + 1, ctx.next_arg_id()};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compiles a non-empty format string and returns the compiled representation
|
|
||||||
// or unknown_format() on unrecognized input.
|
|
||||||
template <typename Args, size_t POS, int ID, typename S>
|
|
||||||
constexpr auto compile_format_string(S format_str) {
|
|
||||||
using char_type = typename S::char_type;
|
|
||||||
constexpr basic_string_view<char_type> str = format_str;
|
|
||||||
if constexpr (str[POS] == '{') {
|
|
||||||
if (POS + 1 == str.size())
|
|
||||||
throw format_error("unmatched '{' in format string");
|
|
||||||
if constexpr (str[POS + 1] == '{') {
|
|
||||||
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
|
|
||||||
} else if constexpr (str[POS + 1] == '}') {
|
|
||||||
using type = get_type<ID, Args>;
|
|
||||||
return parse_tail<Args, POS + 2, ID + 1>(field<char_type, type, ID>(),
|
|
||||||
format_str);
|
|
||||||
} else if constexpr (str[POS + 1] == ':') {
|
|
||||||
using type = get_type<ID, Args>;
|
|
||||||
constexpr auto result = parse_specs<type>(str, POS + 2, ID);
|
|
||||||
return parse_tail<Args, result.end, result.next_arg_id>(
|
|
||||||
spec_field<char_type, type, ID>{result.fmt}, format_str);
|
|
||||||
} else {
|
|
||||||
return unknown_format();
|
|
||||||
}
|
|
||||||
} else if constexpr (str[POS] == '}') {
|
|
||||||
if (POS + 1 == str.size())
|
|
||||||
throw format_error("unmatched '}' in format string");
|
|
||||||
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
|
|
||||||
} else {
|
|
||||||
constexpr auto end = parse_text(str, POS + 1);
|
|
||||||
if constexpr (end - POS > 1) {
|
|
||||||
return parse_tail<Args, end, ID>(make_text(str, POS, end - POS),
|
|
||||||
format_str);
|
|
||||||
} else {
|
|
||||||
return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]},
|
|
||||||
format_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args, typename S,
|
|
||||||
FMT_ENABLE_IF(is_compile_string<S>::value ||
|
|
||||||
detail::is_compiled_string<S>::value)>
|
|
||||||
constexpr auto compile(S format_str) {
|
|
||||||
constexpr basic_string_view<typename S::char_type> str = format_str;
|
|
||||||
if constexpr (str.size() == 0) {
|
|
||||||
return detail::make_text(str, 0, 0);
|
|
||||||
} else {
|
|
||||||
constexpr auto result =
|
|
||||||
detail::compile_format_string<detail::type_list<Args...>, 0, 0>(
|
|
||||||
format_str);
|
|
||||||
if constexpr (std::is_same<remove_cvref_t<decltype(result)>,
|
|
||||||
detail::unknown_format>()) {
|
|
||||||
return detail::compiled_format<S, Args...>(to_string_view(format_str));
|
|
||||||
} else {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
template <typename... Args, typename S,
|
|
||||||
FMT_ENABLE_IF(is_compile_string<S>::value)>
|
|
||||||
constexpr auto compile(S format_str) -> detail::compiled_format<S, Args...> {
|
|
||||||
return detail::compiled_format<S, Args...>(to_string_view(format_str));
|
|
||||||
}
|
|
||||||
#endif // __cpp_if_constexpr
|
|
||||||
|
|
||||||
// Compiles the format string which must be a string literal.
|
|
||||||
template <typename... Args, typename Char, size_t N>
|
|
||||||
auto compile(const Char (&format_str)[N])
|
|
||||||
-> detail::compiled_format<const Char*, Args...> {
|
|
||||||
return detail::compiled_format<const Char*, Args...>(
|
|
||||||
basic_string_view<Char>(format_str, N - 1));
|
|
||||||
}
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
// DEPRECATED! use FMT_COMPILE instead.
|
|
||||||
template <typename... Args>
|
|
||||||
FMT_DEPRECATED auto compile(const Args&... args)
|
|
||||||
-> decltype(detail::compile(args...)) {
|
|
||||||
return detail::compile(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FMT_USE_CONSTEXPR
|
|
||||||
# ifdef __cpp_if_constexpr
|
|
||||||
|
|
||||||
template <typename CompiledFormat, typename... Args,
|
|
||||||
typename Char = typename CompiledFormat::char_type,
|
|
||||||
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
|
|
||||||
FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf,
|
|
||||||
const Args&... args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
cf.format(detail::buffer_appender<Char>(buffer), args...);
|
|
||||||
return to_string(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
|
|
||||||
OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
|
||||||
const Args&... args) {
|
|
||||||
return cf.format(out, args...);
|
|
||||||
}
|
|
||||||
# endif // __cpp_if_constexpr
|
|
||||||
#endif // FMT_USE_CONSTEXPR
|
|
||||||
|
|
||||||
template <typename CompiledFormat, typename... Args,
|
|
||||||
typename Char = typename CompiledFormat::char_type,
|
|
||||||
FMT_ENABLE_IF(std::is_base_of<detail::basic_compiled_format,
|
|
||||||
CompiledFormat>::value)>
|
|
||||||
std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
using context = buffer_context<Char>;
|
|
||||||
detail::cf::vformat_to<context>(detail::buffer_appender<Char>(buffer), cf,
|
|
||||||
make_format_args<context>(args...));
|
|
||||||
return to_string(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
|
||||||
FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
|
||||||
Args&&... args) {
|
|
||||||
#ifdef __cpp_if_constexpr
|
|
||||||
if constexpr (std::is_same<typename S::char_type, char>::value) {
|
|
||||||
constexpr basic_string_view<typename S::char_type> str = S();
|
|
||||||
if (str.size() == 2 && str[0] == '{' && str[1] == '}')
|
|
||||||
return fmt::to_string(detail::first(args...));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
constexpr auto compiled = detail::compile<Args...>(S());
|
|
||||||
return format(compiled, std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
|
||||||
FMT_ENABLE_IF(std::is_base_of<detail::basic_compiled_format,
|
|
||||||
CompiledFormat>::value)>
|
|
||||||
OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
|
||||||
const Args&... args) {
|
|
||||||
using char_type = typename CompiledFormat::char_type;
|
|
||||||
using context = format_context_t<OutputIt, char_type>;
|
|
||||||
return detail::cf::vformat_to<context>(out, cf,
|
|
||||||
make_format_args<context>(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
|
||||||
OutputIt format_to(OutputIt out, const S&, const Args&... args) {
|
|
||||||
constexpr auto compiled = detail::compile<Args...>(S());
|
|
||||||
return format_to(out, compiled, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename OutputIt, typename CompiledFormat, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&& std::is_base_of<
|
|
||||||
detail::basic_compiled_format, CompiledFormat>::value)>
|
|
||||||
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
|
||||||
const CompiledFormat& cf,
|
|
||||||
const Args&... args) {
|
|
||||||
auto it =
|
|
||||||
format_to(detail::truncating_iterator<OutputIt>(out, n), cf, args...);
|
|
||||||
return {it.base(), it.count()};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
|
||||||
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n, const S&,
|
|
||||||
const Args&... args) {
|
|
||||||
constexpr auto compiled = detail::compile<Args...>(S());
|
|
||||||
auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), compiled,
|
|
||||||
args...);
|
|
||||||
return {it.base(), it.count()};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename CompiledFormat, typename... Args>
|
|
||||||
size_t formatted_size(const CompiledFormat& cf, const Args&... args) {
|
|
||||||
return format_to(detail::counting_iterator(), cf, args...).count();
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // FMT_COMPILE_H_
|
|
||||||
2129
src/3rdparty/fmt/fmt/core.h
vendored
2129
src/3rdparty/fmt/fmt/core.h
vendored
File diff suppressed because it is too large
Load Diff
2801
src/3rdparty/fmt/fmt/format-inl.h
vendored
2801
src/3rdparty/fmt/fmt/format-inl.h
vendored
File diff suppressed because it is too large
Load Diff
69
src/3rdparty/fmt/fmt/format.cc
vendored
69
src/3rdparty/fmt/fmt/format.cc
vendored
@@ -1,69 +0,0 @@
|
|||||||
// Formatting library for C++
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// For the license information refer to format.h.
|
|
||||||
|
|
||||||
#include "fmt/format-inl.h"
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
int format_float(char* buf, std::size_t size, const char* format, int precision,
|
|
||||||
T value) {
|
|
||||||
#ifdef FMT_FUZZ
|
|
||||||
if (precision > 100000)
|
|
||||||
throw std::runtime_error(
|
|
||||||
"fuzz mode - avoid large allocation inside snprintf");
|
|
||||||
#endif
|
|
||||||
// Suppress the warning about nonliteral format string.
|
|
||||||
int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;
|
|
||||||
return precision < 0 ? snprintf_ptr(buf, size, format, value)
|
|
||||||
: snprintf_ptr(buf, size, format, precision, value);
|
|
||||||
}
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template struct FMT_INSTANTIATION_DEF_API detail::basic_data<void>;
|
|
||||||
|
|
||||||
// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
|
|
||||||
int (*instantiate_format_float)(double, int, detail::float_specs,
|
|
||||||
detail::buffer<char>&) = detail::format_float;
|
|
||||||
|
|
||||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
|
||||||
template FMT_API detail::locale_ref::locale_ref(const std::locale& loc);
|
|
||||||
template FMT_API std::locale detail::locale_ref::get<std::locale>() const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Explicit instantiations for char.
|
|
||||||
|
|
||||||
template FMT_API std::string detail::grouping_impl<char>(locale_ref);
|
|
||||||
template FMT_API char detail::thousands_sep_impl(locale_ref);
|
|
||||||
template FMT_API char detail::decimal_point_impl(locale_ref);
|
|
||||||
|
|
||||||
template FMT_API void detail::buffer<char>::append(const char*, const char*);
|
|
||||||
|
|
||||||
template FMT_API FMT_BUFFER_CONTEXT(char)::iterator detail::vformat_to(
|
|
||||||
detail::buffer<char>&, string_view,
|
|
||||||
basic_format_args<FMT_BUFFER_CONTEXT(char)>);
|
|
||||||
|
|
||||||
template FMT_API int detail::snprintf_float(double, int, detail::float_specs,
|
|
||||||
detail::buffer<char>&);
|
|
||||||
template FMT_API int detail::snprintf_float(long double, int,
|
|
||||||
detail::float_specs,
|
|
||||||
detail::buffer<char>&);
|
|
||||||
template FMT_API int detail::format_float(double, int, detail::float_specs,
|
|
||||||
detail::buffer<char>&);
|
|
||||||
template FMT_API int detail::format_float(long double, int, detail::float_specs,
|
|
||||||
detail::buffer<char>&);
|
|
||||||
|
|
||||||
// Explicit instantiations for wchar_t.
|
|
||||||
|
|
||||||
template FMT_API std::string detail::grouping_impl<wchar_t>(locale_ref);
|
|
||||||
template FMT_API wchar_t detail::thousands_sep_impl(locale_ref);
|
|
||||||
template FMT_API wchar_t detail::decimal_point_impl(locale_ref);
|
|
||||||
|
|
||||||
template FMT_API void detail::buffer<wchar_t>::append(const wchar_t*,
|
|
||||||
const wchar_t*);
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
3869
src/3rdparty/fmt/fmt/format.h
vendored
3869
src/3rdparty/fmt/fmt/format.h
vendored
File diff suppressed because it is too large
Load Diff
78
src/3rdparty/fmt/fmt/locale.h
vendored
78
src/3rdparty/fmt/fmt/locale.h
vendored
@@ -1,78 +0,0 @@
|
|||||||
// Formatting library for C++ - std::locale support
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 - present, Victor Zverovich
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// For the license information refer to format.h.
|
|
||||||
|
|
||||||
#ifndef FMT_LOCALE_H_
|
|
||||||
#define FMT_LOCALE_H_
|
|
||||||
|
|
||||||
#include <locale>
|
|
||||||
|
|
||||||
#include "format.h"
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template <typename Char>
|
|
||||||
typename buffer_context<Char>::iterator vformat_to(
|
|
||||||
const std::locale& loc, buffer<Char>& buf,
|
|
||||||
basic_string_view<Char> format_str,
|
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
|
||||||
using af = arg_formatter<typename buffer_context<Char>::iterator, Char>;
|
|
||||||
return vformat_to<af>(buffer_appender<Char>(buf), to_string_view(format_str),
|
|
||||||
args, detail::locale_ref(loc));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
std::basic_string<Char> vformat(
|
|
||||||
const std::locale& loc, basic_string_view<Char> format_str,
|
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
detail::vformat_to(loc, buffer, format_str, args);
|
|
||||||
return fmt::to_string(buffer);
|
|
||||||
}
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
|
||||||
inline std::basic_string<Char> vformat(
|
|
||||||
const std::locale& loc, const S& format_str,
|
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
|
||||||
return detail::vformat(loc, to_string_view(format_str), args);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
|
||||||
inline std::basic_string<Char> format(const std::locale& loc,
|
|
||||||
const S& format_str, Args&&... args) {
|
|
||||||
return detail::vformat(
|
|
||||||
loc, to_string_view(format_str),
|
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename OutputIt, typename... Args,
|
|
||||||
typename Char = enable_if_t<
|
|
||||||
detail::is_output_iterator<OutputIt>::value, char_t<S>>>
|
|
||||||
inline OutputIt vformat_to(
|
|
||||||
OutputIt out, const std::locale& loc, const S& format_str,
|
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
|
||||||
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
|
|
||||||
using af =
|
|
||||||
detail::arg_formatter<typename buffer_context<Char>::iterator, Char>;
|
|
||||||
vformat_to<af>(detail::buffer_appender<Char>(buf), to_string_view(format_str),
|
|
||||||
args, detail::locale_ref(loc));
|
|
||||||
return detail::get_iterator(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&&
|
|
||||||
detail::is_string<S>::value)>
|
|
||||||
inline OutputIt format_to(OutputIt out, const std::locale& loc,
|
|
||||||
const S& format_str, Args&&... args) {
|
|
||||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
|
||||||
return vformat_to(out, loc, to_string_view(format_str), vargs);
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // FMT_LOCALE_H_
|
|
||||||
322
src/3rdparty/fmt/fmt/os.cc
vendored
322
src/3rdparty/fmt/fmt/os.cc
vendored
@@ -1,322 +0,0 @@
|
|||||||
// Formatting library for C++ - optional OS-specific functionality
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// For the license information refer to format.h.
|
|
||||||
|
|
||||||
// Disable bogus MSVC warnings.
|
|
||||||
#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER)
|
|
||||||
# define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "fmt/os.h"
|
|
||||||
|
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
#if FMT_USE_FCNTL
|
|
||||||
# include <sys/stat.h>
|
|
||||||
# include <sys/types.h>
|
|
||||||
|
|
||||||
# ifndef _WIN32
|
|
||||||
# include <unistd.h>
|
|
||||||
# else
|
|
||||||
# ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
# define WIN32_LEAN_AND_MEAN
|
|
||||||
# endif
|
|
||||||
# include <io.h>
|
|
||||||
# include <windows.h>
|
|
||||||
|
|
||||||
# define O_CREAT _O_CREAT
|
|
||||||
# define O_TRUNC _O_TRUNC
|
|
||||||
|
|
||||||
# ifndef S_IRUSR
|
|
||||||
# define S_IRUSR _S_IREAD
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifndef S_IWUSR
|
|
||||||
# define S_IWUSR _S_IWRITE
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef __MINGW32__
|
|
||||||
# define _SH_DENYNO 0x40
|
|
||||||
# endif
|
|
||||||
# endif // _WIN32
|
|
||||||
#endif // FMT_USE_FCNTL
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
# include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef fileno
|
|
||||||
# undef fileno
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
#ifdef _WIN32
|
|
||||||
// Return type of read and write functions.
|
|
||||||
using RWResult = int;
|
|
||||||
|
|
||||||
// On Windows the count argument to read and write is unsigned, so convert
|
|
||||||
// it from size_t preventing integer overflow.
|
|
||||||
inline unsigned convert_rwcount(std::size_t count) {
|
|
||||||
return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Return type of read and write functions.
|
|
||||||
using RWResult = ssize_t;
|
|
||||||
|
|
||||||
inline std::size_t convert_rwcount(std::size_t count) { return count; }
|
|
||||||
#endif
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
detail::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
|
|
||||||
if (int error_code = convert(s)) {
|
|
||||||
FMT_THROW(windows_error(error_code,
|
|
||||||
"cannot convert string from UTF-16 to UTF-8"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int detail::utf16_to_utf8::convert(wstring_view s) {
|
|
||||||
if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER;
|
|
||||||
int s_size = static_cast<int>(s.size());
|
|
||||||
if (s_size == 0) {
|
|
||||||
// WideCharToMultiByte does not support zero length, handle separately.
|
|
||||||
buffer_.resize(1);
|
|
||||||
buffer_[0] = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, nullptr, 0,
|
|
||||||
nullptr, nullptr);
|
|
||||||
if (length == 0) return GetLastError();
|
|
||||||
buffer_.resize(length + 1);
|
|
||||||
length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, &buffer_[0],
|
|
||||||
length, nullptr, nullptr);
|
|
||||||
if (length == 0) return GetLastError();
|
|
||||||
buffer_[length] = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void windows_error::init(int err_code, string_view format_str,
|
|
||||||
format_args args) {
|
|
||||||
error_code_ = err_code;
|
|
||||||
memory_buffer buffer;
|
|
||||||
detail::format_windows_error(buffer, err_code, vformat(format_str, args));
|
|
||||||
std::runtime_error& base = *this;
|
|
||||||
base = std::runtime_error(to_string(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
void detail::format_windows_error(detail::buffer<char>& out, int error_code,
|
|
||||||
string_view message) FMT_NOEXCEPT {
|
|
||||||
FMT_TRY {
|
|
||||||
wmemory_buffer buf;
|
|
||||||
buf.resize(inline_buffer_size);
|
|
||||||
for (;;) {
|
|
||||||
wchar_t* system_message = &buf[0];
|
|
||||||
int result = FormatMessageW(
|
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
|
|
||||||
error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), system_message,
|
|
||||||
static_cast<uint32_t>(buf.size()), nullptr);
|
|
||||||
if (result != 0) {
|
|
||||||
utf16_to_utf8 utf8_message;
|
|
||||||
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
|
|
||||||
format_to(buffer_appender<char>(out), "{}: {}", message,
|
|
||||||
utf8_message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
|
||||||
break; // Can't get error message, report error code instead.
|
|
||||||
buf.resize(buf.size() * 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FMT_CATCH(...) {}
|
|
||||||
format_error_code(out, error_code, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void report_windows_error(int error_code,
|
|
||||||
fmt::string_view message) FMT_NOEXCEPT {
|
|
||||||
report_error(detail::format_windows_error, error_code, message);
|
|
||||||
}
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
buffered_file::~buffered_file() FMT_NOEXCEPT {
|
|
||||||
if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
|
|
||||||
report_system_error(errno, "cannot close file");
|
|
||||||
}
|
|
||||||
|
|
||||||
buffered_file::buffered_file(cstring_view filename, cstring_view mode) {
|
|
||||||
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())),
|
|
||||||
nullptr);
|
|
||||||
if (!file_)
|
|
||||||
FMT_THROW(system_error(errno, "cannot open file {}", filename.c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void buffered_file::close() {
|
|
||||||
if (!file_) return;
|
|
||||||
int result = FMT_SYSTEM(fclose(file_));
|
|
||||||
file_ = nullptr;
|
|
||||||
if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// A macro used to prevent expansion of fileno on broken versions of MinGW.
|
|
||||||
#define FMT_ARGS
|
|
||||||
|
|
||||||
int buffered_file::fileno() const {
|
|
||||||
int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
|
|
||||||
if (fd == -1) FMT_THROW(system_error(errno, "cannot get file descriptor"));
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FMT_USE_FCNTL
|
|
||||||
file::file(cstring_view path, int oflag) {
|
|
||||||
int mode = S_IRUSR | S_IWUSR;
|
|
||||||
# if defined(_WIN32) && !defined(__MINGW32__)
|
|
||||||
fd_ = -1;
|
|
||||||
FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
|
|
||||||
# else
|
|
||||||
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
|
|
||||||
# endif
|
|
||||||
if (fd_ == -1)
|
|
||||||
FMT_THROW(system_error(errno, "cannot open file {}", path.c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
file::~file() FMT_NOEXCEPT {
|
|
||||||
// Don't retry close in case of EINTR!
|
|
||||||
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
|
|
||||||
if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
|
|
||||||
report_system_error(errno, "cannot close file");
|
|
||||||
}
|
|
||||||
|
|
||||||
void file::close() {
|
|
||||||
if (fd_ == -1) return;
|
|
||||||
// Don't retry close in case of EINTR!
|
|
||||||
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
|
|
||||||
int result = FMT_POSIX_CALL(close(fd_));
|
|
||||||
fd_ = -1;
|
|
||||||
if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
|
|
||||||
}
|
|
||||||
|
|
||||||
long long file::size() const {
|
|
||||||
# ifdef _WIN32
|
|
||||||
// Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT
|
|
||||||
// is less than 0x0500 as is the case with some default MinGW builds.
|
|
||||||
// Both functions support large file sizes.
|
|
||||||
DWORD size_upper = 0;
|
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd_));
|
|
||||||
DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper));
|
|
||||||
if (size_lower == INVALID_FILE_SIZE) {
|
|
||||||
DWORD error = GetLastError();
|
|
||||||
if (error != NO_ERROR)
|
|
||||||
FMT_THROW(windows_error(GetLastError(), "cannot get file size"));
|
|
||||||
}
|
|
||||||
unsigned long long long_size = size_upper;
|
|
||||||
return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
|
|
||||||
# else
|
|
||||||
using Stat = struct stat;
|
|
||||||
Stat file_stat = Stat();
|
|
||||||
if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
|
|
||||||
FMT_THROW(system_error(errno, "cannot get file attributes"));
|
|
||||||
static_assert(sizeof(long long) >= sizeof(file_stat.st_size),
|
|
||||||
"return type of file::size is not large enough");
|
|
||||||
return file_stat.st_size;
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t file::read(void* buffer, std::size_t count) {
|
|
||||||
RWResult result = 0;
|
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
|
|
||||||
if (result < 0) FMT_THROW(system_error(errno, "cannot read from file"));
|
|
||||||
return detail::to_unsigned(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t file::write(const void* buffer, std::size_t count) {
|
|
||||||
RWResult result = 0;
|
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
|
|
||||||
if (result < 0) FMT_THROW(system_error(errno, "cannot write to file"));
|
|
||||||
return detail::to_unsigned(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
file file::dup(int fd) {
|
|
||||||
// Don't retry as dup doesn't return EINTR.
|
|
||||||
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
|
|
||||||
int new_fd = FMT_POSIX_CALL(dup(fd));
|
|
||||||
if (new_fd == -1)
|
|
||||||
FMT_THROW(system_error(errno, "cannot duplicate file descriptor {}", fd));
|
|
||||||
return file(new_fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void file::dup2(int fd) {
|
|
||||||
int result = 0;
|
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
|
||||||
if (result == -1) {
|
|
||||||
FMT_THROW(system_error(errno, "cannot duplicate file descriptor {} to {}",
|
|
||||||
fd_, fd));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void file::dup2(int fd, error_code& ec) FMT_NOEXCEPT {
|
|
||||||
int result = 0;
|
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
|
||||||
if (result == -1) ec = error_code(errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
void file::pipe(file& read_end, file& write_end) {
|
|
||||||
// Close the descriptors first to make sure that assignments don't throw
|
|
||||||
// and there are no leaks.
|
|
||||||
read_end.close();
|
|
||||||
write_end.close();
|
|
||||||
int fds[2] = {};
|
|
||||||
# ifdef _WIN32
|
|
||||||
// Make the default pipe capacity same as on Linux 2.6.11+.
|
|
||||||
enum { DEFAULT_CAPACITY = 65536 };
|
|
||||||
int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
|
|
||||||
# else
|
|
||||||
// Don't retry as the pipe function doesn't return EINTR.
|
|
||||||
// http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
|
|
||||||
int result = FMT_POSIX_CALL(pipe(fds));
|
|
||||||
# endif
|
|
||||||
if (result != 0) FMT_THROW(system_error(errno, "cannot create pipe"));
|
|
||||||
// The following assignments don't throw because read_fd and write_fd
|
|
||||||
// are closed.
|
|
||||||
read_end = file(fds[0]);
|
|
||||||
write_end = file(fds[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffered_file file::fdopen(const char* mode) {
|
|
||||||
// Don't retry as fdopen doesn't return EINTR.
|
|
||||||
# if defined(__MINGW32__) && defined(_POSIX_)
|
|
||||||
FILE* f = ::fdopen(fd_, mode);
|
|
||||||
# else
|
|
||||||
FILE* f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
|
||||||
# endif
|
|
||||||
if (!f)
|
|
||||||
FMT_THROW(
|
|
||||||
system_error(errno, "cannot associate stream with file descriptor"));
|
|
||||||
buffered_file bf(f);
|
|
||||||
fd_ = -1;
|
|
||||||
return bf;
|
|
||||||
}
|
|
||||||
|
|
||||||
long getpagesize() {
|
|
||||||
# ifdef _WIN32
|
|
||||||
SYSTEM_INFO si;
|
|
||||||
GetSystemInfo(&si);
|
|
||||||
return si.dwPageSize;
|
|
||||||
# else
|
|
||||||
long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
|
|
||||||
if (size < 0) FMT_THROW(system_error(errno, "cannot get memory page size"));
|
|
||||||
return size;
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void ostream::grow(size_t) {
|
|
||||||
if (this->size() == this->capacity()) flush();
|
|
||||||
}
|
|
||||||
#endif // FMT_USE_FCNTL
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
480
src/3rdparty/fmt/fmt/os.h
vendored
480
src/3rdparty/fmt/fmt/os.h
vendored
@@ -1,480 +0,0 @@
|
|||||||
// Formatting library for C++ - optional OS-specific functionality
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 - present, Victor Zverovich
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// For the license information refer to format.h.
|
|
||||||
|
|
||||||
#ifndef FMT_OS_H_
|
|
||||||
#define FMT_OS_H_
|
|
||||||
|
|
||||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
|
||||||
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
|
|
||||||
# undef __STRICT_ANSI__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cerrno>
|
|
||||||
#include <clocale> // for locale_t
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib> // for strtod_l
|
|
||||||
|
|
||||||
#if defined __APPLE__ || defined(__FreeBSD__)
|
|
||||||
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "format.h"
|
|
||||||
|
|
||||||
// UWP doesn't provide _pipe.
|
|
||||||
#if FMT_HAS_INCLUDE("winapifamily.h")
|
|
||||||
# include <winapifamily.h>
|
|
||||||
#endif
|
|
||||||
#if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
|
|
||||||
defined(__linux__)) && \
|
|
||||||
(!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
|
|
||||||
# include <fcntl.h> // for O_RDONLY
|
|
||||||
# define FMT_USE_FCNTL 1
|
|
||||||
#else
|
|
||||||
# define FMT_USE_FCNTL 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FMT_POSIX
|
|
||||||
# if defined(_WIN32) && !defined(__MINGW32__)
|
|
||||||
// Fix warnings about deprecated symbols.
|
|
||||||
# define FMT_POSIX(call) _##call
|
|
||||||
# else
|
|
||||||
# define FMT_POSIX(call) call
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
|
|
||||||
#ifdef FMT_SYSTEM
|
|
||||||
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
|
|
||||||
#else
|
|
||||||
# define FMT_SYSTEM(call) ::call
|
|
||||||
# ifdef _WIN32
|
|
||||||
// Fix warnings about deprecated symbols.
|
|
||||||
# define FMT_POSIX_CALL(call) ::_##call
|
|
||||||
# else
|
|
||||||
# define FMT_POSIX_CALL(call) ::call
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Retries the expression while it evaluates to error_result and errno
|
|
||||||
// equals to EINTR.
|
|
||||||
#ifndef _WIN32
|
|
||||||
# define FMT_RETRY_VAL(result, expression, error_result) \
|
|
||||||
do { \
|
|
||||||
(result) = (expression); \
|
|
||||||
} while ((result) == (error_result) && errno == EINTR)
|
|
||||||
#else
|
|
||||||
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
A reference to a null-terminated string. It can be constructed from a C
|
|
||||||
string or ``std::string``.
|
|
||||||
|
|
||||||
You can use one of the following type aliases for common character types:
|
|
||||||
|
|
||||||
+---------------+-----------------------------+
|
|
||||||
| Type | Definition |
|
|
||||||
+===============+=============================+
|
|
||||||
| cstring_view | basic_cstring_view<char> |
|
|
||||||
+---------------+-----------------------------+
|
|
||||||
| wcstring_view | basic_cstring_view<wchar_t> |
|
|
||||||
+---------------+-----------------------------+
|
|
||||||
|
|
||||||
This class is most useful as a parameter type to allow passing
|
|
||||||
different types of strings to a function, for example::
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
std::string format(cstring_view format_str, const Args & ... args);
|
|
||||||
|
|
||||||
format("{}", 42);
|
|
||||||
format(std::string("{}"), 42);
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename Char> class basic_cstring_view {
|
|
||||||
private:
|
|
||||||
const Char* data_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** Constructs a string reference object from a C string. */
|
|
||||||
basic_cstring_view(const Char* s) : data_(s) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Constructs a string reference from an ``std::string`` object.
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}
|
|
||||||
|
|
||||||
/** Returns the pointer to a C string. */
|
|
||||||
const Char* c_str() const { return data_; }
|
|
||||||
};
|
|
||||||
|
|
||||||
using cstring_view = basic_cstring_view<char>;
|
|
||||||
using wcstring_view = basic_cstring_view<wchar_t>;
|
|
||||||
|
|
||||||
// An error code.
|
|
||||||
class error_code {
|
|
||||||
private:
|
|
||||||
int value_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit error_code(int value = 0) FMT_NOEXCEPT : value_(value) {}
|
|
||||||
|
|
||||||
int get() const FMT_NOEXCEPT { return value_; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
namespace detail {
|
|
||||||
// A converter from UTF-16 to UTF-8.
|
|
||||||
// It is only provided for Windows since other systems support UTF-8 natively.
|
|
||||||
class utf16_to_utf8 {
|
|
||||||
private:
|
|
||||||
memory_buffer buffer_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
utf16_to_utf8() {}
|
|
||||||
FMT_API explicit utf16_to_utf8(wstring_view s);
|
|
||||||
operator string_view() const { return string_view(&buffer_[0], size()); }
|
|
||||||
size_t size() const { return buffer_.size() - 1; }
|
|
||||||
const char* c_str() const { return &buffer_[0]; }
|
|
||||||
std::string str() const { return std::string(&buffer_[0], size()); }
|
|
||||||
|
|
||||||
// Performs conversion returning a system error code instead of
|
|
||||||
// throwing exception on conversion error. This method may still throw
|
|
||||||
// in case of memory allocation error.
|
|
||||||
FMT_API int convert(wstring_view s);
|
|
||||||
};
|
|
||||||
|
|
||||||
FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
|
||||||
string_view message) FMT_NOEXCEPT;
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
/** A Windows error. */
|
|
||||||
class windows_error : public system_error {
|
|
||||||
private:
|
|
||||||
FMT_API void init(int error_code, string_view format_str, format_args args);
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Constructs a :class:`fmt::windows_error` object with the description
|
|
||||||
of the form
|
|
||||||
|
|
||||||
.. parsed-literal::
|
|
||||||
*<message>*: *<system-message>*
|
|
||||||
|
|
||||||
where *<message>* is the formatted message and *<system-message>* is the
|
|
||||||
system message corresponding to the error code.
|
|
||||||
*error_code* is a Windows error code as given by ``GetLastError``.
|
|
||||||
If *error_code* is not a valid error code such as -1, the system message
|
|
||||||
will look like "error -1".
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
// This throws a windows_error with the description
|
|
||||||
// cannot open file 'madeup': The system cannot find the file specified.
|
|
||||||
// or similar (system message may vary).
|
|
||||||
const char *filename = "madeup";
|
|
||||||
LPOFSTRUCT of = LPOFSTRUCT();
|
|
||||||
HFILE file = OpenFile(filename, &of, OF_READ);
|
|
||||||
if (file == HFILE_ERROR) {
|
|
||||||
throw fmt::windows_error(GetLastError(),
|
|
||||||
"cannot open file '{}'", filename);
|
|
||||||
}
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename... Args>
|
|
||||||
windows_error(int error_code, string_view message, const Args&... args) {
|
|
||||||
init(error_code, message, make_format_args(args...));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Reports a Windows error without throwing an exception.
|
|
||||||
// Can be used to report errors from destructors.
|
|
||||||
FMT_API void report_windows_error(int error_code,
|
|
||||||
string_view message) FMT_NOEXCEPT;
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
// A buffered file.
|
|
||||||
class buffered_file {
|
|
||||||
private:
|
|
||||||
FILE* file_;
|
|
||||||
|
|
||||||
friend class file;
|
|
||||||
|
|
||||||
explicit buffered_file(FILE* f) : file_(f) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
buffered_file(const buffered_file&) = delete;
|
|
||||||
void operator=(const buffered_file&) = delete;
|
|
||||||
|
|
||||||
// Constructs a buffered_file object which doesn't represent any file.
|
|
||||||
buffered_file() FMT_NOEXCEPT : file_(nullptr) {}
|
|
||||||
|
|
||||||
// Destroys the object closing the file it represents if any.
|
|
||||||
FMT_API ~buffered_file() FMT_NOEXCEPT;
|
|
||||||
|
|
||||||
public:
|
|
||||||
buffered_file(buffered_file&& other) FMT_NOEXCEPT : file_(other.file_) {
|
|
||||||
other.file_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffered_file& operator=(buffered_file&& other) {
|
|
||||||
close();
|
|
||||||
file_ = other.file_;
|
|
||||||
other.file_ = nullptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opens a file.
|
|
||||||
FMT_API buffered_file(cstring_view filename, cstring_view mode);
|
|
||||||
|
|
||||||
// Closes the file.
|
|
||||||
FMT_API void close();
|
|
||||||
|
|
||||||
// Returns the pointer to a FILE object representing this file.
|
|
||||||
FILE* get() const FMT_NOEXCEPT { return file_; }
|
|
||||||
|
|
||||||
// We place parentheses around fileno to workaround a bug in some versions
|
|
||||||
// of MinGW that define fileno as a macro.
|
|
||||||
FMT_API int(fileno)() const;
|
|
||||||
|
|
||||||
void vprint(string_view format_str, format_args args) {
|
|
||||||
fmt::vprint(file_, format_str, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
inline void print(string_view format_str, const Args&... args) {
|
|
||||||
vprint(format_str, make_format_args(args...));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if FMT_USE_FCNTL
|
|
||||||
// A file. Closed file is represented by a file object with descriptor -1.
|
|
||||||
// Methods that are not declared with FMT_NOEXCEPT may throw
|
|
||||||
// fmt::system_error in case of failure. Note that some errors such as
|
|
||||||
// closing the file multiple times will cause a crash on Windows rather
|
|
||||||
// than an exception. You can get standard behavior by overriding the
|
|
||||||
// invalid parameter handler with _set_invalid_parameter_handler.
|
|
||||||
class file {
|
|
||||||
private:
|
|
||||||
int fd_; // File descriptor.
|
|
||||||
|
|
||||||
// Constructs a file object with a given descriptor.
|
|
||||||
explicit file(int fd) : fd_(fd) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Possible values for the oflag argument to the constructor.
|
|
||||||
enum {
|
|
||||||
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
|
|
||||||
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
|
|
||||||
RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing.
|
|
||||||
CREATE = FMT_POSIX(O_CREAT), // Create if the file doesn't exist.
|
|
||||||
APPEND = FMT_POSIX(O_APPEND) // Open in append mode.
|
|
||||||
};
|
|
||||||
|
|
||||||
// Constructs a file object which doesn't represent any file.
|
|
||||||
file() FMT_NOEXCEPT : fd_(-1) {}
|
|
||||||
|
|
||||||
// Opens a file and constructs a file object representing this file.
|
|
||||||
FMT_API file(cstring_view path, int oflag);
|
|
||||||
|
|
||||||
public:
|
|
||||||
file(const file&) = delete;
|
|
||||||
void operator=(const file&) = delete;
|
|
||||||
|
|
||||||
file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; }
|
|
||||||
|
|
||||||
file& operator=(file&& other) FMT_NOEXCEPT {
|
|
||||||
close();
|
|
||||||
fd_ = other.fd_;
|
|
||||||
other.fd_ = -1;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroys the object closing the file it represents if any.
|
|
||||||
FMT_API ~file() FMT_NOEXCEPT;
|
|
||||||
|
|
||||||
// Returns the file descriptor.
|
|
||||||
int descriptor() const FMT_NOEXCEPT { return fd_; }
|
|
||||||
|
|
||||||
// Closes the file.
|
|
||||||
FMT_API void close();
|
|
||||||
|
|
||||||
// Returns the file size. The size has signed type for consistency with
|
|
||||||
// stat::st_size.
|
|
||||||
FMT_API long long size() const;
|
|
||||||
|
|
||||||
// Attempts to read count bytes from the file into the specified buffer.
|
|
||||||
FMT_API size_t read(void* buffer, size_t count);
|
|
||||||
|
|
||||||
// Attempts to write count bytes from the specified buffer to the file.
|
|
||||||
FMT_API size_t write(const void* buffer, size_t count);
|
|
||||||
|
|
||||||
// Duplicates a file descriptor with the dup function and returns
|
|
||||||
// the duplicate as a file object.
|
|
||||||
FMT_API static file dup(int fd);
|
|
||||||
|
|
||||||
// Makes fd be the copy of this file descriptor, closing fd first if
|
|
||||||
// necessary.
|
|
||||||
FMT_API void dup2(int fd);
|
|
||||||
|
|
||||||
// Makes fd be the copy of this file descriptor, closing fd first if
|
|
||||||
// necessary.
|
|
||||||
FMT_API void dup2(int fd, error_code& ec) FMT_NOEXCEPT;
|
|
||||||
|
|
||||||
// Creates a pipe setting up read_end and write_end file objects for reading
|
|
||||||
// and writing respectively.
|
|
||||||
FMT_API static void pipe(file& read_end, file& write_end);
|
|
||||||
|
|
||||||
// Creates a buffered_file object associated with this file and detaches
|
|
||||||
// this file object from the file.
|
|
||||||
FMT_API buffered_file fdopen(const char* mode);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns the memory page size.
|
|
||||||
long getpagesize();
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
struct buffer_size {
|
|
||||||
size_t value = 0;
|
|
||||||
buffer_size operator=(size_t val) const {
|
|
||||||
auto bs = buffer_size();
|
|
||||||
bs.value = val;
|
|
||||||
return bs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ostream_params {
|
|
||||||
int oflag = file::WRONLY | file::CREATE;
|
|
||||||
size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
|
|
||||||
|
|
||||||
ostream_params() {}
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
ostream_params(T... params, int oflag) : ostream_params(params...) {
|
|
||||||
this->oflag = oflag;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
ostream_params(T... params, detail::buffer_size bs)
|
|
||||||
: ostream_params(params...) {
|
|
||||||
this->buffer_size = bs.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
static constexpr detail::buffer_size buffer_size;
|
|
||||||
|
|
||||||
// A fast output stream which is not thread-safe.
|
|
||||||
class ostream : private detail::buffer<char> {
|
|
||||||
private:
|
|
||||||
file file_;
|
|
||||||
|
|
||||||
void flush() {
|
|
||||||
if (size() == 0) return;
|
|
||||||
file_.write(data(), size());
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void grow(size_t) final;
|
|
||||||
|
|
||||||
ostream(cstring_view path, const detail::ostream_params& params)
|
|
||||||
: file_(path, params.oflag) {
|
|
||||||
set(new char[params.buffer_size], params.buffer_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
ostream(ostream&& other)
|
|
||||||
: detail::buffer<char>(other.data(), other.size(), other.capacity()),
|
|
||||||
file_(std::move(other.file_)) {
|
|
||||||
other.set(nullptr, 0);
|
|
||||||
}
|
|
||||||
~ostream() {
|
|
||||||
flush();
|
|
||||||
delete[] data();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
friend ostream output_file(cstring_view path, T... params);
|
|
||||||
|
|
||||||
void close() {
|
|
||||||
flush();
|
|
||||||
file_.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename... Args>
|
|
||||||
void print(const S& format_str, const Args&... args) {
|
|
||||||
format_to(detail::buffer_appender<char>(*this), format_str, args...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
Opens a file for writing. Supported parameters passed in `params`:
|
|
||||||
* ``<integer>``: Output flags (``file::WRONLY | file::CREATE`` by default)
|
|
||||||
* ``buffer_size=<integer>``: Output buffer size
|
|
||||||
*/
|
|
||||||
template <typename... T>
|
|
||||||
inline ostream output_file(cstring_view path, T... params) {
|
|
||||||
return {path, detail::ostream_params(params...)};
|
|
||||||
}
|
|
||||||
#endif // FMT_USE_FCNTL
|
|
||||||
|
|
||||||
#ifdef FMT_LOCALE
|
|
||||||
// A "C" numeric locale.
|
|
||||||
class locale {
|
|
||||||
private:
|
|
||||||
# ifdef _WIN32
|
|
||||||
using locale_t = _locale_t;
|
|
||||||
|
|
||||||
static void freelocale(locale_t loc) { _free_locale(loc); }
|
|
||||||
|
|
||||||
static double strtod_l(const char* nptr, char** endptr, _locale_t loc) {
|
|
||||||
return _strtod_l(nptr, endptr, loc);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
locale_t locale_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using type = locale_t;
|
|
||||||
locale(const locale&) = delete;
|
|
||||||
void operator=(const locale&) = delete;
|
|
||||||
|
|
||||||
locale() {
|
|
||||||
# ifndef _WIN32
|
|
||||||
locale_ = FMT_SYSTEM(newlocale(LC_NUMERIC_MASK, "C", nullptr));
|
|
||||||
# else
|
|
||||||
locale_ = _create_locale(LC_NUMERIC, "C");
|
|
||||||
# endif
|
|
||||||
if (!locale_) FMT_THROW(system_error(errno, "cannot create locale"));
|
|
||||||
}
|
|
||||||
~locale() { freelocale(locale_); }
|
|
||||||
|
|
||||||
type get() const { return locale_; }
|
|
||||||
|
|
||||||
// Converts string to floating-point number and advances str past the end
|
|
||||||
// of the parsed input.
|
|
||||||
double strtod(const char*& str) const {
|
|
||||||
char* end = nullptr;
|
|
||||||
double result = strtod_l(str, &end, locale_);
|
|
||||||
str = end;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
using Locale FMT_DEPRECATED_ALIAS = locale;
|
|
||||||
#endif // FMT_LOCALE
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // FMT_OS_H_
|
|
||||||
177
src/3rdparty/fmt/fmt/ostream.h
vendored
177
src/3rdparty/fmt/fmt/ostream.h
vendored
@@ -1,177 +0,0 @@
|
|||||||
// Formatting library for C++ - std::ostream support
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 - present, Victor Zverovich
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// For the license information refer to format.h.
|
|
||||||
|
|
||||||
#ifndef FMT_OSTREAM_H_
|
|
||||||
#define FMT_OSTREAM_H_
|
|
||||||
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
#include "format.h"
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
template <typename Char> class basic_printf_parse_context;
|
|
||||||
template <typename OutputIt, typename Char> class basic_printf_context;
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template <class Char> class formatbuf : public std::basic_streambuf<Char> {
|
|
||||||
private:
|
|
||||||
using int_type = typename std::basic_streambuf<Char>::int_type;
|
|
||||||
using traits_type = typename std::basic_streambuf<Char>::traits_type;
|
|
||||||
|
|
||||||
buffer<Char>& buffer_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
formatbuf(buffer<Char>& buf) : buffer_(buf) {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// The put-area is actually always empty. This makes the implementation
|
|
||||||
// simpler and has the advantage that the streambuf and the buffer are always
|
|
||||||
// in sync and sputc never writes into uninitialized memory. The obvious
|
|
||||||
// disadvantage is that each call to sputc always results in a (virtual) call
|
|
||||||
// to overflow. There is no disadvantage here for sputn since this always
|
|
||||||
// results in a call to xsputn.
|
|
||||||
|
|
||||||
int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
|
|
||||||
if (!traits_type::eq_int_type(ch, traits_type::eof()))
|
|
||||||
buffer_.push_back(static_cast<Char>(ch));
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::streamsize xsputn(const Char* s, std::streamsize count) FMT_OVERRIDE {
|
|
||||||
buffer_.append(s, s + count);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct converter {
|
|
||||||
template <typename T, FMT_ENABLE_IF(is_integral<T>::value)> converter(T);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char> struct test_stream : std::basic_ostream<Char> {
|
|
||||||
private:
|
|
||||||
void_t<> operator<<(converter);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Hide insertion operators for built-in types.
|
|
||||||
template <typename Char, typename Traits>
|
|
||||||
void_t<> operator<<(std::basic_ostream<Char, Traits>&, Char);
|
|
||||||
template <typename Char, typename Traits>
|
|
||||||
void_t<> operator<<(std::basic_ostream<Char, Traits>&, char);
|
|
||||||
template <typename Traits>
|
|
||||||
void_t<> operator<<(std::basic_ostream<char, Traits>&, char);
|
|
||||||
template <typename Traits>
|
|
||||||
void_t<> operator<<(std::basic_ostream<char, Traits>&, signed char);
|
|
||||||
template <typename Traits>
|
|
||||||
void_t<> operator<<(std::basic_ostream<char, Traits>&, unsigned char);
|
|
||||||
|
|
||||||
// Checks if T has a user-defined operator<< (e.g. not a member of
|
|
||||||
// std::ostream).
|
|
||||||
template <typename T, typename Char> class is_streamable {
|
|
||||||
private:
|
|
||||||
template <typename U>
|
|
||||||
static bool_constant<!std::is_same<decltype(std::declval<test_stream<Char>&>()
|
|
||||||
<< std::declval<U>()),
|
|
||||||
void_t<>>::value>
|
|
||||||
test(int);
|
|
||||||
|
|
||||||
template <typename> static std::false_type test(...);
|
|
||||||
|
|
||||||
using result = decltype(test<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const bool value = result::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Write the content of buf to os.
|
|
||||||
template <typename Char>
|
|
||||||
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
|
|
||||||
const Char* buf_data = buf.data();
|
|
||||||
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
|
||||||
unsigned_streamsize size = buf.size();
|
|
||||||
unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
|
|
||||||
do {
|
|
||||||
unsigned_streamsize n = size <= max_size ? size : max_size;
|
|
||||||
os.write(buf_data, static_cast<std::streamsize>(n));
|
|
||||||
buf_data += n;
|
|
||||||
size -= n;
|
|
||||||
} while (size != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, typename T>
|
|
||||||
void format_value(buffer<Char>& buf, const T& value,
|
|
||||||
locale_ref loc = locale_ref()) {
|
|
||||||
formatbuf<Char> format_buf(buf);
|
|
||||||
std::basic_ostream<Char> output(&format_buf);
|
|
||||||
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
|
||||||
if (loc) output.imbue(loc.get<std::locale>());
|
|
||||||
#endif
|
|
||||||
output << value;
|
|
||||||
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
|
||||||
buf.try_resize(buf.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Formats an object of type T that has an overloaded ostream operator<<.
|
|
||||||
template <typename T, typename Char>
|
|
||||||
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
|
|
||||||
: private formatter<basic_string_view<Char>, Char> {
|
|
||||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
|
||||||
-> decltype(ctx.begin()) {
|
|
||||||
return formatter<basic_string_view<Char>, Char>::parse(ctx);
|
|
||||||
}
|
|
||||||
template <typename ParseCtx,
|
|
||||||
FMT_ENABLE_IF(std::is_same<
|
|
||||||
ParseCtx, basic_printf_parse_context<Char>>::value)>
|
|
||||||
auto parse(ParseCtx& ctx) -> decltype(ctx.begin()) {
|
|
||||||
return ctx.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt>
|
|
||||||
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx)
|
|
||||||
-> OutputIt {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
format_value(buffer, value, ctx.locale());
|
|
||||||
basic_string_view<Char> str(buffer.data(), buffer.size());
|
|
||||||
return formatter<basic_string_view<Char>, Char>::format(str, ctx);
|
|
||||||
}
|
|
||||||
template <typename OutputIt>
|
|
||||||
auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx)
|
|
||||||
-> OutputIt {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
format_value(buffer, value, ctx.locale());
|
|
||||||
return std::copy(buffer.begin(), buffer.end(), ctx.out());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
|
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
detail::vformat_to(buffer, format_str, args);
|
|
||||||
detail::write_buffer(os, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Prints formatted data to the stream *os*.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
fmt::print(cerr, "Don't {}!", "panic");
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename S, typename... Args,
|
|
||||||
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
|
||||||
void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {
|
|
||||||
vprint(os, to_string_view(format_str),
|
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
|
||||||
}
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // FMT_OSTREAM_H_
|
|
||||||
2
src/3rdparty/fmt/fmt/posix.h
vendored
2
src/3rdparty/fmt/fmt/posix.h
vendored
@@ -1,2 +0,0 @@
|
|||||||
#include "os.h"
|
|
||||||
#warning "fmt/posix.h is deprecated; use fmt/os.h instead"
|
|
||||||
751
src/3rdparty/fmt/fmt/printf.h
vendored
751
src/3rdparty/fmt/fmt/printf.h
vendored
@@ -1,751 +0,0 @@
|
|||||||
// Formatting library for C++ - legacy printf implementation
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// For the license information refer to format.h.
|
|
||||||
|
|
||||||
#ifndef FMT_PRINTF_H_
|
|
||||||
#define FMT_PRINTF_H_
|
|
||||||
|
|
||||||
#include <algorithm> // std::max
|
|
||||||
#include <limits> // std::numeric_limits
|
|
||||||
|
|
||||||
#include "ostream.h"
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
// Checks if a value fits in int - used to avoid warnings about comparing
|
|
||||||
// signed and unsigned integers.
|
|
||||||
template <bool IsSigned> struct int_checker {
|
|
||||||
template <typename T> static bool fits_in_int(T value) {
|
|
||||||
unsigned max = max_value<int>();
|
|
||||||
return value <= max;
|
|
||||||
}
|
|
||||||
static bool fits_in_int(bool) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> struct int_checker<true> {
|
|
||||||
template <typename T> static bool fits_in_int(T value) {
|
|
||||||
return value >= (std::numeric_limits<int>::min)() &&
|
|
||||||
value <= max_value<int>();
|
|
||||||
}
|
|
||||||
static bool fits_in_int(int) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class printf_precision_handler {
|
|
||||||
public:
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
|
||||||
int operator()(T value) {
|
|
||||||
if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
|
|
||||||
FMT_THROW(format_error("number is too big"));
|
|
||||||
return (std::max)(static_cast<int>(value), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
|
||||||
int operator()(T) {
|
|
||||||
FMT_THROW(format_error("precision is not integer"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// An argument visitor that returns true iff arg is a zero integer.
|
|
||||||
class is_zero_int {
|
|
||||||
public:
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
|
||||||
bool operator()(T value) {
|
|
||||||
return value == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
|
||||||
bool operator()(T) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> struct make_unsigned_or_bool : std::make_unsigned<T> {};
|
|
||||||
|
|
||||||
template <> struct make_unsigned_or_bool<bool> { using type = bool; };
|
|
||||||
|
|
||||||
template <typename T, typename Context> class arg_converter {
|
|
||||||
private:
|
|
||||||
using char_type = typename Context::char_type;
|
|
||||||
|
|
||||||
basic_format_arg<Context>& arg_;
|
|
||||||
char_type type_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
arg_converter(basic_format_arg<Context>& arg, char_type type)
|
|
||||||
: arg_(arg), type_(type) {}
|
|
||||||
|
|
||||||
void operator()(bool value) {
|
|
||||||
if (type_ != 's') operator()<bool>(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U, FMT_ENABLE_IF(std::is_integral<U>::value)>
|
|
||||||
void operator()(U value) {
|
|
||||||
bool is_signed = type_ == 'd' || type_ == 'i';
|
|
||||||
using target_type = conditional_t<std::is_same<T, void>::value, U, T>;
|
|
||||||
if (const_check(sizeof(target_type) <= sizeof(int))) {
|
|
||||||
// Extra casts are used to silence warnings.
|
|
||||||
if (is_signed) {
|
|
||||||
arg_ = detail::make_arg<Context>(
|
|
||||||
static_cast<int>(static_cast<target_type>(value)));
|
|
||||||
} else {
|
|
||||||
using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
|
|
||||||
arg_ = detail::make_arg<Context>(
|
|
||||||
static_cast<unsigned>(static_cast<unsigned_type>(value)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (is_signed) {
|
|
||||||
// glibc's printf doesn't sign extend arguments of smaller types:
|
|
||||||
// std::printf("%lld", -42); // prints "4294967254"
|
|
||||||
// but we don't have to do the same because it's a UB.
|
|
||||||
arg_ = detail::make_arg<Context>(static_cast<long long>(value));
|
|
||||||
} else {
|
|
||||||
arg_ = detail::make_arg<Context>(
|
|
||||||
static_cast<typename make_unsigned_or_bool<U>::type>(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U, FMT_ENABLE_IF(!std::is_integral<U>::value)>
|
|
||||||
void operator()(U) {} // No conversion needed for non-integral types.
|
|
||||||
};
|
|
||||||
|
|
||||||
// Converts an integer argument to T for printf, if T is an integral type.
|
|
||||||
// If T is void, the argument is converted to corresponding signed or unsigned
|
|
||||||
// type depending on the type specifier: 'd' and 'i' - signed, other -
|
|
||||||
// unsigned).
|
|
||||||
template <typename T, typename Context, typename Char>
|
|
||||||
void convert_arg(basic_format_arg<Context>& arg, Char type) {
|
|
||||||
visit_format_arg(arg_converter<T, Context>(arg, type), arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts an integer argument to char for printf.
|
|
||||||
template <typename Context> class char_converter {
|
|
||||||
private:
|
|
||||||
basic_format_arg<Context>& arg_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit char_converter(basic_format_arg<Context>& arg) : arg_(arg) {}
|
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
|
||||||
void operator()(T value) {
|
|
||||||
arg_ = detail::make_arg<Context>(
|
|
||||||
static_cast<typename Context::char_type>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
|
||||||
void operator()(T) {} // No conversion needed for non-integral types.
|
|
||||||
};
|
|
||||||
|
|
||||||
// An argument visitor that return a pointer to a C string if argument is a
|
|
||||||
// string or null otherwise.
|
|
||||||
template <typename Char> struct get_cstring {
|
|
||||||
template <typename T> const Char* operator()(T) { return nullptr; }
|
|
||||||
const Char* operator()(const Char* s) { return s; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Checks if an argument is a valid printf width specifier and sets
|
|
||||||
// left alignment if it is negative.
|
|
||||||
template <typename Char> class printf_width_handler {
|
|
||||||
private:
|
|
||||||
using format_specs = basic_format_specs<Char>;
|
|
||||||
|
|
||||||
format_specs& specs_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
|
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
|
||||||
unsigned operator()(T value) {
|
|
||||||
auto width = static_cast<uint32_or_64_or_128_t<T>>(value);
|
|
||||||
if (detail::is_negative(value)) {
|
|
||||||
specs_.align = align::left;
|
|
||||||
width = 0 - width;
|
|
||||||
}
|
|
||||||
unsigned int_max = max_value<int>();
|
|
||||||
if (width > int_max) FMT_THROW(format_error("number is too big"));
|
|
||||||
return static_cast<unsigned>(width);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
|
||||||
unsigned operator()(T) {
|
|
||||||
FMT_THROW(format_error("width is not integer"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, typename Context>
|
|
||||||
void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
|
||||||
basic_format_args<Context> args) {
|
|
||||||
Context(buffer_appender<Char>(buf), format, args).format();
|
|
||||||
}
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
// For printing into memory_buffer.
|
|
||||||
template <typename Char, typename Context>
|
|
||||||
FMT_DEPRECATED void printf(detail::buffer<Char>& buf,
|
|
||||||
basic_string_view<Char> format,
|
|
||||||
basic_format_args<Context> args) {
|
|
||||||
return detail::vprintf(buf, format, args);
|
|
||||||
}
|
|
||||||
using detail::vprintf;
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
class basic_printf_parse_context : public basic_format_parse_context<Char> {
|
|
||||||
using basic_format_parse_context<Char>::basic_format_parse_context;
|
|
||||||
};
|
|
||||||
template <typename OutputIt, typename Char> class basic_printf_context;
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
The ``printf`` argument formatter.
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename OutputIt, typename Char>
|
|
||||||
class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> {
|
|
||||||
public:
|
|
||||||
using iterator = OutputIt;
|
|
||||||
|
|
||||||
private:
|
|
||||||
using char_type = Char;
|
|
||||||
using base = detail::arg_formatter_base<OutputIt, Char>;
|
|
||||||
using context_type = basic_printf_context<OutputIt, Char>;
|
|
||||||
|
|
||||||
context_type& context_;
|
|
||||||
|
|
||||||
void write_null_pointer(char) {
|
|
||||||
this->specs()->type = 0;
|
|
||||||
this->write("(nil)");
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_null_pointer(wchar_t) {
|
|
||||||
this->specs()->type = 0;
|
|
||||||
this->write(L"(nil)");
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
using format_specs = typename base::format_specs;
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Constructs an argument formatter object.
|
|
||||||
*buffer* is a reference to the output buffer and *specs* contains format
|
|
||||||
specifier information for standard argument types.
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
printf_arg_formatter(iterator iter, format_specs& specs, context_type& ctx)
|
|
||||||
: base(iter, &specs, detail::locale_ref()), context_(ctx) {}
|
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(fmt::detail::is_integral<T>::value)>
|
|
||||||
iterator operator()(T value) {
|
|
||||||
// MSVC2013 fails to compile separate overloads for bool and char_type so
|
|
||||||
// use std::is_same instead.
|
|
||||||
if (std::is_same<T, bool>::value) {
|
|
||||||
format_specs& fmt_specs = *this->specs();
|
|
||||||
if (fmt_specs.type != 's') return base::operator()(value ? 1 : 0);
|
|
||||||
fmt_specs.type = 0;
|
|
||||||
this->write(value != 0);
|
|
||||||
} else if (std::is_same<T, char_type>::value) {
|
|
||||||
format_specs& fmt_specs = *this->specs();
|
|
||||||
if (fmt_specs.type && fmt_specs.type != 'c')
|
|
||||||
return (*this)(static_cast<int>(value));
|
|
||||||
fmt_specs.sign = sign::none;
|
|
||||||
fmt_specs.alt = false;
|
|
||||||
fmt_specs.fill[0] = ' '; // Ignore '0' flag for char types.
|
|
||||||
// align::numeric needs to be overwritten here since the '0' flag is
|
|
||||||
// ignored for non-numeric types
|
|
||||||
if (fmt_specs.align == align::none || fmt_specs.align == align::numeric)
|
|
||||||
fmt_specs.align = align::right;
|
|
||||||
return base::operator()(value);
|
|
||||||
} else {
|
|
||||||
return base::operator()(value);
|
|
||||||
}
|
|
||||||
return this->out();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
|
||||||
iterator operator()(T value) {
|
|
||||||
return base::operator()(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Formats a null-terminated C string. */
|
|
||||||
iterator operator()(const char* value) {
|
|
||||||
if (value)
|
|
||||||
base::operator()(value);
|
|
||||||
else if (this->specs()->type == 'p')
|
|
||||||
write_null_pointer(char_type());
|
|
||||||
else
|
|
||||||
this->write("(null)");
|
|
||||||
return this->out();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Formats a null-terminated wide C string. */
|
|
||||||
iterator operator()(const wchar_t* value) {
|
|
||||||
if (value)
|
|
||||||
base::operator()(value);
|
|
||||||
else if (this->specs()->type == 'p')
|
|
||||||
write_null_pointer(char_type());
|
|
||||||
else
|
|
||||||
this->write(L"(null)");
|
|
||||||
return this->out();
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator operator()(basic_string_view<char_type> value) {
|
|
||||||
return base::operator()(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator operator()(monostate value) { return base::operator()(value); }
|
|
||||||
|
|
||||||
/** Formats a pointer. */
|
|
||||||
iterator operator()(const void* value) {
|
|
||||||
if (value) return base::operator()(value);
|
|
||||||
this->specs()->type = 0;
|
|
||||||
write_null_pointer(char_type());
|
|
||||||
return this->out();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Formats an argument of a custom (user-defined) type. */
|
|
||||||
iterator operator()(typename basic_format_arg<context_type>::handle handle) {
|
|
||||||
handle.format(context_.parse_context(), context_);
|
|
||||||
return this->out();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> struct printf_formatter {
|
|
||||||
printf_formatter() = delete;
|
|
||||||
|
|
||||||
template <typename ParseContext>
|
|
||||||
auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
|
||||||
return ctx.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FormatContext>
|
|
||||||
auto format(const T& value, FormatContext& ctx) -> decltype(ctx.out()) {
|
|
||||||
detail::format_value(detail::get_container(ctx.out()), value);
|
|
||||||
return ctx.out();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
This template formats data and writes the output through an output iterator.
|
|
||||||
*/
|
|
||||||
template <typename OutputIt, typename Char> class basic_printf_context {
|
|
||||||
public:
|
|
||||||
/** The character type for the output. */
|
|
||||||
using char_type = Char;
|
|
||||||
using iterator = OutputIt;
|
|
||||||
using format_arg = basic_format_arg<basic_printf_context>;
|
|
||||||
using parse_context_type = basic_printf_parse_context<Char>;
|
|
||||||
template <typename T> using formatter_type = printf_formatter<T>;
|
|
||||||
|
|
||||||
private:
|
|
||||||
using format_specs = basic_format_specs<char_type>;
|
|
||||||
|
|
||||||
OutputIt out_;
|
|
||||||
basic_format_args<basic_printf_context> args_;
|
|
||||||
parse_context_type parse_ctx_;
|
|
||||||
|
|
||||||
static void parse_flags(format_specs& specs, const Char*& it,
|
|
||||||
const Char* end);
|
|
||||||
|
|
||||||
// Returns the argument with specified index or, if arg_index is -1, the next
|
|
||||||
// argument.
|
|
||||||
format_arg get_arg(int arg_index = -1);
|
|
||||||
|
|
||||||
// Parses argument index, flags and width and returns the argument index.
|
|
||||||
int parse_header(const Char*& it, const Char* end, format_specs& specs);
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Constructs a ``printf_context`` object. References to the arguments are
|
|
||||||
stored in the context object so make sure they have appropriate lifetimes.
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
basic_printf_context(OutputIt out, basic_string_view<char_type> format_str,
|
|
||||||
basic_format_args<basic_printf_context> args)
|
|
||||||
: out_(out), args_(args), parse_ctx_(format_str) {}
|
|
||||||
|
|
||||||
OutputIt out() { return out_; }
|
|
||||||
void advance_to(OutputIt it) { out_ = it; }
|
|
||||||
|
|
||||||
detail::locale_ref locale() { return {}; }
|
|
||||||
|
|
||||||
format_arg arg(int id) const { return args_.get(id); }
|
|
||||||
|
|
||||||
parse_context_type& parse_context() { return parse_ctx_; }
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_error(const char* message) {
|
|
||||||
parse_ctx_.on_error(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Formats stored arguments and writes the output to the range. */
|
|
||||||
template <typename ArgFormatter = printf_arg_formatter<OutputIt, Char>>
|
|
||||||
OutputIt format();
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename OutputIt, typename Char>
|
|
||||||
void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& specs,
|
|
||||||
const Char*& it,
|
|
||||||
const Char* end) {
|
|
||||||
for (; it != end; ++it) {
|
|
||||||
switch (*it) {
|
|
||||||
case '-':
|
|
||||||
specs.align = align::left;
|
|
||||||
break;
|
|
||||||
case '+':
|
|
||||||
specs.sign = sign::plus;
|
|
||||||
break;
|
|
||||||
case '0':
|
|
||||||
specs.fill[0] = '0';
|
|
||||||
break;
|
|
||||||
case ' ':
|
|
||||||
if (specs.sign != sign::plus) {
|
|
||||||
specs.sign = sign::space;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '#':
|
|
||||||
specs.alt = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename Char>
|
|
||||||
typename basic_printf_context<OutputIt, Char>::format_arg
|
|
||||||
basic_printf_context<OutputIt, Char>::get_arg(int arg_index) {
|
|
||||||
if (arg_index < 0)
|
|
||||||
arg_index = parse_ctx_.next_arg_id();
|
|
||||||
else
|
|
||||||
parse_ctx_.check_arg_id(--arg_index);
|
|
||||||
return detail::get_arg(*this, arg_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename Char>
|
|
||||||
int basic_printf_context<OutputIt, Char>::parse_header(const Char*& it,
|
|
||||||
const Char* end,
|
|
||||||
format_specs& specs) {
|
|
||||||
int arg_index = -1;
|
|
||||||
char_type c = *it;
|
|
||||||
if (c >= '0' && c <= '9') {
|
|
||||||
// Parse an argument index (if followed by '$') or a width possibly
|
|
||||||
// preceded with '0' flag(s).
|
|
||||||
detail::error_handler eh;
|
|
||||||
int value = parse_nonnegative_int(it, end, eh);
|
|
||||||
if (it != end && *it == '$') { // value is an argument index
|
|
||||||
++it;
|
|
||||||
arg_index = value;
|
|
||||||
} else {
|
|
||||||
if (c == '0') specs.fill[0] = '0';
|
|
||||||
if (value != 0) {
|
|
||||||
// Nonzero value means that we parsed width and don't need to
|
|
||||||
// parse it or flags again, so return now.
|
|
||||||
specs.width = value;
|
|
||||||
return arg_index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parse_flags(specs, it, end);
|
|
||||||
// Parse width.
|
|
||||||
if (it != end) {
|
|
||||||
if (*it >= '0' && *it <= '9') {
|
|
||||||
detail::error_handler eh;
|
|
||||||
specs.width = parse_nonnegative_int(it, end, eh);
|
|
||||||
} else if (*it == '*') {
|
|
||||||
++it;
|
|
||||||
specs.width = static_cast<int>(visit_format_arg(
|
|
||||||
detail::printf_width_handler<char_type>(specs), get_arg()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return arg_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename Char>
|
|
||||||
template <typename ArgFormatter>
|
|
||||||
OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|
||||||
auto out = this->out();
|
|
||||||
const Char* start = parse_ctx_.begin();
|
|
||||||
const Char* end = parse_ctx_.end();
|
|
||||||
auto it = start;
|
|
||||||
while (it != end) {
|
|
||||||
char_type c = *it++;
|
|
||||||
if (c != '%') continue;
|
|
||||||
if (it != end && *it == c) {
|
|
||||||
out = std::copy(start, it, out);
|
|
||||||
start = ++it;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
out = std::copy(start, it - 1, out);
|
|
||||||
|
|
||||||
format_specs specs;
|
|
||||||
specs.align = align::right;
|
|
||||||
|
|
||||||
// Parse argument index, flags and width.
|
|
||||||
int arg_index = parse_header(it, end, specs);
|
|
||||||
if (arg_index == 0) on_error("argument not found");
|
|
||||||
|
|
||||||
// Parse precision.
|
|
||||||
if (it != end && *it == '.') {
|
|
||||||
++it;
|
|
||||||
c = it != end ? *it : 0;
|
|
||||||
if ('0' <= c && c <= '9') {
|
|
||||||
detail::error_handler eh;
|
|
||||||
specs.precision = parse_nonnegative_int(it, end, eh);
|
|
||||||
} else if (c == '*') {
|
|
||||||
++it;
|
|
||||||
specs.precision = static_cast<int>(
|
|
||||||
visit_format_arg(detail::printf_precision_handler(), get_arg()));
|
|
||||||
} else {
|
|
||||||
specs.precision = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
format_arg arg = get_arg(arg_index);
|
|
||||||
// For d, i, o, u, x, and X conversion specifiers, if a precision is
|
|
||||||
// specified, the '0' flag is ignored
|
|
||||||
if (specs.precision >= 0 && arg.is_integral())
|
|
||||||
specs.fill[0] =
|
|
||||||
' '; // Ignore '0' flag for non-numeric types or if '-' present.
|
|
||||||
if (specs.precision >= 0 && arg.type() == detail::type::cstring_type) {
|
|
||||||
auto str = visit_format_arg(detail::get_cstring<Char>(), arg);
|
|
||||||
auto str_end = str + specs.precision;
|
|
||||||
auto nul = std::find(str, str_end, Char());
|
|
||||||
arg = detail::make_arg<basic_printf_context>(basic_string_view<Char>(
|
|
||||||
str,
|
|
||||||
detail::to_unsigned(nul != str_end ? nul - str : specs.precision)));
|
|
||||||
}
|
|
||||||
if (specs.alt && visit_format_arg(detail::is_zero_int(), arg))
|
|
||||||
specs.alt = false;
|
|
||||||
if (specs.fill[0] == '0') {
|
|
||||||
if (arg.is_arithmetic() && specs.align != align::left)
|
|
||||||
specs.align = align::numeric;
|
|
||||||
else
|
|
||||||
specs.fill[0] = ' '; // Ignore '0' flag for non-numeric types or if '-'
|
|
||||||
// flag is also present.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse length and convert the argument to the required type.
|
|
||||||
c = it != end ? *it++ : 0;
|
|
||||||
char_type t = it != end ? *it : 0;
|
|
||||||
using detail::convert_arg;
|
|
||||||
switch (c) {
|
|
||||||
case 'h':
|
|
||||||
if (t == 'h') {
|
|
||||||
++it;
|
|
||||||
t = it != end ? *it : 0;
|
|
||||||
convert_arg<signed char>(arg, t);
|
|
||||||
} else {
|
|
||||||
convert_arg<short>(arg, t);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
if (t == 'l') {
|
|
||||||
++it;
|
|
||||||
t = it != end ? *it : 0;
|
|
||||||
convert_arg<long long>(arg, t);
|
|
||||||
} else {
|
|
||||||
convert_arg<long>(arg, t);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'j':
|
|
||||||
convert_arg<intmax_t>(arg, t);
|
|
||||||
break;
|
|
||||||
case 'z':
|
|
||||||
convert_arg<size_t>(arg, t);
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
convert_arg<std::ptrdiff_t>(arg, t);
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
// printf produces garbage when 'L' is omitted for long double, no
|
|
||||||
// need to do the same.
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
--it;
|
|
||||||
convert_arg<void>(arg, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse type.
|
|
||||||
if (it == end) FMT_THROW(format_error("invalid format string"));
|
|
||||||
specs.type = static_cast<char>(*it++);
|
|
||||||
if (arg.is_integral()) {
|
|
||||||
// Normalize type.
|
|
||||||
switch (specs.type) {
|
|
||||||
case 'i':
|
|
||||||
case 'u':
|
|
||||||
specs.type = 'd';
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
visit_format_arg(detail::char_converter<basic_printf_context>(arg),
|
|
||||||
arg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
start = it;
|
|
||||||
|
|
||||||
// Format argument.
|
|
||||||
out = visit_format_arg(ArgFormatter(out, specs, *this), arg);
|
|
||||||
}
|
|
||||||
return std::copy(start, it, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
using basic_printf_context_t =
|
|
||||||
basic_printf_context<detail::buffer_appender<Char>, Char>;
|
|
||||||
|
|
||||||
using printf_context = basic_printf_context_t<char>;
|
|
||||||
using wprintf_context = basic_printf_context_t<wchar_t>;
|
|
||||||
|
|
||||||
using printf_args = basic_format_args<printf_context>;
|
|
||||||
using wprintf_args = basic_format_args<wprintf_context>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Constructs an `~fmt::format_arg_store` object that contains references to
|
|
||||||
arguments and can be implicitly converted to `~fmt::printf_args`.
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename... Args>
|
|
||||||
inline format_arg_store<printf_context, Args...> make_printf_args(
|
|
||||||
const Args&... args) {
|
|
||||||
return {args...};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Constructs an `~fmt::format_arg_store` object that contains references to
|
|
||||||
arguments and can be implicitly converted to `~fmt::wprintf_args`.
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename... Args>
|
|
||||||
inline format_arg_store<wprintf_context, Args...> make_wprintf_args(
|
|
||||||
const Args&... args) {
|
|
||||||
return {args...};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
|
||||||
inline std::basic_string<Char> vsprintf(
|
|
||||||
const S& format,
|
|
||||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
vprintf(buffer, to_string_view(format), args);
|
|
||||||
return to_string(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Formats arguments and returns the result as a string.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
std::string message = fmt::sprintf("The answer is %d", 42);
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename S, typename... Args,
|
|
||||||
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
|
||||||
inline std::basic_string<Char> sprintf(const S& format, const Args&... args) {
|
|
||||||
using context = basic_printf_context_t<Char>;
|
|
||||||
return vsprintf(to_string_view(format), make_format_args<context>(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
|
||||||
inline int vfprintf(
|
|
||||||
std::FILE* f, const S& format,
|
|
||||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
vprintf(buffer, to_string_view(format), args);
|
|
||||||
size_t size = buffer.size();
|
|
||||||
return std::fwrite(buffer.data(), sizeof(Char), size, f) < size
|
|
||||||
? -1
|
|
||||||
: static_cast<int>(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Prints formatted data to the file *f*.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
fmt::fprintf(stderr, "Don't %s!", "panic");
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename S, typename... Args,
|
|
||||||
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
|
||||||
inline int fprintf(std::FILE* f, const S& format, const Args&... args) {
|
|
||||||
using context = basic_printf_context_t<Char>;
|
|
||||||
return vfprintf(f, to_string_view(format),
|
|
||||||
make_format_args<context>(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
|
||||||
inline int vprintf(
|
|
||||||
const S& format,
|
|
||||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
|
||||||
return vfprintf(stdout, to_string_view(format), args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Prints formatted data to ``stdout``.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
fmt::printf("Elapsed time: %.2f seconds", 1.23);
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename S, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_string<S>::value)>
|
|
||||||
inline int printf(const S& format_str, const Args&... args) {
|
|
||||||
using context = basic_printf_context_t<char_t<S>>;
|
|
||||||
return vprintf(to_string_view(format_str),
|
|
||||||
make_format_args<context>(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
|
||||||
inline int vfprintf(
|
|
||||||
std::basic_ostream<Char>& os, const S& format,
|
|
||||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
vprintf(buffer, to_string_view(format), args);
|
|
||||||
detail::write_buffer(os, buffer);
|
|
||||||
return static_cast<int>(buffer.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Formats arguments and writes the output to the range. */
|
|
||||||
template <typename ArgFormatter, typename Char,
|
|
||||||
typename Context =
|
|
||||||
basic_printf_context<typename ArgFormatter::iterator, Char>>
|
|
||||||
typename ArgFormatter::iterator vprintf(
|
|
||||||
detail::buffer<Char>& out, basic_string_view<Char> format_str,
|
|
||||||
basic_format_args<type_identity_t<Context>> args) {
|
|
||||||
typename ArgFormatter::iterator iter(out);
|
|
||||||
Context(iter, format_str, args).template format<ArgFormatter>();
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Prints formatted data to the stream *os*.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
fmt::fprintf(cerr, "Don't %s!", "panic");
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
|
||||||
inline int fprintf(std::basic_ostream<Char>& os, const S& format_str,
|
|
||||||
const Args&... args) {
|
|
||||||
using context = basic_printf_context_t<Char>;
|
|
||||||
return vfprintf(os, to_string_view(format_str),
|
|
||||||
make_format_args<context>(args...));
|
|
||||||
}
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // FMT_PRINTF_H_
|
|
||||||
393
src/3rdparty/fmt/fmt/ranges.h
vendored
393
src/3rdparty/fmt/fmt/ranges.h
vendored
@@ -1,393 +0,0 @@
|
|||||||
// Formatting library for C++ - experimental range support
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 - present, Victor Zverovich
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// For the license information refer to format.h.
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 - present, Remotion (Igor Schulz)
|
|
||||||
// All Rights Reserved
|
|
||||||
// {fmt} support for ranges, containers and types tuple interface.
|
|
||||||
|
|
||||||
#ifndef FMT_RANGES_H_
|
|
||||||
#define FMT_RANGES_H_
|
|
||||||
|
|
||||||
#include <initializer_list>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "format.h"
|
|
||||||
|
|
||||||
// output only up to N items from the range.
|
|
||||||
#ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
|
|
||||||
# define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
template <typename Char> struct formatting_base {
|
|
||||||
template <typename ParseContext>
|
|
||||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
|
||||||
return ctx.begin();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, typename Enable = void>
|
|
||||||
struct formatting_range : formatting_base<Char> {
|
|
||||||
static FMT_CONSTEXPR_DECL const size_t range_length_limit =
|
|
||||||
FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
|
|
||||||
// range.
|
|
||||||
Char prefix;
|
|
||||||
Char delimiter;
|
|
||||||
Char postfix;
|
|
||||||
formatting_range() : prefix('{'), delimiter(','), postfix('}') {}
|
|
||||||
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
|
|
||||||
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, typename Enable = void>
|
|
||||||
struct formatting_tuple : formatting_base<Char> {
|
|
||||||
Char prefix;
|
|
||||||
Char delimiter;
|
|
||||||
Char postfix;
|
|
||||||
formatting_tuple() : prefix('('), delimiter(','), postfix(')') {}
|
|
||||||
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
|
|
||||||
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template <typename RangeT, typename OutputIterator>
|
|
||||||
OutputIterator copy(const RangeT& range, OutputIterator out) {
|
|
||||||
for (auto it = range.begin(), end = range.end(); it != end; ++it)
|
|
||||||
*out++ = *it;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIterator>
|
|
||||||
OutputIterator copy(const char* str, OutputIterator out) {
|
|
||||||
while (*str) *out++ = *str++;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIterator>
|
|
||||||
OutputIterator copy(char ch, OutputIterator out) {
|
|
||||||
*out++ = ch;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return true value if T has std::string interface, like std::string_view.
|
|
||||||
template <typename T> class is_like_std_string {
|
|
||||||
template <typename U>
|
|
||||||
static auto check(U* p)
|
|
||||||
-> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
|
|
||||||
template <typename> static void check(...);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static FMT_CONSTEXPR_DECL const bool value =
|
|
||||||
is_string<T>::value || !std::is_void<decltype(check<T>(nullptr))>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
struct is_like_std_string<fmt::basic_string_view<Char>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename... Ts> struct conditional_helper {};
|
|
||||||
|
|
||||||
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
|
|
||||||
|
|
||||||
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
|
|
||||||
template <typename T>
|
|
||||||
struct is_range_<
|
|
||||||
T, conditional_t<false,
|
|
||||||
conditional_helper<decltype(std::declval<T>().begin()),
|
|
||||||
decltype(std::declval<T>().end())>,
|
|
||||||
void>> : std::true_type {};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// tuple_size and tuple_element check.
|
|
||||||
template <typename T> class is_tuple_like_ {
|
|
||||||
template <typename U>
|
|
||||||
static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
|
|
||||||
template <typename> static void check(...);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static FMT_CONSTEXPR_DECL const bool value =
|
|
||||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check for integer_sequence
|
|
||||||
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
|
|
||||||
template <typename T, T... N>
|
|
||||||
using integer_sequence = std::integer_sequence<T, N...>;
|
|
||||||
template <size_t... N> using index_sequence = std::index_sequence<N...>;
|
|
||||||
template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
|
|
||||||
#else
|
|
||||||
template <typename T, T... N> struct integer_sequence {
|
|
||||||
using value_type = T;
|
|
||||||
|
|
||||||
static FMT_CONSTEXPR size_t size() { return sizeof...(N); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
|
|
||||||
|
|
||||||
template <typename T, size_t N, T... Ns>
|
|
||||||
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
|
|
||||||
template <typename T, T... Ns>
|
|
||||||
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
|
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
using make_index_sequence = make_integer_sequence<size_t, N>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <class Tuple, class F, size_t... Is>
|
|
||||||
void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) FMT_NOEXCEPT {
|
|
||||||
using std::get;
|
|
||||||
// using free function get<I>(T) now.
|
|
||||||
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
|
|
||||||
(void)_; // blocks warnings
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes(
|
|
||||||
T const&) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
|
|
||||||
const auto indexes = get_indexes(tup);
|
|
||||||
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range>
|
|
||||||
using value_type = remove_cvref_t<decltype(*std::declval<Range>().begin())>;
|
|
||||||
|
|
||||||
template <typename Arg, FMT_ENABLE_IF(!is_like_std_string<
|
|
||||||
typename std::decay<Arg>::type>::value)>
|
|
||||||
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
|
|
||||||
return add_space ? " {}" : "{}";
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Arg, FMT_ENABLE_IF(is_like_std_string<
|
|
||||||
typename std::decay<Arg>::type>::value)>
|
|
||||||
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
|
|
||||||
return add_space ? " \"{}\"" : "\"{}\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char*) {
|
|
||||||
return add_space ? " \"{}\"" : "\"{}\"";
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t*) {
|
|
||||||
return add_space ? L" \"{}\"" : L"\"{}\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) {
|
|
||||||
return add_space ? " '{}'" : "'{}'";
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
|
|
||||||
return add_space ? L" '{}'" : L"'{}'";
|
|
||||||
}
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename T> struct is_tuple_like {
|
|
||||||
static FMT_CONSTEXPR_DECL const bool value =
|
|
||||||
detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TupleT, typename Char>
|
|
||||||
struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
|
|
||||||
private:
|
|
||||||
// C++11 generic lambda for format()
|
|
||||||
template <typename FormatContext> struct format_each {
|
|
||||||
template <typename T> void operator()(const T& v) {
|
|
||||||
if (i > 0) {
|
|
||||||
if (formatting.add_prepostfix_space) {
|
|
||||||
*out++ = ' ';
|
|
||||||
}
|
|
||||||
out = detail::copy(formatting.delimiter, out);
|
|
||||||
}
|
|
||||||
out = format_to(out,
|
|
||||||
detail::format_str_quoted(
|
|
||||||
(formatting.add_delimiter_spaces && i > 0), v),
|
|
||||||
v);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
formatting_tuple<Char>& formatting;
|
|
||||||
size_t& i;
|
|
||||||
typename std::add_lvalue_reference<decltype(
|
|
||||||
std::declval<FormatContext>().out())>::type out;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
formatting_tuple<Char> formatting;
|
|
||||||
|
|
||||||
template <typename ParseContext>
|
|
||||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
|
||||||
return formatting.parse(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FormatContext = format_context>
|
|
||||||
auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
|
|
||||||
auto out = ctx.out();
|
|
||||||
size_t i = 0;
|
|
||||||
detail::copy(formatting.prefix, out);
|
|
||||||
|
|
||||||
detail::for_each(values, format_each<FormatContext>{formatting, i, out});
|
|
||||||
if (formatting.add_prepostfix_space) {
|
|
||||||
*out++ = ' ';
|
|
||||||
}
|
|
||||||
detail::copy(formatting.postfix, out);
|
|
||||||
|
|
||||||
return ctx.out();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename Char> struct is_range {
|
|
||||||
static FMT_CONSTEXPR_DECL const bool value =
|
|
||||||
detail::is_range_<T>::value && !detail::is_like_std_string<T>::value &&
|
|
||||||
!std::is_convertible<T, std::basic_string<Char>>::value &&
|
|
||||||
!std::is_constructible<detail::std_string_view<Char>, T>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename Char>
|
|
||||||
struct formatter<
|
|
||||||
T, Char,
|
|
||||||
enable_if_t<fmt::is_range<T, Char>::value
|
|
||||||
// Workaround a bug in MSVC 2017 and earlier.
|
|
||||||
#if !FMT_MSC_VER || FMT_MSC_VER >= 1927
|
|
||||||
&& has_formatter<detail::value_type<T>, format_context>::value
|
|
||||||
#endif
|
|
||||||
>> {
|
|
||||||
formatting_range<Char> formatting;
|
|
||||||
|
|
||||||
template <typename ParseContext>
|
|
||||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
|
||||||
return formatting.parse(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FormatContext>
|
|
||||||
typename FormatContext::iterator format(const T& values, FormatContext& ctx) {
|
|
||||||
auto out = detail::copy(formatting.prefix, ctx.out());
|
|
||||||
size_t i = 0;
|
|
||||||
auto it = values.begin();
|
|
||||||
auto end = values.end();
|
|
||||||
for (; it != end; ++it) {
|
|
||||||
if (i > 0) {
|
|
||||||
if (formatting.add_prepostfix_space) *out++ = ' ';
|
|
||||||
out = detail::copy(formatting.delimiter, out);
|
|
||||||
}
|
|
||||||
out = format_to(out,
|
|
||||||
detail::format_str_quoted(
|
|
||||||
(formatting.add_delimiter_spaces && i > 0), *it),
|
|
||||||
*it);
|
|
||||||
if (++i > formatting.range_length_limit) {
|
|
||||||
out = format_to(out, " ... <other elements>");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (formatting.add_prepostfix_space) *out++ = ' ';
|
|
||||||
return detail::copy(formatting.postfix, out);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, typename... T> struct tuple_arg_join : detail::view {
|
|
||||||
const std::tuple<T...>& tuple;
|
|
||||||
basic_string_view<Char> sep;
|
|
||||||
|
|
||||||
tuple_arg_join(const std::tuple<T...>& t, basic_string_view<Char> s)
|
|
||||||
: tuple{t}, sep{s} {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char, typename... T>
|
|
||||||
struct formatter<tuple_arg_join<Char, T...>, Char> {
|
|
||||||
template <typename ParseContext>
|
|
||||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
|
||||||
return ctx.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FormatContext>
|
|
||||||
typename FormatContext::iterator format(
|
|
||||||
const tuple_arg_join<Char, T...>& value, FormatContext& ctx) {
|
|
||||||
return format(value, ctx, detail::make_index_sequence<sizeof...(T)>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
template <typename FormatContext, size_t... N>
|
|
||||||
typename FormatContext::iterator format(
|
|
||||||
const tuple_arg_join<Char, T...>& value, FormatContext& ctx,
|
|
||||||
detail::index_sequence<N...>) {
|
|
||||||
return format_args(value, ctx, std::get<N>(value.tuple)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FormatContext>
|
|
||||||
typename FormatContext::iterator format_args(
|
|
||||||
const tuple_arg_join<Char, T...>&, FormatContext& ctx) {
|
|
||||||
// NOTE: for compilers that support C++17, this empty function instantiation
|
|
||||||
// can be replaced with a constexpr branch in the variadic overload.
|
|
||||||
return ctx.out();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FormatContext, typename Arg, typename... Args>
|
|
||||||
typename FormatContext::iterator format_args(
|
|
||||||
const tuple_arg_join<Char, T...>& value, FormatContext& ctx,
|
|
||||||
const Arg& arg, const Args&... args) {
|
|
||||||
using base = formatter<typename std::decay<Arg>::type, Char>;
|
|
||||||
auto out = ctx.out();
|
|
||||||
out = base{}.format(arg, ctx);
|
|
||||||
if (sizeof...(Args) > 0) {
|
|
||||||
out = std::copy(value.sep.begin(), value.sep.end(), out);
|
|
||||||
ctx.advance_to(out);
|
|
||||||
return format_args(value, ctx, args...);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Returns an object that formats `tuple` with elements separated by `sep`.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
std::tuple<int, char> t = {1, 'a'};
|
|
||||||
fmt::print("{}", fmt::join(t, ", "));
|
|
||||||
// Output: "1, a"
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename... T>
|
|
||||||
FMT_CONSTEXPR tuple_arg_join<char, T...> join(const std::tuple<T...>& tuple,
|
|
||||||
string_view sep) {
|
|
||||||
return {tuple, sep};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(const std::tuple<T...>& tuple,
|
|
||||||
wstring_view sep) {
|
|
||||||
return {tuple, sep};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Returns an object that formats `initializer_list` with elements separated by
|
|
||||||
`sep`.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
fmt::print("{}", fmt::join({1, 2, 3}, ", "));
|
|
||||||
// Output: "1, 2, 3"
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
arg_join<const T*, const T*, char> join(std::initializer_list<T> list,
|
|
||||||
string_view sep) {
|
|
||||||
return join(std::begin(list), std::end(list), sep);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
arg_join<const T*, const T*, wchar_t> join(std::initializer_list<T> list,
|
|
||||||
wstring_view sep) {
|
|
||||||
return join(std::begin(list), std::end(list), sep);
|
|
||||||
}
|
|
||||||
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // FMT_RANGES_H_
|
|
||||||
45
src/3rdparty/hwloc/AUTHORS
vendored
45
src/3rdparty/hwloc/AUTHORS
vendored
@@ -1,45 +0,0 @@
|
|||||||
hwloc Authors
|
|
||||||
=============
|
|
||||||
|
|
||||||
The following cumulative list contains the names of most individuals
|
|
||||||
who have committed code to the hwloc repository
|
|
||||||
(either directly or through a third party).
|
|
||||||
|
|
||||||
Name Affiliation(s)
|
|
||||||
--------------------------- --------------------
|
|
||||||
Grzegorz Andrejczuk Intel
|
|
||||||
Cédric Augonnet University of Bordeaux
|
|
||||||
Guillaume Beauchamp Inria
|
|
||||||
Ahmad Boissetri Binzagr Inria
|
|
||||||
Cyril Bordage Inria
|
|
||||||
Nicholas Buroker UWL
|
|
||||||
Christopher M. Cantalupo Intel
|
|
||||||
Jérôme Clet-Ortega University of Bordeaux
|
|
||||||
Ludovic Courtès Inria
|
|
||||||
Clément Foyer Inria
|
|
||||||
Nathalie Furmento CNRS
|
|
||||||
Bryon Gloden
|
|
||||||
Brice Goglin Inria
|
|
||||||
Gilles Gouaillardet RIST
|
|
||||||
Valentin Hoyet Inria
|
|
||||||
Joshua Hursey UWL
|
|
||||||
Alexey Kardashevskiy IBM
|
|
||||||
Rob Latham ANL
|
|
||||||
Douglas MacFarland UWL
|
|
||||||
Marc Marí BSC
|
|
||||||
Jonathan L Peyton Intel
|
|
||||||
Piotr Luc Intel
|
|
||||||
Antoine Rougier intern from University of Bordeaux
|
|
||||||
Jeff Squyres Cisco
|
|
||||||
Samuel Thibault University of Bordeaux
|
|
||||||
Jean-Yves VET DDN
|
|
||||||
Benjamin Worpitz
|
|
||||||
Jeff Zhao Zhaoxin
|
|
||||||
|
|
||||||
Affiliaion abbreviations:
|
|
||||||
-------------------------
|
|
||||||
ANL = Argonne National Lab
|
|
||||||
BSC = Barcelona Supercomputing Center
|
|
||||||
Cisco = Cisco Systems, Inc.
|
|
||||||
CNRS = Centre national de la recherche scientifique (France)
|
|
||||||
UWL = University of Wisconsin-La Crosse
|
|
||||||
40
src/3rdparty/hwloc/CMakeLists.txt
vendored
40
src/3rdparty/hwloc/CMakeLists.txt
vendored
@@ -1,40 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
|
||||||
project (hwloc C)
|
|
||||||
|
|
||||||
include_directories(include)
|
|
||||||
include_directories(src)
|
|
||||||
|
|
||||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
|
|
||||||
set(CMAKE_C_FLAGS_RELEASE "/MT /O2 /Ob2 /DNDEBUG")
|
|
||||||
|
|
||||||
set(HEADERS
|
|
||||||
include/hwloc.h
|
|
||||||
src/static-components.h
|
|
||||||
)
|
|
||||||
|
|
||||||
set(SOURCES
|
|
||||||
src/base64.c
|
|
||||||
src/bind.c
|
|
||||||
src/bitmap.c
|
|
||||||
src/components.c
|
|
||||||
src/diff.c
|
|
||||||
src/distances.c
|
|
||||||
src/misc.c
|
|
||||||
src/pci-common.c
|
|
||||||
src/shmem.c
|
|
||||||
src/topology.c
|
|
||||||
src/topology-noos.c
|
|
||||||
src/topology-synthetic.c
|
|
||||||
src/topology-windows.c
|
|
||||||
src/topology-x86.c
|
|
||||||
src/topology-xml.c
|
|
||||||
src/topology-xml-nolibxml.c
|
|
||||||
src/traversal.c
|
|
||||||
src/memattrs.c
|
|
||||||
src/cpukinds.c
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(hwloc STATIC
|
|
||||||
${HEADERS}
|
|
||||||
${SOURCES}
|
|
||||||
)
|
|
||||||
39
src/3rdparty/hwloc/COPYING
vendored
39
src/3rdparty/hwloc/COPYING
vendored
@@ -1,39 +0,0 @@
|
|||||||
Copyright © 2004-2006 The Trustees of Indiana University and Indiana University Research and Technology Corporation. All rights reserved.
|
|
||||||
Copyright © 2004-2005 The University of Tennessee and The University of Tennessee Research Foundation. All rights reserved.
|
|
||||||
Copyright © 2004-2005 High Performance Computing Center Stuttgart, University of Stuttgart. All rights reserved.
|
|
||||||
Copyright © 2004-2005 The Regents of the University of California. All rights reserved.
|
|
||||||
Copyright © 2009 CNRS
|
|
||||||
Copyright © 2009-2016 Inria. All rights reserved.
|
|
||||||
Copyright © 2009-2015 Université Bordeaux
|
|
||||||
Copyright © 2009-2015 Cisco Systems, Inc. All rights reserved.
|
|
||||||
Copyright © 2009-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
Copyright © 2010 IBM
|
|
||||||
Copyright © 2010 Jirka Hladky
|
|
||||||
Copyright © 2012 Aleksej Saushev, The NetBSD Foundation
|
|
||||||
Copyright © 2012 Blue Brain Project, EPFL. All rights reserved.
|
|
||||||
Copyright © 2013-2014 University of Wisconsin-La Crosse. All rights reserved.
|
|
||||||
Copyright © 2015 Research Organization for Information Science and Technology (RIST). All rights reserved.
|
|
||||||
Copyright © 2015-2016 Intel, Inc. All rights reserved.
|
|
||||||
See COPYING in top-level directory.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
3. The name of the author may not be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
2192
src/3rdparty/hwloc/NEWS
vendored
2192
src/3rdparty/hwloc/NEWS
vendored
File diff suppressed because it is too large
Load Diff
487
src/3rdparty/hwloc/README
vendored
487
src/3rdparty/hwloc/README
vendored
@@ -1,487 +0,0 @@
|
|||||||
This is a truncated and poorly-formatted version of the documentation main page.
|
|
||||||
See https://www.open-mpi.org/projects/hwloc/doc/ for more.
|
|
||||||
|
|
||||||
|
|
||||||
hwloc Overview
|
|
||||||
|
|
||||||
The Hardware Locality (hwloc) software project aims at easing the process of
|
|
||||||
discovering hardware resources in parallel architectures. It offers
|
|
||||||
command-line tools and a C API for consulting these resources, their locality,
|
|
||||||
attributes, and interconnection. hwloc primarily aims at helping
|
|
||||||
high-performance computing (HPC) applications, but is also applicable to any
|
|
||||||
project seeking to exploit code and/or data locality on modern computing
|
|
||||||
platforms.
|
|
||||||
|
|
||||||
hwloc provides command line tools and a C API to obtain the hierarchical map of
|
|
||||||
key computing elements within a node, such as: NUMA memory nodes, shared
|
|
||||||
caches, processor packages, dies and cores, processing units (logical
|
|
||||||
processors or "threads") and even I/O devices. hwloc also gathers various
|
|
||||||
attributes such as cache and memory information, and is portable across a
|
|
||||||
variety of different operating systems and platforms.
|
|
||||||
|
|
||||||
hwloc primarily aims at helping high-performance computing (HPC) applications,
|
|
||||||
but is also applicable to any project seeking to exploit code and/or data
|
|
||||||
locality on modern computing platforms.
|
|
||||||
|
|
||||||
hwloc supports the following operating systems:
|
|
||||||
|
|
||||||
* Linux (with knowledge of cgroups and cpusets, memory targets/initiators,
|
|
||||||
etc.) on all supported hardware, including Intel Xeon Phi, ScaleMP vSMP,
|
|
||||||
and NumaScale NumaConnect.
|
|
||||||
* Solaris (with support for processor sets and logical domains)
|
|
||||||
* AIX
|
|
||||||
* Darwin / OS X
|
|
||||||
* FreeBSD and its variants (such as kFreeBSD/GNU)
|
|
||||||
* NetBSD
|
|
||||||
* HP-UX
|
|
||||||
* Microsoft Windows
|
|
||||||
* IBM BlueGene/Q Compute Node Kernel (CNK)
|
|
||||||
|
|
||||||
Since it uses standard Operating System information, hwloc's support is mostly
|
|
||||||
independant from the processor type (x86, powerpc, ...) and just relies on the
|
|
||||||
Operating System support. The main exception is BSD operating systems (NetBSD,
|
|
||||||
FreeBSD, etc.) because they do not provide support topology information, hence
|
|
||||||
hwloc uses an x86-only CPUID-based backend (which can be used for other OSes
|
|
||||||
too, see the Components and plugins section).
|
|
||||||
|
|
||||||
To check whether hwloc works on a particular machine, just try to build it and
|
|
||||||
run lstopo or lstopo-no-graphics. If some things do not look right (e.g. bogus
|
|
||||||
or missing cache information), see Questions and Bugs.
|
|
||||||
|
|
||||||
hwloc only reports the number of processors on unsupported operating systems;
|
|
||||||
no topology information is available.
|
|
||||||
|
|
||||||
For development and debugging purposes, hwloc also offers the ability to work
|
|
||||||
on "fake" topologies:
|
|
||||||
|
|
||||||
* Symmetrical tree of resources generated from a list of level arities, see
|
|
||||||
Synthetic topologies.
|
|
||||||
* Remote machine simulation through the gathering of topology as XML files,
|
|
||||||
see Importing and exporting topologies from/to XML files.
|
|
||||||
|
|
||||||
hwloc can display the topology in a human-readable format, either in graphical
|
|
||||||
mode (X11), or by exporting in one of several different formats, including:
|
|
||||||
plain text, LaTeX tikzpicture, PDF, PNG, and FIG (see Command-line Examples
|
|
||||||
below). Note that some of the export formats require additional support
|
|
||||||
libraries.
|
|
||||||
|
|
||||||
hwloc offers a programming interface for manipulating topologies and objects.
|
|
||||||
It also brings a powerful CPU bitmap API that is used to describe topology
|
|
||||||
objects location on physical/logical processors. See the Programming Interface
|
|
||||||
below. It may also be used to binding applications onto certain cores or memory
|
|
||||||
nodes. Several utility programs are also provided to ease command-line
|
|
||||||
manipulation of topology objects, binding of processes, and so on.
|
|
||||||
|
|
||||||
Bindings for several other languages are available from the project website.
|
|
||||||
|
|
||||||
Command-line Examples
|
|
||||||
|
|
||||||
On a 4-package 2-core machine with hyper-threading, the lstopo tool may show
|
|
||||||
the following graphical output:
|
|
||||||
|
|
||||||
[dudley]
|
|
||||||
|
|
||||||
Here's the equivalent output in textual form:
|
|
||||||
|
|
||||||
Machine
|
|
||||||
NUMANode L#0 (P#0)
|
|
||||||
Package L#0 + L3 L#0 (4096KB)
|
|
||||||
L2 L#0 (1024KB) + L1 L#0 (16KB) + Core L#0
|
|
||||||
PU L#0 (P#0)
|
|
||||||
PU L#1 (P#8)
|
|
||||||
L2 L#1 (1024KB) + L1 L#1 (16KB) + Core L#1
|
|
||||||
PU L#2 (P#4)
|
|
||||||
PU L#3 (P#12)
|
|
||||||
Package L#1 + L3 L#1 (4096KB)
|
|
||||||
L2 L#2 (1024KB) + L1 L#2 (16KB) + Core L#2
|
|
||||||
PU L#4 (P#1)
|
|
||||||
PU L#5 (P#9)
|
|
||||||
L2 L#3 (1024KB) + L1 L#3 (16KB) + Core L#3
|
|
||||||
PU L#6 (P#5)
|
|
||||||
PU L#7 (P#13)
|
|
||||||
Package L#2 + L3 L#2 (4096KB)
|
|
||||||
L2 L#4 (1024KB) + L1 L#4 (16KB) + Core L#4
|
|
||||||
PU L#8 (P#2)
|
|
||||||
PU L#9 (P#10)
|
|
||||||
L2 L#5 (1024KB) + L1 L#5 (16KB) + Core L#5
|
|
||||||
PU L#10 (P#6)
|
|
||||||
PU L#11 (P#14)
|
|
||||||
Package L#3 + L3 L#3 (4096KB)
|
|
||||||
L2 L#6 (1024KB) + L1 L#6 (16KB) + Core L#6
|
|
||||||
PU L#12 (P#3)
|
|
||||||
PU L#13 (P#11)
|
|
||||||
L2 L#7 (1024KB) + L1 L#7 (16KB) + Core L#7
|
|
||||||
PU L#14 (P#7)
|
|
||||||
PU L#15 (P#15)
|
|
||||||
|
|
||||||
Note that there is also an equivalent output in XML that is meant for exporting
|
|
||||||
/importing topologies but it is hardly readable to human-beings (see Importing
|
|
||||||
and exporting topologies from/to XML files for details).
|
|
||||||
|
|
||||||
On a 4-package 2-core Opteron NUMA machine (with two core cores disallowed by
|
|
||||||
the administrator), the lstopo tool may show the following graphical output
|
|
||||||
(with --disallowed for displaying disallowed objects):
|
|
||||||
|
|
||||||
[hagrid]
|
|
||||||
|
|
||||||
Here's the equivalent output in textual form:
|
|
||||||
|
|
||||||
Machine (32GB total)
|
|
||||||
Package L#0
|
|
||||||
NUMANode L#0 (P#0 8190MB)
|
|
||||||
L2 L#0 (1024KB) + L1 L#0 (64KB) + Core L#0 + PU L#0 (P#0)
|
|
||||||
L2 L#1 (1024KB) + L1 L#1 (64KB) + Core L#1 + PU L#1 (P#1)
|
|
||||||
Package L#1
|
|
||||||
NUMANode L#1 (P#1 8192MB)
|
|
||||||
L2 L#2 (1024KB) + L1 L#2 (64KB) + Core L#2 + PU L#2 (P#2)
|
|
||||||
L2 L#3 (1024KB) + L1 L#3 (64KB) + Core L#3 + PU L#3 (P#3)
|
|
||||||
Package L#2
|
|
||||||
NUMANode L#2 (P#2 8192MB)
|
|
||||||
L2 L#4 (1024KB) + L1 L#4 (64KB) + Core L#4 + PU L#4 (P#4)
|
|
||||||
L2 L#5 (1024KB) + L1 L#5 (64KB) + Core L#5 + PU L#5 (P#5)
|
|
||||||
Package L#3
|
|
||||||
NUMANode L#3 (P#3 8192MB)
|
|
||||||
L2 L#6 (1024KB) + L1 L#6 (64KB) + Core L#6 + PU L#6 (P#6)
|
|
||||||
L2 L#7 (1024KB) + L1 L#7 (64KB) + Core L#7 + PU L#7 (P#7)
|
|
||||||
|
|
||||||
On a 2-package quad-core Xeon (pre-Nehalem, with 2 dual-core dies into each
|
|
||||||
package):
|
|
||||||
|
|
||||||
[emmett]
|
|
||||||
|
|
||||||
Here's the same output in textual form:
|
|
||||||
|
|
||||||
Machine (total 16GB)
|
|
||||||
NUMANode L#0 (P#0 16GB)
|
|
||||||
Package L#0
|
|
||||||
L2 L#0 (4096KB)
|
|
||||||
L1 L#0 (32KB) + Core L#0 + PU L#0 (P#0)
|
|
||||||
L1 L#1 (32KB) + Core L#1 + PU L#1 (P#4)
|
|
||||||
L2 L#1 (4096KB)
|
|
||||||
L1 L#2 (32KB) + Core L#2 + PU L#2 (P#2)
|
|
||||||
L1 L#3 (32KB) + Core L#3 + PU L#3 (P#6)
|
|
||||||
Package L#1
|
|
||||||
L2 L#2 (4096KB)
|
|
||||||
L1 L#4 (32KB) + Core L#4 + PU L#4 (P#1)
|
|
||||||
L1 L#5 (32KB) + Core L#5 + PU L#5 (P#5)
|
|
||||||
L2 L#3 (4096KB)
|
|
||||||
L1 L#6 (32KB) + Core L#6 + PU L#6 (P#3)
|
|
||||||
L1 L#7 (32KB) + Core L#7 + PU L#7 (P#7)
|
|
||||||
|
|
||||||
Programming Interface
|
|
||||||
|
|
||||||
The basic interface is available in hwloc.h. Some higher-level functions are
|
|
||||||
available in hwloc/helper.h to reduce the need to manually manipulate objects
|
|
||||||
and follow links between them. Documentation for all these is provided later in
|
|
||||||
this document. Developers may also want to look at hwloc/inlines.h which
|
|
||||||
contains the actual inline code of some hwloc.h routines, and at this document,
|
|
||||||
which provides good higher-level topology traversal examples.
|
|
||||||
|
|
||||||
To precisely define the vocabulary used by hwloc, a Terms and Definitions
|
|
||||||
section is available and should probably be read first.
|
|
||||||
|
|
||||||
Each hwloc object contains a cpuset describing the list of processing units
|
|
||||||
that it contains. These bitmaps may be used for CPU binding and Memory binding.
|
|
||||||
hwloc offers an extensive bitmap manipulation interface in hwloc/bitmap.h.
|
|
||||||
|
|
||||||
Moreover, hwloc also comes with additional helpers for interoperability with
|
|
||||||
several commonly used environments. See the Interoperability With Other
|
|
||||||
Software section for details.
|
|
||||||
|
|
||||||
The complete API documentation is available in a full set of HTML pages, man
|
|
||||||
pages, and self-contained PDF files (formatted for both both US letter and A4
|
|
||||||
formats) in the source tarball in doc/doxygen-doc/.
|
|
||||||
|
|
||||||
NOTE: If you are building the documentation from a Git clone, you will need to
|
|
||||||
have Doxygen and pdflatex installed -- the documentation will be built during
|
|
||||||
the normal "make" process. The documentation is installed during "make install"
|
|
||||||
to $prefix/share/doc/hwloc/ and your systems default man page tree (under
|
|
||||||
$prefix, of course).
|
|
||||||
|
|
||||||
Portability
|
|
||||||
|
|
||||||
Operating System have varying support for CPU and memory binding, e.g. while
|
|
||||||
some Operating Systems provide interfaces for all kinds of CPU and memory
|
|
||||||
bindings, some others provide only interfaces for a limited number of kinds of
|
|
||||||
CPU and memory binding, and some do not provide any binding interface at all.
|
|
||||||
Hwloc's binding functions would then simply return the ENOSYS error (Function
|
|
||||||
not implemented), meaning that the underlying Operating System does not provide
|
|
||||||
any interface for them. CPU binding and Memory binding provide more information
|
|
||||||
on which hwloc binding functions should be preferred because interfaces for
|
|
||||||
them are usually available on the supported Operating Systems.
|
|
||||||
|
|
||||||
Similarly, the ability of reporting topology information varies from one
|
|
||||||
platform to another. As shown in Command-line Examples, hwloc can obtain
|
|
||||||
information on a wide variety of hardware topologies. However, some platforms
|
|
||||||
and/or operating system versions will only report a subset of this information.
|
|
||||||
For example, on an PPC64-based system with 8 cores (each with 2 hardware
|
|
||||||
threads) running a default 2.6.18-based kernel from RHEL 5.4, hwloc is only
|
|
||||||
able to glean information about NUMA nodes and processor units (PUs). No
|
|
||||||
information about caches, packages, or cores is available.
|
|
||||||
|
|
||||||
Here's the graphical output from lstopo on this platform when Simultaneous
|
|
||||||
Multi-Threading (SMT) is enabled:
|
|
||||||
|
|
||||||
[ppc64-with]
|
|
||||||
|
|
||||||
And here's the graphical output from lstopo on this platform when SMT is
|
|
||||||
disabled:
|
|
||||||
|
|
||||||
[ppc64-with]
|
|
||||||
|
|
||||||
Notice that hwloc only sees half the PUs when SMT is disabled. PU L#6, for
|
|
||||||
example, seems to change location from NUMA node #0 to #1. In reality, no PUs
|
|
||||||
"moved" -- they were simply re-numbered when hwloc only saw half as many (see
|
|
||||||
also Logical index in Indexes and Sets). Hence, PU L#6 in the SMT-disabled
|
|
||||||
picture probably corresponds to PU L#12 in the SMT-enabled picture.
|
|
||||||
|
|
||||||
This same "PUs have disappeared" effect can be seen on other platforms -- even
|
|
||||||
platforms / OSs that provide much more information than the above PPC64 system.
|
|
||||||
This is an unfortunate side-effect of how operating systems report information
|
|
||||||
to hwloc.
|
|
||||||
|
|
||||||
Note that upgrading the Linux kernel on the same PPC64 system mentioned above
|
|
||||||
to 2.6.34, hwloc is able to discover all the topology information. The
|
|
||||||
following picture shows the entire topology layout when SMT is enabled:
|
|
||||||
|
|
||||||
[ppc64-full]
|
|
||||||
|
|
||||||
Developers using the hwloc API or XML output for portable applications should
|
|
||||||
therefore be extremely careful to not make any assumptions about the structure
|
|
||||||
of data that is returned. For example, per the above reported PPC topology, it
|
|
||||||
is not safe to assume that PUs will always be descendants of cores.
|
|
||||||
|
|
||||||
Additionally, future hardware may insert new topology elements that are not
|
|
||||||
available in this version of hwloc. Long-lived applications that are meant to
|
|
||||||
span multiple different hardware platforms should also be careful about making
|
|
||||||
structure assumptions. For example, a new element may someday exist between a
|
|
||||||
core and a PU.
|
|
||||||
|
|
||||||
API Example
|
|
||||||
|
|
||||||
The following small C example (available in the source tree as ``doc/examples/
|
|
||||||
hwloc-hello.c'') prints the topology of the machine and performs some thread
|
|
||||||
and memory binding. More examples are available in the doc/examples/ directory
|
|
||||||
of the source tree.
|
|
||||||
|
|
||||||
/* Example hwloc API program.
|
|
||||||
*
|
|
||||||
* See other examples under doc/examples/ in the source tree
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2016 Inria. All rights reserved.
|
|
||||||
* Copyright (c) 2009-2011 Universit?eacute; Bordeaux
|
|
||||||
* Copyright (c) 2009-2010 Cisco Systems, Inc. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*
|
|
||||||
* hwloc-hello.c
|
|
||||||
*/
|
|
||||||
#include "hwloc.h"
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
static void print_children(hwloc_topology_t topology, hwloc_obj_t obj,
|
|
||||||
int depth)
|
|
||||||
{
|
|
||||||
char type[32], attr[1024];
|
|
||||||
unsigned i;
|
|
||||||
hwloc_obj_type_snprintf(type, sizeof(type), obj, 0);
|
|
||||||
printf("%*s%s", 2*depth, "", type);
|
|
||||||
if (obj->os_index != (unsigned) -1)
|
|
||||||
printf("#%u", obj->os_index);
|
|
||||||
hwloc_obj_attr_snprintf(attr, sizeof(attr), obj, " ", 0);
|
|
||||||
if (*attr)
|
|
||||||
printf("(%s)", attr);
|
|
||||||
printf("\n");
|
|
||||||
for (i = 0; i < obj->arity; i++) {
|
|
||||||
print_children(topology, obj->children[i], depth + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
int depth;
|
|
||||||
unsigned i, n;
|
|
||||||
unsigned long size;
|
|
||||||
int levels;
|
|
||||||
char string[128];
|
|
||||||
int topodepth;
|
|
||||||
void *m;
|
|
||||||
hwloc_topology_t topology;
|
|
||||||
hwloc_cpuset_t cpuset;
|
|
||||||
hwloc_obj_t obj;
|
|
||||||
/* Allocate and initialize topology object. */
|
|
||||||
hwloc_topology_init(&topology);
|
|
||||||
/* ... Optionally, put detection configuration here to ignore
|
|
||||||
some objects types, define a synthetic topology, etc....
|
|
||||||
The default is to detect all the objects of the machine that
|
|
||||||
the caller is allowed to access. See Configure Topology
|
|
||||||
Detection. */
|
|
||||||
/* Perform the topology detection. */
|
|
||||||
hwloc_topology_load(topology);
|
|
||||||
/* Optionally, get some additional topology information
|
|
||||||
in case we need the topology depth later. */
|
|
||||||
topodepth = hwloc_topology_get_depth(topology);
|
|
||||||
/*****************************************************************
|
|
||||||
* First example:
|
|
||||||
* Walk the topology with an array style, from level 0 (always
|
|
||||||
* the system level) to the lowest level (always the proc level).
|
|
||||||
*****************************************************************/
|
|
||||||
for (depth = 0; depth < topodepth; depth++) {
|
|
||||||
printf("*** Objects at level %d\n", depth);
|
|
||||||
for (i = 0; i < hwloc_get_nbobjs_by_depth(topology, depth);
|
|
||||||
i++) {
|
|
||||||
hwloc_obj_type_snprintf(string, sizeof(string),
|
|
||||||
hwloc_get_obj_by_depth(topology, depth, i), 0);
|
|
||||||
printf("Index %u: %s\n", i, string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*****************************************************************
|
|
||||||
* Second example:
|
|
||||||
* Walk the topology with a tree style.
|
|
||||||
*****************************************************************/
|
|
||||||
printf("*** Printing overall tree\n");
|
|
||||||
print_children(topology, hwloc_get_root_obj(topology), 0);
|
|
||||||
/*****************************************************************
|
|
||||||
* Third example:
|
|
||||||
* Print the number of packages.
|
|
||||||
*****************************************************************/
|
|
||||||
depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PACKAGE);
|
|
||||||
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
|
|
||||||
printf("*** The number of packages is unknown\n");
|
|
||||||
} else {
|
|
||||||
printf("*** %u package(s)\n",
|
|
||||||
hwloc_get_nbobjs_by_depth(topology, depth));
|
|
||||||
}
|
|
||||||
/*****************************************************************
|
|
||||||
* Fourth example:
|
|
||||||
* Compute the amount of cache that the first logical processor
|
|
||||||
* has above it.
|
|
||||||
*****************************************************************/
|
|
||||||
levels = 0;
|
|
||||||
size = 0;
|
|
||||||
for (obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 0);
|
|
||||||
obj;
|
|
||||||
obj = obj->parent)
|
|
||||||
if (hwloc_obj_type_is_cache(obj->type)) {
|
|
||||||
levels++;
|
|
||||||
size += obj->attr->cache.size;
|
|
||||||
}
|
|
||||||
printf("*** Logical processor 0 has %d caches totaling %luKB\n",
|
|
||||||
levels, size / 1024);
|
|
||||||
/*****************************************************************
|
|
||||||
* Fifth example:
|
|
||||||
* Bind to only one thread of the last core of the machine.
|
|
||||||
*
|
|
||||||
* First find out where cores are, or else smaller sets of CPUs if
|
|
||||||
* the OS doesn't have the notion of a "core".
|
|
||||||
*****************************************************************/
|
|
||||||
depth = hwloc_get_type_or_below_depth(topology, HWLOC_OBJ_CORE);
|
|
||||||
/* Get last core. */
|
|
||||||
obj = hwloc_get_obj_by_depth(topology, depth,
|
|
||||||
hwloc_get_nbobjs_by_depth(topology, depth) - 1);
|
|
||||||
if (obj) {
|
|
||||||
/* Get a copy of its cpuset that we may modify. */
|
|
||||||
cpuset = hwloc_bitmap_dup(obj->cpuset);
|
|
||||||
/* Get only one logical processor (in case the core is
|
|
||||||
SMT/hyper-threaded). */
|
|
||||||
hwloc_bitmap_singlify(cpuset);
|
|
||||||
/* And try to bind ourself there. */
|
|
||||||
if (hwloc_set_cpubind(topology, cpuset, 0)) {
|
|
||||||
char *str;
|
|
||||||
int error = errno;
|
|
||||||
hwloc_bitmap_asprintf(&str, obj->cpuset);
|
|
||||||
printf("Couldn't bind to cpuset %s: %s\n", str, strerror(error));
|
|
||||||
free(str);
|
|
||||||
}
|
|
||||||
/* Free our cpuset copy */
|
|
||||||
hwloc_bitmap_free(cpuset);
|
|
||||||
}
|
|
||||||
/*****************************************************************
|
|
||||||
* Sixth example:
|
|
||||||
* Allocate some memory on the last NUMA node, bind some existing
|
|
||||||
* memory to the last NUMA node.
|
|
||||||
*****************************************************************/
|
|
||||||
/* Get last node. There's always at least one. */
|
|
||||||
n = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE);
|
|
||||||
obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, n - 1);
|
|
||||||
size = 1024*1024;
|
|
||||||
m = hwloc_alloc_membind(topology, size, obj->nodeset,
|
|
||||||
HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_BYNODESET);
|
|
||||||
hwloc_free(topology, m, size);
|
|
||||||
m = malloc(size);
|
|
||||||
hwloc_set_area_membind(topology, m, size, obj->nodeset,
|
|
||||||
HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_BYNODESET);
|
|
||||||
free(m);
|
|
||||||
/* Destroy topology object. */
|
|
||||||
hwloc_topology_destroy(topology);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hwloc provides a pkg-config executable to obtain relevant compiler and linker
|
|
||||||
flags. See Compiling software on top of hwloc's C API for details on building
|
|
||||||
program on top of hwloc's API using GNU Make or CMake.
|
|
||||||
|
|
||||||
On a machine 2 processor packages -- each package of which has two processing
|
|
||||||
cores -- the output from running hwloc-hello could be something like the
|
|
||||||
following:
|
|
||||||
|
|
||||||
shell$ ./hwloc-hello
|
|
||||||
*** Objects at level 0
|
|
||||||
Index 0: Machine
|
|
||||||
*** Objects at level 1
|
|
||||||
Index 0: Package#0
|
|
||||||
Index 1: Package#1
|
|
||||||
*** Objects at level 2
|
|
||||||
Index 0: Core#0
|
|
||||||
Index 1: Core#1
|
|
||||||
Index 2: Core#3
|
|
||||||
Index 3: Core#2
|
|
||||||
*** Objects at level 3
|
|
||||||
Index 0: PU#0
|
|
||||||
Index 1: PU#1
|
|
||||||
Index 2: PU#2
|
|
||||||
Index 3: PU#3
|
|
||||||
*** Printing overall tree
|
|
||||||
Machine
|
|
||||||
Package#0
|
|
||||||
Core#0
|
|
||||||
PU#0
|
|
||||||
Core#1
|
|
||||||
PU#1
|
|
||||||
Package#1
|
|
||||||
Core#3
|
|
||||||
PU#2
|
|
||||||
Core#2
|
|
||||||
PU#3
|
|
||||||
*** 2 package(s)
|
|
||||||
*** Logical processor 0 has 0 caches totaling 0KB
|
|
||||||
shell$
|
|
||||||
|
|
||||||
Questions and Bugs
|
|
||||||
|
|
||||||
Bugs should be reported in the tracker (https://github.com/open-mpi/hwloc/
|
|
||||||
issues). Opening a new issue automatically displays lots of hints about how to
|
|
||||||
debug and report issues.
|
|
||||||
|
|
||||||
Questions may be sent to the users or developers mailing lists (https://
|
|
||||||
www.open-mpi.org/community/lists/hwloc.php).
|
|
||||||
|
|
||||||
There is also a #hwloc IRC channel on Libera Chat (irc.libera.chat).
|
|
||||||
|
|
||||||
History / Credits
|
|
||||||
|
|
||||||
hwloc is the evolution and merger of the libtopology project and the Portable
|
|
||||||
Linux Processor Affinity (PLPA) (https://www.open-mpi.org/projects/plpa/)
|
|
||||||
project. Because of functional and ideological overlap, these two code bases
|
|
||||||
and ideas were merged and released under the name "hwloc" as an Open MPI
|
|
||||||
sub-project.
|
|
||||||
|
|
||||||
libtopology was initially developed by the Inria Runtime Team-Project. PLPA was
|
|
||||||
initially developed by the Open MPI development team as a sub-project. Both are
|
|
||||||
now deprecated in favor of hwloc, which is distributed as an Open MPI
|
|
||||||
sub-project.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
See https://www.open-mpi.org/projects/hwloc/doc/ for more hwloc documentation,
|
|
||||||
actual links to related pages, images, etc.
|
|
||||||
46
src/3rdparty/hwloc/VERSION
vendored
46
src/3rdparty/hwloc/VERSION
vendored
@@ -1,46 +0,0 @@
|
|||||||
# This is the VERSION file for hwloc, describing the precise version
|
|
||||||
# of hwloc in this distribution. The various components of the version
|
|
||||||
# number below are combined to form a single version number string.
|
|
||||||
|
|
||||||
# major, minor, and release are generally combined in the form
|
|
||||||
# <major>.<minor>.<release>. If release is zero, then it is omitted.
|
|
||||||
|
|
||||||
# Please update HWLOC_VERSION* in contrib/windows/hwloc_config.h too.
|
|
||||||
|
|
||||||
major=2
|
|
||||||
minor=11
|
|
||||||
release=2
|
|
||||||
|
|
||||||
# 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
|
|
||||||
# numeric. Common examples include a1 (alpha release 1), b1 (beta
|
|
||||||
# release 1), sc2005 (Super Computing 2005 release). The only
|
|
||||||
# requirement is that it must be entirely printable ASCII characters
|
|
||||||
# and have no white space.
|
|
||||||
|
|
||||||
greek=
|
|
||||||
|
|
||||||
# The date when this release was created
|
|
||||||
|
|
||||||
date="Sep 26, 2024"
|
|
||||||
|
|
||||||
# If snapshot=1, then use the value from snapshot_version as the
|
|
||||||
# entire hwloc version (i.e., ignore major, minor, release, and
|
|
||||||
# greek). This is only set to 1 when making snapshot tarballs.
|
|
||||||
snapshot=0
|
|
||||||
snapshot_version=${major}.${minor}.${release}${greek}-git
|
|
||||||
|
|
||||||
# The shared library version of hwloc's public library. This version
|
|
||||||
# is maintained in accordance with the "Library Interface Versions"
|
|
||||||
# chapter from the GNU Libtool documentation. Notes:
|
|
||||||
|
|
||||||
# 1. Since version numbers are associated with *releases*, the version
|
|
||||||
# number maintained on the hwloc git master (and developer branches)
|
|
||||||
# is always 0:0:0.
|
|
||||||
|
|
||||||
# 2. Version numbers are described in the Libtool current:revision:age
|
|
||||||
# format.
|
|
||||||
|
|
||||||
libhwloc_so_version=23:1:8
|
|
||||||
|
|
||||||
# Please also update the <TargetName> lines in contrib/windows/libhwloc.vcxproj
|
|
||||||
2872
src/3rdparty/hwloc/include/hwloc.h
vendored
2872
src/3rdparty/hwloc/include/hwloc.h
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2009 CNRS
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* The configuration file */
|
|
||||||
|
|
||||||
#ifndef HWLOC_CONFIG_H
|
|
||||||
#define HWLOC_CONFIG_H
|
|
||||||
|
|
||||||
#define HWLOC_VERSION "2.11.2"
|
|
||||||
#define HWLOC_VERSION_MAJOR 2
|
|
||||||
#define HWLOC_VERSION_MINOR 11
|
|
||||||
#define HWLOC_VERSION_RELEASE 2
|
|
||||||
#define HWLOC_VERSION_GREEK ""
|
|
||||||
|
|
||||||
#define __hwloc_restrict
|
|
||||||
#define __hwloc_inline __inline
|
|
||||||
|
|
||||||
#define __hwloc_attribute_unused
|
|
||||||
#define __hwloc_attribute_malloc
|
|
||||||
#define __hwloc_attribute_const
|
|
||||||
#define __hwloc_attribute_pure
|
|
||||||
#define __hwloc_attribute_deprecated
|
|
||||||
#define __hwloc_attribute_may_alias
|
|
||||||
#define __hwloc_attribute_warn_unused_result
|
|
||||||
|
|
||||||
/* Defined to 1 if you have the `windows.h' header. */
|
|
||||||
#define HWLOC_HAVE_WINDOWS_H 1
|
|
||||||
#define hwloc_pid_t HANDLE
|
|
||||||
#define hwloc_thread_t HANDLE
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <BaseTsd.h>
|
|
||||||
typedef DWORDLONG hwloc_uint64_t;
|
|
||||||
|
|
||||||
#if defined( _USRDLL ) /* dynamic linkage */
|
|
||||||
#if defined( DECLSPEC_EXPORTS )
|
|
||||||
#define HWLOC_DECLSPEC __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
#define HWLOC_DECLSPEC __declspec(dllimport)
|
|
||||||
#endif
|
|
||||||
#else /* static linkage */
|
|
||||||
#define HWLOC_DECLSPEC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Whether we need to re-define all the hwloc public symbols or not */
|
|
||||||
#define HWLOC_SYM_TRANSFORM 0
|
|
||||||
|
|
||||||
/* The hwloc symbol prefix */
|
|
||||||
#define HWLOC_SYM_PREFIX hwloc_
|
|
||||||
|
|
||||||
/* The hwloc symbol prefix in all caps */
|
|
||||||
#define HWLOC_SYM_PREFIX_CAPS HWLOC_
|
|
||||||
|
|
||||||
#endif /* HWLOC_CONFIG_H */
|
|
||||||
513
src/3rdparty/hwloc/include/hwloc/bitmap.h
vendored
513
src/3rdparty/hwloc/include/hwloc/bitmap.h
vendored
@@ -1,513 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2009 CNRS
|
|
||||||
* Copyright © 2009-2023 Inria. All rights reserved.
|
|
||||||
* Copyright © 2009-2012 Université Bordeaux
|
|
||||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief The bitmap API, for use in hwloc itself.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_BITMAP_H
|
|
||||||
#define HWLOC_BITMAP_H
|
|
||||||
|
|
||||||
#include "hwloc/autogen/config.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_bitmap The bitmap API
|
|
||||||
*
|
|
||||||
* The ::hwloc_bitmap_t type represents a set of integers (positive or null).
|
|
||||||
* A bitmap may be of infinite size (all bits are set after some point).
|
|
||||||
* A bitmap may even be full if all bits are set.
|
|
||||||
*
|
|
||||||
* Bitmaps are used by hwloc for sets of OS processors
|
|
||||||
* (which may actually be hardware threads) as by ::hwloc_cpuset_t
|
|
||||||
* (a typedef for ::hwloc_bitmap_t), or sets of NUMA memory nodes
|
|
||||||
* as ::hwloc_nodeset_t (also a typedef for ::hwloc_bitmap_t).
|
|
||||||
* Those are used for cpuset and nodeset fields in the ::hwloc_obj structure,
|
|
||||||
* see \ref hwlocality_object_sets.
|
|
||||||
*
|
|
||||||
* <em>Both CPU and node sets are always indexed by OS physical number.</em>
|
|
||||||
* However users should usually not build CPU and node sets manually
|
|
||||||
* (e.g. with hwloc_bitmap_set()).
|
|
||||||
* One should rather use existing object sets and combine them with
|
|
||||||
* hwloc_bitmap_or(), etc.
|
|
||||||
* For instance, binding the current thread on a pair of cores may be performed with:
|
|
||||||
* \code
|
|
||||||
* hwloc_obj_t core1 = ... , core2 = ... ;
|
|
||||||
* hwloc_bitmap_t set = hwloc_bitmap_alloc();
|
|
||||||
* hwloc_bitmap_or(set, core1->cpuset, core2->cpuset);
|
|
||||||
* hwloc_set_cpubind(topology, set, HWLOC_CPUBIND_THREAD);
|
|
||||||
* hwloc_bitmap_free(set);
|
|
||||||
* \endcode
|
|
||||||
*
|
|
||||||
* \note Most functions below return 0 on success and -1 on error.
|
|
||||||
* The usual error case would be an internal failure to realloc/extend
|
|
||||||
* the storage of the bitmap (\p errno would be set to \c ENOMEM).
|
|
||||||
* See also \ref hwlocality_api_error_reporting.
|
|
||||||
*
|
|
||||||
* \note Several examples of using the bitmap API are available under the
|
|
||||||
* doc/examples/ directory in the source tree.
|
|
||||||
* Regression tests such as tests/hwloc/hwloc_bitmap*.c also make intensive use
|
|
||||||
* of this API.
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief
|
|
||||||
* Set of bits represented as an opaque pointer to an internal bitmap.
|
|
||||||
*/
|
|
||||||
typedef struct hwloc_bitmap_s * hwloc_bitmap_t;
|
|
||||||
/** \brief a non-modifiable ::hwloc_bitmap_t */
|
|
||||||
typedef const struct hwloc_bitmap_s * hwloc_const_bitmap_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bitmap allocation, freeing and copying.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Allocate a new empty bitmap.
|
|
||||||
*
|
|
||||||
* \returns A valid bitmap or \c NULL.
|
|
||||||
*
|
|
||||||
* The bitmap should be freed by a corresponding call to
|
|
||||||
* hwloc_bitmap_free().
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_alloc(void) __hwloc_attribute_malloc;
|
|
||||||
|
|
||||||
/** \brief Allocate a new full bitmap.
|
|
||||||
*
|
|
||||||
* \returns A valid bitmap or \c NULL.
|
|
||||||
*
|
|
||||||
* The bitmap should be freed by a corresponding call to
|
|
||||||
* hwloc_bitmap_free().
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_alloc_full(void) __hwloc_attribute_malloc;
|
|
||||||
|
|
||||||
/** \brief Free bitmap \p bitmap.
|
|
||||||
*
|
|
||||||
* If \p bitmap is \c NULL, no operation is performed.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC void hwloc_bitmap_free(hwloc_bitmap_t bitmap);
|
|
||||||
|
|
||||||
/** \brief Duplicate bitmap \p bitmap by allocating a new bitmap and copying \p bitmap contents.
|
|
||||||
*
|
|
||||||
* If \p bitmap is \c NULL, \c NULL is returned.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_dup(hwloc_const_bitmap_t bitmap) __hwloc_attribute_malloc;
|
|
||||||
|
|
||||||
/** \brief Copy the contents of bitmap \p src into the already allocated bitmap \p dst */
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_copy(hwloc_bitmap_t dst, hwloc_const_bitmap_t src);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bitmap/String Conversion
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Stringify a bitmap.
|
|
||||||
*
|
|
||||||
* 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).
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* \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.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* 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).
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_list_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
|
|
||||||
|
|
||||||
/** \brief Stringify a bitmap in the taskset-specific format.
|
|
||||||
*
|
|
||||||
* The taskset command manipulates bitmap strings that contain a single
|
|
||||||
* (possible very long) hexadecimal number starting with 0x.
|
|
||||||
*
|
|
||||||
* 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).
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_taskset_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Building bitmaps.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Empty the bitmap \p bitmap */
|
|
||||||
HWLOC_DECLSPEC void hwloc_bitmap_zero(hwloc_bitmap_t bitmap);
|
|
||||||
|
|
||||||
/** \brief Fill bitmap \p bitmap with all possible indexes (even if those objects don't exist or are otherwise unavailable) */
|
|
||||||
HWLOC_DECLSPEC void hwloc_bitmap_fill(hwloc_bitmap_t bitmap);
|
|
||||||
|
|
||||||
/** \brief Empty the bitmap \p bitmap and add bit \p id */
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_only(hwloc_bitmap_t bitmap, unsigned id);
|
|
||||||
|
|
||||||
/** \brief Fill the bitmap \p and clear the index \p id */
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_allbut(hwloc_bitmap_t bitmap, unsigned id);
|
|
||||||
|
|
||||||
/** \brief Setup bitmap \p bitmap from unsigned long \p mask */
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_from_ulong(hwloc_bitmap_t bitmap, unsigned long mask);
|
|
||||||
|
|
||||||
/** \brief Setup bitmap \p bitmap from unsigned long \p mask used as \p i -th subset */
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_from_ith_ulong(hwloc_bitmap_t bitmap, unsigned i, unsigned long mask);
|
|
||||||
|
|
||||||
/** \brief Setup bitmap \p bitmap from unsigned longs \p masks used as first \p nr subsets */
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_from_ulongs(hwloc_bitmap_t bitmap, unsigned nr, const unsigned long *masks);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Modifying bitmaps.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Add index \p id in bitmap \p bitmap */
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_set(hwloc_bitmap_t bitmap, unsigned id);
|
|
||||||
|
|
||||||
/** \brief Add indexes from \p begin to \p end in bitmap \p bitmap.
|
|
||||||
*
|
|
||||||
* If \p end is \c -1, the range is infinite.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_set_range(hwloc_bitmap_t bitmap, unsigned begin, int end);
|
|
||||||
|
|
||||||
/** \brief Replace \p i -th subset of bitmap \p bitmap with unsigned long \p mask */
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_set_ith_ulong(hwloc_bitmap_t bitmap, unsigned i, unsigned long mask);
|
|
||||||
|
|
||||||
/** \brief Remove index \p id from bitmap \p bitmap */
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_clr(hwloc_bitmap_t bitmap, unsigned id);
|
|
||||||
|
|
||||||
/** \brief Remove indexes from \p begin to \p end in bitmap \p bitmap.
|
|
||||||
*
|
|
||||||
* If \p end is \c -1, the range is infinite.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_clr_range(hwloc_bitmap_t bitmap, unsigned begin, int end);
|
|
||||||
|
|
||||||
/** \brief Keep a single index among those set in bitmap \p bitmap
|
|
||||||
*
|
|
||||||
* May be useful before binding so that the process does not
|
|
||||||
* have a chance of migrating between multiple processors
|
|
||||||
* in the original mask.
|
|
||||||
* Instead of running the task on any PU inside the given CPU set,
|
|
||||||
* the operating system scheduler will be forced to run it on a single
|
|
||||||
* of these PUs.
|
|
||||||
* It avoids a migration overhead and cache-line ping-pongs between PUs.
|
|
||||||
*
|
|
||||||
* \note This function is NOT meant to distribute multiple processes
|
|
||||||
* within a single CPU set. It always return the same single bit when
|
|
||||||
* called multiple times on the same input set. hwloc_distrib() may
|
|
||||||
* be used for generating CPU sets to distribute multiple tasks below
|
|
||||||
* a single multi-PU object.
|
|
||||||
*
|
|
||||||
* \note This function cannot be applied to an object set directly. It
|
|
||||||
* should be applied to a copy (which may be obtained with hwloc_bitmap_dup()).
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_singlify(hwloc_bitmap_t bitmap);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Consulting bitmaps.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Convert the beginning part of bitmap \p bitmap into unsigned long \p mask */
|
|
||||||
HWLOC_DECLSPEC unsigned long hwloc_bitmap_to_ulong(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Convert the \p i -th subset of bitmap \p bitmap into unsigned long mask */
|
|
||||||
HWLOC_DECLSPEC unsigned long hwloc_bitmap_to_ith_ulong(hwloc_const_bitmap_t bitmap, unsigned i) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Convert the first \p nr subsets of bitmap \p bitmap into the array of \p nr unsigned long \p masks
|
|
||||||
*
|
|
||||||
* \p nr may be determined earlier with hwloc_bitmap_nr_ulongs().
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_to_ulongs(hwloc_const_bitmap_t bitmap, unsigned nr, unsigned long *masks);
|
|
||||||
|
|
||||||
/** \brief Return the number of unsigned longs required for storing bitmap \p bitmap entirely
|
|
||||||
*
|
|
||||||
* This is the number of contiguous unsigned longs from the very first bit of the bitmap
|
|
||||||
* (even if unset) up to the last set bit.
|
|
||||||
* This is useful for knowing the \p nr parameter to pass to hwloc_bitmap_to_ulongs()
|
|
||||||
* (or which calls to hwloc_bitmap_to_ith_ulong() are needed)
|
|
||||||
* to entirely convert a bitmap into multiple unsigned longs.
|
|
||||||
*
|
|
||||||
* When called on the output of hwloc_topology_get_topology_cpuset(),
|
|
||||||
* the returned number is large enough for all cpusets of the topology.
|
|
||||||
*
|
|
||||||
* \return the number of unsigned longs required.
|
|
||||||
* \return -1 if \p bitmap is infinite.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_nr_ulongs(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Test whether index \p id is part of bitmap \p bitmap.
|
|
||||||
*
|
|
||||||
* \return 1 if the bit at index \p id is set in bitmap \p bitmap, 0 otherwise.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_isset(hwloc_const_bitmap_t bitmap, unsigned id) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Test whether bitmap \p bitmap is empty
|
|
||||||
*
|
|
||||||
* \return 1 if bitmap is empty, 0 otherwise.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_iszero(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Test whether bitmap \p bitmap is completely full
|
|
||||||
*
|
|
||||||
* \return 1 if bitmap is full, 0 otherwise.
|
|
||||||
*
|
|
||||||
* \note A full bitmap is always infinitely set.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_isfull(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Compute the first index (least significant bit) in bitmap \p bitmap
|
|
||||||
*
|
|
||||||
* \return the first index set in \p bitmap.
|
|
||||||
* \return -1 if \p bitmap is empty.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_first(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Compute the next index in bitmap \p bitmap which is after index \p prev
|
|
||||||
*
|
|
||||||
* \return the first index set in \p bitmap if \p prev is \c -1.
|
|
||||||
* \return the next index set in \p bitmap if \p prev is not \c -1.
|
|
||||||
* \return -1 if no index with higher index is set in \p bitmap.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_next(hwloc_const_bitmap_t bitmap, int prev) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Compute the last index (most significant bit) in bitmap \p bitmap
|
|
||||||
*
|
|
||||||
* \return the last index set in \p bitmap.
|
|
||||||
* \return -1 if \p bitmap is empty, or if \p bitmap is infinitely set.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_last(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Compute the "weight" of bitmap \p bitmap (i.e., number of
|
|
||||||
* indexes that are in the bitmap).
|
|
||||||
*
|
|
||||||
* \return the number of indexes that are in the bitmap.
|
|
||||||
* \return -1 if \p bitmap is infinitely set.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_weight(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Compute the first unset index (least significant bit) in bitmap \p bitmap
|
|
||||||
*
|
|
||||||
* \return the first unset index in \p bitmap.
|
|
||||||
* \return -1 if \p bitmap is full.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_first_unset(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Compute the next unset index in bitmap \p bitmap which is after index \p prev
|
|
||||||
*
|
|
||||||
* \return the first index unset in \p bitmap if \p prev is \c -1.
|
|
||||||
* \return the next index unset in \p bitmap if \p prev is not \c -1.
|
|
||||||
* \return -1 if no index with higher index is unset in \p bitmap.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_next_unset(hwloc_const_bitmap_t bitmap, int prev) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Compute the last unset index (most significant bit) in bitmap \p bitmap
|
|
||||||
*
|
|
||||||
* \return the last index unset in \p bitmap.
|
|
||||||
* \return -1 if \p bitmap is full, or if \p bitmap is not infinitely set.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_last_unset(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Loop macro iterating on bitmap \p bitmap
|
|
||||||
*
|
|
||||||
* The loop must start with hwloc_bitmap_foreach_begin() and end
|
|
||||||
* with hwloc_bitmap_foreach_end() followed by a terminating ';'.
|
|
||||||
*
|
|
||||||
* \p id is the loop variable; it should be an unsigned int. The
|
|
||||||
* first iteration will set \p id to the lowest index in the bitmap.
|
|
||||||
* Successive iterations will iterate through, in order, all remaining
|
|
||||||
* indexes set in the bitmap. To be specific: each iteration will return a
|
|
||||||
* value for \p id such that hwloc_bitmap_isset(bitmap, id) is true.
|
|
||||||
*
|
|
||||||
* The assert prevents the loop from being infinite if the bitmap is infinitely set.
|
|
||||||
*
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
#define hwloc_bitmap_foreach_begin(id, bitmap) \
|
|
||||||
do { \
|
|
||||||
assert(hwloc_bitmap_weight(bitmap) != -1); \
|
|
||||||
for (id = hwloc_bitmap_first(bitmap); \
|
|
||||||
(unsigned) id != (unsigned) -1; \
|
|
||||||
id = hwloc_bitmap_next(bitmap, id)) {
|
|
||||||
|
|
||||||
/** \brief End of loop macro iterating on a bitmap.
|
|
||||||
*
|
|
||||||
* Needs a terminating ';'.
|
|
||||||
*
|
|
||||||
* \sa hwloc_bitmap_foreach_begin()
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
#define hwloc_bitmap_foreach_end() \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Combining bitmaps.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Or bitmaps \p bitmap1 and \p bitmap2 and store the result in bitmap \p res
|
|
||||||
*
|
|
||||||
* \p res can be the same as \p bitmap1 or \p bitmap2
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_or (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
|
|
||||||
|
|
||||||
/** \brief And bitmaps \p bitmap1 and \p bitmap2 and store the result in bitmap \p res
|
|
||||||
*
|
|
||||||
* \p res can be the same as \p bitmap1 or \p bitmap2
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_and (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
|
|
||||||
|
|
||||||
/** \brief And bitmap \p bitmap1 and the negation of \p bitmap2 and store the result in bitmap \p res
|
|
||||||
*
|
|
||||||
* \p res can be the same as \p bitmap1 or \p bitmap2
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_andnot (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
|
|
||||||
|
|
||||||
/** \brief Xor bitmaps \p bitmap1 and \p bitmap2 and store the result in bitmap \p res
|
|
||||||
*
|
|
||||||
* \p res can be the same as \p bitmap1 or \p bitmap2
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_xor (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
|
|
||||||
|
|
||||||
/** \brief Negate bitmap \p bitmap and store the result in bitmap \p res
|
|
||||||
*
|
|
||||||
* \p res can be the same as \p bitmap
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_not (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Comparing bitmaps.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Test whether bitmaps \p bitmap1 and \p bitmap2 intersects.
|
|
||||||
*
|
|
||||||
* \return 1 if bitmaps intersect, 0 otherwise.
|
|
||||||
*
|
|
||||||
* \note The empty bitmap does not intersect any other bitmap.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_intersects (hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Test whether bitmap \p sub_bitmap is part of bitmap \p super_bitmap.
|
|
||||||
*
|
|
||||||
* \return 1 if \p sub_bitmap is included in \p super_bitmap, 0 otherwise.
|
|
||||||
*
|
|
||||||
* \note The empty bitmap is considered included in any other bitmap.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_isincluded (hwloc_const_bitmap_t sub_bitmap, hwloc_const_bitmap_t super_bitmap) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Test whether bitmap \p bitmap1 is equal to bitmap \p bitmap2.
|
|
||||||
*
|
|
||||||
* \return 1 if bitmaps are equal, 0 otherwise.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_isequal (hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Compare bitmaps \p bitmap1 and \p bitmap2 using their lowest index.
|
|
||||||
*
|
|
||||||
* A bitmap is considered smaller if its least significant bit is smaller.
|
|
||||||
* The empty bitmap is considered higher than anything (because its least significant bit does not exist).
|
|
||||||
*
|
|
||||||
* \return -1 if \p bitmap1 is considered smaller than \p bitmap2.
|
|
||||||
* \return 1 if \p bitmap1 is considered larger than \p bitmap2.
|
|
||||||
*
|
|
||||||
* For instance comparing binary bitmaps 0011 and 0110 returns -1
|
|
||||||
* (hence 0011 is considered smaller than 0110)
|
|
||||||
* because least significant bit of 0011 (0001) is smaller than least significant bit of 0110 (0010).
|
|
||||||
* Comparing 01001 and 00110 would also return -1 for the same reason.
|
|
||||||
*
|
|
||||||
* \return 0 if bitmaps are considered equal, even if they are not strictly equal.
|
|
||||||
* They just need to have the same least significant bit.
|
|
||||||
* For instance, comparing binary bitmaps 0010 and 0110 returns 0 because they have the same least significant bit.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_compare_first(hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** \brief Compare bitmaps \p bitmap1 and \p bitmap2 in lexicographic order.
|
|
||||||
*
|
|
||||||
* Lexicographic comparison of bitmaps, starting for their highest indexes.
|
|
||||||
* Compare last indexes first, then second, etc.
|
|
||||||
* The empty bitmap is considered lower than anything.
|
|
||||||
*
|
|
||||||
* \return -1 if \p bitmap1 is considered smaller than \p bitmap2.
|
|
||||||
* \return 1 if \p bitmap1 is considered larger than \p bitmap2.
|
|
||||||
* \return 0 if bitmaps are equal (contrary to hwloc_bitmap_compare_first()).
|
|
||||||
*
|
|
||||||
* For instance comparing binary bitmaps 0011 and 0110 returns -1
|
|
||||||
* (hence 0011 is considered smaller than 0110).
|
|
||||||
* Comparing 00101 and 01010 returns -1 too.
|
|
||||||
*
|
|
||||||
* \note This is different from the non-existing hwloc_bitmap_compare_last()
|
|
||||||
* which would only compare the highest index of each bitmap.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_bitmap_compare(hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_BITMAP_H */
|
|
||||||
193
src/3rdparty/hwloc/include/hwloc/cpukinds.h
vendored
193
src/3rdparty/hwloc/include/hwloc/cpukinds.h
vendored
@@ -1,193 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2020-2021 Inria. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Kinds of CPU cores.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_CPUKINDS_H
|
|
||||||
#define HWLOC_CPUKINDS_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#elif 0
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_cpukinds Kinds of CPU cores
|
|
||||||
*
|
|
||||||
* Platforms with heterogeneous CPUs may have some cores with
|
|
||||||
* different features or frequencies.
|
|
||||||
* This API exposes identical PUs in sets called CPU kinds.
|
|
||||||
* Each PU of the topology may only be in a single kind.
|
|
||||||
*
|
|
||||||
* The number of kinds may be obtained with hwloc_cpukinds_get_nr().
|
|
||||||
* If the platform is homogeneous, there may be a single kind
|
|
||||||
* with all PUs.
|
|
||||||
* If the platform or operating system does not expose any
|
|
||||||
* information about CPU cores, there may be no kind at all.
|
|
||||||
*
|
|
||||||
* The index of the kind that describes a given CPU set
|
|
||||||
* (if any, and not partially)
|
|
||||||
* may be obtained with hwloc_cpukinds_get_by_cpuset().
|
|
||||||
*
|
|
||||||
* From the index of a kind, it is possible to retrieve information
|
|
||||||
* with hwloc_cpukinds_get_info():
|
|
||||||
* an abstracted efficiency value,
|
|
||||||
* and an array of info attributes
|
|
||||||
* (for instance the "CoreType" and "FrequencyMaxMHz",
|
|
||||||
* see \ref topoattrs_cpukinds).
|
|
||||||
*
|
|
||||||
* A higher efficiency value means greater intrinsic performance
|
|
||||||
* (and possibly less performance/power efficiency).
|
|
||||||
* Kinds with lower efficiency values are ranked first:
|
|
||||||
* Passing 0 as \p kind_index to hwloc_cpukinds_get_info() will
|
|
||||||
* return information about the CPU kind with lower performance
|
|
||||||
* but higher energy-efficiency.
|
|
||||||
* Higher \p kind_index values would rather return information
|
|
||||||
* about power-hungry high-performance cores.
|
|
||||||
*
|
|
||||||
* When available, efficiency values are gathered from the operating system.
|
|
||||||
* If so, \p cpukind_efficiency is set in the struct hwloc_topology_discovery_support array.
|
|
||||||
* This is currently available on Windows 10, Mac OS X (Darwin),
|
|
||||||
* and on some Linux platforms where core "capacity" is exposed in sysfs.
|
|
||||||
*
|
|
||||||
* If the operating system does not expose core efficiencies natively,
|
|
||||||
* hwloc tries to compute efficiencies by comparing CPU kinds using
|
|
||||||
* frequencies (on ARM), or core types and frequencies (on other architectures).
|
|
||||||
* The environment variable HWLOC_CPUKINDS_RANKING may be used
|
|
||||||
* to change this heuristics, see \ref envvar.
|
|
||||||
*
|
|
||||||
* If hwloc fails to rank any kind, for instance because the operating
|
|
||||||
* system does not expose efficiencies and core frequencies,
|
|
||||||
* all kinds will have an unknown efficiency (\c -1),
|
|
||||||
* and they are not indexed/ordered in any specific way.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Get the number of different kinds of CPU cores in the topology.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \return The number of CPU kinds (positive integer) on success.
|
|
||||||
* \return \c 0 if no information about kinds was found.
|
|
||||||
* \return \c -1 with \p errno set to \c EINVAL if \p flags is invalid.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_cpukinds_get_nr(hwloc_topology_t topology,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Get the index of the CPU kind that contains CPUs listed in \p cpuset.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \return The index of the CPU kind (positive integer or 0) on success.
|
|
||||||
* \return \c -1 with \p errno set to \c EXDEV if \p cpuset is
|
|
||||||
* only partially included in the some kind.
|
|
||||||
* \return \c -1 with \p errno set to \c ENOENT if \p cpuset is
|
|
||||||
* not included in any kind, even partially.
|
|
||||||
* \return \c -1 with \p errno set to \c EINVAL if parameters are invalid.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_cpukinds_get_by_cpuset(hwloc_topology_t topology,
|
|
||||||
hwloc_const_bitmap_t cpuset,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Get the CPU set and infos about a CPU kind in the topology.
|
|
||||||
*
|
|
||||||
* \p kind_index identifies one kind of CPU between 0 and the number
|
|
||||||
* of kinds returned by hwloc_cpukinds_get_nr() minus 1.
|
|
||||||
*
|
|
||||||
* If not \c NULL, the bitmap \p cpuset will be filled with
|
|
||||||
* the set of PUs of this kind.
|
|
||||||
*
|
|
||||||
* The integer pointed by \p efficiency, if not \c NULL will, be filled
|
|
||||||
* with the ranking of this kind of CPU in term of efficiency (see above).
|
|
||||||
* It ranges from \c 0 to the number of kinds
|
|
||||||
* (as reported by hwloc_cpukinds_get_nr()) minus 1.
|
|
||||||
*
|
|
||||||
* Kinds with lower efficiency are reported first.
|
|
||||||
*
|
|
||||||
* If there is a single kind in the topology, its efficiency \c 0.
|
|
||||||
* If the efficiency of some kinds of cores is unknown,
|
|
||||||
* the efficiency of all kinds is set to \c -1,
|
|
||||||
* and kinds are reported in no specific order.
|
|
||||||
*
|
|
||||||
* The array of info attributes (for instance the "CoreType",
|
|
||||||
* "FrequencyMaxMHz" or "FrequencyBaseMHz", see \ref topoattrs_cpukinds)
|
|
||||||
* and its length are returned in \p infos or \p nr_infos.
|
|
||||||
* The array belongs to the topology, it should not be freed or modified.
|
|
||||||
*
|
|
||||||
* If \p nr_infos or \p infos is \c NULL, no info is returned.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \return \c 0 on success.
|
|
||||||
* \return \c -1 with \p errno set to \c ENOENT if \p kind_index does not match any CPU kind.
|
|
||||||
* \return \c -1 with \p errno set to \c EINVAL if parameters are invalid.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_cpukinds_get_info(hwloc_topology_t topology,
|
|
||||||
unsigned kind_index,
|
|
||||||
hwloc_bitmap_t cpuset,
|
|
||||||
int *efficiency,
|
|
||||||
unsigned *nr_infos, struct hwloc_info_s **infos,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Register a kind of CPU in the topology.
|
|
||||||
*
|
|
||||||
* Mark the PUs listed in \p cpuset as being of the same kind
|
|
||||||
* with respect to the given attributes.
|
|
||||||
*
|
|
||||||
* \p forced_efficiency should be \c -1 if unknown.
|
|
||||||
* Otherwise it is an abstracted efficiency value to enforce
|
|
||||||
* the ranking of all kinds if all of them have valid (and
|
|
||||||
* different) efficiencies.
|
|
||||||
*
|
|
||||||
* The array \p infos of size \p nr_infos may be used to provide
|
|
||||||
* info names and values describing this kind of PUs.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* Parameters \p cpuset and \p infos will be duplicated internally,
|
|
||||||
* the caller is responsible for freeing them.
|
|
||||||
*
|
|
||||||
* If \p cpuset overlaps with some existing kinds, those might get
|
|
||||||
* modified or split. For instance if existing kind A contains
|
|
||||||
* PUs 0 and 1, and one registers another kind for PU 1 and 2,
|
|
||||||
* there will be 3 resulting kinds:
|
|
||||||
* existing kind A is restricted to only PU 0;
|
|
||||||
* new kind B contains only PU 1 and combines information from A
|
|
||||||
* and from the newly-registered kind;
|
|
||||||
* new kind C contains only PU 2 and only gets information from
|
|
||||||
* the newly-registered kind.
|
|
||||||
*
|
|
||||||
* \note The efficiency \p forced_efficiency provided to this function
|
|
||||||
* may be different from the one reported later by hwloc_cpukinds_get_info()
|
|
||||||
* because hwloc will scale efficiency values down to
|
|
||||||
* between 0 and the number of kinds minus 1.
|
|
||||||
*
|
|
||||||
* \return \c 0 on success.
|
|
||||||
* \return \c -1 with \p errno set to \c EINVAL if some parameters are invalid,
|
|
||||||
* for instance if \p cpuset is \c NULL or empty.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_cpukinds_register(hwloc_topology_t topology,
|
|
||||||
hwloc_bitmap_t cpuset,
|
|
||||||
int forced_efficiency,
|
|
||||||
unsigned nr_infos, struct hwloc_info_s *infos,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_CPUKINDS_H */
|
|
||||||
226
src/3rdparty/hwloc/include/hwloc/cuda.h
vendored
226
src/3rdparty/hwloc/include/hwloc/cuda.h
vendored
@@ -1,226 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2010-2023 Inria. All rights reserved.
|
|
||||||
* Copyright © 2010-2011 Université Bordeaux
|
|
||||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Macros to help interaction between hwloc and the CUDA Driver API.
|
|
||||||
*
|
|
||||||
* Applications that use both hwloc and the CUDA Driver API may want to
|
|
||||||
* include this file so as to get topology information for CUDA devices.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_CUDA_H
|
|
||||||
#define HWLOC_CUDA_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
#include "hwloc/autogen/config.h"
|
|
||||||
#include "hwloc/helper.h"
|
|
||||||
#ifdef HWLOC_LINUX_SYS
|
|
||||||
#include "hwloc/linux.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cuda.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_cuda Interoperability with the CUDA Driver API
|
|
||||||
*
|
|
||||||
* This interface offers ways to retrieve topology information about
|
|
||||||
* CUDA devices when using the CUDA Driver API.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Return the domain, bus and device IDs of the CUDA device \p cudevice.
|
|
||||||
*
|
|
||||||
* Device \p cudevice must match the local machine.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 on error, for instance if device information could not be found.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_cuda_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused,
|
|
||||||
CUdevice cudevice, int *domain, int *bus, int *dev)
|
|
||||||
{
|
|
||||||
CUresult cres;
|
|
||||||
|
|
||||||
#if CUDA_VERSION >= 4000
|
|
||||||
cres = cuDeviceGetAttribute(domain, CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, cudevice);
|
|
||||||
if (cres != CUDA_SUCCESS) {
|
|
||||||
errno = ENOSYS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
*domain = 0;
|
|
||||||
#endif
|
|
||||||
cres = cuDeviceGetAttribute(bus, CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, cudevice);
|
|
||||||
if (cres != CUDA_SUCCESS) {
|
|
||||||
errno = ENOSYS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
cres = cuDeviceGetAttribute(dev, CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, cudevice);
|
|
||||||
if (cres != CUDA_SUCCESS) {
|
|
||||||
errno = ENOSYS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the CPU set of processors that are physically
|
|
||||||
* close to device \p cudevice.
|
|
||||||
*
|
|
||||||
* Store in \p set the CPU-set describing the locality of the CUDA device \p cudevice.
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p cudevice must match the local machine.
|
|
||||||
* I/O devices detection and the CUDA 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_cuda_get_device_osdev()
|
|
||||||
* and hwloc_cuda_get_device_osdev_by_index().
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_cuda_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
|
||||||
CUdevice cudevice, hwloc_cpuset_t set)
|
|
||||||
{
|
|
||||||
#ifdef HWLOC_LINUX_SYS
|
|
||||||
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
|
|
||||||
#define HWLOC_CUDA_DEVICE_SYSFS_PATH_MAX 128
|
|
||||||
char path[HWLOC_CUDA_DEVICE_SYSFS_PATH_MAX];
|
|
||||||
int domainid, busid, deviceid;
|
|
||||||
|
|
||||||
if (hwloc_cuda_get_device_pci_ids(topology, cudevice, &domainid, &busid, &deviceid))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!hwloc_topology_is_thissystem(topology)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.0/local_cpus", domainid, busid, deviceid);
|
|
||||||
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 hwloc PCI device object corresponding to the
|
|
||||||
* CUDA device \p cudevice.
|
|
||||||
*
|
|
||||||
* \return The hwloc PCI device object describing the CUDA device \p cudevice.
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p cudevice must match the local machine.
|
|
||||||
* I/O devices detection must be enabled in topology \p topology.
|
|
||||||
* The CUDA component is not needed in the topology.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_cuda_get_device_pcidev(hwloc_topology_t topology, CUdevice cudevice)
|
|
||||||
{
|
|
||||||
int domain, bus, dev;
|
|
||||||
|
|
||||||
if (hwloc_cuda_get_device_pci_ids(topology, cudevice, &domain, &bus, &dev))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the hwloc OS device object corresponding to CUDA device \p cudevice.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object that describes the given CUDA device \p cudevice.
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p cudevice must match the local machine.
|
|
||||||
* I/O devices detection and the CUDA component must be enabled in the topology.
|
|
||||||
* If not, the locality of the object may still be found using
|
|
||||||
* hwloc_cuda_get_device_cpuset().
|
|
||||||
*
|
|
||||||
* \note This function cannot work if PCI devices are filtered out.
|
|
||||||
*
|
|
||||||
* \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_cuda_get_device_osdev(hwloc_topology_t topology, CUdevice cudevice)
|
|
||||||
{
|
|
||||||
hwloc_obj_t osdev = NULL;
|
|
||||||
int domain, bus, dev;
|
|
||||||
|
|
||||||
if (hwloc_cuda_get_device_pci_ids(topology, cudevice, &domain, &bus, &dev))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
osdev = NULL;
|
|
||||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
|
||||||
hwloc_obj_t pcidev = osdev->parent;
|
|
||||||
if (strncmp(osdev->name, "cuda", 4))
|
|
||||||
continue;
|
|
||||||
if (pcidev
|
|
||||||
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
|
|
||||||
&& (int) pcidev->attr->pcidev.domain == domain
|
|
||||||
&& (int) pcidev->attr->pcidev.bus == bus
|
|
||||||
&& (int) pcidev->attr->pcidev.dev == dev
|
|
||||||
&& pcidev->attr->pcidev.func == 0)
|
|
||||||
return osdev;
|
|
||||||
/* if PCI are filtered out, we need a info attr to match on */
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the hwloc OS device object corresponding to the
|
|
||||||
* CUDA device whose index is \p idx.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object describing the CUDA device whose index is \p idx.
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* The topology \p topology does not necessarily have to match the current
|
|
||||||
* machine. For instance the topology may be an XML import of a remote host.
|
|
||||||
* I/O devices detection and the CUDA component must be enabled in the topology.
|
|
||||||
*
|
|
||||||
* \note The corresponding PCI device object can be obtained by looking
|
|
||||||
* at the OS device parent object (unless PCI devices are filtered out).
|
|
||||||
*
|
|
||||||
* \note This function is identical to hwloc_cudart_get_device_osdev_by_index().
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_cuda_get_device_osdev_by_index(hwloc_topology_t topology, unsigned idx)
|
|
||||||
{
|
|
||||||
hwloc_obj_t osdev = NULL;
|
|
||||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
|
||||||
if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
|
|
||||||
&& osdev->name
|
|
||||||
&& !strncmp("cuda", osdev->name, 4)
|
|
||||||
&& atoi(osdev->name + 4) == (int) idx)
|
|
||||||
return osdev;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_CUDA_H */
|
|
||||||
183
src/3rdparty/hwloc/include/hwloc/cudart.h
vendored
183
src/3rdparty/hwloc/include/hwloc/cudart.h
vendored
@@ -1,183 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2010-2023 Inria. All rights reserved.
|
|
||||||
* Copyright © 2010-2011 Université Bordeaux
|
|
||||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Macros to help interaction between hwloc and the CUDA Runtime API.
|
|
||||||
*
|
|
||||||
* Applications that use both hwloc and the CUDA Runtime API may want to
|
|
||||||
* include this file so as to get topology information for CUDA devices.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_CUDART_H
|
|
||||||
#define HWLOC_CUDART_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
#include "hwloc/autogen/config.h"
|
|
||||||
#include "hwloc/helper.h"
|
|
||||||
#ifdef HWLOC_LINUX_SYS
|
|
||||||
#include "hwloc/linux.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cuda.h> /* for CUDA_VERSION */
|
|
||||||
#include <cuda_runtime_api.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_cudart Interoperability with the CUDA Runtime API
|
|
||||||
*
|
|
||||||
* This interface offers ways to retrieve topology information about
|
|
||||||
* CUDA devices when using the CUDA Runtime API.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Return the domain, bus and device IDs of the CUDA device whose index is \p idx.
|
|
||||||
*
|
|
||||||
* Device index \p idx must match the local machine.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 on error, for instance if device information could not be found.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_cudart_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused,
|
|
||||||
int idx, int *domain, int *bus, int *dev)
|
|
||||||
{
|
|
||||||
cudaError_t cerr;
|
|
||||||
struct cudaDeviceProp prop;
|
|
||||||
|
|
||||||
cerr = cudaGetDeviceProperties(&prop, idx);
|
|
||||||
if (cerr) {
|
|
||||||
errno = ENOSYS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CUDA_VERSION >= 4000
|
|
||||||
*domain = prop.pciDomainID;
|
|
||||||
#else
|
|
||||||
*domain = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*bus = prop.pciBusID;
|
|
||||||
*dev = prop.pciDeviceID;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the CPU set of processors that are physically
|
|
||||||
* close to device \p idx.
|
|
||||||
*
|
|
||||||
* Store in \p set the CPU-set describing the locality of the CUDA device
|
|
||||||
* whose index is \p idx.
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p idx must match the local machine.
|
|
||||||
* I/O devices detection and the CUDA 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_cudart_get_device_osdev_by_index().
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_cudart_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
|
||||||
int idx, hwloc_cpuset_t set)
|
|
||||||
{
|
|
||||||
#ifdef HWLOC_LINUX_SYS
|
|
||||||
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
|
|
||||||
#define HWLOC_CUDART_DEVICE_SYSFS_PATH_MAX 128
|
|
||||||
char path[HWLOC_CUDART_DEVICE_SYSFS_PATH_MAX];
|
|
||||||
int domain, bus, dev;
|
|
||||||
|
|
||||||
if (hwloc_cudart_get_device_pci_ids(topology, idx, &domain, &bus, &dev))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!hwloc_topology_is_thissystem(topology)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.0/local_cpus", (unsigned) domain, (unsigned) bus, (unsigned) dev);
|
|
||||||
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 hwloc PCI device object corresponding to the
|
|
||||||
* CUDA device whose index is \p idx.
|
|
||||||
*
|
|
||||||
* \return The hwloc PCI device object describing the CUDA device whose index is \p idx.
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p idx must match the local machine.
|
|
||||||
* I/O devices detection must be enabled in topology \p topology.
|
|
||||||
* The CUDA component is not needed in the topology.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_cudart_get_device_pcidev(hwloc_topology_t topology, int idx)
|
|
||||||
{
|
|
||||||
int domain, bus, dev;
|
|
||||||
|
|
||||||
if (hwloc_cudart_get_device_pci_ids(topology, idx, &domain, &bus, &dev))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the hwloc OS device object corresponding to the
|
|
||||||
* CUDA device whose index is \p idx.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object describing the CUDA device whose index is \p idx.
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* The topology \p topology does not necessarily have to match the current
|
|
||||||
* machine. For instance the topology may be an XML import of a remote host.
|
|
||||||
* I/O devices detection and the CUDA component must be enabled in the topology.
|
|
||||||
* If not, the locality of the object may still be found using
|
|
||||||
* hwloc_cudart_get_device_cpuset().
|
|
||||||
*
|
|
||||||
* \note The corresponding PCI device object can be obtained by looking
|
|
||||||
* at the OS device parent object (unless PCI devices are filtered out).
|
|
||||||
*
|
|
||||||
* \note This function is identical to hwloc_cuda_get_device_osdev_by_index().
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_cudart_get_device_osdev_by_index(hwloc_topology_t topology, unsigned idx)
|
|
||||||
{
|
|
||||||
hwloc_obj_t osdev = NULL;
|
|
||||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
|
||||||
if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
|
|
||||||
&& osdev->name
|
|
||||||
&& !strncmp("cuda", osdev->name, 4)
|
|
||||||
&& atoi(osdev->name + 4) == (int) idx)
|
|
||||||
return osdev;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_CUDART_H */
|
|
||||||
217
src/3rdparty/hwloc/include/hwloc/deprecated.h
vendored
217
src/3rdparty/hwloc/include/hwloc/deprecated.h
vendored
@@ -1,217 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2009 CNRS
|
|
||||||
* Copyright © 2009-2022 Inria. All rights reserved.
|
|
||||||
* Copyright © 2009-2012 Université Bordeaux
|
|
||||||
* Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file contains the inline code of functions declared in hwloc.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_DEPRECATED_H
|
|
||||||
#define HWLOC_DEPRECATED_H
|
|
||||||
|
|
||||||
#ifndef HWLOC_H
|
|
||||||
#error Please include the main hwloc.h instead
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* backward compat with v2.0 before WHOLE_SYSTEM renaming */
|
|
||||||
#define HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM HWLOC_TOPOLOGY_FLAG_INCLUDE_DISALLOWED
|
|
||||||
/* backward compat with v1.11 before System removal */
|
|
||||||
#define HWLOC_OBJ_SYSTEM HWLOC_OBJ_MACHINE
|
|
||||||
/* backward compat with v1.10 before Socket->Package renaming */
|
|
||||||
#define HWLOC_OBJ_SOCKET HWLOC_OBJ_PACKAGE
|
|
||||||
/* backward compat with v1.10 before Node->NUMANode clarification */
|
|
||||||
#define HWLOC_OBJ_NODE HWLOC_OBJ_NUMANODE
|
|
||||||
|
|
||||||
/** \brief Add a distances structure.
|
|
||||||
*
|
|
||||||
* Superseded by hwloc_distances_add_create()+hwloc_distances_add_values()+hwloc_distances_add_commit()
|
|
||||||
* in v2.5.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_distances_add(hwloc_topology_t topology,
|
|
||||||
unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values,
|
|
||||||
unsigned long kind, unsigned long flags) __hwloc_attribute_deprecated;
|
|
||||||
|
|
||||||
/** \brief Insert a misc object by parent.
|
|
||||||
*
|
|
||||||
* Identical to hwloc_topology_insert_misc_object().
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_topology_insert_misc_object_by_parent(hwloc_topology_t topology, hwloc_obj_t parent, const char *name) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_topology_insert_misc_object_by_parent(hwloc_topology_t topology, hwloc_obj_t parent, const char *name)
|
|
||||||
{
|
|
||||||
return hwloc_topology_insert_misc_object(topology, parent, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Stringify the cpuset containing a set of objects.
|
|
||||||
*
|
|
||||||
* 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).
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_obj_cpuset_snprintf(char *str, size_t size, size_t nobj, struct hwloc_obj * const *objs) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_obj_cpuset_snprintf(char *str, size_t size, size_t nobj, struct hwloc_obj * const *objs)
|
|
||||||
{
|
|
||||||
hwloc_bitmap_t set = hwloc_bitmap_alloc();
|
|
||||||
int res;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
hwloc_bitmap_zero(set);
|
|
||||||
for(i=0; i<nobj; i++)
|
|
||||||
if (objs[i]->cpuset)
|
|
||||||
hwloc_bitmap_or(set, set, objs[i]->cpuset);
|
|
||||||
|
|
||||||
res = hwloc_bitmap_snprintf(str, size, set);
|
|
||||||
hwloc_bitmap_free(set);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Convert a type string into a type and some attributes.
|
|
||||||
*
|
|
||||||
* Deprecated by hwloc_type_sscanf()
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, void *typeattrp, size_t typeattrsize) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, void *typeattrp, size_t typeattrsize)
|
|
||||||
{
|
|
||||||
union hwloc_obj_attr_u attr;
|
|
||||||
int err = hwloc_type_sscanf(string, typep, &attr, sizeof(attr));
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
if (hwloc_obj_type_is_cache(*typep)) {
|
|
||||||
if (depthattrp)
|
|
||||||
*depthattrp = (int) attr.cache.depth;
|
|
||||||
if (typeattrp && typeattrsize >= sizeof(hwloc_obj_cache_type_t))
|
|
||||||
memcpy(typeattrp, &attr.cache.type, sizeof(hwloc_obj_cache_type_t));
|
|
||||||
} else if (*typep == HWLOC_OBJ_GROUP) {
|
|
||||||
if (depthattrp)
|
|
||||||
*depthattrp = (int) attr.group.depth;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Set the default memory binding policy of the current
|
|
||||||
* process or thread to prefer the NUMA node(s) specified by physical \p nodeset
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
|
||||||
{
|
|
||||||
return hwloc_set_membind(topology, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Query the default memory binding policy and physical locality of the
|
|
||||||
* current process or thread.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
|
||||||
{
|
|
||||||
return hwloc_get_membind(topology, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Set the default memory binding policy of the specified
|
|
||||||
* process to prefer the NUMA node(s) specified by physical \p nodeset
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_set_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_set_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
|
||||||
{
|
|
||||||
return hwloc_set_proc_membind(topology, pid, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Query the default memory binding policy and physical locality of the
|
|
||||||
* specified process.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_get_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_get_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
|
||||||
{
|
|
||||||
return hwloc_get_proc_membind(topology, pid, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Bind the already-allocated memory identified by (addr, len)
|
|
||||||
* to the NUMA node(s) in physical \p nodeset.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_set_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_set_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
|
||||||
{
|
|
||||||
return hwloc_set_area_membind(topology, addr, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Query the physical NUMA node(s) and binding policy of the memory
|
|
||||||
* identified by (\p addr, \p len ).
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_get_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_get_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
|
||||||
{
|
|
||||||
return hwloc_get_area_membind(topology, addr, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Allocate some memory on the given physical nodeset \p nodeset
|
|
||||||
*/
|
|
||||||
static __hwloc_inline void *
|
|
||||||
hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_malloc __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline void *
|
|
||||||
hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
|
||||||
{
|
|
||||||
return hwloc_alloc_membind(topology, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Allocate some memory on the given nodeset \p nodeset.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline void *
|
|
||||||
hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_malloc __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline void *
|
|
||||||
hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
|
||||||
{
|
|
||||||
return hwloc_alloc_membind_policy(topology, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Convert a CPU set into a NUMA node set and handle non-NUMA cases
|
|
||||||
*/
|
|
||||||
static __hwloc_inline void
|
|
||||||
hwloc_cpuset_to_nodeset_strict(hwloc_topology_t topology, hwloc_const_cpuset_t _cpuset, hwloc_nodeset_t nodeset) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline void
|
|
||||||
hwloc_cpuset_to_nodeset_strict(hwloc_topology_t topology, hwloc_const_cpuset_t _cpuset, hwloc_nodeset_t nodeset)
|
|
||||||
{
|
|
||||||
hwloc_cpuset_to_nodeset(topology, _cpuset, nodeset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Convert a NUMA node set into a CPU set and handle non-NUMA cases
|
|
||||||
*/
|
|
||||||
static __hwloc_inline void
|
|
||||||
hwloc_cpuset_from_nodeset_strict(hwloc_topology_t topology, hwloc_cpuset_t _cpuset, hwloc_const_nodeset_t nodeset) __hwloc_attribute_deprecated;
|
|
||||||
static __hwloc_inline void
|
|
||||||
hwloc_cpuset_from_nodeset_strict(hwloc_topology_t topology, hwloc_cpuset_t _cpuset, hwloc_const_nodeset_t nodeset)
|
|
||||||
{
|
|
||||||
hwloc_cpuset_from_nodeset(topology, _cpuset, nodeset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_DEPRECATED_H */
|
|
||||||
304
src/3rdparty/hwloc/include/hwloc/diff.h
vendored
304
src/3rdparty/hwloc/include/hwloc/diff.h
vendored
@@ -1,304 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2013-2023 Inria. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Topology differences.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_DIFF_H
|
|
||||||
#define HWLOC_DIFF_H
|
|
||||||
|
|
||||||
#ifndef HWLOC_H
|
|
||||||
#error Please include the main hwloc.h instead
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#elif 0
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_diff Topology differences
|
|
||||||
*
|
|
||||||
* Applications that manipulate many similar topologies, for instance
|
|
||||||
* one for each node of a homogeneous cluster, may want to compress
|
|
||||||
* topologies to reduce the memory footprint.
|
|
||||||
*
|
|
||||||
* This file offers a way to manipulate the difference between topologies
|
|
||||||
* and export/import it to/from XML.
|
|
||||||
* Compression may therefore be achieved by storing one topology
|
|
||||||
* entirely while the others are only described by their differences
|
|
||||||
* with the former.
|
|
||||||
* The actual topology can be reconstructed when actually needed by
|
|
||||||
* applying the precomputed difference to the reference topology.
|
|
||||||
*
|
|
||||||
* This interface targets very similar nodes.
|
|
||||||
* Only very simple differences between topologies are actually
|
|
||||||
* supported, for instance a change in the memory size, the name
|
|
||||||
* of the object, or some info attribute.
|
|
||||||
* More complex differences such as adding or removing objects cannot
|
|
||||||
* be represented in the difference structures and therefore return
|
|
||||||
* errors.
|
|
||||||
* Differences between object sets or topology-wide allowed sets,
|
|
||||||
* cannot be represented either.
|
|
||||||
*
|
|
||||||
* It means that there is no need to apply the difference when
|
|
||||||
* looking at the tree organization (how many levels, how many
|
|
||||||
* objects per level, what kind of objects, CPU and node sets, etc)
|
|
||||||
* and when binding to objects.
|
|
||||||
* However the difference must be applied when looking at object
|
|
||||||
* attributes such as the name, the memory size or info attributes.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Type of one object attribute difference.
|
|
||||||
*/
|
|
||||||
typedef enum hwloc_topology_diff_obj_attr_type_e {
|
|
||||||
/** \brief The object local memory is modified.
|
|
||||||
* The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_uint64_s
|
|
||||||
* (and the index field is ignored).
|
|
||||||
*/
|
|
||||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE,
|
|
||||||
|
|
||||||
/** \brief The object name is modified.
|
|
||||||
* The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_string_s
|
|
||||||
* (and the name field is ignored).
|
|
||||||
*/
|
|
||||||
|
|
||||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME,
|
|
||||||
/** \brief the value of an info attribute is modified.
|
|
||||||
* The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_string_s.
|
|
||||||
*/
|
|
||||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO
|
|
||||||
} hwloc_topology_diff_obj_attr_type_t;
|
|
||||||
|
|
||||||
/** \brief One object attribute difference.
|
|
||||||
*/
|
|
||||||
union hwloc_topology_diff_obj_attr_u {
|
|
||||||
struct hwloc_topology_diff_obj_attr_generic_s {
|
|
||||||
/* each part of the union must start with these */
|
|
||||||
hwloc_topology_diff_obj_attr_type_t type;
|
|
||||||
} generic;
|
|
||||||
|
|
||||||
/** \brief Integer attribute modification with an optional index. */
|
|
||||||
struct hwloc_topology_diff_obj_attr_uint64_s {
|
|
||||||
/* used for storing integer attributes */
|
|
||||||
hwloc_topology_diff_obj_attr_type_t type;
|
|
||||||
hwloc_uint64_t index; /* not used for SIZE */
|
|
||||||
hwloc_uint64_t oldvalue;
|
|
||||||
hwloc_uint64_t newvalue;
|
|
||||||
} uint64;
|
|
||||||
|
|
||||||
/** \brief String attribute modification with an optional name */
|
|
||||||
struct hwloc_topology_diff_obj_attr_string_s {
|
|
||||||
/* used for storing name and info pairs */
|
|
||||||
hwloc_topology_diff_obj_attr_type_t type;
|
|
||||||
char *name; /* not used for NAME */
|
|
||||||
char *oldvalue;
|
|
||||||
char *newvalue;
|
|
||||||
} string;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Type of one element of a difference list.
|
|
||||||
*/
|
|
||||||
typedef enum hwloc_topology_diff_type_e {
|
|
||||||
/** \brief An object attribute was changed.
|
|
||||||
* The union is a hwloc_topology_diff_u::hwloc_topology_diff_obj_attr_s.
|
|
||||||
*/
|
|
||||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR,
|
|
||||||
|
|
||||||
/** \brief The difference is too complex,
|
|
||||||
* it cannot be represented. The difference below
|
|
||||||
* this object has not been checked.
|
|
||||||
* hwloc_topology_diff_build() will return 1.
|
|
||||||
*
|
|
||||||
* The union is a hwloc_topology_diff_u::hwloc_topology_diff_too_complex_s.
|
|
||||||
*/
|
|
||||||
HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX
|
|
||||||
} hwloc_topology_diff_type_t;
|
|
||||||
|
|
||||||
/** \brief One element of a difference list between two topologies.
|
|
||||||
*/
|
|
||||||
typedef union hwloc_topology_diff_u {
|
|
||||||
struct hwloc_topology_diff_generic_s {
|
|
||||||
/* each part of the union must start with these */
|
|
||||||
hwloc_topology_diff_type_t type;
|
|
||||||
union hwloc_topology_diff_u * next; /* pointer to the next element of the list, or NULL */
|
|
||||||
} generic;
|
|
||||||
|
|
||||||
/* A difference in an object attribute. */
|
|
||||||
struct hwloc_topology_diff_obj_attr_s {
|
|
||||||
hwloc_topology_diff_type_t type; /* must be ::HWLOC_TOPOLOGY_DIFF_OBJ_ATTR */
|
|
||||||
union hwloc_topology_diff_u * next;
|
|
||||||
/* List of attribute differences for a single object */
|
|
||||||
int obj_depth;
|
|
||||||
unsigned obj_index;
|
|
||||||
union hwloc_topology_diff_obj_attr_u diff;
|
|
||||||
} obj_attr;
|
|
||||||
|
|
||||||
/* A difference that is too complex. */
|
|
||||||
struct hwloc_topology_diff_too_complex_s {
|
|
||||||
hwloc_topology_diff_type_t type; /* must be ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX */
|
|
||||||
union hwloc_topology_diff_u * next;
|
|
||||||
/* Where we had to stop computing the diff in the first topology */
|
|
||||||
int obj_depth;
|
|
||||||
unsigned obj_index;
|
|
||||||
} too_complex;
|
|
||||||
} * hwloc_topology_diff_t;
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Compute the difference between 2 topologies.
|
|
||||||
*
|
|
||||||
* The difference is stored as a list of ::hwloc_topology_diff_t entries
|
|
||||||
* starting at \p diff.
|
|
||||||
* It is computed by doing a depth-first traversal of both topology trees
|
|
||||||
* simultaneously.
|
|
||||||
*
|
|
||||||
* If the difference between 2 objects is too complex to be represented
|
|
||||||
* (for instance if some objects have different types, or different numbers
|
|
||||||
* of children), a special diff entry of type ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX
|
|
||||||
* is queued.
|
|
||||||
* The computation of the diff does not continue below these objects.
|
|
||||||
* So each such diff entry means that the difference between two subtrees
|
|
||||||
* could not be computed.
|
|
||||||
*
|
|
||||||
* \return 0 if the difference can be represented properly.
|
|
||||||
*
|
|
||||||
* \return 0 with \p diff pointing to NULL if there is no difference
|
|
||||||
* between the topologies.
|
|
||||||
*
|
|
||||||
* \return 1 if the difference is too complex (see above). Some entries in
|
|
||||||
* the list will be of type ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX.
|
|
||||||
*
|
|
||||||
* \return -1 on any other error.
|
|
||||||
*
|
|
||||||
* \note \p flags is currently not used. It should be 0.
|
|
||||||
*
|
|
||||||
* \note The output diff has to be freed with hwloc_topology_diff_destroy().
|
|
||||||
*
|
|
||||||
* \note The output diff can only be exported to XML or passed to
|
|
||||||
* hwloc_topology_diff_apply() if 0 was returned, i.e. if no entry of type
|
|
||||||
* ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX is listed.
|
|
||||||
*
|
|
||||||
* \note The output diff may be modified by removing some entries from
|
|
||||||
* the list. The removed entries should be freed by passing them to
|
|
||||||
* to hwloc_topology_diff_destroy() (possible as another list).
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_topology_diff_build(hwloc_topology_t topology, hwloc_topology_t newtopology, unsigned long flags, hwloc_topology_diff_t *diff);
|
|
||||||
|
|
||||||
/** \brief Flags to be given to hwloc_topology_diff_apply().
|
|
||||||
*/
|
|
||||||
enum hwloc_topology_diff_apply_flags_e {
|
|
||||||
/** \brief Apply topology diff in reverse direction.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE = (1UL<<0)
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Apply a topology diff to an existing topology.
|
|
||||||
*
|
|
||||||
* \p flags is an OR'ed set of ::hwloc_topology_diff_apply_flags_e.
|
|
||||||
*
|
|
||||||
* The new topology is modified in place. hwloc_topology_dup()
|
|
||||||
* may be used to duplicate it before patching.
|
|
||||||
*
|
|
||||||
* If the difference cannot be applied entirely, all previous applied
|
|
||||||
* elements are unapplied before returning.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
*
|
|
||||||
* \return -N if applying the difference failed while trying
|
|
||||||
* to apply the N-th part of the difference. For instance -1
|
|
||||||
* is returned if the very first difference element could not
|
|
||||||
* be applied.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_topology_diff_apply(hwloc_topology_t topology, hwloc_topology_diff_t diff, unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Destroy a list of topology differences.
|
|
||||||
*
|
|
||||||
* \return 0.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_topology_diff_destroy(hwloc_topology_diff_t diff);
|
|
||||||
|
|
||||||
/** \brief Load a list of topology differences from a XML file.
|
|
||||||
*
|
|
||||||
* If not \c NULL, \p refname will be filled with the identifier
|
|
||||||
* string of the reference topology for the difference file,
|
|
||||||
* if any was specified in the XML file.
|
|
||||||
* This identifier is usually the name of the other XML file
|
|
||||||
* that contains the reference topology.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*
|
|
||||||
* \note the pointer returned in refname should later be freed
|
|
||||||
* by the caller.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_topology_diff_load_xml(const char *xmlpath, hwloc_topology_diff_t *diff, char **refname);
|
|
||||||
|
|
||||||
/** \brief Export a list of topology differences to a XML file.
|
|
||||||
*
|
|
||||||
* If not \c NULL, \p refname defines an identifier string
|
|
||||||
* for the reference topology which was used as a base when
|
|
||||||
* computing this difference.
|
|
||||||
* This identifier is usually the name of the other XML file
|
|
||||||
* that contains the reference topology.
|
|
||||||
* This attribute is given back when reading the diff from XML.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_topology_diff_export_xml(hwloc_topology_diff_t diff, const char *refname, const char *xmlpath);
|
|
||||||
|
|
||||||
/** \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).
|
|
||||||
* This buffer may have been filled earlier with
|
|
||||||
* hwloc_topology_diff_export_xmlbuffer().
|
|
||||||
*
|
|
||||||
* If not \c NULL, \p refname will be filled with the identifier
|
|
||||||
* string of the reference topology for the difference file,
|
|
||||||
* if any was specified in the XML file.
|
|
||||||
* This identifier is usually the name of the other XML file
|
|
||||||
* that contains the reference topology.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*
|
|
||||||
* \note the pointer returned in refname should later be freed
|
|
||||||
* by the caller.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_topology_diff_load_xmlbuffer(const char *xmlbuffer, int buflen, hwloc_topology_diff_t *diff, char **refname);
|
|
||||||
|
|
||||||
/** \brief Export a list of topology differences to a XML buffer.
|
|
||||||
*
|
|
||||||
* If not \c NULL, \p refname defines an identifier string
|
|
||||||
* for the reference topology which was used as a base when
|
|
||||||
* computing this difference.
|
|
||||||
* This identifier is usually the name of the other XML file
|
|
||||||
* 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
|
|
||||||
* length.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*
|
|
||||||
* \note The XML buffer should later be freed with hwloc_free_xmlbuffer().
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_topology_diff_export_xmlbuffer(hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_DIFF_H */
|
|
||||||
499
src/3rdparty/hwloc/include/hwloc/distances.h
vendored
499
src/3rdparty/hwloc/include/hwloc/distances.h
vendored
@@ -1,499 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2010-2024 Inria. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Object distances.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_DISTANCES_H
|
|
||||||
#define HWLOC_DISTANCES_H
|
|
||||||
|
|
||||||
#ifndef HWLOC_H
|
|
||||||
#error Please include the main hwloc.h instead
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#elif 0
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_distances_get Retrieve distances between objects
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Matrix of distances between a set of objects.
|
|
||||||
*
|
|
||||||
* The most common matrix contains latencies between NUMA nodes
|
|
||||||
* (as reported in the System Locality Distance Information Table (SLIT)
|
|
||||||
* in the ACPI specification), which may or may not be physically accurate.
|
|
||||||
* It corresponds to the latency for accessing the memory of one node
|
|
||||||
* from a core in another node.
|
|
||||||
* The corresponding kind is ::HWLOC_DISTANCES_KIND_MEANS_LATENCY | ::HWLOC_DISTANCES_KIND_FROM_USER.
|
|
||||||
* The name of this distances structure is "NUMALatency".
|
|
||||||
*
|
|
||||||
* The matrix may also contain bandwidths between random sets of objects,
|
|
||||||
* possibly provided by the user, as specified in the \p kind attribute.
|
|
||||||
* Others common distance structures include and "XGMIBandwidth", "XGMIHops",
|
|
||||||
* "XeLinkBandwidth" and "NVLinkBandwidth".
|
|
||||||
*
|
|
||||||
* Pointers \p objs and \p values should not be replaced, reallocated, freed, etc.
|
|
||||||
* However callers are allowed to modify \p kind as well as the contents
|
|
||||||
* of \p objs and \p values arrays.
|
|
||||||
* For instance, if there is a single NUMA node per Package,
|
|
||||||
* hwloc_get_obj_with_same_locality() may be used to convert between them
|
|
||||||
* and replace NUMA nodes in the \p objs array with the corresponding Packages.
|
|
||||||
* See also hwloc_distances_transform() for applying some transformations
|
|
||||||
* to the structure.
|
|
||||||
*/
|
|
||||||
struct hwloc_distances_s {
|
|
||||||
unsigned nbobjs; /**< \brief Number of objects described by the distance matrix. */
|
|
||||||
hwloc_obj_t *objs; /**< \brief Array of objects described by the distance matrix.
|
|
||||||
* These objects are not in any particular order,
|
|
||||||
* see hwloc_distances_obj_index() and hwloc_distances_obj_pair_values()
|
|
||||||
* for easy ways to find objects in this array and their corresponding values.
|
|
||||||
*/
|
|
||||||
unsigned long kind; /**< \brief OR'ed set of ::hwloc_distances_kind_e. */
|
|
||||||
hwloc_uint64_t *values; /**< \brief Matrix of distances between objects, stored as a one-dimension array.
|
|
||||||
*
|
|
||||||
* Distance from i-th to j-th object is stored in slot i*nbobjs+j.
|
|
||||||
* The meaning of the value depends on the \p kind attribute.
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Kinds of distance matrices.
|
|
||||||
*
|
|
||||||
* The \p kind attribute of struct hwloc_distances_s is a OR'ed set
|
|
||||||
* of kinds.
|
|
||||||
*
|
|
||||||
* Each distance matrix may have only one kind among HWLOC_DISTANCES_KIND_FROM_*
|
|
||||||
* specifying where distance information comes from,
|
|
||||||
* and one kind among HWLOC_DISTANCES_KIND_MEANS_* specifying
|
|
||||||
* whether values are latencies or bandwidths.
|
|
||||||
*/
|
|
||||||
enum hwloc_distances_kind_e {
|
|
||||||
/** \brief These distances were obtained from the operating system or hardware.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_DISTANCES_KIND_FROM_OS = (1UL<<0),
|
|
||||||
/** \brief These distances were provided by the user.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_DISTANCES_KIND_FROM_USER = (1UL<<1),
|
|
||||||
|
|
||||||
/** \brief Distance values are similar to latencies between objects.
|
|
||||||
* Values are smaller for closer objects, hence minimal on the diagonal
|
|
||||||
* of the matrix (distance between an object and itself).
|
|
||||||
* It could also be the number of network hops between objects, etc.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY = (1UL<<2),
|
|
||||||
/** \brief Distance values are similar to bandwidths between objects.
|
|
||||||
* Values are higher for closer objects, hence maximal on the diagonal
|
|
||||||
* of the matrix (distance between an object and itself).
|
|
||||||
* Such values are currently ignored for distance-based grouping.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH = (1UL<<3),
|
|
||||||
|
|
||||||
/** \brief This distances structure covers objects of different types.
|
|
||||||
* This may apply to the "NVLinkBandwidth" structure in presence
|
|
||||||
* of a NVSwitch or POWER processor NVLink port.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES = (1UL<<4)
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Retrieve distance matrices.
|
|
||||||
*
|
|
||||||
* Retrieve distance matrices from the topology into the \p distances array.
|
|
||||||
*
|
|
||||||
* \p flags is currently unused, should be \c 0.
|
|
||||||
*
|
|
||||||
* \p kind serves as a filter. If \c 0, all distance matrices are returned.
|
|
||||||
* If it contains some HWLOC_DISTANCES_KIND_FROM_*, only distance matrices
|
|
||||||
* whose kind matches one of these are returned.
|
|
||||||
* If it contains some HWLOC_DISTANCES_KIND_MEANS_*, only distance matrices
|
|
||||||
* whose kind matches one of these are returned.
|
|
||||||
*
|
|
||||||
* On input, \p nr points to the number of distance matrices that may be stored
|
|
||||||
* in \p distances.
|
|
||||||
* On output, \p nr points to the number of distance matrices that were actually
|
|
||||||
* found, even if some of them couldn't be stored in \p distances.
|
|
||||||
* Distance matrices that couldn't be stored are ignored, but the function still
|
|
||||||
* returns success (\c 0). The caller may find out by comparing the value pointed
|
|
||||||
* by \p nr before and after the function call.
|
|
||||||
*
|
|
||||||
* Each distance matrix returned in the \p distances array should be released
|
|
||||||
* by the caller using hwloc_distances_release().
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_distances_get(hwloc_topology_t topology,
|
|
||||||
unsigned *nr, struct hwloc_distances_s **distances,
|
|
||||||
unsigned long kind, unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Retrieve distance matrices for object at a specific depth in the topology.
|
|
||||||
*
|
|
||||||
* Identical to hwloc_distances_get() with the additional \p depth filter.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_distances_get_by_depth(hwloc_topology_t topology, int depth,
|
|
||||||
unsigned *nr, struct hwloc_distances_s **distances,
|
|
||||||
unsigned long kind, unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Retrieve distance matrices for object of a specific type.
|
|
||||||
*
|
|
||||||
* Identical to hwloc_distances_get() with the additional \p type filter.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_distances_get_by_type(hwloc_topology_t topology, hwloc_obj_type_t type,
|
|
||||||
unsigned *nr, struct hwloc_distances_s **distances,
|
|
||||||
unsigned long kind, unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Retrieve a distance matrix with the given name.
|
|
||||||
*
|
|
||||||
* Usually only one distances structure may match a given name.
|
|
||||||
*
|
|
||||||
* The name of the most common structure is "NUMALatency".
|
|
||||||
* Others include "XGMIBandwidth", "XGMIHops", "XeLinkBandwidth",
|
|
||||||
* and "NVLinkBandwidth".
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_distances_get_by_name(hwloc_topology_t topology, const char *name,
|
|
||||||
unsigned *nr, struct hwloc_distances_s **distances,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Get a description of what a distances structure contains.
|
|
||||||
*
|
|
||||||
* For instance "NUMALatency" for hardware-provided NUMA distances (ACPI SLIT),
|
|
||||||
* or \c NULL if unknown.
|
|
||||||
*
|
|
||||||
* \return the constant string with the name of the distance structure.
|
|
||||||
*
|
|
||||||
* \note The returned name should not be freed by the caller,
|
|
||||||
* it belongs to the hwloc library.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC const char *
|
|
||||||
hwloc_distances_get_name(hwloc_topology_t topology, struct hwloc_distances_s *distances);
|
|
||||||
|
|
||||||
/** \brief Release a distance matrix structure previously returned by hwloc_distances_get().
|
|
||||||
*
|
|
||||||
* \note This function is not required if the structure is removed with hwloc_distances_release_remove().
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC void
|
|
||||||
hwloc_distances_release(hwloc_topology_t topology, struct hwloc_distances_s *distances);
|
|
||||||
|
|
||||||
/** \brief Transformations of distances structures. */
|
|
||||||
enum hwloc_distances_transform_e {
|
|
||||||
/** \brief Remove \c NULL objects from the distances structure.
|
|
||||||
*
|
|
||||||
* Every object that was replaced with \c NULL in the \p objs array
|
|
||||||
* is removed and the \p values array is updated accordingly.
|
|
||||||
*
|
|
||||||
* At least \c 2 objects must remain, otherwise hwloc_distances_transform()
|
|
||||||
* will return \c -1 with \p errno set to \c EINVAL.
|
|
||||||
*
|
|
||||||
* \p kind will be updated with or without ::HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES
|
|
||||||
* according to the remaining objects.
|
|
||||||
*
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL = 0,
|
|
||||||
|
|
||||||
/** \brief Replace bandwidth values with a number of links.
|
|
||||||
*
|
|
||||||
* Usually all values will be either \c 0 (no link) or \c 1 (one link).
|
|
||||||
* However some matrices could get larger values if some pairs of
|
|
||||||
* peers are connected by different numbers of links.
|
|
||||||
*
|
|
||||||
* Values on the diagonal are set to \c 0.
|
|
||||||
*
|
|
||||||
* This transformation only applies to bandwidth matrices.
|
|
||||||
*
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
* \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.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Apply a transformation to a distances structure.
|
|
||||||
*
|
|
||||||
* Modify a distances structure that was previously obtained with
|
|
||||||
* hwloc_distances_get() or one of its variants.
|
|
||||||
*
|
|
||||||
* This modifies the local copy of the distances structures but does
|
|
||||||
* not modify the distances information stored inside the topology
|
|
||||||
* (retrieved by another call to hwloc_distances_get() or exported to XML).
|
|
||||||
* To do so, one should add a new distances structure with same
|
|
||||||
* name, kind, objects and values (see \ref hwlocality_distances_add)
|
|
||||||
* and then remove this old one with hwloc_distances_release_remove().
|
|
||||||
*
|
|
||||||
* \p transform must be one of the transformations listed
|
|
||||||
* in ::hwloc_distances_transform_e.
|
|
||||||
*
|
|
||||||
* These transformations may modify the contents of the \p objs or \p values arrays.
|
|
||||||
*
|
|
||||||
* \p transform_attr must be \c NULL for now.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error for instance if flags are invalid.
|
|
||||||
*
|
|
||||||
* \note Objects in distances array \p objs may be directly modified
|
|
||||||
* in place without using hwloc_distances_transform().
|
|
||||||
* One may use hwloc_get_obj_with_same_locality() to easily convert
|
|
||||||
* between similar objects of different types.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_distances_transform(hwloc_topology_t topology, struct hwloc_distances_s *distances,
|
|
||||||
enum hwloc_distances_transform_e transform,
|
|
||||||
void *transform_attr,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_distances_consult Helpers for consulting distance matrices
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Find the index of an object in a distances structure.
|
|
||||||
*
|
|
||||||
* \return the index of the object in the distances structure if any.
|
|
||||||
* \return -1 if object \p obj is not involved in structure \p distances.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_distances_obj_index(struct hwloc_distances_s *distances, hwloc_obj_t obj)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
for(i=0; i<distances->nbobjs; i++)
|
|
||||||
if (distances->objs[i] == obj)
|
|
||||||
return (int)i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Find the values between two objects in a distance matrices.
|
|
||||||
*
|
|
||||||
* The distance from \p obj1 to \p obj2 is stored in the value pointed by
|
|
||||||
* \p value1to2 and reciprocally.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 if object \p obj1 or \p obj2 is not involved in structure \p distances.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_distances_obj_pair_values(struct hwloc_distances_s *distances,
|
|
||||||
hwloc_obj_t obj1, hwloc_obj_t obj2,
|
|
||||||
hwloc_uint64_t *value1to2, hwloc_uint64_t *value2to1)
|
|
||||||
{
|
|
||||||
int i1 = hwloc_distances_obj_index(distances, obj1);
|
|
||||||
int i2 = hwloc_distances_obj_index(distances, obj2);
|
|
||||||
if (i1 < 0 || i2 < 0)
|
|
||||||
return -1;
|
|
||||||
*value1to2 = distances->values[i1 * distances->nbobjs + i2];
|
|
||||||
*value2to1 = distances->values[i2 * distances->nbobjs + i1];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_distances_add Add distances between objects
|
|
||||||
*
|
|
||||||
* The usual way to add distances is:
|
|
||||||
* \code
|
|
||||||
* hwloc_distances_add_handle_t handle;
|
|
||||||
* int err = -1;
|
|
||||||
* handle = hwloc_distances_add_create(topology, "name", kind, 0);
|
|
||||||
* if (handle) {
|
|
||||||
* err = hwloc_distances_add_values(topology, handle, nbobjs, objs, values, 0);
|
|
||||||
* if (!err)
|
|
||||||
* err = hwloc_distances_add_commit(topology, handle, flags);
|
|
||||||
* }
|
|
||||||
* \endcode
|
|
||||||
* If \p err is \c 0 at the end, then addition was successful.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Handle to a new distances structure during its addition to the topology. */
|
|
||||||
typedef void * hwloc_distances_add_handle_t;
|
|
||||||
|
|
||||||
/** \brief Create a new empty distances structure.
|
|
||||||
*
|
|
||||||
* Create an empty distances structure
|
|
||||||
* to be filled with hwloc_distances_add_values()
|
|
||||||
* and then committed with hwloc_distances_add_commit().
|
|
||||||
*
|
|
||||||
* Parameter \p name is optional, it may be \c NULL.
|
|
||||||
* Otherwise, it will be copied internally and may later be freed by the caller.
|
|
||||||
*
|
|
||||||
* \p kind specifies the kind of distance as a OR'ed set of ::hwloc_distances_kind_e.
|
|
||||||
* Only one kind of meaning and one kind of provenance may be given if appropriate
|
|
||||||
* (e.g. ::HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH and ::HWLOC_DISTANCES_KIND_FROM_USER).
|
|
||||||
* Kind ::HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES will be automatically set
|
|
||||||
* according to objects having different types in hwloc_distances_add_values().
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \return A hwloc_distances_add_handle_t that should then be passed
|
|
||||||
* to hwloc_distances_add_values() and hwloc_distances_add_commit().
|
|
||||||
*
|
|
||||||
* \return \c NULL on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC hwloc_distances_add_handle_t
|
|
||||||
hwloc_distances_add_create(hwloc_topology_t topology,
|
|
||||||
const char *name, unsigned long kind,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Specify the objects and values in a new empty distances structure.
|
|
||||||
*
|
|
||||||
* Specify the objects and values for a new distances structure
|
|
||||||
* that was returned as a handle by hwloc_distances_add_create().
|
|
||||||
* The structure must then be committed with hwloc_distances_add_commit().
|
|
||||||
*
|
|
||||||
* The number of objects is \p nbobjs and the array of objects is \p objs.
|
|
||||||
* Distance values are stored as a one-dimension array in \p values.
|
|
||||||
* The distance from object i to object j is in slot i*nbobjs+j.
|
|
||||||
*
|
|
||||||
* \p nbobjs must be at least 2.
|
|
||||||
*
|
|
||||||
* Arrays \p objs and \p values will be copied internally,
|
|
||||||
* they may later be freed by the caller.
|
|
||||||
*
|
|
||||||
* On error, the temporary distances structure and its content are destroyed.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_distances_add_values(hwloc_topology_t topology,
|
|
||||||
hwloc_distances_add_handle_t handle,
|
|
||||||
unsigned nbobjs, hwloc_obj_t *objs,
|
|
||||||
hwloc_uint64_t *values,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Flags for adding a new distances to a topology. */
|
|
||||||
enum hwloc_distances_add_flag_e {
|
|
||||||
/** \brief Try to group objects based on the newly provided distance information.
|
|
||||||
* Grouping is only performed when the distances structure contains latencies,
|
|
||||||
* and when all objects are of the same type.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_DISTANCES_ADD_FLAG_GROUP = (1UL<<0),
|
|
||||||
/** \brief If grouping, consider the distance values as inaccurate and relax the
|
|
||||||
* comparisons during the grouping algorithms. The actual accuracy may be modified
|
|
||||||
* through the HWLOC_GROUPING_ACCURACY environment variable (see \ref envvar).
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE = (1UL<<1)
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Commit a new distances structure.
|
|
||||||
*
|
|
||||||
* This function finalizes the distances structure and inserts in it the topology.
|
|
||||||
*
|
|
||||||
* Parameter \p handle was previously returned by hwloc_distances_add_create().
|
|
||||||
* Then objects and values were specified with hwloc_distances_add_values().
|
|
||||||
*
|
|
||||||
* \p flags configures the behavior of the function using an optional OR'ed set of
|
|
||||||
* ::hwloc_distances_add_flag_e.
|
|
||||||
* It may be used to request the grouping of existing objects based on distances.
|
|
||||||
*
|
|
||||||
* On error, the temporary distances structure and its content are destroyed.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_distances_add_commit(hwloc_topology_t topology,
|
|
||||||
hwloc_distances_add_handle_t handle,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_distances_remove Remove distances between objects
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Remove all distance matrices from a topology.
|
|
||||||
*
|
|
||||||
* Remove all distance matrices, either provided by the user or
|
|
||||||
* gathered through the OS.
|
|
||||||
*
|
|
||||||
* If these distances were used to group objects, these additional
|
|
||||||
* Group objects are not removed from the topology.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_distances_remove(hwloc_topology_t topology);
|
|
||||||
|
|
||||||
/** \brief Remove distance matrices for objects at a specific depth in the topology.
|
|
||||||
*
|
|
||||||
* Identical to hwloc_distances_remove() but only applies to one level of the topology.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_distances_remove_by_depth(hwloc_topology_t topology, int depth);
|
|
||||||
|
|
||||||
/** \brief Remove distance matrices for objects of a specific type in the topology.
|
|
||||||
*
|
|
||||||
* Identical to hwloc_distances_remove() but only applies to one level of the topology.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_distances_remove_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, type);
|
|
||||||
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
|
|
||||||
return 0;
|
|
||||||
return hwloc_distances_remove_by_depth(topology, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Release and remove the given distance matrice from the topology.
|
|
||||||
*
|
|
||||||
* This function includes a call to hwloc_distances_release().
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_distances_release_remove(hwloc_topology_t topology, struct hwloc_distances_s *distances);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_DISTANCES_H */
|
|
||||||
286
src/3rdparty/hwloc/include/hwloc/export.h
vendored
286
src/3rdparty/hwloc/include/hwloc/export.h
vendored
@@ -1,286 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2009-2018 Inria. All rights reserved.
|
|
||||||
* Copyright © 2009-2012 Université Bordeaux
|
|
||||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Exporting Topologies to XML or to Synthetic strings.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_EXPORT_H
|
|
||||||
#define HWLOC_EXPORT_H
|
|
||||||
|
|
||||||
#ifndef HWLOC_H
|
|
||||||
#error Please include the main hwloc.h instead
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#elif 0
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_xmlexport Exporting Topologies to XML
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Flags for exporting XML topologies.
|
|
||||||
*
|
|
||||||
* Flags to be given as a OR'ed set to hwloc_topology_export_xml().
|
|
||||||
*/
|
|
||||||
enum hwloc_topology_export_xml_flags_e {
|
|
||||||
/** \brief Export XML that is loadable by hwloc v1.x.
|
|
||||||
* However, the export may miss some details about the topology.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1 = (1UL<<0)
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Export the topology into an XML file.
|
|
||||||
*
|
|
||||||
* This file may be loaded later through hwloc_topology_set_xml().
|
|
||||||
*
|
|
||||||
* By default, the latest export format is used, which means older hwloc
|
|
||||||
* releases (e.g. v1.x) will not be able to import it.
|
|
||||||
* Exporting to v1.x specific XML format is possible using flag
|
|
||||||
* ::HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1 but it may miss some details
|
|
||||||
* about the topology.
|
|
||||||
* If there is any chance that the exported file may ever be imported
|
|
||||||
* back by a process using hwloc 1.x, one should consider detecting
|
|
||||||
* it at runtime and using the corresponding export format.
|
|
||||||
*
|
|
||||||
* \p flags is a OR'ed set of ::hwloc_topology_export_xml_flags_e.
|
|
||||||
*
|
|
||||||
* \return 0 on success, or -1 on error.
|
|
||||||
*
|
|
||||||
* \note See also hwloc_topology_set_userdata_export_callback()
|
|
||||||
* for exporting application-specific object userdata.
|
|
||||||
*
|
|
||||||
* \note The topology-specific userdata pointer is ignored when exporting to XML.
|
|
||||||
*
|
|
||||||
* \note Only printable characters may be exported to XML string attributes.
|
|
||||||
* Any other character, especially any non-ASCII character, will be silently
|
|
||||||
* dropped.
|
|
||||||
*
|
|
||||||
* \note If \p name is "-", the XML output is sent to the standard output.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_topology_export_xml(hwloc_topology_t topology, const char *xmlpath, unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Export the topology into a newly-allocated XML memory buffer.
|
|
||||||
*
|
|
||||||
* \p xmlbuffer is allocated by the callee and should be freed with
|
|
||||||
* hwloc_free_xmlbuffer() later in the caller.
|
|
||||||
*
|
|
||||||
* This memory buffer may be loaded later through hwloc_topology_set_xmlbuffer().
|
|
||||||
*
|
|
||||||
* By default, the latest export format is used, which means older hwloc
|
|
||||||
* releases (e.g. v1.x) will not be able to import it.
|
|
||||||
* Exporting to v1.x specific XML format is possible using flag
|
|
||||||
* ::HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1 but it may miss some details
|
|
||||||
* about the topology.
|
|
||||||
* If there is any chance that the exported buffer may ever be imported
|
|
||||||
* back by a process using hwloc 1.x, one should consider detecting
|
|
||||||
* it at runtime and using the corresponding export format.
|
|
||||||
*
|
|
||||||
* The returned buffer ends with a \0 that is included in the returned
|
|
||||||
* length.
|
|
||||||
*
|
|
||||||
* \p flags is a OR'ed set of ::hwloc_topology_export_xml_flags_e.
|
|
||||||
*
|
|
||||||
* \return 0 on success, or -1 on error.
|
|
||||||
*
|
|
||||||
* \note See also hwloc_topology_set_userdata_export_callback()
|
|
||||||
* for exporting application-specific object userdata.
|
|
||||||
*
|
|
||||||
* \note The topology-specific userdata pointer is ignored when exporting to XML.
|
|
||||||
*
|
|
||||||
* \note Only printable characters may be exported to XML string attributes.
|
|
||||||
* Any other character, especially any non-ASCII character, will be silently
|
|
||||||
* dropped.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen, unsigned long flags);
|
|
||||||
|
|
||||||
/** \brief Free a buffer allocated by hwloc_topology_export_xmlbuffer() */
|
|
||||||
HWLOC_DECLSPEC void hwloc_free_xmlbuffer(hwloc_topology_t topology, char *xmlbuffer);
|
|
||||||
|
|
||||||
/** \brief Set the application-specific callback for exporting object userdata
|
|
||||||
*
|
|
||||||
* The object userdata pointer is not exported to XML by default because hwloc
|
|
||||||
* does not know what it contains.
|
|
||||||
*
|
|
||||||
* This function lets applications set \p export_cb to a callback function
|
|
||||||
* that converts this opaque userdata into an exportable string.
|
|
||||||
*
|
|
||||||
* \p export_cb is invoked during XML export for each object whose
|
|
||||||
* \p userdata pointer is not \c NULL.
|
|
||||||
* The callback should use hwloc_export_obj_userdata() or
|
|
||||||
* hwloc_export_obj_userdata_base64() to actually export
|
|
||||||
* something to XML (possibly multiple times per object).
|
|
||||||
*
|
|
||||||
* \p export_cb may be set to \c NULL if userdata should not be exported to XML.
|
|
||||||
*
|
|
||||||
* \note The topology-specific userdata pointer is ignored when exporting to XML.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC void hwloc_topology_set_userdata_export_callback(hwloc_topology_t topology,
|
|
||||||
void (*export_cb)(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj));
|
|
||||||
|
|
||||||
/** \brief Export some object userdata to XML
|
|
||||||
*
|
|
||||||
* This function may only be called from within the export() callback passed
|
|
||||||
* to hwloc_topology_set_userdata_export_callback().
|
|
||||||
* It may be invoked one of multiple times to export some userdata to XML.
|
|
||||||
* The \p buffer content of length \p length is stored with optional name
|
|
||||||
* \p name.
|
|
||||||
*
|
|
||||||
* When importing this XML file, the import() callback (if set) will be
|
|
||||||
* called exactly as many times as hwloc_export_obj_userdata() was called
|
|
||||||
* during export(). It will receive the corresponding \p name, \p buffer
|
|
||||||
* and \p length arguments.
|
|
||||||
*
|
|
||||||
* \p reserved, \p topology and \p obj must be the first three parameters
|
|
||||||
* that were given to the export callback.
|
|
||||||
*
|
|
||||||
* Only printable characters may be exported to XML string attributes.
|
|
||||||
*
|
|
||||||
* If exporting binary data, the application should first encode into
|
|
||||||
* printable characters only (or use hwloc_export_obj_userdata_base64()).
|
|
||||||
* It should also take care of portability issues if the export may
|
|
||||||
* be reimported on a different architecture.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c EINVAL if a non-printable character is
|
|
||||||
* passed in \p name or \b buffer.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_export_obj_userdata(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length);
|
|
||||||
|
|
||||||
/** \brief Encode and export some object userdata to XML
|
|
||||||
*
|
|
||||||
* This function is similar to hwloc_export_obj_userdata() but it encodes
|
|
||||||
* the input buffer into printable characters before exporting.
|
|
||||||
* On import, decoding is automatically performed before the data is given
|
|
||||||
* to the import() callback if any.
|
|
||||||
*
|
|
||||||
* This function may only be called from within the export() callback passed
|
|
||||||
* to hwloc_topology_set_userdata_export_callback().
|
|
||||||
*
|
|
||||||
* The name must be made of printable characters for export to XML string attributes.
|
|
||||||
*
|
|
||||||
* The function does not take care of portability issues if the export
|
|
||||||
* may be reimported on a different architecture.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c EINVAL if a non-printable character is
|
|
||||||
* passed in \p name.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_export_obj_userdata_base64(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length);
|
|
||||||
|
|
||||||
/** \brief Set the application-specific callback for importing userdata
|
|
||||||
*
|
|
||||||
* On XML import, userdata is ignored by default because hwloc does not know
|
|
||||||
* how to store it in memory.
|
|
||||||
*
|
|
||||||
* This function lets applications set \p import_cb to a callback function
|
|
||||||
* that will get the XML-stored userdata and store it in the object as expected
|
|
||||||
* by the application.
|
|
||||||
*
|
|
||||||
* \p import_cb is called during hwloc_topology_load() as many times as
|
|
||||||
* hwloc_export_obj_userdata() was called during export. The topology
|
|
||||||
* is not entirely setup yet. Object attributes are ready to consult,
|
|
||||||
* but links between objects are not.
|
|
||||||
*
|
|
||||||
* \p import_cb may be \c NULL if userdata should be ignored during import.
|
|
||||||
*
|
|
||||||
* \note \p buffer contains \p length characters followed by a null byte ('\0').
|
|
||||||
*
|
|
||||||
* \note This function should be called before hwloc_topology_load().
|
|
||||||
*
|
|
||||||
* \note The topology-specific userdata pointer is ignored when importing from XML.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC void hwloc_topology_set_userdata_import_callback(hwloc_topology_t topology,
|
|
||||||
void (*import_cb)(hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length));
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_syntheticexport Exporting Topologies to Synthetic
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Flags for exporting synthetic topologies.
|
|
||||||
*
|
|
||||||
* Flags to be given as a OR'ed set to hwloc_topology_export_synthetic().
|
|
||||||
*/
|
|
||||||
enum hwloc_topology_export_synthetic_flags_e {
|
|
||||||
/** \brief Export extended types such as L2dcache as basic types such as Cache.
|
|
||||||
*
|
|
||||||
* This is required if loading the synthetic description with hwloc < 1.9.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES = (1UL<<0),
|
|
||||||
|
|
||||||
/** \brief Do not export level attributes.
|
|
||||||
*
|
|
||||||
* Ignore level attributes such as memory/cache sizes or PU indexes.
|
|
||||||
* This is required if loading the synthetic description with hwloc < 1.10.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS = (1UL<<1),
|
|
||||||
|
|
||||||
/** \brief Export the memory hierarchy as expected in hwloc 1.x.
|
|
||||||
*
|
|
||||||
* Instead of attaching memory children to levels, export single NUMA node child
|
|
||||||
* as normal intermediate levels, when possible.
|
|
||||||
* This is required if loading the synthetic description with hwloc 1.x.
|
|
||||||
* However this may fail if some objects have multiple local NUMA nodes.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_V1 = (1UL<<2),
|
|
||||||
|
|
||||||
/** \brief Do not export memory information.
|
|
||||||
*
|
|
||||||
* Only export the actual hierarchy of normal CPU-side objects and ignore
|
|
||||||
* where memory is attached.
|
|
||||||
* This is useful for when the hierarchy of CPUs is what really matters,
|
|
||||||
* but it behaves as if there was a single machine-wide NUMA node.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_IGNORE_MEMORY = (1UL<<3)
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Export the topology as a synthetic string.
|
|
||||||
*
|
|
||||||
* At most \p buflen characters will be written in \p buffer,
|
|
||||||
* including the terminating \0.
|
|
||||||
*
|
|
||||||
* This exported string may be given back to hwloc_topology_set_synthetic().
|
|
||||||
*
|
|
||||||
* \p flags is a OR'ed set of ::hwloc_topology_export_synthetic_flags_e.
|
|
||||||
*
|
|
||||||
* \return The number of characters that were written,
|
|
||||||
* not including the terminating \0.
|
|
||||||
*
|
|
||||||
* \return -1 if the topology could not be exported,
|
|
||||||
* for instance if it is not symmetric.
|
|
||||||
*
|
|
||||||
* \note I/O and Misc children are ignored, the synthetic string only
|
|
||||||
* describes normal children.
|
|
||||||
*
|
|
||||||
* \note A 1024-byte buffer should be large enough for exporting
|
|
||||||
* topologies in the vast majority of cases.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_topology_export_synthetic(hwloc_topology_t topology, char *buffer, size_t buflen, unsigned long flags);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_EXPORT_H */
|
|
||||||
137
src/3rdparty/hwloc/include/hwloc/gl.h
vendored
137
src/3rdparty/hwloc/include/hwloc/gl.h
vendored
@@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2012 Blue Brain Project, EPFL. All rights reserved.
|
|
||||||
* Copyright © 2012-2023 Inria. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Macros to help interaction between hwloc and OpenGL displays.
|
|
||||||
*
|
|
||||||
* Applications that use both hwloc and OpenGL may want to include
|
|
||||||
* this file so as to get topology information for OpenGL displays.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_GL_H
|
|
||||||
#define HWLOC_GL_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_gl Interoperability with OpenGL displays
|
|
||||||
*
|
|
||||||
* This interface offers ways to retrieve topology information about
|
|
||||||
* OpenGL displays.
|
|
||||||
*
|
|
||||||
* Only the NVIDIA display locality information is currently available,
|
|
||||||
* using the NV-CONTROL X11 extension and the NVCtrl library.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Get the hwloc OS device object corresponding to the
|
|
||||||
* OpenGL display given by port and device index.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object describing the OpenGL display
|
|
||||||
* whose port (server) is \p port and device (screen) is \p device.
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* The topology \p topology does not necessarily have to match the current
|
|
||||||
* machine. For instance the topology may be an XML import of a remote host.
|
|
||||||
* I/O devices detection and the GL component must be enabled in the topology.
|
|
||||||
*
|
|
||||||
* \note The corresponding PCI device object can be obtained by looking
|
|
||||||
* at the OS device parent object (unless PCI devices are filtered out).
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_gl_get_display_osdev_by_port_device(hwloc_topology_t topology,
|
|
||||||
unsigned port, unsigned device)
|
|
||||||
{
|
|
||||||
unsigned x = (unsigned) -1, y = (unsigned) -1;
|
|
||||||
hwloc_obj_t osdev = NULL;
|
|
||||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
|
||||||
if (HWLOC_OBJ_OSDEV_GPU == osdev->attr->osdev.type
|
|
||||||
&& osdev->name
|
|
||||||
&& sscanf(osdev->name, ":%u.%u", &x, &y) == 2
|
|
||||||
&& port == x && device == y)
|
|
||||||
return osdev;
|
|
||||||
}
|
|
||||||
errno = EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the hwloc OS device object corresponding to the
|
|
||||||
* OpenGL display given by name.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object describing the OpenGL display
|
|
||||||
* whose name is \p name, built as ":port.device" such as ":0.0" .
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* The topology \p topology does not necessarily have to match the current
|
|
||||||
* machine. For instance the topology may be an XML import of a remote host.
|
|
||||||
* I/O devices detection and the GL component must be enabled in the topology.
|
|
||||||
*
|
|
||||||
* \note The corresponding PCI device object can be obtained by looking
|
|
||||||
* at the OS device parent object (unless PCI devices are filtered out).
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_gl_get_display_osdev_by_name(hwloc_topology_t topology,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
hwloc_obj_t osdev = NULL;
|
|
||||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
|
||||||
if (HWLOC_OBJ_OSDEV_GPU == osdev->attr->osdev.type
|
|
||||||
&& osdev->name
|
|
||||||
&& !strcmp(name, osdev->name))
|
|
||||||
return osdev;
|
|
||||||
}
|
|
||||||
errno = EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the OpenGL display port and device corresponding
|
|
||||||
* to the given hwloc OS object.
|
|
||||||
*
|
|
||||||
* Retrieves the OpenGL display port (server) in \p port and device (screen)
|
|
||||||
* in \p screen that correspond to the given hwloc OS device object.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 if none could be found.
|
|
||||||
*
|
|
||||||
* The topology \p topology does not necessarily have to match the current
|
|
||||||
* machine. For instance the topology may be an XML import of a remote host.
|
|
||||||
* I/O devices detection and the GL component must be enabled in the topology.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_gl_get_display_by_osdev(hwloc_topology_t topology __hwloc_attribute_unused,
|
|
||||||
hwloc_obj_t osdev,
|
|
||||||
unsigned *port, unsigned *device)
|
|
||||||
{
|
|
||||||
unsigned x = -1, y = -1;
|
|
||||||
if (HWLOC_OBJ_OSDEV_GPU == osdev->attr->osdev.type
|
|
||||||
&& sscanf(osdev->name, ":%u.%u", &x, &y) == 2) {
|
|
||||||
*port = x;
|
|
||||||
*device = y;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_GL_H */
|
|
||||||
|
|
||||||
133
src/3rdparty/hwloc/include/hwloc/glibc-sched.h
vendored
133
src/3rdparty/hwloc/include/hwloc/glibc-sched.h
vendored
@@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2009 CNRS
|
|
||||||
* Copyright © 2009-2023 Inria. All rights reserved.
|
|
||||||
* Copyright © 2009-2011 Université Bordeaux
|
|
||||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Macros to help interaction between hwloc and glibc scheduling routines.
|
|
||||||
*
|
|
||||||
* Applications that use both hwloc and glibc scheduling routines such as
|
|
||||||
* sched_getaffinity() or pthread_attr_setaffinity_np() may want to include
|
|
||||||
* this file so as to ease conversion between their respective types.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_GLIBC_SCHED_H
|
|
||||||
#define HWLOC_GLIBC_SCHED_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
#include "hwloc/helper.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#if !defined _GNU_SOURCE || (!defined _SCHED_H && !defined _SCHED_H_) || (!defined CPU_SETSIZE && !defined sched_priority)
|
|
||||||
#error Please make sure to include sched.h before including glibc-sched.h, and define _GNU_SOURCE before any inclusion of sched.h
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HWLOC_HAVE_CPU_SET
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_glibc_sched Interoperability with glibc sched affinity
|
|
||||||
*
|
|
||||||
* This interface offers ways to convert between hwloc cpusets and glibc cpusets
|
|
||||||
* such as those manipulated by sched_getaffinity() or pthread_attr_setaffinity_np().
|
|
||||||
*
|
|
||||||
* \note Topology \p topology must match the current machine.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Convert hwloc CPU set \p toposet into glibc sched affinity CPU set \p schedset
|
|
||||||
*
|
|
||||||
* This function may be used before calling sched_setaffinity or any other function
|
|
||||||
* that takes a cpu_set_t as input parameter.
|
|
||||||
*
|
|
||||||
* \p schedsetsize should be sizeof(cpu_set_t) unless \p schedset was dynamically allocated with CPU_ALLOC
|
|
||||||
*
|
|
||||||
* \return 0.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_cpuset_to_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_cpuset_t hwlocset,
|
|
||||||
cpu_set_t *schedset, size_t schedsetsize)
|
|
||||||
{
|
|
||||||
#ifdef CPU_ZERO_S
|
|
||||||
unsigned cpu;
|
|
||||||
CPU_ZERO_S(schedsetsize, schedset);
|
|
||||||
hwloc_bitmap_foreach_begin(cpu, hwlocset)
|
|
||||||
CPU_SET_S(cpu, schedsetsize, schedset);
|
|
||||||
hwloc_bitmap_foreach_end();
|
|
||||||
#else /* !CPU_ZERO_S */
|
|
||||||
unsigned cpu;
|
|
||||||
CPU_ZERO(schedset);
|
|
||||||
assert(schedsetsize == sizeof(cpu_set_t));
|
|
||||||
hwloc_bitmap_foreach_begin(cpu, hwlocset)
|
|
||||||
CPU_SET(cpu, schedset);
|
|
||||||
hwloc_bitmap_foreach_end();
|
|
||||||
#endif /* !CPU_ZERO_S */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Convert glibc sched affinity CPU set \p schedset into hwloc CPU set
|
|
||||||
*
|
|
||||||
* This function may be used before calling sched_setaffinity or any other function
|
|
||||||
* that takes a cpu_set_t as input parameter.
|
|
||||||
*
|
|
||||||
* \p schedsetsize should be sizeof(cpu_set_t) unless \p schedset was dynamically allocated with CPU_ALLOC
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_cpuset_from_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_cpuset_t hwlocset,
|
|
||||||
const cpu_set_t *schedset, size_t schedsetsize)
|
|
||||||
{
|
|
||||||
int cpu;
|
|
||||||
#ifdef CPU_ZERO_S
|
|
||||||
int count;
|
|
||||||
#endif
|
|
||||||
hwloc_bitmap_zero(hwlocset);
|
|
||||||
#ifdef CPU_ZERO_S
|
|
||||||
count = CPU_COUNT_S(schedsetsize, schedset);
|
|
||||||
cpu = 0;
|
|
||||||
while (count) {
|
|
||||||
if (CPU_ISSET_S(cpu, schedsetsize, schedset)) {
|
|
||||||
if (hwloc_bitmap_set(hwlocset, cpu) < 0)
|
|
||||||
return -1;
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
cpu++;
|
|
||||||
}
|
|
||||||
#else /* !CPU_ZERO_S */
|
|
||||||
/* sched.h does not support dynamic cpu_set_t (introduced in glibc 2.7),
|
|
||||||
* assume we have a very old interface without CPU_COUNT (added in 2.6)
|
|
||||||
*/
|
|
||||||
assert(schedsetsize == sizeof(cpu_set_t));
|
|
||||||
for(cpu=0; cpu<CPU_SETSIZE; cpu++)
|
|
||||||
if (CPU_ISSET(cpu, schedset))
|
|
||||||
if (hwloc_bitmap_set(hwlocset, cpu) < 0)
|
|
||||||
return -1;
|
|
||||||
#endif /* !CPU_ZERO_S */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* CPU_SET */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_GLIBC_SCHED_H */
|
|
||||||
1331
src/3rdparty/hwloc/include/hwloc/helper.h
vendored
1331
src/3rdparty/hwloc/include/hwloc/helper.h
vendored
File diff suppressed because it is too large
Load Diff
146
src/3rdparty/hwloc/include/hwloc/inlines.h
vendored
146
src/3rdparty/hwloc/include/hwloc/inlines.h
vendored
@@ -1,146 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2009 CNRS
|
|
||||||
* Copyright © 2009-2018 Inria. All rights reserved.
|
|
||||||
* Copyright © 2009-2012 Université Bordeaux
|
|
||||||
* Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file contains the inline code of functions declared in hwloc.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_INLINES_H
|
|
||||||
#define HWLOC_INLINES_H
|
|
||||||
|
|
||||||
#ifndef HWLOC_H
|
|
||||||
#error Please include the main hwloc.h instead
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, type);
|
|
||||||
|
|
||||||
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
|
|
||||||
return depth;
|
|
||||||
|
|
||||||
/* find the highest existing level with type order >= */
|
|
||||||
for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
|
|
||||||
if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
|
|
||||||
return depth+1;
|
|
||||||
|
|
||||||
/* Shouldn't ever happen, as there is always a Machine level with lower order and known depth. */
|
|
||||||
/* abort(); */
|
|
||||||
}
|
|
||||||
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, type);
|
|
||||||
|
|
||||||
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
|
|
||||||
return depth;
|
|
||||||
|
|
||||||
/* find the lowest existing level with type order <= */
|
|
||||||
for(depth = 0; ; depth++)
|
|
||||||
if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
|
|
||||||
return depth-1;
|
|
||||||
|
|
||||||
/* Shouldn't ever happen, as there is always a PU level with higher order and known depth. */
|
|
||||||
/* abort(); */
|
|
||||||
}
|
|
||||||
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_get_nbobjs_by_type (hwloc_topology_t topology, hwloc_obj_type_t type)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, type);
|
|
||||||
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
|
|
||||||
return 0;
|
|
||||||
if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
|
|
||||||
return -1; /* FIXME: agregate nbobjs from different levels? */
|
|
||||||
return (int) hwloc_get_nbobjs_by_depth(topology, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_get_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type, unsigned idx)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, type);
|
|
||||||
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
|
|
||||||
return NULL;
|
|
||||||
if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
|
|
||||||
return NULL;
|
|
||||||
return hwloc_get_obj_by_depth(topology, depth, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_get_next_obj_by_depth (hwloc_topology_t topology, int depth, hwloc_obj_t prev)
|
|
||||||
{
|
|
||||||
if (!prev)
|
|
||||||
return hwloc_get_obj_by_depth (topology, depth, 0);
|
|
||||||
if (prev->depth != depth)
|
|
||||||
return NULL;
|
|
||||||
return prev->next_cousin;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
|
|
||||||
hwloc_obj_t prev)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, type);
|
|
||||||
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
|
|
||||||
return NULL;
|
|
||||||
return hwloc_get_next_obj_by_depth (topology, depth, prev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_get_root_obj (hwloc_topology_t topology)
|
|
||||||
{
|
|
||||||
return hwloc_get_obj_by_depth (topology, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __hwloc_inline const char *
|
|
||||||
hwloc_obj_get_info_by_name(hwloc_obj_t obj, const char *name)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
for(i=0; i<obj->infos_count; i++) {
|
|
||||||
struct hwloc_info_s *info = &obj->infos[i];
|
|
||||||
if (!strcmp(info->name, name))
|
|
||||||
return info->value;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __hwloc_inline void *
|
|
||||||
hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags)
|
|
||||||
{
|
|
||||||
void *p = hwloc_alloc_membind(topology, len, set, policy, flags);
|
|
||||||
if (p)
|
|
||||||
return p;
|
|
||||||
|
|
||||||
if (hwloc_set_membind(topology, set, policy, flags) < 0)
|
|
||||||
/* hwloc_set_membind() takes care of ignoring errors if non-STRICT */
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
p = hwloc_alloc(topology, len);
|
|
||||||
if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
|
|
||||||
/* Enforce the binding by touching the data */
|
|
||||||
memset(p, 0, len);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_INLINES_H */
|
|
||||||
161
src/3rdparty/hwloc/include/hwloc/levelzero.h
vendored
161
src/3rdparty/hwloc/include/hwloc/levelzero.h
vendored
@@ -1,161 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021-2023 Inria. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Macros to help interaction between hwloc and the oneAPI Level Zero interface.
|
|
||||||
*
|
|
||||||
* Applications that use both hwloc and Level Zero may want to
|
|
||||||
* include this file so as to get topology information for L0 devices.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_LEVELZERO_H
|
|
||||||
#define HWLOC_LEVELZERO_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
#include "hwloc/autogen/config.h"
|
|
||||||
#include "hwloc/helper.h"
|
|
||||||
#ifdef HWLOC_LINUX_SYS
|
|
||||||
#include "hwloc/linux.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <level_zero/ze_api.h>
|
|
||||||
#include <level_zero/zes_api.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \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.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Get the CPU set of logical processors that are physically
|
|
||||||
* close to the Level Zero 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).
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
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];
|
|
||||||
zes_pci_properties_t pci;
|
|
||||||
zes_device_handle_t sdevice = device;
|
|
||||||
ze_result_t res;
|
|
||||||
|
|
||||||
if (!hwloc_topology_is_thissystem(topology)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = zesDevicePciGetProperties(sdevice, &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 hwloc OS device object corresponding to Level Zero 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.
|
|
||||||
* 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 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)
|
|
||||||
{
|
|
||||||
zes_device_handle_t sdevice = device;
|
|
||||||
zes_pci_properties_t pci;
|
|
||||||
ze_result_t res;
|
|
||||||
hwloc_obj_t osdev;
|
|
||||||
|
|
||||||
if (!hwloc_topology_is_thissystem(topology)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = zesDevicePciGetProperties(sdevice, &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;
|
|
||||||
|
|
||||||
if (strncmp(osdev->name, "ze", 2))
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_LEVELZERO_H */
|
|
||||||
294
src/3rdparty/hwloc/include/hwloc/linux-libnuma.h
vendored
294
src/3rdparty/hwloc/include/hwloc/linux-libnuma.h
vendored
@@ -1,294 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2009 CNRS
|
|
||||||
* Copyright © 2009-2023 Inria. All rights reserved.
|
|
||||||
* Copyright © 2009-2010, 2012 Université Bordeaux
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Macros to help interaction between hwloc and Linux libnuma.
|
|
||||||
*
|
|
||||||
* Applications that use both Linux libnuma and hwloc may want to
|
|
||||||
* include this file so as to ease conversion between their respective types.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_LINUX_LIBNUMA_H
|
|
||||||
#define HWLOC_LINUX_LIBNUMA_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
|
|
||||||
#include <numa.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_linux_libnuma_ulongs Interoperability with Linux libnuma unsigned long masks
|
|
||||||
*
|
|
||||||
* This interface helps converting between Linux libnuma unsigned long masks
|
|
||||||
* and hwloc cpusets and nodesets.
|
|
||||||
*
|
|
||||||
* \note Topology \p topology must match the current machine.
|
|
||||||
*
|
|
||||||
* \note The behavior of libnuma is undefined if the kernel is not NUMA-aware.
|
|
||||||
* (when CONFIG_NUMA is not set in the kernel configuration).
|
|
||||||
* This helper and libnuma may thus not be strictly compatible in this case,
|
|
||||||
* which may be detected by checking whether numa_available() returns -1.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Convert hwloc CPU set \p cpuset into the array of unsigned long \p mask
|
|
||||||
*
|
|
||||||
* \p mask is the array of unsigned long that will be filled.
|
|
||||||
* \p maxnode contains the maximal node number that may be stored in \p mask.
|
|
||||||
* \p maxnode will be set to the maximal node number that was found, plus one.
|
|
||||||
*
|
|
||||||
* This function may be used before calling set_mempolicy, mbind, migrate_pages
|
|
||||||
* or any other function that takes an array of unsigned long and a maximal
|
|
||||||
* node number as input parameter.
|
|
||||||
*
|
|
||||||
* \return 0.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_cpuset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset,
|
|
||||||
unsigned long *mask, unsigned long *maxnode)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
|
||||||
unsigned long outmaxnode = -1;
|
|
||||||
hwloc_obj_t node = NULL;
|
|
||||||
|
|
||||||
/* round-up to the next ulong and clear all bytes */
|
|
||||||
*maxnode = (*maxnode + 8*sizeof(*mask) - 1) & ~(8*sizeof(*mask) - 1);
|
|
||||||
memset(mask, 0, *maxnode/8);
|
|
||||||
|
|
||||||
while ((node = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, node)) != NULL) {
|
|
||||||
if (node->os_index >= *maxnode)
|
|
||||||
continue;
|
|
||||||
mask[node->os_index/sizeof(*mask)/8] |= 1UL << (node->os_index % (sizeof(*mask)*8));
|
|
||||||
if (outmaxnode == (unsigned long) -1 || outmaxnode < node->os_index)
|
|
||||||
outmaxnode = node->os_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
*maxnode = outmaxnode+1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Convert hwloc NUMA node set \p nodeset into the array of unsigned long \p mask
|
|
||||||
*
|
|
||||||
* \p mask is the array of unsigned long that will be filled.
|
|
||||||
* \p maxnode contains the maximal node number that may be stored in \p mask.
|
|
||||||
* \p maxnode will be set to the maximal node number that was found, plus one.
|
|
||||||
*
|
|
||||||
* This function may be used before calling set_mempolicy, mbind, migrate_pages
|
|
||||||
* or any other function that takes an array of unsigned long and a maximal
|
|
||||||
* node number as input parameter.
|
|
||||||
*
|
|
||||||
* \return 0.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_nodeset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset,
|
|
||||||
unsigned long *mask, unsigned long *maxnode)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
|
||||||
unsigned long outmaxnode = -1;
|
|
||||||
hwloc_obj_t node = NULL;
|
|
||||||
|
|
||||||
/* round-up to the next ulong and clear all bytes */
|
|
||||||
*maxnode = (*maxnode + 8*sizeof(*mask) - 1) & ~(8*sizeof(*mask) - 1);
|
|
||||||
memset(mask, 0, *maxnode/8);
|
|
||||||
|
|
||||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL) {
|
|
||||||
if (node->os_index >= *maxnode)
|
|
||||||
continue;
|
|
||||||
if (!hwloc_bitmap_isset(nodeset, node->os_index))
|
|
||||||
continue;
|
|
||||||
mask[node->os_index/sizeof(*mask)/8] |= 1UL << (node->os_index % (sizeof(*mask)*8));
|
|
||||||
if (outmaxnode == (unsigned long) -1 || outmaxnode < node->os_index)
|
|
||||||
outmaxnode = node->os_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
*maxnode = outmaxnode+1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Convert the array of unsigned long \p mask into hwloc CPU set
|
|
||||||
*
|
|
||||||
* \p mask is a array of unsigned long that will be read.
|
|
||||||
* \p maxnode contains the maximal node number that may be read in \p mask.
|
|
||||||
*
|
|
||||||
* This function may be used after calling get_mempolicy or any other function
|
|
||||||
* that takes an array of unsigned long as output parameter (and possibly
|
|
||||||
* a maximal node number as input parameter).
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 on error, for instance if failing an internal reallocation.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_cpuset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_cpuset_t cpuset,
|
|
||||||
const unsigned long *mask, unsigned long maxnode)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
|
||||||
hwloc_obj_t node = NULL;
|
|
||||||
hwloc_bitmap_zero(cpuset);
|
|
||||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
|
||||||
if (node->os_index < maxnode
|
|
||||||
&& (mask[node->os_index/sizeof(*mask)/8] & (1UL << (node->os_index % (sizeof(*mask)*8)))))
|
|
||||||
if (hwloc_bitmap_or(cpuset, cpuset, node->cpuset) < 0)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Convert the array of unsigned long \p mask into hwloc NUMA node set
|
|
||||||
*
|
|
||||||
* \p mask is a array of unsigned long that will be read.
|
|
||||||
* \p maxnode contains the maximal node number that may be read in \p mask.
|
|
||||||
*
|
|
||||||
* This function may be used after calling get_mempolicy or any other function
|
|
||||||
* that takes an array of unsigned long as output parameter (and possibly
|
|
||||||
* a maximal node number as input parameter).
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_nodeset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_nodeset_t nodeset,
|
|
||||||
const unsigned long *mask, unsigned long maxnode)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
|
||||||
hwloc_obj_t node = NULL;
|
|
||||||
hwloc_bitmap_zero(nodeset);
|
|
||||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
|
||||||
if (node->os_index < maxnode
|
|
||||||
&& (mask[node->os_index/sizeof(*mask)/8] & (1UL << (node->os_index % (sizeof(*mask)*8)))))
|
|
||||||
if (hwloc_bitmap_set(nodeset, node->os_index) < 0)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_linux_libnuma_bitmask Interoperability with Linux libnuma bitmask
|
|
||||||
*
|
|
||||||
* This interface helps converting between Linux libnuma bitmasks
|
|
||||||
* and hwloc cpusets and nodesets.
|
|
||||||
*
|
|
||||||
* \note Topology \p topology must match the current machine.
|
|
||||||
*
|
|
||||||
* \note The behavior of libnuma is undefined if the kernel is not NUMA-aware.
|
|
||||||
* (when CONFIG_NUMA is not set in the kernel configuration).
|
|
||||||
* This helper and libnuma may thus not be strictly compatible in this case,
|
|
||||||
* which may be detected by checking whether numa_available() returns -1.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Convert hwloc CPU set \p cpuset into the returned libnuma bitmask
|
|
||||||
*
|
|
||||||
* The returned bitmask should later be freed with numa_bitmask_free.
|
|
||||||
*
|
|
||||||
* This function may be used before calling many numa_ functions
|
|
||||||
* that use a struct bitmask as an input parameter.
|
|
||||||
*
|
|
||||||
* \return newly allocated struct bitmask, or \c NULL on error.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline struct bitmask *
|
|
||||||
hwloc_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset) __hwloc_attribute_malloc;
|
|
||||||
static __hwloc_inline struct bitmask *
|
|
||||||
hwloc_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
|
||||||
hwloc_obj_t node = NULL;
|
|
||||||
struct bitmask *bitmask = numa_allocate_cpumask();
|
|
||||||
if (!bitmask)
|
|
||||||
return NULL;
|
|
||||||
while ((node = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, node)) != NULL)
|
|
||||||
if (node->attr->numanode.local_memory)
|
|
||||||
numa_bitmask_setbit(bitmask, node->os_index);
|
|
||||||
return bitmask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Convert hwloc NUMA node set \p nodeset into the returned libnuma bitmask
|
|
||||||
*
|
|
||||||
* The returned bitmask should later be freed with numa_bitmask_free.
|
|
||||||
*
|
|
||||||
* This function may be used before calling many numa_ functions
|
|
||||||
* that use a struct bitmask as an input parameter.
|
|
||||||
*
|
|
||||||
* \return newly allocated struct bitmask, or \c NULL on error.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline struct bitmask *
|
|
||||||
hwloc_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset) __hwloc_attribute_malloc;
|
|
||||||
static __hwloc_inline struct bitmask *
|
|
||||||
hwloc_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
|
||||||
hwloc_obj_t node = NULL;
|
|
||||||
struct bitmask *bitmask = numa_allocate_cpumask();
|
|
||||||
if (!bitmask)
|
|
||||||
return NULL;
|
|
||||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
|
||||||
if (hwloc_bitmap_isset(nodeset, node->os_index) && node->attr->numanode.local_memory)
|
|
||||||
numa_bitmask_setbit(bitmask, node->os_index);
|
|
||||||
return bitmask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Convert libnuma bitmask \p bitmask into hwloc CPU set \p cpuset
|
|
||||||
*
|
|
||||||
* This function may be used after calling many numa_ functions
|
|
||||||
* that use a struct bitmask as an output parameter.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_cpuset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_cpuset_t cpuset,
|
|
||||||
const struct bitmask *bitmask)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
|
||||||
hwloc_obj_t node = NULL;
|
|
||||||
hwloc_bitmap_zero(cpuset);
|
|
||||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
|
||||||
if (numa_bitmask_isbitset(bitmask, node->os_index))
|
|
||||||
if (hwloc_bitmap_or(cpuset, cpuset, node->cpuset) < 0)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Convert libnuma bitmask \p bitmask into hwloc NUMA node set \p nodeset
|
|
||||||
*
|
|
||||||
* This function may be used after calling many numa_ functions
|
|
||||||
* that use a struct bitmask as an output parameter.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_nodeset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_nodeset_t nodeset,
|
|
||||||
const struct bitmask *bitmask)
|
|
||||||
{
|
|
||||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
|
||||||
hwloc_obj_t node = NULL;
|
|
||||||
hwloc_bitmap_zero(nodeset);
|
|
||||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
|
||||||
if (numa_bitmask_isbitset(bitmask, node->os_index))
|
|
||||||
if (hwloc_bitmap_set(nodeset, node->os_index) < 0)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_LINUX_NUMA_H */
|
|
||||||
95
src/3rdparty/hwloc/include/hwloc/linux.h
vendored
95
src/3rdparty/hwloc/include/hwloc/linux.h
vendored
@@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2009 CNRS
|
|
||||||
* Copyright © 2009-2023 Inria. All rights reserved.
|
|
||||||
* Copyright © 2009-2011 Université Bordeaux
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Macros to help interaction between hwloc and Linux.
|
|
||||||
*
|
|
||||||
* Applications that use hwloc on Linux may want to include this file
|
|
||||||
* if using some low-level Linux features.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_LINUX_H
|
|
||||||
#define HWLOC_LINUX_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_linux Linux-specific helpers
|
|
||||||
*
|
|
||||||
* This includes helpers for manipulating Linux kernel cpumap files, and hwloc
|
|
||||||
* equivalents of the Linux sched_setaffinity and sched_getaffinity system calls.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Bind a thread \p tid on cpus given in cpuset \p set
|
|
||||||
*
|
|
||||||
* The behavior is exactly the same as the Linux sched_setaffinity system call,
|
|
||||||
* but uses a hwloc cpuset.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*
|
|
||||||
* \note This is equivalent to calling hwloc_set_proc_cpubind() with
|
|
||||||
* HWLOC_CPUBIND_THREAD as flags.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_linux_set_tid_cpubind(hwloc_topology_t topology, pid_t tid, hwloc_const_cpuset_t set);
|
|
||||||
|
|
||||||
/** \brief Get the current binding of thread \p tid
|
|
||||||
*
|
|
||||||
* The CPU-set \p set (previously allocated by the caller)
|
|
||||||
* is filled with the list of PUs which the thread
|
|
||||||
* was last bound to.
|
|
||||||
*
|
|
||||||
* The behavior is exactly the same as the Linux sched_getaffinity system call,
|
|
||||||
* but uses a hwloc cpuset.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*
|
|
||||||
* \note This is equivalent to calling hwloc_get_proc_cpubind() with
|
|
||||||
* ::HWLOC_CPUBIND_THREAD as flags.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_linux_get_tid_cpubind(hwloc_topology_t topology, pid_t tid, hwloc_cpuset_t set);
|
|
||||||
|
|
||||||
/** \brief Get the last physical CPU where thread \p tid ran.
|
|
||||||
*
|
|
||||||
* The CPU-set \p set (previously allocated by the caller)
|
|
||||||
* is filled with the PU which the thread last ran on.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*
|
|
||||||
* \note This is equivalent to calling hwloc_get_proc_last_cpu_location() with
|
|
||||||
* ::HWLOC_CPUBIND_THREAD as flags.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_linux_get_tid_last_cpu_location(hwloc_topology_t topology, pid_t tid, hwloc_bitmap_t set);
|
|
||||||
|
|
||||||
/** \brief Convert a linux kernel cpumask file \p path into a hwloc bitmap \p set.
|
|
||||||
*
|
|
||||||
* Might be used when reading CPU set from sysfs attributes such as topology
|
|
||||||
* and caches for processors, or local_cpus for devices.
|
|
||||||
*
|
|
||||||
* \return 0 on success, -1 on error.
|
|
||||||
*
|
|
||||||
* \note This function ignores the HWLOC_FSROOT environment variable.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int hwloc_linux_read_path_as_cpumask(const char *path, hwloc_bitmap_t set);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_LINUX_H */
|
|
||||||
606
src/3rdparty/hwloc/include/hwloc/memattrs.h
vendored
606
src/3rdparty/hwloc/include/hwloc/memattrs.h
vendored
@@ -1,606 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2019-2024 Inria. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Memory node attributes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_MEMATTR_H
|
|
||||||
#define HWLOC_MEMATTR_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#elif 0
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_memattrs Comparing memory node attributes for finding where to allocate on
|
|
||||||
*
|
|
||||||
* Platforms with heterogeneous memory require ways to decide whether
|
|
||||||
* a buffer should be allocated on "fast" memory (such as HBM),
|
|
||||||
* "normal" memory (DDR) or even "slow" but large-capacity memory
|
|
||||||
* (non-volatile memory).
|
|
||||||
* These memory nodes are called "Targets" while the CPU accessing them
|
|
||||||
* is called the "Initiator". Access performance depends on their
|
|
||||||
* locality (NUMA platforms) as well as the intrinsic performance
|
|
||||||
* of the targets (heterogeneous platforms).
|
|
||||||
*
|
|
||||||
* The following attributes describe the performance of memory accesses
|
|
||||||
* from an Initiator to a memory Target, for instance their latency
|
|
||||||
* or bandwidth.
|
|
||||||
* Initiators performing these memory accesses are usually some PUs or Cores
|
|
||||||
* (described as a CPU set).
|
|
||||||
* Hence a Core may choose where to allocate a memory buffer by comparing
|
|
||||||
* the attributes of different target memory nodes nearby.
|
|
||||||
*
|
|
||||||
* There are also some attributes that are system-wide.
|
|
||||||
* Their value does not depend on a specific initiator performing
|
|
||||||
* an access.
|
|
||||||
* The memory node Capacity is an example of such attribute without
|
|
||||||
* initiator.
|
|
||||||
*
|
|
||||||
* One way to use this API is to start with a cpuset describing the Cores where
|
|
||||||
* a program is bound. The best target NUMA node for allocating memory in this
|
|
||||||
* program on these Cores may be obtained by passing this cpuset as an initiator
|
|
||||||
* to hwloc_memattr_get_best_target() with the relevant memory attribute.
|
|
||||||
* For instance, if the code is latency limited, use the Latency attribute.
|
|
||||||
*
|
|
||||||
* A more flexible approach consists in getting the list of local NUMA nodes
|
|
||||||
* by passing this cpuset to hwloc_get_local_numanode_objs().
|
|
||||||
* Attribute values for these nodes, if any, may then be obtained with
|
|
||||||
* hwloc_memattr_get_value() and manually compared with the desired criteria.
|
|
||||||
*
|
|
||||||
* Memory attributes are also used internally to build Memory Tiers which provide
|
|
||||||
* an easy way to distinguish NUMA nodes of different kinds, as explained
|
|
||||||
* in \ref heteromem.
|
|
||||||
*
|
|
||||||
* \sa An example is available in doc/examples/memory-attributes.c in the source tree.
|
|
||||||
*
|
|
||||||
* \note The API also supports specific objects as initiator,
|
|
||||||
* but it is currently not used internally by hwloc.
|
|
||||||
* Users may for instance use it to provide custom performance
|
|
||||||
* values for host memory accesses performed by GPUs.
|
|
||||||
*
|
|
||||||
* \note The interface actually also accepts targets that are not NUMA nodes.
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Predefined memory attribute IDs.
|
|
||||||
* See ::hwloc_memattr_id_t for the generic definition of IDs
|
|
||||||
* for predefined or custom attributes.
|
|
||||||
*/
|
|
||||||
enum hwloc_memattr_id_e {
|
|
||||||
/** \brief
|
|
||||||
* The \"Capacity\" is returned in bytes (local_memory attribute in objects).
|
|
||||||
*
|
|
||||||
* Best capacity nodes are nodes with <b>higher capacity</b>.
|
|
||||||
*
|
|
||||||
* No initiator is involved when looking at this attribute.
|
|
||||||
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST.
|
|
||||||
*
|
|
||||||
* Capacity values may not be modified using hwloc_memattr_set_value().
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_ID_CAPACITY = 0,
|
|
||||||
|
|
||||||
/** \brief
|
|
||||||
* The \"Locality\" is returned as the number of PUs in that locality
|
|
||||||
* (e.g. the weight of its cpuset).
|
|
||||||
*
|
|
||||||
* Best locality nodes are nodes with <b>smaller locality</b>
|
|
||||||
* (nodes that are local to very few PUs).
|
|
||||||
* Poor locality nodes are nodes with larger locality
|
|
||||||
* (nodes that are local to the entire machine).
|
|
||||||
*
|
|
||||||
* No initiator is involved when looking at this attribute.
|
|
||||||
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST.
|
|
||||||
|
|
||||||
* Locality values may not be modified using hwloc_memattr_set_value().
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_ID_LOCALITY = 1,
|
|
||||||
|
|
||||||
/** \brief
|
|
||||||
* The \"Bandwidth\" is returned in MiB/s, as seen from the given initiator location.
|
|
||||||
*
|
|
||||||
* Best bandwidth nodes are nodes with <b>higher bandwidth</b>.
|
|
||||||
*
|
|
||||||
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST
|
|
||||||
* and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
|
|
||||||
*
|
|
||||||
* This is the average bandwidth for read and write accesses. If the platform
|
|
||||||
* provides individual read and write bandwidths but no explicit average value,
|
|
||||||
* hwloc computes and returns the average.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_ID_BANDWIDTH = 2,
|
|
||||||
|
|
||||||
/** \brief
|
|
||||||
* The \"ReadBandwidth\" is returned in MiB/s, as seen from the given initiator location.
|
|
||||||
*
|
|
||||||
* Best bandwidth nodes are nodes with <b>higher bandwidth</b>.
|
|
||||||
*
|
|
||||||
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST
|
|
||||||
* and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_ID_READ_BANDWIDTH = 4,
|
|
||||||
|
|
||||||
/** \brief
|
|
||||||
* The \"WriteBandwidth\" is returned in MiB/s, as seen from the given initiator location.
|
|
||||||
*
|
|
||||||
* Best bandwidth nodes are nodes with <b>higher bandwidth</b>.
|
|
||||||
*
|
|
||||||
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST
|
|
||||||
* and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_ID_WRITE_BANDWIDTH = 5,
|
|
||||||
|
|
||||||
/** \brief
|
|
||||||
* The \"Latency\" is returned as nanoseconds, as seen from the given initiator location.
|
|
||||||
*
|
|
||||||
* Best latency nodes are nodes with <b>smaller latency</b>.
|
|
||||||
*
|
|
||||||
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_LOWER_FIRST
|
|
||||||
* and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
|
|
||||||
*
|
|
||||||
* This is the average latency for read and write accesses. If the platform
|
|
||||||
* provides individual read and write latencies but no explicit average value,
|
|
||||||
* hwloc computes and returns the average.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_ID_LATENCY = 3,
|
|
||||||
|
|
||||||
/** \brief
|
|
||||||
* The \"ReadLatency\" is returned as nanoseconds, as seen from the given initiator location.
|
|
||||||
*
|
|
||||||
* Best latency nodes are nodes with <b>smaller latency</b>.
|
|
||||||
*
|
|
||||||
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_LOWER_FIRST
|
|
||||||
* and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_ID_READ_LATENCY = 6,
|
|
||||||
|
|
||||||
/** \brief
|
|
||||||
* The \"WriteLatency\" is returned as nanoseconds, as seen from the given initiator location.
|
|
||||||
*
|
|
||||||
* Best latency nodes are nodes with <b>smaller latency</b>.
|
|
||||||
*
|
|
||||||
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_LOWER_FIRST
|
|
||||||
* and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_ID_WRITE_LATENCY = 7,
|
|
||||||
|
|
||||||
/* TODO persistence? */
|
|
||||||
|
|
||||||
HWLOC_MEMATTR_ID_MAX /**< \private
|
|
||||||
* Sentinel value for predefined attributes.
|
|
||||||
* Dynamically registered custom attributes start here.
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief A memory attribute identifier.
|
|
||||||
*
|
|
||||||
* hwloc predefines some commonly-used attributes in ::hwloc_memattr_id_e.
|
|
||||||
* One may then dynamically register custom ones with hwloc_memattr_register(),
|
|
||||||
* they will be assigned IDs immediately after the predefined ones.
|
|
||||||
* See \ref hwlocality_memattrs_manage for more information about
|
|
||||||
* existing attribute IDs.
|
|
||||||
*/
|
|
||||||
typedef unsigned hwloc_memattr_id_t;
|
|
||||||
|
|
||||||
/** \brief Return the identifier of the memory attribute with the given name.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c EINVAL if no such attribute exists.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_memattr_get_by_name(hwloc_topology_t topology,
|
|
||||||
const char *name,
|
|
||||||
hwloc_memattr_id_t *id);
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Type of location. */
|
|
||||||
enum hwloc_location_type_e {
|
|
||||||
/** \brief Location is given as a cpuset, in the location cpuset union field. \hideinitializer */
|
|
||||||
HWLOC_LOCATION_TYPE_CPUSET = 1,
|
|
||||||
/** \brief Location is given as an object, in the location object union field. \hideinitializer */
|
|
||||||
HWLOC_LOCATION_TYPE_OBJECT = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Where to measure attributes from. */
|
|
||||||
struct hwloc_location {
|
|
||||||
/** \brief Type of location. */
|
|
||||||
enum hwloc_location_type_e type;
|
|
||||||
/** \brief Actual location. */
|
|
||||||
union hwloc_location_u {
|
|
||||||
/** \brief Location as a cpuset, when the location type is ::HWLOC_LOCATION_TYPE_CPUSET. */
|
|
||||||
hwloc_cpuset_t cpuset;
|
|
||||||
/** \brief Location as an object, when the location type is ::HWLOC_LOCATION_TYPE_OBJECT. */
|
|
||||||
hwloc_obj_t object;
|
|
||||||
} location;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Flags for selecting target NUMA nodes. */
|
|
||||||
enum hwloc_local_numanode_flag_e {
|
|
||||||
/** \brief Select NUMA nodes whose locality is larger than the given cpuset.
|
|
||||||
* For instance, if a single PU (or its cpuset) is given in \p initiator,
|
|
||||||
* select all nodes close to the package that contains this PU.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY = (1UL<<0),
|
|
||||||
|
|
||||||
/** \brief Select NUMA nodes whose locality is smaller than the given cpuset.
|
|
||||||
* For instance, if a package (or its cpuset) is given in \p initiator,
|
|
||||||
* also select nodes that are attached to only a half of that package.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY = (1UL<<1),
|
|
||||||
|
|
||||||
/** \brief Select all NUMA nodes in the topology.
|
|
||||||
* The initiator \p initiator is ignored.
|
|
||||||
* \hideinitializer
|
|
||||||
*/
|
|
||||||
HWLOC_LOCAL_NUMANODE_FLAG_ALL = (1UL<<2)
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Return an array of local NUMA nodes.
|
|
||||||
*
|
|
||||||
* By default only select the NUMA nodes whose locality is exactly
|
|
||||||
* the given \p location. More nodes may be selected if additional flags
|
|
||||||
* are given as a OR'ed set of ::hwloc_local_numanode_flag_e.
|
|
||||||
*
|
|
||||||
* If \p location is given as an explicit object, its CPU set is used
|
|
||||||
* to find NUMA nodes with the corresponding locality.
|
|
||||||
* If the object does not have a CPU set (e.g. I/O object), the CPU
|
|
||||||
* parent (where the I/O object is attached) is used.
|
|
||||||
*
|
|
||||||
* On input, \p nr points to the number of nodes that may be stored
|
|
||||||
* in the \p nodes array.
|
|
||||||
* On output, \p nr will be changed to the number of stored nodes,
|
|
||||||
* or the number of nodes that would have been stored if there were
|
|
||||||
* enough room.
|
|
||||||
*
|
|
||||||
* \return 0 on success or -1 on error.
|
|
||||||
*
|
|
||||||
* \note Some of these NUMA nodes may not have any memory attribute
|
|
||||||
* values and hence not be reported as actual targets in other functions.
|
|
||||||
*
|
|
||||||
* \note The number of NUMA nodes in the topology (obtained by
|
|
||||||
* hwloc_bitmap_weight() on the root object nodeset) may be used
|
|
||||||
* to allocate the \p nodes array.
|
|
||||||
*
|
|
||||||
* \note When an object CPU set is given as locality, for instance a Package,
|
|
||||||
* and when flags contain both ::HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY
|
|
||||||
* and ::HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY,
|
|
||||||
* the returned array corresponds to the nodeset of that object.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_get_local_numanode_objs(hwloc_topology_t topology,
|
|
||||||
struct hwloc_location *location,
|
|
||||||
unsigned *nr,
|
|
||||||
hwloc_obj_t *nodes,
|
|
||||||
unsigned long flags);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Return an attribute value for a specific target NUMA node.
|
|
||||||
*
|
|
||||||
* If the attribute does not relate to a specific initiator
|
|
||||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
|
|
||||||
* location \p initiator is ignored and may be \c NULL.
|
|
||||||
*
|
|
||||||
* \p target_node cannot be \c NULL. If \p attribute is ::HWLOC_MEMATTR_ID_CAPACITY,
|
|
||||||
* \p target_node must be a NUMA node. If it is ::HWLOC_MEMATTR_ID_LOCALITY,
|
|
||||||
* \p target_node must have a CPU set.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 on error, for instance with errno set to \c EINVAL if flags
|
|
||||||
* are invalid or no such attribute exists.
|
|
||||||
*
|
|
||||||
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
|
|
||||||
* when refering to accesses performed by CPU cores.
|
|
||||||
* ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
|
|
||||||
* but users may for instance use it to provide custom information about
|
|
||||||
* host memory accesses performed by GPUs.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_memattr_get_value(hwloc_topology_t topology,
|
|
||||||
hwloc_memattr_id_t attribute,
|
|
||||||
hwloc_obj_t target_node,
|
|
||||||
struct hwloc_location *initiator,
|
|
||||||
unsigned long flags,
|
|
||||||
hwloc_uint64_t *value);
|
|
||||||
|
|
||||||
/** \brief Return the best target NUMA node for the given attribute and initiator.
|
|
||||||
*
|
|
||||||
* If the attribute does not relate to a specific initiator
|
|
||||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
|
|
||||||
* location \p initiator is ignored and may be \c NULL.
|
|
||||||
*
|
|
||||||
* If \p value is non \c NULL, the corresponding value is returned there.
|
|
||||||
*
|
|
||||||
* If multiple targets have the same attribute values, only one is
|
|
||||||
* returned (and there is no way to clarify how that one is chosen).
|
|
||||||
* Applications that want to detect targets with identical/similar
|
|
||||||
* values, or that want to look at values for multiple attributes,
|
|
||||||
* should rather get all values using hwloc_memattr_get_value()
|
|
||||||
* and manually select the target they consider the best.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c ENOENT if there are no matching targets.
|
|
||||||
* \return -1 with errno set to \c EINVAL if flags are invalid,
|
|
||||||
* or no such attribute exists.
|
|
||||||
*
|
|
||||||
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
|
|
||||||
* when refering to accesses performed by CPU cores.
|
|
||||||
* ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
|
|
||||||
* but users may for instance use it to provide custom information about
|
|
||||||
* host memory accesses performed by GPUs.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_memattr_get_best_target(hwloc_topology_t topology,
|
|
||||||
hwloc_memattr_id_t attribute,
|
|
||||||
struct hwloc_location *initiator,
|
|
||||||
unsigned long flags,
|
|
||||||
hwloc_obj_t *best_target, hwloc_uint64_t *value);
|
|
||||||
|
|
||||||
/** \brief Return the best initiator for the given attribute and target NUMA node.
|
|
||||||
*
|
|
||||||
* If \p value is non \c NULL, the corresponding value is returned there.
|
|
||||||
*
|
|
||||||
* If multiple initiators have the same attribute values, only one is
|
|
||||||
* returned (and there is no way to clarify how that one is chosen).
|
|
||||||
* Applications that want to detect initiators with identical/similar
|
|
||||||
* values, or that want to look at values for multiple attributes,
|
|
||||||
* should rather get all values using hwloc_memattr_get_value()
|
|
||||||
* and manually select the initiator they consider the best.
|
|
||||||
*
|
|
||||||
* The returned initiator should not be modified or freed,
|
|
||||||
* it belongs to the topology.
|
|
||||||
*
|
|
||||||
* \p target_node cannot be \c NULL.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c ENOENT if there are no matching initiators.
|
|
||||||
* \return -1 with errno set to \c EINVAL if the attribute does not relate to a specific initiator
|
|
||||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR).
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_memattr_get_best_initiator(hwloc_topology_t topology,
|
|
||||||
hwloc_memattr_id_t attribute,
|
|
||||||
hwloc_obj_t target_node,
|
|
||||||
unsigned long flags,
|
|
||||||
struct hwloc_location *best_initiator, hwloc_uint64_t *value);
|
|
||||||
|
|
||||||
/** \brief Return the target NUMA nodes that have some values for a given attribute.
|
|
||||||
*
|
|
||||||
* Return targets for the given attribute in the \p targets array
|
|
||||||
* (for the given initiator if any).
|
|
||||||
* If \p values is not \c NULL, the corresponding attribute values
|
|
||||||
* are stored in the array it points to.
|
|
||||||
*
|
|
||||||
* On input, \p nr points to the number of targets that may be stored
|
|
||||||
* in the array \p targets (and \p values).
|
|
||||||
* On output, \p nr points to the number of targets (and values) that
|
|
||||||
* were actually found, even if some of them couldn't be stored in the array.
|
|
||||||
* Targets that couldn't be stored are ignored, but the function still
|
|
||||||
* returns success (\c 0). The caller may find out by comparing the value pointed
|
|
||||||
* by \p nr before and after the function call.
|
|
||||||
*
|
|
||||||
* The returned targets should not be modified or freed,
|
|
||||||
* they belong to the topology.
|
|
||||||
*
|
|
||||||
* Argument \p initiator is ignored if the attribute does not relate to a specific
|
|
||||||
* initiator (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR).
|
|
||||||
* Otherwise \p initiator may be non \c NULL to report only targets
|
|
||||||
* that have a value for that initiator.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \note This function is meant for tools and debugging (listing internal information)
|
|
||||||
* rather than for application queries. Applications should rather select useful
|
|
||||||
* NUMA nodes with hwloc_get_local_numanode_objs() and then look at their attribute
|
|
||||||
* values.
|
|
||||||
*
|
|
||||||
* \return 0 on success or -1 on error.
|
|
||||||
*
|
|
||||||
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
|
|
||||||
* when referring to accesses performed by CPU cores.
|
|
||||||
* ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
|
|
||||||
* but users may for instance use it to provide custom information about
|
|
||||||
* host memory accesses performed by GPUs.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_memattr_get_targets(hwloc_topology_t topology,
|
|
||||||
hwloc_memattr_id_t attribute,
|
|
||||||
struct hwloc_location *initiator,
|
|
||||||
unsigned long flags,
|
|
||||||
unsigned *nr, hwloc_obj_t *targets, hwloc_uint64_t *values);
|
|
||||||
|
|
||||||
/** \brief Return the initiators that have values for a given attribute for a specific target NUMA node.
|
|
||||||
*
|
|
||||||
* Return initiators for the given attribute and target node in the
|
|
||||||
* \p initiators array.
|
|
||||||
* If \p values is not \c NULL, the corresponding attribute values
|
|
||||||
* are stored in the array it points to.
|
|
||||||
*
|
|
||||||
* On input, \p nr points to the number of initiators that may be stored
|
|
||||||
* in the array \p initiators (and \p values).
|
|
||||||
* On output, \p nr points to the number of initiators (and values) that
|
|
||||||
* were actually found, even if some of them couldn't be stored in the array.
|
|
||||||
* Initiators that couldn't be stored are ignored, but the function still
|
|
||||||
* returns success (\c 0). The caller may find out by comparing the value pointed
|
|
||||||
* by \p nr before and after the function call.
|
|
||||||
*
|
|
||||||
* The returned initiators should not be modified or freed,
|
|
||||||
* they belong to the topology.
|
|
||||||
*
|
|
||||||
* \p target_node cannot be \c NULL.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* If the attribute does not relate to a specific initiator
|
|
||||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
|
|
||||||
* no initiator is returned.
|
|
||||||
*
|
|
||||||
* \return 0 on success or -1 on error.
|
|
||||||
*
|
|
||||||
* \note This function is meant for tools and debugging (listing internal information)
|
|
||||||
* rather than for application queries. Applications should rather select useful
|
|
||||||
* NUMA nodes with hwloc_get_local_numanode_objs() and then look at their attribute
|
|
||||||
* values for some relevant initiators.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_memattr_get_initiators(hwloc_topology_t topology,
|
|
||||||
hwloc_memattr_id_t attribute,
|
|
||||||
hwloc_obj_t target_node,
|
|
||||||
unsigned long flags,
|
|
||||||
unsigned *nr, struct hwloc_location *initiators, hwloc_uint64_t *values);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_memattrs_manage Managing memory attributes
|
|
||||||
*
|
|
||||||
* Memory attribues are identified by an ID (::hwloc_memattr_id_t)
|
|
||||||
* and a name. hwloc_memattr_get_name() and hwloc_memattr_get_by_name()
|
|
||||||
* convert between them (or return error if the attribute does not exist).
|
|
||||||
*
|
|
||||||
* The set of valid ::hwloc_memattr_id_t is a contigous set starting at \c 0.
|
|
||||||
* It first contains predefined attributes, as listed
|
|
||||||
* in ::hwloc_memattr_id_e (from \c 0 to \c HWLOC_MEMATTR_ID_MAX-1).
|
|
||||||
* Then custom attributes may be dynamically registered with
|
|
||||||
* hwloc_memattr_register(). They will get the following IDs
|
|
||||||
* (\c HWLOC_MEMATTR_ID_MAX for the first one, etc.).
|
|
||||||
*
|
|
||||||
* To iterate over all valid attributes
|
|
||||||
* (either predefined or dynamically registered custom ones),
|
|
||||||
* one may iterate over IDs starting from \c 0 until hwloc_memattr_get_name()
|
|
||||||
* or hwloc_memattr_get_flags() returns an error.
|
|
||||||
*
|
|
||||||
* The values for an existing attribute or for custom dynamically registered ones
|
|
||||||
* may be set or modified with hwloc_memattr_set_value().
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Return the name of a memory attribute.
|
|
||||||
*
|
|
||||||
* The output pointer \p name cannot be \c NULL.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c EINVAL if the attribute does not exist.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_memattr_get_name(hwloc_topology_t topology,
|
|
||||||
hwloc_memattr_id_t attribute,
|
|
||||||
const char **name);
|
|
||||||
|
|
||||||
/** \brief Return the flags of the given attribute.
|
|
||||||
*
|
|
||||||
* Flags are a OR'ed set of ::hwloc_memattr_flag_e.
|
|
||||||
*
|
|
||||||
* The output pointer \p flags cannot be \c NULL.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c EINVAL if the attribute does not exist.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_memattr_get_flags(hwloc_topology_t topology,
|
|
||||||
hwloc_memattr_id_t attribute,
|
|
||||||
unsigned long *flags);
|
|
||||||
|
|
||||||
/** \brief Memory attribute flags.
|
|
||||||
* Given to hwloc_memattr_register() and returned by hwloc_memattr_get_flags().
|
|
||||||
*/
|
|
||||||
enum hwloc_memattr_flag_e {
|
|
||||||
/** \brief The best nodes for this memory attribute are those with the higher values.
|
|
||||||
* For instance Bandwidth.
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_FLAG_HIGHER_FIRST = (1UL<<0),
|
|
||||||
/** \brief The best nodes for this memory attribute are those with the lower values.
|
|
||||||
* For instance Latency.
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_FLAG_LOWER_FIRST = (1UL<<1),
|
|
||||||
/** \brief The value returned for this memory attribute depends on the given initiator.
|
|
||||||
* For instance Bandwidth and Latency, but not Capacity.
|
|
||||||
*/
|
|
||||||
HWLOC_MEMATTR_FLAG_NEED_INITIATOR = (1UL<<2)
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Register a new memory attribute.
|
|
||||||
*
|
|
||||||
* Add a new custom memory attribute.
|
|
||||||
* Flags are a OR'ed set of ::hwloc_memattr_flag_e. It must contain one of
|
|
||||||
* ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST or ::HWLOC_MEMATTR_FLAG_LOWER_FIRST but not both.
|
|
||||||
*
|
|
||||||
* The new attribute \p id is immediately after the last existing attribute ID
|
|
||||||
* (which is either the ID of the last registered attribute if any,
|
|
||||||
* or the ID of the last predefined attribute in ::hwloc_memattr_id_e).
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 with errno set to \c EINVAL if an invalid set of flags is given.
|
|
||||||
* \return -1 with errno set to \c EBUSY if another attribute already uses this name.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_memattr_register(hwloc_topology_t topology,
|
|
||||||
const char *name,
|
|
||||||
unsigned long flags,
|
|
||||||
hwloc_memattr_id_t *id);
|
|
||||||
|
|
||||||
/** \brief Set an attribute value for a specific target NUMA node.
|
|
||||||
*
|
|
||||||
* If the attribute does not relate to a specific initiator
|
|
||||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
|
|
||||||
* location \p initiator is ignored and may be \c NULL.
|
|
||||||
*
|
|
||||||
* The initiator will be copied into the topology,
|
|
||||||
* the caller should free anything allocated to store the initiator,
|
|
||||||
* for instance the cpuset.
|
|
||||||
*
|
|
||||||
* \p target_node cannot be \c NULL.
|
|
||||||
*
|
|
||||||
* \p attribute cannot be ::HWLOC_MEMATTR_FLAG_ID_CAPACITY or
|
|
||||||
* ::HWLOC_MEMATTR_FLAG_ID_LOCALITY.
|
|
||||||
*
|
|
||||||
* \p flags must be \c 0 for now.
|
|
||||||
*
|
|
||||||
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
|
|
||||||
* when referring to accesses performed by CPU cores.
|
|
||||||
* ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
|
|
||||||
* but users may for instance use it to provide custom information about
|
|
||||||
* host memory accesses performed by GPUs.
|
|
||||||
*
|
|
||||||
* \return 0 on success or -1 on error.
|
|
||||||
*/
|
|
||||||
HWLOC_DECLSPEC int
|
|
||||||
hwloc_memattr_set_value(hwloc_topology_t topology,
|
|
||||||
hwloc_memattr_id_t attribute,
|
|
||||||
hwloc_obj_t target_node,
|
|
||||||
struct hwloc_location *initiator,
|
|
||||||
unsigned long flags,
|
|
||||||
hwloc_uint64_t value);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_MEMATTR_H */
|
|
||||||
184
src/3rdparty/hwloc/include/hwloc/nvml.h
vendored
184
src/3rdparty/hwloc/include/hwloc/nvml.h
vendored
@@ -1,184 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2012-2023 Inria. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Macros to help interaction between hwloc and the NVIDIA Management Library.
|
|
||||||
*
|
|
||||||
* Applications that use both hwloc and the NVIDIA Management Library may want to
|
|
||||||
* include this file so as to get topology information for NVML devices.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_NVML_H
|
|
||||||
#define HWLOC_NVML_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
#include "hwloc/autogen/config.h"
|
|
||||||
#include "hwloc/helper.h"
|
|
||||||
#ifdef HWLOC_LINUX_SYS
|
|
||||||
#include "hwloc/linux.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <nvml.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_nvml Interoperability with the NVIDIA Management Library
|
|
||||||
*
|
|
||||||
* This interface offers ways to retrieve topology information about
|
|
||||||
* devices managed by the NVIDIA Management Library (NVML).
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Get the CPU set of processors that are physically
|
|
||||||
* close to NVML device \p device.
|
|
||||||
*
|
|
||||||
* Store in \p set the CPU-set describing the locality of the NVML device \p device.
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p device must match the local machine.
|
|
||||||
* I/O devices detection and the NVML 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_nvml_get_device_osdev()
|
|
||||||
* and hwloc_nvml_get_device_osdev_by_index().
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_nvml_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
|
||||||
nvmlDevice_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_NVML_DEVICE_SYSFS_PATH_MAX 128
|
|
||||||
char path[HWLOC_NVML_DEVICE_SYSFS_PATH_MAX];
|
|
||||||
nvmlReturn_t nvres;
|
|
||||||
nvmlPciInfo_t pci;
|
|
||||||
|
|
||||||
if (!hwloc_topology_is_thissystem(topology)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
nvres = nvmlDeviceGetPciInfo(device, &pci);
|
|
||||||
if (NVML_SUCCESS != nvres) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.0/local_cpus", pci.domain, pci.bus, pci.device);
|
|
||||||
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 hwloc OS device object corresponding to the
|
|
||||||
* NVML device whose index is \p idx.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object describing the NVML device whose index is \p idx.
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* The topology \p topology does not necessarily have to match the current
|
|
||||||
* machine. For instance the topology may be an XML import of a remote host.
|
|
||||||
* I/O devices detection and the NVML component must be enabled in the topology.
|
|
||||||
*
|
|
||||||
* \note The corresponding PCI device object can be obtained by looking
|
|
||||||
* at the OS device parent object (unless PCI devices are filtered out).
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_nvml_get_device_osdev_by_index(hwloc_topology_t topology, unsigned idx)
|
|
||||||
{
|
|
||||||
hwloc_obj_t osdev = NULL;
|
|
||||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
|
||||||
if (HWLOC_OBJ_OSDEV_GPU == osdev->attr->osdev.type
|
|
||||||
&& osdev->name
|
|
||||||
&& !strncmp("nvml", osdev->name, 4)
|
|
||||||
&& atoi(osdev->name + 4) == (int) idx)
|
|
||||||
return osdev;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the hwloc OS device object corresponding to NVML device \p device.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object that describes the given NVML device \p device.
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p device must match the local machine.
|
|
||||||
* I/O devices detection and the NVML component must be enabled in the topology.
|
|
||||||
* If not, the locality of the object may still be found using
|
|
||||||
* hwloc_nvml_get_device_cpuset().
|
|
||||||
*
|
|
||||||
* \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_nvml_get_device_osdev(hwloc_topology_t topology, nvmlDevice_t device)
|
|
||||||
{
|
|
||||||
hwloc_obj_t osdev;
|
|
||||||
nvmlReturn_t nvres;
|
|
||||||
nvmlPciInfo_t pci;
|
|
||||||
char uuid[64];
|
|
||||||
|
|
||||||
if (!hwloc_topology_is_thissystem(topology)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
nvres = nvmlDeviceGetPciInfo(device, &pci);
|
|
||||||
if (NVML_SUCCESS != nvres)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
nvres = nvmlDeviceGetUUID(device, uuid, sizeof(uuid));
|
|
||||||
if (NVML_SUCCESS != nvres)
|
|
||||||
uuid[0] = '\0';
|
|
||||||
|
|
||||||
osdev = NULL;
|
|
||||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
|
||||||
hwloc_obj_t pcidev = osdev->parent;
|
|
||||||
const char *info;
|
|
||||||
|
|
||||||
if (strncmp(osdev->name, "nvml", 4))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pcidev
|
|
||||||
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
|
|
||||||
&& pcidev->attr->pcidev.domain == pci.domain
|
|
||||||
&& pcidev->attr->pcidev.bus == pci.bus
|
|
||||||
&& pcidev->attr->pcidev.dev == pci.device
|
|
||||||
&& pcidev->attr->pcidev.func == 0)
|
|
||||||
return osdev;
|
|
||||||
|
|
||||||
info = hwloc_obj_get_info_by_name(osdev, "NVIDIAUUID");
|
|
||||||
if (info && !strcmp(info, uuid))
|
|
||||||
return osdev;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_NVML_H */
|
|
||||||
277
src/3rdparty/hwloc/include/hwloc/opencl.h
vendored
277
src/3rdparty/hwloc/include/hwloc/opencl.h
vendored
@@ -1,277 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2012-2023 Inria. All rights reserved.
|
|
||||||
* Copyright © 2013, 2018 Université Bordeaux. All right reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Macros to help interaction between hwloc and the OpenCL interface.
|
|
||||||
*
|
|
||||||
* Applications that use both hwloc and OpenCL may want to
|
|
||||||
* include this file so as to get topology information for OpenCL devices.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_OPENCL_H
|
|
||||||
#define HWLOC_OPENCL_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
#include "hwloc/autogen/config.h"
|
|
||||||
#include "hwloc/helper.h"
|
|
||||||
#ifdef HWLOC_LINUX_SYS
|
|
||||||
#include "hwloc/linux.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <OpenCL/cl.h>
|
|
||||||
#else
|
|
||||||
#include <CL/cl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* OpenCL extensions aren't always shipped with default headers, and
|
|
||||||
* they don't always reflect what the installed implementations support.
|
|
||||||
* Try everything and let the implementation return errors when non supported.
|
|
||||||
*/
|
|
||||||
/* Copyright (c) 2008-2018 The Khronos Group Inc. */
|
|
||||||
|
|
||||||
/* needs "cl_khr_pci_bus_info" device extension, but not strictly required for clGetDeviceInfo() */
|
|
||||||
typedef struct {
|
|
||||||
cl_uint pci_domain;
|
|
||||||
cl_uint pci_bus;
|
|
||||||
cl_uint pci_device;
|
|
||||||
cl_uint pci_function;
|
|
||||||
} hwloc_cl_device_pci_bus_info_khr;
|
|
||||||
#define HWLOC_CL_DEVICE_PCI_BUS_INFO_KHR 0x410F
|
|
||||||
|
|
||||||
/* needs "cl_amd_device_attribute_query" device extension, but not strictly required for clGetDeviceInfo() */
|
|
||||||
#define HWLOC_CL_DEVICE_TOPOLOGY_AMD 0x4037
|
|
||||||
typedef union {
|
|
||||||
struct { cl_uint type; cl_uint data[5]; } raw;
|
|
||||||
struct { cl_uint type; cl_char unused[17]; cl_char bus; cl_char device; cl_char function; } pcie;
|
|
||||||
} hwloc_cl_device_topology_amd;
|
|
||||||
#define HWLOC_CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD 1
|
|
||||||
|
|
||||||
/* needs "cl_nv_device_attribute_query" device extension, but not strictly required for clGetDeviceInfo() */
|
|
||||||
#define HWLOC_CL_DEVICE_PCI_BUS_ID_NV 0x4008
|
|
||||||
#define HWLOC_CL_DEVICE_PCI_SLOT_ID_NV 0x4009
|
|
||||||
#define HWLOC_CL_DEVICE_PCI_DOMAIN_ID_NV 0x400A
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_opencl Interoperability with OpenCL
|
|
||||||
*
|
|
||||||
* This interface offers ways to retrieve topology information about
|
|
||||||
* OpenCL devices.
|
|
||||||
*
|
|
||||||
* Only AMD and NVIDIA OpenCL implementations currently offer useful locality
|
|
||||||
* information about their devices.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Return the domain, bus and device IDs of the OpenCL device \p device.
|
|
||||||
*
|
|
||||||
* Device \p device must match the local machine.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 on error, for instance if device information could not be found.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_opencl_get_device_pci_busid(cl_device_id device,
|
|
||||||
unsigned *domain, unsigned *bus, unsigned *dev, unsigned *func)
|
|
||||||
{
|
|
||||||
hwloc_cl_device_topology_amd amdtopo;
|
|
||||||
hwloc_cl_device_pci_bus_info_khr khrbusinfo;
|
|
||||||
cl_uint nvbus, nvslot, nvdomain;
|
|
||||||
cl_int clret;
|
|
||||||
|
|
||||||
clret = clGetDeviceInfo(device, HWLOC_CL_DEVICE_PCI_BUS_INFO_KHR, sizeof(khrbusinfo), &khrbusinfo, NULL);
|
|
||||||
if (CL_SUCCESS == clret) {
|
|
||||||
*domain = (unsigned) khrbusinfo.pci_domain;
|
|
||||||
*bus = (unsigned) khrbusinfo.pci_bus;
|
|
||||||
*dev = (unsigned) khrbusinfo.pci_device;
|
|
||||||
*func = (unsigned) khrbusinfo.pci_function;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
clret = clGetDeviceInfo(device, HWLOC_CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
|
|
||||||
if (CL_SUCCESS == clret
|
|
||||||
&& HWLOC_CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD == amdtopo.raw.type) {
|
|
||||||
*domain = 0; /* can't do anything better */
|
|
||||||
/* cl_device_topology_amd stores bus ID in cl_char, dont convert those signed char directly to unsigned int */
|
|
||||||
*bus = (unsigned) (unsigned char) amdtopo.pcie.bus;
|
|
||||||
*dev = (unsigned) (unsigned char) amdtopo.pcie.device;
|
|
||||||
*func = (unsigned) (unsigned char) amdtopo.pcie.function;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
clret = clGetDeviceInfo(device, HWLOC_CL_DEVICE_PCI_BUS_ID_NV, sizeof(nvbus), &nvbus, NULL);
|
|
||||||
if (CL_SUCCESS == clret) {
|
|
||||||
clret = clGetDeviceInfo(device, HWLOC_CL_DEVICE_PCI_SLOT_ID_NV, sizeof(nvslot), &nvslot, NULL);
|
|
||||||
if (CL_SUCCESS == clret) {
|
|
||||||
clret = clGetDeviceInfo(device, HWLOC_CL_DEVICE_PCI_DOMAIN_ID_NV, sizeof(nvdomain), &nvdomain, NULL);
|
|
||||||
if (CL_SUCCESS == clret) { /* available since CUDA 10.2 */
|
|
||||||
*domain = nvdomain;
|
|
||||||
} else {
|
|
||||||
*domain = 0;
|
|
||||||
}
|
|
||||||
*bus = nvbus & 0xff;
|
|
||||||
/* non-documented but used in many other projects */
|
|
||||||
*dev = nvslot >> 3;
|
|
||||||
*func = nvslot & 0x7;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the CPU set of processors that are physically
|
|
||||||
* close to OpenCL device \p device.
|
|
||||||
*
|
|
||||||
* Store in \p set the CPU-set describing the locality of the OpenCL device \p device.
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p device must match the local machine.
|
|
||||||
* I/O devices detection and the OpenCL 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_opencl_get_device_osdev()
|
|
||||||
* and hwloc_opencl_get_device_osdev_by_index().
|
|
||||||
*
|
|
||||||
* This function is currently only implemented in a meaningful way for
|
|
||||||
* Linux with the AMD or NVIDIA OpenCL implementation; other systems will simply
|
|
||||||
* get a full cpuset.
|
|
||||||
*
|
|
||||||
* \return 0 on success.
|
|
||||||
* \return -1 on error, for instance if the device could not be found.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_opencl_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
|
||||||
cl_device_id device __hwloc_attribute_unused,
|
|
||||||
hwloc_cpuset_t set)
|
|
||||||
{
|
|
||||||
#if (defined HWLOC_LINUX_SYS)
|
|
||||||
/* If we're on Linux, try AMD/NVIDIA extensions + the sysfs mechanism to get the local cpus */
|
|
||||||
#define HWLOC_OPENCL_DEVICE_SYSFS_PATH_MAX 128
|
|
||||||
char path[HWLOC_OPENCL_DEVICE_SYSFS_PATH_MAX];
|
|
||||||
unsigned pcidomain, pcibus, pcidev, pcifunc;
|
|
||||||
|
|
||||||
if (!hwloc_topology_is_thissystem(topology)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hwloc_opencl_get_device_pci_busid(device, &pcidomain, &pcibus, &pcidev, &pcifunc) < 0) {
|
|
||||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/local_cpus", pcidomain, pcibus, pcidev, pcifunc);
|
|
||||||
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 hwloc OS device object corresponding to the
|
|
||||||
* OpenCL device for the given indexes.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object describing the OpenCL device
|
|
||||||
* whose platform index is \p platform_index,
|
|
||||||
* and whose device index within this platform if \p device_index.
|
|
||||||
* \return \c NULL if there is none.
|
|
||||||
*
|
|
||||||
* The topology \p topology does not necessarily have to match the current
|
|
||||||
* machine. For instance the topology may be an XML import of a remote host.
|
|
||||||
* I/O devices detection and the OpenCL component must be enabled in the topology.
|
|
||||||
*
|
|
||||||
* \note The corresponding PCI device object can be obtained by looking
|
|
||||||
* at the OS device parent object (unless PCI devices are filtered out).
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_opencl_get_device_osdev_by_index(hwloc_topology_t topology,
|
|
||||||
unsigned platform_index, unsigned device_index)
|
|
||||||
{
|
|
||||||
unsigned x = (unsigned) -1, y = (unsigned) -1;
|
|
||||||
hwloc_obj_t osdev = NULL;
|
|
||||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
|
||||||
if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
|
|
||||||
&& osdev->name
|
|
||||||
&& sscanf(osdev->name, "opencl%ud%u", &x, &y) == 2
|
|
||||||
&& platform_index == x && device_index == y)
|
|
||||||
return osdev;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the hwloc OS device object corresponding to OpenCL device \p deviceX.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object corresponding to the given OpenCL device \p device.
|
|
||||||
* \return \c NULL if none could be found, for instance
|
|
||||||
* if required OpenCL attributes are not available.
|
|
||||||
*
|
|
||||||
* This function currently only works on AMD and NVIDIA OpenCL devices that support
|
|
||||||
* relevant OpenCL extensions. hwloc_opencl_get_device_osdev_by_index()
|
|
||||||
* should be preferred whenever possible, i.e. when platform and device index
|
|
||||||
* are known.
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p device must match the local machine.
|
|
||||||
* I/O devices detection and the OpenCL component must be enabled in the topology.
|
|
||||||
* If not, the locality of the object may still be found using
|
|
||||||
* hwloc_opencl_get_device_cpuset().
|
|
||||||
*
|
|
||||||
* \note This function cannot work if PCI devices are filtered out.
|
|
||||||
*
|
|
||||||
* \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_opencl_get_device_osdev(hwloc_topology_t topology __hwloc_attribute_unused,
|
|
||||||
cl_device_id device __hwloc_attribute_unused)
|
|
||||||
{
|
|
||||||
hwloc_obj_t osdev;
|
|
||||||
unsigned pcidomain, pcibus, pcidevice, pcifunc;
|
|
||||||
|
|
||||||
if (hwloc_opencl_get_device_pci_busid(device, &pcidomain, &pcibus, &pcidevice, &pcifunc) < 0) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
osdev = NULL;
|
|
||||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
|
||||||
hwloc_obj_t pcidev = osdev->parent;
|
|
||||||
if (strncmp(osdev->name, "opencl", 6))
|
|
||||||
continue;
|
|
||||||
if (pcidev
|
|
||||||
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
|
|
||||||
&& pcidev->attr->pcidev.domain == pcidomain
|
|
||||||
&& pcidev->attr->pcidev.bus == pcibus
|
|
||||||
&& pcidev->attr->pcidev.dev == pcidevice
|
|
||||||
&& pcidev->attr->pcidev.func == pcifunc)
|
|
||||||
return osdev;
|
|
||||||
/* if PCI are filtered out, we need a info attr to match on */
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_OPENCL_H */
|
|
||||||
155
src/3rdparty/hwloc/include/hwloc/openfabrics-verbs.h
vendored
155
src/3rdparty/hwloc/include/hwloc/openfabrics-verbs.h
vendored
@@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2009 CNRS
|
|
||||||
* Copyright © 2009-2023 Inria. All rights reserved.
|
|
||||||
* Copyright © 2009-2010 Université Bordeaux
|
|
||||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
|
||||||
* See COPYING in top-level directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Macros to help interaction between hwloc and OpenFabrics
|
|
||||||
* verbs.
|
|
||||||
*
|
|
||||||
* Applications that use both hwloc and OpenFabrics verbs may want to
|
|
||||||
* include this file so as to get topology information for OpenFabrics
|
|
||||||
* hardware (InfiniBand, etc).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HWLOC_OPENFABRICS_VERBS_H
|
|
||||||
#define HWLOC_OPENFABRICS_VERBS_H
|
|
||||||
|
|
||||||
#include "hwloc.h"
|
|
||||||
#include "hwloc/autogen/config.h"
|
|
||||||
#ifdef HWLOC_LINUX_SYS
|
|
||||||
#include "hwloc/linux.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <infiniband/verbs.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \defgroup hwlocality_openfabrics Interoperability with OpenFabrics
|
|
||||||
*
|
|
||||||
* This interface offers ways to retrieve topology information about
|
|
||||||
* OpenFabrics devices (InfiniBand, Omni-Path, usNIC, etc).
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \brief Get the CPU set of processors that are physically
|
|
||||||
* close to device \p ibdev.
|
|
||||||
*
|
|
||||||
* Store in \p set the CPU-set describing the locality of the OpenFabrics
|
|
||||||
* device \p ibdev (InfiniBand, etc).
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p ibdev must match the local machine.
|
|
||||||
* I/O devices detection is 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_ibv_get_device_osdev()
|
|
||||||
* and hwloc_ibv_get_device_osdev_by_name().
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline int
|
|
||||||
hwloc_ibv_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
|
||||||
struct ibv_device *ibdev, hwloc_cpuset_t set)
|
|
||||||
{
|
|
||||||
#ifdef HWLOC_LINUX_SYS
|
|
||||||
/* If we're on Linux, use the verbs-provided sysfs mechanism to
|
|
||||||
get the local cpus */
|
|
||||||
#define HWLOC_OPENFABRICS_VERBS_SYSFS_PATH_MAX 128
|
|
||||||
char path[HWLOC_OPENFABRICS_VERBS_SYSFS_PATH_MAX];
|
|
||||||
|
|
||||||
if (!hwloc_topology_is_thissystem(topology)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(path, "/sys/class/infiniband/%s/device/local_cpus",
|
|
||||||
ibv_get_device_name(ibdev));
|
|
||||||
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 hwloc OS device object corresponding to the OpenFabrics
|
|
||||||
* device named \p ibname.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object describing the OpenFabrics device
|
|
||||||
* (InfiniBand, Omni-Path, usNIC, etc) whose name is \p ibname
|
|
||||||
* (mlx5_0, hfi1_0, usnic_0, qib0, etc).
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* The name \p ibname is usually obtained from ibv_get_device_name().
|
|
||||||
*
|
|
||||||
* The topology \p topology does not necessarily have to match the current
|
|
||||||
* machine. For instance the topology may be an XML import of a remote host.
|
|
||||||
* I/O devices detection must be enabled in the topology.
|
|
||||||
*
|
|
||||||
* \note The corresponding PCI device object can be obtained by looking
|
|
||||||
* at the OS device parent object.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_ibv_get_device_osdev_by_name(hwloc_topology_t topology,
|
|
||||||
const char *ibname)
|
|
||||||
{
|
|
||||||
hwloc_obj_t osdev = NULL;
|
|
||||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
|
||||||
if (HWLOC_OBJ_OSDEV_OPENFABRICS == osdev->attr->osdev.type
|
|
||||||
&& osdev->name && !strcmp(ibname, osdev->name))
|
|
||||||
return osdev;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief Get the hwloc OS device object corresponding to the OpenFabrics
|
|
||||||
* device \p ibdev.
|
|
||||||
*
|
|
||||||
* \return The hwloc OS device object describing the OpenFabrics
|
|
||||||
* device \p ibdev (InfiniBand, etc).
|
|
||||||
* \return \c NULL if none could be found.
|
|
||||||
*
|
|
||||||
* Topology \p topology and device \p ibdev must match the local machine.
|
|
||||||
* I/O devices detection must be enabled in the topology.
|
|
||||||
* If not, the locality of the object may still be found using
|
|
||||||
* hwloc_ibv_get_device_cpuset().
|
|
||||||
*
|
|
||||||
* \note The corresponding PCI device object can be obtained by looking
|
|
||||||
* at the OS device parent object.
|
|
||||||
*/
|
|
||||||
static __hwloc_inline hwloc_obj_t
|
|
||||||
hwloc_ibv_get_device_osdev(hwloc_topology_t topology,
|
|
||||||
struct ibv_device *ibdev)
|
|
||||||
{
|
|
||||||
if (!hwloc_topology_is_thissystem(topology)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return hwloc_ibv_get_device_osdev_by_name(topology, ibv_get_device_name(ibdev));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HWLOC_OPENFABRICS_VERBS_H */
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user