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

Compare commits

...

62 Commits

Author SHA1 Message Date
XMRig
57a4998ae2 Fix Linux build. 2025-06-13 04:05:30 +07:00
XMRig
34b4448a81 Split BasicCpuInfo_arm. 2025-06-13 03:57:13 +07:00
XMRig
650d794fb1 Initial Windows ARM64 support via MSYS2. 2025-06-13 03:00:34 +07:00
XMRig
064a61988a Update deps scripts. 2025-06-12 00:52:49 +07:00
xmrig
2ab7f85ccd Merge pull request #3665 from SChernykh/dev
Tweaked autoconfig for AMD CPUs with < 2 MB L3 cache per thread
2025-06-11 23:40:46 +07:00
SChernykh
e4c30eb0dd Tweaked autoconfig for AMD CPUs with < 2 MB L3 cache per thread 2025-06-11 18:34:50 +02:00
XMRig
d4e57d9427 Fix LLHTTP_EXPORT 2025-06-10 03:13:34 +07:00
XMRig
9a71190ca1 Update llhttp to 9.3.0 2025-06-09 03:02:26 +07:00
XMRig
a7dcbb143e Bump minimum CMake version to 3.10 2025-06-08 23:23:40 +07:00
XMRig
a6a0f80b12 Fix header path. 2025-06-06 14:42:49 +07:00
XMRig
682834b87d Universal fix for NaN and Infinity in JSON output 2025-06-06 14:36:21 +07:00
XMRig
184d6100dc Update rapidjson 2025-06-05 01:22:31 +07:00
XMRig
0c52d789a9 v6.22.4-dev 2025-06-04 18:59:39 +07:00
XMRig
e33334f11a Merge branch 'master' into dev 2025-06-04 18:58:55 +07:00
XMRig
6184224a66 v6.22.3 2025-06-04 18:11:51 +07:00
XMRig
f499155032 Merge branch 'dev' 2025-06-04 18:11:14 +07:00
xmrig
a32b688dcf Update CHANGELOG.md 2025-06-04 01:47:57 +07:00
XMRig
35b334d58a Fixed compile warning. 2025-05-31 01:12:00 +07:00
XMRig
33623492fe Allow run generate_cl.js from the scripts directory. 2025-05-30 01:47:08 +07:00
xmrig
77009bd0d1 Merge pull request #3662 from ybh1998/keccak_f800
Fix type of `keccak_f800`
2025-05-30 01:04:22 +07:00
ybh1998
46572dcb3d Fix type of keccak_f800 2025-05-30 01:57:08 +08:00
xmrig
0d9af3347d Merge pull request #3652 from SChernykh/dev
Fixed HttpsClient::flush logic
2025-04-17 16:12:31 +07:00
SChernykh
d24e13e605 Fixed HttpsClient::flush logic
- Don't write empty buffers
- Don't write if an error was returned
2025-04-17 10:32:14 +02:00
xmrig
36fdfa2694 Merge pull request #3646 from SChernykh/dev
Optimized autoconfig for AMD CPUs with < 2 MB L3 cache per thread
2025-03-22 18:36:09 +07:00
SChernykh
6cfc02d24f Optimized autoconfig for AMD CPUs with < 2 MB L3 cache per thread 2025-03-22 11:34:23 +01:00
XMRig
16ecb8f085 Allow use of the previous CUDA plugin version with a warning. 2024-12-23 23:14:06 +07:00
xmrig
0229c65232 Merge pull request #3605 from SChernykh/dev
CUDA backend: update RandomX dataset when it changes
2024-12-18 22:36:08 +07:00
SChernykh
4a13a8a75c CUDA backend: update RandomX dataset when it changes 2024-12-18 13:45:10 +01:00
XMRig
cd2fd9d7a6 Simplified getting PCI topology for the OpenCL backend. 2024-11-08 13:03:35 +07:00
XMRig
064cd3ef20 Fixed and simplified OpenCL GPU type detection. 2024-11-08 07:09:35 +07:00
XMRig
e8bbd134f9 v6.22.3-dev 2024-11-03 15:06:54 +07:00
XMRig
cf86a1e05c Merge branch 'master' into dev 2024-11-03 15:06:22 +07:00
XMRig
f9e990d0f0 v6.22.2 2024-11-03 14:38:44 +07:00
XMRig
200f23bba7 Merge branch 'dev' 2024-11-03 14:38:00 +07:00
xmrig
4234b20e21 Update CHANGELOG.md 2024-11-03 14:31:17 +07:00
xmrig
c5d8b8265b Merge pull request #3571 from SChernykh/dev
Fix number of threads on the new Intel Core Ultra CPUs
2024-10-25 20:55:35 +07:00
SChernykh
77c14c8362 Fix number of threads on the new Intel Core Ultra CPUs 2024-10-25 13:44:24 +02:00
xmrig
8b03750806 Merge pull request #3569 from SChernykh/dev
Fix: don't use NaN in hashrate calculations
2024-10-23 17:18:36 +07:00
SChernykh
40949f2767 Fix: don't use NaN in hashrate calculations 2024-10-23 11:40:27 +02:00
XMRig
56c447e02a v6.22.2-dev 2024-10-23 13:36:56 +07:00
XMRig
21c206f05d Merge branch 'master' into dev 2024-10-23 13:36:19 +07:00
XMRig
ee65b3d159 v6.22.1 2024-10-23 12:53:06 +07:00
XMRig
1f75d198d8 Merge branch 'dev' 2024-10-23 12:52:16 +07:00
xmrig
5cf2422766 Update CHANGELOG.md 2024-10-22 17:34:07 +07:00
XMRig
a32f9b5b04 Fixed --version output on ARM. 2024-10-21 08:48:58 +07:00
XMRig
8a4792f638 Update hwloc for MSVC. 2024-10-21 08:31:52 +07:00
XMRig
e32731b60b Update deps 2024-10-20 09:49:06 +07:00
xmrig
e1ae367084 Merge pull request #3540 from SChernykh/dev
Detect AMD engineering samples in randomx_boost.sh
2024-08-29 19:50:43 +07:00
SChernykh
bc1c8358c4 Detect AMD engineering samples in randomx_boost.sh 2024-08-29 14:47:30 +02:00
xmrig
e0af8f0c6b Merge pull request #3539 from SChernykh/dev
Added Zen5 to randomx_boost.sh
2024-08-28 18:51:39 +07:00
SChernykh
29f9c8cf4c Added Zen5 to randomx_boost.sh 2024-08-28 13:49:27 +02:00
xmrig
26f4936f6f Merge pull request #3535 from SChernykh/dev
RandomX: tweaks for Zen5
2024-08-20 06:47:30 +07:00
SChernykh
a411ee3565 RandomX: tweaks for Zen5 2024-08-19 21:01:49 +02:00
xmrig
01bd0d48a1 Merge pull request #3534 from SChernykh/dev
Fixed threads auto-config on Zen5
2024-08-17 06:23:49 +07:00
SChernykh
20d555668b Fixed threads auto-config on Zen5 2024-08-16 23:36:22 +02:00
xmrig
56baec762f Merge pull request #3531 from SChernykh/dev
Always reset nonce on RandomX dataset change
2024-08-14 22:16:34 +07:00
SChernykh
17a52fb418 Always reset nonce on RandomX dataset change
Also never get a new job when mining is paused
2024-08-14 16:41:03 +02:00
XMRig
7e4caa8929 Merge remote-tracking branch 'remotes/origin/master' into dev 2024-08-12 03:02:19 +07:00
xmrig
ef14d55aa5 Merge pull request #3529 from eltociear/patch-1
docs: update ghostrider/README.md
2024-08-12 03:01:13 +07:00
XMRig
5776fdcc20 v6.22.1-dev 2024-08-12 02:15:08 +07:00
XMRig
fe0f69031b Merge branch 'master' into dev 2024-08-12 02:14:40 +07:00
Ikko Eltociear Ashimine
e682f89298 docs: update ghostrider/README.md
nubmer -> number
2024-08-12 03:54:26 +09:00
99 changed files with 7805 additions and 10965 deletions

View File

@@ -1,3 +1,20 @@
# v6.22.3
- [#3605](https://github.com/xmrig/xmrig/pull/3605) CUDA backend: added missing RandomX dataset update.
- [#3646](https://github.com/xmrig/xmrig/pull/3646) Optimized auto-config for AMD CPUs with less than 2 MB L3 cache per thread.
- [#3652](https://github.com/xmrig/xmrig/pull/3652) Fixed possible crash when submitting RandomX benchmark.
- [#3662](https://github.com/xmrig/xmrig/pull/3662) Fixed OpenCL kernel compilation error on some platforms.
# 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 # v6.22.0
- [#2411](https://github.com/xmrig/xmrig/pull/2411) Added support for [Yada](https://yadacoin.io/) (`rx/yada` algorithm). - [#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. - [#3492](https://github.com/xmrig/xmrig/pull/3492) Fixed `--background` option on Unix systems.

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.10)
project(xmrig) project(xmrig)
option(WITH_HWLOC "Enable hwloc support" ON) option(WITH_HWLOC "Enable hwloc support" ON)
@@ -240,7 +240,10 @@ add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${HEADE
target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB} ${ARGON2_LIBRARY} ${ETHASH_LIBRARY} ${GHOSTRIDER_LIBRARY}) target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB} ${ARGON2_LIBRARY} ${ETHASH_LIBRARY} ${GHOSTRIDER_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}>) if (NOT ARM_TARGET)
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}>)
endif()
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/scripts/benchmark_1M.cmd" $<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}/scripts/benchmark_1M.cmd" $<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}/scripts/benchmark_10M.cmd" $<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}/scripts/benchmark_10M.cmd" $<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}/scripts/pool_mine_example.cmd" $<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}/scripts/pool_mine_example.cmd" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
@@ -249,5 +252,5 @@ if (WIN32)
endif() endif()
if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_BUILD_TYPE STREQUAL Release AND NOT CMAKE_GENERATOR STREQUAL Xcode) if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_BUILD_TYPE STREQUAL Release AND NOT CMAKE_GENERATOR STREQUAL Xcode)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_PROJECT_NAME}) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} "$<TARGET_FILE:${CMAKE_PROJECT_NAME}>")
endif() endif()

View File

@@ -29,6 +29,8 @@ else()
set(WITH_VAES OFF) set(WITH_VAES OFF)
endif() endif()
add_definitions(-DRAPIDJSON_WRITE_DEFAULT_FLAGS=6) # rapidjson::kWriteNanAndInfFlag | rapidjson::kWriteNanAndInfNullFlag
if (ARM_V8) if (ARM_V8)
set(ARM_TARGET 8) set(ARM_TARGET 8)
elseif (ARM_V7) elseif (ARM_V7)
@@ -36,7 +38,7 @@ elseif (ARM_V7)
endif() endif()
if (NOT ARM_TARGET) if (NOT ARM_TARGET)
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|armv8-a)$") if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64|armv8-a)$")
set(ARM_TARGET 8) set(ARM_TARGET 8)
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7|armv7f|armv7s|armv7k|armv7-a|armv7l|armv7ve)$") elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7|armv7f|armv7s|armv7k|armv7-a|armv7l|armv7ve)$")
set(ARM_TARGET 7) set(ARM_TARGET 7)

View File

@@ -84,7 +84,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
endif() endif()
endif() endif()
if (BUILD_STATIC) if (BUILD_STATIC OR WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
endif() endif()

View File

@@ -20,7 +20,6 @@ else()
endif() endif()
endif() endif()
if (XMRIG_OS_WIN) if (XMRIG_OS_WIN)
add_definitions(-DWIN32 -DXMRIG_OS_WIN) add_definitions(-DWIN32 -DXMRIG_OS_WIN)
elseif(XMRIG_OS_APPLE) elseif(XMRIG_OS_APPLE)

View File

@@ -1,8 +1,8 @@
#!/bin/sh -e #!/bin/sh -e
HWLOC_VERSION_MAJOR="2" HWLOC_VERSION_MAJOR="2"
HWLOC_VERSION_MINOR="10" HWLOC_VERSION_MINOR="12"
HWLOC_VERSION_PATCH="0" 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}"

View File

@@ -1,6 +1,6 @@
#!/bin/sh -e #!/bin/sh -e
OPENSSL_VERSION="3.0.14" OPENSSL_VERSION="3.0.16"
mkdir -p deps mkdir -p deps
mkdir -p deps/include mkdir -p deps/include

View File

@@ -1,6 +1,6 @@
#!/bin/sh -e #!/bin/sh -e
UV_VERSION="1.48.0" UV_VERSION="1.51.0"
mkdir -p deps mkdir -p deps
mkdir -p deps/include mkdir -p deps/include

View File

@@ -6,7 +6,6 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const { text2h, text2h_bundle, addIncludes } = require('./js/opencl'); const { text2h, text2h_bundle, addIncludes } = require('./js/opencl');
const { opencl_minify } = require('./js/opencl_minify'); const { opencl_minify } = require('./js/opencl_minify');
const cwd = process.cwd();
function cn() function cn()
@@ -76,18 +75,24 @@ function kawpow()
fs.writeFileSync('kawpow_dag_cl.h', text2h(kawpow_dag, 'xmrig', 'kawpow_dag_cl')); fs.writeFileSync('kawpow_dag_cl.h', text2h(kawpow_dag, 'xmrig', 'kawpow_dag_cl'));
} }
for (let i = 0; i < 2; i++) {
if (fs.existsSync('src/backend/opencl/cl/OclSource.h')) {
break;
}
process.chdir(path.resolve('src/backend/opencl/cl/cn')); process.chdir('..');
}
process.chdir(path.resolve('src/backend/opencl/cl'));
const cwd = process.cwd();
process.chdir(path.resolve(cwd, 'cn'));
cn(); cn();
cn_r(); cn_r();
process.chdir(cwd); process.chdir(path.resolve(cwd, 'rx'));
process.chdir(path.resolve('src/backend/opencl/cl/rx'));
rx(); rx();
process.chdir(cwd); process.chdir(path.resolve(cwd, 'kawpow'));
process.chdir(path.resolve('src/backend/opencl/cl/kawpow'));
kawpow(); kawpow();

View File

@@ -8,7 +8,7 @@ else
modprobe msr allow_writes=on modprobe msr allow_writes=on
fi fi
if grep -E 'AMD Ryzen|AMD EPYC' /proc/cpuinfo > /dev/null; if grep -E 'AMD Ryzen|AMD EPYC|AuthenticAMD' /proc/cpuinfo > /dev/null;
then then
if grep "cpu family[[:space:]]\{1,\}:[[:space:]]25" /proc/cpuinfo > /dev/null; if grep "cpu family[[:space:]]\{1,\}:[[:space:]]25" /proc/cpuinfo > /dev/null;
then then
@@ -28,6 +28,14 @@ if grep -E 'AMD Ryzen|AMD EPYC' /proc/cpuinfo > /dev/null;
wrmsr -a 0xc001102b 0x2000cc10 wrmsr -a 0xc001102b 0x2000cc10
echo "MSR register values for Zen3 applied" echo "MSR register values for Zen3 applied"
fi 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

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.10)
project(argon2 C) project(argon2 C)
set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD 99)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.10)
project (hwloc C) project (hwloc C)
include_directories(include) include_directories(include)

View File

@@ -1,5 +1,5 @@
Copyright © 2009 CNRS Copyright © 2009 CNRS
Copyright © 2009-2023 Inria. All rights reserved. Copyright © 2009-2024 Inria. All rights reserved.
Copyright © 2009-2013 Université Bordeaux Copyright © 2009-2013 Université Bordeaux
Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
Copyright © 2020 Hewlett Packard Enterprise. All rights reserved. Copyright © 2020 Hewlett Packard Enterprise. All rights reserved.
@@ -17,6 +17,71 @@ bug fixes (and other actions) for each version of hwloc since version
0.9. 0.9.
Version 2.11.2
--------------
* Add missing CPU info attrs on aarch64 on Linux.
* Use ACPI CPPC on Linux to get better information about cpukinds,
at least on AMD CPUs.
* Fix crash when manipulating cpukinds after topology
duplication, thanks to Hadrien Grasland for the report.
* Fix missing input target checks in memattr functions,
thanks to Hadrien Grasland for the report.
* Fix a memory leak when ignoring NUMA distances on FreeBSD.
* Fix build failure on old Linux distributions without accessat().
* Fix non-Windows importing of XML topologies and CPUID dumps exported
on Windows.
* hwloc-calc --cpuset-output-format systemd-dbus-api now allows
to generate AllowedCPUs information for systemd slices.
See the hwloc-calc manpage for examples. Thanks to Pierre Neyron.
* Some fixes in manpage EXAMPLES and split them into subsections.
Version 2.11.1
--------------
* Fix bash completions, thanks Tavis Rudd.
Version 2.11.0
--------------
* API
+ Add HWLOC_MEMBIND_WEIGHTED_INTERLEAVE memory binding policy on
Linux 6.9+. Thanks to Honggyu Kim for the patch.
- weighted_interleave_membind is added to membind support bits.
- The "weighted" policy is added to the hwloc-bind tool.
+ Add hwloc_obj_set_subtype(). Thanks to Hadrien Grasland for the report.
* GPU support
+ Don't hide the GPU NUMA node on NVIDIA Grace Hopper.
+ Get Intel GPU OpenCL device locality.
+ Add bandwidths between subdevices in the LevelZero XeLinkBandwidth
matrix.
+ Fix PCI Gen4+ link speed of NVIDIA GPU obtained from NVML,
thanks to Akram Sbaih for the report.
* Windows support
+ Fix Windows support when UNICODE is enabled, several hwloc features
were missing, thanks to Martin for the report.
+ Fix the enabling of CUDA in Windows CMake build,
Thanks to Moritz Kreutzer for the patch.
+ Fix CUDA/OpenCL test source path in Windows CMake.
* Tools
+ Option --best-memattr may now return multiple nodes. Additional
configuration flags may be given to tweak its behavior.
+ hwloc-info has a new --get-attr option to get a single attribute.
+ hwloc-info now supports "levels", "support" and "topology"
special keywords for backward compatibility for hwloc 3.0.
+ The --taskset command-line option is superseded by the new
--cpuset-output-format which also allows to export as list.
+ hwloc-calc may now import bitmasks described as a list of bits
with the new "--cpuset-input-format list".
* Misc
+ The MemoryTiersNr info attribute in the root object now says how many
memory tiers were built. Thanks to Antoine Morvan for the report.
+ Fix the management of infinite cpusets in the bitmap printf/sscanf
API as well as in command-line tools.
+ Add section "Compiling software on top of hwloc's C API" in the
documentation with examples for GNU Make and CMake,
thanks to Florent Pruvost for the help.
Version 2.10.0 Version 2.10.0
-------------- --------------
* Heterogeneous Memory core improvements * Heterogeneous Memory core improvements

View File

@@ -418,14 +418,8 @@ return 0;
} }
hwloc provides a pkg-config executable to obtain relevant compiler and linker hwloc provides a pkg-config executable to obtain relevant compiler and linker
flags. For example, it can be used thusly to compile applications that utilize flags. See Compiling software on top of hwloc's C API for details on building
the hwloc library (assuming GNU Make): program on top of hwloc's API using GNU Make or CMake.
CFLAGS += $(shell pkg-config --cflags hwloc)
LDLIBS += $(shell pkg-config --libs hwloc)
hwloc-hello: hwloc-hello.c
$(CC) hwloc-hello.c $(CFLAGS) -o hwloc-hello $(LDLIBS)
On a machine 2 processor packages -- each package of which has two processing 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 cores -- the output from running hwloc-hello could be something like the

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2010-2023 Inria. All rights reserved. * Copyright © 2010-2024 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -28,18 +28,18 @@ extern "C" {
/** \brief Matrix of distances between a set of objects. /** \brief Matrix of distances between a set of objects.
* *
* This matrix often contains latencies between NUMA nodes * The most common matrix contains latencies between NUMA nodes
* (as reported in the System Locality Distance Information Table (SLIT) * (as reported in the System Locality Distance Information Table (SLIT)
* in the ACPI specification), which may or may not be physically accurate. * in the ACPI specification), which may or may not be physically accurate.
* It corresponds to the latency for accessing the memory of one node * It corresponds to the latency for accessing the memory of one node
* from a core in another node. * from a core in another node.
* The corresponding kind is ::HWLOC_DISTANCES_KIND_FROM_OS | ::HWLOC_DISTANCES_KIND_FROM_USER. * The corresponding kind is ::HWLOC_DISTANCES_KIND_MEANS_LATENCY | ::HWLOC_DISTANCES_KIND_FROM_USER.
* The name of this distances structure is "NUMALatency". * The name of this distances structure is "NUMALatency".
* Others distance structures include and "XGMIBandwidth", "XGMIHops",
* "XeLinkBandwidth" and "NVLinkBandwidth".
* *
* The matrix may also contain bandwidths between random sets of objects, * The matrix may also contain bandwidths between random sets of objects,
* possibly provided by the user, as specified in the \p kind attribute. * 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. * 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 * However callers are allowed to modify \p kind as well as the contents
@@ -70,11 +70,10 @@ struct hwloc_distances_s {
* The \p kind attribute of struct hwloc_distances_s is a OR'ed set * The \p kind attribute of struct hwloc_distances_s is a OR'ed set
* of kinds. * of kinds.
* *
* A kind of format HWLOC_DISTANCES_KIND_FROM_* specifies where the * Each distance matrix may have only one kind among HWLOC_DISTANCES_KIND_FROM_*
* distance information comes from, if known. * specifying where distance information comes from,
* * and one kind among HWLOC_DISTANCES_KIND_MEANS_* specifying
* A kind of format HWLOC_DISTANCES_KIND_MEANS_* specifies whether * whether values are latencies or bandwidths.
* values are latencies or bandwidths, if applicable.
*/ */
enum hwloc_distances_kind_e { enum hwloc_distances_kind_e {
/** \brief These distances were obtained from the operating system or hardware. /** \brief These distances were obtained from the operating system or hardware.
@@ -357,6 +356,8 @@ typedef void * hwloc_distances_add_handle_t;
* Otherwise, it will be copied internally and may later be freed by the caller. * 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. * \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 * Kind ::HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES will be automatically set
* according to objects having different types in hwloc_distances_add_values(). * according to objects having different types in hwloc_distances_add_values().
* *
@@ -403,7 +404,8 @@ HWLOC_DECLSPEC int hwloc_distances_add_values(hwloc_topology_t topology,
/** \brief Flags for adding a new distances to a topology. */ /** \brief Flags for adding a new distances to a topology. */
enum hwloc_distances_add_flag_e { enum hwloc_distances_add_flag_e {
/** \brief Try to group objects based on the newly provided distance information. /** \brief Try to group objects based on the newly provided distance information.
* This is ignored for distances between objects of different types. * Grouping is only performed when the distances structure contains latencies,
* and when all objects are of the same type.
* \hideinitializer * \hideinitializer
*/ */
HWLOC_DISTANCES_ADD_FLAG_GROUP = (1UL<<0), HWLOC_DISTANCES_ADD_FLAG_GROUP = (1UL<<0),

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2023 Inria. All rights reserved. * Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2012 Université Bordeaux * Copyright © 2009-2012 Université Bordeaux
* Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved. * Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
@@ -946,6 +946,14 @@ enum hwloc_distrib_flags_e {
* *
* \return 0 on success, -1 on error. * \return 0 on success, -1 on error.
* *
* \note On hybrid CPUs (or asymmetric platforms), distribution may be suboptimal
* since the number of cores or PUs inside packages or below caches may vary
* (the top-down recursive partitioning ignores these numbers until reaching their levels).
* Hence it is recommended to distribute only inside a single homogeneous domain.
* For instance on a CPU with energy-efficient E-cores and high-performance P-cores,
* one should distribute separately N tasks on E-cores and M tasks on P-cores
* instead of trying to distribute directly M+N tasks on the entire CPUs.
*
* \note This function requires the \p roots objects to have a CPU set. * \note This function requires the \p roots objects to have a CPU set.
*/ */
static __hwloc_inline int static __hwloc_inline int
@@ -960,7 +968,7 @@ hwloc_distrib(hwloc_topology_t topology,
unsigned given, givenweight; unsigned given, givenweight;
hwloc_cpuset_t *cpusetp = set; hwloc_cpuset_t *cpusetp = set;
if (flags & ~HWLOC_DISTRIB_FLAG_REVERSE) { if (!n || (flags & ~HWLOC_DISTRIB_FLAG_REVERSE)) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2019-2023 Inria. All rights reserved. * Copyright © 2019-2024 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -69,7 +69,10 @@ extern "C" {
* @{ * @{
*/ */
/** \brief Memory node attributes. */ /** \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 { enum hwloc_memattr_id_e {
/** \brief /** \brief
* The \"Capacity\" is returned in bytes (local_memory attribute in objects). * The \"Capacity\" is returned in bytes (local_memory attribute in objects).
@@ -78,6 +81,8 @@ enum hwloc_memattr_id_e {
* *
* No initiator is involved when looking at this attribute. * No initiator is involved when looking at this attribute.
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST. * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST.
*
* Capacity values may not be modified using hwloc_memattr_set_value().
* \hideinitializer * \hideinitializer
*/ */
HWLOC_MEMATTR_ID_CAPACITY = 0, HWLOC_MEMATTR_ID_CAPACITY = 0,
@@ -93,6 +98,8 @@ enum hwloc_memattr_id_e {
* *
* No initiator is involved when looking at this attribute. * No initiator is involved when looking at this attribute.
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST. * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST.
* Locality values may not be modified using hwloc_memattr_set_value().
* \hideinitializer * \hideinitializer
*/ */
HWLOC_MEMATTR_ID_LOCALITY = 1, HWLOC_MEMATTR_ID_LOCALITY = 1,
@@ -173,11 +180,19 @@ enum hwloc_memattr_id_e {
/* TODO persistence? */ /* TODO persistence? */
HWLOC_MEMATTR_ID_MAX /**< \private Sentinel value */ HWLOC_MEMATTR_ID_MAX /**< \private
* Sentinel value for predefined attributes.
* Dynamically registered custom attributes start here.
*/
}; };
/** \brief A memory attribute identifier. /** \brief A memory attribute identifier.
* May be either one of ::hwloc_memattr_id_e or a new id returned by hwloc_memattr_register(). *
* 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; typedef unsigned hwloc_memattr_id_t;
@@ -283,6 +298,10 @@ hwloc_get_local_numanode_objs(hwloc_topology_t topology,
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR), * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
* location \p initiator is ignored and may be \c NULL. * 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. * \p flags must be \c 0 for now.
* *
* \return 0 on success. * \return 0 on success.
@@ -352,6 +371,8 @@ hwloc_memattr_get_best_target(hwloc_topology_t topology,
* The returned initiator should not be modified or freed, * The returned initiator should not be modified or freed,
* it belongs to the topology. * it belongs to the topology.
* *
* \p target_node cannot be \c NULL.
*
* \p flags must be \c 0 for now. * \p flags must be \c 0 for now.
* *
* \return 0 on success. * \return 0 on success.
@@ -362,100 +383,10 @@ hwloc_memattr_get_best_target(hwloc_topology_t topology,
HWLOC_DECLSPEC int HWLOC_DECLSPEC int
hwloc_memattr_get_best_initiator(hwloc_topology_t topology, hwloc_memattr_get_best_initiator(hwloc_topology_t topology,
hwloc_memattr_id_t attribute, hwloc_memattr_id_t attribute,
hwloc_obj_t target, hwloc_obj_t target_node,
unsigned long flags, unsigned long flags,
struct hwloc_location *best_initiator, hwloc_uint64_t *value); struct hwloc_location *best_initiator, hwloc_uint64_t *value);
/** @} */
/** \defgroup hwlocality_memattrs_manage Managing memory attributes
* @{
*/
/** \brief Return the name of a memory attribute.
*
* \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.
*
* \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 specific memory attribute that is not defined in ::hwloc_memattr_id_e.
* Flags are a OR'ed set of ::hwloc_memattr_flag_e. It must contain at least
* one of ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST or ::HWLOC_MEMATTR_FLAG_LOWER_FIRST.
*
* \return 0 on success.
* \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 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);
/** \brief Return the target NUMA nodes that have some values for a given attribute. /** \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 * Return targets for the given attribute in the \p targets array
@@ -519,6 +450,8 @@ hwloc_memattr_get_targets(hwloc_topology_t topology,
* The returned initiators should not be modified or freed, * The returned initiators should not be modified or freed,
* they belong to the topology. * they belong to the topology.
* *
* \p target_node cannot be \c NULL.
*
* \p flags must be \c 0 for now. * \p flags must be \c 0 for now.
* *
* If the attribute does not relate to a specific initiator * If the attribute does not relate to a specific initiator
@@ -538,6 +471,131 @@ hwloc_memattr_get_initiators(hwloc_topology_t topology,
hwloc_obj_t target_node, hwloc_obj_t target_node,
unsigned long flags, unsigned long flags,
unsigned *nr, struct hwloc_location *initiators, hwloc_uint64_t *values); 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 #ifdef __cplusplus

View File

@@ -41,6 +41,15 @@ extern "C" {
*/ */
/* Copyright (c) 2008-2018 The Khronos Group Inc. */ /* 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() */ /* needs "cl_amd_device_attribute_query" device extension, but not strictly required for clGetDeviceInfo() */
#define HWLOC_CL_DEVICE_TOPOLOGY_AMD 0x4037 #define HWLOC_CL_DEVICE_TOPOLOGY_AMD 0x4037
typedef union { typedef union {
@@ -78,9 +87,19 @@ hwloc_opencl_get_device_pci_busid(cl_device_id device,
unsigned *domain, unsigned *bus, unsigned *dev, unsigned *func) unsigned *domain, unsigned *bus, unsigned *dev, unsigned *func)
{ {
hwloc_cl_device_topology_amd amdtopo; hwloc_cl_device_topology_amd amdtopo;
hwloc_cl_device_pci_bus_info_khr khrbusinfo;
cl_uint nvbus, nvslot, nvdomain; cl_uint nvbus, nvslot, nvdomain;
cl_int clret; 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); clret = clGetDeviceInfo(device, HWLOC_CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
if (CL_SUCCESS == clret if (CL_SUCCESS == clret
&& HWLOC_CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD == amdtopo.raw.type) { && HWLOC_CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD == amdtopo.raw.type) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2013-2022 Inria. All rights reserved. * Copyright © 2013-2024 Inria. All rights reserved.
* Copyright © 2016 Cisco Systems, Inc. All rights reserved. * Copyright © 2016 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -645,6 +645,19 @@ HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_parent_by_busid(struct hwloc_to
*/ */
HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func); HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func);
/** @} */
/** \defgroup hwlocality_components_distances Components and Plugins: distances
*
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
*
* @{
*/
/** \brief Handle to a new distances structure during its addition to the topology. */ /** \brief Handle to a new distances structure during its addition to the topology. */
typedef void * hwloc_backend_distances_add_handle_t; typedef void * hwloc_backend_distances_add_handle_t;

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* Copyright © 2010-2022 Inria. All rights reserved. * Copyright © 2010-2024 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -210,6 +210,7 @@ extern "C" {
#define hwloc_obj_get_info_by_name HWLOC_NAME(obj_get_info_by_name) #define hwloc_obj_get_info_by_name HWLOC_NAME(obj_get_info_by_name)
#define hwloc_obj_add_info HWLOC_NAME(obj_add_info) #define hwloc_obj_add_info HWLOC_NAME(obj_add_info)
#define hwloc_obj_set_subtype HWLOC_NAME(obj_set_subtype)
#define HWLOC_CPUBIND_PROCESS HWLOC_NAME_CAPS(CPUBIND_PROCESS) #define HWLOC_CPUBIND_PROCESS HWLOC_NAME_CAPS(CPUBIND_PROCESS)
#define HWLOC_CPUBIND_THREAD HWLOC_NAME_CAPS(CPUBIND_THREAD) #define HWLOC_CPUBIND_THREAD HWLOC_NAME_CAPS(CPUBIND_THREAD)
@@ -232,6 +233,7 @@ extern "C" {
#define HWLOC_MEMBIND_FIRSTTOUCH HWLOC_NAME_CAPS(MEMBIND_FIRSTTOUCH) #define HWLOC_MEMBIND_FIRSTTOUCH HWLOC_NAME_CAPS(MEMBIND_FIRSTTOUCH)
#define HWLOC_MEMBIND_BIND HWLOC_NAME_CAPS(MEMBIND_BIND) #define HWLOC_MEMBIND_BIND HWLOC_NAME_CAPS(MEMBIND_BIND)
#define HWLOC_MEMBIND_INTERLEAVE HWLOC_NAME_CAPS(MEMBIND_INTERLEAVE) #define HWLOC_MEMBIND_INTERLEAVE HWLOC_NAME_CAPS(MEMBIND_INTERLEAVE)
#define HWLOC_MEMBIND_WEIGHTED_INTERLEAVE HWLOC_NAME_CAPS(MEMBIND_WEIGHTED_INTERLEAVE)
#define HWLOC_MEMBIND_NEXTTOUCH HWLOC_NAME_CAPS(MEMBIND_NEXTTOUCH) #define HWLOC_MEMBIND_NEXTTOUCH HWLOC_NAME_CAPS(MEMBIND_NEXTTOUCH)
#define HWLOC_MEMBIND_MIXED HWLOC_NAME_CAPS(MEMBIND_MIXED) #define HWLOC_MEMBIND_MIXED HWLOC_NAME_CAPS(MEMBIND_MIXED)
@@ -560,6 +562,7 @@ extern "C" {
/* opencl.h */ /* opencl.h */
#define hwloc_cl_device_pci_bus_info_khr HWLOC_NAME(cl_device_pci_bus_info_khr)
#define hwloc_cl_device_topology_amd HWLOC_NAME(cl_device_topology_amd) #define hwloc_cl_device_topology_amd HWLOC_NAME(cl_device_topology_amd)
#define hwloc_opencl_get_device_pci_busid HWLOC_NAME(opencl_get_device_pci_ids) #define hwloc_opencl_get_device_pci_busid HWLOC_NAME(opencl_get_device_pci_ids)
#define hwloc_opencl_get_device_cpuset HWLOC_NAME(opencl_get_device_cpuset) #define hwloc_opencl_get_device_cpuset HWLOC_NAME(opencl_get_device_cpuset)
@@ -715,6 +718,8 @@ extern "C" {
#define hwloc__obj_type_is_dcache HWLOC_NAME(_obj_type_is_dcache) #define hwloc__obj_type_is_dcache HWLOC_NAME(_obj_type_is_dcache)
#define hwloc__obj_type_is_icache HWLOC_NAME(_obj_type_is_icache) #define hwloc__obj_type_is_icache HWLOC_NAME(_obj_type_is_icache)
#define hwloc__pci_link_speed HWLOC_NAME(_pci_link_speed)
/* private/cpuid-x86.h */ /* private/cpuid-x86.h */
#define hwloc_have_x86_cpuid HWLOC_NAME(have_x86_cpuid) #define hwloc_have_x86_cpuid HWLOC_NAME(have_x86_cpuid)

View File

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

View File

@@ -11,6 +11,22 @@
#ifndef HWLOC_PRIVATE_CPUID_X86_H #ifndef HWLOC_PRIVATE_CPUID_X86_H
#define HWLOC_PRIVATE_CPUID_X86_H #define HWLOC_PRIVATE_CPUID_X86_H
/* A macro for annotating memory as uninitialized when building with MSAN
* (and otherwise having no effect). See below for why this is used with
* our custom assembly.
*/
#ifdef __has_feature
#define HWLOC_HAS_FEATURE(name) __has_feature(name)
#else
#define HWLOC_HAS_FEATURE(name) 0
#endif
#if HWLOC_HAS_FEATURE(memory_sanitizer) || defined(MEMORY_SANITIZER)
#include <sanitizer/msan_interface.h>
#define HWLOC_ANNOTATE_MEMORY_IS_INITIALIZED(ptr, len) __msan_unpoison(ptr, len)
#else
#define HWLOC_ANNOTATE_MEMORY_IS_INITIALIZED(ptr, len)
#endif
#if (defined HWLOC_X86_32_ARCH) && (!defined HWLOC_HAVE_MSVC_CPUIDEX) #if (defined HWLOC_X86_32_ARCH) && (!defined HWLOC_HAVE_MSVC_CPUIDEX)
static __hwloc_inline int hwloc_have_x86_cpuid(void) static __hwloc_inline int hwloc_have_x86_cpuid(void)
{ {
@@ -71,12 +87,18 @@ static __hwloc_inline void hwloc_x86_cpuid(unsigned *eax, unsigned *ebx, unsigne
"movl %k2,%1\n\t" "movl %k2,%1\n\t"
: "+a" (*eax), "=m" (*ebx), "=&r"(sav_rbx), : "+a" (*eax), "=m" (*ebx), "=&r"(sav_rbx),
"+c" (*ecx), "=&d" (*edx)); "+c" (*ecx), "=&d" (*edx));
/* MSAN does not recognize the effect of the above assembly on the memory operand
* (`"=m"(*ebx)`). This may get improved in MSAN at some point in the future, e.g.
* see https://github.com/llvm/llvm-project/pull/77393. */
HWLOC_ANNOTATE_MEMORY_IS_INITIALIZED(ebx, sizeof *ebx);
#elif defined(HWLOC_X86_32_ARCH) #elif defined(HWLOC_X86_32_ARCH)
__asm__( __asm__(
"mov %%ebx,%1\n\t" "mov %%ebx,%1\n\t"
"cpuid\n\t" "cpuid\n\t"
"xchg %%ebx,%1\n\t" "xchg %%ebx,%1\n\t"
: "+a" (*eax), "=&SD" (*ebx), "+c" (*ecx), "=&d" (*edx)); : "+a" (*eax), "=&SD" (*ebx), "+c" (*ecx), "=&d" (*edx));
/* See above. */
HWLOC_ANNOTATE_MEMORY_IS_INITIALIZED(ebx, sizeof *ebx);
#else #else
#error unknown architecture #error unknown architecture
#endif #endif

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2019 Inria. All rights reserved. * Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2012 Université Bordeaux * Copyright © 2009-2012 Université Bordeaux
* Copyright © 2011 Cisco Systems, Inc. All rights reserved. * Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
@@ -573,4 +573,35 @@ typedef SSIZE_T ssize_t;
# endif # endif
#endif #endif
static __inline float
hwloc__pci_link_speed(unsigned generation, unsigned lanes)
{
float lanespeed;
/*
* These are single-direction bandwidths only.
*
* Gen1 used NRZ with 8/10 encoding.
* PCIe Gen1 = 2.5GT/s signal-rate per lane x 8/10 = 0.25GB/s data-rate per lane
* PCIe Gen2 = 5 GT/s signal-rate per lane x 8/10 = 0.5 GB/s data-rate per lane
* Gen3 switched to NRZ with 128/130 encoding.
* PCIe Gen3 = 8 GT/s signal-rate per lane x 128/130 = 1 GB/s data-rate per lane
* PCIe Gen4 = 16 GT/s signal-rate per lane x 128/130 = 2 GB/s data-rate per lane
* PCIe Gen5 = 32 GT/s signal-rate per lane x 128/130 = 4 GB/s data-rate per lane
* Gen6 switched to PAM with with 242/256 FLIT (242B payload protected by 8B CRC + 6B FEC).
* PCIe Gen6 = 64 GT/s signal-rate per lane x 242/256 = 8 GB/s data-rate per lane
* PCIe Gen7 = 128GT/s signal-rate per lane x 242/256 = 16 GB/s data-rate per lane
*/
/* lanespeed in Gbit/s */
if (generation <= 2)
lanespeed = 2.5f * generation * 0.8f;
else if (generation <= 5)
lanespeed = 8.0f * (1<<(generation-3)) * 128/130;
else
lanespeed = 8.0f * (1<<(generation-3)) * 242/256; /* assume Gen8 will be 256 GT/s and so on */
/* linkspeed in GB/s */
return lanespeed * lanes / 8;
}
#endif /* HWLOC_PRIVATE_MISC_H */ #endif /* HWLOC_PRIVATE_MISC_H */

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2010, 2012 Université Bordeaux * Copyright © 2009-2010, 2012 Université Bordeaux
* Copyright © 2011-2015 Cisco Systems, Inc. All rights reserved. * Copyright © 2011-2015 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
@@ -287,6 +287,7 @@ static __hwloc_inline int hwloc__check_membind_policy(hwloc_membind_policy_t pol
|| policy == HWLOC_MEMBIND_FIRSTTOUCH || policy == HWLOC_MEMBIND_FIRSTTOUCH
|| policy == HWLOC_MEMBIND_BIND || policy == HWLOC_MEMBIND_BIND
|| policy == HWLOC_MEMBIND_INTERLEAVE || policy == HWLOC_MEMBIND_INTERLEAVE
|| policy == HWLOC_MEMBIND_WEIGHTED_INTERLEAVE
|| policy == HWLOC_MEMBIND_NEXTTOUCH) || policy == HWLOC_MEMBIND_NEXTTOUCH)
return 0; return 0;
return -1; return -1;

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux * Copyright © 2009-2011 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
@@ -245,6 +245,7 @@ int hwloc_bitmap_copy(struct hwloc_bitmap_s * dst, const struct hwloc_bitmap_s *
/* Strings always use 32bit groups */ /* Strings always use 32bit groups */
#define HWLOC_PRIxSUBBITMAP "%08lx" #define HWLOC_PRIxSUBBITMAP "%08lx"
#define HWLOC_BITMAP_SUBSTRING_SIZE 32 #define HWLOC_BITMAP_SUBSTRING_SIZE 32
#define HWLOC_BITMAP_SUBSTRING_FULL_VALUE 0xFFFFFFFFUL
#define HWLOC_BITMAP_SUBSTRING_LENGTH (HWLOC_BITMAP_SUBSTRING_SIZE/4) #define HWLOC_BITMAP_SUBSTRING_LENGTH (HWLOC_BITMAP_SUBSTRING_SIZE/4)
#define HWLOC_BITMAP_STRING_PER_LONG (HWLOC_BITS_PER_LONG/HWLOC_BITMAP_SUBSTRING_SIZE) #define HWLOC_BITMAP_STRING_PER_LONG (HWLOC_BITS_PER_LONG/HWLOC_BITMAP_SUBSTRING_SIZE)
@@ -261,6 +262,7 @@ int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const stru
const unsigned long accum_mask = ~0UL; const unsigned long accum_mask = ~0UL;
#else /* HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE */ #else /* HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE */
const unsigned long accum_mask = ((1UL << HWLOC_BITMAP_SUBSTRING_SIZE) - 1) << (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE); const unsigned long accum_mask = ((1UL << HWLOC_BITMAP_SUBSTRING_SIZE) - 1) << (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE);
int merge_with_infinite_prefix = 0;
#endif /* HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE */ #endif /* HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE */
HWLOC__BITMAP_CHECK(set); HWLOC__BITMAP_CHECK(set);
@@ -279,6 +281,9 @@ int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const stru
res = size>0 ? (int)size - 1 : 0; res = size>0 ? (int)size - 1 : 0;
tmp += res; tmp += res;
size -= res; size -= res;
#if HWLOC_BITS_PER_LONG > HWLOC_BITMAP_SUBSTRING_SIZE
merge_with_infinite_prefix = 1;
#endif
} }
i=(int) set->ulongs_count-1; i=(int) set->ulongs_count-1;
@@ -294,16 +299,24 @@ int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const stru
} }
while (i>=0 || accumed) { while (i>=0 || accumed) {
unsigned long value;
/* Refill accumulator */ /* Refill accumulator */
if (!accumed) { if (!accumed) {
accum = set->ulongs[i--]; accum = set->ulongs[i--];
accumed = HWLOC_BITS_PER_LONG; accumed = HWLOC_BITS_PER_LONG;
} }
value = (accum & accum_mask) >> (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE);
if (accum & accum_mask) { #if HWLOC_BITS_PER_LONG > HWLOC_BITMAP_SUBSTRING_SIZE
if (merge_with_infinite_prefix && value == HWLOC_BITMAP_SUBSTRING_FULL_VALUE) {
/* first full subbitmap merged with infinite prefix */
res = 0;
} else
#endif
if (value) {
/* print the whole subset if not empty */ /* print the whole subset if not empty */
res = hwloc_snprintf(tmp, size, needcomma ? ",0x" HWLOC_PRIxSUBBITMAP : "0x" HWLOC_PRIxSUBBITMAP, res = hwloc_snprintf(tmp, size, needcomma ? ",0x" HWLOC_PRIxSUBBITMAP : "0x" HWLOC_PRIxSUBBITMAP, value);
(accum & accum_mask) >> (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE));
needcomma = 1; needcomma = 1;
} else if (i == -1 && accumed == HWLOC_BITMAP_SUBSTRING_SIZE) { } else if (i == -1 && accumed == HWLOC_BITMAP_SUBSTRING_SIZE) {
/* print a single 0 to mark the last subset */ /* print a single 0 to mark the last subset */
@@ -323,6 +336,7 @@ int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const stru
#else #else
accum <<= HWLOC_BITMAP_SUBSTRING_SIZE; accum <<= HWLOC_BITMAP_SUBSTRING_SIZE;
accumed -= HWLOC_BITMAP_SUBSTRING_SIZE; accumed -= HWLOC_BITMAP_SUBSTRING_SIZE;
merge_with_infinite_prefix = 0;
#endif #endif
if (res >= size) if (res >= size)
@@ -362,7 +376,8 @@ int hwloc_bitmap_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restric
{ {
const char * current = string; const char * current = string;
unsigned long accum = 0; unsigned long accum = 0;
int count=0; int count = 0;
int ulongcount;
int infinite = 0; int infinite = 0;
/* count how many substrings there are */ /* count how many substrings there are */
@@ -383,9 +398,20 @@ int hwloc_bitmap_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restric
count--; count--;
} }
if (hwloc_bitmap_reset_by_ulongs(set, (count + HWLOC_BITMAP_STRING_PER_LONG - 1) / HWLOC_BITMAP_STRING_PER_LONG) < 0) ulongcount = (count + HWLOC_BITMAP_STRING_PER_LONG - 1) / HWLOC_BITMAP_STRING_PER_LONG;
if (hwloc_bitmap_reset_by_ulongs(set, ulongcount) < 0)
return -1; return -1;
set->infinite = 0;
set->infinite = 0; /* will be updated later */
#if HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE
if (infinite && (count % HWLOC_BITMAP_STRING_PER_LONG) != 0) {
/* accumulate substrings of the first ulong that are hidden in the infinite prefix */
int i;
for(i = (count % HWLOC_BITMAP_STRING_PER_LONG); i < HWLOC_BITMAP_STRING_PER_LONG; i++)
accum |= (HWLOC_BITMAP_SUBSTRING_FULL_VALUE << (i*HWLOC_BITMAP_SUBSTRING_SIZE));
}
#endif
while (*current != '\0') { while (*current != '\0') {
unsigned long val; unsigned long val;
@@ -544,6 +570,9 @@ int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, co
ssize_t size = buflen; ssize_t size = buflen;
char *tmp = buf; char *tmp = buf;
int res, ret = 0; int res, ret = 0;
#if HWLOC_BITS_PER_LONG == 64
int merge_with_infinite_prefix = 0;
#endif
int started = 0; int started = 0;
int i; int i;
@@ -563,6 +592,9 @@ int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, co
res = size>0 ? (int)size - 1 : 0; res = size>0 ? (int)size - 1 : 0;
tmp += res; tmp += res;
size -= res; size -= res;
#if HWLOC_BITS_PER_LONG == 64
merge_with_infinite_prefix = 1;
#endif
} }
i=set->ulongs_count-1; i=set->ulongs_count-1;
@@ -582,7 +614,11 @@ int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, co
if (started) { if (started) {
/* print the whole subset */ /* print the whole subset */
#if HWLOC_BITS_PER_LONG == 64 #if HWLOC_BITS_PER_LONG == 64
res = hwloc_snprintf(tmp, size, "%016lx", val); if (merge_with_infinite_prefix && (val & 0xffffffff00000000UL) == 0xffffffff00000000UL) {
res = hwloc_snprintf(tmp, size, "%08lx", val & 0xffffffffUL);
} else {
res = hwloc_snprintf(tmp, size, "%016lx", val);
}
#else #else
res = hwloc_snprintf(tmp, size, "%08lx", val); res = hwloc_snprintf(tmp, size, "%08lx", val);
#endif #endif
@@ -599,6 +635,9 @@ int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, co
res = size>0 ? (int)size - 1 : 0; res = size>0 ? (int)size - 1 : 0;
tmp += res; tmp += res;
size -= res; size -= res;
#if HWLOC_BITS_PER_LONG == 64
merge_with_infinite_prefix = 0;
#endif
} }
/* if didn't display anything, display 0x0 */ /* if didn't display anything, display 0x0 */
@@ -679,6 +718,10 @@ int hwloc_bitmap_taskset_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc
goto failed; goto failed;
set->ulongs[count-1] = val; set->ulongs[count-1] = val;
if (infinite && tmpchars != HWLOC_BITS_PER_LONG/4) {
/* infinite prefix with partial substring, fill remaining bits */
set->ulongs[count-1] |= (~0ULL)<<(4*tmpchars);
}
current += tmpchars; current += tmpchars;
chars -= tmpchars; chars -= tmpchars;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2020-2022 Inria. All rights reserved. * Copyright © 2020-2024 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -50,6 +50,7 @@ hwloc_internal_cpukinds_dup(hwloc_topology_t new, hwloc_topology_t old)
return -1; return -1;
new->cpukinds = kinds; new->cpukinds = kinds;
new->nr_cpukinds = old->nr_cpukinds; new->nr_cpukinds = old->nr_cpukinds;
new->nr_cpukinds_allocated = old->nr_cpukinds;
memcpy(kinds, old->cpukinds, old->nr_cpukinds * sizeof(*kinds)); memcpy(kinds, old->cpukinds, old->nr_cpukinds * sizeof(*kinds));
for(i=0;i<old->nr_cpukinds; i++) { for(i=0;i<old->nr_cpukinds; i++) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2010-2022 Inria. All rights reserved. * Copyright © 2010-2024 Inria. All rights reserved.
* Copyright © 2011-2012 Université Bordeaux * Copyright © 2011-2012 Université Bordeaux
* Copyright © 2011 Cisco Systems, Inc. All rights reserved. * Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
@@ -624,8 +624,8 @@ void * hwloc_distances_add_create(hwloc_topology_t topology,
return NULL; return NULL;
} }
if ((kind & ~HWLOC_DISTANCES_KIND_ALL) if ((kind & ~HWLOC_DISTANCES_KIND_ALL)
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_FROM_ALL) != 1 || hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_FROM_ALL) > 1
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_MEANS_ALL) != 1) { || hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_MEANS_ALL) > 1) {
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2020-2023 Inria. All rights reserved. * Copyright © 2020-2024 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -14,13 +14,26 @@
*/ */
static __hwloc_inline static __hwloc_inline
hwloc_uint64_t hwloc__memattr_get_convenience_value(hwloc_memattr_id_t id, int hwloc__memattr_get_convenience_value(hwloc_memattr_id_t id,
hwloc_obj_t node) hwloc_obj_t node,
hwloc_uint64_t *valuep)
{ {
if (id == HWLOC_MEMATTR_ID_CAPACITY) if (id == HWLOC_MEMATTR_ID_CAPACITY) {
return node->attr->numanode.local_memory; if (node->type != HWLOC_OBJ_NUMANODE) {
else if (id == HWLOC_MEMATTR_ID_LOCALITY) errno = EINVAL;
return hwloc_bitmap_weight(node->cpuset); return -1;
}
*valuep = node->attr->numanode.local_memory;
return 0;
}
else if (id == HWLOC_MEMATTR_ID_LOCALITY) {
if (!node->cpuset) {
errno = EINVAL;
return -1;
}
*valuep = hwloc_bitmap_weight(node->cpuset);
return 0;
}
else else
assert(0); assert(0);
return 0; /* shut up the compiler */ return 0; /* shut up the compiler */
@@ -622,7 +635,7 @@ hwloc_memattr_get_targets(hwloc_topology_t topology,
if (found<max) { if (found<max) {
targets[found] = node; targets[found] = node;
if (values) if (values)
values[found] = hwloc__memattr_get_convenience_value(id, node); hwloc__memattr_get_convenience_value(id, node, &values[found]);
} }
found++; found++;
} }
@@ -748,7 +761,7 @@ hwloc_memattr_get_initiators(hwloc_topology_t topology,
struct hwloc_internal_memattr_target_s *imtg; struct hwloc_internal_memattr_target_s *imtg;
unsigned i, max; unsigned i, max;
if (flags) { if (flags || !target_node) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -810,7 +823,7 @@ hwloc_memattr_get_value(hwloc_topology_t topology,
struct hwloc_internal_memattr_s *imattr; struct hwloc_internal_memattr_s *imattr;
struct hwloc_internal_memattr_target_s *imtg; struct hwloc_internal_memattr_target_s *imtg;
if (flags) { if (flags || !target_node) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -823,8 +836,7 @@ hwloc_memattr_get_value(hwloc_topology_t topology,
if (imattr->iflags & HWLOC_IMATTR_FLAG_CONVENIENCE) { if (imattr->iflags & HWLOC_IMATTR_FLAG_CONVENIENCE) {
/* convenience attributes */ /* convenience attributes */
*valuep = hwloc__memattr_get_convenience_value(id, target_node); return hwloc__memattr_get_convenience_value(id, target_node, valuep);
return 0;
} }
/* normal attributes */ /* normal attributes */
@@ -936,7 +948,7 @@ hwloc_memattr_set_value(hwloc_topology_t topology,
{ {
struct hwloc_internal_location_s iloc, *ilocp; struct hwloc_internal_location_s iloc, *ilocp;
if (flags) { if (flags || !target_node) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -1007,10 +1019,10 @@ hwloc_memattr_get_best_target(hwloc_topology_t topology,
/* convenience attributes */ /* convenience attributes */
for(j=0; ; j++) { for(j=0; ; j++) {
hwloc_obj_t node = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, j); hwloc_obj_t node = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, j);
hwloc_uint64_t value; hwloc_uint64_t value = 0;
if (!node) if (!node)
break; break;
value = hwloc__memattr_get_convenience_value(id, node); hwloc__memattr_get_convenience_value(id, node, &value);
hwloc__update_best_target(&best, &best_value, &found, hwloc__update_best_target(&best, &best_value, &found,
node, value, node, value,
imattr->flags & HWLOC_MEMATTR_FLAG_HIGHER_FIRST); imattr->flags & HWLOC_MEMATTR_FLAG_HIGHER_FIRST);
@@ -1093,7 +1105,7 @@ hwloc_memattr_get_best_initiator(hwloc_topology_t topology,
int found; int found;
unsigned i; unsigned i;
if (flags) { if (flags || !target_node) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -1806,6 +1818,12 @@ hwloc__apply_memory_tiers_subtypes(hwloc_topology_t topology,
} }
} }
} }
if (nr_tiers > 1) {
hwloc_obj_t root = hwloc_get_root_obj(topology);
char tmp[20];
snprintf(tmp, sizeof(tmp), "%u", nr_tiers);
hwloc__add_info_nodup(&root->infos, &root->infos_count, "MemoryTiersNr", tmp, 1);
}
} }
int int

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2009-2022 Inria. All rights reserved. * Copyright © 2009-2024 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -886,36 +886,12 @@ hwloc_pcidisc_find_linkspeed(const unsigned char *config,
unsigned offset, float *linkspeed) unsigned offset, float *linkspeed)
{ {
unsigned linksta, speed, width; unsigned linksta, speed, width;
float lanespeed;
memcpy(&linksta, &config[offset + HWLOC_PCI_EXP_LNKSTA], 4); memcpy(&linksta, &config[offset + HWLOC_PCI_EXP_LNKSTA], 4);
speed = linksta & HWLOC_PCI_EXP_LNKSTA_SPEED; /* PCIe generation */ speed = linksta & HWLOC_PCI_EXP_LNKSTA_SPEED; /* PCIe generation */
width = (linksta & HWLOC_PCI_EXP_LNKSTA_WIDTH) >> 4; /* how many lanes */ width = (linksta & HWLOC_PCI_EXP_LNKSTA_WIDTH) >> 4; /* how many lanes */
/*
* These are single-direction bandwidths only.
*
* Gen1 used NRZ with 8/10 encoding.
* PCIe Gen1 = 2.5GT/s signal-rate per lane x 8/10 = 0.25GB/s data-rate per lane
* PCIe Gen2 = 5 GT/s signal-rate per lane x 8/10 = 0.5 GB/s data-rate per lane
* Gen3 switched to NRZ with 128/130 encoding.
* PCIe Gen3 = 8 GT/s signal-rate per lane x 128/130 = 1 GB/s data-rate per lane
* PCIe Gen4 = 16 GT/s signal-rate per lane x 128/130 = 2 GB/s data-rate per lane
* PCIe Gen5 = 32 GT/s signal-rate per lane x 128/130 = 4 GB/s data-rate per lane
* Gen6 switched to PAM with with 242/256 FLIT (242B payload protected by 8B CRC + 6B FEC).
* PCIe Gen6 = 64 GT/s signal-rate per lane x 242/256 = 8 GB/s data-rate per lane
* PCIe Gen7 = 128GT/s signal-rate per lane x 242/256 = 16 GB/s data-rate per lane
*/
/* lanespeed in Gbit/s */ *linkspeed = hwloc__pci_link_speed(speed, width);
if (speed <= 2)
lanespeed = 2.5f * speed * 0.8f;
else if (speed <= 5)
lanespeed = 8.0f * (1<<(speed-3)) * 128/130;
else
lanespeed = 8.0f * (1<<(speed-3)) * 242/256; /* assume Gen8 will be 256 GT/s and so on */
/* linkspeed in GB/s */
*linkspeed = lanespeed * width / 8;
return 0; return 0;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2023 Inria. All rights reserved. * Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2012, 2020 Université Bordeaux * Copyright © 2009-2012, 2020 Université Bordeaux
* Copyright © 2011 Cisco Systems, Inc. All rights reserved. * Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
@@ -220,7 +220,7 @@ static void hwloc_win_get_function_ptrs(void)
#pragma GCC diagnostic ignored "-Wcast-function-type" #pragma GCC diagnostic ignored "-Wcast-function-type"
#endif #endif
kernel32 = LoadLibrary("kernel32.dll"); kernel32 = LoadLibrary(TEXT("kernel32.dll"));
if (kernel32) { if (kernel32) {
GetActiveProcessorGroupCountProc = GetActiveProcessorGroupCountProc =
(PFN_GETACTIVEPROCESSORGROUPCOUNT) GetProcAddress(kernel32, "GetActiveProcessorGroupCount"); (PFN_GETACTIVEPROCESSORGROUPCOUNT) GetProcAddress(kernel32, "GetActiveProcessorGroupCount");
@@ -249,12 +249,12 @@ static void hwloc_win_get_function_ptrs(void)
} }
if (!QueryWorkingSetExProc) { if (!QueryWorkingSetExProc) {
HMODULE psapi = LoadLibrary("psapi.dll"); HMODULE psapi = LoadLibrary(TEXT("psapi.dll"));
if (psapi) if (psapi)
QueryWorkingSetExProc = (PFN_QUERYWORKINGSETEX) GetProcAddress(psapi, "QueryWorkingSetEx"); QueryWorkingSetExProc = (PFN_QUERYWORKINGSETEX) GetProcAddress(psapi, "QueryWorkingSetEx");
} }
ntdll = GetModuleHandle("ntdll"); ntdll = GetModuleHandle(TEXT("ntdll"));
RtlGetVersionProc = (PFN_RTLGETVERSION) GetProcAddress(ntdll, "RtlGetVersion"); RtlGetVersionProc = (PFN_RTLGETVERSION) GetProcAddress(ntdll, "RtlGetVersion");
#if HWLOC_HAVE_GCC_W_CAST_FUNCTION_TYPE #if HWLOC_HAVE_GCC_W_CAST_FUNCTION_TYPE

View File

@@ -1,11 +1,11 @@
/* /*
* Copyright © 2010-2023 Inria. All rights reserved. * Copyright © 2010-2024 Inria. All rights reserved.
* Copyright © 2010-2013 Université Bordeaux * Copyright © 2010-2013 Université Bordeaux
* Copyright © 2010-2011 Cisco Systems, Inc. All rights reserved. * Copyright © 2010-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
* *
* *
* This backend is only used when the operating system does not export * This backend is mostly used when the operating system does not export
* the necessary hardware topology information to user-space applications. * the necessary hardware topology information to user-space applications.
* Currently, FreeBSD and NetBSD only add PUs and then fallback to this * Currently, FreeBSD and NetBSD only add PUs and then fallback to this
* backend for CPU/Cache discovery. * backend for CPU/Cache discovery.
@@ -15,6 +15,7 @@
* on various architectures, without having to use this x86-specific code. * on various architectures, without having to use this x86-specific code.
* But this backend is still used after them to annotate some objects with * But this backend is still used after them to annotate some objects with
* additional details (CPU info in Package, Inclusiveness in Caches). * additional details (CPU info in Package, Inclusiveness in Caches).
* It may also be enabled manually to work-around bugs in native OS discovery.
*/ */
#include "private/autogen/config.h" #include "private/autogen/config.h"
@@ -487,7 +488,7 @@ static void read_amd_cores_legacy(struct procinfo *infos, struct cpuiddump *src_
} }
/* AMD unit/node from CPUID 0x8000001e leaf (topoext) */ /* AMD unit/node from CPUID 0x8000001e leaf (topoext) */
static void read_amd_cores_topoext(struct hwloc_x86_backend_data_s *data, struct procinfo *infos, unsigned long flags, struct cpuiddump *src_cpuiddump) static void read_amd_cores_topoext(struct hwloc_x86_backend_data_s *data, struct procinfo *infos, unsigned long flags __hwloc_attribute_unused, struct cpuiddump *src_cpuiddump)
{ {
unsigned apic_id, nodes_per_proc = 0; unsigned apic_id, nodes_per_proc = 0;
unsigned eax, ebx, ecx, edx; unsigned eax, ebx, ecx, edx;
@@ -496,7 +497,6 @@ static void read_amd_cores_topoext(struct hwloc_x86_backend_data_s *data, struct
cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump); cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump);
infos->apicid = apic_id = eax; infos->apicid = apic_id = eax;
if (flags & HWLOC_X86_DISC_FLAG_TOPOEXT_NUMANODES) {
if (infos->cpufamilynumber == 0x16) { if (infos->cpufamilynumber == 0x16) {
/* ecx is reserved */ /* ecx is reserved */
infos->ids[NODE] = 0; infos->ids[NODE] = 0;
@@ -511,7 +511,6 @@ static void read_amd_cores_topoext(struct hwloc_x86_backend_data_s *data, struct
|| (infos->cpufamilynumber == 0x19 && nodes_per_proc > 1)) { || (infos->cpufamilynumber == 0x19 && nodes_per_proc > 1)) {
hwloc_debug("warning: undefined nodes_per_proc value %u, assuming it means %u\n", nodes_per_proc, nodes_per_proc); hwloc_debug("warning: undefined nodes_per_proc value %u, assuming it means %u\n", nodes_per_proc, nodes_per_proc);
} }
}
if (infos->cpufamilynumber <= 0x16) { /* topoext appeared in 0x15 and compute-units were only used in 0x15 and 0x16 */ if (infos->cpufamilynumber <= 0x16) { /* topoext appeared in 0x15 and compute-units were only used in 0x15 and 0x16 */
unsigned cores_per_unit; unsigned cores_per_unit;
@@ -533,9 +532,9 @@ static void read_amd_cores_topoext(struct hwloc_x86_backend_data_s *data, struct
} }
/* Intel core/thread or even die/module/tile from CPUID 0x0b or 0x1f leaves (v1 and v2 extended topology enumeration) /* Intel core/thread or even die/module/tile from CPUID 0x0b or 0x1f leaves (v1 and v2 extended topology enumeration)
* or AMD complex/ccd from CPUID 0x80000026 (extended CPU topology) * or AMD core/thread or even complex/ccd from CPUID 0x0b or 0x80000026 (extended CPU topology)
*/ */
static void read_extended_topo(struct hwloc_x86_backend_data_s *data, struct procinfo *infos, unsigned leaf, enum cpuid_type cpuid_type, struct cpuiddump *src_cpuiddump) static void read_extended_topo(struct hwloc_x86_backend_data_s *data, struct procinfo *infos, unsigned leaf, enum cpuid_type cpuid_type __hwloc_attribute_unused, struct cpuiddump *src_cpuiddump)
{ {
unsigned level, apic_nextshift, apic_type, apic_id = 0, apic_shift = 0, id; unsigned level, apic_nextshift, apic_type, apic_id = 0, apic_shift = 0, id;
unsigned threadid __hwloc_attribute_unused = 0; /* shut-up compiler */ unsigned threadid __hwloc_attribute_unused = 0; /* shut-up compiler */
@@ -547,20 +546,15 @@ static void read_extended_topo(struct hwloc_x86_backend_data_s *data, struct pro
eax = leaf; eax = leaf;
cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump); cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump);
/* Intel specifies that the 0x0b/0x1f loop should stop when we get "invalid domain" (0 in ecx[8:15]) /* Intel specifies that the 0x0b/0x1f loop should stop when we get "invalid domain" (0 in ecx[8:15])
* (if so, we also get 0 in eax/ebx for invalid subleaves). * (if so, we also get 0 in eax/ebx for invalid subleaves). Zhaoxin implements this too.
* However AMD rather says that the 0x80000026/0x0b loop should stop when we get "no thread at this level" (0 in ebx[0:15]). * However AMD rather says that the 0x80000026/0x0b loop should stop when we get "no thread at this level" (0 in ebx[0:15]).
* Zhaoxin follows the Intel specs but also returns "no thread at this level" for the last *valid* level (at least on KH-4000). *
* From the Linux kernel code, it's very likely that AMD also returns "invalid domain" * Linux kernel <= 6.8 used "invalid domain" for both Intel and AMD (in detect_extended_topology())
* (because detect_extended_topology() uses that for all x86 CPUs) * but x86 discovery revamp in 6.9 now properly checks both Intel and AMD conditions (in topo_subleaf()).
* but keep with the official doc until AMD can clarify that (see #593). * So let's assume we are allowed to break-out once one of the Intel+AMD conditions is met.
*/ */
if (cpuid_type == amd) { if (!(ebx & 0xffff) || !(ecx & 0xff00))
if (!(ebx & 0xffff)) break;
break;
} else {
if (!(ecx & 0xff00))
break;
}
apic_packageshift = eax & 0x1f; apic_packageshift = eax & 0x1f;
} }
@@ -572,13 +566,8 @@ static void read_extended_topo(struct hwloc_x86_backend_data_s *data, struct pro
ecx = level; ecx = level;
eax = leaf; eax = leaf;
cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump); cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump);
if (cpuid_type == amd) { if (!(ebx & 0xffff) || !(ecx & 0xff00))
if (!(ebx & 0xffff)) break;
break;
} else {
if (!(ecx & 0xff00))
break;
}
apic_nextshift = eax & 0x1f; apic_nextshift = eax & 0x1f;
apic_type = (ecx & 0xff00) >> 8; apic_type = (ecx & 0xff00) >> 8;
apic_id = edx; apic_id = edx;
@@ -1825,7 +1814,7 @@ hwloc_x86_check_cpuiddump_input(const char *src_cpuiddump_path, hwloc_bitmap_t s
goto out_with_path; goto out_with_path;
} }
fclose(file); fclose(file);
if (strcmp(line, "Architecture: x86\n")) { if (strncmp(line, "Architecture: x86", 17)) {
fprintf(stderr, "hwloc/x86: Found non-x86 dumped cpuid summary in %s: %s\n", path, line); fprintf(stderr, "hwloc/x86: Found non-x86 dumped cpuid summary in %s: %s\n", path, line);
goto out_with_path; goto out_with_path;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux * Copyright © 2009-2011 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
@@ -41,7 +41,7 @@ typedef struct hwloc__nolibxml_import_state_data_s {
static char * static char *
hwloc__nolibxml_import_ignore_spaces(char *buffer) hwloc__nolibxml_import_ignore_spaces(char *buffer)
{ {
return buffer + strspn(buffer, " \t\n"); return buffer + strspn(buffer, " \t\n\r");
} }
static int static int

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2023 Inria. All rights reserved. * Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2011, 2020 Université Bordeaux * Copyright © 2009-2011, 2020 Université Bordeaux
* Copyright © 2009-2018 Cisco Systems, Inc. All rights reserved. * Copyright © 2009-2018 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
@@ -872,6 +872,10 @@ hwloc__xml_import_object(hwloc_topology_t topology,
/* deal with possible future type */ /* deal with possible future type */
obj->type = HWLOC_OBJ_GROUP; obj->type = HWLOC_OBJ_GROUP;
obj->attr->group.kind = HWLOC_GROUP_KIND_INTEL_MODULE; obj->attr->group.kind = HWLOC_GROUP_KIND_INTEL_MODULE;
} else if (!strcasecmp(attrvalue, "Cluster")) {
/* deal with possible future type */
obj->type = HWLOC_OBJ_GROUP;
obj->attr->group.kind = HWLOC_GROUP_KIND_LINUX_CLUSTER;
} else if (!strcasecmp(attrvalue, "MemCache")) { } else if (!strcasecmp(attrvalue, "MemCache")) {
/* ignore possible future type */ /* ignore possible future type */
obj->type = _HWLOC_OBJ_FUTURE; obj->type = _HWLOC_OBJ_FUTURE;
@@ -1344,7 +1348,7 @@ hwloc__xml_v2import_support(hwloc_topology_t topology,
HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_support) == 4*sizeof(void*)); HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_support) == 4*sizeof(void*));
HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_discovery_support) == 6); HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_discovery_support) == 6);
HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_cpubind_support) == 11); HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_cpubind_support) == 11);
HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_membind_support) == 15); HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_membind_support) == 16);
HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_misc_support) == 1); HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_misc_support) == 1);
#endif #endif
@@ -1378,6 +1382,7 @@ hwloc__xml_v2import_support(hwloc_topology_t topology,
else DO(membind,firsttouch_membind); else DO(membind,firsttouch_membind);
else DO(membind,bind_membind); else DO(membind,bind_membind);
else DO(membind,interleave_membind); else DO(membind,interleave_membind);
else DO(membind,weighted_interleave_membind);
else DO(membind,nexttouch_membind); else DO(membind,nexttouch_membind);
else DO(membind,migrate_membind); else DO(membind,migrate_membind);
else DO(membind,get_area_memlocation); else DO(membind,get_area_memlocation);
@@ -1436,6 +1441,10 @@ hwloc__xml_v2import_distances(hwloc_topology_t topology,
} }
else if (!strcmp(attrname, "kind")) { else if (!strcmp(attrname, "kind")) {
kind = strtoul(attrvalue, NULL, 10); kind = strtoul(attrvalue, NULL, 10);
/* forward compat with "HOPS" kind in v3 */
if (kind & (1UL<<5))
/* hops becomes latency */
kind = (kind & ~(1UL<<5)) | HWLOC_DISTANCES_KIND_MEANS_LATENCY;
} }
else if (!strcmp(attrname, "name")) { else if (!strcmp(attrname, "name")) {
name = attrvalue; name = attrvalue;
@@ -3087,7 +3096,7 @@ hwloc__xml_v2export_support(hwloc__xml_export_state_t parentstate, hwloc_topolog
HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_support) == 4*sizeof(void*)); HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_support) == 4*sizeof(void*));
HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_discovery_support) == 6); HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_discovery_support) == 6);
HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_cpubind_support) == 11); HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_cpubind_support) == 11);
HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_membind_support) == 15); HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_membind_support) == 16);
HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_misc_support) == 1); HWLOC_BUILD_ASSERT(sizeof(struct hwloc_topology_misc_support) == 1);
#endif #endif
@@ -3132,6 +3141,7 @@ hwloc__xml_v2export_support(hwloc__xml_export_state_t parentstate, hwloc_topolog
DO(membind,firsttouch_membind); DO(membind,firsttouch_membind);
DO(membind,bind_membind); DO(membind,bind_membind);
DO(membind,interleave_membind); DO(membind,interleave_membind);
DO(membind,weighted_interleave_membind);
DO(membind,nexttouch_membind); DO(membind,nexttouch_membind);
DO(membind,migrate_membind); DO(membind,migrate_membind);
DO(membind,get_area_memlocation); DO(membind,get_area_memlocation);

View File

@@ -465,6 +465,20 @@ hwloc_debug_print_objects(int indent __hwloc_attribute_unused, hwloc_obj_t obj)
#define hwloc_debug_print_objects(indent, obj) do { /* nothing */ } while (0) #define hwloc_debug_print_objects(indent, obj) do { /* nothing */ } while (0)
#endif /* !HWLOC_DEBUG */ #endif /* !HWLOC_DEBUG */
int hwloc_obj_set_subtype(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj, const char *subtype)
{
char *new = NULL;
if (subtype) {
new = strdup(subtype);
if (!new)
return -1;
}
if (obj->subtype)
free(obj->subtype);
obj->subtype = new;
return 0;
}
void hwloc__free_infos(struct hwloc_info_s *infos, unsigned count) void hwloc__free_infos(struct hwloc_info_s *infos, unsigned count)
{ {
unsigned i; unsigned i;

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.10)
project (ethash C) project (ethash C)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os")

View File

@@ -4,7 +4,7 @@
#include "llhttp.h" #include "llhttp.h"
#define CALLBACK_MAYBE(PARSER, NAME, ...) \ #define CALLBACK_MAYBE(PARSER, NAME) \
do { \ do { \
const llhttp_settings_t* settings; \ const llhttp_settings_t* settings; \
settings = (const llhttp_settings_t*) (PARSER)->settings; \ settings = (const llhttp_settings_t*) (PARSER)->settings; \
@@ -12,7 +12,22 @@
err = 0; \ err = 0; \
break; \ break; \
} \ } \
err = settings->NAME(__VA_ARGS__); \ err = settings->NAME((PARSER)); \
} while (0)
#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \
do { \
const llhttp_settings_t* settings; \
settings = (const llhttp_settings_t*) (PARSER)->settings; \
if (settings == NULL || settings->NAME == NULL) { \
err = 0; \
break; \
} \
err = settings->NAME((PARSER), (START), (LEN)); \
if (err == -1) { \
err = HPE_USER; \
llhttp_set_error_reason((PARSER), "Span callback error in " #NAME); \
} \
} while (0) } while (0)
void llhttp_init(llhttp_t* parser, llhttp_type_t type, void llhttp_init(llhttp_t* parser, llhttp_type_t type,
@@ -31,21 +46,25 @@ extern int wasm_on_url(llhttp_t* p, const char* at, size_t length);
extern int wasm_on_status(llhttp_t* p, const char* at, size_t length); extern int wasm_on_status(llhttp_t* p, const char* at, size_t length);
extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length); extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length);
extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length); extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length);
extern int wasm_on_headers_complete(llhttp_t * p); extern int wasm_on_headers_complete(llhttp_t * p, int status_code,
uint8_t upgrade, int should_keep_alive);
extern int wasm_on_body(llhttp_t* p, const char* at, size_t length); extern int wasm_on_body(llhttp_t* p, const char* at, size_t length);
extern int wasm_on_message_complete(llhttp_t * p); extern int wasm_on_message_complete(llhttp_t * p);
static int wasm_on_headers_complete_wrap(llhttp_t* p) {
return wasm_on_headers_complete(p, p->status_code, p->upgrade,
llhttp_should_keep_alive(p));
}
const llhttp_settings_t wasm_settings = { const llhttp_settings_t wasm_settings = {
wasm_on_message_begin, .on_message_begin = wasm_on_message_begin,
wasm_on_url, .on_url = wasm_on_url,
wasm_on_status, .on_status = wasm_on_status,
wasm_on_header_field, .on_header_field = wasm_on_header_field,
wasm_on_header_value, .on_header_value = wasm_on_header_value,
wasm_on_headers_complete, .on_headers_complete = wasm_on_headers_complete_wrap,
wasm_on_body, .on_body = wasm_on_body,
wasm_on_message_complete, .on_message_complete = wasm_on_message_complete,
NULL,
NULL,
}; };
@@ -59,6 +78,8 @@ void llhttp_free(llhttp_t* parser) {
free(parser); free(parser);
} }
#endif // defined(__wasm__)
/* Some getters required to get stuff from the parser */ /* Some getters required to get stuff from the parser */
uint8_t llhttp_get_type(llhttp_t* parser) { uint8_t llhttp_get_type(llhttp_t* parser) {
@@ -85,14 +106,12 @@ uint8_t llhttp_get_upgrade(llhttp_t* parser) {
return parser->upgrade; return parser->upgrade;
} }
#endif // defined(__wasm__)
void llhttp_reset(llhttp_t* parser) { void llhttp_reset(llhttp_t* parser) {
llhttp_type_t type = parser->type; llhttp_type_t type = parser->type;
const llhttp_settings_t* settings = parser->settings; const llhttp_settings_t* settings = parser->settings;
void* data = parser->data; void* data = parser->data;
uint8_t lenient_flags = parser->lenient_flags; uint16_t lenient_flags = parser->lenient_flags;
llhttp__internal_init(parser); llhttp__internal_init(parser);
@@ -123,7 +142,7 @@ llhttp_errno_t llhttp_finish(llhttp_t* parser) {
switch (parser->finish) { switch (parser->finish) {
case HTTP_FINISH_SAFE_WITH_CB: case HTTP_FINISH_SAFE_WITH_CB:
CALLBACK_MAYBE(parser, on_message_complete, parser); CALLBACK_MAYBE(parser, on_message_complete);
if (err != HPE_OK) return err; if (err != HPE_OK) return err;
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -199,12 +218,21 @@ const char* llhttp_errno_name(llhttp_errno_t err) {
const char* llhttp_method_name(llhttp_method_t method) { const char* llhttp_method_name(llhttp_method_t method) {
#define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING; #define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING;
switch (method) { switch (method) {
HTTP_METHOD_MAP(HTTP_METHOD_GEN) HTTP_ALL_METHOD_MAP(HTTP_METHOD_GEN)
default: abort(); default: abort();
} }
#undef HTTP_METHOD_GEN #undef HTTP_METHOD_GEN
} }
const char* llhttp_status_name(llhttp_status_t status) {
#define HTTP_STATUS_GEN(NUM, NAME, STRING) case HTTP_STATUS_##NAME: return #STRING;
switch (status) {
HTTP_STATUS_MAP(HTTP_STATUS_GEN)
default: abort();
}
#undef HTTP_STATUS_GEN
}
void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) { void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) {
if (enabled) { if (enabled) {
@@ -232,103 +260,236 @@ void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) {
} }
} }
void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_TRANSFER_ENCODING;
} else {
parser->lenient_flags &= ~LENIENT_TRANSFER_ENCODING;
}
}
void llhttp_set_lenient_version(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_VERSION;
} else {
parser->lenient_flags &= ~LENIENT_VERSION;
}
}
void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_DATA_AFTER_CLOSE;
} else {
parser->lenient_flags &= ~LENIENT_DATA_AFTER_CLOSE;
}
}
void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_OPTIONAL_LF_AFTER_CR;
} else {
parser->lenient_flags &= ~LENIENT_OPTIONAL_LF_AFTER_CR;
}
}
void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_OPTIONAL_CRLF_AFTER_CHUNK;
} else {
parser->lenient_flags &= ~LENIENT_OPTIONAL_CRLF_AFTER_CHUNK;
}
}
void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_OPTIONAL_CR_BEFORE_LF;
} else {
parser->lenient_flags &= ~LENIENT_OPTIONAL_CR_BEFORE_LF;
}
}
void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_SPACES_AFTER_CHUNK_SIZE;
} else {
parser->lenient_flags &= ~LENIENT_SPACES_AFTER_CHUNK_SIZE;
}
}
/* Callbacks */ /* Callbacks */
int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_message_begin, s); CALLBACK_MAYBE(s, on_message_begin);
return err;
}
int llhttp__on_protocol(llhttp_t* s, const char* p, const char* endp) {
int err;
SPAN_CALLBACK_MAYBE(s, on_protocol, p, endp - p);
return err;
}
int llhttp__on_protocol_complete(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_protocol_complete);
return err; return err;
} }
int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_url, s, p, endp - p); SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p);
return err; return err;
} }
int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_url_complete, s); CALLBACK_MAYBE(s, on_url_complete);
return err; return err;
} }
int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_status, s, p, endp - p); SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p);
return err; return err;
} }
int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_status_complete, s); CALLBACK_MAYBE(s, on_status_complete);
return err;
}
int llhttp__on_method(llhttp_t* s, const char* p, const char* endp) {
int err;
SPAN_CALLBACK_MAYBE(s, on_method, p, endp - p);
return err;
}
int llhttp__on_method_complete(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_method_complete);
return err;
}
int llhttp__on_version(llhttp_t* s, const char* p, const char* endp) {
int err;
SPAN_CALLBACK_MAYBE(s, on_version, p, endp - p);
return err;
}
int llhttp__on_version_complete(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_version_complete);
return err; return err;
} }
int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_header_field, s, p, endp - p); SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p);
return err; return err;
} }
int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_header_field_complete, s); CALLBACK_MAYBE(s, on_header_field_complete);
return err; return err;
} }
int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_header_value, s, p, endp - p); SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p);
return err; return err;
} }
int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_header_value_complete, s); CALLBACK_MAYBE(s, on_header_value_complete);
return err; return err;
} }
int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_headers_complete, s); CALLBACK_MAYBE(s, on_headers_complete);
return err; return err;
} }
int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_message_complete, s); CALLBACK_MAYBE(s, on_message_complete);
return err; return err;
} }
int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_body, s, p, endp - p); SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p);
return err; return err;
} }
int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_chunk_header, s); CALLBACK_MAYBE(s, on_chunk_header);
return err;
}
int llhttp__on_chunk_extension_name(llhttp_t* s, const char* p, const char* endp) {
int err;
SPAN_CALLBACK_MAYBE(s, on_chunk_extension_name, p, endp - p);
return err;
}
int llhttp__on_chunk_extension_name_complete(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_chunk_extension_name_complete);
return err;
}
int llhttp__on_chunk_extension_value(llhttp_t* s, const char* p, const char* endp) {
int err;
SPAN_CALLBACK_MAYBE(s, on_chunk_extension_value, p, endp - p);
return err;
}
int llhttp__on_chunk_extension_value_complete(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_chunk_extension_value_complete);
return err; return err;
} }
int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) { int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
int err; int err;
CALLBACK_MAYBE(s, on_chunk_complete, s); CALLBACK_MAYBE(s, on_chunk_complete);
return err;
}
int llhttp__on_reset(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_reset);
return err; return err;
} }

View File

@@ -1,253 +0,0 @@
#ifndef INCLUDE_LLHTTP_API_H_
#define INCLUDE_LLHTTP_API_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#if defined(__wasm__)
#define LLHTTP_EXPORT __attribute__((visibility("default")))
#else
#define LLHTTP_EXPORT
#endif
typedef llhttp__internal_t llhttp_t;
typedef struct llhttp_settings_s llhttp_settings_t;
typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length);
typedef int (*llhttp_cb)(llhttp_t*);
struct llhttp_settings_s {
/* Possible return values 0, -1, `HPE_PAUSED` */
llhttp_cb on_message_begin;
llhttp_data_cb on_url;
llhttp_data_cb on_status;
llhttp_data_cb on_header_field;
llhttp_data_cb on_header_value;
/* Possible return values:
* 0 - Proceed normally
* 1 - Assume that request/response has no body, and proceed to parsing the
* next message
* 2 - Assume absence of body (as above) and make `llhttp_execute()` return
* `HPE_PAUSED_UPGRADE`
* -1 - Error
* `HPE_PAUSED`
*/
llhttp_cb on_headers_complete;
llhttp_data_cb on_body;
/* Possible return values 0, -1, `HPE_PAUSED` */
llhttp_cb on_message_complete;
/* When on_chunk_header is called, the current chunk length is stored
* in parser->content_length.
* Possible return values 0, -1, `HPE_PAUSED`
*/
llhttp_cb on_chunk_header;
llhttp_cb on_chunk_complete;
llhttp_cb on_url_complete;
llhttp_cb on_status_complete;
llhttp_cb on_header_field_complete;
llhttp_cb on_header_value_complete;
};
/* Initialize the parser with specific type and user settings.
*
* NOTE: lifetime of `settings` has to be at least the same as the lifetime of
* the `parser` here. In practice, `settings` has to be either a static
* variable or be allocated with `malloc`, `new`, etc.
*/
LLHTTP_EXPORT
void llhttp_init(llhttp_t* parser, llhttp_type_t type,
const llhttp_settings_t* settings);
#if defined(__wasm__)
LLHTTP_EXPORT
llhttp_t* llhttp_alloc(llhttp_type_t type);
LLHTTP_EXPORT
void llhttp_free(llhttp_t* parser);
LLHTTP_EXPORT
uint8_t llhttp_get_type(llhttp_t* parser);
LLHTTP_EXPORT
uint8_t llhttp_get_http_major(llhttp_t* parser);
LLHTTP_EXPORT
uint8_t llhttp_get_http_minor(llhttp_t* parser);
LLHTTP_EXPORT
uint8_t llhttp_get_method(llhttp_t* parser);
LLHTTP_EXPORT
int llhttp_get_status_code(llhttp_t* parser);
LLHTTP_EXPORT
uint8_t llhttp_get_upgrade(llhttp_t* parser);
#endif // defined(__wasm__)
/* Reset an already initialized parser back to the start state, preserving the
* existing parser type, callback settings, user data, and lenient flags.
*/
LLHTTP_EXPORT
void llhttp_reset(llhttp_t* parser);
/* Initialize the settings object */
LLHTTP_EXPORT
void llhttp_settings_init(llhttp_settings_t* settings);
/* Parse full or partial request/response, invoking user callbacks along the
* way.
*
* If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing
* interrupts, and such errno is returned from `llhttp_execute()`. If
* `HPE_PAUSED` was used as a errno, the execution can be resumed with
* `llhttp_resume()` call.
*
* In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE`
* is returned after fully parsing the request/response. If the user wishes to
* continue parsing, they need to invoke `llhttp_resume_after_upgrade()`.
*
* NOTE: if this function ever returns a non-pause type error, it will continue
* to return the same error upon each successive call up until `llhttp_init()`
* is called.
*/
LLHTTP_EXPORT
llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len);
/* This method should be called when the other side has no further bytes to
* send (e.g. shutdown of readable side of the TCP connection.)
*
* Requests without `Content-Length` and other messages might require treating
* all incoming bytes as the part of the body, up to the last byte of the
* connection. This method will invoke `on_message_complete()` callback if the
* request was terminated safely. Otherwise a error code would be returned.
*/
LLHTTP_EXPORT
llhttp_errno_t llhttp_finish(llhttp_t* parser);
/* Returns `1` if the incoming message is parsed until the last byte, and has
* to be completed by calling `llhttp_finish()` on EOF
*/
LLHTTP_EXPORT
int llhttp_message_needs_eof(const llhttp_t* parser);
/* Returns `1` if there might be any other messages following the last that was
* successfully parsed.
*/
LLHTTP_EXPORT
int llhttp_should_keep_alive(const llhttp_t* parser);
/* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set
* appropriate error reason.
*
* Important: do not call this from user callbacks! User callbacks must return
* `HPE_PAUSED` if pausing is required.
*/
LLHTTP_EXPORT
void llhttp_pause(llhttp_t* parser);
/* Might be called to resume the execution after the pause in user's callback.
* See `llhttp_execute()` above for details.
*
* Call this only if `llhttp_execute()` returns `HPE_PAUSED`.
*/
LLHTTP_EXPORT
void llhttp_resume(llhttp_t* parser);
/* Might be called to resume the execution after the pause in user's callback.
* See `llhttp_execute()` above for details.
*
* Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE`
*/
LLHTTP_EXPORT
void llhttp_resume_after_upgrade(llhttp_t* parser);
/* Returns the latest return error */
LLHTTP_EXPORT
llhttp_errno_t llhttp_get_errno(const llhttp_t* parser);
/* Returns the verbal explanation of the latest returned error.
*
* Note: User callback should set error reason when returning the error. See
* `llhttp_set_error_reason()` for details.
*/
LLHTTP_EXPORT
const char* llhttp_get_error_reason(const llhttp_t* parser);
/* Assign verbal description to the returned error. Must be called in user
* callbacks right before returning the errno.
*
* Note: `HPE_USER` error code might be useful in user callbacks.
*/
LLHTTP_EXPORT
void llhttp_set_error_reason(llhttp_t* parser, const char* reason);
/* Returns the pointer to the last parsed byte before the returned error. The
* pointer is relative to the `data` argument of `llhttp_execute()`.
*
* Note: this method might be useful for counting the number of parsed bytes.
*/
LLHTTP_EXPORT
const char* llhttp_get_error_pos(const llhttp_t* parser);
/* Returns textual name of error code */
LLHTTP_EXPORT
const char* llhttp_errno_name(llhttp_errno_t err);
/* Returns textual name of HTTP method */
LLHTTP_EXPORT
const char* llhttp_method_name(llhttp_method_t method);
/* Enables/disables lenient header value parsing (disabled by default).
*
* Lenient parsing disables header value token checks, extending llhttp's
* protocol support to highly non-compliant clients/server. No
* `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when
* lenient parsing is "on".
*
* **(USE AT YOUR OWN RISK)**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_headers(llhttp_t* parser, int enabled);
/* Enables/disables lenient handling of conflicting `Transfer-Encoding` and
* `Content-Length` headers (disabled by default).
*
* Normally `llhttp` would error when `Transfer-Encoding` is present in
* conjunction with `Content-Length`. This error is important to prevent HTTP
* request smuggling, but may be less desirable for small number of cases
* involving legacy servers.
*
* **(USE AT YOUR OWN RISK)**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);
/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0
* requests responses.
*
* Normally `llhttp` would error on (in strict mode) or discard (in loose mode)
* the HTTP request/response after the request/response with `Connection: close`
* and `Content-Length`. This is important to prevent cache poisoning attacks,
* but might interact badly with outdated and insecure clients. With this flag
* the extra request/response will be parsed normally.
*
* **(USE AT YOUR OWN RISK)**
*/
void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* INCLUDE_LLHTTP_API_H_ */

View File

@@ -39,20 +39,41 @@ int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
int hasBody; int hasBody;
hasBody = parser->flags & F_CHUNKED || parser->content_length > 0; hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;
if (parser->upgrade && (parser->method == HTTP_CONNECT || if (
(parser->flags & F_SKIPBODY) || !hasBody)) { (parser->upgrade && (parser->method == HTTP_CONNECT ||
(parser->flags & F_SKIPBODY) || !hasBody)) ||
/* See RFC 2616 section 4.4 - 1xx e.g. Continue */
(parser->type == HTTP_RESPONSE && parser->status_code == 101)
) {
/* Exit, the rest of the message is in a different protocol. */ /* Exit, the rest of the message is in a different protocol. */
return 1; return 1;
} }
if (parser->flags & F_SKIPBODY) { if (parser->type == HTTP_RESPONSE && parser->status_code == 100) {
/* No body, restart as the message is complete */
return 0;
}
/* See RFC 2616 section 4.4 */
if (
parser->flags & F_SKIPBODY || /* response to a HEAD request */
(
parser->type == HTTP_RESPONSE && (
parser->status_code == 102 || /* Processing */
parser->status_code == 103 || /* Early Hints */
parser->status_code == 204 || /* No Content */
parser->status_code == 304 /* Not Modified */
)
)
) {
return 0; return 0;
} else if (parser->flags & F_CHUNKED) { } else if (parser->flags & F_CHUNKED) {
/* chunked encoding - ignore Content-Length header, prepare for a chunk */ /* chunked encoding - ignore Content-Length header, prepare for a chunk */
return 2; return 2;
} else if (parser->flags & F_TRANSFER_ENCODING) { } else if (parser->flags & F_TRANSFER_ENCODING) {
if (parser->type == HTTP_REQUEST && if (parser->type == HTTP_REQUEST &&
(parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0) { (parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0 &&
(parser->lenient_flags & LENIENT_TRANSFER_ENCODING) == 0) {
/* RFC 7230 3.3.3 */ /* RFC 7230 3.3.3 */
/* If a Transfer-Encoding header field /* If a Transfer-Encoding header field

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,11 @@
#ifndef INCLUDE_LLHTTP_H_ #ifndef INCLUDE_LLHTTP_H_
#define INCLUDE_LLHTTP_H_ #define INCLUDE_LLHTTP_H_
#define LLHTTP_VERSION_MAJOR 5 #define LLHTTP_VERSION_MAJOR 9
#define LLHTTP_VERSION_MINOR 1 #define LLHTTP_VERSION_MINOR 3
#define LLHTTP_VERSION_PATCH 0 #define LLHTTP_VERSION_PATCH 0
#ifndef LLHTTP_STRICT_MODE
# define LLHTTP_STRICT_MODE 0
#endif
#ifndef INCLUDE_LLHTTP_ITSELF_H_ #ifndef INCLUDE_LLHTTP_ITSELF_H_
#define INCLUDE_LLHTTP_ITSELF_H_ #define INCLUDE_LLHTTP_ITSELF_H_
#ifdef __cplusplus #ifdef __cplusplus
@@ -33,11 +30,12 @@ struct llhttp__internal_s {
uint8_t http_major; uint8_t http_major;
uint8_t http_minor; uint8_t http_minor;
uint8_t header_state; uint8_t header_state;
uint8_t lenient_flags; uint16_t lenient_flags;
uint8_t upgrade; uint8_t upgrade;
uint8_t finish; uint8_t finish;
uint16_t flags; uint16_t flags;
uint16_t status_code; uint16_t status_code;
uint8_t initial_message_completed;
void* settings; void* settings;
}; };
@@ -49,6 +47,7 @@ int llhttp__internal_execute(llhttp__internal_t* s, const char* p, const char* e
#endif #endif
#endif /* INCLUDE_LLHTTP_ITSELF_H_ */ #endif /* INCLUDE_LLHTTP_ITSELF_H_ */
#ifndef LLLLHTTP_C_HEADERS_ #ifndef LLLLHTTP_C_HEADERS_
#define LLLLHTTP_C_HEADERS_ #define LLLLHTTP_C_HEADERS_
#ifdef __cplusplus #ifdef __cplusplus
@@ -59,8 +58,10 @@ enum llhttp_errno {
HPE_OK = 0, HPE_OK = 0,
HPE_INTERNAL = 1, HPE_INTERNAL = 1,
HPE_STRICT = 2, HPE_STRICT = 2,
HPE_CR_EXPECTED = 25,
HPE_LF_EXPECTED = 3, HPE_LF_EXPECTED = 3,
HPE_UNEXPECTED_CONTENT_LENGTH = 4, HPE_UNEXPECTED_CONTENT_LENGTH = 4,
HPE_UNEXPECTED_SPACE = 30,
HPE_CLOSED_CONNECTION = 5, HPE_CLOSED_CONNECTION = 5,
HPE_INVALID_METHOD = 6, HPE_INVALID_METHOD = 6,
HPE_INVALID_URL = 7, HPE_INVALID_URL = 7,
@@ -80,7 +81,17 @@ enum llhttp_errno {
HPE_PAUSED = 21, HPE_PAUSED = 21,
HPE_PAUSED_UPGRADE = 22, HPE_PAUSED_UPGRADE = 22,
HPE_PAUSED_H2_UPGRADE = 23, HPE_PAUSED_H2_UPGRADE = 23,
HPE_USER = 24 HPE_USER = 24,
HPE_CB_URL_COMPLETE = 26,
HPE_CB_STATUS_COMPLETE = 27,
HPE_CB_METHOD_COMPLETE = 32,
HPE_CB_VERSION_COMPLETE = 33,
HPE_CB_HEADER_FIELD_COMPLETE = 28,
HPE_CB_HEADER_VALUE_COMPLETE = 29,
HPE_CB_CHUNK_EXTENSION_NAME_COMPLETE = 34,
HPE_CB_CHUNK_EXTENSION_VALUE_COMPLETE = 35,
HPE_CB_RESET = 31,
HPE_CB_PROTOCOL_COMPLETE = 38
}; };
typedef enum llhttp_errno llhttp_errno_t; typedef enum llhttp_errno llhttp_errno_t;
@@ -100,7 +111,14 @@ typedef enum llhttp_flags llhttp_flags_t;
enum llhttp_lenient_flags { enum llhttp_lenient_flags {
LENIENT_HEADERS = 0x1, LENIENT_HEADERS = 0x1,
LENIENT_CHUNKED_LENGTH = 0x2, LENIENT_CHUNKED_LENGTH = 0x2,
LENIENT_KEEP_ALIVE = 0x4 LENIENT_KEEP_ALIVE = 0x4,
LENIENT_TRANSFER_ENCODING = 0x8,
LENIENT_VERSION = 0x10,
LENIENT_DATA_AFTER_CLOSE = 0x20,
LENIENT_OPTIONAL_LF_AFTER_CR = 0x40,
LENIENT_OPTIONAL_CRLF_AFTER_CHUNK = 0x80,
LENIENT_OPTIONAL_CR_BEFORE_LF = 0x100,
LENIENT_SPACES_AFTER_CHUNK_SIZE = 0x200
}; };
typedef enum llhttp_lenient_flags llhttp_lenient_flags_t; typedef enum llhttp_lenient_flags llhttp_lenient_flags_t;
@@ -164,16 +182,122 @@ enum llhttp_method {
HTTP_SET_PARAMETER = 42, HTTP_SET_PARAMETER = 42,
HTTP_REDIRECT = 43, HTTP_REDIRECT = 43,
HTTP_RECORD = 44, HTTP_RECORD = 44,
HTTP_FLUSH = 45 HTTP_FLUSH = 45,
HTTP_QUERY = 46
}; };
typedef enum llhttp_method llhttp_method_t; typedef enum llhttp_method llhttp_method_t;
enum llhttp_status {
HTTP_STATUS_CONTINUE = 100,
HTTP_STATUS_SWITCHING_PROTOCOLS = 101,
HTTP_STATUS_PROCESSING = 102,
HTTP_STATUS_EARLY_HINTS = 103,
HTTP_STATUS_RESPONSE_IS_STALE = 110,
HTTP_STATUS_REVALIDATION_FAILED = 111,
HTTP_STATUS_DISCONNECTED_OPERATION = 112,
HTTP_STATUS_HEURISTIC_EXPIRATION = 113,
HTTP_STATUS_MISCELLANEOUS_WARNING = 199,
HTTP_STATUS_OK = 200,
HTTP_STATUS_CREATED = 201,
HTTP_STATUS_ACCEPTED = 202,
HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203,
HTTP_STATUS_NO_CONTENT = 204,
HTTP_STATUS_RESET_CONTENT = 205,
HTTP_STATUS_PARTIAL_CONTENT = 206,
HTTP_STATUS_MULTI_STATUS = 207,
HTTP_STATUS_ALREADY_REPORTED = 208,
HTTP_STATUS_TRANSFORMATION_APPLIED = 214,
HTTP_STATUS_IM_USED = 226,
HTTP_STATUS_MISCELLANEOUS_PERSISTENT_WARNING = 299,
HTTP_STATUS_MULTIPLE_CHOICES = 300,
HTTP_STATUS_MOVED_PERMANENTLY = 301,
HTTP_STATUS_FOUND = 302,
HTTP_STATUS_SEE_OTHER = 303,
HTTP_STATUS_NOT_MODIFIED = 304,
HTTP_STATUS_USE_PROXY = 305,
HTTP_STATUS_SWITCH_PROXY = 306,
HTTP_STATUS_TEMPORARY_REDIRECT = 307,
HTTP_STATUS_PERMANENT_REDIRECT = 308,
HTTP_STATUS_BAD_REQUEST = 400,
HTTP_STATUS_UNAUTHORIZED = 401,
HTTP_STATUS_PAYMENT_REQUIRED = 402,
HTTP_STATUS_FORBIDDEN = 403,
HTTP_STATUS_NOT_FOUND = 404,
HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
HTTP_STATUS_NOT_ACCEPTABLE = 406,
HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407,
HTTP_STATUS_REQUEST_TIMEOUT = 408,
HTTP_STATUS_CONFLICT = 409,
HTTP_STATUS_GONE = 410,
HTTP_STATUS_LENGTH_REQUIRED = 411,
HTTP_STATUS_PRECONDITION_FAILED = 412,
HTTP_STATUS_PAYLOAD_TOO_LARGE = 413,
HTTP_STATUS_URI_TOO_LONG = 414,
HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,
HTTP_STATUS_RANGE_NOT_SATISFIABLE = 416,
HTTP_STATUS_EXPECTATION_FAILED = 417,
HTTP_STATUS_IM_A_TEAPOT = 418,
HTTP_STATUS_PAGE_EXPIRED = 419,
HTTP_STATUS_ENHANCE_YOUR_CALM = 420,
HTTP_STATUS_MISDIRECTED_REQUEST = 421,
HTTP_STATUS_UNPROCESSABLE_ENTITY = 422,
HTTP_STATUS_LOCKED = 423,
HTTP_STATUS_FAILED_DEPENDENCY = 424,
HTTP_STATUS_TOO_EARLY = 425,
HTTP_STATUS_UPGRADE_REQUIRED = 426,
HTTP_STATUS_PRECONDITION_REQUIRED = 428,
HTTP_STATUS_TOO_MANY_REQUESTS = 429,
HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL = 430,
HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
HTTP_STATUS_LOGIN_TIMEOUT = 440,
HTTP_STATUS_NO_RESPONSE = 444,
HTTP_STATUS_RETRY_WITH = 449,
HTTP_STATUS_BLOCKED_BY_PARENTAL_CONTROL = 450,
HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS = 451,
HTTP_STATUS_CLIENT_CLOSED_LOAD_BALANCED_REQUEST = 460,
HTTP_STATUS_INVALID_X_FORWARDED_FOR = 463,
HTTP_STATUS_REQUEST_HEADER_TOO_LARGE = 494,
HTTP_STATUS_SSL_CERTIFICATE_ERROR = 495,
HTTP_STATUS_SSL_CERTIFICATE_REQUIRED = 496,
HTTP_STATUS_HTTP_REQUEST_SENT_TO_HTTPS_PORT = 497,
HTTP_STATUS_INVALID_TOKEN = 498,
HTTP_STATUS_CLIENT_CLOSED_REQUEST = 499,
HTTP_STATUS_INTERNAL_SERVER_ERROR = 500,
HTTP_STATUS_NOT_IMPLEMENTED = 501,
HTTP_STATUS_BAD_GATEWAY = 502,
HTTP_STATUS_SERVICE_UNAVAILABLE = 503,
HTTP_STATUS_GATEWAY_TIMEOUT = 504,
HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED = 505,
HTTP_STATUS_VARIANT_ALSO_NEGOTIATES = 506,
HTTP_STATUS_INSUFFICIENT_STORAGE = 507,
HTTP_STATUS_LOOP_DETECTED = 508,
HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED = 509,
HTTP_STATUS_NOT_EXTENDED = 510,
HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511,
HTTP_STATUS_WEB_SERVER_UNKNOWN_ERROR = 520,
HTTP_STATUS_WEB_SERVER_IS_DOWN = 521,
HTTP_STATUS_CONNECTION_TIMEOUT = 522,
HTTP_STATUS_ORIGIN_IS_UNREACHABLE = 523,
HTTP_STATUS_TIMEOUT_OCCURED = 524,
HTTP_STATUS_SSL_HANDSHAKE_FAILED = 525,
HTTP_STATUS_INVALID_SSL_CERTIFICATE = 526,
HTTP_STATUS_RAILGUN_ERROR = 527,
HTTP_STATUS_SITE_IS_OVERLOADED = 529,
HTTP_STATUS_SITE_IS_FROZEN = 530,
HTTP_STATUS_IDENTITY_PROVIDER_AUTHENTICATION_ERROR = 561,
HTTP_STATUS_NETWORK_READ_TIMEOUT = 598,
HTTP_STATUS_NETWORK_CONNECT_TIMEOUT = 599
};
typedef enum llhttp_status llhttp_status_t;
#define HTTP_ERRNO_MAP(XX) \ #define HTTP_ERRNO_MAP(XX) \
XX(0, OK, OK) \ XX(0, OK, OK) \
XX(1, INTERNAL, INTERNAL) \ XX(1, INTERNAL, INTERNAL) \
XX(2, STRICT, STRICT) \ XX(2, STRICT, STRICT) \
XX(25, CR_EXPECTED, CR_EXPECTED) \
XX(3, LF_EXPECTED, LF_EXPECTED) \ XX(3, LF_EXPECTED, LF_EXPECTED) \
XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \ XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \
XX(30, UNEXPECTED_SPACE, UNEXPECTED_SPACE) \
XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \ XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \
XX(6, INVALID_METHOD, INVALID_METHOD) \ XX(6, INVALID_METHOD, INVALID_METHOD) \
XX(7, INVALID_URL, INVALID_URL) \ XX(7, INVALID_URL, INVALID_URL) \
@@ -194,9 +318,74 @@ typedef enum llhttp_method llhttp_method_t;
XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \ XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \
XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \ XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \
XX(24, USER, USER) \ XX(24, USER, USER) \
XX(26, CB_URL_COMPLETE, CB_URL_COMPLETE) \
XX(27, CB_STATUS_COMPLETE, CB_STATUS_COMPLETE) \
XX(32, CB_METHOD_COMPLETE, CB_METHOD_COMPLETE) \
XX(33, CB_VERSION_COMPLETE, CB_VERSION_COMPLETE) \
XX(28, CB_HEADER_FIELD_COMPLETE, CB_HEADER_FIELD_COMPLETE) \
XX(29, CB_HEADER_VALUE_COMPLETE, CB_HEADER_VALUE_COMPLETE) \
XX(34, CB_CHUNK_EXTENSION_NAME_COMPLETE, CB_CHUNK_EXTENSION_NAME_COMPLETE) \
XX(35, CB_CHUNK_EXTENSION_VALUE_COMPLETE, CB_CHUNK_EXTENSION_VALUE_COMPLETE) \
XX(31, CB_RESET, CB_RESET) \
XX(38, CB_PROTOCOL_COMPLETE, CB_PROTOCOL_COMPLETE) \
#define HTTP_METHOD_MAP(XX) \ #define HTTP_METHOD_MAP(XX) \
XX(0, DELETE, DELETE) \
XX(1, GET, GET) \
XX(2, HEAD, HEAD) \
XX(3, POST, POST) \
XX(4, PUT, PUT) \
XX(5, CONNECT, CONNECT) \
XX(6, OPTIONS, OPTIONS) \
XX(7, TRACE, TRACE) \
XX(8, COPY, COPY) \
XX(9, LOCK, LOCK) \
XX(10, MKCOL, MKCOL) \
XX(11, MOVE, MOVE) \
XX(12, PROPFIND, PROPFIND) \
XX(13, PROPPATCH, PROPPATCH) \
XX(14, SEARCH, SEARCH) \
XX(15, UNLOCK, UNLOCK) \
XX(16, BIND, BIND) \
XX(17, REBIND, REBIND) \
XX(18, UNBIND, UNBIND) \
XX(19, ACL, ACL) \
XX(20, REPORT, REPORT) \
XX(21, MKACTIVITY, MKACTIVITY) \
XX(22, CHECKOUT, CHECKOUT) \
XX(23, MERGE, MERGE) \
XX(24, MSEARCH, M-SEARCH) \
XX(25, NOTIFY, NOTIFY) \
XX(26, SUBSCRIBE, SUBSCRIBE) \
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
XX(28, PATCH, PATCH) \
XX(29, PURGE, PURGE) \
XX(30, MKCALENDAR, MKCALENDAR) \
XX(31, LINK, LINK) \
XX(32, UNLINK, UNLINK) \
XX(33, SOURCE, SOURCE) \
XX(46, QUERY, QUERY) \
#define RTSP_METHOD_MAP(XX) \
XX(1, GET, GET) \
XX(3, POST, POST) \
XX(6, OPTIONS, OPTIONS) \
XX(35, DESCRIBE, DESCRIBE) \
XX(36, ANNOUNCE, ANNOUNCE) \
XX(37, SETUP, SETUP) \
XX(38, PLAY, PLAY) \
XX(39, PAUSE, PAUSE) \
XX(40, TEARDOWN, TEARDOWN) \
XX(41, GET_PARAMETER, GET_PARAMETER) \
XX(42, SET_PARAMETER, SET_PARAMETER) \
XX(43, REDIRECT, REDIRECT) \
XX(44, RECORD, RECORD) \
XX(45, FLUSH, FLUSH) \
#define HTTP_ALL_METHOD_MAP(XX) \
XX(0, DELETE, DELETE) \ XX(0, DELETE, DELETE) \
XX(1, GET, GET) \ XX(1, GET, GET) \
XX(2, HEAD, HEAD) \ XX(2, HEAD, HEAD) \
@@ -243,14 +432,117 @@ typedef enum llhttp_method llhttp_method_t;
XX(43, REDIRECT, REDIRECT) \ XX(43, REDIRECT, REDIRECT) \
XX(44, RECORD, RECORD) \ XX(44, RECORD, RECORD) \
XX(45, FLUSH, FLUSH) \ XX(45, FLUSH, FLUSH) \
XX(46, QUERY, QUERY) \
#define HTTP_STATUS_MAP(XX) \
XX(100, CONTINUE, CONTINUE) \
XX(101, SWITCHING_PROTOCOLS, SWITCHING_PROTOCOLS) \
XX(102, PROCESSING, PROCESSING) \
XX(103, EARLY_HINTS, EARLY_HINTS) \
XX(110, RESPONSE_IS_STALE, RESPONSE_IS_STALE) \
XX(111, REVALIDATION_FAILED, REVALIDATION_FAILED) \
XX(112, DISCONNECTED_OPERATION, DISCONNECTED_OPERATION) \
XX(113, HEURISTIC_EXPIRATION, HEURISTIC_EXPIRATION) \
XX(199, MISCELLANEOUS_WARNING, MISCELLANEOUS_WARNING) \
XX(200, OK, OK) \
XX(201, CREATED, CREATED) \
XX(202, ACCEPTED, ACCEPTED) \
XX(203, NON_AUTHORITATIVE_INFORMATION, NON_AUTHORITATIVE_INFORMATION) \
XX(204, NO_CONTENT, NO_CONTENT) \
XX(205, RESET_CONTENT, RESET_CONTENT) \
XX(206, PARTIAL_CONTENT, PARTIAL_CONTENT) \
XX(207, MULTI_STATUS, MULTI_STATUS) \
XX(208, ALREADY_REPORTED, ALREADY_REPORTED) \
XX(214, TRANSFORMATION_APPLIED, TRANSFORMATION_APPLIED) \
XX(226, IM_USED, IM_USED) \
XX(299, MISCELLANEOUS_PERSISTENT_WARNING, MISCELLANEOUS_PERSISTENT_WARNING) \
XX(300, MULTIPLE_CHOICES, MULTIPLE_CHOICES) \
XX(301, MOVED_PERMANENTLY, MOVED_PERMANENTLY) \
XX(302, FOUND, FOUND) \
XX(303, SEE_OTHER, SEE_OTHER) \
XX(304, NOT_MODIFIED, NOT_MODIFIED) \
XX(305, USE_PROXY, USE_PROXY) \
XX(306, SWITCH_PROXY, SWITCH_PROXY) \
XX(307, TEMPORARY_REDIRECT, TEMPORARY_REDIRECT) \
XX(308, PERMANENT_REDIRECT, PERMANENT_REDIRECT) \
XX(400, BAD_REQUEST, BAD_REQUEST) \
XX(401, UNAUTHORIZED, UNAUTHORIZED) \
XX(402, PAYMENT_REQUIRED, PAYMENT_REQUIRED) \
XX(403, FORBIDDEN, FORBIDDEN) \
XX(404, NOT_FOUND, NOT_FOUND) \
XX(405, METHOD_NOT_ALLOWED, METHOD_NOT_ALLOWED) \
XX(406, NOT_ACCEPTABLE, NOT_ACCEPTABLE) \
XX(407, PROXY_AUTHENTICATION_REQUIRED, PROXY_AUTHENTICATION_REQUIRED) \
XX(408, REQUEST_TIMEOUT, REQUEST_TIMEOUT) \
XX(409, CONFLICT, CONFLICT) \
XX(410, GONE, GONE) \
XX(411, LENGTH_REQUIRED, LENGTH_REQUIRED) \
XX(412, PRECONDITION_FAILED, PRECONDITION_FAILED) \
XX(413, PAYLOAD_TOO_LARGE, PAYLOAD_TOO_LARGE) \
XX(414, URI_TOO_LONG, URI_TOO_LONG) \
XX(415, UNSUPPORTED_MEDIA_TYPE, UNSUPPORTED_MEDIA_TYPE) \
XX(416, RANGE_NOT_SATISFIABLE, RANGE_NOT_SATISFIABLE) \
XX(417, EXPECTATION_FAILED, EXPECTATION_FAILED) \
XX(418, IM_A_TEAPOT, IM_A_TEAPOT) \
XX(419, PAGE_EXPIRED, PAGE_EXPIRED) \
XX(420, ENHANCE_YOUR_CALM, ENHANCE_YOUR_CALM) \
XX(421, MISDIRECTED_REQUEST, MISDIRECTED_REQUEST) \
XX(422, UNPROCESSABLE_ENTITY, UNPROCESSABLE_ENTITY) \
XX(423, LOCKED, LOCKED) \
XX(424, FAILED_DEPENDENCY, FAILED_DEPENDENCY) \
XX(425, TOO_EARLY, TOO_EARLY) \
XX(426, UPGRADE_REQUIRED, UPGRADE_REQUIRED) \
XX(428, PRECONDITION_REQUIRED, PRECONDITION_REQUIRED) \
XX(429, TOO_MANY_REQUESTS, TOO_MANY_REQUESTS) \
XX(430, REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL, REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL) \
XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, REQUEST_HEADER_FIELDS_TOO_LARGE) \
XX(440, LOGIN_TIMEOUT, LOGIN_TIMEOUT) \
XX(444, NO_RESPONSE, NO_RESPONSE) \
XX(449, RETRY_WITH, RETRY_WITH) \
XX(450, BLOCKED_BY_PARENTAL_CONTROL, BLOCKED_BY_PARENTAL_CONTROL) \
XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, UNAVAILABLE_FOR_LEGAL_REASONS) \
XX(460, CLIENT_CLOSED_LOAD_BALANCED_REQUEST, CLIENT_CLOSED_LOAD_BALANCED_REQUEST) \
XX(463, INVALID_X_FORWARDED_FOR, INVALID_X_FORWARDED_FOR) \
XX(494, REQUEST_HEADER_TOO_LARGE, REQUEST_HEADER_TOO_LARGE) \
XX(495, SSL_CERTIFICATE_ERROR, SSL_CERTIFICATE_ERROR) \
XX(496, SSL_CERTIFICATE_REQUIRED, SSL_CERTIFICATE_REQUIRED) \
XX(497, HTTP_REQUEST_SENT_TO_HTTPS_PORT, HTTP_REQUEST_SENT_TO_HTTPS_PORT) \
XX(498, INVALID_TOKEN, INVALID_TOKEN) \
XX(499, CLIENT_CLOSED_REQUEST, CLIENT_CLOSED_REQUEST) \
XX(500, INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR) \
XX(501, NOT_IMPLEMENTED, NOT_IMPLEMENTED) \
XX(502, BAD_GATEWAY, BAD_GATEWAY) \
XX(503, SERVICE_UNAVAILABLE, SERVICE_UNAVAILABLE) \
XX(504, GATEWAY_TIMEOUT, GATEWAY_TIMEOUT) \
XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP_VERSION_NOT_SUPPORTED) \
XX(506, VARIANT_ALSO_NEGOTIATES, VARIANT_ALSO_NEGOTIATES) \
XX(507, INSUFFICIENT_STORAGE, INSUFFICIENT_STORAGE) \
XX(508, LOOP_DETECTED, LOOP_DETECTED) \
XX(509, BANDWIDTH_LIMIT_EXCEEDED, BANDWIDTH_LIMIT_EXCEEDED) \
XX(510, NOT_EXTENDED, NOT_EXTENDED) \
XX(511, NETWORK_AUTHENTICATION_REQUIRED, NETWORK_AUTHENTICATION_REQUIRED) \
XX(520, WEB_SERVER_UNKNOWN_ERROR, WEB_SERVER_UNKNOWN_ERROR) \
XX(521, WEB_SERVER_IS_DOWN, WEB_SERVER_IS_DOWN) \
XX(522, CONNECTION_TIMEOUT, CONNECTION_TIMEOUT) \
XX(523, ORIGIN_IS_UNREACHABLE, ORIGIN_IS_UNREACHABLE) \
XX(524, TIMEOUT_OCCURED, TIMEOUT_OCCURED) \
XX(525, SSL_HANDSHAKE_FAILED, SSL_HANDSHAKE_FAILED) \
XX(526, INVALID_SSL_CERTIFICATE, INVALID_SSL_CERTIFICATE) \
XX(527, RAILGUN_ERROR, RAILGUN_ERROR) \
XX(529, SITE_IS_OVERLOADED, SITE_IS_OVERLOADED) \
XX(530, SITE_IS_FROZEN, SITE_IS_FROZEN) \
XX(561, IDENTITY_PROVIDER_AUTHENTICATION_ERROR, IDENTITY_PROVIDER_AUTHENTICATION_ERROR) \
XX(598, NETWORK_READ_TIMEOUT, NETWORK_READ_TIMEOUT) \
XX(599, NETWORK_CONNECT_TIMEOUT, NETWORK_CONNECT_TIMEOUT) \
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif /* LLLLHTTP_C_HEADERS_ */ #endif /* LLLLHTTP_C_HEADERS_ */
#ifndef INCLUDE_LLHTTP_API_H_ #ifndef INCLUDE_LLHTTP_API_H_
#define INCLUDE_LLHTTP_API_H_ #define INCLUDE_LLHTTP_API_H_
#ifdef __cplusplus #ifdef __cplusplus
@@ -274,10 +566,16 @@ struct llhttp_settings_s {
/* Possible return values 0, -1, `HPE_PAUSED` */ /* Possible return values 0, -1, `HPE_PAUSED` */
llhttp_cb on_message_begin; llhttp_cb on_message_begin;
/* Possible return values 0, -1, HPE_USER */
llhttp_data_cb on_protocol;
llhttp_data_cb on_url; llhttp_data_cb on_url;
llhttp_data_cb on_status; llhttp_data_cb on_status;
llhttp_data_cb on_method;
llhttp_data_cb on_version;
llhttp_data_cb on_header_field; llhttp_data_cb on_header_field;
llhttp_data_cb on_header_value; llhttp_data_cb on_header_value;
llhttp_data_cb on_chunk_extension_name;
llhttp_data_cb on_chunk_extension_value;
/* Possible return values: /* Possible return values:
* 0 - Proceed normally * 0 - Proceed normally
@@ -290,10 +588,20 @@ struct llhttp_settings_s {
*/ */
llhttp_cb on_headers_complete; llhttp_cb on_headers_complete;
/* Possible return values 0, -1, HPE_USER */
llhttp_data_cb on_body; llhttp_data_cb on_body;
/* Possible return values 0, -1, `HPE_PAUSED` */ /* Possible return values 0, -1, `HPE_PAUSED` */
llhttp_cb on_message_complete; llhttp_cb on_message_complete;
llhttp_cb on_protocol_complete;
llhttp_cb on_url_complete;
llhttp_cb on_status_complete;
llhttp_cb on_method_complete;
llhttp_cb on_version_complete;
llhttp_cb on_header_field_complete;
llhttp_cb on_header_value_complete;
llhttp_cb on_chunk_extension_name_complete;
llhttp_cb on_chunk_extension_value_complete;
/* When on_chunk_header is called, the current chunk length is stored /* When on_chunk_header is called, the current chunk length is stored
* in parser->content_length. * in parser->content_length.
@@ -301,11 +609,7 @@ struct llhttp_settings_s {
*/ */
llhttp_cb on_chunk_header; llhttp_cb on_chunk_header;
llhttp_cb on_chunk_complete; llhttp_cb on_chunk_complete;
llhttp_cb on_reset;
llhttp_cb on_url_complete;
llhttp_cb on_status_complete;
llhttp_cb on_header_field_complete;
llhttp_cb on_header_value_complete;
}; };
/* Initialize the parser with specific type and user settings. /* Initialize the parser with specific type and user settings.
@@ -318,8 +622,6 @@ LLHTTP_EXPORT
void llhttp_init(llhttp_t* parser, llhttp_type_t type, void llhttp_init(llhttp_t* parser, llhttp_type_t type,
const llhttp_settings_t* settings); const llhttp_settings_t* settings);
#if defined(__wasm__)
LLHTTP_EXPORT LLHTTP_EXPORT
llhttp_t* llhttp_alloc(llhttp_type_t type); llhttp_t* llhttp_alloc(llhttp_type_t type);
@@ -344,8 +646,6 @@ int llhttp_get_status_code(llhttp_t* parser);
LLHTTP_EXPORT LLHTTP_EXPORT
uint8_t llhttp_get_upgrade(llhttp_t* parser); uint8_t llhttp_get_upgrade(llhttp_t* parser);
#endif // defined(__wasm__)
/* Reset an already initialized parser back to the start state, preserving the /* Reset an already initialized parser back to the start state, preserving the
* existing parser type, callback settings, user data, and lenient flags. * existing parser type, callback settings, user data, and lenient flags.
*/ */
@@ -459,6 +759,9 @@ const char* llhttp_errno_name(llhttp_errno_t err);
LLHTTP_EXPORT LLHTTP_EXPORT
const char* llhttp_method_name(llhttp_method_t method); const char* llhttp_method_name(llhttp_method_t method);
/* Returns textual name of HTTP status */
LLHTTP_EXPORT
const char* llhttp_status_name(llhttp_status_t status);
/* Enables/disables lenient header value parsing (disabled by default). /* Enables/disables lenient header value parsing (disabled by default).
* *
@@ -467,7 +770,8 @@ const char* llhttp_method_name(llhttp_method_t method);
* `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when * `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when
* lenient parsing is "on". * lenient parsing is "on".
* *
* **(USE AT YOUR OWN RISK)** * **Enabling this flag can pose a security issue since you will be exposed to
* request smuggling attacks. USE WITH CAUTION!**
*/ */
LLHTTP_EXPORT LLHTTP_EXPORT
void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); void llhttp_set_lenient_headers(llhttp_t* parser, int enabled);
@@ -481,7 +785,8 @@ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled);
* request smuggling, but may be less desirable for small number of cases * request smuggling, but may be less desirable for small number of cases
* involving legacy servers. * involving legacy servers.
* *
* **(USE AT YOUR OWN RISK)** * **Enabling this flag can pose a security issue since you will be exposed to
* request smuggling attacks. USE WITH CAUTION!**
*/ */
LLHTTP_EXPORT LLHTTP_EXPORT
void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled); void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);
@@ -496,13 +801,105 @@ void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);
* but might interact badly with outdated and insecure clients. With this flag * but might interact badly with outdated and insecure clients. With this flag
* the extra request/response will be parsed normally. * the extra request/response will be parsed normally.
* *
* **(USE AT YOUR OWN RISK)** * **Enabling this flag can pose a security issue since you will be exposed to
* poisoning attacks. USE WITH CAUTION!**
*/ */
LLHTTP_EXPORT
void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled); void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled);
/* Enables/disables lenient handling of `Transfer-Encoding` header.
*
* Normally `llhttp` would error when a `Transfer-Encoding` has `chunked` value
* and another value after it (either in a single header or in multiple
* headers whose value are internally joined using `, `).
* This is mandated by the spec to reliably determine request body size and thus
* avoid request smuggling.
* With this flag the extra value will be parsed normally.
*
* **Enabling this flag can pose a security issue since you will be exposed to
* request smuggling attacks. USE WITH CAUTION!**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled);
/* Enables/disables lenient handling of HTTP version.
*
* Normally `llhttp` would error when the HTTP version in the request or status line
* is not `0.9`, `1.0`, `1.1` or `2.0`.
* With this flag the invalid value will be parsed normally.
*
* **Enabling this flag can pose a security issue since you will allow unsupported
* HTTP versions. USE WITH CAUTION!**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_version(llhttp_t* parser, int enabled);
/* Enables/disables lenient handling of additional data received after a message ends
* and keep-alive is disabled.
*
* Normally `llhttp` would error when additional unexpected data is received if the message
* contains the `Connection` header with `close` value.
* With this flag the extra data will discarded without throwing an error.
*
* **Enabling this flag can pose a security issue since you will be exposed to
* poisoning attacks. USE WITH CAUTION!**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled);
/* Enables/disables lenient handling of incomplete CRLF sequences.
*
* Normally `llhttp` would error when a CR is not followed by LF when terminating the
* request line, the status line, the headers or a chunk header.
* With this flag only a CR is required to terminate such sections.
*
* **Enabling this flag can pose a security issue since you will be exposed to
* request smuggling attacks. USE WITH CAUTION!**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled);
/*
* Enables/disables lenient handling of line separators.
*
* Normally `llhttp` would error when a LF is not preceded by CR when terminating the
* request line, the status line, the headers, a chunk header or a chunk data.
* With this flag only a LF is required to terminate such sections.
*
* **Enabling this flag can pose a security issue since you will be exposed to
* request smuggling attacks. USE WITH CAUTION!**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled);
/* Enables/disables lenient handling of chunks not separated via CRLF.
*
* Normally `llhttp` would error when after a chunk data a CRLF is missing before
* starting a new chunk.
* With this flag the new chunk can start immediately after the previous one.
*
* **Enabling this flag can pose a security issue since you will be exposed to
* request smuggling attacks. USE WITH CAUTION!**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled);
/* Enables/disables lenient handling of spaces after chunk size.
*
* Normally `llhttp` would error when after a chunk size is followed by one or more
* spaces are present instead of a CRLF or `;`.
* With this flag this check is disabled.
*
* **Enabling this flag can pose a security issue since you will be exposed to
* request smuggling attacks. USE WITH CAUTION!**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif /* INCLUDE_LLHTTP_API_H_ */ #endif /* INCLUDE_LLHTTP_API_H_ */
#endif /* INCLUDE_LLHTTP_H_ */ #endif /* INCLUDE_LLHTTP_H_ */

View File

@@ -19,6 +19,7 @@
#include "internal/meta.h" #include "internal/meta.h"
#include <memory> #include <memory>
#include <limits>
#if RAPIDJSON_HAS_CXX11 #if RAPIDJSON_HAS_CXX11
#include <type_traits> #include <type_traits>
@@ -433,7 +434,7 @@ namespace internal {
template<typename T, typename A> template<typename T, typename A>
inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n) inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
{ {
RAPIDJSON_NOEXCEPT_ASSERT(old_n <= SIZE_MAX / sizeof(T) && new_n <= SIZE_MAX / sizeof(T)); RAPIDJSON_NOEXCEPT_ASSERT(old_n <= (std::numeric_limits<size_t>::max)() / sizeof(T) && new_n <= (std::numeric_limits<size_t>::max)() / sizeof(T));
return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T))); return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
} }
@@ -496,9 +497,9 @@ public:
#endif #endif
/* implicit */ /* implicit */
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
allocator_type(), allocator_type(),
baseAllocator_(allocator) baseAllocator_(baseAllocator)
{ } { }
~StdAllocator() RAPIDJSON_NOEXCEPT ~StdAllocator() RAPIDJSON_NOEXCEPT

View File

@@ -75,7 +75,7 @@ class GenericDocument;
User can define this to use CrtAllocator or MemoryPoolAllocator. User can define this to use CrtAllocator or MemoryPoolAllocator.
*/ */
#ifndef RAPIDJSON_DEFAULT_ALLOCATOR #ifndef RAPIDJSON_DEFAULT_ALLOCATOR
#define RAPIDJSON_DEFAULT_ALLOCATOR MemoryPoolAllocator<CrtAllocator> #define RAPIDJSON_DEFAULT_ALLOCATOR ::RAPIDJSON_NAMESPACE::MemoryPoolAllocator<::RAPIDJSON_NAMESPACE::CrtAllocator>
#endif #endif
/*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR /*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR
@@ -85,7 +85,7 @@ class GenericDocument;
User can define this to use CrtAllocator or MemoryPoolAllocator. User can define this to use CrtAllocator or MemoryPoolAllocator.
*/ */
#ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR #ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR
#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR CrtAllocator #define RAPIDJSON_DEFAULT_STACK_ALLOCATOR ::RAPIDJSON_NAMESPACE::CrtAllocator
#endif #endif
/*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY /*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY
@@ -1033,7 +1033,7 @@ public:
return false; return false;
for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) if (rhsMemberItr == rhs.MemberEnd() || (!(lhsMemberItr->value == rhsMemberItr->value)))
return false; return false;
} }
return true; return true;
@@ -1042,7 +1042,7 @@ public:
if (data_.a.size != rhs.data_.a.size) if (data_.a.size != rhs.data_.a.size)
return false; return false;
for (SizeType i = 0; i < data_.a.size; i++) for (SizeType i = 0; i < data_.a.size; i++)
if ((*this)[i] != rhs[i]) if (!((*this)[i] == rhs[i]))
return false; return false;
return true; return true;
@@ -1078,6 +1078,7 @@ public:
*/ */
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
#ifndef __cpp_impl_three_way_comparison
//! Not-equal-to operator //! Not-equal-to operator
/*! \return !(*this == rhs) /*! \return !(*this == rhs)
*/ */
@@ -1092,7 +1093,6 @@ public:
*/ */
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
#ifndef __cpp_lib_three_way_comparison
//! Equal-to operator with arbitrary types (symmetric version) //! Equal-to operator with arbitrary types (symmetric version)
/*! \return (rhs == lhs) /*! \return (rhs == lhs)
*/ */
@@ -1230,13 +1230,28 @@ public:
else { else {
RAPIDJSON_ASSERT(false); // see above note RAPIDJSON_ASSERT(false); // see above note
// This will generate -Wexit-time-destructors in clang #if RAPIDJSON_HAS_CXX11
// static GenericValue NullValue; // Use thread-local storage to prevent races between threads.
// return NullValue; // Use static buffer and placement-new to prevent destruction, with
// alignas() to ensure proper alignment.
// Use static buffer and placement-new to prevent destruction alignas(GenericValue) thread_local static char buffer[sizeof(GenericValue)];
static char buffer[sizeof(GenericValue)];
return *new (buffer) GenericValue(); return *new (buffer) GenericValue();
#elif defined(_MSC_VER) && _MSC_VER < 1900
// There's no way to solve both thread locality and proper alignment
// simultaneously.
__declspec(thread) static char buffer[sizeof(GenericValue)];
return *new (buffer) GenericValue();
#elif defined(__GNUC__) || defined(__clang__)
// This will generate -Wexit-time-destructors in clang, but that's
// better than having under-alignment.
__thread static GenericValue buffer;
return buffer;
#else
// Don't know what compiler this is, so don't know how to ensure
// thread-locality.
static GenericValue buffer;
return buffer;
#endif
} }
} }
template <typename SourceAllocator> template <typename SourceAllocator>
@@ -2430,13 +2445,14 @@ private:
data_.f.flags = kShortStringFlag; data_.f.flags = kShortStringFlag;
data_.ss.SetLength(s.length); data_.ss.SetLength(s.length);
str = data_.ss.str; str = data_.ss.str;
std::memmove(str, s, s.length * sizeof(Ch));
} else { } else {
data_.f.flags = kCopyStringFlag; data_.f.flags = kCopyStringFlag;
data_.s.length = s.length; data_.s.length = s.length;
str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch))); str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
SetStringPointer(str); SetStringPointer(str);
std::memcpy(str, s, s.length * sizeof(Ch));
} }
std::memcpy(str, s, s.length * sizeof(Ch));
str[s.length] = '\0'; str[s.length] = '\0';
} }
@@ -2486,6 +2502,7 @@ public:
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document. typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
typedef Allocator AllocatorType; //!< Allocator type from template parameter. typedef Allocator AllocatorType; //!< Allocator type from template parameter.
typedef StackAllocator StackAllocatorType; //!< StackAllocator type from template parameter.
//! Constructor //! Constructor
/*! Creates an empty document of specified type. /*! Creates an empty document of specified type.

View File

@@ -177,10 +177,10 @@ struct UTF8 {
template <typename InputStream, typename OutputStream> template <typename InputStream, typename OutputStream>
static bool Validate(InputStream& is, OutputStream& os) { static bool Validate(InputStream& is, OutputStream& os) {
#define RAPIDJSON_COPY() os.Put(c = is.Take()) #define RAPIDJSON_COPY() if (c != '\0') os.Put(c = is.Take())
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) #define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) #define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
Ch c; Ch c = static_cast<Ch>(-1);
RAPIDJSON_COPY(); RAPIDJSON_COPY();
if (!(c & 0x80)) if (!(c & 0x80))
return true; return true;

View File

@@ -104,15 +104,69 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode val
case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'."); case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'.");
case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors."); case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors.");
case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'."); case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf', indices '%matches'.");
case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors."); case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors.");
case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors."); case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors.");
case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'."); case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
case kValidateErrorReadOnly: return RAPIDJSON_ERROR_STRING("Property is read-only but has been provided when validation is for writing.");
case kValidateErrorWriteOnly: return RAPIDJSON_ERROR_STRING("Property is write-only but has been provided when validation is for reading.");
default: return RAPIDJSON_ERROR_STRING("Unknown error."); default: return RAPIDJSON_ERROR_STRING("Unknown error.");
} }
} }
//! Maps error code of schema document compilation into error message.
/*!
\ingroup RAPIDJSON_ERRORS
\param schemaErrorCode Error code obtained from compiling the schema document.
\return the error message.
\note User can make a copy of this function for localization.
Using switch-case is safer for future modification of error codes.
*/
inline const RAPIDJSON_ERROR_CHARTYPE* GetSchemaError_En(SchemaErrorCode schemaErrorCode) {
switch (schemaErrorCode) {
case kSchemaErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
case kSchemaErrorStartUnknown: return RAPIDJSON_ERROR_STRING("Pointer '%value' to start of schema does not resolve to a location in the document.");
case kSchemaErrorRefPlainName: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' must be a JSON pointer.");
case kSchemaErrorRefInvalid: return RAPIDJSON_ERROR_STRING("$ref must not be an empty string.");
case kSchemaErrorRefPointerInvalid: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' is not a valid JSON pointer at offset '%offset'.");
case kSchemaErrorRefUnknown: return RAPIDJSON_ERROR_STRING("$ref '%value' does not resolve to a location in the target document.");
case kSchemaErrorRefCyclical: return RAPIDJSON_ERROR_STRING("$ref '%value' is cyclical.");
case kSchemaErrorRefNoRemoteProvider: return RAPIDJSON_ERROR_STRING("$ref is remote but there is no remote provider.");
case kSchemaErrorRefNoRemoteSchema: return RAPIDJSON_ERROR_STRING("$ref '%value' is remote but the remote provider did not return a schema.");
case kSchemaErrorRegexInvalid: return RAPIDJSON_ERROR_STRING("Invalid regular expression '%value' in 'pattern' or 'patternProperties'.");
case kSchemaErrorSpecUnknown: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not recognized.");
case kSchemaErrorSpecUnsupported: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not supported.");
case kSchemaErrorSpecIllegal: return RAPIDJSON_ERROR_STRING("Both JSON schema draft and OpenAPI version found in document.");
case kSchemaErrorReadOnlyAndWriteOnly: return RAPIDJSON_ERROR_STRING("Property must not be both 'readOnly' and 'writeOnly'.");
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
}
}
//! Maps error code of pointer parse into error message.
/*!
\ingroup RAPIDJSON_ERRORS
\param pointerParseErrorCode Error code obtained from pointer parse.
\return the error message.
\note User can make a copy of this function for localization.
Using switch-case is safer for future modification of error codes.
*/
inline const RAPIDJSON_ERROR_CHARTYPE* GetPointerParseError_En(PointerParseErrorCode pointerParseErrorCode) {
switch (pointerParseErrorCode) {
case kPointerParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
case kPointerParseErrorTokenMustBeginWithSolidus: return RAPIDJSON_ERROR_STRING("A token must begin with a '/'.");
case kPointerParseErrorInvalidEscape: return RAPIDJSON_ERROR_STRING("Invalid escape.");
case kPointerParseErrorInvalidPercentEncoding: return RAPIDJSON_ERROR_STRING("Invalid percent encoding in URI fragment.");
case kPointerParseErrorCharacterMustPercentEncode: return RAPIDJSON_ERROR_STRING("A character must be percent encoded in a URI fragment.");
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
}
}
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END
#ifdef __clang__ #ifdef __clang__

View File

@@ -42,7 +42,7 @@ RAPIDJSON_DIAG_OFF(padded)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_ERROR_STRING // RAPIDJSON_ERROR_STRING
//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. //! Macro for converting string literal to \ref RAPIDJSON_ERROR_CHARTYPE[].
/*! \ingroup RAPIDJSON_ERRORS /*! \ingroup RAPIDJSON_ERRORS
By default this conversion macro does nothing. By default this conversion macro does nothing.
On Windows, user can define this macro as \c _T(x) for supporting both On Windows, user can define this macro as \c _T(x) for supporting both
@@ -185,14 +185,17 @@ enum ValidateErrorCode {
kValidateErrorPatternProperties, //!< See other errors. kValidateErrorPatternProperties, //!< See other errors.
kValidateErrorDependencies, //!< Object has missing property or schema dependencies. kValidateErrorDependencies, //!< Object has missing property or schema dependencies.
kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values.
kValidateErrorType, //!< Property has a type that is not allowed by the schema.. kValidateErrorType, //!< Property has a type that is not allowed by the schema.
kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'. kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'.
kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'. kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'.
kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'. kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'.
kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'. kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'.
kValidateErrorNot //!< Property matched the sub-schema specified by 'not'. kValidateErrorNot, //!< Property matched the sub-schema specified by 'not'.
kValidateErrorReadOnly, //!< Property is read-only but has been provided when validation is for writing
kValidateErrorWriteOnly //!< Property is write-only but has been provided when validation is for reading
}; };
//! Function pointer type of GetValidateError(). //! Function pointer type of GetValidateError().
@@ -207,6 +210,72 @@ enum ValidateErrorCode {
*/ */
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode); typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode);
///////////////////////////////////////////////////////////////////////////////
// SchemaErrorCode
//! Error codes when validating.
/*! \ingroup RAPIDJSON_ERRORS
\see GenericSchemaValidator
*/
enum SchemaErrorCode {
kSchemaErrorNone = 0, //!< No error.
kSchemaErrorStartUnknown, //!< Pointer to start of schema does not resolve to a location in the document
kSchemaErrorRefPlainName, //!< $ref fragment must be a JSON pointer
kSchemaErrorRefInvalid, //!< $ref must not be an empty string
kSchemaErrorRefPointerInvalid, //!< $ref fragment is not a valid JSON pointer at offset
kSchemaErrorRefUnknown, //!< $ref does not resolve to a location in the target document
kSchemaErrorRefCyclical, //!< $ref is cyclical
kSchemaErrorRefNoRemoteProvider, //!< $ref is remote but there is no remote provider
kSchemaErrorRefNoRemoteSchema, //!< $ref is remote but the remote provider did not return a schema
kSchemaErrorRegexInvalid, //!< Invalid regular expression in 'pattern' or 'patternProperties'
kSchemaErrorSpecUnknown, //!< JSON schema draft or OpenAPI version is not recognized
kSchemaErrorSpecUnsupported, //!< JSON schema draft or OpenAPI version is not supported
kSchemaErrorSpecIllegal, //!< Both JSON schema draft and OpenAPI version found in document
kSchemaErrorReadOnlyAndWriteOnly //!< Property must not be both 'readOnly' and 'writeOnly'
};
//! Function pointer type of GetSchemaError().
/*! \ingroup RAPIDJSON_ERRORS
This is the prototype for \c GetSchemaError_X(), where \c X is a locale.
User can dynamically change locale in runtime, e.g.:
\code
GetSchemaErrorFunc GetSchemaError = GetSchemaError_En; // or whatever
const RAPIDJSON_ERROR_CHARTYPE* s = GetSchemaError(validator.GetInvalidSchemaCode());
\endcode
*/
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetSchemaErrorFunc)(SchemaErrorCode);
///////////////////////////////////////////////////////////////////////////////
// PointerParseErrorCode
//! Error code of JSON pointer parsing.
/*! \ingroup RAPIDJSON_ERRORS
\see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
*/
enum PointerParseErrorCode {
kPointerParseErrorNone = 0, //!< The parse is successful
kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
kPointerParseErrorInvalidEscape, //!< Invalid escape
kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
};
//! Function pointer type of GetPointerParseError().
/*! \ingroup RAPIDJSON_ERRORS
This is the prototype for \c GetPointerParseError_X(), where \c X is a locale.
User can dynamically change locale in runtime, e.g.:
\code
GetPointerParseErrorFunc GetPointerParseError = GetPointerParseError_En; // or whatever
const RAPIDJSON_ERROR_CHARTYPE* s = GetPointerParseError(pointer.GetParseErrorCode());
\endcode
*/
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetPointerParseErrorFunc)(PointerParseErrorCode);
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END
#ifdef __clang__ #ifdef __clang__

View File

@@ -19,7 +19,11 @@
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64)
#include <intrin.h> // for _umul128 #include <intrin.h> // for _umul128
#if !defined(_ARM64EC_)
#pragma intrinsic(_umul128) #pragma intrinsic(_umul128)
#else
#pragma comment(lib,"softintrin")
#endif
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@@ -255,7 +259,7 @@ private:
if (low < k) if (low < k)
(*outHigh)++; (*outHigh)++;
return low; return low;
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
__extension__ typedef unsigned __int128 uint128; __extension__ typedef unsigned __int128 uint128;
uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b); uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
p += k; p += k;

View File

@@ -25,7 +25,11 @@
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
#include <intrin.h> #include <intrin.h>
#if !defined(_ARM64EC_)
#pragma intrinsic(_umul128) #pragma intrinsic(_umul128)
#else
#pragma comment(lib,"softintrin")
#endif
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@@ -75,7 +79,7 @@ struct DiyFp {
if (l & (uint64_t(1) << 63)) // rounding if (l & (uint64_t(1) << 63)) // rounding
h++; h++;
return DiyFp(h, e + rhs.e + 64); return DiyFp(h, e + rhs.e + 64);
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
__extension__ typedef unsigned __int128 uint128; __extension__ typedef unsigned __int128 uint128;
uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f); uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
uint64_t h = static_cast<uint64_t>(p >> 64); uint64_t h = static_cast<uint64_t>(p >> 64);

View File

@@ -58,11 +58,11 @@ inline int CountDecimalDigit32(uint32_t n) {
} }
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
static const uint64_t kPow10[] = { 1U, 10U, 100U, 1000U, 10000U, 100000U, 1000000U, 10000000U, 100000000U, static const uint64_t kPow10[] = { 1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL, 10000000ULL, 100000000ULL,
1000000000U, 10000000000U, 100000000000U, 1000000000000U, 1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL,
10000000000000U, 100000000000000U, 1000000000000000U, 10000000000000ULL, 100000000000000ULL, 1000000000000000ULL,
10000000000000000U, 100000000000000000U, 1000000000000000000U, 10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL,
10000000000000000000U }; 10000000000000000000ULL };
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
const DiyFp wp_w = Mp - W; const DiyFp wp_w = Mp - W;
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e); uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);

View File

@@ -615,7 +615,7 @@ public:
RAPIDJSON_ASSERT(regex_.IsValid()); RAPIDJSON_ASSERT(regex_.IsValid());
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
stateSet_ = static_cast<unsigned*>(allocator_->Malloc(GetStateSetSize())); stateSet_ = static_cast<uint32_t*>(allocator_->Malloc(GetStateSetSize()));
state0_.template Reserve<SizeType>(regex_.stateCount_); state0_.template Reserve<SizeType>(regex_.stateCount_);
state1_.template Reserve<SizeType>(regex_.stateCount_); state1_.template Reserve<SizeType>(regex_.stateCount_);
} }

View File

@@ -134,7 +134,7 @@ inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result)
int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
for (; i < dLen; i++) { for (; i < dLen; i++) {
if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > Ch('5'))) (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] >= Ch('5')))
break; break;
significand = significand * 10u + static_cast<unsigned>(decimals[i] - Ch('0')); significand = significand * 10u + static_cast<unsigned>(decimals[i] - Ch('0'));
} }

View File

@@ -18,6 +18,7 @@
#include "document.h" #include "document.h"
#include "uri.h" #include "uri.h"
#include "internal/itoa.h" #include "internal/itoa.h"
#include "error/error.h" // PointerParseErrorCode
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
@@ -27,23 +28,16 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif #endif
#if defined(RAPIDJSON_CPLUSPLUS) && RAPIDJSON_CPLUSPLUS >= 201703L
#define RAPIDJSON_IF_CONSTEXPR if constexpr
#else
#define RAPIDJSON_IF_CONSTEXPR if
#endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
//! Error code of parsing.
/*! \ingroup RAPIDJSON_ERRORS
\see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
*/
enum PointerParseErrorCode {
kPointerParseErrorNone = 0, //!< The parse is successful
kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
kPointerParseErrorInvalidEscape, //!< Invalid escape
kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GenericPointer // GenericPointer
@@ -84,7 +78,7 @@ public:
typedef GenericUri<ValueType, Allocator> UriType; typedef GenericUri<ValueType, Allocator> UriType;
//! A token is the basic units of internal representation. //! A token is the basic units of internal representation.
/*! /*!
A JSON pointer string representation "/foo/123" is parsed to two tokens: A JSON pointer string representation "/foo/123" is parsed to two tokens:
"foo" and 123. 123 will be represented in both numeric form and string form. "foo" and 123. 123 will be represented in both numeric form and string form.
@@ -303,7 +297,7 @@ public:
SizeType length = static_cast<SizeType>(end - buffer); SizeType length = static_cast<SizeType>(end - buffer);
buffer[length] = '\0'; buffer[length] = '\0';
if (sizeof(Ch) == 1) { RAPIDJSON_IF_CONSTEXPR (sizeof(Ch) == 1) {
Token token = { reinterpret_cast<Ch*>(buffer), length, index }; Token token = { reinterpret_cast<Ch*>(buffer), length, index };
return Append(token, allocator); return Append(token, allocator);
} }
@@ -902,10 +896,16 @@ private:
std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
} }
// Adjust pointers to name buffer // The names of each token point to a string in the nameBuffer_. The
std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; // previous memcpy copied over string pointers into the rhs.nameBuffer_,
for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) // but they should point to the strings in the new nameBuffer_.
t->name += diff; for (size_t i = 0; i < rhs.tokenCount_; ++i) {
// The offset between the string address and the name buffer should
// still be constant, so we can just get this offset and set each new
// token name according the new buffer start + the known offset.
std::ptrdiff_t name_offset = rhs.tokens_[i].name - rhs.nameBuffer_;
tokens_[i].name = nameBuffer_ + name_offset;
}
return nameBuffer_ + nameBufferSize; return nameBuffer_ + nameBufferSize;
} }

View File

@@ -195,7 +195,7 @@
*/ */
#ifndef RAPIDJSON_NO_INT64DEFINE #ifndef RAPIDJSON_NO_INT64DEFINE
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 #if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
#include "msinttypes/stdint.h" #include "msinttypes/stdint.h"
#include "msinttypes/inttypes.h" #include "msinttypes/inttypes.h"
#else #else
@@ -268,7 +268,7 @@
# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) # elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
// Detect with architecture macros // Detect with architecture macros
# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) # elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) # elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN

View File

@@ -1433,7 +1433,7 @@ private:
class NumberStream<InputStream, StackCharacter, true, false> : public NumberStream<InputStream, StackCharacter, false, false> { class NumberStream<InputStream, StackCharacter, true, false> : public NumberStream<InputStream, StackCharacter, false, false> {
typedef NumberStream<InputStream, StackCharacter, false, false> Base; typedef NumberStream<InputStream, StackCharacter, false, false> Base;
public: public:
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {} NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {}
RAPIDJSON_FORCEINLINE Ch TakePush() { RAPIDJSON_FORCEINLINE Ch TakePush() {
stackStream.Put(static_cast<StackCharacter>(Base::is.Peek())); stackStream.Put(static_cast<StackCharacter>(Base::is.Peek()));
@@ -1459,7 +1459,7 @@ private:
class NumberStream<InputStream, StackCharacter, true, true> : public NumberStream<InputStream, StackCharacter, true, false> { class NumberStream<InputStream, StackCharacter, true, true> : public NumberStream<InputStream, StackCharacter, true, false> {
typedef NumberStream<InputStream, StackCharacter, true, false> Base; typedef NumberStream<InputStream, StackCharacter, true, false> Base;
public: public:
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s) {}
RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
}; };
@@ -1584,7 +1584,7 @@ private:
// Parse frac = decimal-point 1*DIGIT // Parse frac = decimal-point 1*DIGIT
int expFrac = 0; int expFrac = 0;
size_t decimalPosition; size_t decimalPosition;
if (Consume(s, '.')) { if (!useNanOrInf && Consume(s, '.')) {
decimalPosition = s.Length(); decimalPosition = s.Length();
if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
@@ -1631,7 +1631,7 @@ private:
// Parse exp = e [ minus / plus ] 1*DIGIT // Parse exp = e [ minus / plus ] 1*DIGIT
int exp = 0; int exp = 0;
if (Consume(s, 'e') || Consume(s, 'E')) { if (!useNanOrInf && (Consume(s, 'e') || Consume(s, 'E'))) {
if (!useDouble) { if (!useDouble) {
d = static_cast<double>(use64bit ? i64 : i); d = static_cast<double>(use64bit ? i64 : i);
useDouble = true; useDouble = true;
@@ -1694,7 +1694,7 @@ private:
} }
else { else {
SizeType numCharsToCopy = static_cast<SizeType>(s.Length()); SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
GenericStringStream<UTF8<NumberCharacter>> srcStream(s.Pop()); GenericStringStream<UTF8<NumberCharacter> > srcStream(s.Pop());
StackStream<typename TargetEncoding::Ch> dstStream(stack_); StackStream<typename TargetEncoding::Ch> dstStream(stack_);
while (numCharsToCopy--) { while (numCharsToCopy--) {
Transcoder<UTF8<typename TargetEncoding::Ch>, TargetEncoding>::Transcode(srcStream, dstStream); Transcoder<UTF8<typename TargetEncoding::Ch>, TargetEncoding>::Transcode(srcStream, dstStream);

File diff suppressed because it is too large Load Diff

View File

@@ -238,20 +238,27 @@ private:
// Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated. // Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated.
// Order: scheme, auth, path, query, frag, base, uri // Order: scheme, auth, path, query, frag, base, uri
// Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
size_t total = (3 * len + 7) * sizeof(Ch); size_t total = (3 * len + 7) * sizeof(Ch);
scheme_ = static_cast<Ch*>(allocator_->Malloc(total)); scheme_ = static_cast<Ch*>(allocator_->Malloc(total));
*scheme_ = '\0'; *scheme_ = '\0';
auth_ = scheme_ + 1; auth_ = scheme_;
auth_++;
*auth_ = '\0'; *auth_ = '\0';
path_ = auth_ + 1; path_ = auth_;
path_++;
*path_ = '\0'; *path_ = '\0';
query_ = path_ + 1; query_ = path_;
query_++;
*query_ = '\0'; *query_ = '\0';
frag_ = query_ + 1; frag_ = query_;
frag_++;
*frag_ = '\0'; *frag_ = '\0';
base_ = frag_ + 1; base_ = frag_;
base_++;
*base_ = '\0'; *base_ = '\0';
uri_ = base_ + 1; uri_ = base_;
uri_++;
*uri_ = '\0'; *uri_ = '\0';
return total; return total;
} }
@@ -293,7 +300,9 @@ private:
} }
} }
// Look for auth (//([^/?#]*))? // Look for auth (//([^/?#]*))?
auth_ = scheme_ + GetSchemeStringLength() + 1; // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
auth_ = scheme_ + GetSchemeStringLength();
auth_++;
*auth_ = '\0'; *auth_ = '\0';
if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') { if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') {
pos2 = start + 2; pos2 = start + 2;
@@ -308,7 +317,9 @@ private:
start = pos2; start = pos2;
} }
// Look for path ([^?#]*) // Look for path ([^?#]*)
path_ = auth_ + GetAuthStringLength() + 1; // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
path_ = auth_ + GetAuthStringLength();
path_++;
*path_ = '\0'; *path_ = '\0';
if (start < len) { if (start < len) {
pos2 = start; pos2 = start;
@@ -326,7 +337,9 @@ private:
} }
} }
// Look for query (\?([^#]*))? // Look for query (\?([^#]*))?
query_ = path_ + GetPathStringLength() + 1; // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
query_ = path_ + GetPathStringLength();
query_++;
*query_ = '\0'; *query_ = '\0';
if (start < len && uri[start] == '?') { if (start < len && uri[start] == '?') {
pos2 = start + 1; pos2 = start + 1;
@@ -341,7 +354,9 @@ private:
} }
} }
// Look for fragment (#(.*))? // Look for fragment (#(.*))?
frag_ = query_ + GetQueryStringLength() + 1; // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
frag_ = query_ + GetQueryStringLength();
frag_++;
*frag_ = '\0'; *frag_ = '\0';
if (start < len && uri[start] == '#') { if (start < len && uri[start] == '#') {
std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch)); std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch));

View File

@@ -67,6 +67,7 @@ enum WriteFlag {
kWriteNoFlags = 0, //!< No flags are set. kWriteNoFlags = 0, //!< No flags are set.
kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
kWriteNanAndInfNullFlag = 4, //!< Allow writing of Infinity, -Infinity and NaN as null.
kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
}; };
@@ -349,8 +350,13 @@ protected:
bool WriteDouble(double d) { bool WriteDouble(double d) {
if (internal::Double(d).IsNanOrInf()) { if (internal::Double(d).IsNanOrInf()) {
if (!(writeFlags & kWriteNanAndInfFlag)) if (!(writeFlags & kWriteNanAndInfFlag) && !(writeFlags & kWriteNanAndInfNullFlag))
return false; return false;
if (writeFlags & kWriteNanAndInfNullFlag) {
PutReserve(*os_, 4);
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l');
return true;
}
if (internal::Double(d).IsNan()) { if (internal::Double(d).IsNan()) {
PutReserve(*os_, 3); PutReserve(*os_, 3);
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
@@ -549,6 +555,11 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) {
// Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
return false; return false;
if (kWriteDefaultFlags & kWriteNanAndInfNullFlag) {
PutReserve(*os_, 4);
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l');
return true;
}
if (internal::Double(d).IsNan()) { if (internal::Double(d).IsNan()) {
PutReserve(*os_, 3); PutReserve(*os_, 3);
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');

View File

@@ -30,10 +30,10 @@
#include "base/tools/Handle.h" #include "base/tools/Handle.h"
inline static const char *format(double h, char *buf, size_t size) inline static const char *format(std::pair<bool, double> h, char *buf, size_t size)
{ {
if (std::isnormal(h)) { if (h.first) {
snprintf(buf, size, (h < 100.0) ? "%04.2f" : "%03.1f", h); snprintf(buf, size, (h.second < 100.0) ? "%04.2f" : "%03.1f", h.second);
return buf; return buf;
} }
@@ -80,15 +80,16 @@ double xmrig::Hashrate::average() const
} }
const char *xmrig::Hashrate::format(double h, char *buf, size_t size) const char *xmrig::Hashrate::format(std::pair<bool, double> h, char *buf, size_t size)
{ {
return ::format(h, buf, size); return ::format(h, buf, size);
} }
rapidjson::Value xmrig::Hashrate::normalize(double d) rapidjson::Value xmrig::Hashrate::normalize(std::pair<bool, double> d)
{ {
return Json::normalize(d, false); using namespace rapidjson;
return d.first ? Value(floor(d.second * 100.0) / 100.0) : Value(kNullType);
} }
@@ -122,11 +123,11 @@ rapidjson::Value xmrig::Hashrate::toJSON(size_t threadId, rapidjson::Document &d
#endif #endif
double xmrig::Hashrate::hashrate(size_t index, size_t ms) const std::pair<bool, double> xmrig::Hashrate::hashrate(size_t index, size_t ms) const
{ {
assert(index < m_threads); assert(index < m_threads);
if (index >= m_threads) { if (index >= m_threads) {
return nan(""); return { false, 0.0 };
} }
uint64_t earliestHashCount = 0; uint64_t earliestHashCount = 0;
@@ -157,17 +158,27 @@ double xmrig::Hashrate::hashrate(size_t index, size_t ms) const
} while (idx != idx_start); } while (idx != idx_start);
if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) { if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) {
return nan(""); return { false, 0.0 };
} }
if (lastestStamp - earliestStamp == 0) { if (lastestHashCnt == earliestHashCount) {
return nan(""); return { true, 0.0 };
}
if (lastestStamp == earliestStamp) {
return { false, 0.0 };
} }
const auto hashes = static_cast<double>(lastestHashCnt - earliestHashCount); const auto hashes = static_cast<double>(lastestHashCnt - earliestHashCount);
const auto time = static_cast<double>(lastestStamp - earliestStamp) / 1000.0; const auto time = static_cast<double>(lastestStamp - earliestStamp);
return hashes / time; const auto hr = hashes * 1000.0 / time;
if (!std::isnormal(hr)) {
return { false, 0.0 };
}
return { true, hr };
} }

View File

@@ -47,16 +47,16 @@ public:
Hashrate(size_t threads); Hashrate(size_t threads);
~Hashrate(); ~Hashrate();
inline double calc(size_t ms) const { const double data = hashrate(0U, ms); return std::isnormal(data) ? data : 0.0; } inline std::pair<bool, double> calc(size_t ms) const { return hashrate(0U, ms); }
inline double calc(size_t threadId, size_t ms) const { return hashrate(threadId + 1, ms); } inline std::pair<bool, double> calc(size_t threadId, size_t ms) const { return hashrate(threadId + 1, ms); }
inline size_t threads() const { return m_threads > 0U ? m_threads - 1U : 0U; } inline size_t threads() const { return m_threads > 0U ? m_threads - 1U : 0U; }
inline void add(size_t threadId, uint64_t count, uint64_t timestamp) { addData(threadId + 1U, count, timestamp); } inline void add(size_t threadId, uint64_t count, uint64_t timestamp) { addData(threadId + 1U, count, timestamp); }
inline void add(uint64_t count, uint64_t timestamp) { addData(0U, count, timestamp); } inline void add(uint64_t count, uint64_t timestamp) { addData(0U, count, timestamp); }
double average() const; double average() const;
static const char *format(double h, char *buf, size_t size); static const char *format(std::pair<bool, double> h, char *buf, size_t size);
static rapidjson::Value normalize(double d); static rapidjson::Value normalize(std::pair<bool, double> d);
# ifdef XMRIG_FEATURE_API # ifdef XMRIG_FEATURE_API
rapidjson::Value toJSON(rapidjson::Document &doc) const; rapidjson::Value toJSON(rapidjson::Document &doc) const;
@@ -64,7 +64,7 @@ public:
# endif # endif
private: private:
double hashrate(size_t index, size_t ms) const; std::pair<bool, double> hashrate(size_t index, size_t ms) const;
void addData(size_t index, uint64_t count, uint64_t timestamp); void addData(size_t index, uint64_t count, uint64_t timestamp);
constexpr static size_t kBucketSize = 2 << 11; constexpr static size_t kBucketSize = 2 << 11;

View File

@@ -1,6 +1,6 @@
/* XMRig /* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright (c) 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -19,10 +19,8 @@
#ifndef XMRIG_PCITOPOLOGY_H #ifndef XMRIG_PCITOPOLOGY_H
#define XMRIG_PCITOPOLOGY_H #define XMRIG_PCITOPOLOGY_H
#include <cstdio> #include <cstdio>
#include "base/tools/String.h" #include "base/tools/String.h"
@@ -33,7 +31,14 @@ class PciTopology
{ {
public: public:
PciTopology() = default; PciTopology() = default;
PciTopology(uint32_t bus, uint32_t device, uint32_t function) : m_valid(true), m_bus(bus), m_device(device), m_function(function) {}
template<typename T>
inline PciTopology(T bus, T device, T function)
: m_valid(true),
m_bus(static_cast<uint8_t>(bus)),
m_device(static_cast<uint8_t>(device)),
m_function(static_cast<uint8_t>(function))
{}
inline bool isEqual(const PciTopology &other) const { return m_valid == other.m_valid && toUint32() == other.toUint32(); } inline bool isEqual(const PciTopology &other) const { return m_valid == other.m_valid && toUint32() == other.toUint32(); }
inline bool isValid() const { return m_valid; } inline bool isValid() const { return m_valid; }
@@ -70,4 +75,4 @@ private:
} // namespace xmrig } // namespace xmrig
#endif /* XMRIG_PCITOPOLOGY_H */ #endif // XMRIG_PCITOPOLOGY_H

View File

@@ -359,7 +359,9 @@ void xmrig::CpuWorker<N>::start()
} }
} }
consumeJob(); if (!Nonce::isPaused()) {
consumeJob();
}
} }
} }

View File

@@ -49,8 +49,15 @@ endif()
if (XMRIG_ARM) if (XMRIG_ARM)
list(APPEND SOURCES_BACKEND_CPU src/backend/cpu/platform/BasicCpuInfo_arm.cpp) list(APPEND SOURCES_BACKEND_CPU src/backend/cpu/platform/BasicCpuInfo_arm.cpp)
if (XMRIG_OS_UNIX) if (XMRIG_OS_WIN)
list(APPEND SOURCES_BACKEND_CPU src/backend/cpu/platform/lscpu_arm.cpp) list(APPEND SOURCES_BACKEND_CPU src/backend/cpu/platform/BasicCpuInfo_arm_win.cpp)
elseif(XMRIG_OS_APPLE)
list(APPEND SOURCES_BACKEND_CPU src/backend/cpu/platform/BasicCpuInfo_arm_mac.cpp)
else()
list(APPEND SOURCES_BACKEND_CPU
src/backend/cpu/platform/lscpu_arm.cpp
src/backend/cpu/platform/BasicCpuInfo_arm_unix.cpp
)
endif() endif()
else() else()
list(APPEND SOURCES_BACKEND_CPU src/backend/cpu/platform/BasicCpuInfo.cpp) list(APPEND SOURCES_BACKEND_CPU src/backend/cpu/platform/BasicCpuInfo.cpp)

View File

@@ -1,7 +1,7 @@
/* XMRig /* XMRig
* Copyright (c) 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright (c) 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <support@xmrig.com> * Copyright (c) 2016-2025 XMRig <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -85,6 +85,8 @@ private:
uint32_t m_family = 0; uint32_t m_family = 0;
uint32_t m_model = 0; uint32_t m_model = 0;
uint32_t m_stepping = 0; uint32_t m_stepping = 0;
# else
void init_arm();
# endif # endif
Assembly m_assembly = Assembly::NONE; Assembly m_assembly = Assembly::NONE;

View File

@@ -1,6 +1,6 @@
/* XMRig /* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <support@xmrig.com> * Copyright (c) 2016-2025 XMRig <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -16,44 +16,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "base/tools/String.h"
#include <array> #include <array>
#include <cstring> #include <cstring>
#include <fstream>
#include <thread> #include <thread>
#if __ARM_FEATURE_CRYPTO && !defined(__APPLE__)
# include <sys/auxv.h>
# if !defined(XMRIG_OS_FREEBSD)
# include <asm/hwcap.h>
# else
# include <stdint.h>
# include <machine/armreg.h>
# ifndef ID_AA64ISAR0_AES_VAL
# define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES
# endif
# endif
#endif
#include "backend/cpu/platform/BasicCpuInfo.h" #include "backend/cpu/platform/BasicCpuInfo.h"
#include "3rdparty/rapidjson/document.h" #include "3rdparty/rapidjson/document.h"
#if defined(XMRIG_OS_UNIX)
namespace xmrig {
extern String cpu_name_arm();
} // namespace xmrig
#elif defined(XMRIG_OS_MACOS)
# include <sys/sysctl.h>
#endif
xmrig::BasicCpuInfo::BasicCpuInfo() : xmrig::BasicCpuInfo::BasicCpuInfo() :
m_threads(std::thread::hardware_concurrency()) m_threads(std::thread::hardware_concurrency())
{ {
@@ -68,28 +39,7 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
memcpy(m_brand, "ARMv7", 5); memcpy(m_brand, "ARMv7", 5);
# endif # endif
# if __ARM_FEATURE_CRYPTO init_arm();
# if defined(__APPLE__)
m_flags.set(FLAG_AES, true);
# elif defined(XMRIG_OS_FREEBSD)
uint64_t isar0 = READ_SPECIALREG(id_aa64isar0_el1);
m_flags.set(FLAG_AES, ID_AA64ISAR0_AES_VAL(isar0) >= ID_AA64ISAR0_AES_BASE);
# else
m_flags.set(FLAG_AES, getauxval(AT_HWCAP) & HWCAP_AES);
# endif
# endif
# if defined(XMRIG_OS_UNIX)
auto name = cpu_name_arm();
if (!name.isNull()) {
strncpy(m_brand, name, sizeof(m_brand) - 1);
}
m_flags.set(FLAG_PDPE1GB, std::ifstream("/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages").good());
# elif defined(XMRIG_OS_MACOS)
size_t buflen = sizeof(m_brand);
sysctlbyname("machdep.cpu.brand_string", &m_brand, &buflen, nullptr, 0);
# endif
} }

View File

@@ -0,0 +1,32 @@
/* XMRig
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/cpu/platform/BasicCpuInfo.h"
#include <sys/sysctl.h>
void xmrig::BasicCpuInfo::init_arm()
{
# if __ARM_FEATURE_CRYPTO
m_flags.set(FLAG_AES, true); // FIXME
# endif
size_t buflen = sizeof(m_brand);
sysctlbyname("machdep.cpu.brand_string", &m_brand, &buflen, nullptr, 0);
}

View File

@@ -0,0 +1,68 @@
/* XMRig
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/cpu/platform/BasicCpuInfo.h"
#include "base/tools/String.h"
#include <fstream>
#if __ARM_FEATURE_CRYPTO
# include <sys/auxv.h>
# if !defined(XMRIG_OS_FREEBSD)
# include <asm/hwcap.h>
# else
# include <stdint.h>
# include <machine/armreg.h>
# ifndef ID_AA64ISAR0_AES_VAL
# define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES
# endif
# endif
#endif
namespace xmrig {
extern String cpu_name_arm();
} // namespace xmrig
void xmrig::BasicCpuInfo::init_arm()
{
# if __ARM_FEATURE_CRYPTO
# if defined(XMRIG_OS_FREEBSD)
uint64_t isar0 = READ_SPECIALREG(id_aa64isar0_el1);
m_flags.set(FLAG_AES, ID_AA64ISAR0_AES_VAL(isar0) >= ID_AA64ISAR0_AES_BASE);
# else
m_flags.set(FLAG_AES, getauxval(AT_HWCAP) & HWCAP_AES);
# endif
# endif
# if defined(XMRIG_OS_UNIX)
auto name = cpu_name_arm();
if (!name.isNull()) {
strncpy(m_brand, name, sizeof(m_brand) - 1);
}
m_flags.set(FLAG_PDPE1GB, std::ifstream("/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages").good());
# endif
}

View File

@@ -0,0 +1,27 @@
/* XMRig
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/cpu/platform/BasicCpuInfo.h"
void xmrig::BasicCpuInfo::init_arm()
{
# if __ARM_FEATURE_CRYPTO
m_flags.set(FLAG_AES, true); // FIXME
# endif
}

View File

@@ -320,13 +320,20 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith
L2 += l2->attr->cache.size; L2 += l2->attr->cache.size;
L2_associativity = l2->attr->cache.associativity; L2_associativity = l2->attr->cache.associativity;
if (L3_exclusive && l2->attr->cache.size >= scratchpad) { if (L3_exclusive) {
extra += scratchpad; if (vendor() == VENDOR_AMD) {
// For some reason, AMD CPUs can use only half of the exclusive L2/L3 cache combo efficiently
extra += std::min<size_t>(l2->attr->cache.size / 2, scratchpad);
}
else if (l2->attr->cache.size >= scratchpad) {
extra += scratchpad;
}
} }
} }
} }
if (scratchpad == 2 * oneMiB) { // This code is supposed to run only on Intel CPUs
if ((vendor() == VENDOR_INTEL) && (scratchpad == 2 * oneMiB)) {
if (L2 && (cores.size() * oneMiB) == L2 && L2_associativity == 16 && L3 >= L2) { if (L2 && (cores.size() * oneMiB) == L2 && L2_associativity == 16 && L3 >= L2) {
L3 = L2; L3 = L2;
extra = L2; extra = L2;
@@ -341,7 +348,7 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith
} }
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
if ((algorithm.family() == Algorithm::RANDOM_X) && L3_exclusive && (PUs > cores.size()) && (PUs < cores.size() * 2)) { if ((vendor() == VENDOR_INTEL) && (algorithm.family() == Algorithm::RANDOM_X) && L3_exclusive && (PUs < cores.size() * 2)) {
// Use all L3+L2 on latest Intel CPUs with P-cores, E-cores and exclusive L3 cache // Use all L3+L2 on latest Intel CPUs with P-cores, E-cores and exclusive L3 cache
cacheHashes = (L3 + L2) / scratchpad; cacheHashes = (L3 + L2) / scratchpad;
} }

View File

@@ -1,6 +1,6 @@
/* XMRig /* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright (c) 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -227,7 +227,7 @@ public:
# endif # endif
Log::print("|" CYAN_BOLD("%3zu") " |" CYAN_BOLD("%4u") " |" YELLOW(" %7s") " |" CYAN_BOLD("%10d") " |" CYAN_BOLD("%8d") " |" Log::print("|" CYAN_BOLD("%3zu") " |" CYAN_BOLD("%4u") " |" YELLOW(" %7s") " |" CYAN_BOLD("%10d") " |" CYAN_BOLD("%8d") " |"
CYAN_BOLD("%7d") " |" CYAN_BOLD("%3d") " |" CYAN_BOLD("%4d") " |" CYAN("%7zu") " | " GREEN("%s"), CYAN_BOLD("%7d") " |" CYAN_BOLD("%3d") " |" CYAN_BOLD("%4d") " |" CYAN("%7zu") " | " GREEN_BOLD("%s"),
i, i,
data.thread.index(), data.thread.index(),
data.device.topology().toString().data(), data.device.topology().toString().data(),
@@ -372,15 +372,20 @@ void xmrig::CudaBackend::printHashrate(bool details)
char num[16 * 3] = { 0 }; char num[16 * 3] = { 0 };
const double hashrate_short = hashrate()->calc(Hashrate::ShortInterval); auto hashrate_short = hashrate()->calc(Hashrate::ShortInterval);
const double hashrate_medium = hashrate()->calc(Hashrate::MediumInterval); auto hashrate_medium = hashrate()->calc(Hashrate::MediumInterval);
const double hashrate_large = hashrate()->calc(Hashrate::LargeInterval); auto hashrate_large = hashrate()->calc(Hashrate::LargeInterval);
double scale = 1.0; double scale = 1.0;
const char* h = " H/s"; const char* h = " H/s";
if ((hashrate_short >= 1e6) || (hashrate_medium >= 1e6) || (hashrate_large >= 1e6)) { if ((hashrate_short.second >= 1e6) || (hashrate_medium.second >= 1e6) || (hashrate_large.second >= 1e6)) {
scale = 1e-6; scale = 1e-6;
hashrate_short.second *= scale;
hashrate_medium.second *= scale;
hashrate_large.second *= scale;
h = "MH/s"; h = "MH/s";
} }
@@ -388,12 +393,20 @@ void xmrig::CudaBackend::printHashrate(bool details)
size_t i = 0; size_t i = 0;
for (const auto& data : d_ptr->threads) { for (const auto& data : d_ptr->threads) {
Log::print("| %8zu | %8" PRId64 " | %8s | %8s | %8s |" CYAN_BOLD(" #%u") YELLOW(" %s") GREEN(" %s"), auto h0 = hashrate()->calc(i, Hashrate::ShortInterval);
auto h1 = hashrate()->calc(i, Hashrate::MediumInterval);
auto h2 = hashrate()->calc(i, Hashrate::LargeInterval);
h0.second *= scale;
h1.second *= scale;
h2.second *= scale;
Log::print("| %8zu | %8" PRId64 " | %8s | %8s | %8s |" CYAN_BOLD(" #%u") YELLOW(" %s") GREEN(" %s"),
i, i,
data.thread.affinity(), data.thread.affinity(),
Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval) * scale, num, sizeof num / 3), Hashrate::format(h0, num, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval) * scale, num + 16, sizeof num / 3), Hashrate::format(h1, num + 16, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval) * scale, num + 16 * 2, sizeof num / 3), Hashrate::format(h2, num + 16 * 2, sizeof num / 3),
data.device.index(), data.device.index(),
data.device.topology().toString().data(), data.device.topology().toString().data(),
data.device.name().data() data.device.name().data()
@@ -403,9 +416,9 @@ void xmrig::CudaBackend::printHashrate(bool details)
} }
Log::print(WHITE_BOLD_S "| - | - | %8s | %8s | %8s |", Log::print(WHITE_BOLD_S "| - | - | %8s | %8s | %8s |",
Hashrate::format(hashrate_short * scale, num, sizeof num / 3), Hashrate::format(hashrate_short , num, sizeof num / 3),
Hashrate::format(hashrate_medium * scale, num + 16, sizeof num / 3), Hashrate::format(hashrate_medium, num + 16, sizeof num / 3),
Hashrate::format(hashrate_large * scale, num + 16 * 2, sizeof num / 3) Hashrate::format(hashrate_large , num + 16 * 2, sizeof num / 3)
); );
} }

View File

@@ -158,7 +158,7 @@ void xmrig::CudaWorker::start()
std::this_thread::yield(); std::this_thread::yield();
} }
if (!consumeJob()) { if (isReady() && !consumeJob()) {
return; return;
} }
} }

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet> * Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh> * Copyright 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -22,7 +22,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "backend/cuda/runners/CudaRxRunner.h" #include "backend/cuda/runners/CudaRxRunner.h"
#include "backend/cuda/CudaLaunchData.h" #include "backend/cuda/CudaLaunchData.h"
#include "backend/cuda/wrappers/CudaLib.h" #include "backend/cuda/wrappers/CudaLib.h"
@@ -55,12 +54,21 @@ bool xmrig::CudaRxRunner::run(uint32_t startNonce, uint32_t *rescount, uint32_t
bool xmrig::CudaRxRunner::set(const Job &job, uint8_t *blob) bool xmrig::CudaRxRunner::set(const Job &job, uint8_t *blob)
{ {
if (!m_datasetHost && (m_seed != job.seed())) {
m_seed = job.seed();
if (m_ready) {
const auto *dataset = Rx::dataset(job, 0);
callWrapper(CudaLib::rxUpdateDataset(m_ctx, dataset->raw(), dataset->size(false)));
}
}
const bool rc = CudaBaseRunner::set(job, blob); const bool rc = CudaBaseRunner::set(job, blob);
if (!rc || m_ready) { if (!rc || m_ready) {
return rc; return rc;
} }
auto dataset = Rx::dataset(job, 0); const auto *dataset = Rx::dataset(job, 0);
m_ready = callWrapper(CudaLib::rxPrepare(m_ctx, dataset->raw(), dataset->size(false), m_datasetHost, m_intensity)); m_ready = callWrapper(CudaLib::rxPrepare(m_ctx, dataset->raw(), dataset->size(false), m_datasetHost, m_intensity));
return m_ready; return m_ready;

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet> * Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh> * Copyright 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
#include "backend/cuda/runners/CudaBaseRunner.h" #include "backend/cuda/runners/CudaBaseRunner.h"
#include "base/tools/Buffer.h"
namespace xmrig { namespace xmrig {
@@ -46,6 +47,7 @@ protected:
private: private:
bool m_ready = false; bool m_ready = false;
const bool m_datasetHost = false; const bool m_datasetHost = false;
Buffer m_seed;
size_t m_intensity = 0; size_t m_intensity = 0;
}; };

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet> * Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh> * Copyright 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -22,7 +22,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "backend/cuda/wrappers/CudaDevice.h" #include "backend/cuda/wrappers/CudaDevice.h"
#include "3rdparty/rapidjson/document.h" #include "3rdparty/rapidjson/document.h"
#include "backend/cuda/CudaThreads.h" #include "backend/cuda/CudaThreads.h"
@@ -41,7 +40,7 @@
xmrig::CudaDevice::CudaDevice(uint32_t index, int32_t bfactor, int32_t bsleep) : xmrig::CudaDevice::CudaDevice(uint32_t index, int32_t bfactor, int32_t bsleep) :
m_index(index) m_index(index)
{ {
auto ctx = CudaLib::alloc(index, bfactor, bsleep); auto *ctx = CudaLib::alloc(index, bfactor, bsleep);
if (!CudaLib::deviceInfo(ctx, 0, 0, Algorithm::INVALID)) { if (!CudaLib::deviceInfo(ctx, 0, 0, Algorithm::INVALID)) {
CudaLib::release(ctx); CudaLib::release(ctx);
@@ -50,7 +49,7 @@ xmrig::CudaDevice::CudaDevice(uint32_t index, int32_t bfactor, int32_t bsleep) :
m_ctx = ctx; m_ctx = ctx;
m_name = CudaLib::deviceName(ctx); m_name = CudaLib::deviceName(ctx);
m_topology = PciTopology(CudaLib::deviceUint(ctx, CudaLib::DevicePciBusID), CudaLib::deviceUint(ctx, CudaLib::DevicePciDeviceID), 0); m_topology = { CudaLib::deviceUint(ctx, CudaLib::DevicePciBusID), CudaLib::deviceUint(ctx, CudaLib::DevicePciDeviceID), 0U };
} }

View File

@@ -19,10 +19,10 @@
#include <stdexcept> #include <stdexcept>
#include <uv.h> #include <uv.h>
#include "backend/cuda/wrappers/CudaLib.h" #include "backend/cuda/wrappers/CudaLib.h"
#include "base/io/Env.h" #include "base/io/Env.h"
#include "base/io/log/Log.h" #include "base/io/log/Log.h"
#include "base/io/log/Tags.h"
#include "base/kernel/Process.h" #include "base/kernel/Process.h"
#include "crypto/rx/RxAlgo.h" #include "crypto/rx/RxAlgo.h"
@@ -68,6 +68,7 @@ static const char *kPluginVersion = "pluginVersion";
static const char *kRelease = "release"; static const char *kRelease = "release";
static const char *kRxHash = "rxHash"; static const char *kRxHash = "rxHash";
static const char *kRxPrepare = "rxPrepare"; static const char *kRxPrepare = "rxPrepare";
static const char *kRxUpdateDataset = "rxUpdateDataset";
static const char *kSetJob = "setJob"; static const char *kSetJob = "setJob";
static const char *kSetJob_v2 = "setJob_v2"; static const char *kSetJob_v2 = "setJob_v2";
static const char *kVersion = "version"; static const char *kVersion = "version";
@@ -92,6 +93,7 @@ using pluginVersion_t = const char * (*)();
using release_t = void (*)(nvid_ctx *); using release_t = void (*)(nvid_ctx *);
using rxHash_t = bool (*)(nvid_ctx *, uint32_t, uint64_t, uint32_t *, uint32_t *); using rxHash_t = bool (*)(nvid_ctx *, uint32_t, uint64_t, uint32_t *, uint32_t *);
using rxPrepare_t = bool (*)(nvid_ctx *, const void *, size_t, bool, uint32_t); using rxPrepare_t = bool (*)(nvid_ctx *, const void *, size_t, bool, uint32_t);
using rxUpdateDataset_t = bool (*)(nvid_ctx *, const void *, size_t);
using setJob_t = bool (*)(nvid_ctx *, const void *, size_t, uint32_t); using setJob_t = bool (*)(nvid_ctx *, const void *, size_t, uint32_t);
using setJob_v2_t = bool (*)(nvid_ctx *, const void *, size_t, const char *); using setJob_v2_t = bool (*)(nvid_ctx *, const void *, size_t, const char *);
using version_t = uint32_t (*)(Version); using version_t = uint32_t (*)(Version);
@@ -116,6 +118,7 @@ static pluginVersion_t pPluginVersion = nullptr;
static release_t pRelease = nullptr; static release_t pRelease = nullptr;
static rxHash_t pRxHash = nullptr; static rxHash_t pRxHash = nullptr;
static rxPrepare_t pRxPrepare = nullptr; static rxPrepare_t pRxPrepare = nullptr;
static rxUpdateDataset_t pRxUpdateDataset = nullptr;
static setJob_t pSetJob = nullptr; static setJob_t pSetJob = nullptr;
static setJob_v2_t pSetJob_v2 = nullptr; static setJob_v2_t pSetJob_v2 = nullptr;
static version_t pVersion = nullptr; static version_t pVersion = nullptr;
@@ -202,10 +205,26 @@ bool xmrig::CudaLib::rxHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t target,
bool xmrig::CudaLib::rxPrepare(nvid_ctx *ctx, const void *dataset, size_t datasetSize, bool dataset_host, uint32_t batchSize) noexcept bool xmrig::CudaLib::rxPrepare(nvid_ctx *ctx, const void *dataset, size_t datasetSize, bool dataset_host, uint32_t batchSize) noexcept
{ {
# ifdef XMRIG_ALGO_RANDOMX
if (!pRxUpdateDataset) {
LOG_WARN("%s" YELLOW_BOLD("CUDA plugin is outdated. Please update to the latest version"), Tags::randomx());
}
# endif
return pRxPrepare(ctx, dataset, datasetSize, dataset_host, batchSize); return pRxPrepare(ctx, dataset, datasetSize, dataset_host, batchSize);
} }
bool xmrig::CudaLib::rxUpdateDataset(nvid_ctx *ctx, const void *dataset, size_t datasetSize) noexcept
{
if (pRxUpdateDataset) {
return pRxUpdateDataset(ctx, dataset, datasetSize);
}
return true;
}
bool xmrig::CudaLib::kawPowHash(nvid_ctx *ctx, uint8_t* job_blob, uint64_t target, uint32_t *rescount, uint32_t *resnonce, uint32_t *skipped_hashes) noexcept bool xmrig::CudaLib::kawPowHash(nvid_ctx *ctx, uint8_t* job_blob, uint64_t target, uint32_t *rescount, uint32_t *resnonce, uint32_t *skipped_hashes) noexcept
{ {
return pKawPowHash(ctx, job_blob, target, rescount, resnonce, skipped_hashes); return pKawPowHash(ctx, job_blob, target, rescount, resnonce, skipped_hashes);
@@ -401,5 +420,7 @@ void xmrig::CudaLib::load()
DLSYM(SetJob_v2); DLSYM(SetJob_v2);
} }
uv_dlsym(&cudaLib, kRxUpdateDataset, reinterpret_cast<void**>(&pRxUpdateDataset));
pInit(); pInit();
} }

View File

@@ -1,6 +1,6 @@
/* XMRig /* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright (c) 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -71,6 +71,7 @@ public:
static bool deviceInit(nvid_ctx *ctx) noexcept; static bool deviceInit(nvid_ctx *ctx) noexcept;
static bool rxHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t target, uint32_t *rescount, uint32_t *resnonce) noexcept; static bool rxHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t target, uint32_t *rescount, uint32_t *resnonce) noexcept;
static bool rxPrepare(nvid_ctx *ctx, const void *dataset, size_t datasetSize, bool dataset_host, uint32_t batchSize) noexcept; static bool rxPrepare(nvid_ctx *ctx, const void *dataset, size_t datasetSize, bool dataset_host, uint32_t batchSize) noexcept;
static bool rxUpdateDataset(nvid_ctx *ctx, const void *dataset, size_t datasetSize) noexcept;
static bool kawPowHash(nvid_ctx *ctx, uint8_t* job_blob, uint64_t target, uint32_t *rescount, uint32_t *resnonce, uint32_t *skipped_hashes) noexcept; static bool kawPowHash(nvid_ctx *ctx, uint8_t* job_blob, uint64_t target, uint32_t *rescount, uint32_t *resnonce, uint32_t *skipped_hashes) noexcept;
static bool kawPowPrepare(nvid_ctx *ctx, const void* cache, size_t cache_size, const void* dag_precalc, size_t dag_size, uint32_t height, const uint64_t* dag_sizes) noexcept; static bool kawPowPrepare(nvid_ctx *ctx, const void* cache, size_t cache_size, const void* dag_precalc, size_t dag_size, uint32_t height, const uint64_t* dag_sizes) noexcept;
static bool kawPowStopHash(nvid_ctx *ctx) noexcept; static bool kawPowStopHash(nvid_ctx *ctx) noexcept;

View File

@@ -352,15 +352,20 @@ void xmrig::OclBackend::printHashrate(bool details)
char num[16 * 3] = { 0 }; char num[16 * 3] = { 0 };
const double hashrate_short = hashrate()->calc(Hashrate::ShortInterval); auto hashrate_short = hashrate()->calc(Hashrate::ShortInterval);
const double hashrate_medium = hashrate()->calc(Hashrate::MediumInterval); auto hashrate_medium = hashrate()->calc(Hashrate::MediumInterval);
const double hashrate_large = hashrate()->calc(Hashrate::LargeInterval); auto hashrate_large = hashrate()->calc(Hashrate::LargeInterval);
double scale = 1.0; double scale = 1.0;
const char* h = " H/s"; const char* h = " H/s";
if ((hashrate_short >= 1e6) || (hashrate_medium >= 1e6) || (hashrate_large >= 1e6)) { if ((hashrate_short.second >= 1e6) || (hashrate_medium.second >= 1e6) || (hashrate_large.second >= 1e6)) {
scale = 1e-6; scale = 1e-6;
hashrate_short.second *= scale;
hashrate_medium.second *= scale;
hashrate_large.second *= scale;
h = "MH/s"; h = "MH/s";
} }
@@ -368,12 +373,16 @@ void xmrig::OclBackend::printHashrate(bool details)
size_t i = 0; size_t i = 0;
for (const auto& data : d_ptr->threads) { for (const auto& data : d_ptr->threads) {
Log::print("| %8zu | %8" PRId64 " | %8s | %8s | %8s |" CYAN_BOLD(" #%u") YELLOW(" %s") " %s", auto h0 = hashrate()->calc(i, Hashrate::ShortInterval);
auto h1 = hashrate()->calc(i, Hashrate::MediumInterval);
auto h2 = hashrate()->calc(i, Hashrate::LargeInterval);
Log::print("| %8zu | %8" PRId64 " | %8s | %8s | %8s |" CYAN_BOLD(" #%u") YELLOW(" %s") " %s",
i, i,
data.affinity, data.affinity,
Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval) * scale, num, sizeof num / 3), Hashrate::format(h0, num, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval) * scale, num + 16, sizeof num / 3), Hashrate::format(h1, num + 16, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval) * scale, num + 16 * 2, sizeof num / 3), Hashrate::format(h2, num + 16 * 2, sizeof num / 3),
data.device.index(), data.device.index(),
data.device.topology().toString().data(), data.device.topology().toString().data(),
data.device.printableName().data() data.device.printableName().data()
@@ -383,9 +392,9 @@ void xmrig::OclBackend::printHashrate(bool details)
} }
Log::print(WHITE_BOLD_S "| - | - | %8s | %8s | %8s |", Log::print(WHITE_BOLD_S "| - | - | %8s | %8s | %8s |",
Hashrate::format(hashrate_short * scale, num, sizeof num / 3), Hashrate::format(hashrate_short , num, sizeof num / 3),
Hashrate::format(hashrate_medium * scale, num + 16, sizeof num / 3), Hashrate::format(hashrate_medium, num + 16, sizeof num / 3),
Hashrate::format(hashrate_large * scale, num + 16 * 2, sizeof num / 3) Hashrate::format(hashrate_large , num + 16 * 2, sizeof num / 3)
); );
} }

View File

@@ -190,7 +190,7 @@ void xmrig::OclWorker::start()
std::this_thread::yield(); std::this_thread::yield();
} }
if (!consumeJob()) { if (isReady() && !consumeJob()) {
return; return;
} }
} }

View File

@@ -74,7 +74,7 @@ void keccak_f800_round(uint32_t st[25], const int r)
// Keccak - implemented as a variant of SHAKE // Keccak - implemented as a variant of SHAKE
// The width is 800, with a bitrate of 576, a capacity of 224, and no padding // The width is 800, with a bitrate of 576, a capacity of 224, and no padding
// Only need 64 bits of output for mining // Only need 64 bits of output for mining
uint64_t keccak_f800(uint32_t* st) void keccak_f800(uint32_t* st)
{ {
// Complete all 22 rounds as a separate impl to // Complete all 22 rounds as a separate impl to
// evaluate only first 8 words is wasteful of regsters // evaluate only first 8 words is wasteful of regsters

View File

@@ -2,7 +2,7 @@
namespace xmrig { namespace xmrig {
static const char kawpow_cl[5948] = { static const char kawpow_cl[5944] = {
0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x63,0x6c,0x5f,0x63,0x6c,0x61,0x6e,0x67,0x5f,0x73,0x74,0x6f,0x72,0x61,0x67,0x65,0x5f,0x63,0x6c,0x61,0x73,0x73,0x5f,0x73,0x70, 0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x63,0x6c,0x5f,0x63,0x6c,0x61,0x6e,0x67,0x5f,0x73,0x74,0x6f,0x72,0x61,0x67,0x65,0x5f,0x63,0x6c,0x61,0x73,0x73,0x5f,0x73,0x70,
0x65,0x63,0x69,0x66,0x69,0x65,0x72,0x73,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x4f,0x50,0x45,0x4e,0x43,0x4c,0x20,0x45,0x58,0x54,0x45,0x4e,0x53,0x49,0x4f, 0x65,0x63,0x69,0x66,0x69,0x65,0x72,0x73,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x4f,0x50,0x45,0x4e,0x43,0x4c,0x20,0x45,0x58,0x54,0x45,0x4e,0x53,0x49,0x4f,
0x4e,0x20,0x63,0x6c,0x5f,0x63,0x6c,0x61,0x6e,0x67,0x5f,0x73,0x74,0x6f,0x72,0x61,0x67,0x65,0x5f,0x63,0x6c,0x61,0x73,0x73,0x5f,0x73,0x70,0x65,0x63,0x69,0x66,0x69, 0x4e,0x20,0x63,0x6c,0x5f,0x63,0x6c,0x61,0x6e,0x67,0x5f,0x73,0x74,0x6f,0x72,0x61,0x67,0x65,0x5f,0x63,0x6c,0x61,0x73,0x73,0x5f,0x73,0x70,0x65,0x63,0x69,0x66,0x69,
@@ -76,119 +76,119 @@ static const char kawpow_cl[5948] = {
0x3d,0x73,0x74,0x5b,0x6a,0x2b,0x69,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x35,0x3b,0x20,0x69,0x2b,0x2b, 0x3d,0x73,0x74,0x5b,0x6a,0x2b,0x69,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x35,0x3b,0x20,0x69,0x2b,0x2b,
0x29,0x0a,0x73,0x74,0x5b,0x6a,0x2b,0x69,0x5d,0x20,0x5e,0x3d,0x20,0x28,0x7e,0x62,0x63,0x5b,0x28,0x69,0x2b,0x31,0x29,0x20,0x25,0x20,0x35,0x5d,0x29,0x26,0x62,0x63, 0x29,0x0a,0x73,0x74,0x5b,0x6a,0x2b,0x69,0x5d,0x20,0x5e,0x3d,0x20,0x28,0x7e,0x62,0x63,0x5b,0x28,0x69,0x2b,0x31,0x29,0x20,0x25,0x20,0x35,0x5d,0x29,0x26,0x62,0x63,
0x5b,0x28,0x69,0x2b,0x32,0x29,0x20,0x25,0x20,0x35,0x5d,0x3b,0x0a,0x7d,0x0a,0x73,0x74,0x5b,0x30,0x5d,0x20,0x5e,0x3d,0x20,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x5f, 0x5b,0x28,0x69,0x2b,0x32,0x29,0x20,0x25,0x20,0x35,0x5d,0x3b,0x0a,0x7d,0x0a,0x73,0x74,0x5b,0x30,0x5d,0x20,0x5e,0x3d,0x20,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x5f,
0x72,0x6e,0x64,0x63,0x5b,0x72,0x5d,0x3b,0x0a,0x7d,0x0a,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x28, 0x72,0x6e,0x64,0x63,0x5b,0x72,0x5d,0x3b,0x0a,0x7d,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x28,0x75,0x69,0x6e,0x74,
0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x73,0x74,0x29,0x0a,0x7b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x72,0x3d,0x30,0x3b,0x20,0x72,0x3c, 0x33,0x32,0x5f,0x74,0x2a,0x20,0x73,0x74,0x29,0x0a,0x7b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x72,0x3d,0x30,0x3b,0x20,0x72,0x3c,0x32,0x32,0x3b,0x20,
0x32,0x32,0x3b,0x20,0x72,0x2b,0x2b,0x29,0x20,0x7b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x5f,0x72,0x6f,0x75,0x6e,0x64,0x28,0x73,0x74,0x2c, 0x72,0x2b,0x2b,0x29,0x20,0x7b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x5f,0x72,0x6f,0x75,0x6e,0x64,0x28,0x73,0x74,0x2c,0x72,0x29,0x3b,0x0a,
0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x66,0x6e,0x76,0x31,0x61,0x28,0x68,0x2c,0x20,0x64,0x29,0x20,0x28,0x68,0x20,0x3d, 0x7d,0x0a,0x7d,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x66,0x6e,0x76,0x31,0x61,0x28,0x68,0x2c,0x20,0x64,0x29,0x20,0x28,0x68,0x20,0x3d,0x20,0x28,0x68,0x20,
0x20,0x28,0x68,0x20,0x5e,0x20,0x64,0x29,0x20,0x2a,0x20,0x46,0x4e,0x56,0x5f,0x50,0x52,0x49,0x4d,0x45,0x29,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74, 0x5e,0x20,0x64,0x29,0x20,0x2a,0x20,0x46,0x4e,0x56,0x5f,0x50,0x52,0x49,0x4d,0x45,0x29,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,0x75,0x63,0x74,
0x72,0x75,0x63,0x74,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x7a,0x2c,0x77,0x2c,0x6a,0x73,0x72,0x2c,0x6a,0x63,0x6f,0x6e,0x67,0x3b,0x0a,0x7d, 0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x7a,0x2c,0x77,0x2c,0x6a,0x73,0x72,0x2c,0x6a,0x63,0x6f,0x6e,0x67,0x3b,0x0a,0x7d,0x20,0x6b,0x69,0x73,
0x20,0x6b,0x69,0x73,0x73,0x39,0x39,0x5f,0x74,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6b,0x69,0x73,0x73,0x39,0x39,0x28,0x6b,0x69,0x73,0x73,0x39, 0x73,0x39,0x39,0x5f,0x74,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6b,0x69,0x73,0x73,0x39,0x39,0x28,0x6b,0x69,0x73,0x73,0x39,0x39,0x5f,0x74,0x2a,
0x39,0x5f,0x74,0x2a,0x20,0x73,0x74,0x29,0x0a,0x7b,0x0a,0x73,0x74,0x2d,0x3e,0x7a,0x3d,0x33,0x36,0x39,0x36,0x39,0x2a,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x26,0x36,0x35, 0x20,0x73,0x74,0x29,0x0a,0x7b,0x0a,0x73,0x74,0x2d,0x3e,0x7a,0x3d,0x33,0x36,0x39,0x36,0x39,0x2a,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x26,0x36,0x35,0x35,0x33,0x35,0x29,
0x35,0x33,0x35,0x29,0x2b,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x3e,0x3e,0x31,0x36,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x77,0x3d,0x31,0x38,0x30,0x30,0x30,0x2a,0x28,0x73, 0x2b,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x3e,0x3e,0x31,0x36,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x77,0x3d,0x31,0x38,0x30,0x30,0x30,0x2a,0x28,0x73,0x74,0x2d,0x3e,0x77,
0x74,0x2d,0x3e,0x77,0x26,0x36,0x35,0x35,0x33,0x35,0x29,0x2b,0x28,0x73,0x74,0x2d,0x3e,0x77,0x3e,0x3e,0x31,0x36,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f, 0x26,0x36,0x35,0x35,0x33,0x35,0x29,0x2b,0x28,0x73,0x74,0x2d,0x3e,0x77,0x3e,0x3e,0x31,0x36,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x4d,0x57,
0x74,0x20,0x4d,0x57,0x43,0x3d,0x28,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x3c,0x3c,0x31,0x36,0x29,0x2b,0x73,0x74,0x2d,0x3e,0x77,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a, 0x43,0x3d,0x28,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x3c,0x3c,0x31,0x36,0x29,0x2b,0x73,0x74,0x2d,0x3e,0x77,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x20,0x5e,
0x73,0x72,0x20,0x5e,0x3d,0x20,0x28,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x3c,0x3c,0x31,0x37,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x20,0x5e,0x3d,0x20, 0x3d,0x20,0x28,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x3c,0x3c,0x31,0x37,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x20,0x5e,0x3d,0x20,0x28,0x73,0x74,0x2d,
0x28,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x3e,0x3e,0x31,0x33,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x20,0x5e,0x3d,0x20,0x28,0x73,0x74,0x2d,0x3e,0x6a, 0x3e,0x6a,0x73,0x72,0x3e,0x3e,0x31,0x33,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x20,0x5e,0x3d,0x20,0x28,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x3c,0x3c,
0x73,0x72,0x3c,0x3c,0x35,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e,0x67,0x3d,0x36,0x39,0x30,0x36,0x39,0x2a,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e, 0x35,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e,0x67,0x3d,0x36,0x39,0x30,0x36,0x39,0x2a,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e,0x67,0x2b,0x31,0x32,
0x67,0x2b,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x28,0x4d,0x57,0x43,0x5e,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e, 0x33,0x34,0x35,0x36,0x37,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x28,0x4d,0x57,0x43,0x5e,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e,0x67,0x29,0x2b,0x73,
0x67,0x29,0x2b,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x76,0x6f,0x69,0x64,0x20,0x66,0x69,0x6c,0x6c,0x5f,0x6d,0x69,0x78,0x28,0x6c,0x6f,0x63, 0x74,0x2d,0x3e,0x6a,0x73,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x76,0x6f,0x69,0x64,0x20,0x66,0x69,0x6c,0x6c,0x5f,0x6d,0x69,0x78,0x28,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,
0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x73,0x65,0x65,0x64,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x61,0x6e,0x65,0x5f, 0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x73,0x65,0x65,0x64,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x2c,0x75,
0x69,0x64,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6d,0x69,0x78,0x29,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x66,0x6e,0x76, 0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6d,0x69,0x78,0x29,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,
0x5f,0x68,0x61,0x73,0x68,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53,0x3b,0x0a,0x6b,0x69,0x73,0x73,0x39,0x39,0x5f,0x74, 0x68,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53,0x3b,0x0a,0x6b,0x69,0x73,0x73,0x39,0x39,0x5f,0x74,0x20,0x73,0x74,0x3b,
0x20,0x73,0x74,0x3b,0x0a,0x73,0x74,0x2e,0x7a,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x73,0x65,0x65,0x64,0x5b,0x30,0x5d, 0x0a,0x73,0x74,0x2e,0x7a,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x73,0x65,0x65,0x64,0x5b,0x30,0x5d,0x29,0x3b,0x0a,0x73,
0x29,0x3b,0x0a,0x73,0x74,0x2e,0x77,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x73,0x65,0x65,0x64,0x5b,0x31,0x5d,0x29,0x3b, 0x74,0x2e,0x77,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x73,0x65,0x65,0x64,0x5b,0x31,0x5d,0x29,0x3b,0x0a,0x73,0x74,0x2e,
0x0a,0x73,0x74,0x2e,0x6a,0x73,0x72,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,0x3b, 0x6a,0x73,0x72,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,0x3b,0x0a,0x73,0x74,0x2e,
0x0a,0x73,0x74,0x2e,0x6a,0x63,0x6f,0x6e,0x67,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64, 0x6a,0x63,0x6f,0x6e,0x67,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,0x3b,0x0a,0x23,
0x29,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20, 0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,
0x69,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x6d,0x69,0x78,0x5b,0x69,0x5d,0x3d,0x6b,0x69,0x73,0x73, 0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x6d,0x69,0x78,0x5b,0x69,0x5d,0x3d,0x6b,0x69,0x73,0x73,0x39,0x39,0x28,0x26,
0x39,0x39,0x28,0x26,0x73,0x74,0x29,0x3b,0x0a,0x7d,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74, 0x73,0x74,0x29,0x3b,0x0a,0x7d,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,
0x33,0x32,0x5f,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x5d,0x3b,0x0a,0x7d,0x20,0x73, 0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x5d,0x3b,0x0a,0x7d,0x20,0x73,0x68,0x75,0x66,0x66,
0x68,0x75,0x66,0x66,0x6c,0x65,0x5f,0x74,0x3b,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33, 0x6c,0x65,0x5f,0x74,0x3b,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
0x32,0x5f,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x33,0x32,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x5d, 0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x33,0x32,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x5d,0x3b,0x0a,0x7d,0x20,
0x3b,0x0a,0x7d,0x20,0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x3b,0x0a,0x23,0x69,0x66,0x20,0x50,0x4c,0x41,0x54,0x46,0x4f,0x52,0x4d,0x20,0x21,0x3d,0x20,0x4f,0x50, 0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x3b,0x0a,0x23,0x69,0x66,0x20,0x50,0x4c,0x41,0x54,0x46,0x4f,0x52,0x4d,0x20,0x21,0x3d,0x20,0x4f,0x50,0x45,0x4e,0x43,0x4c,
0x45,0x4e,0x43,0x4c,0x5f,0x50,0x4c,0x41,0x54,0x46,0x4f,0x52,0x4d,0x5f,0x4e,0x56,0x49,0x44,0x49,0x41,0x20,0x0a,0x5f,0x5f,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74, 0x5f,0x50,0x4c,0x41,0x54,0x46,0x4f,0x52,0x4d,0x5f,0x4e,0x56,0x49,0x44,0x49,0x41,0x20,0x0a,0x5f,0x5f,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x5f,0x5f,0x28,
0x65,0x5f,0x5f,0x28,0x28,0x72,0x65,0x71,0x64,0x5f,0x77,0x6f,0x72,0x6b,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x73,0x69,0x7a,0x65,0x28,0x47,0x52,0x4f,0x55,0x50,0x5f, 0x28,0x72,0x65,0x71,0x64,0x5f,0x77,0x6f,0x72,0x6b,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x73,0x69,0x7a,0x65,0x28,0x47,0x52,0x4f,0x55,0x50,0x5f,0x53,0x49,0x5a,0x45,
0x53,0x49,0x5a,0x45,0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64, 0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,0x70,0x72,0x6f,
0x20,0x70,0x72,0x6f,0x67,0x70,0x6f,0x77,0x5f,0x73,0x65,0x61,0x72,0x63,0x68,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x64,0x61,0x67,0x5f,0x74,0x20,0x63, 0x67,0x70,0x6f,0x77,0x5f,0x73,0x65,0x61,0x72,0x63,0x68,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x64,0x61,0x67,0x5f,0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,
0x6f,0x6e,0x73,0x74,0x2a,0x20,0x67,0x5f,0x64,0x61,0x67,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x6a,0x6f,0x62,0x5f,0x62, 0x2a,0x20,0x67,0x5f,0x64,0x61,0x67,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x6a,0x6f,0x62,0x5f,0x62,0x6c,0x6f,0x62,0x2c,
0x6c,0x6f,0x62,0x2c,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2c,0x75,0x69,0x6e,0x74,0x20,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65, 0x75,0x6c,0x6f,0x6e,0x67,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2c,0x75,0x69,0x6e,0x74,0x20,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x2c,0x76,0x6f,0x6c,
0x2c,0x76,0x6f,0x6c,0x61,0x74,0x69,0x6c,0x65,0x20,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73, 0x61,0x74,0x69,0x6c,0x65,0x20,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x2c,0x76,0x6f,0x6c,
0x2c,0x76,0x6f,0x6c,0x61,0x74,0x69,0x6c,0x65,0x20,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x73,0x74,0x6f,0x70,0x29,0x0a,0x7b, 0x61,0x74,0x69,0x6c,0x65,0x20,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x73,0x74,0x6f,0x70,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,
0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x69,0x64,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64, 0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x69,0x64,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,
0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x69,0x64,0x3d,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62, 0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x69,0x64,0x3d,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,
0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x73,0x74,0x6f,0x70,0x5b,0x30,0x5d,0x29,0x20,0x7b,0x0a,0x69,0x66,0x28,0x6c,0x69,0x64,0x3d,0x3d, 0x64,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x73,0x74,0x6f,0x70,0x5b,0x30,0x5d,0x29,0x20,0x7b,0x0a,0x69,0x66,0x28,0x6c,0x69,0x64,0x3d,0x3d,0x30,0x29,0x20,0x7b,
0x30,0x29,0x20,0x7b,0x0a,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,0x28,0x73,0x74,0x6f,0x70,0x2b,0x31,0x29,0x3b,0x0a,0x7d,0x0a,0x72,0x65,0x74,0x75,0x72, 0x0a,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,0x28,0x73,0x74,0x6f,0x70,0x2b,0x31,0x29,0x3b,0x0a,0x7d,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,
0x6e,0x3b,0x0a,0x7d,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x68,0x75,0x66,0x66,0x6c,0x65,0x5f,0x74,0x20,0x73,0x68,0x61,0x72,0x65,0x5b,0x48,0x41,0x53, 0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x68,0x75,0x66,0x66,0x6c,0x65,0x5f,0x74,0x20,0x73,0x68,0x61,0x72,0x65,0x5b,0x48,0x41,0x53,0x48,0x45,0x53,0x5f,
0x48,0x45,0x53,0x5f,0x50,0x45,0x52,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74, 0x50,0x45,0x52,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x63,0x5f,0x64,
0x20,0x63,0x5f,0x64,0x61,0x67,0x5b,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x41,0x43,0x48,0x45,0x5f,0x57,0x4f,0x52,0x44,0x53,0x5d,0x3b,0x0a,0x63,0x6f,0x6e, 0x61,0x67,0x5b,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x41,0x43,0x48,0x45,0x5f,0x57,0x4f,0x52,0x44,0x53,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,
0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x6c,0x69,0x64,0x26,0x28,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57, 0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x6c,0x69,0x64,0x26,0x28,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,
0x5f,0x4c,0x41,0x4e,0x45,0x53,0x2d,0x31,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x72,0x6f,0x75,0x70,0x5f, 0x45,0x53,0x2d,0x31,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x3d,0x6c,
0x69,0x64,0x3d,0x6c,0x69,0x64,0x2f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33, 0x69,0x64,0x2f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
0x32,0x5f,0x74,0x20,0x77,0x6f,0x72,0x64,0x3d,0x6c,0x69,0x64,0x2a,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x3b,0x20, 0x77,0x6f,0x72,0x64,0x3d,0x6c,0x69,0x64,0x2a,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x3b,0x20,0x77,0x6f,0x72,0x64,
0x77,0x6f,0x72,0x64,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x41,0x43,0x48,0x45,0x5f,0x57,0x4f,0x52,0x44,0x53,0x3b,0x20,0x77,0x6f,0x72,0x64,0x2b,0x3d, 0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x41,0x43,0x48,0x45,0x5f,0x57,0x4f,0x52,0x44,0x53,0x3b,0x20,0x77,0x6f,0x72,0x64,0x2b,0x3d,0x47,0x52,0x4f,0x55,
0x47,0x52,0x4f,0x55,0x50,0x5f,0x53,0x49,0x5a,0x45,0x2a,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x29,0x0a,0x7b,0x0a, 0x50,0x5f,0x53,0x49,0x5a,0x45,0x2a,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x29,0x0a,0x7b,0x0a,0x64,0x61,0x67,0x5f,
0x64,0x61,0x67,0x5f,0x74,0x20,0x6c,0x6f,0x61,0x64,0x3d,0x67,0x5f,0x64,0x61,0x67,0x5b,0x77,0x6f,0x72,0x64,0x2f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41, 0x74,0x20,0x6c,0x6f,0x61,0x64,0x3d,0x67,0x5f,0x64,0x61,0x67,0x5b,0x77,0x6f,0x72,0x64,0x2f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,
0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f, 0x41,0x44,0x53,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,
0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x63,0x5f,0x64,0x61,0x67,0x5b,0x77,0x6f,0x72,0x64,0x2b,0x69,0x5d,0x3d, 0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x63,0x5f,0x64,0x61,0x67,0x5b,0x77,0x6f,0x72,0x64,0x2b,0x69,0x5d,0x3d,0x6c,0x6f,0x61,0x64,
0x6c,0x6f,0x61,0x64,0x2e,0x73,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x68,0x61,0x73,0x68,0x5f,0x73,0x65,0x65,0x64,0x5b, 0x2e,0x73,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x68,0x61,0x73,0x68,0x5f,0x73,0x65,0x65,0x64,0x5b,0x32,0x5d,0x3b,0x20,
0x32,0x5d,0x3b,0x20,0x0a,0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x20,0x64,0x69,0x67,0x65,0x73,0x74,0x3b,0x20,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20, 0x0a,0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x20,0x64,0x69,0x67,0x65,0x73,0x74,0x3b,0x20,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,0x74,
0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x38,0x5d,0x3b,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,0x74,0x65,0x5b,0x32,0x35,0x5d,0x3b, 0x65,0x32,0x5b,0x38,0x5d,0x3b,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,0x74,0x65,0x5b,0x32,0x35,0x5d,0x3b,0x20,0x0a,0x66,0x6f,
0x20,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x31,0x30,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65, 0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x31,0x30,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,
0x5b,0x69,0x5d,0x3d,0x6a,0x6f,0x62,0x5f,0x62,0x6c,0x6f,0x62,0x5b,0x69,0x5d,0x3b,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x38,0x5d,0x3d,0x67,0x69,0x64,0x3b,0x0a,0x66, 0x6a,0x6f,0x62,0x5f,0x62,0x6c,0x6f,0x62,0x5b,0x69,0x5d,0x3b,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x38,0x5d,0x3d,0x67,0x69,0x64,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,
0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x31,0x30,0x3b,0x20,0x69,0x3c,0x32,0x35,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69, 0x69,0x6e,0x74,0x20,0x69,0x3d,0x31,0x30,0x3b,0x20,0x69,0x3c,0x32,0x35,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x72,0x61,
0x5d,0x3d,0x72,0x61,0x76,0x65,0x6e,0x63,0x6f,0x69,0x6e,0x5f,0x72,0x6e,0x64,0x63,0x5b,0x69,0x2d,0x31,0x30,0x5d,0x3b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66, 0x76,0x65,0x6e,0x63,0x6f,0x69,0x6e,0x5f,0x72,0x6e,0x64,0x63,0x5b,0x69,0x2d,0x31,0x30,0x5d,0x3b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x28,
0x38,0x30,0x30,0x28,0x73,0x74,0x61,0x74,0x65,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x69, 0x73,0x74,0x61,0x74,0x65,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,
0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x69,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d, 0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x69,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,
0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x68,0x3d,0x30,0x3b,0x20,0x68,0x3c, 0x72,0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x68,0x3d,0x30,0x3b,0x20,0x68,0x3c,0x50,0x52,0x4f,0x47,
0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x20,0x68,0x2b,0x2b,0x29,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6d, 0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x20,0x68,0x2b,0x2b,0x29,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6d,0x69,0x78,0x5b,0x50,
0x69,0x78,0x5b,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x5d,0x3b,0x0a,0x69,0x66,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x3d,0x68,0x29, 0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x5d,0x3b,0x0a,0x69,0x66,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x3d,0x68,0x29,0x20,0x7b,0x0a,0x73,
0x20,0x7b,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x30,0x5d,0x3d,0x73,0x74, 0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x30,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x32,
0x61,0x74,0x65,0x32,0x5b,0x30,0x5d,0x3b,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73, 0x5b,0x30,0x5d,0x3b,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x31,0x5d,0x3d,
0x5b,0x31,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x31,0x5d,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43, 0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x31,0x5d,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,
0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x66,0x69,0x6c,0x6c,0x5f,0x6d,0x69,0x78,0x28,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72, 0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x66,0x69,0x6c,0x6c,0x5f,0x6d,0x69,0x78,0x28,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,
0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x2c,0x6d,0x69,0x78,0x29,0x3b,0x0a,0x23,0x70, 0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x2c,0x6d,0x69,0x78,0x29,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,
0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x32,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x6f,0x6f, 0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x32,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x6f,0x6f,0x70,0x3d,0x30,0x3b,
0x70,0x3d,0x30,0x3b,0x20,0x6c,0x6f,0x6f,0x70,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x4e,0x54,0x5f,0x44,0x41,0x47,0x3b,0x20,0x2b,0x2b,0x6c,0x6f,0x6f, 0x20,0x6c,0x6f,0x6f,0x70,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x4e,0x54,0x5f,0x44,0x41,0x47,0x3b,0x20,0x2b,0x2b,0x6c,0x6f,0x6f,0x70,0x29,0x0a,0x7b,
0x70,0x29,0x0a,0x7b,0x0a,0x69,0x66,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x3d,0x28,0x6c,0x6f,0x6f,0x70,0x20,0x25,0x20,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57, 0x0a,0x69,0x66,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x3d,0x28,0x6c,0x6f,0x6f,0x70,0x20,0x25,0x20,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,
0x5f,0x4c,0x41,0x4e,0x45,0x53,0x29,0x29,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x30,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f, 0x45,0x53,0x29,0x29,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x30,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x3d,
0x69,0x64,0x5d,0x3d,0x6d,0x69,0x78,0x5b,0x30,0x5d,0x3b,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45, 0x6d,0x69,0x78,0x5b,0x30,0x5d,0x3b,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,
0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x73,0x68,0x61,0x72,0x65,0x5b, 0x4e,0x43,0x45,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x73,0x68,0x61,0x72,0x65,0x5b,0x30,0x5d,0x2e,0x75,
0x30,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x3b,0x0a,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x25,0x3d,0x20, 0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x3b,0x0a,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x25,0x3d,0x20,0x50,0x52,0x4f,0x47,
0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x45,0x4c,0x45,0x4d,0x45,0x4e,0x54,0x53,0x3b,0x0a,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x6f,0x66,0x66, 0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x45,0x4c,0x45,0x4d,0x45,0x4e,0x54,0x53,0x3b,0x0a,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x6f,0x66,0x66,0x73,0x65,0x74,0x2a,
0x73,0x65,0x74,0x2a,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x2b,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x5e,0x6c,0x6f,0x6f,0x70,0x29, 0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x2b,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x5e,0x6c,0x6f,0x6f,0x70,0x29,0x20,0x25,0x20,0x50,
0x20,0x25,0x20,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x0a,0x64,0x61,0x67,0x5f,0x74,0x20,0x64,0x61,0x74,0x61,0x5f,0x64,0x61,0x67, 0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x0a,0x64,0x61,0x67,0x5f,0x74,0x20,0x64,0x61,0x74,0x61,0x5f,0x64,0x61,0x67,0x3d,0x67,0x5f,0x64,
0x3d,0x67,0x5f,0x64,0x61,0x67,0x5b,0x6f,0x66,0x66,0x73,0x65,0x74,0x5d,0x3b,0x0a,0x69,0x66,0x28,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x29,0x20,0x62, 0x61,0x67,0x5b,0x6f,0x66,0x66,0x73,0x65,0x74,0x5d,0x3b,0x0a,0x69,0x66,0x28,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x29,0x20,0x62,0x61,0x72,0x72,0x69,
0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x75,0x69,0x6e, 0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x33,0x32,0x5f,0x74,0x20,0x64,0x61,0x74,0x61,0x3b,0x0a,0x58,0x4d,0x52,0x49,0x47,0x5f,0x49,0x4e,0x43,0x4c,0x55,0x44,0x45,0x5f,0x50,0x52,0x4f,0x47,0x50,0x4f, 0x74,0x20,0x64,0x61,0x74,0x61,0x3b,0x0a,0x58,0x4d,0x52,0x49,0x47,0x5f,0x49,0x4e,0x43,0x4c,0x55,0x44,0x45,0x5f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x41,
0x57,0x5f,0x52,0x41,0x4e,0x44,0x4f,0x4d,0x5f,0x4d,0x41,0x54,0x48,0x0a,0x69,0x66,0x28,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x29,0x20,0x62,0x61,0x72, 0x4e,0x44,0x4f,0x4d,0x5f,0x4d,0x41,0x54,0x48,0x0a,0x69,0x66,0x28,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x29,0x20,0x62,0x61,0x72,0x72,0x69,0x65,0x72,
0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x58,0x4d,0x52,0x49,0x47, 0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x58,0x4d,0x52,0x49,0x47,0x5f,0x49,0x4e,0x43,
0x5f,0x49,0x4e,0x43,0x4c,0x55,0x44,0x45,0x5f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x54,0x41,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x0a,0x7d,0x0a,0x75,0x69, 0x4c,0x55,0x44,0x45,0x5f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x54,0x41,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x0a,0x7d,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,
0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,0x68,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53, 0x5f,0x74,0x20,0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,0x68,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53,0x3b,0x0a,0x23,0x70,
0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69, 0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,0x4f,
0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x66,0x6e,0x76,0x31,0x61,0x28,0x6d,0x69,0x78,0x5f,0x68,0x61, 0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x66,0x6e,0x76,0x31,0x61,0x28,0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,0x68,0x2c,0x6d,
0x73,0x68,0x2c,0x6d,0x69,0x78,0x5b,0x69,0x5d,0x29,0x3b,0x0a,0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x20,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70, 0x69,0x78,0x5b,0x69,0x5d,0x29,0x3b,0x0a,0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x20,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x3b,0x0a,0x66,0x6f,
0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x64,0x69,0x67,0x65,0x73,0x74, 0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,
0x5f,0x74,0x65,0x6d,0x70,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x5d,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49, 0x70,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x5d,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53,0x3b,0x0a,0x73,
0x53,0x3b,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x6c,0x61,0x6e,0x65,0x5f, 0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x5d,0x3d,
0x69,0x64,0x5d,0x3d,0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,0x68,0x3b,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f, 0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,0x68,0x3b,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,
0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28, 0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,
0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x66, 0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x66,0x6e,0x76,0x31,0x61,
0x6e,0x76,0x31,0x61,0x28,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x20,0x25,0x20,0x38,0x5d,0x2c, 0x28,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x20,0x25,0x20,0x38,0x5d,0x2c,0x73,0x68,0x61,0x72,
0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x5d,0x29,0x3b,0x0a,0x69,0x66,0x28, 0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x5d,0x29,0x3b,0x0a,0x69,0x66,0x28,0x68,0x3d,0x3d,0x6c,
0x68,0x3d,0x3d,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,0x0a,0x64,0x69,0x67,0x65,0x73,0x74,0x3d,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x3b,0x0a, 0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,0x0a,0x64,0x69,0x67,0x65,0x73,0x74,0x3d,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x3b,0x0a,0x7d,0x0a,0x75,0x69,
0x7d,0x0a,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x3b,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74, 0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x3b,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,0x74,0x65,0x5b,
0x61,0x74,0x65,0x5b,0x32,0x35,0x5d,0x3d,0x7b,0x30,0x78,0x30,0x7d,0x3b,0x20,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c, 0x32,0x35,0x5d,0x3d,0x7b,0x30,0x78,0x30,0x7d,0x3b,0x20,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x69,
0x38,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x69,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20, 0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x69,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,
0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x38,0x3b,0x20,0x69,0x3c,0x31,0x36,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x64,0x69, 0x20,0x69,0x3d,0x38,0x3b,0x20,0x69,0x3c,0x31,0x36,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x64,0x69,0x67,0x65,0x73,0x74,
0x67,0x65,0x73,0x74,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x2d,0x38,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x31,0x36, 0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x2d,0x38,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x31,0x36,0x3b,0x20,0x69,0x3c,
0x3b,0x20,0x69,0x3c,0x32,0x35,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x72,0x61,0x76,0x65,0x6e,0x63,0x6f,0x69,0x6e,0x5f, 0x32,0x35,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x72,0x61,0x76,0x65,0x6e,0x63,0x6f,0x69,0x6e,0x5f,0x72,0x6e,0x64,0x63,
0x72,0x6e,0x64,0x63,0x5b,0x69,0x2d,0x31,0x36,0x5d,0x3b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x28,0x73,0x74,0x61,0x74,0x65,0x29,0x3b,0x0a, 0x5b,0x69,0x2d,0x31,0x36,0x5d,0x3b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x28,0x73,0x74,0x61,0x74,0x65,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,
0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x72,0x65,0x73,0x3d,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x73,0x74,0x61,0x74,0x65,0x5b,0x31,0x5d,0x3c, 0x36,0x34,0x5f,0x74,0x20,0x72,0x65,0x73,0x3d,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x73,0x74,0x61,0x74,0x65,0x5b,0x31,0x5d,0x3c,0x3c,0x33,0x32,0x7c,
0x3c,0x33,0x32,0x7c,0x73,0x74,0x61,0x74,0x65,0x5b,0x30,0x5d,0x3b,0x0a,0x72,0x65,0x73,0x75,0x6c,0x74,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x28,0x61,0x73, 0x73,0x74,0x61,0x74,0x65,0x5b,0x30,0x5d,0x3b,0x0a,0x72,0x65,0x73,0x75,0x6c,0x74,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x28,0x61,0x73,0x5f,0x75,0x63,0x68,
0x5f,0x75,0x63,0x68,0x61,0x72,0x38,0x28,0x72,0x65,0x73,0x29,0x2e,0x73,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x69,0x66,0x28,0x72,0x65, 0x61,0x72,0x38,0x28,0x72,0x65,0x73,0x29,0x2e,0x73,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x69,0x66,0x28,0x72,0x65,0x73,0x75,0x6c,0x74,
0x73,0x75,0x6c,0x74,0x3c,0x3d,0x74,0x61,0x72,0x67,0x65,0x74,0x29,0x0a,0x7b,0x0a,0x2a,0x73,0x74,0x6f,0x70,0x3d,0x31,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75, 0x3c,0x3d,0x74,0x61,0x72,0x67,0x65,0x74,0x29,0x0a,0x7b,0x0a,0x2a,0x73,0x74,0x6f,0x70,0x3d,0x31,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,
0x69,0x6e,0x74,0x20,0x6b,0x3d,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,0x28,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x29,0x2b,0x31,0x3b,0x0a,0x69,0x66,0x28, 0x6b,0x3d,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,0x28,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x29,0x2b,0x31,0x3b,0x0a,0x69,0x66,0x28,0x6b,0x3c,0x3d,0x31,
0x6b,0x3c,0x3d,0x31,0x35,0x29,0x0a,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x5b,0x6b,0x5d,0x3d,0x67,0x69,0x64,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x00 0x35,0x29,0x0a,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x5b,0x6b,0x5d,0x3d,0x67,0x69,0x64,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x00
}; };
} // namespace xmrig } // namespace xmrig

View File

@@ -5,13 +5,7 @@ if (BUILD_STATIC AND XMRIG_OS_UNIX AND WITH_OPENCL)
endif() endif()
if (WITH_OPENCL) if (WITH_OPENCL)
add_definitions(/DXMRIG_FEATURE_OPENCL) add_definitions(/DXMRIG_FEATURE_OPENCL /DCL_USE_DEPRECATED_OPENCL_1_2_APIS)
add_definitions(/DCL_USE_DEPRECATED_OPENCL_1_2_APIS)
if (XMRIG_OS_APPLE)
add_definitions(/DCL_TARGET_OPENCL_VERSION=120)
elseif (WITH_OPENCL_VERSION)
add_definitions(/DCL_TARGET_OPENCL_VERSION=${WITH_OPENCL_VERSION})
endif()
set(HEADERS_BACKEND_OPENCL set(HEADERS_BACKEND_OPENCL
src/backend/opencl/cl/OclSource.h src/backend/opencl/cl/OclSource.h
@@ -71,6 +65,13 @@ if (WITH_OPENCL)
src/backend/opencl/wrappers/OclPlatform.cpp src/backend/opencl/wrappers/OclPlatform.cpp
) )
if (XMRIG_OS_APPLE)
add_definitions(/DCL_TARGET_OPENCL_VERSION=120)
list(APPEND SOURCES_BACKEND_OPENCL src/backend/opencl/wrappers/OclDevice_mac.cpp)
elseif (WITH_OPENCL_VERSION)
add_definitions(/DCL_TARGET_OPENCL_VERSION=${WITH_OPENCL_VERSION})
endif()
if (WIN32) if (WIN32)
list(APPEND SOURCES_BACKEND_OPENCL src/backend/opencl/OclCache_win.cpp) list(APPEND SOURCES_BACKEND_OPENCL src/backend/opencl/OclCache_win.cpp)
else() else()

View File

@@ -1,6 +1,7 @@
/* XMRig /* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh> * Copyright (c) 2021 Spudz76 <https://github.com/Spudz76>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright (c) 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -17,6 +18,7 @@
*/ */
#include "backend/opencl/wrappers/OclDevice.h" #include "backend/opencl/wrappers/OclDevice.h"
#include "3rdparty/fmt/core.h"
#include "3rdparty/rapidjson/document.h" #include "3rdparty/rapidjson/document.h"
#include "backend/opencl/OclGenerator.h" #include "backend/opencl/OclGenerator.h"
#include "backend/opencl/OclThreads.h" #include "backend/opencl/OclThreads.h"
@@ -30,19 +32,21 @@
#include <algorithm> #include <algorithm>
#include <map>
// NOLINTNEXTLINE(modernize-use-using)
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;
} topology_amd;
namespace xmrig { namespace xmrig {
struct topology_amd {
cl_uint type;
cl_char unused[17];
cl_char bus;
cl_char device;
cl_char function;
};
#ifdef XMRIG_ALGO_RANDOMX #ifdef XMRIG_ALGO_RANDOMX
extern bool ocl_generic_rx_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads); extern bool ocl_generic_rx_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads);
#endif #endif
@@ -81,9 +85,11 @@ static OclVendor getPlatformVendorId(const String &vendor, const String &extensi
return OCL_VENDOR_INTEL; return OCL_VENDOR_INTEL;
} }
# ifdef XMRIG_OS_APPLE
if (extensions.contains("cl_APPLE_") || vendor.contains("Apple")) { if (extensions.contains("cl_APPLE_") || vendor.contains("Apple")) {
return OCL_VENDOR_APPLE; return OCL_VENDOR_APPLE;
} }
# endif
return OCL_VENDOR_UNKNOWN; return OCL_VENDOR_UNKNOWN;
} }
@@ -103,117 +109,16 @@ static OclVendor getVendorId(const String &vendor)
return OCL_VENDOR_INTEL; return OCL_VENDOR_INTEL;
} }
# ifdef XMRIG_OS_APPLE
if (vendor.contains("Apple")) { if (vendor.contains("Apple")) {
return OCL_VENDOR_APPLE; return OCL_VENDOR_APPLE;
} }
# endif
return OCL_VENDOR_UNKNOWN; return OCL_VENDOR_UNKNOWN;
} }
static OclDevice::Type getType(const String &name, const OclVendor platformVendorId)
{
if (platformVendorId == OCL_VENDOR_APPLE) {
// Apple Platform: uses product names, not gfx# or codenames
if (name.contains("AMD Radeon")) {
if (name.contains(" 450 ") ||
name.contains(" 455 ") ||
name.contains(" 460 ")) {
return OclDevice::Baffin;
}
if (name.contains(" 555 ") || name.contains(" 555X ") ||
name.contains(" 560 ") || name.contains(" 560X ") ||
name.contains(" 570 ") || name.contains(" 570X ") ||
name.contains(" 575 ") || name.contains(" 575X ")) {
return OclDevice::Polaris;
}
if (name.contains(" 580 ") || name.contains(" 580X ")) {
return OclDevice::Ellesmere;
}
if (name.contains(" Vega ")) {
if (name.contains(" 48 ") ||
name.contains(" 56 ") ||
name.contains(" 64 ") ||
name.contains(" 64X ")) {
return OclDevice::Vega_10;
}
if (name.contains(" 16 ") ||
name.contains(" 20 ") ||
name.contains(" II ")) {
return OclDevice::Vega_20;
}
}
if (name.contains(" 5700 ") || name.contains(" W5700X ")) {
return OclDevice::Navi_10;
}
if (name.contains(" 5600 ") || name.contains(" 5600M ")) {
return OclDevice::Navi_12;
}
if (name.contains(" 5300 ") || name.contains(" 5300M ") ||
name.contains(" 5500 ") || name.contains(" 5500M ")) {
return OclDevice::Navi_14;
}
if (name.contains(" W6800 ") || name.contains(" W6900X ")) {
return OclDevice::Navi_21;
}
}
}
if (name == "gfx900" || name == "gfx901") {
return OclDevice::Vega_10;
}
if (name == "gfx902" || name == "gfx903") {
return OclDevice::Raven;
}
if (name == "gfx906" || name == "gfx907") {
return OclDevice::Vega_20;
}
if (name == "gfx1010") {
return OclDevice::Navi_10;
}
if (name == "gfx1011") {
return OclDevice::Navi_12;
}
if (name == "gfx1012") {
return OclDevice::Navi_14;
}
if (name == "gfx1030") {
return OclDevice::Navi_21;
}
if (name == "gfx804") {
return OclDevice::Lexa;
}
if (name == "Baffin") {
return OclDevice::Baffin;
}
if (name.contains("Ellesmere")) {
return OclDevice::Ellesmere;
}
if (name == "gfx803" || name.contains("polaris")) {
return OclDevice::Polaris;
}
return OclDevice::Unknown;
}
} // namespace xmrig } // namespace xmrig
@@ -231,21 +136,21 @@ xmrig::OclDevice::OclDevice(uint32_t index, cl_device_id id, cl_platform_id plat
{ {
m_vendorId = getVendorId(m_vendor); m_vendorId = getVendorId(m_vendor);
m_platformVendorId = getPlatformVendorId(m_platformVendor, m_extensions); m_platformVendorId = getPlatformVendorId(m_platformVendor, m_extensions);
m_type = getType(m_name, m_platformVendorId); m_type = getType(m_name);
if (m_extensions.contains("cl_amd_device_attribute_query")) { if (m_extensions.contains("cl_amd_device_attribute_query")) {
topology_amd topology; topology_amd topology{};
if (OclLib::getDeviceInfo(id, CL_DEVICE_TOPOLOGY_AMD, sizeof(topology), &topology) == CL_SUCCESS && topology.type == CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD) {
if (OclLib::getDeviceInfo(id, CL_DEVICE_TOPOLOGY_AMD, sizeof(topology), &topology, nullptr) == CL_SUCCESS && topology.raw.type == CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD) { m_topology = { topology.bus, topology.device, topology.function };
m_topology = PciTopology(static_cast<uint32_t>(topology.pcie.bus), static_cast<uint32_t>(topology.pcie.device), static_cast<uint32_t>(topology.pcie.function));
} }
m_board = OclLib::getString(id, CL_DEVICE_BOARD_NAME_AMD); m_board = OclLib::getString(id, CL_DEVICE_BOARD_NAME_AMD);
} }
else if (m_extensions.contains("cl_nv_device_attribute_query")) { else if (m_extensions.contains("cl_nv_device_attribute_query")) {
cl_uint bus = 0; cl_uint bus = 0;
if (OclLib::getDeviceInfo(id, CL_DEVICE_PCI_BUS_ID_NV, sizeof (bus), &bus, nullptr) == CL_SUCCESS) { if (OclLib::getDeviceInfo(id, CL_DEVICE_PCI_BUS_ID_NV, sizeof(bus), &bus) == CL_SUCCESS) {
cl_uint slot = OclLib::getUint(id, CL_DEVICE_PCI_SLOT_ID_NV); cl_uint slot = OclLib::getUint(id, CL_DEVICE_PCI_SLOT_ID_NV);
m_topology = PciTopology(bus, (slot >> 3) & 0xff, slot & 7); m_topology = { bus, (slot >> 3) & 0xff, slot & 7 };
} }
} }
} }
@@ -253,17 +158,11 @@ xmrig::OclDevice::OclDevice(uint32_t index, cl_device_id id, cl_platform_id plat
xmrig::String xmrig::OclDevice::printableName() const xmrig::String xmrig::OclDevice::printableName() const
{ {
const size_t size = m_board.size() + m_name.size() + 64;
char *buf = new char[size]();
if (m_board.isNull()) { if (m_board.isNull()) {
snprintf(buf, size, GREEN_BOLD("%s"), m_name.data()); return fmt::format(GREEN_BOLD("{}"), m_name).c_str();
}
else {
snprintf(buf, size, GREEN_BOLD("%s") " (" CYAN_BOLD("%s") ")", m_board.data(), m_name.data());
} }
return buf; return fmt::format(GREEN_BOLD("{}") " (" CYAN_BOLD("{}") ")", m_board, m_name).c_str();
} }
@@ -311,3 +210,35 @@ void xmrig::OclDevice::toJSON(rapidjson::Value &out, rapidjson::Document &doc) c
# endif # endif
} }
#endif #endif
#ifndef XMRIG_OS_APPLE
xmrig::OclDevice::Type xmrig::OclDevice::getType(const String &name)
{
static std::map<const char *, OclDevice::Type> types = {
{ "gfx900", Vega_10 },
{ "gfx901", Vega_10 },
{ "gfx902", Raven },
{ "gfx903", Raven },
{ "gfx906", Vega_20 },
{ "gfx907", Vega_20 },
{ "gfx1010", Navi_10 },
{ "gfx1011", Navi_12 },
{ "gfx1012", Navi_14 },
{ "gfx1030", Navi_21 },
{ "gfx804", Lexa },
{ "Baffin", Baffin },
{ "Ellesmere", Ellesmere },
{ "gfx803", Polaris },
{ "polaris", Polaris },
};
for (auto &kv : types) {
if (name.contains(kv.first)) {
return kv.second;
}
}
return OclDevice::Unknown;
}
#endif

View File

@@ -1,6 +1,6 @@
/* XMRig /* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright (c) 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -86,6 +86,8 @@ public:
# endif # endif
private: private:
static OclDevice::Type getType(const String &name);
cl_device_id m_id = nullptr; cl_device_id m_id = nullptr;
cl_platform_id m_platform = nullptr; cl_platform_id m_platform = nullptr;
const String m_platformVendor; const String m_platformVendor;

View File

@@ -0,0 +1,77 @@
/* XMRig
* Copyright (c) 2021 Spudz76 <https://github.com/Spudz76>
* Copyright (c) 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/opencl/wrappers/OclDevice.h"
xmrig::OclDevice::Type xmrig::OclDevice::getType(const String &name)
{
// Apple Platform: uses product names, not gfx# or codenames
if (name.contains("AMD Radeon")) {
if (name.contains(" 450 ") ||
name.contains(" 455 ") ||
name.contains(" 460 ")) {
return Baffin;
}
if (name.contains(" 555 ") || name.contains(" 555X ") ||
name.contains(" 560 ") || name.contains(" 560X ") ||
name.contains(" 570 ") || name.contains(" 570X ") ||
name.contains(" 575 ") || name.contains(" 575X ")) {
return Polaris;
}
if (name.contains(" 580 ") || name.contains(" 580X ")) {
return Ellesmere;
}
if (name.contains(" Vega ")) {
if (name.contains(" 48 ") ||
name.contains(" 56 ") ||
name.contains(" 64 ") ||
name.contains(" 64X ")) {
return Vega_10;
}
if (name.contains(" 16 ") ||
name.contains(" 20 ") ||
name.contains(" II ")) {
return Vega_20;
}
}
if (name.contains(" 5700 ") || name.contains(" W5700X ")) {
return Navi_10;
}
if (name.contains(" 5600 ") || name.contains(" 5600M ")) {
return Navi_12;
}
if (name.contains(" 5300 ") || name.contains(" 5300M ") ||
name.contains(" 5500 ") || name.contains(" 5500M ")) {
return Navi_14;
}
if (name.contains(" W6800 ") || name.contains(" W6900X ")) {
return Navi_21;
}
}
return OclDevice::Unknown;
}

View File

@@ -1,6 +1,6 @@
/* XMRig /* XMRig
* Copyright (c) 2018-2024 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright (c) 2016-2025 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@
#include "base/api/Api.h" #include "base/api/Api.h"
#include "3rdparty/rapidjson/writer.h"
#include "base/api/interfaces/IApiListener.h" #include "base/api/interfaces/IApiListener.h"
#include "base/api/requests/HttpApiRequest.h" #include "base/api/requests/HttpApiRequest.h"
#include "base/crypto/keccak.h" #include "base/crypto/keccak.h"
@@ -31,7 +32,6 @@
#include "base/tools/Chrono.h" #include "base/tools/Chrono.h"
#include "base/tools/Cvt.h" #include "base/tools/Cvt.h"
#include "core/config/Config.h" #include "core/config/Config.h"
#include "core/Controller.h"
#include "version.h" #include "version.h"
@@ -46,6 +46,12 @@
namespace xmrig { namespace xmrig {
static_assert(
RAPIDJSON_WRITE_DEFAULT_FLAGS == (rapidjson::kWriteNanAndInfFlag | rapidjson::kWriteNanAndInfNullFlag),
"(rapidjson::kWriteNanAndInfFlag | rapidjson::kWriteNanAndInfNullFlag) required"
);
static rapidjson::Value getResources(rapidjson::Document &doc) static rapidjson::Value getResources(rapidjson::Document &doc)
{ {
using namespace rapidjson; using namespace rapidjson;

View File

@@ -1,6 +1,6 @@
/* XMRig /* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright (c) 2016-2025 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
#include <windows.h> #include <windows.h>
#ifdef __GNUC__ #if defined(__GNUC__) && !defined(__clang__)
# include <fcntl.h> # include <fcntl.h>
# include <sys/stat.h> # include <sys/stat.h>
# include <ext/stdio_filebuf.h> # include <ext/stdio_filebuf.h>
@@ -39,7 +39,7 @@
namespace xmrig { namespace xmrig {
#if defined(_MSC_VER) || defined (__GNUC__) #if defined(_MSC_VER) || (defined(__GNUC__) && !defined(__clang__))
static std::wstring toUtf16(const char *str) static std::wstring toUtf16(const char *str)
{ {
const int size = static_cast<int>(strlen(str)); const int size = static_cast<int>(strlen(str));
@@ -62,7 +62,7 @@ static std::wstring toUtf16(const char *str)
if (!ifs.is_open()) { \ if (!ifs.is_open()) { \
return false; \ return false; \
} }
#elif defined(__GNUC__) #elif defined(__GNUC__) && !defined(__clang__)
# define OPEN_IFS(name) \ # define OPEN_IFS(name) \
const int fd = _wopen(toUtf16(name).c_str(), _O_RDONLY | _O_BINARY); \ const int fd = _wopen(toUtf16(name).c_str(), _O_RDONLY | _O_BINARY); \
if (fd == -1) { \ if (fd == -1) { \
@@ -103,7 +103,7 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc)
if (!ofs.is_open()) { if (!ofs.is_open()) {
return false; return false;
} }
# elif defined(__GNUC__) # elif defined(__GNUC__) && !defined(__clang__)
const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_CREAT | _O_TRUNC, _S_IWRITE); const int fd = _wopen(toUtf16(fileName).c_str(), _O_WRONLY | _O_BINARY | _O_CREAT | _O_TRUNC, _S_IWRITE);
if (fd == -1) { if (fd == -1) {
return false; return false;

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet> * Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh> * Copyright 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -22,11 +22,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <cstdio> #include <cstdio>
#include <uv.h> #include <uv.h>
#ifdef XMRIG_FEATURE_TLS #ifdef XMRIG_FEATURE_TLS
# include <openssl/opensslv.h> # include <openssl/opensslv.h>
#endif #endif
@@ -66,13 +64,13 @@ static int showVersion()
# endif # endif
printf("\n features:" printf("\n features:"
# if defined(__i386__) || defined(_M_IX86) # if defined(__x86_64__) || defined(_M_AMD64) || defined (__arm64__) || defined (__aarch64__)
" 32-bit"
# elif defined(__x86_64__) || defined(_M_AMD64)
" 64-bit" " 64-bit"
# else
" 32-bit"
# endif # endif
# if defined(__AES__) || defined(_MSC_VER) # if defined(__AES__) || defined(_MSC_VER) || defined(__ARM_FEATURE_CRYPTO)
" AES" " AES"
# endif # endif
"\n"); "\n");

View File

@@ -1,7 +1,7 @@
/* XMRig /* XMRig
* Copyright (c) 2014-2019 heapwolf <https://github.com/heapwolf> * Copyright (c) 2014-2019 heapwolf <https://github.com/heapwolf>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright (c) 2016-2025 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -17,7 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "base/net/http/HttpData.h" #include "base/net/http/HttpData.h"
#include "3rdparty/llhttp/llhttp.h" #include "3rdparty/llhttp/llhttp.h"
#include "3rdparty/rapidjson/document.h" #include "3rdparty/rapidjson/document.h"
@@ -29,76 +28,6 @@
#include <stdexcept> #include <stdexcept>
/* Status Codes */
#define HTTP_STATUS_MAP(XX) \
XX(100, CONTINUE, Continue) \
XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
XX(102, PROCESSING, Processing) \
XX(200, OK, OK) \
XX(201, CREATED, Created) \
XX(202, ACCEPTED, Accepted) \
XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \
XX(204, NO_CONTENT, No Content) \
XX(205, RESET_CONTENT, Reset Content) \
XX(206, PARTIAL_CONTENT, Partial Content) \
XX(207, MULTI_STATUS, Multi-Status) \
XX(208, ALREADY_REPORTED, Already Reported) \
XX(226, IM_USED, IM Used) \
XX(300, MULTIPLE_CHOICES, Multiple Choices) \
XX(301, MOVED_PERMANENTLY, Moved Permanently) \
XX(302, FOUND, Found) \
XX(303, SEE_OTHER, See Other) \
XX(304, NOT_MODIFIED, Not Modified) \
XX(305, USE_PROXY, Use Proxy) \
XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
XX(400, BAD_REQUEST, Bad Request) \
XX(401, UNAUTHORIZED, Unauthorized) \
XX(402, PAYMENT_REQUIRED, Payment Required) \
XX(403, FORBIDDEN, Forbidden) \
XX(404, NOT_FOUND, Not Found) \
XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
XX(406, NOT_ACCEPTABLE, Not Acceptable) \
XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
XX(408, REQUEST_TIMEOUT, Request Timeout) \
XX(409, CONFLICT, Conflict) \
XX(410, GONE, Gone) \
XX(411, LENGTH_REQUIRED, Length Required) \
XX(412, PRECONDITION_FAILED, Precondition Failed) \
XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
XX(414, URI_TOO_LONG, URI Too Long) \
XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
XX(417, EXPECTATION_FAILED, Expectation Failed) \
XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
XX(423, LOCKED, Locked) \
XX(424, FAILED_DEPENDENCY, Failed Dependency) \
XX(426, UPGRADE_REQUIRED, Upgrade Required) \
XX(428, PRECONDITION_REQUIRED, Precondition Required) \
XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
XX(501, NOT_IMPLEMENTED, Not Implemented) \
XX(502, BAD_GATEWAY, Bad Gateway) \
XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
XX(508, LOOP_DETECTED, Loop Detected) \
XX(510, NOT_EXTENDED, Not Extended) \
XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
enum http_status
{
# define XX(num, name, string) HTTP_STATUS_##name = num,
HTTP_STATUS_MAP(XX)
# undef XX
};
namespace xmrig { namespace xmrig {
@@ -108,17 +37,6 @@ const std::string HttpData::kContentTypeL = "content-type";
const std::string HttpData::kTextPlain = "text/plain"; const std::string HttpData::kTextPlain = "text/plain";
static const char *http_status_str(enum http_status s)
{
switch (s) {
# define XX(num, name, string) case HTTP_STATUS_##name: return #string;
HTTP_STATUS_MAP(XX)
# undef XX
default: return "<unknown>";
}
}
} // namespace xmrig } // namespace xmrig
@@ -173,5 +91,5 @@ const char *xmrig::HttpData::statusName(int status)
return uv_strerror(status); return uv_strerror(status);
} }
return http_status_str(static_cast<http_status>(status)); return llhttp_status_name(static_cast<llhttp_status>(status));
} }

View File

@@ -189,10 +189,12 @@ void xmrig::HttpsClient::flush(bool close)
} }
char *data = nullptr; char *data = nullptr;
const size_t size = BIO_get_mem_data(m_write, &data); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) const long size = BIO_get_mem_data(m_write, &data); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast)
std::string body(data, size); std::string body(data, (size > 0) ? size : 0);
(void) BIO_reset(m_write); (void) BIO_reset(m_write);
HttpContext::write(std::move(body), close); if (!body.empty()) {
HttpContext::write(std::move(body), close);
}
} }

View File

@@ -7,8 +7,8 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd> * Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2019 Howard Chu <https://github.com/hyc> * Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2018-2024 SChernykh <https://github.com/SChernykh> * Copyright 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2025 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -67,7 +67,7 @@ public:
inline bool isNicehash() const { return m_nicehash; } inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return (m_size > 0 && m_diff > 0) || !m_poolWallet.isEmpty(); } inline bool isValid() const { return (m_size > 0 && m_diff > 0) || !m_poolWallet.isEmpty(); }
inline bool setId(const char *id) { return m_id = id; } inline bool setId(const char *id) { return (m_id = id); }
inline const Algorithm &algorithm() const { return m_algorithm; } inline const Algorithm &algorithm() const { return m_algorithm; }
inline const Buffer &seed() const { return m_seed; } inline const Buffer &seed() const { return m_seed; }
inline const String &clientId() const { return m_clientId; } inline const String &clientId() const { return m_clientId; }

View File

@@ -173,7 +173,7 @@ public:
Value total(kArrayType); Value total(kArrayType);
Value threads(kArrayType); Value threads(kArrayType);
double t[3] = { 0.0 }; std::pair<bool, double> t[3] = { { true, 0.0 }, { true, 0.0 }, { true, 0.0 } };
for (IBackend *backend : backends) { for (IBackend *backend : backends) {
const Hashrate *hr = backend->hashrate(); const Hashrate *hr = backend->hashrate();
@@ -181,9 +181,13 @@ public:
continue; continue;
} }
t[0] += hr->calc(Hashrate::ShortInterval); const auto h0 = hr->calc(Hashrate::ShortInterval);
t[1] += hr->calc(Hashrate::MediumInterval); const auto h1 = hr->calc(Hashrate::MediumInterval);
t[2] += hr->calc(Hashrate::LargeInterval); const auto h2 = hr->calc(Hashrate::LargeInterval);
if (h0.first) { t[0].second += h0.second; } else { t[0].first = false; }
if (h1.first) { t[1].second += h1.second; } else { t[1].first = false; }
if (h2.first) { t[2].second += h2.second; } else { t[2].first = false; }
if (version > 1) { if (version > 1) {
continue; continue;
@@ -204,7 +208,7 @@ public:
total.PushBack(Hashrate::normalize(t[2]), allocator); total.PushBack(Hashrate::normalize(t[2]), allocator);
hashrate.AddMember("total", total, allocator); hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", Hashrate::normalize(maxHashrate[algorithm]), allocator); hashrate.AddMember("highest", Hashrate::normalize({ maxHashrate[algorithm] > 0.0, maxHashrate[algorithm] }), allocator);
if (version == 1) { if (version == 1) {
hashrate.AddMember("threads", threads, allocator); hashrate.AddMember("threads", threads, allocator);
@@ -283,7 +287,7 @@ public:
void printHashrate(bool details) void printHashrate(bool details)
{ {
char num[16 * 5] = { 0 }; char num[16 * 5] = { 0 };
double speed[3] = { 0.0 }; std::pair<bool, double> speed[3] = { { true, 0.0 }, { true, 0.0 }, { true, 0.0 } };
uint32_t count = 0; uint32_t count = 0;
double avg_hashrate = 0.0; double avg_hashrate = 0.0;
@@ -293,9 +297,13 @@ public:
if (hashrate) { if (hashrate) {
++count; ++count;
speed[0] += hashrate->calc(Hashrate::ShortInterval); const auto h0 = hashrate->calc(Hashrate::ShortInterval);
speed[1] += hashrate->calc(Hashrate::MediumInterval); const auto h1 = hashrate->calc(Hashrate::MediumInterval);
speed[2] += hashrate->calc(Hashrate::LargeInterval); const auto h2 = hashrate->calc(Hashrate::LargeInterval);
if (h0.first) { speed[0].second += h0.second; } else { speed[0].first = false; }
if (h1.first) { speed[1].second += h1.second; } else { speed[1].first = false; }
if (h2.first) { speed[2].second += h2.second; } else { speed[2].first = false; }
avg_hashrate += hashrate->average(); avg_hashrate += hashrate->average();
} }
@@ -312,8 +320,13 @@ public:
double scale = 1.0; double scale = 1.0;
const char* h = "H/s"; const char* h = "H/s";
if ((speed[0] >= 1e6) || (speed[1] >= 1e6) || (speed[2] >= 1e6) || (maxHashrate[algorithm] >= 1e6)) { if ((speed[0].second >= 1e6) || (speed[1].second >= 1e6) || (speed[2].second >= 1e6) || (maxHashrate[algorithm] >= 1e6)) {
scale = 1e-6; scale = 1e-6;
speed[0].second *= scale;
speed[1].second *= scale;
speed[2].second *= scale;
h = "MH/s"; h = "MH/s";
} }
@@ -322,16 +335,16 @@ public:
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (algorithm.family() == Algorithm::GHOSTRIDER) { if (algorithm.family() == Algorithm::GHOSTRIDER) {
snprintf(avg_hashrate_buf, sizeof(avg_hashrate_buf), " avg " CYAN_BOLD("%s %s"), Hashrate::format(avg_hashrate * scale, num + 16 * 4, 16), h); snprintf(avg_hashrate_buf, sizeof(avg_hashrate_buf), " avg " CYAN_BOLD("%s %s"), Hashrate::format({ true, avg_hashrate * scale }, num + 16 * 4, 16), h);
} }
# endif # endif
LOG_INFO("%s " WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("%s") " max " CYAN_BOLD("%s %s") "%s", LOG_INFO("%s " WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("%s") " max " CYAN_BOLD("%s %s") "%s",
Tags::miner(), Tags::miner(),
Hashrate::format(speed[0] * scale, num, 16), Hashrate::format(speed[0], num, 16),
Hashrate::format(speed[1] * scale, num + 16, 16), Hashrate::format(speed[1], num + 16, 16),
Hashrate::format(speed[2] * scale, num + 16 * 2, 16), h, Hashrate::format(speed[2], num + 16 * 2, 16), h,
Hashrate::format(maxHashrate[algorithm] * scale, num + 16 * 3, 16), h, Hashrate::format({ maxHashrate[algorithm] > 0.0, maxHashrate[algorithm] * scale }, num + 16 * 3, 16), h,
avg_hashrate_buf avg_hashrate_buf
); );
@@ -576,6 +589,11 @@ void xmrig::Miner::setJob(const Job &job, bool donate)
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
const bool ready = d_ptr->initRX(); const bool ready = d_ptr->initRX();
// Always reset nonce on RandomX dataset change
if (!ready) {
d_ptr->reset = true;
}
# else # else
constexpr const bool ready = true; constexpr const bool ready = true;
# endif # endif
@@ -641,7 +659,10 @@ void xmrig::Miner::onTimer(const Timer *)
} }
if (backend->hashrate()) { if (backend->hashrate()) {
maxHashrate += backend->hashrate()->calc(Hashrate::ShortInterval); const auto h = backend->hashrate()->calc(Hashrate::ShortInterval);
if (h.first) {
maxHashrate += h.second;
}
} }
} }

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.10)
project(GhostRider) project(GhostRider)
set(HEADERS set(HEADERS

View File

@@ -16,7 +16,7 @@ xmrig -a gr -o rtm.suprnova.cc:4273 --tls -u WALLET_ADDRESS -p x
You can use **rtm_ghostrider_example.cmd** as a template and put pool URL and your wallet address there. The general XMRig documentation is available [here](https://xmrig.com/docs/miner). You can use **rtm_ghostrider_example.cmd** as a template and put pool URL and your wallet address there. The general XMRig documentation is available [here](https://xmrig.com/docs/miner).
**Using `--threads` or `-t` option is NOT recommended because it turns off advanced built-in config.** If you want to tweak the nubmer of threads used for GhostRider, it's recommended to start using config.json instead of command line. The best suitable command line option for this is `--cpu-max-threads-hint=N` where N can be between 0 and 100. **Using `--threads` or `-t` option is NOT recommended because it turns off advanced built-in config.** If you want to tweak the number of threads used for GhostRider, it's recommended to start using config.json instead of command line. The best suitable command line option for this is `--cpu-max-threads-hint=N` where N can be between 0 and 100.
## Performance ## Performance

View File

@@ -392,13 +392,17 @@ FORCE_INLINE rx_vec_f128 rx_cvt_packed_int_vec_f128(const void* addr) {
typedef uint8x16_t rx_vec_i128; typedef uint8x16_t rx_vec_i128;
typedef float64x2_t rx_vec_f128; typedef float64x2_t rx_vec_f128;
#if !defined(XMRIG_OS_WIN) // FIXME
inline void* rx_aligned_alloc(size_t size, size_t align) { inline void* rx_aligned_alloc(size_t size, size_t align) {
void* p; void* p;
if (posix_memalign(&p, align, size) == 0) if (posix_memalign(&p, align, size) == 0)
return p; return p;
return 0; return 0;
}; };
#else
# define rx_aligned_alloc(a, b) malloc(a)
#endif
#define rx_aligned_free(a) free(a) #define rx_aligned_free(a) free(a)

View File

@@ -267,8 +267,8 @@ namespace randomx {
initDatasetAVX2 = false; initDatasetAVX2 = false;
break; break;
case xmrig::ICpuInfo::ARCH_ZEN5: case xmrig::ICpuInfo::ARCH_ZEN5:
// TODO: test it // AVX2 init is 49% faster on Zen5
initDatasetAVX2 = false; initDatasetAVX2 = true;
break; break;
} }
} }

View File

@@ -1,7 +1,7 @@
/* XMRig /* XMRig
* Copyright (c) 2018-2019 tevador <tevador@gmail.com> * Copyright (c) 2018-2019 tevador <tevador@gmail.com>
* Copyright (c) 2018-2020 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2024 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright (c) 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -17,9 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "crypto/rx/RxBasicStorage.h" #include "crypto/rx/RxBasicStorage.h"
#include "backend/common/Tags.h"
#include "base/io/log/Log.h" #include "base/io/log/Log.h"
#include "base/io/log/Tags.h" #include "base/io/log/Tags.h"
#include "base/tools/Chrono.h" #include "base/tools/Chrono.h"

View File

@@ -60,8 +60,6 @@ static const std::array<MsrItems, kMsrArraySize> msrPresets = {
MsrItems{{ 0xC0011020, 0ULL }, { 0xC0011021, 0x40ULL, ~0x20ULL }, { 0xC0011022, 0x1510000ULL }, { 0xC001102b, 0x2000cc16ULL }}, MsrItems{{ 0xC0011020, 0ULL }, { 0xC0011021, 0x40ULL, ~0x20ULL }, { 0xC0011022, 0x1510000ULL }, { 0xC001102b, 0x2000cc16ULL }},
MsrItems{{ 0xC0011020, 0x0004480000000000ULL }, { 0xC0011021, 0x001c000200000040ULL, ~0x20ULL }, { 0xC0011022, 0xc000000401570000ULL }, { 0xC001102b, 0x2000cc10ULL }}, MsrItems{{ 0xC0011020, 0x0004480000000000ULL }, { 0xC0011021, 0x001c000200000040ULL, ~0x20ULL }, { 0xC0011022, 0xc000000401570000ULL }, { 0xC001102b, 0x2000cc10ULL }},
MsrItems{{ 0xC0011020, 0x0004400000000000ULL }, { 0xC0011021, 0x0004000000000040ULL, ~0x20ULL }, { 0xC0011022, 0x8680000401570000ULL }, { 0xC001102b, 0x2040cc10ULL }}, MsrItems{{ 0xC0011020, 0x0004400000000000ULL }, { 0xC0011021, 0x0004000000000040ULL, ~0x20ULL }, { 0xC0011022, 0x8680000401570000ULL }, { 0xC001102b, 0x2040cc10ULL }},
// TODO: Tune it for Zen5 when it's available
MsrItems{{ 0xC0011020, 0x0004400000000000ULL }, { 0xC0011021, 0x0004000000000040ULL, ~0x20ULL }, { 0xC0011022, 0x8680000401570000ULL }, { 0xC001102b, 0x2040cc10ULL }}, MsrItems{{ 0xC0011020, 0x0004400000000000ULL }, { 0xC0011021, 0x0004000000000040ULL, ~0x20ULL }, { 0xC0011022, 0x8680000401570000ULL }, { 0xC001102b, 0x2040cc10ULL }},
MsrItems{{ 0x1a4, 0xf }}, MsrItems{{ 0x1a4, 0xf }},

View File

@@ -1,6 +1,6 @@
/* XMRig /* XMRig
* Copyright (c) 2018-2024 SChernykh <https://github.com/SChernykh> * Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2024 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright (c) 2016-2025 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -22,15 +22,15 @@
#define APP_ID "xmrig" #define APP_ID "xmrig"
#define APP_NAME "XMRig" #define APP_NAME "XMRig"
#define APP_DESC "XMRig miner" #define APP_DESC "XMRig miner"
#define APP_VERSION "6.22.0" #define APP_VERSION "6.22.4-dev"
#define APP_DOMAIN "xmrig.com" #define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com" #define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2024 xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2025 xmrig.com"
#define APP_KIND "miner" #define APP_KIND "miner"
#define APP_VER_MAJOR 6 #define APP_VER_MAJOR 6
#define APP_VER_MINOR 22 #define APP_VER_MINOR 22
#define APP_VER_PATCH 0 #define APP_VER_PATCH 4
#ifdef _MSC_VER #ifdef _MSC_VER
# if (_MSC_VER >= 1930) # if (_MSC_VER >= 1930)