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

Compare commits

...

404 Commits

Author SHA1 Message Date
XMRig
07d53fb77e Merge branch 'dev' into sync-base 2022-07-10 06:53:04 +07:00
xmrig
4c57b60e59 Merge pull request #3082 from SChernykh/dev
Fixed GCC 12 warnings
2022-07-03 16:59:26 +07:00
SChernykh
e6c81d7166 Fixed GCC 12 warnings 2022-07-03 11:51:46 +02:00
xmrig
94840c70d8 Update README.md 2022-07-02 22:27:51 +07:00
XMRig
e1478bfa94 v6.18.1-dev 2022-06-26 18:32:12 +07:00
XMRig
6df6e15267 Merge branch 'master' into dev 2022-06-26 18:31:40 +07:00
XMRig
834ea44507 v6.18.0 2022-06-23 20:04:00 +07:00
XMRig
73dc0ffb7e Merge branch 'dev' 2022-06-23 20:03:29 +07:00
XMRig
e57641d6b1 v6.18.0-dev 2022-06-23 17:36:31 +07:00
XMRig
b324e34444 Update hwloc for msvc. 2022-06-23 16:45:54 +07:00
XMRig
fdfbb60840 Update deps. 2022-06-19 13:39:32 +07:00
XMRig
3ded8e6734 Merge branch 'dev' into sync-base 2022-06-14 05:19:28 +07:00
xmrig
ee51dec499 Merge pull request #3068 from SChernykh/dev
Better fix for daemon solo mining with ZMQ
2022-06-13 03:37:56 +07:00
SChernykh
575742078c Better fix for daemon solo mining with ZMQ 2022-06-12 22:32:50 +02:00
xmrig
6bab67bced Merge pull request #3067 from SChernykh/dev
Monero v15 network upgrade support and more house keeping
2022-06-13 01:16:34 +07:00
SChernykh
db9069897d Improved daemon ZMQ mining stability 2022-06-12 14:41:47 +02:00
SChernykh
30641b1bdf Fixed ZMQ debug log 2022-06-12 12:33:09 +02:00
SChernykh
45061f40d8 Monero v15 network upgrade support 2022-06-12 11:49:54 +02:00
SChernykh
9f70752090 Fixed debug GhostRider build 2022-06-12 11:47:56 +02:00
SChernykh
22d6a7525e Removed deprecated AstroBWTv1 and v2 2022-06-12 11:47:36 +02:00
XMRig
774f630e14 Update Log class. 2022-06-10 02:15:10 +07:00
xmrig
09a7219651 Merge pull request #3055 from benthetechguy/patch-1
Add armv7 to README
2022-05-21 15:50:01 +07:00
benthetechguy
97869f3347 Add armv7 to supported architectures 2022-05-20 23:19:34 -04:00
xmrig
1bbbff7d17 Merge pull request #3054 from SChernykh/dev
Fixes for 32-bit ARM
2022-05-21 09:57:17 +07:00
SChernykh
97683e5719 Fixes for 32-bit ARM 2022-05-20 21:16:10 +02:00
xmrig
059d5d8421 Merge pull request #3051 from SChernykh/dev
Fixed unaligned memory read in DMI
2022-05-20 09:11:26 +07:00
SChernykh
285719cde4 Fixed unaligned memory read in DMI 2022-05-19 20:56:19 +02:00
XMRig
d6a1c98314 Update Signals class. 2022-05-17 18:05:53 +07:00
XMRig
75283445fd Update Console class. 2022-05-15 12:13:27 +07:00
XMRig
45084cb718 Update Watcher class. 2022-05-13 03:18:25 +07:00
XMRig
bc150fec04 Sync ConsoleLog class, base versions and TLS init. 2022-05-07 21:41:55 +07:00
xmrig
c877ba8145 Merge pull request #3042 from SChernykh/dev
Fixed being unable to resume from pause-on-battery
2022-05-06 02:14:52 +07:00
SChernykh
6793981066 Fixed being unable to resume from pause-on-battery
Fixes #3041
2022-05-05 21:13:02 +02:00
XMRig
9a0cd68ea5 Update and move Title class. 2022-04-27 12:14:20 +07:00
XMRig
603eb261c5 Update Entry class. 2022-04-23 23:08:27 +07:00
xmrig
1ae9a4e428 Merge pull request #3031 from SChernykh/dev
Fixed --cpu-priority not working sometimes
2022-04-20 07:44:33 +07:00
SChernykh
0e57053c5a Fixed --cpu-priority not working sometimes 2022-04-19 19:57:12 +02:00
XMRig
de97f3492e Sync TLS changes. 2022-04-19 16:34:18 +07:00
XMRig
8a167cb2a7 Sync with base. 2022-04-17 06:03:39 +07:00
XMRig
d0953a507c Merge branch 'dev' into sync-base 2022-04-16 02:57:59 +07:00
XMRig
fe8e198106 Update Arguments class. 2022-04-16 02:52:46 +07:00
xmrig
232d2d6dc5 Merge pull request #3020 from SChernykh/dev
Removed old AstroBWT algorithm
2022-04-15 16:03:26 +07:00
SChernykh
a3cb74f29b Removed old AstroBWT algorithm
It's not used anywhere now.
2022-04-15 10:59:31 +02:00
XMRig
dfc3b4632a Added backward compatibility support. 2022-04-15 14:13:45 +07:00
XMRig
6106bf30de Backport non breaking changes from the new base. 2022-04-08 14:33:16 +07:00
XMRig
56753d7c4a v6.17.1-dev 2022-04-06 01:58:24 +07:00
XMRig
f7b9e3ca67 Merge branch 'master' into dev 2022-04-06 01:58:03 +07:00
XMRig
56c95703a5 v6.17.0 2022-04-05 21:46:01 +07:00
XMRig
eadf272425 Merge branch 'dev' 2022-04-05 21:45:26 +07:00
XMRig
cb227a0a79 Merge branch 'dev' of github.com:xmrig/xmrig into dev 2022-04-05 15:15:47 +07:00
XMRig
4c171bea1e Disable donate for astrobwt/v2. 2022-04-05 15:15:03 +07:00
xmrig
e55a854314 Update CHANGELOG.md 2022-04-04 20:33:39 +07:00
XMRig
5bdfafd719 v6.17.0-dev 2022-04-04 20:17:40 +07:00
xmrig
15a2091837 Merge pull request #2991 from SChernykh/dev
Fixed compilation error
2022-03-24 22:46:33 +07:00
SChernykh
48bd09f730 Fixed compilation error 2022-03-24 16:38:47 +01:00
xmrig
21fb970949 Merge pull request #2990 from SChernykh/dev
Optimized keccak
2022-03-24 22:22:21 +07:00
SChernykh
23c12fc351 Optimized keccak
Big astrobwt/v2 speedup on non-AVX2 CPUs: **Core i7-2600 +64% (17 -> 28 kh/s)**
2022-03-24 13:10:03 +01:00
xmrig
71d193676a Merge pull request #2974 from SChernykh/dev
Fixed AstroBWT OpenCL config generation
2022-03-16 16:19:08 +07:00
SChernykh
baef34ba8c Fixed AstroBWT OpenCL config generation 2022-03-16 10:15:38 +01:00
xmrig
95a739d821 Merge pull request #2969 from SChernykh/dev
Dero HE (astrobwt/v2) OpenCL support
2022-03-15 08:51:46 +07:00
SChernykh
7b9135aadc Dero HE (astrobwt/v2) OpenCL support 2022-03-14 20:13:31 +01:00
xmrig
e6f694ca9e Merge pull request #2958 from SChernykh/dev
Fixed out of bounds access in astrobwt/v2
2022-03-10 06:40:34 +07:00
xmrig
afd79e7537 Merge pull request #2961 from SChernykh/derohe_cuda
Dero HE (astrobwt/v2) CUDA config generator
2022-03-10 06:37:30 +07:00
SChernykh
a2728af4f7 Dero HE (astrobwt/v2) CUDA config generator 2022-03-10 00:24:49 +01:00
SChernykh
65dbded9c4 Fixed out of bounds access in astrobwt/v2 2022-03-08 22:31:34 +01:00
XMRig
f25e65b5ac Update hwloc for MSVC builds. 2022-03-07 04:29:13 +07:00
XMRig
bbb19ea2f9 #2941 Update deps scripts. 2022-03-07 00:27:49 +07:00
xmrig
1c5b332add Merge pull request #2954 from SChernykh/dev
Dero HE fork support (astrobwt/v2 algorithm)
2022-03-06 04:18:43 +07:00
SChernykh
87fd0ea94a Added alternative algo names for Dero HE 2022-03-05 13:32:16 +01:00
SChernykh
4a42dca2cb Show block/miniblock counters more often 2022-03-05 10:00:39 +01:00
SChernykh
b674fafa0f DaemonClient: fixed broken coin setting 2022-03-05 09:56:30 +01:00
SChernykh
b5da73389f Dero HE fork support (astrobwt/v2 algorithm) 2022-03-05 00:31:18 +01:00
XMRig
bf5e38545c Fixed displayed DMI memory information for empty slots. 2022-03-01 02:50:30 +07:00
xmrig
f7543ada60 Merge pull request #2932 from SChernykh/dev
Fixed GhostRider with hwloc disabled
2022-02-16 19:23:26 +07:00
SChernykh
95e1705fc8 Fixed GhostRider with hwloc disabled 2022-02-16 08:13:48 +01:00
XMRig
2d0b07afbc v6.16.5-dev 2022-02-05 16:22:55 +07:00
XMRig
b33ccf0e0b Merge branch 'master' into dev 2022-02-05 16:21:19 +07:00
XMRig
4f5f9bdffb v6.16.4 2022-02-04 16:11:37 +07:00
XMRig
4d3e3daa6a Merge branch 'dev' 2022-02-04 16:10:58 +07:00
xmrig
802029e5f5 Update CHANGELOG.md 2022-02-04 15:14:46 +07:00
XMRig
14117e9658 #2910 Fixed donation for GhostRider/RTM. 2022-01-31 14:29:41 +07:00
xmrig
7ccb1d65f0 Merge pull request #2908 from Spudz76/dev-addMSVC2022
Add MSVC/2022 to version.h
2022-01-31 10:14:47 +07:00
Tony Butler
15de3cc16c Add MSVC/2022 to version.h 2022-01-28 21:09:24 -07:00
xmrig
124daa4afd Merge pull request #2898 from SChernykh/armv7
Fixed armv7 compilation
2022-01-26 23:38:45 +07:00
xmrig
5de1609b7d Merge pull request #2904 from SChernykh/dev
Fixed unaligned memory accesses
2022-01-26 23:26:03 +07:00
SChernykh
644f4cc017 Fixed unaligned memory accesses 2022-01-26 17:18:18 +01:00
XMRig
41a3f97060 v6.16.4-dev 2022-01-25 23:21:54 +07:00
XMRig
452080cfbd Merge branch 'master' into dev 2022-01-25 23:21:21 +07:00
XMRig
4f103b6b45 v6.16.3 2022-01-25 21:53:47 +07:00
XMRig
39609c9183 Merge branch 'dev' 2022-01-25 21:53:19 +07:00
xmrig
2adb7b2b74 Update CHANGELOG.md 2022-01-25 20:57:06 +07:00
SChernykh
3673137df6 Fixed armv7 compilation
Fix for error `Unsupported target. Must be either ARMv7-A+NEON or ARMv8-A.`
2022-01-25 12:37:41 +01:00
xmrig
faa7095865 Merge pull request #2893 from SChernykh/dev
KawPow OpenCL: use separate UV loop for building programs
2022-01-24 19:30:24 +07:00
SChernykh
e0701f9dad KawPow OpenCL: build next period only when it's not in cache 2022-01-24 13:28:58 +01:00
SChernykh
14aacf8636 KawPow OpenCL: use separate UV loop for building programs
Fixes #2890: uv_default_loop() can't be used there because UV loops are not thread safe.
2022-01-24 13:20:04 +01:00
xmrig
c764441337 Update CHANGELOG.md 2022-01-22 00:05:54 +07:00
xmrig
05fae12a63 Merge pull request #2882 from benthetechguy/armv7-gcc
armv7 compilation fix
2022-01-21 23:52:59 +07:00
XMRig
8059ce67f9 Add missing DNS options to config example. 2022-01-21 20:17:00 +07:00
benthetechguy
10111fd7f9 armv7 compilation fix
Compilation fails for armv7 on gcc 11, and updating the version in that line fixes it.
2022-01-20 20:47:26 -05:00
xmrig
2d25bec2df Merge pull request #2873 from SChernykh/dev
Fixed GhostRider benchmark on single-core systems
2022-01-18 10:13:16 +07:00
SChernykh
cab244d468 Fixed GhostRider benchmark on single-core systems
Fixes #2871
2022-01-17 19:59:21 +01:00
xmrig
4001488888 Merge pull request #2856 from SChernykh/dev
Fix for short responses from some Raptoreum pools
2022-01-05 10:22:39 +07:00
SChernykh
9bec1521b8 Fix for short responses from some Raptoreum pools 2022-01-04 23:54:59 +01:00
xmrig
7bde3ed5f7 Merge pull request #2848 from Spudz76/dev-addClientReconnect
Add support for client.reconnect method
2021-12-30 20:44:22 +07:00
Tony Butler
2e738509bb Add support for client.reconnect method 2021-12-30 06:26:52 -07:00
xmrig
f5447088cb Merge pull request #2837 from SChernykh/dev
RandomX: don't restart mining threads when the seed changes
2021-12-26 18:03:48 +07:00
SChernykh
7f2f50a8d9 RandomX: don't restart mining threads when the seed changes
It helps to not loose huge pages when the seed changes (every 2048 blocks, ~2.8 days).
2021-12-25 13:39:15 +01:00
xmrig
5747ccfafc Merge pull request #2827 from SChernykh/dev
GhostRider: set correct priority for helper threads
2021-12-20 18:07:23 +07:00
SChernykh
93081eb1f6 GhostRidere: set correct priority for helper threads
Fixes #2825
2021-12-20 12:05:17 +01:00
xmrig
4bf65c8669 Update README.md 2021-12-19 22:26:50 +07:00
xmrig
1a6fc3a665 Merge pull request #2815 from SChernykh/dev
Fixed cn-heavy in 32-bit builds
2021-12-16 10:44:16 +07:00
SChernykh
8dede14ac8 Fixed cn-heavy in 32-bit builds 2021-12-15 21:17:25 +00:00
xmrig
20687a397e Merge pull request #2782 from SChernykh/dev
Updated GhostRider documentation
2021-12-03 22:16:33 +07:00
SChernykh
454f97fa0f Updated GhostRider documentation
Added examples for SSL port command line that don't use #1 pool.
2021-12-03 12:30:09 +01:00
xmrig
8149fc7dcb Merge pull request #2778 from SChernykh/dev
Fixed "READY threads X/X" display after algo switching
2021-12-03 15:02:58 +07:00
SChernykh
a39ab89236 Fixed "READY threads X/X" display after algo switching 2021-12-03 07:44:23 +01:00
XMRig
5b8501fb57 v6.16.3-dev 2021-12-02 22:10:57 +07:00
XMRig
039be2ab75 Merge branch 'master' into dev 2021-12-02 22:10:23 +07:00
XMRig
718c7e0fc1 v6.16.2 2021-12-02 20:55:27 +07:00
XMRig
ef7951b91d Merge branch 'dev' 2021-12-02 20:54:50 +07:00
xmrig
214b1f021b Update CHANGELOG.md 2021-12-02 20:52:53 +07:00
XMRig
81b18c0741 #2771 Fixed environment variables support in EthStratumClient. 2021-12-02 19:36:51 +07:00
xmrig
8e83f72456 Merge pull request #2772 from SChernykh/dev
Compilation fixes
2021-12-02 19:36:09 +07:00
SChernykh
c2ae625032 Compilationn fixes 2021-12-02 13:34:24 +01:00
xmrig
60566dc84c Merge pull request #2769 from SChernykh/compiler_fix
Performance fixes
2021-12-02 10:00:29 +07:00
SChernykh
4ea8fe694d GhostRider benchmark: added 20 more possible rounds 2021-12-01 20:26:41 +01:00
SChernykh
669d1ab008 Updated changelog and GhostRider readme 2021-12-01 18:14:01 +01:00
SChernykh
e87d5111a2 Compiler fix 2021-12-01 17:08:40 +01:00
xmrig
56158779de Merge pull request #2761 from SChernykh/dev
Refactored Chrono::highResolutionMSecs()
2021-11-30 19:13:24 +07:00
SChernykh
efb322df66 Refactored Chrono::highResolutionMSecs()
Improved precision
2021-11-30 08:11:09 +01:00
xmrig
e673d541c1 Merge pull request #2751 from SChernykh/dev
VAES crash fixes
2021-11-30 09:49:37 +07:00
SChernykh
a98db529fb Explicitly use QueryPerformanceCounter() on Windows 2021-11-29 21:58:24 +01:00
SChernykh
1a9eaaad8f VAES crash fixes 2021-11-29 21:05:51 +01:00
XMRig
be5fbca9b6 v6.16.2-dev 2021-11-29 21:35:42 +07:00
XMRig
2feb264375 Merge branch 'master' into dev 2021-11-29 21:35:02 +07:00
XMRig
00990f2649 v6.16.1 2021-11-29 20:43:17 +07:00
XMRig
d78713be48 Merge branch 'dev' 2021-11-29 20:42:32 +07:00
XMRig
77367abe13 Fixed Clang build. 2021-11-29 16:01:16 +07:00
xmrig
cd046f6fd0 Merge pull request #2747 from SChernykh/dev
Disable VAES in 32-bit builds
2021-11-29 15:50:17 +07:00
SChernykh
63b7ec2887 Check compiler support for VAES 2021-11-29 09:48:15 +01:00
xmrig
a1e8f1c3e5 Merge pull request #2746 from Spudz76/dev-fixVAESCompile
Fix compile for VAES support with GCC<10
2021-11-29 15:38:35 +07:00
SChernykh
6db480a1ab Disable VAES in 32-bit builds 2021-11-29 09:32:00 +01:00
Tony Butler
a7acd9de6d Fix compile for VAES support with GCC<10 2021-11-28 22:11:42 -07:00
XMRig
a64f4d1870 v6.16.1-dev 2021-11-29 09:29:24 +07:00
XMRig
9bfe59b630 Merge branch 'master' into dev 2021-11-29 09:28:43 +07:00
xmrig
1a4bf16521 Merge pull request #2740 from SChernykh/dev
Added VAES support for Cryptonight variants
2021-11-29 09:26:45 +07:00
SChernykh
a4d5d0a75a Added VAES support for Cryptonight variants 2021-11-28 20:49:54 +01:00
xmrig
c40f1f9f66 Merge pull request #2738 from SChernykh/dev
More GhostRider fixes
2021-11-28 18:19:08 +07:00
SChernykh
15e5052dd0 More GhostRider fixes
- Fixed "difficulty is not a number" when diff is high on some pools
- Fixed GhostRider compilation when WITH_KAWPOW=OFF
2021-11-28 12:11:08 +01:00
xmrig
f9f7963453 Merge pull request #2734 from Spudz76/dev-nitpickWhitespace
Slash and burn EOL whitespace everywhere
2021-11-28 10:51:45 +07:00
Tony Butler
02240eff8c Slash and burn EOL whitespace everywhere 2021-11-27 17:59:40 -07:00
xmrig
d64c963e5e Merge pull request #2729 from SChernykh/dev
GhostRider hotfixes
2021-11-27 18:31:19 +07:00
SChernykh
c6292ce9ee GhostRider hotfixes
- Added average hashrate display
- Fixed the number of threads shown at startup
- Fixed `--threads` or `-t` command line option (but `--cpu-max-threads-hint` is recommended to use)
2021-11-27 12:27:26 +01:00
XMRig
cd652e2644 v6.16.0 2021-11-26 18:57:07 +07:00
XMRig
6f5ef0fe0f Merge branch 'dev' 2021-11-26 18:51:53 +07:00
xmrig
01fa968763 Update CHANGELOG.md 2021-11-26 18:50:34 +07:00
xmrig
8e6f3ad99e Merge pull request #2719 from SChernykh/dev
Added GhostRider release notes
2021-11-25 19:21:50 +07:00
SChernykh
b1f2479ec1 Added GhostRider release notes 2021-11-25 13:19:01 +01:00
XMRig
ecceba8ecd Add GhostRider support for AutoClient. 2021-11-25 17:44:36 +07:00
xmrig
cb5f4a9c17 Merge pull request #2716 from Spudz76/dev-initGR
Only initGhostRider() when job is in the family
2021-11-25 09:09:16 +07:00
Tony Butler
3a8ebfdcb6 Only initGhostRider() when job is in the family 2021-11-24 13:04:03 -07:00
xmrig
0dcafeb571 Merge pull request #2715 from SChernykh/dev
Benchmark support for GhostRider (offline only)
2021-11-24 22:05:44 +07:00
SChernykh
a1d7ee4c6b Benchmark support for GhostRider (offline only)
Command line:
```
./xmrig --bench=250K -a gr --rotation 15
```
Where `rotation` is an integer between 0 and 19 (inclusive).
2021-11-24 15:54:09 +01:00
XMRig
03e70ba2ed v6.16.0-dev 2021-11-24 19:49:21 +07:00
xmrig
19ef8c5d65 Merge pull request #2714 from SChernykh/gh3
GhostRider: fixed invalid hashes on ARMv8
2021-11-24 19:40:48 +07:00
SChernykh
63baa9e263 GhostRider: fixed invalid hashes on ARMv8 2021-11-24 13:39:55 +01:00
xmrig
1248bd5859 Merge pull request #2713 from SChernykh/gh3
Optimized quad hash for Ryzens
2021-11-24 18:21:01 +07:00
SChernykh
5c951ddb8a Optimized quad hash for Ryzens 2021-11-24 08:16:41 +01:00
xmrig
4ab0ad928d Merge pull request #2712 from SChernykh/gh3
GhostRider algorithm (Raptoreum) support
2021-11-24 09:49:34 +07:00
SChernykh
e67eb47796 Faster quad hash for GhostRider algos (Ryzen CPUs) 2021-11-23 22:14:46 +01:00
SChernykh
a6656a8c49 Fixed broken difficulty adjustment on some Raptoreum pools 2021-11-23 18:02:58 +01:00
SChernykh
a903d0a5bd Fixed compilation error 2021-11-23 08:52:30 +01:00
SChernykh
ceaebfd877 GhostRider algorithm (Raptoreum) support 2021-11-23 08:14:01 +01:00
xmrig
5156ff11a8 Merge pull request #2684 from SChernykh/fix-183
MSR mod: fix for error 183
2021-11-11 17:50:08 +07:00
xmrig
e0143a92a8 Merge pull request #2682 from SChernykh/dev
Fix: use cn-heavy optimization only for Vermeer CPUs
2021-11-11 17:49:51 +07:00
SChernykh
f682d9a2e9 MSR mod: fix for error 183
When WinRing0 driver starts, but some other version already created "\\.\WinRing0_1_2_0", it returns error 183 ERROR_ALREADY_EXISTS - "Cannot create a file when that file already exists."
2021-11-11 10:26:38 +01:00
SChernykh
3bece0ff40 Fix: use cn-heavy optimization only for Vermeer CPUs
Fixes #2680
2021-11-11 07:57:05 +01:00
XMRig
e6c456a970 v6.15.4-dev 2021-11-02 18:26:44 +07:00
XMRig
923d1d712f Merge branch 'master' into dev 2021-11-02 18:26:12 +07:00
XMRig
ae8459bd35 v6.15.3 2021-11-01 19:59:05 +07:00
XMRig
3a7be07c62 Merge branch 'dev' 2021-11-01 19:58:30 +07:00
xmrig
e1cc0000c6 Update CHANGELOG.md 2021-11-01 12:27:10 +07:00
xmrig
1210e8e95c Merge pull request #2644 from Spudz76/dev-fixMemleaks
Patch a couple minor leaks
2021-10-25 20:33:10 +07:00
xmrig
a45fbd9cae Merge pull request #2646 from SChernykh/dev
Fix MSVC compilation error
2021-10-25 20:31:12 +07:00
Tony Butler
f6d45f7990 Fix various memory leaks 2021-10-25 04:06:49 -06:00
SChernykh
b9464f993b Fix MSVC compilation error 2021-10-25 10:26:44 +02:00
xmrig
f8f73b0cd7 Merge pull request #2641 from SChernykh/dev
AstroBWT: fixed rare incorrect hashes
2021-10-20 07:24:15 +07:00
SChernykh
df6ab2edd8 AstroBWT: fixed rare incorrect hashes 2021-10-19 19:08:56 +02:00
xmrig
8bf7600154 Merge pull request #2639 from SChernykh/dev
AstroBWT even bigger speedup (up to +35%)
2021-10-19 22:50:07 +07:00
SChernykh
a30501956f AstroBWT even bigger speedup 2021-10-19 17:37:45 +02:00
xmrig
c287a40a20 Merge pull request #2636 from SChernykh/dev
AstroBWT speedup (up to +7%)
2021-10-19 07:58:24 +07:00
SChernykh
04f50c24e2 AstroBWT speedup 2021-10-18 18:05:51 +02:00
xmrig
7627b23212 Merge pull request #2614 from Spudz76/dev-fixAppleOpenCL
OpenCL fixes for non-AMD platforms
2021-10-13 06:20:53 +07:00
XMRig
e90e7febfb Merge branch 'StriderDM-merge_mining_tag_fix' into dev 2021-10-13 05:43:27 +07:00
XMRig
733b85a132 Code cleanup. 2021-10-13 05:43:05 +07:00
XMRig
35ba786e63 Merge branch 'merge_mining_tag_fix' of https://github.com/StriderDM/xmrig into StriderDM-merge_mining_tag_fix 2021-10-13 05:33:34 +07:00
David Main
446810a837 fix: expand validation of tx_extra for merge mining tag 2021-10-12 11:17:37 +02:00
Tony Butler
c6a68c3e51 Cap max threads to 4096 with nVidia OpenCL 2021-10-11 04:17:01 -06:00
Tony Butler
ca8bef3ade Adjust API version logic 2021-10-11 04:17:01 -06:00
Tony Butler
d735caa334 Adjust definitions and replace literal 0x4038 2021-10-11 04:17:01 -06:00
Tony Butler
eb54cc0e0f Revert amd_bitalign/amd_bfe polyfills 2021-10-11 04:17:01 -06:00
Tony Butler
84c67c37cd Apply "no-static-without-amd" fixes 2021-10-11 04:17:01 -06:00
Tony Butler
b44f38a362 Attempt repair of cn/r output-array access problem 2021-10-11 04:17:01 -06:00
Tony Butler
8ed4088d0a Second try at fixing cn/r atomic_inc() call 2021-10-11 04:17:01 -06:00
Tony Butler
cdcea2a4f9 Attempt fix for cn/r on Apple-AMD 2021-10-11 04:17:01 -06:00
Tony Butler
f0d80326ec Add Ellesmere correctly (still just a Polaris alias) 2021-10-11 04:17:01 -06:00
Tony Butler
cb8fc26cbe Add every Apple AMD GPU type 2021-10-11 04:17:01 -06:00
Tony Butler
5ec5b5ed00 Possibly fix problem with clGetProgramInfo crash 2021-10-11 04:17:01 -06:00
Tony Butler
67e29c1af1 Readjust OclDevice logic and add OCL_VENDOR_APPLE 2021-10-11 04:17:01 -06:00
xmrig
4bd94a79a4 Merge pull request #2623 from Spudz76/dev-fixWithoutKawpow
Fix #2583 compiling without kawpow (string ref is nonexistent then)
2021-10-11 16:41:44 +07:00
Tony Butler
80e597d951 Fix #2583 compiling without kawpow (string ref is nonexistent then) 2021-10-11 03:31:28 -06:00
XMRig
2e269f5b8c v6.15.3-dev 2021-10-06 02:01:29 +07:00
XMRig
57b8e35903 Merge branch 'master' into dev 2021-10-06 02:00:49 +07:00
XMRig
53be5765e6 v6.15.2 2021-10-05 23:28:29 +07:00
XMRig
68741c925b Merge branch 'dev' 2021-10-05 23:28:06 +07:00
xmrig
9ce207e667 Update CHANGELOG.md 2021-10-05 22:24:58 +07:00
XMRig
07e0966517 Added "--versions" alias. 2021-10-05 21:49:03 +07:00
XMRig
a9d4c2a923 Removed uv_os_gethostname call for all OS. 2021-09-28 23:56:33 +07:00
xmrig
dc02e1feaa Merge pull request #2606 from SChernykh/dev
Fix: AstroBWT auto-config ignored max-threads-hint
2021-09-26 18:51:47 +07:00
SChernykh
7daff331dc Fix: AstroBWT auto-config ignored max-threads-hint 2021-09-26 12:22:58 +02:00
XMRig
058a2fb0f4 v6.15.2-dev 2021-09-22 19:13:07 +07:00
XMRig
4fff3b946e Merge branch 'master' into dev 2021-09-22 19:12:38 +07:00
XMRig
f7aa5e781b v6.15.1 2021-09-22 13:08:00 +07:00
XMRig
298c5cccfa Merge branch 'dev' 2021-09-22 13:05:36 +07:00
xmrig
2985571620 Update CHANGELOG.md 2021-09-21 18:59:47 +07:00
xmrig
279d29cd7f Merge pull request #2594 from SChernykh/dev
Added Windows taskbar icon colors
2021-09-20 23:07:00 +07:00
SChernykh
387320ad6d Added Windows taskbar icon colors
- Red when there's no connection to any pool
- Yellow when mining is paused
- No color during normal mining
2021-09-20 18:03:22 +02:00
XMRig
76cd83edb2 Merge branch 'Spudz76-dev-fixAsteriskProfiling' into dev 2021-09-20 20:56:11 +07:00
XMRig
7f4d667351 Remove unnecessary string. 2021-09-20 20:53:36 +07:00
Tony Butler
8027716264 Fix --threads generates "*" profile without "kawpow":false to negate it. 2021-09-20 06:49:17 -06:00
xmrig
a459dd7741 Merge pull request #2591 from Spudz76/dev-fixCompileNoRX
Fix compile warning/crash when WITH_RANDOMX=OFF
2021-09-20 10:50:00 +07:00
Tony Butler
ef6011ac12 Fix compile warning when WITH_RANDOMX=OFF 2021-09-19 18:12:46 -06:00
xmrig
6d66051d92 Merge pull request #2586 from SChernykh/dev
Fixed Windows 7 compatibility
2021-09-17 17:11:09 +07:00
SChernykh
b2cc2ef0d7 Fixed Windows 7 compatibility
Fixes #2585
2021-09-17 12:05:37 +02:00
xmrig
9805320517 Merge pull request #2582 from Spudz76/dev-fixupRXnaming
Fixup RandomX naming consistency
2021-09-17 08:03:03 +07:00
Tony Butler
582d17bb84 Fixup RandomX naming consistency 2021-09-16 08:24:37 -06:00
XMRig
9e5f5b35a6 v6.15.1-dev 2021-08-31 18:57:08 +07:00
XMRig
9a9c69ff50 Merge branch 'master' into dev 2021-08-31 18:56:31 +07:00
XMRig
5c1f3f395c v6.15.0 2021-08-31 14:42:43 +07:00
XMRig
23cefffe43 Merge branch 'dev' 2021-08-31 14:41:47 +07:00
XMRig
d048d5a639 Fixed class/struct inconsistency. 2021-08-31 03:32:36 +07:00
xmrig
9a6f773dea Update CHANGELOG.md 2021-08-29 20:19:41 +07:00
XMRig
cd7c7902a9 Fixed clang build. 2021-08-29 18:52:11 +07:00
xmrig
fd3dad920d Merge pull request #2565 from SChernykh/dev
AstroBWT: add AVX2 Salsa20 implementation
2021-08-29 15:42:00 +07:00
SChernykh
3dc192f63e AstroBWT: add AVX2 Salsa20 implementation
+4.5% speedup on Ryzen 5 5600X
2021-08-29 10:35:43 +02:00
XMRig
123c7ab140 Added support for new CUDA plugin API. 2021-08-29 14:22:19 +07:00
XMRig
838996a0fc v6.15.0-dev 2021-08-28 19:53:28 +07:00
XMRig
6e4fea34a4 #2555 Update deps. 2021-08-28 13:10:48 +07:00
XMRig
b52c289931 Increase RANDOMX_PROGRAM_MAX_SIZE 2021-08-28 12:32:57 +07:00
XMRig
4dbb5b89da Update hwloc for MSVC. 2021-08-28 12:16:41 +07:00
XMRig
84d0212e79 Merge branch 'pr2563' into dev 2021-08-28 11:54:11 +07:00
XMRig
35acb3f00b Merge branch 'GraftRandomX' of https://github.com/Stardock2018/xmrig into pr2563 2021-08-28 11:50:17 +07:00
Chris
7f2771b466 Fixed Algorithm id
Algorithm id should be 0x72151267, second and third byte encode L3 and L2 size.
0x72 = 'r'
0x15 = 1 << 0x15 (L3 size)
0x12 = 1 << 0x12 (L2 size)
0x67 = 'g'
2021-08-27 10:31:36 -06:00
Chris
5fdf5516ff Added Graft RandonX 2021-08-27 08:19:54 -06:00
XMRig
234de96784 Update rapidjson. 2021-08-27 18:51:59 +07:00
XMRig
df4532d9a1 Cleanup ARM code. 2021-08-27 12:36:08 +07:00
XMRig
c27f535768 Fixed build on Linux. 2021-08-25 18:52:54 +07:00
XMRig
c7ac314110 Code cleanup based on Clang-Tidy. 2021-08-25 18:45:15 +07:00
XMRig
3215403815 Add missing files. 2021-08-23 18:43:14 +07:00
XMRig
bea2a6cf5b Update BlockTemplate class. 2021-08-23 18:32:58 +07:00
xmrig
a28f411339 Merge pull request #2548 from xmrig/feature-auto-coin
Added automatic coin detection for daemon mining
2021-08-19 15:35:37 +07:00
XMRig
460d9c75c5 Add global wallet address parser for DaemonClient. 2021-08-18 13:36:50 +07:00
XMRig
d1033abbe5 Update Coin, BlobReader and WalletAddress. 2021-08-17 08:17:21 +07:00
XMRig
9eac9dd30a v6.14.2-dev 2021-08-15 02:12:33 +07:00
XMRig
8d7b6adf98 Merge branch 'master' into dev 2021-08-15 02:11:29 +07:00
XMRig
230ff87634 v6.14.1 2021-08-15 00:42:47 +07:00
XMRig
19adf2630a Merge branch 'dev' 2021-08-15 00:42:12 +07:00
xmrig
3de4b16117 Update CHANGELOG.md 2021-08-15 00:37:23 +07:00
XMRig
602e3a7587 Fix algorithms order. 2021-08-14 05:48:37 +07:00
XMRig
4f6ffb67c1 Cleanup. 2021-08-14 04:58:01 +07:00
xmrig
a0194ddd18 Merge pull request #2537 from SChernykh/dev
Fixed Termux build
2021-08-13 21:14:35 +07:00
SChernykh
30f7e876a2 Update CnHash.cpp 2021-08-13 16:03:15 +02:00
SChernykh
5958490c23 Fixed Termux build 2021-08-13 12:02:03 +02:00
XMRig
f92ad4423d Fix Job::getNumTransactions. 2021-08-12 22:30:47 +07:00
XMRig
e0749a82c2 Fix cn-pico name. 2021-08-12 17:52:52 +07:00
xmrig
440aa003af Merge pull request #2532 from xmrig/feature-stable-algo-id
Refactoring: Stable (persistent) algorithms IDs.
2021-08-12 02:03:39 +07:00
XMRig
9580f5395f Removed shortName. 2021-08-11 22:26:34 +07:00
XMRig
e9ae4deb91 Removed duplicate strings. 2021-08-11 22:07:43 +07:00
XMRig
aee0762424 Fix typo. 2021-08-11 16:27:36 +07:00
XMRig
e6332eff2b Implemented stable algorithm ids. 2021-08-11 03:46:34 +07:00
XMRig
d0a632f557 Optimize CnHash storage. 2021-08-10 14:54:35 +07:00
XMRig
f4cdc527b0 #2527 Fix narrowing conversion. 2021-08-10 01:40:36 +07:00
XMRig
661dc515ab namespace cleanup. 2021-08-09 23:51:07 +07:00
XMRig
6d9bafe068 v6.14.1-dev 2021-08-09 17:20:15 +07:00
XMRig
202c8aaee8 Merge branch 'master' into dev 2021-08-09 17:19:48 +07:00
XMRig
410084384e v6.14.0 2021-08-09 16:09:15 +07:00
XMRig
43e98c509a Merge branch 'dev' 2021-08-09 16:08:20 +07:00
XMRig
08d79ddcdc v6.14.0-dev 2021-08-08 19:36:54 +07:00
xmrig
0fdf063760 Merge pull request #2512 from SChernykh/dev
Show the number of transactions in pool job
2021-08-08 00:52:06 +07:00
SChernykh
929205536c Show the number of transactions in pool job
Useful to check if pool/proxy is working properly and can also be used to compare different pools.
2021-08-07 19:38:31 +02:00
XMRig
d24581c963 #2492 Add missing --huge-pages-jit command line option. 2021-07-24 12:27:48 +07:00
xmrig
2eb2e90631 Merge pull request #2484 from SChernykh/zmq
ZeroMQ support for solo mining
2021-07-17 17:14:42 +07:00
SChernykh
0842e6b9d2 ZeroMQ support for solo mining
Gets new blocks from daemon immediately without polling, saving ~0.5 seconds on average when daemon gets new block from the network. Also saves some CPU cycles because it doesn't need to poll daemon every second.

Testing: add "daemon-zmq-port": 28083 to xmrig's pool config in config.json and run ./monerod --testnet --zmq-pub tcp://127.0.0.1:28083
2021-07-15 11:13:14 +02:00
XMRig
93805cd167 #2476 Fixed crash in DMI memory reader. 2021-07-06 23:07:31 +07:00
xmrig
755fe28bc3 Merge pull request #2472 from SChernykh/dev
Updates from xmrig-proxy
2021-07-05 19:13:14 +07:00
SChernykh
59d780169f Merge branch 'dev' of https://github.com/SChernykh/xmrig into dev 2021-07-05 13:57:16 +02:00
SChernykh
a30ede04f3 Updates from xmrig-proxy 2021-07-05 13:56:37 +02:00
XMRig
3f2dfa4279 Sync with proxy. 2021-07-05 02:31:29 +07:00
XMRig
7177b42903 v6.13.2-dev 2021-07-03 16:00:30 +07:00
XMRig
21638c2f58 Merge branch 'master' into dev 2021-07-03 16:00:05 +07:00
XMRig
02b2b87bb6 v6.13.1 2021-07-03 15:29:49 +07:00
XMRig
c8a9dba8fd Merge branch 'dev' 2021-07-03 15:29:14 +07:00
xmrig
9a77d39a3f Update CHANGELOG.md 2021-07-03 15:16:47 +07:00
xmrig
28a1d0fe1e Merge pull request #2468 from SChernykh/dev
Fix: don't send miner signature during regular mining
2021-07-02 00:37:04 +07:00
XMRig
0243789c04 v6.13.1-dev 2021-07-02 00:36:32 +07:00
XMRig
45dd58f808 Merge branch 'master' into dev 2021-07-02 00:35:52 +07:00
SChernykh
1b4abe1e98 Fix: don't send miner signature during regular mining 2021-07-01 19:31:55 +02:00
XMRig
9f778742a6 v6.13.0 2021-07-01 20:03:52 +07:00
XMRig
015f8aeed4 Merge branch 'dev' 2021-07-01 20:02:38 +07:00
xmrig
9e6311a7e0 Update CHANGELOG.md 2021-07-01 13:54:09 +07:00
XMRig
0af9d2e75b v6.13.0-dev 2021-06-28 19:02:48 +07:00
xmrig
6e2a84a46c Merge pull request #2445 from SChernykh/miner_signature
Support for solo mining with miner signatures (Wownero)
2021-06-28 18:11:13 +07:00
SChernykh
6bb8913066 Correct handling of block submit responses for Dero 2021-06-24 18:06:07 +02:00
SChernykh
cf104ebdc5 Update signing algorithm 2021-06-21 23:49:13 +02:00
XMRig
ecba750442 Add token support for online benchmark. 2021-06-20 09:28:39 +07:00
SChernykh
3967badc55 Added profiling 2021-06-19 16:19:16 +02:00
SChernykh
3f3f9b0661 Fixed GCC warnings 2021-06-19 14:54:03 +02:00
SChernykh
e3fc78a66c Fix Wownero hardfork version 2021-06-18 13:52:24 +02:00
SChernykh
e6d833c227 Proxy miner signature support 2021-06-17 22:48:08 +02:00
SChernykh
ebe299902c Proxy miner signature support (WIP) 2021-06-17 16:58:18 +02:00
SChernykh
bc63b63a2a More sanity checks 2021-06-17 13:18:34 +02:00
SChernykh
e739e7d704 More error handling in DaemonClient::parseJob 2021-06-17 10:39:22 +02:00
SChernykh
1bae083587 Fixed CalculateMerkleTreeHash 2021-06-17 10:26:17 +02:00
SChernykh
88959bd703 BlockTemplate: miner tx and root hash updating 2021-06-16 23:44:05 +02:00
SChernykh
93e689d601 Fix buffer size in generateMinerSignature 2021-06-16 18:20:11 +02:00
SChernykh
a136790bee Added support for solo mining with miner signatures (Wownero) 2021-06-16 18:07:36 +02:00
SChernykh
29f2dd4b9e Cleanup 2021-06-16 11:47:17 +02:00
SChernykh
3003c067d3 Fixed random32_unbiased 2021-06-16 00:19:49 +02:00
SChernykh
89bc6418b1 Secret key derivation 2021-06-16 00:10:34 +02:00
SChernykh
8458b4ee39 Added signature functions 2021-06-15 15:51:29 +02:00
SChernykh
7bfb801ce2 Cryptonote tools WIP 2021-06-15 00:28:32 +02:00
xmrig
4567499905 Merge pull request #2433 from candrews/patch-2
Fix shellcheck warnings in randomx_boost.sh
2021-06-09 23:41:58 +07:00
Craig Andrews
9b63955b09 Fix shellcheck warnings in randomx_boost.sh
Checked using www.shellcheck.net

Specific issues addessed:
* https://github.com/koalaman/shellcheck/wiki/SC2002
* Use POSIX instead of bash for wider compatibility
* Fail on error
2021-06-08 21:56:02 -04:00
XMRig
0414511de0 v6.12.3-dev 2021-05-31 13:51:41 +07:00
XMRig
b61dad128c Merge branch 'master' into dev 2021-05-31 13:49:35 +07:00
XMRig
80ae339343 v6.12.2 2021-05-31 12:58:30 +07:00
XMRig
4d87555398 Merge branch 'dev' 2021-05-31 12:57:55 +07:00
xmrig
bef82c5de6 Update CHANGELOG.md 2021-05-30 21:28:28 +07:00
xmrig
b069ad5dd1 Merge pull request #2358 from zzjzxq33/patch-1
Update openssl version to 1.1.1k
2021-05-30 17:53:53 +07:00
xmrig
f6a0646271 Merge pull request #2401 from SChernykh/dev
RandomX: fix broken light mode mining
2021-05-22 18:54:29 +07:00
SChernykh
b5f1a1feae RandomX: fix broken light mode mining
It broke after #2395
2021-05-22 13:49:22 +02:00
XMRig
1ce059da1c Add "argon2/ninja" algorithm alias. 2021-05-22 15:10:50 +07:00
xmrig
2929451ee1 Merge pull request #2398 from SChernykh/dev
RandomX ARMv8: optimized dataset read
2021-05-21 09:58:54 +07:00
SChernykh
94fecb5e92 RandomX ARMv8: optimized dataset read
Break dependency from readReg2 and readReg3. It should run faster on superscalar and out-of-order CPUs i.e. Apple M1.
2021-05-20 21:24:28 +02:00
xmrig
3bfa5ea038 Merge pull request #2395 from SChernykh/dev
RandomX: rewrote dataset read code
2021-05-20 18:58:48 +07:00
SChernykh
ff82ca57f2 RandomX: rewrote dataset read code
Unified code for AMD and Intel
1% faster on Intel
0.15% faster on AMD Ryzen
2021-05-20 12:45:42 +02:00
xmrig
7f7b1fb073 Merge pull request #2393 from SChernykh/dev
RandomX: added BMI2 version for scratchpad prefetch
2021-05-19 22:54:58 +07:00
SChernykh
d443dd86f1 RandomX: added BMI2 version for scratchpad prefetch
Saves 1 instruction and 1 byte in the main loop.
2021-05-19 17:52:16 +02:00
xmrig
3ac8f6b23a Merge pull request #2386 from SChernykh/dev
Enabled IMUL_RCP optimization for light mode mining
2021-05-17 16:36:23 +07:00
SChernykh
9b1f020a8b Enabled IMUL_RCP optimization for light mode mining
Better fix for #2377
2021-05-17 11:26:40 +02:00
XMRig
8bf88a4e74 Merge branch 'Spudz76-dev-fixCLKawPowPlatformHandling' into dev 2021-05-16 10:10:33 +07:00
XMRig
08a2c143f5 Regenerate OpenCL headers. 2021-05-16 10:09:29 +07:00
Tony Butler
4eb9a1aad5 Fix CL code for KawPow where it assumes everything is AMD 2021-05-15 20:34:57 -06:00
xmrig
c8c40586a1 Merge pull request #2378 from SChernykh/dev
Fixed broken light mode mining on x86
2021-05-16 07:03:57 +07:00
SChernykh
29cb416107 Fixed broken light mode mining on x86 2021-05-15 21:41:39 +02:00
xmrig
465169ff12 Merge pull request #2375 from Spudz76/dev-fixMacOSCudaLoader
Fixup MacOS CUDA backend default loader name
2021-05-14 18:48:09 +07:00
Tony Butler
df2bcd8192 Fixup MacOS CUDA backend default loader name 2021-05-14 05:28:31 -06:00
zzjzxq33
d89bb56964 Update openssl version to 1.1.1k 2021-05-09 11:11:46 +08:00
XMRig
87a0864e3b ...and --cpu-affinity. 2021-05-08 04:36:09 +07:00
XMRig
ecf5579f36 #2351 Fixed help output for --cpu-priority option. 2021-05-08 04:34:22 +07:00
xmrig
d5523d819f Merge pull request #2341 from SChernykh/dev
Update sse2neon.h
2021-05-03 23:17:12 +07:00
SChernykh
dbda2e9ccd Update sse2neon.h 2021-05-03 18:08:59 +02:00
xmrig
8babd7bc0a Merge pull request #2340 from SChernykh/dev
Fix AES detection on FreeBSD on ARM
2021-05-03 19:06:49 +07:00
SChernykh
27ced139a6 Fix AES detection on FreeBSD on ARM 2021-05-03 09:57:43 +02:00
xmrig
b46849e813 Merge pull request #2322 from SChernykh/dev
Update randomx_boost.sh
2021-04-28 19:12:37 +07:00
SChernykh
a96a6108ff Update randomx_boost.sh
- Support builtin MSR, see #2283
- Added detection of AMD EPYC CPUs
2021-04-28 14:10:30 +02:00
xmrig
c50c78b700 Merge pull request #2312 from SChernykh/dev
Add  missing allow_writes=on to randomx_boost.sh
2021-04-25 20:46:07 +07:00
SChernykh
cd7ab2c79f Add missing allow_writes=on to randomx_boost.sh 2021-04-25 15:31:30 +02:00
XMRig
695fbc013b #2280 Disable GPU backends in benchmark mode. 2021-04-25 15:28:45 +07:00
XMRig
a403c53543 Merge branch 'jsonboss-patch-1' into dev 2021-04-24 23:22:56 +07:00
XMRig
e26fbc96e9 Removed unnecessary system call. 2021-04-24 23:22:10 +07:00
XMRig
259c165e60 Merge branch 'patch-1' of https://github.com/jsonboss/xmrig into jsonboss-patch-1 2021-04-24 22:14:59 +07:00
XMRig
7897bf02dc v6.12.2-dev 2021-04-24 01:53:07 +07:00
XMRig
05f62c5ccc Merge branch 'master' into dev 2021-04-24 01:52:37 +07:00
XMRig
d82e100e30 v6.12.1 2021-04-23 19:43:12 +07:00
XMRig
5f869a414c Merge branch 'dev' 2021-04-23 19:42:29 +07:00
xmrig
7fd6be7d83 Update CHANGELOG.md 2021-04-23 18:54:42 +07:00
xmrig
ae6c536e98 Merge pull request #2296 from SChernykh/dev
Fixed Zen3 asm for cn/upx2
2021-04-21 19:52:52 +07:00
XMRig
c66c593123 v6.12.1-dev 2021-04-21 19:51:03 +07:00
XMRig
b3788b2ba3 Merge branch 'master' into dev 2021-04-21 19:49:54 +07:00
SChernykh
b7adb34c37 Fixed Zen3 asm for cn/upx2
- Invalid rounding mode was used which caused rejected shares sometimes
- Also optimized CN implode/explode functions a bit.
2021-04-21 13:22:25 +02:00
XMRig
ace8409a56 v6.12.0 2021-04-20 20:55:58 +07:00
XMRig
e2c757d9dd Merge branch 'dev' 2021-04-20 20:55:35 +07:00
xmrig
da35de993f Update CHANGELOG.md 2021-04-19 23:20:10 +07:00
xmrig
854b7618ef Merge pull request #2289 from SChernykh/dev
RandomX: optimized IMUL_RCP instruction
2021-04-19 22:54:02 +07:00
SChernykh
3477f9fbc1 RandomX: optimized IMUL_RCP instruction
+0.4% on AMD Zen2
+0.3% on AMD Zen3
+0.1% on Intel SandyBridge
+0.3% on rx/wow on Intel SandyBridge
2021-04-19 17:43:58 +02:00
xmrig
5799744f2f Update CHANGELOG.md 2021-04-19 20:56:45 +07:00
xmrig
61d165a314 Merge pull request #2287 from SChernykh/dev
Fixed rounding mode after running cn/upx
2021-04-19 18:06:16 +07:00
SChernykh
69186f2470 Optimized cn/upx for Zen3
0.9% faster
2021-04-19 12:29:44 +02:00
SChernykh
730d4a6cee Fix dvision by zero check in percent() 2021-04-19 12:05:07 +02:00
SChernykh
54bc91d5e3 Fixed rounding mode after running cn/upx 2021-04-19 12:02:57 +02:00
jsonboss
2012ffb231 support builtin msr 2021-04-19 10:38:27 +08:00
XMRig
5f9e0ebc6c v6.12.0-dev 2021-04-18 20:12:03 +07:00
xmrig
f314c69a70 Merge pull request #2278 from SChernykh/dev
Optimized cn/upx2
2021-04-17 23:41:26 +07:00
SChernykh
16fe462cad Optimized cn/upx2 for Ryzen CPUs 2021-04-17 18:18:26 +02:00
xmrig
e6e2987ddf Merge pull request #2276 from SChernykh/dev
Added support for Uplexa (cn/upx2 algorithm)
2021-04-17 20:10:54 +07:00
SChernykh
ed456b02cf Update CnHash.cpp 2021-04-17 15:06:31 +02:00
SChernykh
da7f5826cb Added support for Uplexa (cn/upx2 algorithm) 2021-04-17 14:53:42 +02:00
XMRig
6cb398bb42 Merge branch 'dev' of github.com:xmrig/xmrig into dev 2021-04-14 23:44:42 +07:00
XMRig
748be760e8 Added support for --user command line option for the benchmark. 2021-04-14 23:43:31 +07:00
xmrig
4a4118bb8e Merge pull request #2261 from SChernykh/dev
Show total hashrate if compiled without OpenCL
2021-04-13 19:06:42 +07:00
SChernykh
77f1bf0861 Show total hashrate if compiled without OpenCL 2021-04-13 14:02:29 +02:00
XMRig
6bb29b3e7b v6.11.3-dev 2021-04-11 21:13:39 +07:00
XMRig
f720772338 Merge branch 'master' into dev 2021-04-11 21:13:08 +07:00
582 changed files with 100526 additions and 17374 deletions

View File

@@ -1,3 +1,126 @@
# v6.18.0
- [#3067](https://github.com/xmrig/xmrig/pull/3067) Monero v15 network upgrade support and more house keeping.
- Removed deprecated AstroBWTv1 and v2.
- Fixed debug GhostRider build.
- Monero v15 network upgrade support.
- Fixed ZMQ debug log.
- Improved daemon ZMQ mining stability.
- [#3054](https://github.com/xmrig/xmrig/pull/3054) Fixes for 32-bit ARM.
- [#3042](https://github.com/xmrig/xmrig/pull/3042) Fixed being unable to resume from `pause-on-battery`.
- [#3031](https://github.com/xmrig/xmrig/pull/3031) Fixed `--cpu-priority` not working sometimes.
- [#3020](https://github.com/xmrig/xmrig/pull/3020) Removed old AstroBWT algorithm.
# v6.17.0
- [#2954](https://github.com/xmrig/xmrig/pull/2954) **Dero HE fork support (`astrobwt/v2` algorithm).**
- [#2961](https://github.com/xmrig/xmrig/pull/2961) Dero HE (`astrobwt/v2`) CUDA config generator.
- [#2969](https://github.com/xmrig/xmrig/pull/2969) Dero HE (`astrobwt/v2`) OpenCL support.
- Fixed displayed DMI memory information for empty slots.
- [#2932](https://github.com/xmrig/xmrig/pull/2932) Fixed GhostRider with hwloc disabled.
# v6.16.4
- [#2904](https://github.com/xmrig/xmrig/pull/2904) Fixed unaligned memory accesses.
- [#2908](https://github.com/xmrig/xmrig/pull/2908) Added MSVC/2022 to `version.h`.
- [#2910](https://github.com/xmrig/xmrig/issues/2910) Fixed donation for GhostRider/RTM.
# v6.16.3
- [#2778](https://github.com/xmrig/xmrig/pull/2778) Fixed `READY threads X/X` display after algorithm switching.
- [#2782](https://github.com/xmrig/xmrig/pull/2782) Updated GhostRider documentation.
- [#2815](https://github.com/xmrig/xmrig/pull/2815) Fixed `cn-heavy` in 32-bit builds.
- [#2827](https://github.com/xmrig/xmrig/pull/2827) GhostRider: set correct priority for helper threads.
- [#2837](https://github.com/xmrig/xmrig/pull/2837) RandomX: don't restart mining threads when the seed changes.
- [#2848](https://github.com/xmrig/xmrig/pull/2848) GhostRider: added support for `client.reconnect` method.
- [#2856](https://github.com/xmrig/xmrig/pull/2856) Fix for short responses from some Raptoreum pools.
- [#2873](https://github.com/xmrig/xmrig/pull/2873) Fixed GhostRider benchmark on single-core systems.
- [#2882](https://github.com/xmrig/xmrig/pull/2882) Fixed ARMv7 compilation.
- [#2893](https://github.com/xmrig/xmrig/pull/2893) KawPow OpenCL: use separate UV loop for building programs.
# v6.16.2
- [#2751](https://github.com/xmrig/xmrig/pull/2751) Fixed crash on CPUs supporting VAES and running GCC-compiled xmrig.
- [#2761](https://github.com/xmrig/xmrig/pull/2761) Fixed broken auto-tuning in GCC Windows build.
- [#2771](https://github.com/xmrig/xmrig/issues/2771) Fixed environment variables support for GhostRider and KawPow.
- [#2769](https://github.com/xmrig/xmrig/pull/2769) Performance fixes:
- Fixed several performance bottlenecks introduced in v6.16.1.
- Fixed overall GCC-compiled build performance, it's the same speed as MSVC build now.
- **Linux builds are up to 10% faster now compared to v6.16.0 GCC build.**
- **Windows builds are up to 5% faster now compared to v6.16.0 MSVC build.**
# v6.16.1
- [#2729](https://github.com/xmrig/xmrig/pull/2729) GhostRider fixes:
- Added average hashrate display.
- Fixed the number of threads shown at startup.
- Fixed `--threads` or `-t` command line option (but `--cpu-max-threads-hint` is recommended to use).
- [#2738](https://github.com/xmrig/xmrig/pull/2738) GhostRider fixes:
- Fixed "difficulty is not a number" error when diff is high on some pools.
- Fixed GhostRider compilation when `WITH_KAWPOW=OFF`.
- [#2740](https://github.com/xmrig/xmrig/pull/2740) Added VAES support for Cryptonight variants **+4% speedup on Zen3**.
- VAES instructions are available on Intel Ice Lake/AMD Zen3 and newer CPUs.
- +4% speedup on Ryzen 5 5600X.
# v6.16.0
- [#2712](https://github.com/xmrig/xmrig/pull/2712) **GhostRider algorithm (Raptoreum) support**: read the [RELEASE NOTES](src/crypto/ghostrider/README.md) for quick start guide and performance comparisons.
- [#2682](https://github.com/xmrig/xmrig/pull/2682) Fixed: use cn-heavy optimization only for Vermeer CPUs.
- [#2684](https://github.com/xmrig/xmrig/pull/2684) MSR mod: fix for error 183.
# v6.15.3
- [#2614](https://github.com/xmrig/xmrig/pull/2614) OpenCL fixes for non-AMD platforms.
- [#2623](https://github.com/xmrig/xmrig/pull/2623) Fixed compiling without kawpow.
- [#2636](https://github.com/xmrig/xmrig/pull/2636) [#2639](https://github.com/xmrig/xmrig/pull/2639) AstroBWT speedup (up to +35%).
- [#2646](https://github.com/xmrig/xmrig/pull/2646) Fixed MSVC compilation error.
# v6.15.2
- [#2606](https://github.com/xmrig/xmrig/pull/2606) Fixed: AstroBWT auto-config ignored `max-threads-hint`.
- Fixed possible crash on Windows (regression in v6.15.1).
# v6.15.1
- [#2586](https://github.com/xmrig/xmrig/pull/2586) Fixed Windows 7 compatibility.
- [#2594](https://github.com/xmrig/xmrig/pull/2594) Added Windows taskbar icon colors.
# v6.15.0
- [#2548](https://github.com/xmrig/xmrig/pull/2548) Added automatic coin detection for daemon mining.
- [#2563](https://github.com/xmrig/xmrig/pull/2563) Added new algorithm RandomX Graft (`rx/graft`).
- [#2565](https://github.com/xmrig/xmrig/pull/2565) AstroBWT: added AVX2 Salsa20 implementation.
- Added support for new CUDA plugin API (previous API still supported).
# v6.14.1
- [#2532](https://github.com/xmrig/xmrig/pull/2532) Refactoring: stable (persistent) algorithms IDs.
- [#2537](https://github.com/xmrig/xmrig/pull/2537) Fixed Termux build.
# v6.14.0
- [#2484](https://github.com/xmrig/xmrig/pull/2484) Added ZeroMQ support for solo mining.
- [#2476](https://github.com/xmrig/xmrig/issues/2476) Fixed crash in DMI memory reader.
- [#2492](https://github.com/xmrig/xmrig/issues/2492) Added missing `--huge-pages-jit` command line option.
- [#2512](https://github.com/xmrig/xmrig/pull/2512) Added show the number of transactions in pool job.
# v6.13.1
- [#2468](https://github.com/xmrig/xmrig/pull/2468) Fixed regression in previous version: don't send miner signature during regular mining.
# v6.13.0
- [#2445](https://github.com/xmrig/xmrig/pull/2445) Added support for solo mining with miner signatures for the upcoming Wownero fork.
# v6.12.2
- [#2280](https://github.com/xmrig/xmrig/issues/2280) GPU backends are now disabled in benchmark mode.
- [#2322](https://github.com/xmrig/xmrig/pull/2322) Improved MSR compatibility with recent Linux kernels and updated `randomx_boost.sh`.
- [#2340](https://github.com/xmrig/xmrig/pull/2340) Fixed AES detection on FreeBSD on ARM.
- [#2341](https://github.com/xmrig/xmrig/pull/2341) `sse2neon` updated to the latest version.
- [#2351](https://github.com/xmrig/xmrig/issues/2351) Fixed help output for `--cpu-priority` and `--cpu-affinity` option.
- [#2375](https://github.com/xmrig/xmrig/pull/2375) Fixed macOS CUDA backend default loader name.
- [#2378](https://github.com/xmrig/xmrig/pull/2378) Fixed broken light mode mining on x86.
- [#2379](https://github.com/xmrig/xmrig/pull/2379) Fixed CL code for KawPow where it assumes everything is AMD.
- [#2386](https://github.com/xmrig/xmrig/pull/2386) RandomX: enabled `IMUL_RCP` optimization for light mode mining.
- [#2393](https://github.com/xmrig/xmrig/pull/2393) RandomX: added BMI2 version for scratchpad prefetch.
- [#2395](https://github.com/xmrig/xmrig/pull/2395) RandomX: rewrote dataset read code.
- [#2398](https://github.com/xmrig/xmrig/pull/2398) RandomX: optimized ARMv8 dataset read.
- Added `argon2/ninja` alias for `argon2/wrkz` algorithm.
# v6.12.1
- [#2296](https://github.com/xmrig/xmrig/pull/2296) Fixed Zen3 assembly code for `cn/upx2` algorithm.
# v6.12.0
- [#2276](https://github.com/xmrig/xmrig/pull/2276) Added support for Uplexa (`cn/upx2` algorithm).
- [#2261](https://github.com/xmrig/xmrig/pull/2261) Show total hashrate if compiled without OpenCL.
- [#2289](https://github.com/xmrig/xmrig/pull/2289) RandomX: optimized `IMUL_RCP` instruction.
- Added support for `--user` command line option for online benchmark.
# v6.11.2 # v6.11.2
- [#2207](https://github.com/xmrig/xmrig/issues/2207) Fixed regression in HTTP parser and llhttp updated to v5.1.0. - [#2207](https://github.com/xmrig/xmrig/issues/2207) Fixed regression in HTTP parser and llhttp updated to v5.1.0.

View File

@@ -5,10 +5,11 @@ option(WITH_HWLOC "Enable hwloc support" ON)
option(WITH_CN_LITE "Enable CryptoNight-Lite algorithms family" ON) option(WITH_CN_LITE "Enable CryptoNight-Lite algorithms family" ON)
option(WITH_CN_HEAVY "Enable CryptoNight-Heavy algorithms family" ON) option(WITH_CN_HEAVY "Enable CryptoNight-Heavy algorithms family" ON)
option(WITH_CN_PICO "Enable CryptoNight-Pico algorithm" ON) option(WITH_CN_PICO "Enable CryptoNight-Pico algorithm" ON)
option(WITH_CN_FEMTO "Enable CryptoNight-UPX2 algorithm" ON)
option(WITH_RANDOMX "Enable RandomX algorithms family" ON) option(WITH_RANDOMX "Enable RandomX algorithms family" ON)
option(WITH_ARGON2 "Enable Argon2 algorithms family" ON) option(WITH_ARGON2 "Enable Argon2 algorithms family" ON)
option(WITH_ASTROBWT "Enable AstroBWT algorithms family" ON)
option(WITH_KAWPOW "Enable KawPow algorithms family" ON) option(WITH_KAWPOW "Enable KawPow algorithms family" ON)
option(WITH_GHOSTRIDER "Enable GhostRider algorithm" ON)
option(WITH_HTTP "Enable HTTP protocol support (client/server)" ON) option(WITH_HTTP "Enable HTTP protocol support (client/server)" ON)
option(WITH_DEBUG_LOG "Enable debug log output" OFF) option(WITH_DEBUG_LOG "Enable debug log output" OFF)
option(WITH_TLS "Enable OpenSSL support" ON) option(WITH_TLS "Enable OpenSSL support" ON)
@@ -17,6 +18,8 @@ option(WITH_MSR "Enable MSR mod & 1st-gen Ryzen fix" ON)
option(WITH_ENV_VARS "Enable environment variables support in config file" ON) option(WITH_ENV_VARS "Enable environment variables support in config file" ON)
option(WITH_EMBEDDED_CONFIG "Enable internal embedded JSON config" OFF) option(WITH_EMBEDDED_CONFIG "Enable internal embedded JSON config" OFF)
option(WITH_OPENCL "Enable OpenCL backend" ON) option(WITH_OPENCL "Enable OpenCL backend" ON)
set(WITH_OPENCL_VERSION 200 CACHE STRING "Target OpenCL version")
set_property(CACHE WITH_OPENCL_VERSION PROPERTY STRINGS 120 200 210 220)
option(WITH_CUDA "Enable CUDA backend" ON) option(WITH_CUDA "Enable CUDA backend" ON)
option(WITH_NVML "Enable NVML (NVIDIA Management Library) support (only if CUDA backend enabled)" ON) option(WITH_NVML "Enable NVML (NVIDIA Management Library) support (only if CUDA backend enabled)" ON)
option(WITH_ADL "Enable ADL (AMD Display Library) or sysfs support (only if OpenCL backend enabled)" ON) option(WITH_ADL "Enable ADL (AMD Display Library) or sysfs support (only if OpenCL backend enabled)" ON)
@@ -24,6 +27,7 @@ option(WITH_STRICT_CACHE "Enable strict checks for OpenCL cache" ON)
option(WITH_INTERLEAVE_DEBUG_LOG "Enable debug log for threads interleave" OFF) option(WITH_INTERLEAVE_DEBUG_LOG "Enable debug log for threads interleave" OFF)
option(WITH_PROFILING "Enable profiling for developers" OFF) option(WITH_PROFILING "Enable profiling for developers" OFF)
option(WITH_SSE4_1 "Enable SSE 4.1 for Blake2" ON) option(WITH_SSE4_1 "Enable SSE 4.1 for Blake2" ON)
option(WITH_VAES "Enable VAES instructions for Cryptonight" ON)
option(WITH_BENCHMARK "Enable builtin RandomX benchmark and stress test" ON) option(WITH_BENCHMARK "Enable builtin RandomX benchmark and stress test" ON)
option(WITH_SECURE_JIT "Enable secure access to JIT memory" OFF) option(WITH_SECURE_JIT "Enable secure access to JIT memory" OFF)
option(WITH_DMI "Enable DMI/SMBIOS reader" ON) option(WITH_DMI "Enable DMI/SMBIOS reader" ON)
@@ -55,6 +59,7 @@ set(HEADERS
src/core/config/usage.h src/core/config/usage.h
src/core/Controller.h src/core/Controller.h
src/core/Miner.h src/core/Miner.h
src/core/Taskbar.h
src/net/interfaces/IJobResultListener.h src/net/interfaces/IJobResultListener.h
src/net/JobResult.h src/net/JobResult.h
src/net/JobResults.h src/net/JobResults.h
@@ -103,6 +108,7 @@ set(SOURCES
src/core/config/ConfigTransform.cpp src/core/config/ConfigTransform.cpp
src/core/Controller.cpp src/core/Controller.cpp
src/core/Miner.cpp src/core/Miner.cpp
src/core/Taskbar.cpp
src/net/JobResults.cpp src/net/JobResults.cpp
src/net/Network.cpp src/net/Network.cpp
src/net/strategies/DonateStrategy.cpp src/net/strategies/DonateStrategy.cpp
@@ -123,6 +129,19 @@ set(SOURCES_CRYPTO
src/crypto/common/VirtualMemory.cpp src/crypto/common/VirtualMemory.cpp
) )
if (CMAKE_C_COMPILER_ID MATCHES GNU)
set_source_files_properties(src/crypto/cn/CnHash.cpp PROPERTIES COMPILE_FLAGS "-Ofast -fno-tree-vectorize")
endif()
if (WITH_VAES)
add_definitions(-DXMRIG_VAES)
set(HEADERS_CRYPTO "${HEADERS_CRYPTO}" src/crypto/cn/CryptoNight_x86_vaes.h)
set(SOURCES_CRYPTO "${SOURCES_CRYPTO}" src/crypto/cn/CryptoNight_x86_vaes.cpp)
if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES Clang)
set_source_files_properties(src/crypto/cn/CryptoNight_x86_vaes.cpp PROPERTIES COMPILE_FLAGS "-Ofast -fno-tree-vectorize -mavx2 -mvaes")
endif()
endif()
if (WITH_HWLOC) if (WITH_HWLOC)
list(APPEND HEADERS_CRYPTO list(APPEND HEADERS_CRYPTO
src/crypto/common/NUMAMemoryPool.h src/crypto/common/NUMAMemoryPool.h
@@ -137,14 +156,12 @@ endif()
if (XMRIG_OS_WIN) if (XMRIG_OS_WIN)
list(APPEND SOURCES_OS list(APPEND SOURCES_OS
res/app.rc res/app.rc
src/App_win.cpp
src/crypto/common/VirtualMemory_win.cpp src/crypto/common/VirtualMemory_win.cpp
) )
set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv) set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
elseif (XMRIG_OS_APPLE) elseif (XMRIG_OS_APPLE)
list(APPEND SOURCES_OS list(APPEND SOURCES_OS
src/App_unix.cpp
src/crypto/common/VirtualMemory_unix.cpp src/crypto/common/VirtualMemory_unix.cpp
) )
@@ -153,7 +170,6 @@ elseif (XMRIG_OS_APPLE)
set(EXTRA_LIBS ${IOKIT_LIBRARY} ${CORESERVICES_LIBRARY}) set(EXTRA_LIBS ${IOKIT_LIBRARY} ${CORESERVICES_LIBRARY})
else() else()
list(APPEND SOURCES_OS list(APPEND SOURCES_OS
src/App_unix.cpp
src/crypto/common/VirtualMemory_unix.cpp src/crypto/common/VirtualMemory_unix.cpp
) )
@@ -171,7 +187,7 @@ else()
endif() endif()
endif() endif()
add_definitions(-DXMRIG_MINER_PROJECT -DXMRIG_JSON_SINGLE_LINE_ARRAY) add_definitions(-DXMRIG_MINER_PROJECT -DXMRIG_LEGACY -DXMRIG_JSON_SINGLE_LINE_ARRAY)
add_definitions(-D__STDC_FORMAT_MACROS -DUNICODE -D_FILE_OFFSET_BITS=64) add_definitions(-D__STDC_FORMAT_MACROS -DUNICODE -D_FILE_OFFSET_BITS=64)
find_package(UV REQUIRED) find_package(UV REQUIRED)
@@ -179,8 +195,8 @@ find_package(UV REQUIRED)
include(cmake/flags.cmake) include(cmake/flags.cmake)
include(cmake/randomx.cmake) include(cmake/randomx.cmake)
include(cmake/argon2.cmake) include(cmake/argon2.cmake)
include(cmake/astrobwt.cmake)
include(cmake/kawpow.cmake) include(cmake/kawpow.cmake)
include(cmake/ghostrider.cmake)
include(cmake/OpenSSL.cmake) include(cmake/OpenSSL.cmake)
include(cmake/asm.cmake) include(cmake/asm.cmake)
@@ -196,6 +212,10 @@ if (WITH_CN_PICO)
add_definitions(/DXMRIG_ALGO_CN_PICO) add_definitions(/DXMRIG_ALGO_CN_PICO)
endif() endif()
if (WITH_CN_FEMTO)
add_definitions(/DXMRIG_ALGO_CN_FEMTO)
endif()
if (WITH_EMBEDDED_CONFIG) if (WITH_EMBEDDED_CONFIG)
add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG) add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG)
endif() endif()
@@ -212,7 +232,7 @@ if (WITH_DEBUG_LOG)
endif() endif()
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES}) add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES})
target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB} ${ARGON2_LIBRARY} ${ETHASH_LIBRARY}) 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}>) 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}>)
@@ -220,6 +240,7 @@ if (WIN32)
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}>)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/scripts/solo_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/solo_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/rtm_ghostrider_example.cmd" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
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)

View File

@@ -7,10 +7,10 @@
[![GitHub stars](https://img.shields.io/github/stars/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/stargazers) [![GitHub stars](https://img.shields.io/github/stars/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/network) [![GitHub forks](https://img.shields.io/github/forks/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/network)
XMRig is a high performance, open source, cross platform RandomX, KawPow, CryptoNight and AstroBWT unified CPU/GPU miner and [RandomX benchmark](https://xmrig.com/benchmark). Official binaries are available for Windows, Linux, macOS and FreeBSD. XMRig is a high performance, open source, cross platform RandomX, KawPow, CryptoNight and [GhostRider](https://github.com/xmrig/xmrig/tree/master/src/crypto/ghostrider#readme) unified CPU/GPU miner and [RandomX benchmark](https://xmrig.com/benchmark). Official binaries are available for Windows, Linux, macOS and FreeBSD.
## Mining backends ## Mining backends
- **CPU** (x64/ARMv8) - **CPU** (x64/ARMv7/ARMv8)
- **OpenCL** for AMD GPUs. - **OpenCL** for AMD GPUs.
- **CUDA** for NVIDIA GPUs via external [CUDA plugin](https://github.com/xmrig/xmrig-cuda). - **CUDA** for NVIDIA GPUs via external [CUDA plugin](https://github.com/xmrig/xmrig-cuda).

View File

@@ -1,45 +0,0 @@
if (WITH_ASTROBWT)
add_definitions(/DXMRIG_ALGO_ASTROBWT)
list(APPEND HEADERS_CRYPTO
src/crypto/astrobwt/AstroBWT.h
)
list(APPEND SOURCES_CRYPTO
src/crypto/astrobwt/AstroBWT.cpp
)
if (XMRIG_ARM)
list(APPEND HEADERS_CRYPTO
src/crypto/astrobwt/salsa20_ref/ecrypt-config.h
src/crypto/astrobwt/salsa20_ref/ecrypt-machine.h
src/crypto/astrobwt/salsa20_ref/ecrypt-portable.h
src/crypto/astrobwt/salsa20_ref/ecrypt-sync.h
)
list(APPEND SOURCES_CRYPTO
src/crypto/astrobwt/salsa20_ref/salsa20.c
)
else()
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
add_definitions(/DASTROBWT_AVX2)
if (CMAKE_C_COMPILER_ID MATCHES MSVC)
enable_language(ASM_MASM)
list(APPEND SOURCES_CRYPTO src/crypto/astrobwt/sha3_256_avx2.asm)
else()
enable_language(ASM)
list(APPEND SOURCES_CRYPTO src/crypto/astrobwt/sha3_256_avx2.S)
endif()
endif()
list(APPEND HEADERS_CRYPTO
src/crypto/astrobwt/Salsa20.hpp
)
list(APPEND SOURCES_CRYPTO
src/crypto/astrobwt/Salsa20.cpp
)
endif()
else()
remove_definitions(/DXMRIG_ALGO_ASTROBWT)
endif()

View File

@@ -1,11 +1,31 @@
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(XMRIG_64_BIT ON)
add_definitions(-DXMRIG_64_BIT)
else()
set(XMRIG_64_BIT OFF)
endif()
if (NOT CMAKE_SYSTEM_PROCESSOR) if (NOT CMAKE_SYSTEM_PROCESSOR)
message(WARNING "CMAKE_SYSTEM_PROCESSOR not defined") message(WARNING "CMAKE_SYSTEM_PROCESSOR not defined")
endif() endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64)$" AND CMAKE_SIZEOF_VOID_P EQUAL 8) include(CheckCXXCompilerFlag)
add_definitions(/DRAPIDJSON_SSE2)
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
set(VAES_SUPPORTED ON)
else()
CHECK_CXX_COMPILER_FLAG("-mavx2 -mvaes" VAES_SUPPORTED)
endif()
if (NOT VAES_SUPPORTED)
set(WITH_VAES OFF)
endif()
if (XMRIG_64_BIT AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64)$")
add_definitions(-DRAPIDJSON_SSE2)
else() else()
set(WITH_SSE4_1 OFF) set(WITH_SSE4_1 OFF)
set(WITH_VAES OFF)
endif() endif()
if (NOT ARM_TARGET) if (NOT ARM_TARGET)
@@ -17,31 +37,23 @@ if (NOT ARM_TARGET)
endif() endif()
if (ARM_TARGET AND ARM_TARGET GREATER 6) if (ARM_TARGET AND ARM_TARGET GREATER 6)
set(XMRIG_ARM ON) set(XMRIG_ARM ON)
add_definitions(/DXMRIG_ARM) add_definitions(-DXMRIG_ARM=${ARM_TARGET})
message(STATUS "Use ARM_TARGET=${ARM_TARGET} (${CMAKE_SYSTEM_PROCESSOR})") message(STATUS "Use ARM_TARGET=${ARM_TARGET} (${CMAKE_SYSTEM_PROCESSOR})")
include(CheckCXXCompilerFlag)
if (ARM_TARGET EQUAL 8) if (ARM_TARGET EQUAL 8)
set(XMRIG_ARMv8 ON)
add_definitions(/DXMRIG_ARMv8)
CHECK_CXX_COMPILER_FLAG(-march=armv8-a+crypto XMRIG_ARM_CRYPTO) CHECK_CXX_COMPILER_FLAG(-march=armv8-a+crypto XMRIG_ARM_CRYPTO)
if (XMRIG_ARM_CRYPTO) if (XMRIG_ARM_CRYPTO)
add_definitions(/DXMRIG_ARM_CRYPTO) add_definitions(-DXMRIG_ARM_CRYPTO)
set(ARM8_CXX_FLAGS "-march=armv8-a+crypto") set(ARM8_CXX_FLAGS "-march=armv8-a+crypto")
else() else()
set(ARM8_CXX_FLAGS "-march=armv8-a") set(ARM8_CXX_FLAGS "-march=armv8-a")
endif() endif()
elseif (ARM_TARGET EQUAL 7)
set(XMRIG_ARMv7 ON)
add_definitions(/DXMRIG_ARMv7)
endif() endif()
endif() endif()
if (WITH_SSE4_1) if (WITH_SSE4_1)
add_definitions(/DXMRIG_FEATURE_SSE4_1) add_definitions(-DXMRIG_FEATURE_SSE4_1)
endif() endif()

View File

@@ -22,12 +22,12 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexceptions -fno-rtti -Wno-strict-aliasing -Wno-class-memaccess") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexceptions -fno-rtti -Wno-strict-aliasing -Wno-class-memaccess")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s")
if (XMRIG_ARMv8) if (ARM_TARGET EQUAL 8)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARM8_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARM8_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARM8_CXX_FLAGS} -flax-vector-conversions") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARM8_CXX_FLAGS} -flax-vector-conversions")
elseif (XMRIG_ARMv7) elseif (ARM_TARGET EQUAL 7)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfpu=neon")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -flax-vector-conversions") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mfpu=neon -flax-vector-conversions")
else() else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
@@ -80,10 +80,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexceptions -fno-rtti -Wno-missing-braces") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexceptions -fno-rtti -Wno-missing-braces")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
if (XMRIG_ARMv8) if (ARM_TARGET EQUAL 8)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARM8_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARM8_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARM8_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARM8_CXX_FLAGS}")
elseif (XMRIG_ARMv7) elseif (ARM_TARGET EQUAL 7)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}")
else() else()

8
cmake/ghostrider.cmake Normal file
View File

@@ -0,0 +1,8 @@
if (WITH_GHOSTRIDER)
add_definitions(/DXMRIG_ALGO_GHOSTRIDER)
add_subdirectory(src/crypto/ghostrider)
set(GHOSTRIDER_LIBRARY ghostrider)
else()
remove_definitions(/DXMRIG_ALGO_GHOSTRIDER)
set(GHOSTRIDER_LIBRARY "")
endif()

View File

@@ -22,32 +22,31 @@ endif()
if (XMRIG_OS_WIN) if (XMRIG_OS_WIN)
add_definitions(/DWIN32) add_definitions(-DWIN32 -DXMRIG_OS_WIN)
add_definitions(/DXMRIG_OS_WIN)
elseif(XMRIG_OS_APPLE) elseif(XMRIG_OS_APPLE)
add_definitions(/DXMRIG_OS_APPLE) add_definitions(-DXMRIG_OS_APPLE)
if (XMRIG_OS_IOS) if (XMRIG_OS_IOS)
add_definitions(/DXMRIG_OS_IOS) add_definitions(-DXMRIG_OS_IOS)
else() else()
add_definitions(/DXMRIG_OS_MACOS) add_definitions(-DXMRIG_OS_MACOS)
endif() endif()
if (XMRIG_ARM) if (XMRIG_ARM)
set(WITH_SECURE_JIT ON) set(WITH_SECURE_JIT ON)
endif() endif()
elseif(XMRIG_OS_UNIX) elseif(XMRIG_OS_UNIX)
add_definitions(/DXMRIG_OS_UNIX) add_definitions(-DXMRIG_OS_UNIX)
if (XMRIG_OS_ANDROID) if (XMRIG_OS_ANDROID)
add_definitions(/DXMRIG_OS_ANDROID) add_definitions(-DXMRIG_OS_ANDROID)
elseif (XMRIG_OS_LINUX) elseif (XMRIG_OS_LINUX)
add_definitions(/DXMRIG_OS_LINUX) add_definitions(-DXMRIG_OS_LINUX)
elseif (XMRIG_OS_FREEBSD) elseif (XMRIG_OS_FREEBSD)
add_definitions(/DXMRIG_OS_FREEBSD) add_definitions(-DXMRIG_OS_FREEBSD)
endif() endif()
endif() endif()
if (WITH_SECURE_JIT) if (WITH_SECURE_JIT)
add_definitions(/DXMRIG_SECURE_JIT) add_definitions(-DXMRIG_SECURE_JIT)
endif() endif()

View File

@@ -20,7 +20,7 @@ VS_VERSION_INFO VERSIONINFO
BEGIN BEGIN
BLOCK "000004b0" BLOCK "000004b0"
BEGIN BEGIN
VALUE "CompanyName", APP_SITE VALUE "CompanyName", APP_DOMAIN
VALUE "FileDescription", APP_DESC VALUE "FileDescription", APP_DESC
VALUE "FileVersion", APP_VERSION VALUE "FileVersion", APP_VERSION
VALUE "LegalCopyright", APP_COPYRIGHT VALUE "LegalCopyright", APP_COPYRIGHT

View File

@@ -1,6 +1,10 @@
#!/bin/bash -e #!/bin/bash -e
HWLOC_VERSION="2.4.1" HWLOC_VERSION_MAJOR="2"
HWLOC_VERSION_MINOR="7"
HWLOC_VERSION_PATCH="1"
HWLOC_VERSION="${HWLOC_VERSION_MAJOR}.${HWLOC_VERSION_MINOR}.${HWLOC_VERSION_PATCH}"
mkdir -p deps mkdir -p deps
mkdir -p deps/include mkdir -p deps/include
@@ -8,7 +12,7 @@ mkdir -p deps/lib
mkdir -p build && cd build mkdir -p build && cd build
wget https://download.open-mpi.org/release/hwloc/v2.4/hwloc-${HWLOC_VERSION}.tar.gz -O hwloc-${HWLOC_VERSION}.tar.gz wget https://download.open-mpi.org/release/hwloc/v${HWLOC_VERSION_MAJOR}.${HWLOC_VERSION_MINOR}/hwloc-${HWLOC_VERSION}.tar.gz -O hwloc-${HWLOC_VERSION}.tar.gz
tar -xzf hwloc-${HWLOC_VERSION}.tar.gz tar -xzf hwloc-${HWLOC_VERSION}.tar.gz
cd hwloc-${HWLOC_VERSION} cd hwloc-${HWLOC_VERSION}
@@ -16,4 +20,4 @@ cd hwloc-${HWLOC_VERSION}
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu) make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
cp -fr include ../../deps cp -fr include ../../deps
cp hwloc/.libs/libhwloc.a ../../deps/lib cp hwloc/.libs/libhwloc.a ../../deps/lib
cd .. cd ..

View File

@@ -1,6 +1,6 @@
#!/bin/bash -e #!/bin/bash -e
LIBRESSL_VERSION="3.0.2" LIBRESSL_VERSION="3.5.2"
mkdir -p deps mkdir -p deps
mkdir -p deps/include mkdir -p deps/include
@@ -17,4 +17,4 @@ make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
cp -fr include ../../deps cp -fr include ../../deps
cp crypto/.libs/libcrypto.a ../../deps/lib cp crypto/.libs/libcrypto.a ../../deps/lib
cp ssl/.libs/libssl.a ../../deps/lib cp ssl/.libs/libssl.a ../../deps/lib
cd .. cd ..

View File

@@ -1,6 +1,6 @@
#!/bin/bash -e #!/bin/bash -e
OPENSSL_VERSION="1.1.1j" OPENSSL_VERSION="1.1.1o"
mkdir -p deps mkdir -p deps
mkdir -p deps/include mkdir -p deps/include
@@ -17,4 +17,4 @@ make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
cp -fr include ../../deps cp -fr include ../../deps
cp libcrypto.a ../../deps/lib cp libcrypto.a ../../deps/lib
cp libssl.a ../../deps/lib cp libssl.a ../../deps/lib
cd .. cd ..

20
scripts/build.openssl3.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/bash -e
OPENSSL_VERSION="3.0.3"
mkdir -p deps
mkdir -p deps/include
mkdir -p deps/lib
mkdir -p build && cd build
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz
tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
cd openssl-${OPENSSL_VERSION}
./config -no-shared -no-asm -no-zlib -no-comp -no-dgram -no-filenames -no-cms
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
cp -fr include ../../deps
cp libcrypto.a ../../deps/lib
cp libssl.a ../../deps/lib
cd ..

View File

@@ -1,6 +1,6 @@
#!/bin/bash -e #!/bin/bash -e
UV_VERSION="1.41.0" UV_VERSION="1.44.1"
mkdir -p deps mkdir -p deps
mkdir -p deps/include mkdir -p deps/include
@@ -17,4 +17,4 @@ sh autogen.sh
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu) make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
cp -fr include ../../deps cp -fr include ../../deps
cp .libs/libuv.a ../../deps/lib cp .libs/libuv.a ../../deps/lib
cd .. cd ..

View File

@@ -51,6 +51,7 @@ function rx()
'randomx_constants_wow.h', 'randomx_constants_wow.h',
'randomx_constants_arqma.h', 'randomx_constants_arqma.h',
'randomx_constants_keva.h', 'randomx_constants_keva.h',
'randomx_constants_graft.h',
'aes.cl', 'aes.cl',
'blake2b.cl', 'blake2b.cl',
'randomx_vm.cl', 'randomx_vm.cl',
@@ -66,15 +67,6 @@ function rx()
} }
function astrobwt()
{
const astrobwt = opencl_minify(addIncludes('astrobwt.cl', [ 'BWT.cl', 'salsa20.cl', 'sha3.cl' ]));
// fs.writeFileSync('astrobwt_gen.cl', astrobwt);
fs.writeFileSync('astrobwt_cl.h', text2h(astrobwt, 'xmrig', 'astrobwt_cl'));
}
function kawpow() function kawpow()
{ {
const kawpow = opencl_minify(addIncludes('kawpow.cl', [ 'defs.h' ])); const kawpow = opencl_minify(addIncludes('kawpow.cl', [ 'defs.h' ]));
@@ -96,11 +88,6 @@ process.chdir(path.resolve('src/backend/opencl/cl/rx'));
rx(); rx();
process.chdir(cwd);
process.chdir(path.resolve('src/backend/opencl/cl/astrobwt'));
astrobwt();
process.chdir(cwd); process.chdir(cwd);
process.chdir(path.resolve('src/backend/opencl/cl/kawpow')); process.chdir(path.resolve('src/backend/opencl/cl/kawpow'));

View File

@@ -1,28 +1,34 @@
#!/bin/bash #!/bin/sh -e
modprobe msr MSR_FILE=/sys/module/msr/parameters/allow_writes
if cat /proc/cpuinfo | grep "AMD Ryzen" > /dev/null; if test -e "$MSR_FILE"; then
echo on > $MSR_FILE
else
modprobe msr allow_writes=on
fi
if grep -E 'AMD Ryzen|AMD EPYC' /proc/cpuinfo > /dev/null;
then then
if cat /proc/cpuinfo | grep "cpu family[[:space:]]:[[:space:]]25" > /dev/null; if grep "cpu family[[:space:]]:[[:space:]]25" /proc/cpuinfo > /dev/null;
then then
echo "Detected Ryzen (Zen3)" echo "Detected Zen3 CPU"
wrmsr -a 0xc0011020 0x4480000000000 wrmsr -a 0xc0011020 0x4480000000000
wrmsr -a 0xc0011021 0x1c000200000040 wrmsr -a 0xc0011021 0x1c000200000040
wrmsr -a 0xc0011022 0xc000000401500000 wrmsr -a 0xc0011022 0xc000000401500000
wrmsr -a 0xc001102b 0x2000cc14 wrmsr -a 0xc001102b 0x2000cc14
echo "MSR register values for Ryzen (Zen3) applied" echo "MSR register values for Zen3 applied"
else else
echo "Detected Ryzen (Zen1/Zen2)" echo "Detected Zen1/Zen2 CPU"
wrmsr -a 0xc0011020 0 wrmsr -a 0xc0011020 0
wrmsr -a 0xc0011021 0x40 wrmsr -a 0xc0011021 0x40
wrmsr -a 0xc0011022 0x1510000 wrmsr -a 0xc0011022 0x1510000
wrmsr -a 0xc001102b 0x2000cc16 wrmsr -a 0xc001102b 0x2000cc16
echo "MSR register values for Ryzen (Zen1/Zen2) applied" echo "MSR register values for Zen1/Zen2 applied"
fi fi
elif cat /proc/cpuinfo | grep "Intel" > /dev/null; elif grep "Intel" /proc/cpuinfo > /dev/null;
then then
echo "Detected Intel" echo "Detected Intel CPU"
wrmsr -a 0x1a4 0xf wrmsr -a 0x1a4 0xf
echo "MSR register values for Intel applied" echo "MSR register values for Intel applied"
else else

View File

@@ -0,0 +1,23 @@
:: Example batch file for mining Raptoreum at a pool
::
:: Format:
:: xmrig.exe -a gr -o <pool address>:<pool port> -u <pool username/wallet> -p <pool password>
::
:: Fields:
:: pool address The host name of the pool stratum or its IP address, for example raptoreumemporium.com
:: pool port The port of the pool's stratum to connect to, for example 3333. Check your pool's getting started page.
:: pool username/wallet For most pools, this is the wallet address you want to mine to. Some pools require a username
:: pool password For most pools this can be just 'x'. For pools using usernames, you may need to provide a password as configured on the pool.
::
:: List of Raptoreum mining pools:
:: https://miningpoolstats.stream/raptoreum
::
:: Choose pools outside of top 5 to help Raptoreum network be more decentralized!
:: Smaller pools also often have smaller fees/payout limits.
cd %~dp0
:: Use this command line to connect to non-SSL port
xmrig.exe -a gr -o raptoreumemporium.com:3008 -u WALLET_ADDRESS -p x
:: Or use this command line to connect to an SSL port
:: xmrig.exe -a gr -o rtm.suprnova.cc:4273 --tls -u WALLET_ADDRESS -p x
pause

View File

@@ -44,7 +44,7 @@ extern "C" {
typedef cl_uint cl_dx9_media_adapter_type_khr; typedef cl_uint cl_dx9_media_adapter_type_khr;
typedef cl_uint cl_dx9_media_adapter_set_khr; typedef cl_uint cl_dx9_media_adapter_set_khr;
#if defined(_WIN32) #if defined(_WIN32)
#include <d3d9.h> #include <d3d9.h>
typedef struct _cl_dx9_surface_info_khr typedef struct _cl_dx9_surface_info_khr
@@ -105,7 +105,7 @@ typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromDX9MediaSurfaceKHR_fn)(
cl_mem_flags flags, cl_mem_flags flags,
cl_dx9_media_adapter_type_khr adapter_type, cl_dx9_media_adapter_type_khr adapter_type,
void * surface_info, void * surface_info,
cl_uint plane, cl_uint plane,
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2; cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2;
typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireDX9MediaSurfacesKHR_fn)( typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireDX9MediaSurfacesKHR_fn)(

View File

@@ -35,7 +35,7 @@ extern "C" {
#include <CL/cl_gl.h> #include <CL/cl_gl.h>
/* /*
* cl_khr_gl_event extension * cl_khr_gl_event extension
*/ */
#define CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR 0x200D #define CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR 0x200D

View File

@@ -1471,7 +1471,7 @@ typedef enum _ADLProfilePropertyType
#define ADL_HDR_FREESYNC_HDR 0x0004 ///< FreeSync HDR supported #define ADL_HDR_FREESYNC_HDR 0x0004 ///< FreeSync HDR supported
/// @} /// @}
/// \defgroup define_FreesyncFlags ADLDDCInfo2 Freesync HDR flags /// \defgroup define_FreesyncFlags ADLDDCInfo2 Freesync HDR flags
/// @{ /// @{
/// defines for iFreesyncFlags in ADLDDCInfo2 /// defines for iFreesyncFlags in ADLDDCInfo2
#define ADL_HDR_FREESYNC_BACKLIGHT_SUPPORT 0x0001 ///< Global backlight control supported #define ADL_HDR_FREESYNC_BACKLIGHT_SUPPORT 0x0001 ///< Global backlight control supported
@@ -1738,7 +1738,7 @@ enum ADLODNDPMMaskType
ADL_ODN_DPM_MASK = 1 << 2, ADL_ODN_DPM_MASK = 1 << 2,
}; };
//ODN features Bits for ADLODNCapabilitiesX2 //ODN features Bits for ADLODNCapabilitiesX2
enum ADLODNFeatureControl enum ADLODNFeatureControl
{ {
ADL_ODN_SCLK_DPM = 1 << 0, ADL_ODN_SCLK_DPM = 1 << 0,
@@ -1764,7 +1764,7 @@ enum ADLODNFeatureControl
//If any new feature is added, PPLIB only needs to add ext feature ID and Item ID(Seeting ID). These IDs should match the drive defined in CWDDEPM.h //If any new feature is added, PPLIB only needs to add ext feature ID and Item ID(Seeting ID). These IDs should match the drive defined in CWDDEPM.h
enum ADLODNExtFeatureControl enum ADLODNExtFeatureControl
{ {
ADL_ODN_EXT_FEATURE_MEMORY_TIMING_TUNE = 1 << 0, ADL_ODN_EXT_FEATURE_MEMORY_TIMING_TUNE = 1 << 0,
ADL_ODN_EXT_FEATURE_FAN_ZERO_RPM_CONTROL = 1 << 1, ADL_ODN_EXT_FEATURE_FAN_ZERO_RPM_CONTROL = 1 << 1,
ADL_ODN_EXT_FEATURE_AUTO_UV_ENGINE = 1 << 2, //Auto under voltage ADL_ODN_EXT_FEATURE_AUTO_UV_ENGINE = 1 << 2, //Auto under voltage
@@ -1794,7 +1794,7 @@ enum ADLODNExtSettingId
ADL_ODN_PARAMETER_FAN_CURVE_SPEED_5, ADL_ODN_PARAMETER_FAN_CURVE_SPEED_5,
ADL_ODN_POWERGAUGE, ADL_ODN_POWERGAUGE,
ODN_COUNT ODN_COUNT
} ; } ;
//OD8 Capability features bits //OD8 Capability features bits
@@ -1811,7 +1811,7 @@ enum ADLOD8FeatureControl
ADL_OD8_MEMORY_TIMING_TUNE = 1 << 8, ADL_OD8_MEMORY_TIMING_TUNE = 1 << 8,
ADL_OD8_FAN_ZERO_RPM_CONTROL = 1 << 9 , ADL_OD8_FAN_ZERO_RPM_CONTROL = 1 << 9 ,
ADL_OD8_AUTO_UV_ENGINE = 1 << 10, //Auto under voltage ADL_OD8_AUTO_UV_ENGINE = 1 << 10, //Auto under voltage
ADL_OD8_AUTO_OC_ENGINE = 1 << 11, //Auto overclock engine ADL_OD8_AUTO_OC_ENGINE = 1 << 11, //Auto overclock engine
ADL_OD8_AUTO_OC_MEMORY = 1 << 12, //Auto overclock memory ADL_OD8_AUTO_OC_MEMORY = 1 << 12, //Auto overclock memory
ADL_OD8_FAN_CURVE = 1 << 13, //Fan curve ADL_OD8_FAN_CURVE = 1 << 13, //Fan curve
ADL_OD8_WS_AUTO_FAN_ACOUSTIC_LIMIT = 1 << 14, //Workstation Manual Fan controller ADL_OD8_WS_AUTO_FAN_ACOUSTIC_LIMIT = 1 << 14, //Workstation Manual Fan controller
@@ -1888,7 +1888,7 @@ typedef enum _ADLSensorType
PMLOG_TEMPERATURE_VRSOC = 24, PMLOG_TEMPERATURE_VRSOC = 24,
PMLOG_TEMPERATURE_VRMVDD0 = 25, PMLOG_TEMPERATURE_VRMVDD0 = 25,
PMLOG_TEMPERATURE_VRMVDD1 = 26, PMLOG_TEMPERATURE_VRMVDD1 = 26,
PMLOG_TEMPERATURE_HOTSPOT = 27, PMLOG_TEMPERATURE_HOTSPOT = 27,
PMLOG_TEMPERATURE_GFX = 28, PMLOG_TEMPERATURE_GFX = 28,
PMLOG_TEMPERATURE_SOC = 29, PMLOG_TEMPERATURE_SOC = 29,
PMLOG_GFX_POWER = 30, PMLOG_GFX_POWER = 30,

View File

@@ -37,7 +37,7 @@
#define __stdcall #define __stdcall
#endif /* (LINUX) */ #endif /* (LINUX) */
/// Memory Allocation Call back /// Memory Allocation Call back
typedef void* ( __stdcall *ADL_MAIN_MALLOC_CALLBACK )( int ); typedef void* ( __stdcall *ADL_MAIN_MALLOC_CALLBACK )( int );

View File

@@ -1753,7 +1753,7 @@ typedef struct ADLPXConfigCaps
///\brief Enum containing PX or HG type ///\brief Enum containing PX or HG type
/// ///
/// This enum is used to get PX or hG type /// This enum is used to get PX or hG type
/// ///
/// \nosubgrouping /// \nosubgrouping
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
enum ADLPxType enum ADLPxType

25
src/3rdparty/epee/LICENSE.txt vendored Normal file
View File

@@ -0,0 +1,25 @@
Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Andrey N. Sabelnikov nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Andrey N. Sabelnikov BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

1
src/3rdparty/epee/README.md vendored Normal file
View File

@@ -0,0 +1 @@
epee - is a small library of helpers, wrappers, tools and and so on, used to make my life easier.

176
src/3rdparty/epee/span.h vendored Normal file
View File

@@ -0,0 +1,176 @@
// Copyright (c) 2017-2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#include <algorithm>
#include <cstdint>
#include <memory>
#include <string>
#include <type_traits>
namespace epee
{
/*!
\brief Non-owning sequence of data. Does not deep copy
Inspired by `gsl::span` and/or `boost::iterator_range`. This class is
intended to be used as a parameter type for functions that need to take a
writable or read-only sequence of data. Most common cases are `span<char>`
and `span<std::uint8_t>`. Using as a class member is only recommended if
clearly documented as not doing a deep-copy. C-arrays are easily convertible
to this type.
\note Conversion from C string literal to `span<const char>` will include
the NULL-terminator.
\note Never allows derived-to-base pointer conversion; an array of derived
types is not an array of base types.
*/
template<typename T>
class span
{
template<typename U>
static constexpr bool safe_conversion() noexcept
{
// Allow exact matches or `T*` -> `const T*`.
using with_const = typename std::add_const<U>::type;
return std::is_same<T, U>() ||
(std::is_const<T>() && std::is_same<T, with_const>());
}
public:
using value_type = T;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using iterator = pointer;
using const_iterator = const_pointer;
constexpr span() noexcept : ptr(nullptr), len(0) {}
constexpr span(std::nullptr_t) noexcept : span() {}
//! Prevent derived-to-base conversions; invalid in this context.
template<typename U, typename = typename std::enable_if<safe_conversion<U>()>::type>
constexpr span(U* const src_ptr, const std::size_t count) noexcept
: ptr(src_ptr), len(count) {}
//! Conversion from C-array. Prevents common bugs with sizeof + arrays.
template<std::size_t N>
constexpr span(T (&src)[N]) noexcept : span(src, N) {}
constexpr span(const span&) noexcept = default;
span& operator=(const span&) noexcept = default;
/*! Try to remove `amount` elements from beginning of span.
\return Number of elements removed. */
std::size_t remove_prefix(std::size_t amount) noexcept
{
amount = std::min(len, amount);
ptr += amount;
len -= amount;
return amount;
}
constexpr iterator begin() const noexcept { return ptr; }
constexpr const_iterator cbegin() const noexcept { return ptr; }
constexpr iterator end() const noexcept { return begin() + size(); }
constexpr const_iterator cend() const noexcept { return cbegin() + size(); }
constexpr bool empty() const noexcept { return size() == 0; }
constexpr pointer data() const noexcept { return ptr; }
constexpr std::size_t size() const noexcept { return len; }
constexpr std::size_t size_bytes() const noexcept { return size() * sizeof(value_type); }
T &operator[](size_t idx) noexcept { return ptr[idx]; }
const T &operator[](size_t idx) const noexcept { return ptr[idx]; }
private:
T* ptr;
std::size_t len;
};
//! \return `span<const T::value_type>` from a STL compatible `src`.
template<typename T>
constexpr span<const typename T::value_type> to_span(const T& src)
{
// compiler provides diagnostic if size() is not size_t.
return {src.data(), src.size()};
}
//! \return `span<T::value_type>` from a STL compatible `src`.
template<typename T>
constexpr span<typename T::value_type> to_mut_span(T& src)
{
// compiler provides diagnostic if size() is not size_t.
return {src.data(), src.size()};
}
template<typename T>
constexpr bool has_padding() noexcept
{
return !std::is_standard_layout<T>() || alignof(T) != 1;
}
//! \return Cast data from `src` as `span<const std::uint8_t>`.
template<typename T>
span<const std::uint8_t> to_byte_span(const span<const T> src) noexcept
{
static_assert(!has_padding<T>(), "source type may have padding");
return {reinterpret_cast<const std::uint8_t*>(src.data()), src.size_bytes()};
}
//! \return `span<const std::uint8_t>` which represents the bytes at `&src`.
template<typename T>
span<const std::uint8_t> as_byte_span(const T& src) noexcept
{
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
static_assert(!has_padding<T>(), "source type may have padding");
return {reinterpret_cast<const std::uint8_t*>(std::addressof(src)), sizeof(T)};
}
//! \return `span<std::uint8_t>` which represents the bytes at `&src`.
template<typename T>
span<std::uint8_t> as_mut_byte_span(T& src) noexcept
{
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
static_assert(!has_padding<T>(), "source type may have padding");
return {reinterpret_cast<std::uint8_t*>(std::addressof(src)), sizeof(T)};
}
//! make a span from a std::string
template<typename T>
span<const T> strspan(const std::string &s) noexcept
{
static_assert(std::is_same<T, char>() || std::is_same<T, unsigned char>() || std::is_same<T, int8_t>() || std::is_same<T, uint8_t>(), "Unexpected type");
return {reinterpret_cast<const T*>(s.data()), s.size()};
}
}

View File

@@ -81,7 +81,7 @@ Examples
.. code:: c++ .. code:: c++
#include <fmt/core.h> #include <fmt/core.h>
int main() { int main() {
fmt::print("Hello, world!\n"); fmt::print("Hello, world!\n");
} }
@@ -293,11 +293,11 @@ Projects using this library
An open-source library for mathematical programming An open-source library for mathematical programming
* `Aseprite <https://github.com/aseprite/aseprite>`_: * `Aseprite <https://github.com/aseprite/aseprite>`_:
Animated sprite editor & pixel art tool Animated sprite editor & pixel art tool
* `AvioBook <https://www.aviobook.aero/en>`_: A comprehensive aircraft * `AvioBook <https://www.aviobook.aero/en>`_: A comprehensive aircraft
operations suite operations suite
* `Celestia <https://celestia.space/>`_: Real-time 3D visualization of space * `Celestia <https://celestia.space/>`_: Real-time 3D visualization of space
* `Ceph <https://ceph.com/>`_: A scalable distributed storage system * `Ceph <https://ceph.com/>`_: A scalable distributed storage system
@@ -351,7 +351,7 @@ Projects using this library
* `quasardb <https://www.quasardb.net/>`_: A distributed, high-performance, * `quasardb <https://www.quasardb.net/>`_: A distributed, high-performance,
associative database associative database
* `Quill <https://github.com/odygrd/quill>`_: Asynchronous low-latency logging library * `Quill <https://github.com/odygrd/quill>`_: Asynchronous low-latency logging library
* `QKW <https://github.com/ravijanjam/qkw>`_: Generalizing aliasing to simplify * `QKW <https://github.com/ravijanjam/qkw>`_: Generalizing aliasing to simplify

View File

@@ -3,9 +3,9 @@
* DISCLAIMER * DISCLAIMER
* This file is part of the mingw-w64 runtime package. * This file is part of the mingw-w64 runtime package.
* *
* The mingw-w64 runtime package and its code is distributed in the hope that it * The mingw-w64 runtime package and its code is distributed in the hope that it
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/ */
/* /*
@@ -109,11 +109,7 @@ char *optarg; /* argument associated with option */
extern char __declspec(dllimport) *__progname; extern char __declspec(dllimport) *__progname;
#endif #endif
#ifdef __CYGWIN__
static char EMSG[] = ""; static char EMSG[] = "";
#else
#define EMSG ""
#endif
static int getopt_internal(int, char * const *, const char *, static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int); const struct option *, int *, int);

View File

@@ -1,5 +1,5 @@
Copyright © 2009 CNRS Copyright © 2009 CNRS
Copyright © 2009-2020 Inria. All rights reserved. Copyright © 2009-2022 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,158 @@ bug fixes (and other actions) for each version of hwloc since version
0.9. 0.9.
Version 2.7.1
-------------
* Workaround crashes when virtual machines report incoherent x86 CPUID
information about numbers of cores and threads.
Thanks to Peter Bense for the report.
* Use setenv() instead of putenv() when trying to force enable oneAPI L0
support, to avoid issues with applications that touch the environment,
thanks to Josh Hursey for the patch.
* Add some warnings at the end of configure when GPU libraries are
missing on the system or their path is missing in the environment.
Version 2.7.0
-------------
* Backends
+ Add support for NUMA nodes and caches with more than 64 PUs across
multiple processor groups on Windows 11 and Windows Server 2022.
+ Group objects are not created for Windows processor groups anymore,
except if HWLOC_WINDOWS_PROCESSOR_GROUP_OBJS=1 in the environment.
+ Expose "Cluster" group objects on Linux kernel 5.16+ for CPUs
that share some internal cache or bus. This can be equivalent
to the L2 Cache level on some platforms (e.g. x86) or a specific
level between L2 and L3 on others (e.g. ARM Kungpeng 920).
Thanks to Jonathan Cameron for the help.
- HWLOC_DONT_MERGE_CLUSTER_GROUPS=1 may be set in the environment
to prevent these groups from being merged with identical caches, etc.
+ Improve the oneAPI LevelZero backend:
- Expose subdevices such as "ze0.1" inside root OS devices ("ze0")
when the hardware contains multiple subdevices.
- Add many new attributes to describe device type, and the
numbers of slices, subslices, execution units and threads.
- Expose the memory information as LevelZeroHBM/DDR/MemorySize infos.
+ Ignore the max frequencies of cores in Linux cpukinds when the
base frequencies are available (to avoid exposing hybrid CPUs
when Intel Turbo Boost Max 3.0 gives slightly different max
frequencies to CPU cores).
- May be reverted by setting HWLOC_CPUKINDS_MAXFREQ=1 in the environment.
* Tools
+ Add --grey and --palette options to switch lstopo to greyscale or
white-background-only graphics, or to tune individual colors.
* Build
+ Windows CMake builds now support non-MSVC compilers, detect several
features at build time, can build/run tests, etc.
Thanks to Michael Hirsch and Alexander Neumann .
Version 2.6.0
-------------
* Backends
+ Expose two cpukinds for energy-efficient cores (icestorm) and
high-performance cores (firestorm) on Apple M1 on Mac OS X.
+ Use sysfs CPU "capacity" to rank hybrid cores by efficiency
on Linux when available (mostly on recent ARM platforms for now).
+ Improve HWLOC_MEMBIND_BIND (without the STRICT flag) on Linux kernel
>= 5.15: If more than one node is given, the kernel may now use all
of them instead of only the first one before falling back to others.
+ Expose cache os_index when available on Linux, it may be needed
when using resctrl to configure cache partitioning, memory bandwidth
monitoring, etc.
+ Add a "XGMIHops" distances matrix in the RSMI backend for AMD GPU
interconnected through XGMI links.
+ Expose AMD GPU memory information (VRAM and GTT) in the RSMI backend.
+ Add OS devices such as "bxi0" for Atos/Bull BXI HCAs on Linux.
* Tools
+ lstopo has a better placement algorithm with respect to I/O
objects, see --children-order in the manpage for details.
+ hwloc-annotate may now change object subtypes and cache or memory
sizes.
* Build
+ Allow to specify the ROCm installation for building the RSMI backend:
- Use a custom installation path if specified with --with-rocm=<dir>.
- Use /opt/rocm-<version> if specified with --with-rocm-version=<version>
or the ROCM_VERSION environment variable.
- Try /opt/rocm if it exists.
- See "How do I enable ROCm SMI and select which version to use?"
in the FAQ for details.
+ Add a CMakeLists for Windows under contrib/windows-cmake/ .
* Documentation
+ Add FAQ entry "How do I create a custom heterogeneous and
asymmetric topology?"
Version 2.5.0
-------------
* API
+ Add hwloc/windows.h to query Windows processor groups.
+ Add hwloc_get_obj_with_same_locality() to convert between objects
with same locality, for instance NUMA nodes and Packages,
or OS devices within a PCI device.
+ Add hwloc_distances_transform() to modify distances structures.
- hwloc-annotate and lstopo have new distances-transform options.
+ hwloc_distances_add() is replaced with _add_create() followed by
_add_values() and _add_commit(). See hwloc/distances.h for details.
+ Add topology flags to mitigate binding modifications during
hwloc discovery, especially on Windows:
- HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING and _MEMBINDING
restrict discovery to PUs and NUMA nodes inside the binding.
- HWLOC_TOPOLOGY_FLAG_DONT_CHANGE_BINDING prevents from ever
changing the binding during discovery.
* Backends
+ Add a levelzero backend for oneAPI L0 devices, exposed as OS devices
of subtype "LevelZero" and name such as "ze0".
- Add hwloc/levelzero.h for interoperability between converting
between L0 API devices and hwloc cpusets or OS devices.
+ Expose NEC Vector Engine cards on Linux as OS devices of subtype
"VectorEngine" and name "ve0", etc.
Thanks to Anara Kozhokanova, Tim Cramer and Erich Focht for the help.
+ Add a NVLinkBandwidth distances structure between NVIDIA GPUs
(and POWER processor or NVSwitches) in the NVML backend,
and a XGMIBandwidth distances structure between AMD GPUs
in the RSMI backends.
- See "Topology Attributes: Distances, Memory Attributes and CPU Kinds"
in the documentation for details about these new distances.
+ Add support for NUMA node 0 being offline in Linux, thanks to Jirka Hladky.
* Build
+ Add --with-cuda-version=<version> or look at the CUDA_VERSION
environment variable to find the appropriate CUDA pkg-config files.
Thanks to Stephen Herbein for the suggestion.
- Also add --with-cuda=<dir> to specify the CUDA installation path
manually (and its NVML and OpenCL components).
Thanks to Andrea Bocci for the suggestion.
- See "How do I enable CUDA and select which CUDA version to use?"
in the FAQ for details.
* Tools
+ lstopo now has a --windows-processor-groups option on Windows.
+ hwloc-ps now has a --short-name option to avoid long/truncated
command path.
+ hwloc-ps now has a --single-ancestor option to return a single
(possibly too large) object where a process is bound.
+ hwloc-ps --pid-cmd may now query environment variables,
including MPI-specific variables to find out process ranks.
Version 2.4.1
-------------
* Fix AMD OpenCL device locality when PCI bus or device number >= 128.
Thanks to Edgar Leon for reporting the issue.
+ Applications using any of the following inline functions must
be recompiled to get the fix: hwloc_opencl_get_device_pci_busid()
hwloc_opencl_get_device_cpuset(), hwloc_opencl_get_device_osdev().
* Fix the ranking of cpukinds on non-Windows systems,
thanks to Ivan Kochin for the report.
* Fix the insertion of custom Groups after loading the topology,
thanks to Scott Hicks.
* Add support for CPU0 being offline in Linux, thanks to Garrett Clay.
* Fix missing x86 Package and Core objects FreeBSD/NetBSD.
Thanks to Thibault Payet and Yuri Victorovich for the report.
* Fix the import of very large distances with heterogeneous object types.
* Fix a memory leak in the Linux backend,
thanks to Perceval Anichini.
Version 2.4.0 Version 2.4.0
------------- -------------
* API * API

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=4 minor=7
release=0 release=1
# 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="Nov 26, 2020" date="Mar 20, 2022"
# 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,7 +41,7 @@ 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=19:0:4 libhwloc_so_version=20:3:5
libnetloc_so_version=0:0:0 libnetloc_so_version=0:0:0
# Please also update the <TargetName> lines in contrib/windows/libhwloc.vcxproj # Please also update the <TargetName> lines in contrib/windows/libhwloc.vcxproj

View File

@@ -29,7 +29,7 @@
* THAT IS IN THE PDF/HTML THAT IS ***NOT*** IN hwloc.h! * THAT IS IN THE PDF/HTML THAT IS ***NOT*** IN hwloc.h!
* *
* There are entire paragraph-length descriptions, discussions, and * There are entire paragraph-length descriptions, discussions, and
* pretty prictures to explain subtle corner cases, provide concrete * pretty pictures to explain subtle corner cases, provide concrete
* examples, etc. * examples, etc.
* *
* Please, go read the documentation. :-) * Please, go read the documentation. :-)
@@ -93,7 +93,7 @@ extern "C" {
* Two stable releases of the same series usually have the same ::HWLOC_API_VERSION * Two stable releases of the same series usually have the same ::HWLOC_API_VERSION
* even if their HWLOC_VERSION are different. * even if their HWLOC_VERSION are different.
*/ */
#define HWLOC_API_VERSION 0x00020400 #define HWLOC_API_VERSION 0x00020500
/** \brief Indicate at runtime which hwloc API version was used at build time. /** \brief Indicate at runtime which hwloc API version was used at build time.
* *
@@ -346,7 +346,8 @@ typedef enum hwloc_obj_osdev_type_e {
* For instance the "eth0" interface on Linux. */ * For instance the "eth0" interface on Linux. */
HWLOC_OBJ_OSDEV_OPENFABRICS, /**< \brief Operating system openfabrics device. HWLOC_OBJ_OSDEV_OPENFABRICS, /**< \brief Operating system openfabrics device.
* For instance the "mlx4_0" InfiniBand HCA, * For instance the "mlx4_0" InfiniBand HCA,
* or "hfi1_0" Omni-Path interface on Linux. */ * "hfi1_0" Omni-Path interface,
* or "bxi0" Atos/Bull BXI HCA on Linux. */
HWLOC_OBJ_OSDEV_DMA, /**< \brief Operating system dma engine device. HWLOC_OBJ_OSDEV_DMA, /**< \brief Operating system dma engine device.
* For instance the "dma0chan0" DMA channel on Linux. */ * For instance the "dma0chan0" DMA channel on Linux. */
HWLOC_OBJ_OSDEV_COPROC /**< \brief Operating system co-processor device. HWLOC_OBJ_OSDEV_COPROC /**< \brief Operating system co-processor device.
@@ -516,7 +517,7 @@ struct hwloc_obj {
* objects). * objects).
* *
* If the ::HWLOC_TOPOLOGY_FLAG_INCLUDE_DISALLOWED configuration flag is set, * If the ::HWLOC_TOPOLOGY_FLAG_INCLUDE_DISALLOWED configuration flag is set,
* some of these CPUs may not be allowed for binding, * some of these CPUs may be online but not allowed for binding,
* see hwloc_topology_get_allowed_cpuset(). * see hwloc_topology_get_allowed_cpuset().
* *
* \note All objects have non-NULL CPU and node sets except Misc and I/O objects. * \note All objects have non-NULL CPU and node sets except Misc and I/O objects.
@@ -548,7 +549,7 @@ struct hwloc_obj {
* nodes more precisely. * nodes more precisely.
* *
* If the ::HWLOC_TOPOLOGY_FLAG_INCLUDE_DISALLOWED configuration flag is set, * If the ::HWLOC_TOPOLOGY_FLAG_INCLUDE_DISALLOWED configuration flag is set,
* some of these nodes may not be allowed for allocation, * some of these nodes may be online but not allowed for allocation,
* see hwloc_topology_get_allowed_nodeset(). * see hwloc_topology_get_allowed_nodeset().
* *
* If there are no NUMA nodes in the machine, all the memory is close to this * If there are no NUMA nodes in the machine, all the memory is close to this
@@ -641,7 +642,7 @@ union hwloc_obj_attr_u {
unsigned char revision; unsigned char revision;
float linkspeed; /* in GB/s */ float linkspeed; /* in GB/s */
} pcidev; } pcidev;
/** \brief Bridge specific Object Attribues */ /** \brief Bridge specific Object Attributes */
struct hwloc_bridge_attr_s { struct hwloc_bridge_attr_s {
union { union {
struct hwloc_pcidev_attr_s pci; struct hwloc_pcidev_attr_s pci;
@@ -1088,7 +1089,7 @@ HWLOC_DECLSPEC int hwloc_obj_add_info(hwloc_obj_t obj, const char *name, const c
* *
* Some operating systems only support binding threads or processes to a single PU. * Some operating systems only support binding threads or processes to a single PU.
* Others allow binding to larger sets such as entire Cores or Packages or * Others allow binding to larger sets such as entire Cores or Packages or
* even random sets of invididual PUs. In such operating system, the scheduler * even random sets of individual PUs. In such operating system, the scheduler
* is free to run the task on one of these PU, then migrate it to another PU, etc. * is free to run the task on one of these PU, then migrate it to another PU, etc.
* It is often useful to call hwloc_bitmap_singlify() on the target CPU set before * It is often useful to call hwloc_bitmap_singlify() on the target CPU set before
* passing it to the binding function to avoid these expensive migrations. * passing it to the binding function to avoid these expensive migrations.
@@ -1166,7 +1167,7 @@ typedef enum {
* CPUs are idle, operating systems may execute the thread/process * CPUs are idle, operating systems may execute the thread/process
* on those other CPUs instead of the designated CPUs, to let them * on those other CPUs instead of the designated CPUs, to let them
* progress anyway. Strict binding means that the thread/process * progress anyway. Strict binding means that the thread/process
* will _never_ execute on other cpus than the designated CPUs, even * will _never_ execute on other CPUs than the designated CPUs, even
* when those are busy with other tasks and other CPUs are idle. * when those are busy with other tasks and other CPUs are idle.
* *
* \note Depending on the operating system, strict binding may not * \note Depending on the operating system, strict binding may not
@@ -1203,7 +1204,7 @@ typedef enum {
HWLOC_CPUBIND_NOMEMBIND = (1<<3) HWLOC_CPUBIND_NOMEMBIND = (1<<3)
} hwloc_cpubind_flags_t; } hwloc_cpubind_flags_t;
/** \brief Bind current process or thread on cpus given in physical bitmap \p set. /** \brief Bind current process or thread on CPUs given in physical bitmap \p set.
* *
* \return -1 with errno set to ENOSYS if the action is not supported * \return -1 with errno set to ENOSYS if the action is not supported
* \return -1 with errno set to EXDEV if the binding cannot be enforced * \return -1 with errno set to EXDEV if the binding cannot be enforced
@@ -1212,12 +1213,13 @@ HWLOC_DECLSPEC int hwloc_set_cpubind(hwloc_topology_t topology, hwloc_const_cpus
/** \brief Get current process or thread binding. /** \brief Get current process or thread binding.
* *
* Writes into \p set the physical cpuset which the process or thread (according to \e * The CPU-set \p set (previously allocated by the caller)
* flags) was last bound to. * is filled with the list of PUs which the process or
* thread (according to \e flags) was last bound to.
*/ */
HWLOC_DECLSPEC int hwloc_get_cpubind(hwloc_topology_t topology, hwloc_cpuset_t set, int flags); HWLOC_DECLSPEC int hwloc_get_cpubind(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
/** \brief Bind a process \p pid on cpus given in physical bitmap \p set. /** \brief Bind a process \p pid on CPUs given in physical bitmap \p set.
* *
* \note \p hwloc_pid_t is \p pid_t on Unix platforms, * \note \p hwloc_pid_t is \p pid_t on Unix platforms,
* and \p HANDLE on native Windows platforms. * and \p HANDLE on native Windows platforms.
@@ -1231,6 +1233,10 @@ HWLOC_DECLSPEC int hwloc_get_cpubind(hwloc_topology_t topology, hwloc_cpuset_t s
HWLOC_DECLSPEC int hwloc_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t set, int flags); HWLOC_DECLSPEC int hwloc_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t set, int flags);
/** \brief Get the current physical binding of process \p pid. /** \brief Get the current physical binding of process \p pid.
*
* The CPU-set \p set (previously allocated by the caller)
* is filled with the list of PUs which the process
* was last bound to.
* *
* \note \p hwloc_pid_t is \p pid_t on Unix platforms, * \note \p hwloc_pid_t is \p pid_t on Unix platforms,
* and \p HANDLE on native Windows platforms. * and \p HANDLE on native Windows platforms.
@@ -1244,7 +1250,7 @@ HWLOC_DECLSPEC int hwloc_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t
HWLOC_DECLSPEC int hwloc_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags); HWLOC_DECLSPEC int hwloc_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags);
#ifdef hwloc_thread_t #ifdef hwloc_thread_t
/** \brief Bind a thread \p thread on cpus given in physical bitmap \p set. /** \brief Bind a thread \p thread on CPUs given in physical bitmap \p set.
* *
* \note \p hwloc_thread_t is \p pthread_t on Unix platforms, * \note \p hwloc_thread_t is \p pthread_t on Unix platforms,
* and \p HANDLE on native Windows platforms. * and \p HANDLE on native Windows platforms.
@@ -1256,6 +1262,10 @@ HWLOC_DECLSPEC int hwloc_set_thread_cpubind(hwloc_topology_t topology, hwloc_thr
#ifdef hwloc_thread_t #ifdef hwloc_thread_t
/** \brief Get the current physical binding of thread \p tid. /** \brief Get the current physical binding of thread \p tid.
*
* The CPU-set \p set (previously allocated by the caller)
* is filled with the list of PUs which the thread
* was last bound to.
* *
* \note \p hwloc_thread_t is \p pthread_t on Unix platforms, * \note \p hwloc_thread_t is \p pthread_t on Unix platforms,
* and \p HANDLE on native Windows platforms. * and \p HANDLE on native Windows platforms.
@@ -1266,6 +1276,10 @@ HWLOC_DECLSPEC int hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thr
#endif #endif
/** \brief Get the last physical CPU where the current process or thread ran. /** \brief Get the last physical CPU where the current process or thread ran.
*
* The CPU-set \p set (previously allocated by the caller)
* is filled with the list of PUs which the process or
* thread (according to \e flags) last ran on.
* *
* The operating system may move some tasks from one processor * The operating system may move some tasks from one processor
* to another at any time according to their binding, * to another at any time according to their binding,
@@ -1281,6 +1295,10 @@ HWLOC_DECLSPEC int hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thr
HWLOC_DECLSPEC int hwloc_get_last_cpu_location(hwloc_topology_t topology, hwloc_cpuset_t set, int flags); HWLOC_DECLSPEC int hwloc_get_last_cpu_location(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
/** \brief Get the last physical CPU where a process ran. /** \brief Get the last physical CPU where a process ran.
*
* The CPU-set \p set (previously allocated by the caller)
* is filled with the list of PUs which the process
* last ran on.
* *
* The operating system may move some tasks from one processor * The operating system may move some tasks from one processor
* to another at any time according to their binding, * to another at any time according to their binding,
@@ -1511,6 +1529,9 @@ HWLOC_DECLSPEC int hwloc_set_membind(hwloc_topology_t topology, hwloc_const_bitm
/** \brief Query the default memory binding policy and physical locality of the /** \brief Query the default memory binding policy and physical locality of the
* current process or thread. * current process or thread.
* *
* The bitmap \p set (previously allocated by the caller)
* is filled with the process or thread memory binding.
*
* This function has two output parameters: \p set and \p policy. * This function has two output parameters: \p set and \p policy.
* The values returned in these parameters depend on both the \p flags * The values returned in these parameters depend on both the \p flags
* passed in and the current memory binding policies and nodesets in * passed in and the current memory binding policies and nodesets in
@@ -1571,6 +1592,9 @@ HWLOC_DECLSPEC int hwloc_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t
/** \brief Query the default memory binding policy and physical locality of the /** \brief Query the default memory binding policy and physical locality of the
* specified process. * specified process.
* *
* The bitmap \p set (previously allocated by the caller)
* is filled with the process memory binding.
*
* This function has two output parameters: \p set and \p policy. * This function has two output parameters: \p set and \p policy.
* The values returned in these parameters depend on both the \p flags * The values returned in these parameters depend on both the \p flags
* passed in and the current memory binding policies and nodesets in * passed in and the current memory binding policies and nodesets in
@@ -1624,6 +1648,9 @@ HWLOC_DECLSPEC int hwloc_set_area_membind(hwloc_topology_t topology, const void
/** \brief Query the CPUs near the physical NUMA node(s) and binding policy of /** \brief Query the CPUs near the physical NUMA node(s) and binding policy of
* the memory identified by (\p addr, \p len ). * the memory identified by (\p addr, \p len ).
* *
* The bitmap \p set (previously allocated by the caller)
* is filled with the memory area binding.
*
* This function has two output parameters: \p set and \p policy. * This function has two output parameters: \p set and \p policy.
* The values returned in these parameters depend on both the \p flags * The values returned in these parameters depend on both the \p flags
* passed in and the memory binding policies and nodesets of the pages * passed in and the memory binding policies and nodesets of the pages
@@ -1652,7 +1679,8 @@ HWLOC_DECLSPEC int hwloc_get_area_membind(hwloc_topology_t topology, const void
/** \brief Get the NUMA nodes where memory identified by (\p addr, \p len ) is physically allocated. /** \brief Get the NUMA nodes where memory identified by (\p addr, \p len ) is physically allocated.
* *
* Fills \p set according to the NUMA nodes where the memory area pages * The bitmap \p set (previously allocated by the caller)
* is filled according to the NUMA nodes where the memory area pages
* are physically allocated. If no page is actually allocated yet, * are physically allocated. If no page is actually allocated yet,
* \p set may be empty. * \p set may be empty.
* *
@@ -1698,9 +1726,12 @@ HWLOC_DECLSPEC void *hwloc_alloc_membind(hwloc_topology_t topology, size_t len,
/** \brief Allocate some memory on NUMA memory nodes specified by \p set /** \brief Allocate some memory on NUMA memory nodes specified by \p set
* *
* This is similar to hwloc_alloc_membind_nodeset() except that it is allowed to change * First, try to allocate properly with hwloc_alloc_membind().
* the current memory binding policy, thus providing more binding support, at * On failure, the current process or thread memory binding policy
* the expense of changing the current state. * is changed with hwloc_set_membind() before allocating memory.
* Thus this function works in more cases, at the expense of changing
* the current state (possibly affecting future allocations that
* would not specify any policy).
* *
* If ::HWLOC_MEMBIND_BYNODESET is specified, set is considered a nodeset. * If ::HWLOC_MEMBIND_BYNODESET is specified, set is considered a nodeset.
* Otherwise it's a cpuset. * Otherwise it's a cpuset.
@@ -1883,8 +1914,9 @@ HWLOC_DECLSPEC int hwloc_topology_set_components(hwloc_topology_t __hwloc_restri
enum hwloc_topology_flags_e { enum hwloc_topology_flags_e {
/** \brief Detect the whole system, ignore reservations, include disallowed objects. /** \brief Detect the whole system, ignore reservations, include disallowed objects.
* *
* Gather all resources, even if some were disabled by the administrator. * Gather all online resources, even if some were disabled by the administrator.
* For instance, ignore Linux Cgroup/Cpusets and gather all processors and memory nodes. * For instance, ignore Linux Cgroup/Cpusets and gather all processors and memory nodes.
* However offline PUs and NUMA nodes are still ignored.
* *
* When this flag is not set, PUs and NUMA nodes that are disallowed are not added to the topology. * When this flag is not set, PUs and NUMA nodes that are disallowed are not added to the topology.
* Parent objects (package, core, cache, etc.) are added only if some of their children are allowed. * Parent objects (package, core, cache, etc.) are added only if some of their children are allowed.
@@ -1966,17 +1998,81 @@ enum hwloc_topology_flags_e {
* hwloc and machine support. * hwloc and machine support.
* *
*/ */
HWLOC_TOPOLOGY_FLAG_IMPORT_SUPPORT = (1UL<<3) HWLOC_TOPOLOGY_FLAG_IMPORT_SUPPORT = (1UL<<3),
/** \brief Do not consider resources outside of the process CPU binding.
*
* If the binding of the process is limited to a subset of cores,
* ignore the other cores during discovery.
*
* The resulting topology is identical to what a call to hwloc_topology_restrict()
* would generate, but this flag also prevents hwloc from ever touching other
* resources during the discovery.
*
* This flag especially tells the x86 backend to never temporarily
* rebind a thread on any excluded core. This is useful on Windows
* because such temporary rebinding can change the process binding.
* Another use-case is to avoid cores that would not be able to
* perform the hwloc discovery anytime soon because they are busy
* executing some high-priority real-time tasks.
*
* If process CPU binding is not supported,
* the thread CPU binding is considered instead if supported,
* or the flag is ignored.
*
* This flag requires ::HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM as well
* since binding support is required.
*/
HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING = (1UL<<4),
/** \brief Do not consider resources outside of the process memory binding.
*
* If the binding of the process is limited to a subset of NUMA nodes,
* ignore the other NUMA nodes during discovery.
*
* The resulting topology is identical to what a call to hwloc_topology_restrict()
* would generate, but this flag also prevents hwloc from ever touching other
* resources during the discovery.
*
* This flag is meant to be used together with
* ::HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING when both cores
* and NUMA nodes should be ignored outside of the process binding.
*
* If process memory binding is not supported,
* the thread memory binding is considered instead if supported,
* or the flag is ignored.
*
* This flag requires ::HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM as well
* since binding support is required.
*/
HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_MEMBINDING = (1UL<<5),
/** \brief Do not ever modify the process or thread binding during discovery.
*
* This flag disables all hwloc discovery steps that require a change of
* the process or thread binding. This currently only affects the x86
* backend which gets entirely disabled.
*
* This is useful when hwloc_topology_load() is called while the
* application also creates additional threads or modifies the binding.
*
* This flag is also a strict way to make sure the process binding will
* not change to due thread binding changes on Windows
* (see ::HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING).
*/
HWLOC_TOPOLOGY_FLAG_DONT_CHANGE_BINDING = (1UL<<6)
}; };
/** \brief Set OR'ed flags to non-yet-loaded topology. /** \brief Set OR'ed flags to non-yet-loaded topology.
* *
* Set a OR'ed set of ::hwloc_topology_flags_e onto a topology that was not yet loaded. * Set a OR'ed set of ::hwloc_topology_flags_e onto a topology that was not yet loaded.
* *
* If this function is called multiple times, the last invokation will erase * If this function is called multiple times, the last invocation will erase
* and replace the set of flags that was previously set. * and replace the set of flags that was previously set.
* *
* The flags set in a topology may be retrieved with hwloc_topology_get_flags() * By default, no flags are set (\c 0).
*
* The flags set in a topology may be retrieved with hwloc_topology_get_flags().
*/ */
HWLOC_DECLSPEC int hwloc_topology_set_flags (hwloc_topology_t topology, unsigned long flags); HWLOC_DECLSPEC int hwloc_topology_set_flags (hwloc_topology_t topology, unsigned long flags);
@@ -1984,6 +2080,9 @@ HWLOC_DECLSPEC int hwloc_topology_set_flags (hwloc_topology_t topology, unsigned
* *
* Get the OR'ed set of ::hwloc_topology_flags_e of a topology. * Get the OR'ed set of ::hwloc_topology_flags_e of a topology.
* *
* If hwloc_topology_set_flags() was not called earlier,
* no flags are set (\c 0 is returned).
*
* \return the flags previously set with hwloc_topology_set_flags(). * \return the flags previously set with hwloc_topology_set_flags().
*/ */
HWLOC_DECLSPEC unsigned long hwloc_topology_get_flags (hwloc_topology_t topology); HWLOC_DECLSPEC unsigned long hwloc_topology_get_flags (hwloc_topology_t topology);

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2021 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,9 +11,9 @@
#ifndef HWLOC_CONFIG_H #ifndef HWLOC_CONFIG_H
#define HWLOC_CONFIG_H #define HWLOC_CONFIG_H
#define HWLOC_VERSION "2.4.1" #define HWLOC_VERSION "2.7.1"
#define HWLOC_VERSION_MAJOR 2 #define HWLOC_VERSION_MAJOR 2
#define HWLOC_VERSION_MINOR 4 #define HWLOC_VERSION_MINOR 7
#define HWLOC_VERSION_RELEASE 1 #define HWLOC_VERSION_RELEASE 1
#define HWLOC_VERSION_GREEK "" #define HWLOC_VERSION_GREEK ""

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2020 Inria. All rights reserved. * Copyright © 2020-2021 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -42,18 +42,23 @@ extern "C" {
* (for instance the "CoreType" and "FrequencyMaxMHz", * (for instance the "CoreType" and "FrequencyMaxMHz",
* see \ref topoattrs_cpukinds). * see \ref topoattrs_cpukinds).
* *
* A higher efficiency value means intrinsic greater performance * A higher efficiency value means greater intrinsic performance
* (and possibly less performance/power efficiency). * (and possibly less performance/power efficiency).
* Kinds with lower efficiency are ranked first: * Kinds with lower efficiency values are ranked first:
* Passing 0 as \p kind_index to hwloc_cpukinds_get_info() will * Passing 0 as \p kind_index to hwloc_cpukinds_get_info() will
* return information about the less efficient CPU kind. * return information about the CPU kind with lower performance
* but higher energy-efficiency.
* Higher \p kind_index values would rather return information
* about power-hungry high-performance cores.
* *
* When available, efficiency values are gathered from the operating * When available, efficiency values are gathered from the operating system.
* system (when \p cpukind_efficiency is set in the * If so, \p cpukind_efficiency is set in the struct hwloc_topology_discovery_support array.
* struct hwloc_topology_discovery_support array, only on Windows 10 for now). * This is currently available on Windows 10, Mac OS X (Darwin),
* Otherwise hwloc tries to compute efficiencies * and on some Linux platforms where core "capacity" is exposed in sysfs.
* by comparing CPU kinds using frequencies (on ARM), *
* or core types and frequencies (on other architectures). * If the operating system does not expose core efficiencies natively,
* hwloc tries to compute efficiencies by comparing CPU kinds using
* frequencies (on ARM), or core types and frequencies (on other architectures).
* The environment variable HWLOC_CPUKINDS_RANKING may be used * The environment variable HWLOC_CPUKINDS_RANKING may be used
* to change this heuristics, see \ref envvar. * to change this heuristics, see \ref envvar.
* *

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2010-2020 Inria. All rights reserved. * Copyright © 2010-2021 Inria. All rights reserved.
* Copyright © 2010-2011 Université Bordeaux * Copyright © 2010-2011 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.
@@ -75,7 +75,7 @@ hwloc_cuda_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused
/** \brief Get the CPU set of processors that are physically /** \brief Get the CPU set of processors that are physically
* close to device \p cudevice. * close to device \p cudevice.
* *
* Return the CPU set describing the locality of the CUDA device \p cudevice. * Store in \p set the CPU-set describing the locality of the CUDA device \p cudevice.
* *
* Topology \p topology and device \p cudevice must match the local machine. * Topology \p topology and device \p cudevice must match the local machine.
* I/O devices detection and the CUDA component are not needed in the topology. * I/O devices detection and the CUDA component are not needed in the topology.
@@ -120,8 +120,8 @@ hwloc_cuda_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
/** \brief Get the hwloc PCI device object corresponding to the /** \brief Get the hwloc PCI device object corresponding to the
* CUDA device \p cudevice. * CUDA device \p cudevice.
* *
* Return the PCI device object describing the CUDA device \p cudevice. * \return The hwloc PCI device object describing the CUDA device \p cudevice.
* Return NULL if there is none. * \return \c NULL if none could be found.
* *
* Topology \p topology and device \p cudevice must match the local machine. * Topology \p topology and device \p cudevice must match the local machine.
* I/O devices detection must be enabled in topology \p topology. * I/O devices detection must be enabled in topology \p topology.
@@ -140,8 +140,8 @@ hwloc_cuda_get_device_pcidev(hwloc_topology_t topology, CUdevice cudevice)
/** \brief Get the hwloc OS device object corresponding to CUDA device \p cudevice. /** \brief Get the hwloc OS device object corresponding to CUDA device \p cudevice.
* *
* Return the hwloc OS device object that describes the given * \return The hwloc OS device object that describes the given CUDA device \p cudevice.
* CUDA device \p cudevice. Return NULL if there is none. * \return \c NULL if none could be found.
* *
* Topology \p topology and device \p cudevice must match the local machine. * Topology \p topology and device \p cudevice must match the local machine.
* I/O devices detection and the CUDA component must be enabled in the topology. * I/O devices detection and the CUDA component must be enabled in the topology.
@@ -183,8 +183,8 @@ hwloc_cuda_get_device_osdev(hwloc_topology_t topology, CUdevice cudevice)
/** \brief Get the hwloc OS device object corresponding to the /** \brief Get the hwloc OS device object corresponding to the
* CUDA device whose index is \p idx. * CUDA device whose index is \p idx.
* *
* Return the OS device object describing the CUDA device whose * \return The hwloc OS device object describing the CUDA device whose index is \p idx.
* index is \p idx. Return NULL if there is none. * \return \c NULL if none could be found.
* *
* The topology \p topology does not necessarily have to match the current * The topology \p topology does not necessarily have to match the current
* machine. For instance the topology may be an XML import of a remote host. * machine. For instance the topology may be an XML import of a remote host.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2010-2020 Inria. All rights reserved. * Copyright © 2010-2021 Inria. All rights reserved.
* Copyright © 2010-2011 Université Bordeaux * Copyright © 2010-2011 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.
@@ -72,7 +72,7 @@ hwloc_cudart_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unus
/** \brief Get the CPU set of processors that are physically /** \brief Get the CPU set of processors that are physically
* close to device \p idx. * close to device \p idx.
* *
* Return the CPU set describing the locality of the CUDA device * Store in \p set the CPU-set describing the locality of the CUDA device
* whose index is \p idx. * whose index is \p idx.
* *
* Topology \p topology and device \p idx must match the local machine. * Topology \p topology and device \p idx must match the local machine.
@@ -117,8 +117,8 @@ hwloc_cudart_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unuse
/** \brief Get the hwloc PCI device object corresponding to the /** \brief Get the hwloc PCI device object corresponding to the
* CUDA device whose index is \p idx. * CUDA device whose index is \p idx.
* *
* Return the PCI device object describing the CUDA device whose * \return The hwloc PCI device object describing the CUDA device whose index is \p idx.
* index is \p idx. Return NULL if there is none. * \return \c NULL if none could be found.
* *
* Topology \p topology and device \p idx must match the local machine. * Topology \p topology and device \p idx must match the local machine.
* I/O devices detection must be enabled in topology \p topology. * I/O devices detection must be enabled in topology \p topology.
@@ -138,8 +138,8 @@ hwloc_cudart_get_device_pcidev(hwloc_topology_t topology, int idx)
/** \brief Get the hwloc OS device object corresponding to the /** \brief Get the hwloc OS device object corresponding to the
* CUDA device whose index is \p idx. * CUDA device whose index is \p idx.
* *
* Return the OS device object describing the CUDA device whose * \return The hwloc OS device object describing the CUDA device whose index is \p idx.
* index is \p idx. Return NULL if there is none. * \return \c NULL if none could be found.
* *
* The topology \p topology does not necessarily have to match the current * The topology \p topology does not necessarily have to match the current
* machine. For instance the topology may be an XML import of a remote host. * machine. For instance the topology may be an XML import of a remote host.

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2018 Inria. All rights reserved. * Copyright © 2009-2021 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.
@@ -30,6 +30,15 @@ extern "C" {
/* backward compat with v1.10 before Node->NUMANode clarification */ /* backward compat with v1.10 before Node->NUMANode clarification */
#define HWLOC_OBJ_NODE HWLOC_OBJ_NUMANODE #define HWLOC_OBJ_NODE HWLOC_OBJ_NUMANODE
/** \brief Add a distances structure.
*
* Superseded by hwloc_distances_add_create()+hwloc_distances_add_values()+hwloc_distances_add_commit()
* in v2.5.
*/
HWLOC_DECLSPEC int hwloc_distances_add(hwloc_topology_t topology,
unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values,
unsigned long kind, unsigned long flags) __hwloc_attribute_deprecated;
/** \brief Insert a misc object by parent. /** \brief Insert a misc object by parent.
* *
* Identical to hwloc_topology_insert_misc_object(). * Identical to hwloc_topology_insert_misc_object().

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2010-2020 Inria. All rights reserved. * Copyright © 2010-2021 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -35,9 +35,20 @@ extern "C" {
* 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_FROM_OS | ::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"
* 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.
*
* Pointers \p objs and \p values should not be replaced, reallocated, freed, etc.
* However callers are allowed to modify \p kind as well as the contents
* of \p objs and \p values arrays.
* For instance, if there is a single NUMA node per Package,
* hwloc_get_obj_with_same_locality() may be used to convert between them
* and replace NUMA nodes in the \p objs array with the corresponding Packages.
* See also hwloc_distances_transform() for applying some transformations
* to the structure.
*/ */
struct hwloc_distances_s { struct hwloc_distances_s {
unsigned nbobjs; /**< \brief Number of objects described by the distance matrix. */ unsigned nbobjs; /**< \brief Number of objects described by the distance matrix. */
@@ -91,6 +102,8 @@ enum hwloc_distances_kind_e {
HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH = (1UL<<3), HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH = (1UL<<3),
/** \brief This distances structure covers objects of different types. /** \brief This distances structure covers objects of different types.
* This may apply to the "NVLinkBandwidth" structure in presence
* of a NVSwitch or POWER processor NVLink port.
* \hideinitializer * \hideinitializer
*/ */
HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES = (1UL<<4) HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES = (1UL<<4)
@@ -147,6 +160,7 @@ hwloc_distances_get_by_type(hwloc_topology_t topology, hwloc_obj_type_t type,
* Usually only one distances structure may match a given name. * Usually only one distances structure may match a given name.
* *
* The name of the most common structure is "NUMALatency". * The name of the most common structure is "NUMALatency".
* Others include "XGMIBandwidth", "XGMIHops" and "NVLinkBandwidth".
*/ */
HWLOC_DECLSPEC int HWLOC_DECLSPEC int
hwloc_distances_get_by_name(hwloc_topology_t topology, const char *name, hwloc_distances_get_by_name(hwloc_topology_t topology, const char *name,
@@ -168,6 +182,85 @@ hwloc_distances_get_name(hwloc_topology_t topology, struct hwloc_distances_s *di
HWLOC_DECLSPEC void HWLOC_DECLSPEC void
hwloc_distances_release(hwloc_topology_t topology, struct hwloc_distances_s *distances); hwloc_distances_release(hwloc_topology_t topology, struct hwloc_distances_s *distances);
/** \brief Transformations of distances structures. */
enum hwloc_distances_transform_e {
/** \brief Remove \c NULL objects from the distances structure.
*
* Every object that was replaced with \c NULL in the \p objs array
* is removed and the \p values array is updated accordingly.
*
* At least \c 2 objects must remain, otherwise hwloc_distances_transform()
* will return \c -1 with \p errno set to \c EINVAL.
*
* \p kind will be updated with or without ::HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES
* according to the remaining objects.
*
* \hideinitializer
*/
HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL = 0,
/** \brief Replace bandwidth values with a number of links.
*
* Usually all values will be either \c 0 (no link) or \c 1 (one link).
* However some matrices could get larger values if some pairs of
* peers are connected by different numbers of links.
*
* Values on the diagonal are set to \c 0.
*
* This transformation only applies to bandwidth matrices.
*
* \hideinitializer
*/
HWLOC_DISTANCES_TRANSFORM_LINKS = 1,
/** \brief Merge switches with multiple ports into a single object.
* This currently only applies to NVSwitches where GPUs seem connected to different
* separate switch ports in the NVLinkBandwidth matrix. This transformation will
* replace all of them with the same port connected to all GPUs.
* Other ports are removed by applying ::HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL internally.
* \hideinitializer
*/
HWLOC_DISTANCES_TRANSFORM_MERGE_SWITCH_PORTS = 2,
/** \brief Apply a transitive closure to the matrix to connect objects across switches.
* This currently only applies to GPUs and NVSwitches in the NVLinkBandwidth matrix.
* All pairs of GPUs will be reported as directly connected.
* \hideinitializer
*/
HWLOC_DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE = 3
};
/** \brief Apply a transformation to a distances structure.
*
* Modify a distances structure that was previously obtained with
* hwloc_distances_get() or one of its variants.
*
* This modifies the local copy of the distances structures but does
* not modify the distances information stored inside the topology
* (retrieved by another call to hwloc_distances_get() or exported to XML).
* To do so, one should add a new distances structure with same
* name, kind, objects and values (see \ref hwlocality_distances_add)
* and then remove this old one with hwloc_distances_release_remove().
*
* \p transform must be one of the transformations listed
* in ::hwloc_distances_transform_e.
*
* These transformations may modify the contents of the \p objs or \p values arrays.
*
* \p transform_attr must be \c NULL for now.
*
* \p flags must be \c 0 for now.
*
* \note Objects in distances array \p objs may be directly modified
* in place without using hwloc_distances_transform().
* One may use hwloc_get_obj_with_same_locality() to easily convert
* between similar objects of different types.
*/
HWLOC_DECLSPEC int hwloc_distances_transform(hwloc_topology_t topology, struct hwloc_distances_s *distances,
enum hwloc_distances_transform_e transform,
void *transform_attr,
unsigned long flags);
/** @} */ /** @} */
@@ -215,13 +308,84 @@ hwloc_distances_obj_pair_values(struct hwloc_distances_s *distances,
/** \defgroup hwlocality_distances_add Add or remove distances between objects /** \defgroup hwlocality_distances_add Add distances between objects
*
* The usual way to add distances is:
* \code
* hwloc_distances_add_handle_t handle;
* int err = -1;
* handle = hwloc_distances_add_create(topology, "name", kind, 0);
* if (handle) {
* err = hwloc_distances_add_values(topology, handle, nbobjs, objs, values, 0);
* if (!err)
* err = hwloc_distances_add_commit(topology, handle, flags);
* }
* \endcode
* If \p err is \c 0 at the end, then addition was successful.
*
* @{ * @{
*/ */
/** \brief Handle to a new distances structure during its addition to the topology. */
typedef void * hwloc_distances_add_handle_t;
/** \brief Create a new empty distances structure.
*
* Create an empty distances structure
* to be filled with hwloc_distances_add_values()
* and then committed with hwloc_distances_add_commit().
*
* Parameter \p name is optional, it may be \c NULL.
* Otherwise, it will be copied internally and may later be freed by the caller.
*
* \p kind specifies the kind of distance as a OR'ed set of ::hwloc_distances_kind_e.
* Kind ::HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES will be automatically set
* according to objects having different types in hwloc_distances_add_values().
*
* \p flags must be \c 0 for now.
*
* \return A hwloc_distances_add_handle_t that should then be passed
* to hwloc_distances_add_values() and hwloc_distances_add_commit().
*
* \return \c NULL on error.
*/
HWLOC_DECLSPEC hwloc_distances_add_handle_t
hwloc_distances_add_create(hwloc_topology_t topology,
const char *name, unsigned long kind,
unsigned long flags);
/** \brief Specify the objects and values in a new empty distances structure.
*
* Specify the objects and values for a new distances structure
* that was returned as a handle by hwloc_distances_add_create().
* The structure must then be committed with hwloc_distances_add_commit().
*
* The number of objects is \p nbobjs and the array of objects is \p objs.
* Distance values are stored as a one-dimension array in \p values.
* The distance from object i to object j is in slot i*nbobjs+j.
*
* \p nbobjs must be at least 2.
*
* Arrays \p objs and \p values will be copied internally,
* they may later be freed by the caller.
*
* On error, the temporary distances structure and its content are destroyed.
*
* \p flags must be \c 0 for now.
*
* \return \c 0 on success.
* \return \c -1 on error.
*/
HWLOC_DECLSPEC int hwloc_distances_add_values(hwloc_topology_t topology,
hwloc_distances_add_handle_t handle,
unsigned nbobjs, hwloc_obj_t *objs,
hwloc_uint64_t *values,
unsigned long flags);
/** \brief Flags for adding a new distances to a topology. */ /** \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.
* \hideinitializer * \hideinitializer
*/ */
HWLOC_DISTANCES_ADD_FLAG_GROUP = (1UL<<0), HWLOC_DISTANCES_ADD_FLAG_GROUP = (1UL<<0),
@@ -233,23 +397,33 @@ enum hwloc_distances_add_flag_e {
HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE = (1UL<<1) HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE = (1UL<<1)
}; };
/** \brief Provide a new distance matrix. /** \brief Commit a new distances structure.
* *
* Provide the matrix of distances between a set of objects given by \p nbobjs * This function finalizes the distances structure and inserts in it the topology.
* and the \p objs array. \p nbobjs must be at least 2.
* The distances are stored as a one-dimension array in \p values.
* The distance from object i to object j is in slot i*nbobjs+j.
* *
* \p kind specifies the kind of distance as a OR'ed set of ::hwloc_distances_kind_e. * Parameter \p handle was previously returned by hwloc_distances_add_create().
* Kind ::HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES will be automatically added * Then objects and values were specified with hwloc_distances_add_values().
* if objects of different types are given.
* *
* \p flags configures the behavior of the function using an optional OR'ed set of * \p flags configures the behavior of the function using an optional OR'ed set of
* ::hwloc_distances_add_flag_e. * ::hwloc_distances_add_flag_e.
* It may be used to request the grouping of existing objects based on distances.
*
* On error, the temporary distances structure and its content are destroyed.
*
* \return \c 0 on success.
* \return \c -1 on error.
*/
HWLOC_DECLSPEC int hwloc_distances_add_commit(hwloc_topology_t topology,
hwloc_distances_add_handle_t handle,
unsigned long flags);
/** @} */
/** \defgroup hwlocality_distances_remove Remove distances between objects
* @{
*/ */
HWLOC_DECLSPEC int hwloc_distances_add(hwloc_topology_t topology,
unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values,
unsigned long kind, unsigned long flags);
/** \brief Remove all distance matrices from a topology. /** \brief Remove all distance matrices from a topology.
* *

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2012 Blue Brain Project, EPFL. All rights reserved. * Copyright © 2012 Blue Brain Project, EPFL. All rights reserved.
* Copyright © 2012-2013 Inria. All rights reserved. * Copyright © 2012-2021 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -39,9 +39,9 @@ extern "C" {
/** \brief Get the hwloc OS device object corresponding to the /** \brief Get the hwloc OS device object corresponding to the
* OpenGL display given by port and device index. * OpenGL display given by port and device index.
* *
* Return the OS device object describing the OpenGL display * \return The hwloc OS device object describing the OpenGL display
* whose port (server) is \p port and device (screen) is \p device. * whose port (server) is \p port and device (screen) is \p device.
* Return NULL if there is none. * \return \c NULL if none could be found.
* *
* The topology \p topology does not necessarily have to match the current * The topology \p topology does not necessarily have to match the current
* machine. For instance the topology may be an XML import of a remote host. * machine. For instance the topology may be an XML import of a remote host.
@@ -70,9 +70,9 @@ hwloc_gl_get_display_osdev_by_port_device(hwloc_topology_t topology,
/** \brief Get the hwloc OS device object corresponding to the /** \brief Get the hwloc OS device object corresponding to the
* OpenGL display given by name. * OpenGL display given by name.
* *
* Return the OS device object describing the OpenGL display * \return The hwloc OS device object describing the OpenGL display
* whose name is \p name, built as ":port.device" such as ":0.0" . * whose name is \p name, built as ":port.device" such as ":0.0" .
* Return NULL if there is none. * \return \c NULL if none could be found.
* *
* The topology \p topology does not necessarily have to match the current * The topology \p topology does not necessarily have to match the current
* machine. For instance the topology may be an XML import of a remote host. * machine. For instance the topology may be an XML import of a remote host.
@@ -99,9 +99,10 @@ hwloc_gl_get_display_osdev_by_name(hwloc_topology_t topology,
/** \brief Get the OpenGL display port and device corresponding /** \brief Get the OpenGL display port and device corresponding
* to the given hwloc OS object. * to the given hwloc OS object.
* *
* Return the OpenGL display port (server) in \p port and device (screen) * Retrieves the OpenGL display port (server) in \p port and device (screen)
* in \p screen that correspond to the given hwloc OS device object. * in \p screen that correspond to the given hwloc OS device object.
* Return \c -1 if there is none. *
* \return \c -1 if none could be found.
* *
* The topology \p topology does not necessarily have to match the current * The topology \p topology does not necessarily have to match the current
* machine. For instance the topology may be an XML import of a remote host. * machine. For instance the topology may be an XML import of a remote host.

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2021 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.
@@ -807,6 +807,49 @@ hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_
return obj; return obj;
} }
/** \brief Return an object of a different type with same locality.
*
* If the source object \p src is a normal or memory type,
* this function returns an object of type \p type with same
* CPU and node sets, either below or above in the hierarchy.
*
* If the source object \p src is a PCI or an OS device within a PCI
* device, the function may either return that PCI device, or another
* OS device in the same PCI parent.
* This may for instance be useful for converting between OS devices
* such as "nvml0" or "rsmi1" used in distance structures into the
* the PCI device, or the CUDA or OpenCL OS device that correspond
* to the same physical card.
*
* If not \c NULL, parameter \p subtype only select objects whose
* subtype attribute exists and is \p subtype (case-insensitively),
* for instance "OpenCL" or "CUDA".
*
* If not \c NULL, parameter \p nameprefix only selects objects whose
* name attribute exists and starts with \p nameprefix (case-insensitively),
* for instance "rsmi" for matching "rsmi0".
*
* If multiple objects match, the first one is returned.
*
* This function will not walk the hierarchy across bridges since
* the PCI locality may become different.
* This function cannot also convert between normal/memory objects
* and I/O or Misc objects.
*
* \p flags must be \c 0 for now.
*
* \return An object with identical locality,
* matching \p subtype and \p nameprefix if any.
*
* \return \c NULL if no matching object could be found,
* or if the source object and target type are incompatible,
* for instance if converting between CPU and I/O objects.
*/
HWLOC_DECLSPEC hwloc_obj_t
hwloc_get_obj_with_same_locality(hwloc_topology_t topology, hwloc_obj_t src,
hwloc_obj_type_t type, const char *subtype, const char *nameprefix,
unsigned long flags);
/** @} */ /** @} */

View File

@@ -0,0 +1,157 @@
/*
* Copyright © 2021 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
/** \file
* \brief Macros to help interaction between hwloc and the oneAPI Level Zero interface.
*
* Applications that use both hwloc and Level Zero may want to
* include this file so as to get topology information for L0 devices.
*/
#ifndef HWLOC_LEVELZERO_H
#define HWLOC_LEVELZERO_H
#include "hwloc.h"
#include "hwloc/autogen/config.h"
#include "hwloc/helper.h"
#ifdef HWLOC_LINUX_SYS
#include "hwloc/linux.h"
#endif
#include <level_zero/ze_api.h>
#include <level_zero/zes_api.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup hwlocality_levelzero Interoperability with the oneAPI Level Zero interface.
*
* This interface offers ways to retrieve topology information about
* devices managed by the Level Zero API.
*
* @{
*/
/** \brief Get the CPU set of logical processors that are physically
* close to the Level Zero device \p device
*
* Store in \p set the CPU-set describing the locality of
* the Level Zero device \p device.
*
* Topology \p topology and device \p device must match the local machine.
* The Level Zero must have been initialized with Sysman enabled
* (ZES_ENABLE_SYSMAN=1 in the environment).
* I/O devices detection and the Level Zero component are not needed in the
* topology.
*
* The function only returns the locality of the device.
* If more information about the device is needed, OS objects should
* be used instead, see hwloc_levelzero_get_device_osdev().
*
* This function is currently only implemented in a meaningful way for
* Linux; other systems will simply get a full cpuset.
*/
static __hwloc_inline int
hwloc_levelzero_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
ze_device_handle_t device, hwloc_cpuset_t set)
{
#ifdef HWLOC_LINUX_SYS
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
#define HWLOC_LEVELZERO_DEVICE_SYSFS_PATH_MAX 128
char path[HWLOC_LEVELZERO_DEVICE_SYSFS_PATH_MAX];
zes_pci_properties_t pci;
zes_device_handle_t sdevice = device;
ze_result_t res;
if (!hwloc_topology_is_thissystem(topology)) {
errno = EINVAL;
return -1;
}
res = zesDevicePciGetProperties(sdevice, &pci);
if (res != ZE_RESULT_SUCCESS) {
errno = EINVAL;
return -1;
}
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/local_cpus",
pci.address.domain, pci.address.bus, pci.address.device, pci.address.function);
if (hwloc_linux_read_path_as_cpumask(path, set) < 0
|| hwloc_bitmap_iszero(set))
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
#else
/* Non-Linux systems simply get a full cpuset */
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
#endif
return 0;
}
/** \brief Get the hwloc OS device object corresponding to Level Zero device
* \p device.
*
* \return The hwloc OS device object that describes the given Level Zero device \p device.
* \return \c NULL if none could be found.
*
* Topology \p topology and device \p dv_ind must match the local machine.
* I/O devices detection and the Level Zero component must be enabled in the
* topology. If not, the locality of the object may still be found using
* hwloc_levelzero_get_device_cpuset().
*
* \note The corresponding hwloc PCI device may be found by looking
* at the result parent pointer (unless PCI devices are filtered out).
*/
static __hwloc_inline hwloc_obj_t
hwloc_levelzero_get_device_osdev(hwloc_topology_t topology, ze_device_handle_t device)
{
zes_device_handle_t sdevice = device;
zes_pci_properties_t pci;
ze_result_t res;
hwloc_obj_t osdev;
if (!hwloc_topology_is_thissystem(topology)) {
errno = EINVAL;
return NULL;
}
res = zesDevicePciGetProperties(sdevice, &pci);
if (res != ZE_RESULT_SUCCESS) {
/* L0 was likely initialized without sysman, don't bother */
errno = EINVAL;
return NULL;
}
osdev = NULL;
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
hwloc_obj_t pcidev = osdev->parent;
if (strncmp(osdev->name, "ze", 2))
continue;
if (pcidev
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
&& pcidev->attr->pcidev.domain == pci.address.domain
&& pcidev->attr->pcidev.bus == pci.address.bus
&& pcidev->attr->pcidev.dev == pci.address.device
&& pcidev->attr->pcidev.func == pci.address.function)
return osdev;
/* FIXME: when we'll have serialnumber, try it in case PCI is filtered-out */
}
return NULL;
}
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HWLOC_LEVELZERO_H */

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2016 Inria. All rights reserved. * Copyright © 2009-2021 Inria. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux * Copyright © 2009-2011 Université Bordeaux
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -44,6 +44,10 @@ extern "C" {
HWLOC_DECLSPEC int hwloc_linux_set_tid_cpubind(hwloc_topology_t topology, pid_t tid, hwloc_const_cpuset_t set); HWLOC_DECLSPEC int hwloc_linux_set_tid_cpubind(hwloc_topology_t topology, pid_t tid, hwloc_const_cpuset_t set);
/** \brief Get the current binding of thread \p tid /** \brief Get the current binding of thread \p tid
*
* The CPU-set \p set (previously allocated by the caller)
* is filled with the list of PUs which the thread
* was last bound to.
* *
* The behavior is exactly the same as the Linux sched_getaffinity system call, * The behavior is exactly the same as the Linux sched_getaffinity system call,
* but uses a hwloc cpuset. * but uses a hwloc cpuset.
@@ -54,6 +58,9 @@ HWLOC_DECLSPEC int hwloc_linux_set_tid_cpubind(hwloc_topology_t topology, pid_t
HWLOC_DECLSPEC int hwloc_linux_get_tid_cpubind(hwloc_topology_t topology, pid_t tid, hwloc_cpuset_t set); HWLOC_DECLSPEC int hwloc_linux_get_tid_cpubind(hwloc_topology_t topology, pid_t tid, hwloc_cpuset_t set);
/** \brief Get the last physical CPU where thread \p tid ran. /** \brief Get the last physical CPU where thread \p tid ran.
*
* The CPU-set \p set (previously allocated by the caller)
* is filled with the PU which the thread last ran on.
* *
* \note This is equivalent to calling hwloc_get_proc_last_cpu_location() with * \note This is equivalent to calling hwloc_get_proc_last_cpu_location() with
* ::HWLOC_CPUBIND_THREAD as flags. * ::HWLOC_CPUBIND_THREAD as flags.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2019-2020 Inria. All rights reserved. * Copyright © 2019-2022 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -354,7 +354,7 @@ hwloc_memattr_register(hwloc_topology_t topology,
* \p flags must be \c 0 for now. * \p flags must be \c 0 for now.
* *
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET * \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
* when refering to accesses performed by CPU cores. * when referring to accesses performed by CPU cores.
* ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc, * ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
* but users may for instance use it to provide custom information about * but users may for instance use it to provide custom information about
* host memory accesses performed by GPUs. * host memory accesses performed by GPUs.
@@ -398,7 +398,7 @@ hwloc_memattr_set_value(hwloc_topology_t topology,
* values. * values.
* *
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET * \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
* when refering to accesses performed by CPU cores. * when referring to accesses performed by CPU cores.
* ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc, * ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
* but users may for instance use it to provide custom information about * but users may for instance use it to provide custom information about
* host memory accesses performed by GPUs. * host memory accesses performed by GPUs.
@@ -408,7 +408,7 @@ hwloc_memattr_get_targets(hwloc_topology_t topology,
hwloc_memattr_id_t attribute, hwloc_memattr_id_t attribute,
struct hwloc_location *initiator, struct hwloc_location *initiator,
unsigned long flags, unsigned long flags,
unsigned *nrp, hwloc_obj_t *targets, hwloc_uint64_t *values); unsigned *nr, hwloc_obj_t *targets, hwloc_uint64_t *values);
/** \brief Return the initiators that have values for a given attribute for a specific target NUMA node. /** \brief Return the initiators that have values for a given attribute for a specific target NUMA node.
* *

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2012-2020 Inria. All rights reserved. * Copyright © 2012-2021 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -39,7 +39,7 @@ extern "C" {
/** \brief Get the CPU set of processors that are physically /** \brief Get the CPU set of processors that are physically
* close to NVML device \p device. * close to NVML device \p device.
* *
* Return the CPU set describing the locality of the NVML device \p device. * Store in \p set the CPU-set describing the locality of the NVML device \p device.
* *
* Topology \p topology and device \p device must match the local machine. * Topology \p topology and device \p device must match the local machine.
* I/O devices detection and the NVML component are not needed in the topology. * I/O devices detection and the NVML component are not needed in the topology.
@@ -88,8 +88,8 @@ hwloc_nvml_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
/** \brief Get the hwloc OS device object corresponding to the /** \brief Get the hwloc OS device object corresponding to the
* NVML device whose index is \p idx. * NVML device whose index is \p idx.
* *
* Return the OS device object describing the NVML device whose * \return The hwloc OS device object describing the NVML device whose index is \p idx.
* index is \p idx. Returns NULL if there is none. * \return \c NULL if none could be found.
* *
* The topology \p topology does not necessarily have to match the current * The topology \p topology does not necessarily have to match the current
* machine. For instance the topology may be an XML import of a remote host. * machine. For instance the topology may be an XML import of a remote host.
@@ -114,8 +114,8 @@ hwloc_nvml_get_device_osdev_by_index(hwloc_topology_t topology, unsigned idx)
/** \brief Get the hwloc OS device object corresponding to NVML device \p device. /** \brief Get the hwloc OS device object corresponding to NVML device \p device.
* *
* Return the hwloc OS device object that describes the given * \return The hwloc OS device object that describes the given NVML device \p device.
* NVML device \p device. Return NULL if there is none. * \return \c NULL if none could be found.
* *
* Topology \p topology and device \p device must match the local machine. * Topology \p topology and device \p device must match the local machine.
* I/O devices detection and the NVML component must be enabled in the topology. * I/O devices detection and the NVML component must be enabled in the topology.

View File

@@ -113,7 +113,7 @@ hwloc_opencl_get_device_pci_busid(cl_device_id device,
/** \brief Get the CPU set of processors that are physically /** \brief Get the CPU set of processors that are physically
* close to OpenCL device \p device. * close to OpenCL device \p device.
* *
* Return the CPU set describing the locality of the OpenCL device \p device. * Store in \p set the CPU-set describing the locality of the OpenCL device \p device.
* *
* Topology \p topology and device \p device must match the local machine. * Topology \p topology and device \p device must match the local machine.
* I/O devices detection and the OpenCL component are not needed in the topology. * I/O devices detection and the OpenCL component are not needed in the topology.
@@ -162,10 +162,10 @@ hwloc_opencl_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unuse
/** \brief Get the hwloc OS device object corresponding to the /** \brief Get the hwloc OS device object corresponding to the
* OpenCL device for the given indexes. * OpenCL device for the given indexes.
* *
* Return the OS device object describing the OpenCL device * \return The hwloc OS device object describing the OpenCL device
* whose platform index is \p platform_index, * whose platform index is \p platform_index,
* and whose device index within this platform if \p device_index. * and whose device index within this platform if \p device_index.
* Return NULL if there is none. * \return \c NULL if there is none.
* *
* The topology \p topology does not necessarily have to match the current * The topology \p topology does not necessarily have to match the current
* machine. For instance the topology may be an XML import of a remote host. * machine. For instance the topology may be an XML import of a remote host.
@@ -192,8 +192,9 @@ hwloc_opencl_get_device_osdev_by_index(hwloc_topology_t topology,
/** \brief Get the hwloc OS device object corresponding to OpenCL device \p deviceX. /** \brief Get the hwloc OS device object corresponding to OpenCL device \p deviceX.
* *
* Use OpenCL device attributes to find the corresponding hwloc OS device object. * \return The hwloc OS device object corresponding to the given OpenCL device \p device.
* Return NULL if there is none or if useful attributes are not available. * \return \c NULL if none could be found, for instance
* if required OpenCL attributes are not available.
* *
* This function currently only works on AMD and NVIDIA OpenCL devices that support * This function currently only works on AMD and NVIDIA OpenCL devices that support
* relevant OpenCL extensions. hwloc_opencl_get_device_osdev_by_index() * relevant OpenCL extensions. hwloc_opencl_get_device_osdev_by_index()

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2021 Inria. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux * Copyright © 2009-2010 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.
@@ -44,7 +44,7 @@ extern "C" {
/** \brief Get the CPU set of processors that are physically /** \brief Get the CPU set of processors that are physically
* close to device \p ibdev. * close to device \p ibdev.
* *
* Return the CPU set describing the locality of the OpenFabrics * Store in \p set the CPU-set describing the locality of the OpenFabrics
* device \p ibdev (InfiniBand, etc). * device \p ibdev (InfiniBand, etc).
* *
* Topology \p topology and device \p ibdev must match the local machine. * Topology \p topology and device \p ibdev must match the local machine.
@@ -88,10 +88,11 @@ hwloc_ibv_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
/** \brief Get the hwloc OS device object corresponding to the OpenFabrics /** \brief Get the hwloc OS device object corresponding to the OpenFabrics
* device named \p ibname. * device named \p ibname.
* *
* Return the OS device object describing the OpenFabrics device * \return The hwloc OS device object describing the OpenFabrics device
* (InfiniBand, Omni-Path, usNIC, etc) whose name is \p ibname * (InfiniBand, Omni-Path, usNIC, etc) whose name is \p ibname
* (mlx5_0, hfi1_0, usnic_0, qib0, etc). * (mlx5_0, hfi1_0, usnic_0, qib0, etc).
* Returns NULL if there is none. * \return \c NULL if none could be found.
*
* The name \p ibname is usually obtained from ibv_get_device_name(). * The name \p ibname is usually obtained from ibv_get_device_name().
* *
* The topology \p topology does not necessarily have to match the current * The topology \p topology does not necessarily have to match the current
@@ -117,8 +118,9 @@ hwloc_ibv_get_device_osdev_by_name(hwloc_topology_t topology,
/** \brief Get the hwloc OS device object corresponding to the OpenFabrics /** \brief Get the hwloc OS device object corresponding to the OpenFabrics
* device \p ibdev. * device \p ibdev.
* *
* Return the OS device object describing the OpenFabrics device \p ibdev * \return The hwloc OS device object describing the OpenFabrics
* (InfiniBand, etc). Returns NULL if there is none. * device \p ibdev (InfiniBand, etc).
* \return \c NULL if none could be found.
* *
* Topology \p topology and device \p ibdev must match the local machine. * Topology \p topology and device \p ibdev must match the local machine.
* I/O devices detection must be enabled in the topology. * I/O devices detection must be enabled in the topology.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2013-2020 Inria. All rights reserved. * Copyright © 2013-2021 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.
*/ */
@@ -27,6 +27,9 @@ struct hwloc_backend;
/** \defgroup hwlocality_disc_components Components and Plugins: Discovery components /** \defgroup hwlocality_disc_components Components and Plugins: Discovery components
*
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
*
* @{ * @{
*/ */
@@ -93,6 +96,9 @@ struct hwloc_disc_component {
/** \defgroup hwlocality_disc_backends Components and Plugins: Discovery backends /** \defgroup hwlocality_disc_backends Components and Plugins: Discovery backends
*
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
*
* @{ * @{
*/ */
@@ -241,6 +247,9 @@ HWLOC_DECLSPEC int hwloc_backend_enable(struct hwloc_backend *backend);
/** \defgroup hwlocality_generic_components Components and Plugins: Generic components /** \defgroup hwlocality_generic_components Components and Plugins: Generic components
*
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
*
* @{ * @{
*/ */
@@ -310,10 +319,26 @@ struct hwloc_component {
/** \defgroup hwlocality_components_core_funcs Components and Plugins: Core functions to be used by components /** \defgroup hwlocality_components_core_funcs Components and Plugins: Core functions to be used by components
*
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
*
* @{ * @{
*/ */
/** \brief Check whether insertion errors are hidden */ /** \brief Check whether error messages are hidden.
*
* Callers should print critical error messages
* (e.g. invalid hw topo info, invalid config)
* only if this function returns strictly less than 2.
*
* Callers should print non-critical error messages
* (e.g. failure to initialize CUDA)
* if this function returns 0.
*
* This function return 1 by default (show critical only),
* 0 in lstopo (show all),
* or anything set in HWLOC_HIDE_ERRORS in the environment.
*/
HWLOC_DECLSPEC int hwloc_hide_errors(void); HWLOC_DECLSPEC int hwloc_hide_errors(void);
/** \brief Add an object to the topology. /** \brief Add an object to the topology.
@@ -455,6 +480,9 @@ hwloc_plugin_check_namespace(const char *pluginname __hwloc_attribute_unused, co
/** \defgroup hwlocality_components_filtering Components and Plugins: Filtering objects /** \defgroup hwlocality_components_filtering Components and Plugins: Filtering objects
*
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
*
* @{ * @{
*/ */
@@ -469,9 +497,11 @@ hwloc_filter_check_pcidev_subtype_important(unsigned classid)
return (baseclass == 0x03 /* PCI_BASE_CLASS_DISPLAY */ return (baseclass == 0x03 /* PCI_BASE_CLASS_DISPLAY */
|| baseclass == 0x02 /* PCI_BASE_CLASS_NETWORK */ || baseclass == 0x02 /* PCI_BASE_CLASS_NETWORK */
|| baseclass == 0x01 /* PCI_BASE_CLASS_STORAGE */ || baseclass == 0x01 /* PCI_BASE_CLASS_STORAGE */
|| baseclass == 0x00 /* Unclassified, for Atos/Bull BXI */
|| baseclass == 0x0b /* PCI_BASE_CLASS_PROCESSOR */ || baseclass == 0x0b /* PCI_BASE_CLASS_PROCESSOR */
|| classid == 0x0c04 /* PCI_CLASS_SERIAL_FIBER */ || classid == 0x0c04 /* PCI_CLASS_SERIAL_FIBER */
|| classid == 0x0c06 /* PCI_CLASS_SERIAL_INFINIBAND */ || classid == 0x0c06 /* PCI_CLASS_SERIAL_INFINIBAND */
|| baseclass == 0x06 /* PCI_BASE_CLASS_BRIDGE with non-PCI downstream. the core will drop the useless ones later */
|| baseclass == 0x12 /* Processing Accelerators */); || baseclass == 0x12 /* Processing Accelerators */);
} }
@@ -527,6 +557,9 @@ hwloc_filter_check_keep_object(hwloc_topology_t topology, hwloc_obj_t obj)
/** \defgroup hwlocality_components_pcidisc Components and Plugins: helpers for PCI discovery /** \defgroup hwlocality_components_pcidisc Components and Plugins: helpers for PCI discovery
*
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
*
* @{ * @{
*/ */
@@ -578,18 +611,76 @@ HWLOC_DECLSPEC int hwloc_pcidisc_tree_attach(struct hwloc_topology *topology, st
/** \defgroup hwlocality_components_pcifind Components and Plugins: finding PCI objects during other discoveries /** \defgroup hwlocality_components_pcifind Components and Plugins: finding PCI objects during other discoveries
*
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
*
* @{ * @{
*/ */
/** \brief Find the normal parent of a PCI bus ID. /** \brief Find the object or a parent of a PCI bus ID.
* *
* Look at PCI affinity to find out where the given PCI bus ID should be attached. * When attaching a new object (typically an OS device) whose locality
* is specified by PCI bus ID, this function returns the PCI object
* to use as a parent for attaching.
* *
* This function should be used to attach an I/O device under the corresponding * If the exact PCI device with this bus ID exists, it is returned.
* PCI object (if any), or under a normal (non-I/O) object with same locality. * Otherwise (for instance if it was filtered out), the function returns
* another object with similar locality (for instance a parent bridge,
* or the local CPU Package).
*/ */
HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_parent_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func); HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_parent_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func);
/** \brief Find the PCI device or bridge matching a PCI bus ID exactly.
*
* This is useful for adding specific information about some objects
* based on their PCI id. When it comes to attaching objects based on
* PCI locality, hwloc_pci_find_parent_by_busid() should be preferred.
*/
HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func);
/** \brief Handle to a new distances structure during its addition to the topology. */
typedef void * hwloc_backend_distances_add_handle_t;
/** \brief Create a new empty distances structure.
*
* This is identical to hwloc_distances_add_create()
* but this variant is designed for backend inserting
* distances during topology discovery.
*/
HWLOC_DECLSPEC hwloc_backend_distances_add_handle_t
hwloc_backend_distances_add_create(hwloc_topology_t topology,
const char *name, unsigned long kind,
unsigned long flags);
/** \brief Specify the objects and values in a new empty distances structure.
*
* This is similar to hwloc_distances_add_values()
* but this variant is designed for backend inserting
* distances during topology discovery.
*
* The only semantical difference is that \p objs and \p values
* are not duplicated, but directly attached to the topology.
* On success, these arrays are given to the core and should not
* ever be freed by the caller anymore.
*/
HWLOC_DECLSPEC int
hwloc_backend_distances_add_values(hwloc_topology_t topology,
hwloc_backend_distances_add_handle_t handle,
unsigned nbobjs, hwloc_obj_t *objs,
hwloc_uint64_t *values,
unsigned long flags);
/** \brief Commit a new distances structure.
*
* This is similar to hwloc_distances_add_commit()
* but this variant is designed for backend inserting
* distances during topology discovery.
*/
HWLOC_DECLSPEC int
hwloc_backend_distances_add_commit(hwloc_topology_t topology,
hwloc_backend_distances_add_handle_t handle,
unsigned long flags);
/** @} */ /** @} */

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-2020 Inria. All rights reserved. * Copyright © 2010-2021 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -120,6 +120,9 @@ extern "C" {
#define HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM HWLOC_NAME_CAPS(TOPOLOGY_FLAG_IS_THISSYSTEM) #define HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM HWLOC_NAME_CAPS(TOPOLOGY_FLAG_IS_THISSYSTEM)
#define HWLOC_TOPOLOGY_FLAG_THISSYSTEM_ALLOWED_RESOURCES HWLOC_NAME_CAPS(TOPOLOGY_FLAG_THISSYSTEM_ALLOWED_RESOURCES) #define HWLOC_TOPOLOGY_FLAG_THISSYSTEM_ALLOWED_RESOURCES HWLOC_NAME_CAPS(TOPOLOGY_FLAG_THISSYSTEM_ALLOWED_RESOURCES)
#define HWLOC_TOPOLOGY_FLAG_IMPORT_SUPPORT HWLOC_NAME_CAPS(TOPOLOGY_FLAG_IMPORT_SUPPORT) #define HWLOC_TOPOLOGY_FLAG_IMPORT_SUPPORT HWLOC_NAME_CAPS(TOPOLOGY_FLAG_IMPORT_SUPPORT)
#define HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING HWLOC_NAME_CAPS(TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING)
#define HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_MEMBINDING HWLOC_NAME_CAPS(TOPOLOGY_FLAG_RESTRICT_TO_MEMBINDING)
#define HWLOC_TOPOLOGY_FLAG_DONT_CHANGE_BINDING HWLOC_NAME_CAPS(TOPOLOGY_FLAG_DONT_CHANGE_BINDING)
#define hwloc_topology_set_pid HWLOC_NAME(topology_set_pid) #define hwloc_topology_set_pid HWLOC_NAME(topology_set_pid)
#define hwloc_topology_set_synthetic HWLOC_NAME(topology_set_synthetic) #define hwloc_topology_set_synthetic HWLOC_NAME(topology_set_synthetic)
@@ -356,6 +359,7 @@ extern "C" {
#define hwloc_get_closest_objs HWLOC_NAME(get_closest_objs) #define hwloc_get_closest_objs HWLOC_NAME(get_closest_objs)
#define hwloc_get_obj_below_by_type HWLOC_NAME(get_obj_below_by_type) #define hwloc_get_obj_below_by_type HWLOC_NAME(get_obj_below_by_type)
#define hwloc_get_obj_below_array_by_type HWLOC_NAME(get_obj_below_array_by_type) #define hwloc_get_obj_below_array_by_type HWLOC_NAME(get_obj_below_array_by_type)
#define hwloc_get_obj_with_same_locality HWLOC_NAME(get_obj_with_same_locality)
#define hwloc_distrib_flags_e HWLOC_NAME(distrib_flags_e) #define hwloc_distrib_flags_e HWLOC_NAME(distrib_flags_e)
#define HWLOC_DISTRIB_FLAG_REVERSE HWLOC_NAME_CAPS(DISTRIB_FLAG_REVERSE) #define HWLOC_DISTRIB_FLAG_REVERSE HWLOC_NAME_CAPS(DISTRIB_FLAG_REVERSE)
#define hwloc_distrib HWLOC_NAME(distrib) #define hwloc_distrib HWLOC_NAME(distrib)
@@ -454,11 +458,22 @@ extern "C" {
#define hwloc_distances_obj_index HWLOC_NAME(distances_obj_index) #define hwloc_distances_obj_index HWLOC_NAME(distances_obj_index)
#define hwloc_distances_obj_pair_values HWLOC_NAME(distances_pair_values) #define hwloc_distances_obj_pair_values HWLOC_NAME(distances_pair_values)
#define hwloc_distances_transform_e HWLOC_NAME(distances_transform_e)
#define HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL HWLOC_NAME_CAPS(DISTANCES_TRANSFORM_REMOVE_NULL)
#define HWLOC_DISTANCES_TRANSFORM_LINKS HWLOC_NAME_CAPS(DISTANCES_TRANSFORM_LINKS)
#define HWLOC_DISTANCES_TRANSFORM_MERGE_SWITCH_PORTS HWLOC_NAME_CAPS(DISTANCES_TRANSFORM_MERGE_SWITCH_PORTS)
#define HWLOC_DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE HWLOC_NAME_CAPS(DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE)
#define hwloc_distances_transform HWLOC_NAME(distances_transform)
#define hwloc_distances_add_flag_e HWLOC_NAME(distances_add_flag_e) #define hwloc_distances_add_flag_e HWLOC_NAME(distances_add_flag_e)
#define HWLOC_DISTANCES_ADD_FLAG_GROUP HWLOC_NAME_CAPS(DISTANCES_ADD_FLAG_GROUP) #define HWLOC_DISTANCES_ADD_FLAG_GROUP HWLOC_NAME_CAPS(DISTANCES_ADD_FLAG_GROUP)
#define HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE HWLOC_NAME_CAPS(DISTANCES_ADD_FLAG_GROUP_INACCURATE) #define HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE HWLOC_NAME_CAPS(DISTANCES_ADD_FLAG_GROUP_INACCURATE)
#define hwloc_distances_add HWLOC_NAME(distances_add) #define hwloc_distances_add_handle_t HWLOC_NAME(distances_add_handle_t)
#define hwloc_distances_add_create HWLOC_NAME(distances_add_create)
#define hwloc_distances_add_values HWLOC_NAME(distances_add_values)
#define hwloc_distances_add_commit HWLOC_NAME(distances_add_commit)
#define hwloc_distances_remove HWLOC_NAME(distances_remove) #define hwloc_distances_remove HWLOC_NAME(distances_remove)
#define hwloc_distances_remove_by_depth HWLOC_NAME(distances_remove_by_depth) #define hwloc_distances_remove_by_depth HWLOC_NAME(distances_remove_by_depth)
#define hwloc_distances_remove_by_type HWLOC_NAME(distances_remove_by_type) #define hwloc_distances_remove_by_type HWLOC_NAME(distances_remove_by_type)
@@ -523,6 +538,11 @@ extern "C" {
#define hwloc_linux_get_tid_last_cpu_location HWLOC_NAME(linux_get_tid_last_cpu_location) #define hwloc_linux_get_tid_last_cpu_location HWLOC_NAME(linux_get_tid_last_cpu_location)
#define hwloc_linux_read_path_as_cpumask HWLOC_NAME(linux_read_file_cpumask) #define hwloc_linux_read_path_as_cpumask HWLOC_NAME(linux_read_file_cpumask)
/* windows.h */
#define hwloc_windows_get_nr_processor_groups HWLOC_NAME(windows_get_nr_processor_groups)
#define hwloc_windows_get_processor_group_cpuset HWLOC_NAME(windows_get_processor_group_cpuset)
/* openfabrics-verbs.h */ /* openfabrics-verbs.h */
#define hwloc_ibv_get_device_cpuset HWLOC_NAME(ibv_get_device_cpuset) #define hwloc_ibv_get_device_cpuset HWLOC_NAME(ibv_get_device_cpuset)
@@ -564,6 +584,11 @@ extern "C" {
#define hwloc_rsmi_get_device_osdev HWLOC_NAME(rsmi_get_device_osdev) #define hwloc_rsmi_get_device_osdev HWLOC_NAME(rsmi_get_device_osdev)
#define hwloc_rsmi_get_device_osdev_by_index HWLOC_NAME(rsmi_get_device_osdev_by_index) #define hwloc_rsmi_get_device_osdev_by_index HWLOC_NAME(rsmi_get_device_osdev_by_index)
/* levelzero.h */
#define hwloc_levelzero_get_device_cpuset HWLOC_NAME(levelzero_get_device_cpuset)
#define hwloc_levelzero_get_device_osdev HWLOC_NAME(levelzero_get_device_osdev)
/* gl.h */ /* gl.h */
#define hwloc_gl_get_display_osdev_by_port_device HWLOC_NAME(gl_get_display_osdev_by_port_device) #define hwloc_gl_get_display_osdev_by_port_device HWLOC_NAME(gl_get_display_osdev_by_port_device)
@@ -620,10 +645,18 @@ extern "C" {
#define hwloc_pcidisc_tree_insert_by_busid HWLOC_NAME(pcidisc_tree_insert_by_busid) #define hwloc_pcidisc_tree_insert_by_busid HWLOC_NAME(pcidisc_tree_insert_by_busid)
#define hwloc_pcidisc_tree_attach HWLOC_NAME(pcidisc_tree_attach) #define hwloc_pcidisc_tree_attach HWLOC_NAME(pcidisc_tree_attach)
#define hwloc_pci_find_by_busid HWLOC_NAME(pcidisc_find_by_busid)
#define hwloc_pci_find_parent_by_busid HWLOC_NAME(pcidisc_find_busid_parent) #define hwloc_pci_find_parent_by_busid HWLOC_NAME(pcidisc_find_busid_parent)
#define hwloc_backend_distances_add_handle_t HWLOC_NAME(backend_distances_add_handle_t)
#define hwloc_backend_distances_add_create HWLOC_NAME(backend_distances_add_create)
#define hwloc_backend_distances_add_values HWLOC_NAME(backend_distances_add_values)
#define hwloc_backend_distances_add_commit HWLOC_NAME(backend_distances_add_commit)
/* hwloc/deprecated.h */ /* hwloc/deprecated.h */
#define hwloc_distances_add HWLOC_NAME(distances_add)
#define hwloc_topology_insert_misc_object_by_parent HWLOC_NAME(topology_insert_misc_object_by_parent) #define hwloc_topology_insert_misc_object_by_parent HWLOC_NAME(topology_insert_misc_object_by_parent)
#define hwloc_obj_cpuset_snprintf HWLOC_NAME(obj_cpuset_snprintf) #define hwloc_obj_cpuset_snprintf HWLOC_NAME(obj_cpuset_snprintf)
#define hwloc_obj_type_sscanf HWLOC_NAME(obj_type_sscanf) #define hwloc_obj_type_sscanf HWLOC_NAME(obj_type_sscanf)
@@ -733,6 +766,7 @@ extern "C" {
#define hwloc_cuda_component HWLOC_NAME(cuda_component) #define hwloc_cuda_component HWLOC_NAME(cuda_component)
#define hwloc_gl_component HWLOC_NAME(gl_component) #define hwloc_gl_component HWLOC_NAME(gl_component)
#define hwloc_levelzero_component HWLOC_NAME(levelzero_component)
#define hwloc_nvml_component HWLOC_NAME(nvml_component) #define hwloc_nvml_component HWLOC_NAME(nvml_component)
#define hwloc_rsmi_component HWLOC_NAME(rsmi_component) #define hwloc_rsmi_component HWLOC_NAME(rsmi_component)
#define hwloc_opencl_component HWLOC_NAME(opencl_component) #define hwloc_opencl_component HWLOC_NAME(opencl_component)
@@ -772,7 +806,6 @@ extern "C" {
#define hwloc_pci_discovery_init HWLOC_NAME(pci_discovery_init) #define hwloc_pci_discovery_init HWLOC_NAME(pci_discovery_init)
#define hwloc_pci_discovery_prepare HWLOC_NAME(pci_discovery_prepare) #define hwloc_pci_discovery_prepare HWLOC_NAME(pci_discovery_prepare)
#define hwloc_pci_discovery_exit HWLOC_NAME(pci_discovery_exit) #define hwloc_pci_discovery_exit HWLOC_NAME(pci_discovery_exit)
#define hwloc_pci_find_by_busid HWLOC_NAME(pcidisc_find_by_busid)
#define hwloc_find_insert_io_parent_by_complete_cpuset HWLOC_NAME(hwloc_find_insert_io_parent_by_complete_cpuset) #define hwloc_find_insert_io_parent_by_complete_cpuset HWLOC_NAME(hwloc_find_insert_io_parent_by_complete_cpuset)
#define hwloc__add_info HWLOC_NAME(_add_info) #define hwloc__add_info HWLOC_NAME(_add_info)
@@ -816,7 +849,6 @@ extern "C" {
#define hwloc_internal_distances_dup HWLOC_NAME(internal_distances_dup) #define hwloc_internal_distances_dup HWLOC_NAME(internal_distances_dup)
#define hwloc_internal_distances_refresh HWLOC_NAME(internal_distances_refresh) #define hwloc_internal_distances_refresh HWLOC_NAME(internal_distances_refresh)
#define hwloc_internal_distances_destroy HWLOC_NAME(internal_distances_destroy) #define hwloc_internal_distances_destroy HWLOC_NAME(internal_distances_destroy)
#define hwloc_internal_distances_add HWLOC_NAME(internal_distances_add) #define hwloc_internal_distances_add HWLOC_NAME(internal_distances_add)
#define hwloc_internal_distances_add_by_index HWLOC_NAME(internal_distances_add_by_index) #define hwloc_internal_distances_add_by_index HWLOC_NAME(internal_distances_add_by_index)
#define hwloc_internal_distances_invalidate_cached_objs HWLOC_NAME(hwloc_internal_distances_invalidate_cached_objs) #define hwloc_internal_distances_invalidate_cached_objs HWLOC_NAME(hwloc_internal_distances_invalidate_cached_objs)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2012-2020 Inria. All rights reserved. * Copyright © 2012-2021 Inria. All rights reserved.
* Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved. * Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.
* Written by Advanced Micro Devices, * Written by Advanced Micro Devices,
* See COPYING in top-level directory. * See COPYING in top-level directory.
@@ -41,7 +41,7 @@ extern "C" {
/** \brief Get the CPU set of logical processors that are physically /** \brief Get the CPU set of logical processors that are physically
* close to AMD GPU device whose index is \p dv_ind. * close to AMD GPU device whose index is \p dv_ind.
* *
* Return the CPU set describing the locality of the AMD GPU device * Store in \p set the CPU-set describing the locality of the AMD GPU device
* whose index is \p dv_ind. * whose index is \p dv_ind.
* *
* Topology \p topology and device \p dv_ind must match the local machine. * Topology \p topology and device \p dv_ind must match the local machine.
@@ -96,8 +96,9 @@ hwloc_rsmi_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
/** \brief Get the hwloc OS device object corresponding to the /** \brief Get the hwloc OS device object corresponding to the
* AMD GPU device whose index is \p dv_ind. * AMD GPU device whose index is \p dv_ind.
* *
* Return the OS device object describing the AMD GPU device whose * \return The hwloc OS device object describing the AMD GPU device whose
* index is \p dv_ind. Returns NULL if there is none. * index is \p dv_ind.
* \return \c NULL if none could be found.
* *
* The topology \p topology does not necessarily have to match the current * The topology \p topology does not necessarily have to match the current
* machine. For instance the topology may be an XML import of a remote host. * machine. For instance the topology may be an XML import of a remote host.
@@ -124,8 +125,9 @@ hwloc_rsmi_get_device_osdev_by_index(hwloc_topology_t topology, uint32_t dv_ind)
/** \brief Get the hwloc OS device object corresponding to AMD GPU device, /** \brief Get the hwloc OS device object corresponding to AMD GPU device,
* whose index is \p dv_ind. * whose index is \p dv_ind.
* *
* Return the hwloc OS device object that describes the given * \return The hwloc OS device object that describes the given
* AMD GPU, whose index is \p dv_ind Return NULL if there is none. * AMD GPU, whose index is \p dv_ind.
* \return \c NULL if none could be found.
* *
* Topology \p topology and device \p dv_ind must match the local machine. * Topology \p topology and device \p dv_ind must match the local machine.
* I/O devices detection and the ROCm SMI component must be enabled in the * I/O devices detection and the ROCm SMI component must be enabled in the

View File

@@ -0,0 +1,76 @@
/*
* Copyright © 2021 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
/** \file
* \brief Macros to help interaction between hwloc and Windows.
*
* Applications that use hwloc on Windows may want to include this file
* for Windows specific hwloc features.
*/
#ifndef HWLOC_WINDOWS_H
#define HWLOC_WINDOWS_H
#include "hwloc.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup hwlocality_windows Windows-specific helpers
*
* These functions query Windows processor groups.
* These groups partition the operating system into virtual sets
* of up to 64 neighbor PUs.
* Threads and processes may only be bound inside a single group.
* Although Windows processor groups may be exposed in the hwloc
* hierarchy as hwloc Groups, they are also often merged into
* existing hwloc objects such as NUMA nodes or Packages.
* This API provides explicit information about Windows processor
* groups so that applications know whether binding to a large
* set of PUs may fail because it spans over multiple Windows
* processor groups.
*
* @{
*/
/** \brief Get the number of Windows processor groups
*
* \p flags must be 0 for now.
*
* \return at least \c 1 on success.
* \return -1 on error, for instance if the topology does not match
* the current system (e.g. loaded from another machine through XML).
*/
HWLOC_DECLSPEC int hwloc_windows_get_nr_processor_groups(hwloc_topology_t topology, unsigned long flags);
/** \brief Get the CPU-set of a Windows processor group.
*
* Get the set of PU included in the processor group specified
* by \p pg_index.
* \p pg_index must be between \c 0 and the value returned
* by hwloc_windows_get_nr_processor_groups() minus 1.
*
* \p flags must be 0 for now.
*
* \return \c 0 on success.
* \return \c -1 on error, for instance if \p pg_index is invalid,
* or if the topology does not match the current system (e.g. loaded
* from another machine through XML).
*/
HWLOC_DECLSPEC int hwloc_windows_get_processor_group_cpuset(hwloc_topology_t topology, unsigned pg_index, hwloc_cpuset_t cpuset, unsigned long flags);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HWLOC_WINDOWS_H */

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009, 2011, 2012 CNRS. All rights reserved. * Copyright © 2009, 2011, 2012 CNRS. All rights reserved.
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2021 Inria. All rights reserved.
* Copyright © 2009, 2011, 2012, 2015 Université Bordeaux. All rights reserved. * Copyright © 2009, 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$
@@ -290,10 +290,6 @@
/* Define to '1' if sysctlbyname is present and usable */ /* Define to '1' if sysctlbyname is present and usable */
/* #undef HAVE_SYSCTLBYNAME */ /* #undef HAVE_SYSCTLBYNAME */
/* Define to 1 if the system has the type
`SYSTEM_LOGICAL_PROCESSOR_INFORMATION'. */
#define HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION 1
/* Define to 1 if the system has the type /* Define to 1 if the system has the type
`SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX'. */ `SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX'. */
#define HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX 1 #define HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX 1

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2018-2019 Inria. All rights reserved. * Copyright © 2018-2020 Inria. All rights reserved.
* *
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -31,6 +31,7 @@ HWLOC_DECLSPEC extern const struct hwloc_component hwloc_cuda_component;
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_gl_component; HWLOC_DECLSPEC extern const struct hwloc_component hwloc_gl_component;
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_nvml_component; HWLOC_DECLSPEC extern const struct hwloc_component hwloc_nvml_component;
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_rsmi_component; HWLOC_DECLSPEC extern const struct hwloc_component hwloc_rsmi_component;
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_levelzero_component;
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_opencl_component; HWLOC_DECLSPEC extern const struct hwloc_component hwloc_opencl_component;
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_pci_component; HWLOC_DECLSPEC extern const struct hwloc_component hwloc_pci_component;

View File

@@ -504,7 +504,7 @@ hwloc__obj_type_is_icache(hwloc_obj_type_t type)
} \ } \
} while(0) } while(0)
#else /* HAVE_USELOCALE */ #else /* HAVE_USELOCALE */
#if __HWLOC_HAVE_ATTRIBUTE_UNUSED #if HWLOC_HAVE_ATTRIBUTE_UNUSED
#define hwloc_localeswitch_declare int __dummy_nolocale __hwloc_attribute_unused #define hwloc_localeswitch_declare int __dummy_nolocale __hwloc_attribute_unused
#define hwloc_localeswitch_init() #define hwloc_localeswitch_init()
#else #else

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2021 Inria. All rights reserved.
* Copyright © 2009-2012, 2020 Université Bordeaux * Copyright © 2009-2012, 2020 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* *
@@ -166,6 +166,7 @@ struct hwloc_topology {
unsigned long kind; unsigned long kind;
#define HWLOC_INTERNAL_DIST_FLAG_OBJS_VALID (1U<<0) /* if the objs array is valid below */ #define HWLOC_INTERNAL_DIST_FLAG_OBJS_VALID (1U<<0) /* if the objs array is valid below */
#define HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED (1U<<1) /* if the distances isn't in the list yet */
unsigned iflags; unsigned iflags;
/* objects are currently stored in physical_index order */ /* objects are currently stored in physical_index order */
@@ -304,11 +305,6 @@ extern void hwloc_pci_discovery_init(struct hwloc_topology *topology);
extern void hwloc_pci_discovery_prepare(struct hwloc_topology *topology); extern void hwloc_pci_discovery_prepare(struct hwloc_topology *topology);
extern void hwloc_pci_discovery_exit(struct hwloc_topology *topology); extern void hwloc_pci_discovery_exit(struct hwloc_topology *topology);
/* Look for an object matching the given domain/bus/func,
* either exactly or return the smallest container bridge
*/
extern struct hwloc_obj * hwloc_pci_find_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func);
/* Look for an object matching complete cpuset exactly, or insert one. /* Look for an object matching complete cpuset exactly, or insert one.
* Return NULL on failure. * Return NULL on failure.
* Return a good fallback (object above) on failure to insert. * Return a good fallback (object above) on failure to insert.
@@ -408,10 +404,14 @@ extern void hwloc_internal_distances_prepare(hwloc_topology_t topology);
extern void hwloc_internal_distances_destroy(hwloc_topology_t topology); extern void hwloc_internal_distances_destroy(hwloc_topology_t topology);
extern int hwloc_internal_distances_dup(hwloc_topology_t new, hwloc_topology_t old); extern int hwloc_internal_distances_dup(hwloc_topology_t new, hwloc_topology_t old);
extern void hwloc_internal_distances_refresh(hwloc_topology_t topology); extern void hwloc_internal_distances_refresh(hwloc_topology_t topology);
extern int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name, unsigned nbobjs, hwloc_obj_t *objs, uint64_t *values, unsigned long kind, unsigned long flags);
extern int hwloc_internal_distances_add_by_index(hwloc_topology_t topology, const char *name, hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types, unsigned nbobjs, uint64_t *indexes, uint64_t *values, unsigned long kind, unsigned long flags);
extern void hwloc_internal_distances_invalidate_cached_objs(hwloc_topology_t topology); extern void hwloc_internal_distances_invalidate_cached_objs(hwloc_topology_t topology);
/* these distances_add() functions are higher-level than those in hwloc/plugins.h
* but they may change in the future, hence they are not exported to plugins.
*/
extern int hwloc_internal_distances_add_by_index(hwloc_topology_t topology, const char *name, hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types, unsigned nbobjs, uint64_t *indexes, uint64_t *values, unsigned long kind, unsigned long flags);
extern int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name, unsigned nbobjs, hwloc_obj_t *objs, uint64_t *values, unsigned long kind, unsigned long flags);
extern void hwloc_internal_memattrs_init(hwloc_topology_t topology); extern void hwloc_internal_memattrs_init(hwloc_topology_t topology);
extern void hwloc_internal_memattrs_prepare(hwloc_topology_t topology); extern void hwloc_internal_memattrs_prepare(hwloc_topology_t topology);
extern void hwloc_internal_memattrs_destroy(hwloc_topology_t topology); extern void hwloc_internal_memattrs_destroy(hwloc_topology_t topology);
@@ -480,6 +480,7 @@ extern char * hwloc_progname(struct hwloc_topology *topology);
#define HWLOC_GROUP_KIND_AIX_SDL_UNKNOWN 210 /* subkind is SDL level */ #define HWLOC_GROUP_KIND_AIX_SDL_UNKNOWN 210 /* subkind is SDL level */
#define HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP 220 /* no subkind */ #define HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP 220 /* no subkind */
#define HWLOC_GROUP_KIND_WINDOWS_RELATIONSHIP_UNKNOWN 221 /* no subkind */ #define HWLOC_GROUP_KIND_WINDOWS_RELATIONSHIP_UNKNOWN 221 /* no subkind */
#define HWLOC_GROUP_KIND_LINUX_CLUSTER 222 /* no subkind */
/* distance groups */ /* distance groups */
#define HWLOC_GROUP_KIND_DISTANCE 900 /* subkind is round of adding these groups during distance based grouping */ #define HWLOC_GROUP_KIND_DISTANCE 900 /* subkind is round of adding these groups during distance based grouping */
/* finally, hwloc-specific groups required to insert something else, should disappear as soon as possible */ /* finally, hwloc-specific groups required to insert something else, should disappear as soon as possible */

View File

@@ -0,0 +1,21 @@
/*
* Copyright © 2009 Université Bordeaux
* Copyright © 2020 Inria. All rights reserved.
*
* See COPYING in top-level directory.
*/
#ifndef HWLOC_PRIVATE_WINDOWS_H
#define HWLOC_PRIVATE_WINDOWS_H
#ifdef __GNUC__
#define _ANONYMOUS_UNION __extension__
#define _ANONYMOUS_STRUCT __extension__
#else
#define _ANONYMOUS_UNION
#define _ANONYMOUS_STRUCT
#endif /* __GNUC__ */
#define DUMMYUNIONNAME
#define DUMMYSTRUCTNAME
#endif /* HWLOC_PRIVATE_WINDOWS_H */

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2021 Inria. All rights reserved.
* Copyright © 2012 Université Bordeaux * Copyright © 2012 Université Bordeaux
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -124,7 +124,7 @@ hwloc_dlforeachfile(const char *_paths,
*colon = '\0'; *colon = '\0';
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, " Looking under %s\n", path); fprintf(stderr, "hwloc: Looking under %s\n", path);
dir = opendir(path); dir = opendir(path);
if (!dir) if (!dir)
@@ -198,7 +198,7 @@ hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
char *componentsymbolname; char *componentsymbolname;
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Plugin dlforeach found `%s'\n", filename); fprintf(stderr, "hwloc: Plugin dlforeach found `%s'\n", filename);
basename = strrchr(filename, '/'); basename = strrchr(filename, '/');
if (!basename) if (!basename)
@@ -208,7 +208,7 @@ hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
if (hwloc_plugins_blacklist && strstr(hwloc_plugins_blacklist, basename)) { if (hwloc_plugins_blacklist && strstr(hwloc_plugins_blacklist, basename)) {
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Plugin `%s' is blacklisted in the environment\n", basename); fprintf(stderr, "hwloc: Plugin `%s' is blacklisted in the environment\n", basename);
goto out; goto out;
} }
@@ -216,14 +216,14 @@ hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
handle = hwloc_dlopenext(filename); handle = hwloc_dlopenext(filename);
if (!handle) { if (!handle) {
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Failed to load plugin: %s\n", hwloc_dlerror()); fprintf(stderr, "hwloc: Failed to load plugin: %s\n", hwloc_dlerror());
goto out; goto out;
} }
componentsymbolname = malloc(strlen(basename)+10+1); componentsymbolname = malloc(strlen(basename)+10+1);
if (!componentsymbolname) { if (!componentsymbolname) {
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Failed to allocation component `%s' symbol\n", fprintf(stderr, "hwloc: Failed to allocation component `%s' symbol\n",
basename); basename);
goto out_with_handle; goto out_with_handle;
} }
@@ -231,38 +231,38 @@ hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
component = hwloc_dlsym(handle, componentsymbolname); component = hwloc_dlsym(handle, componentsymbolname);
if (!component) { if (!component) {
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Failed to find component symbol `%s'\n", fprintf(stderr, "hwloc: Failed to find component symbol `%s'\n",
componentsymbolname); componentsymbolname);
free(componentsymbolname); free(componentsymbolname);
goto out_with_handle; goto out_with_handle;
} }
if (component->abi != HWLOC_COMPONENT_ABI) { if (component->abi != HWLOC_COMPONENT_ABI) {
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Plugin symbol ABI %u instead of %d\n", fprintf(stderr, "hwloc: Plugin symbol ABI %u instead of %d\n",
component->abi, HWLOC_COMPONENT_ABI); component->abi, HWLOC_COMPONENT_ABI);
free(componentsymbolname); free(componentsymbolname);
goto out_with_handle; goto out_with_handle;
} }
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Plugin contains expected symbol `%s'\n", fprintf(stderr, "hwloc: Plugin contains expected symbol `%s'\n",
componentsymbolname); componentsymbolname);
free(componentsymbolname); free(componentsymbolname);
if (HWLOC_COMPONENT_TYPE_DISC == component->type) { if (HWLOC_COMPONENT_TYPE_DISC == component->type) {
if (strncmp(basename, "hwloc_", 6)) { if (strncmp(basename, "hwloc_", 6)) {
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Plugin name `%s' doesn't match its type DISCOVERY\n", basename); fprintf(stderr, "hwloc: Plugin name `%s' doesn't match its type DISCOVERY\n", basename);
goto out_with_handle; goto out_with_handle;
} }
} else if (HWLOC_COMPONENT_TYPE_XML == component->type) { } else if (HWLOC_COMPONENT_TYPE_XML == component->type) {
if (strncmp(basename, "hwloc_xml_", 10)) { if (strncmp(basename, "hwloc_xml_", 10)) {
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Plugin name `%s' doesn't match its type XML\n", basename); fprintf(stderr, "hwloc: Plugin name `%s' doesn't match its type XML\n", basename);
goto out_with_handle; goto out_with_handle;
} }
} else { } else {
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Plugin name `%s' has invalid type %u\n", fprintf(stderr, "hwloc: Plugin name `%s' has invalid type %u\n",
basename, (unsigned) component->type); basename, (unsigned) component->type);
goto out_with_handle; goto out_with_handle;
} }
@@ -277,7 +277,7 @@ hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
desc->handle = handle; desc->handle = handle;
desc->next = NULL; desc->next = NULL;
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Plugin descriptor `%s' ready\n", basename); fprintf(stderr, "hwloc: Plugin descriptor `%s' ready\n", basename);
/* append to the list */ /* append to the list */
prevdesc = &hwloc_plugins; prevdesc = &hwloc_plugins;
@@ -285,7 +285,7 @@ hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
prevdesc = &((*prevdesc)->next); prevdesc = &((*prevdesc)->next);
*prevdesc = desc; *prevdesc = desc;
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Plugin descriptor `%s' queued\n", basename); fprintf(stderr, "hwloc: Plugin descriptor `%s' queued\n", basename);
return 0; return 0;
out_with_handle: out_with_handle:
@@ -300,7 +300,7 @@ hwloc_plugins_exit(void)
struct hwloc__plugin_desc *desc, *next; struct hwloc__plugin_desc *desc, *next;
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Closing all plugins\n"); fprintf(stderr, "hwloc: Closing all plugins\n");
desc = hwloc_plugins; desc = hwloc_plugins;
while (desc) { while (desc) {
@@ -340,7 +340,7 @@ hwloc_plugins_init(void)
hwloc_plugins = NULL; hwloc_plugins = NULL;
if (hwloc_plugins_verbose) if (hwloc_plugins_verbose)
fprintf(stderr, "Starting plugin dlforeach in %s\n", path); fprintf(stderr, "hwloc: Starting plugin dlforeach in %s\n", path);
err = hwloc_dlforeachfile(path, hwloc__dlforeach_cb, NULL); err = hwloc_dlforeachfile(path, hwloc__dlforeach_cb, NULL);
if (err) if (err)
goto out_with_init; goto out_with_init;
@@ -364,14 +364,14 @@ hwloc_disc_component_register(struct hwloc_disc_component *component,
/* check that the component name is valid */ /* check that the component name is valid */
if (!strcmp(component->name, HWLOC_COMPONENT_STOP_NAME)) { if (!strcmp(component->name, HWLOC_COMPONENT_STOP_NAME)) {
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Cannot register discovery component with reserved name `" HWLOC_COMPONENT_STOP_NAME "'\n"); fprintf(stderr, "hwloc: Cannot register discovery component with reserved name `" HWLOC_COMPONENT_STOP_NAME "'\n");
return -1; return -1;
} }
if (strchr(component->name, HWLOC_COMPONENT_EXCLUDE_CHAR) if (strchr(component->name, HWLOC_COMPONENT_EXCLUDE_CHAR)
|| strchr(component->name, HWLOC_COMPONENT_PHASESEP_CHAR) || strchr(component->name, HWLOC_COMPONENT_PHASESEP_CHAR)
|| strcspn(component->name, HWLOC_COMPONENT_SEPS) != strlen(component->name)) { || strcspn(component->name, HWLOC_COMPONENT_SEPS) != strlen(component->name)) {
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Cannot register discovery component with name `%s' containing reserved characters `%c" HWLOC_COMPONENT_SEPS "'\n", fprintf(stderr, "hwloc: Cannot register discovery component with name `%s' containing reserved characters `%c" HWLOC_COMPONENT_SEPS "'\n",
component->name, HWLOC_COMPONENT_EXCLUDE_CHAR); component->name, HWLOC_COMPONENT_EXCLUDE_CHAR);
return -1; return -1;
} }
@@ -386,8 +386,9 @@ hwloc_disc_component_register(struct hwloc_disc_component *component,
|HWLOC_DISC_PHASE_MISC |HWLOC_DISC_PHASE_MISC
|HWLOC_DISC_PHASE_ANNOTATE |HWLOC_DISC_PHASE_ANNOTATE
|HWLOC_DISC_PHASE_TWEAK))) { |HWLOC_DISC_PHASE_TWEAK))) {
fprintf(stderr, "Cannot register discovery component `%s' with invalid phases 0x%x\n", if (hwloc_hide_errors() < 2)
component->name, component->phases); fprintf(stderr, "hwloc: Cannot register discovery component `%s' with invalid phases 0x%x\n",
component->name, component->phases);
return -1; return -1;
} }
@@ -398,13 +399,13 @@ hwloc_disc_component_register(struct hwloc_disc_component *component,
if ((*prev)->priority < component->priority) { if ((*prev)->priority < component->priority) {
/* drop the existing component */ /* drop the existing component */
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Dropping previously registered discovery component `%s', priority %u lower than new one %u\n", fprintf(stderr, "hwloc: Dropping previously registered discovery component `%s', priority %u lower than new one %u\n",
(*prev)->name, (*prev)->priority, component->priority); (*prev)->name, (*prev)->priority, component->priority);
*prev = (*prev)->next; *prev = (*prev)->next;
} else { } else {
/* drop the new one */ /* drop the new one */
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Ignoring new discovery component `%s', priority %u lower than previously registered one %u\n", fprintf(stderr, "hwloc: Ignoring new discovery component `%s', priority %u lower than previously registered one %u\n",
component->name, component->priority, (*prev)->priority); component->name, component->priority, (*prev)->priority);
return -1; return -1;
} }
@@ -412,7 +413,7 @@ hwloc_disc_component_register(struct hwloc_disc_component *component,
prev = &((*prev)->next); prev = &((*prev)->next);
} }
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Registered discovery component `%s' phases 0x%x with priority %u (%s%s)\n", fprintf(stderr, "hwloc: Registered discovery component `%s' phases 0x%x with priority %u (%s%s)\n",
component->name, component->phases, component->priority, component->name, component->phases, component->priority,
filename ? "from plugin " : "statically build", filename ? filename : ""); filename ? "from plugin " : "statically build", filename ? filename : "");
@@ -475,15 +476,16 @@ hwloc_components_init(void)
/* hwloc_static_components is created by configure in static-components.h */ /* hwloc_static_components is created by configure in static-components.h */
for(i=0; NULL != hwloc_static_components[i]; i++) { for(i=0; NULL != hwloc_static_components[i]; i++) {
if (hwloc_static_components[i]->flags) { if (hwloc_static_components[i]->flags) {
fprintf(stderr, "Ignoring static component with invalid flags %lx\n", if (hwloc_hide_errors() < 2)
hwloc_static_components[i]->flags); fprintf(stderr, "hwloc: Ignoring static component with invalid flags %lx\n",
hwloc_static_components[i]->flags);
continue; continue;
} }
/* initialize the component */ /* initialize the component */
if (hwloc_static_components[i]->init && hwloc_static_components[i]->init(0) < 0) { if (hwloc_static_components[i]->init && hwloc_static_components[i]->init(0) < 0) {
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Ignoring static component, failed to initialize\n"); fprintf(stderr, "hwloc: Ignoring static component, failed to initialize\n");
continue; continue;
} }
/* queue ->finalize() callback if any */ /* queue ->finalize() callback if any */
@@ -503,15 +505,16 @@ hwloc_components_init(void)
#ifdef HWLOC_HAVE_PLUGINS #ifdef HWLOC_HAVE_PLUGINS
for(desc = hwloc_plugins; NULL != desc; desc = desc->next) { for(desc = hwloc_plugins; NULL != desc; desc = desc->next) {
if (desc->component->flags) { if (desc->component->flags) {
fprintf(stderr, "Ignoring plugin `%s' component with invalid flags %lx\n", if (hwloc_hide_errors() < 2)
desc->name, desc->component->flags); fprintf(stderr, "hwloc: Ignoring plugin `%s' component with invalid flags %lx\n",
desc->name, desc->component->flags);
continue; continue;
} }
/* initialize the component */ /* initialize the component */
if (desc->component->init && desc->component->init(0) < 0) { if (desc->component->init && desc->component->init(0) < 0) {
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Ignoring plugin `%s', failed to initialize\n", desc->name); fprintf(stderr, "hwloc: Ignoring plugin `%s', failed to initialize\n", desc->name);
continue; continue;
} }
/* queue ->finalize() callback if any */ /* queue ->finalize() callback if any */
@@ -608,7 +611,7 @@ hwloc_disc_component_blacklist_one(struct hwloc_topology *topology,
/* replace linuxpci and linuxio with linux (with IO phases) /* replace linuxpci and linuxio with linux (with IO phases)
* for backward compatibility with pre-v2.0 and v2.0 respectively */ * for backward compatibility with pre-v2.0 and v2.0 respectively */
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Replacing deprecated component `%s' with `linux' IO phases in blacklisting\n", name); fprintf(stderr, "hwloc: Replacing deprecated component `%s' with `linux' IO phases in blacklisting\n", name);
comp = hwloc_disc_component_find("linux", NULL); comp = hwloc_disc_component_find("linux", NULL);
phases = HWLOC_DISC_PHASE_PCI | HWLOC_DISC_PHASE_IO | HWLOC_DISC_PHASE_MISC | HWLOC_DISC_PHASE_ANNOTATE; phases = HWLOC_DISC_PHASE_PCI | HWLOC_DISC_PHASE_IO | HWLOC_DISC_PHASE_MISC | HWLOC_DISC_PHASE_ANNOTATE;
@@ -624,7 +627,7 @@ hwloc_disc_component_blacklist_one(struct hwloc_topology *topology,
} }
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Blacklisting component `%s` phases 0x%x\n", comp->name, phases); fprintf(stderr, "hwloc: Blacklisting component `%s` phases 0x%x\n", comp->name, phases);
for(i=0; i<topology->nr_blacklisted_components; i++) { for(i=0; i<topology->nr_blacklisted_components; i++) {
if (topology->blacklisted_components[i].component == comp) { if (topology->blacklisted_components[i].component == comp) {
@@ -727,7 +730,7 @@ hwloc_disc_component_try_enable(struct hwloc_topology *topology,
if (hwloc_components_verbose) if (hwloc_components_verbose)
/* do not warn if envvar_forced since system-wide HWLOC_COMPONENTS must be silently ignored after set_xml() etc. /* do not warn if envvar_forced since system-wide HWLOC_COMPONENTS must be silently ignored after set_xml() etc.
*/ */
fprintf(stderr, "Excluding discovery component `%s' phases 0x%x, conflicts with excludes 0x%x\n", fprintf(stderr, "hwloc: Excluding discovery component `%s' phases 0x%x, conflicts with excludes 0x%x\n",
comp->name, comp->phases, topology->backend_excluded_phases); comp->name, comp->phases, topology->backend_excluded_phases);
return -1; return -1;
} }
@@ -735,8 +738,8 @@ hwloc_disc_component_try_enable(struct hwloc_topology *topology,
backend = comp->instantiate(topology, comp, topology->backend_excluded_phases | blacklisted_phases, backend = comp->instantiate(topology, comp, topology->backend_excluded_phases | blacklisted_phases,
NULL, NULL, NULL); NULL, NULL, NULL);
if (!backend) { if (!backend) {
if (hwloc_components_verbose || envvar_forced) if (hwloc_components_verbose || (envvar_forced && hwloc_hide_errors() < 2))
fprintf(stderr, "Failed to instantiate discovery component `%s'\n", comp->name); fprintf(stderr, "hwloc: Failed to instantiate discovery component `%s'\n", comp->name);
return -1; return -1;
} }
@@ -817,7 +820,7 @@ hwloc_disc_components_enable_others(struct hwloc_topology *topology)
name = curenv; name = curenv;
if (!strcmp(name, "linuxpci") || !strcmp(name, "linuxio")) { if (!strcmp(name, "linuxpci") || !strcmp(name, "linuxio")) {
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Replacing deprecated component `%s' with `linux' in envvar forcing\n", name); fprintf(stderr, "hwloc: Replacing deprecated component `%s' with `linux' in envvar forcing\n", name);
name = "linux"; name = "linux";
} }
@@ -832,7 +835,8 @@ hwloc_disc_components_enable_others(struct hwloc_topology *topology)
if (comp->phases & ~blacklisted_phases) if (comp->phases & ~blacklisted_phases)
hwloc_disc_component_try_enable(topology, comp, 1 /* envvar forced */, blacklisted_phases); hwloc_disc_component_try_enable(topology, comp, 1 /* envvar forced */, blacklisted_phases);
} else { } else {
fprintf(stderr, "Cannot find discovery component `%s'\n", name); if (hwloc_hide_errors() < 2)
fprintf(stderr, "hwloc: Cannot find discovery component `%s'\n", name);
} }
/* restore chars (the second loop below needs env to be unmodified) */ /* restore chars (the second loop below needs env to be unmodified) */
@@ -864,7 +868,7 @@ hwloc_disc_components_enable_others(struct hwloc_topology *topology)
if (!(comp->phases & ~blacklisted_phases)) { if (!(comp->phases & ~blacklisted_phases)) {
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Excluding blacklisted discovery component `%s' phases 0x%x\n", fprintf(stderr, "hwloc: Excluding blacklisted discovery component `%s' phases 0x%x\n",
comp->name, comp->phases); comp->name, comp->phases);
goto nextcomp; goto nextcomp;
} }
@@ -879,7 +883,7 @@ nextcomp:
/* print a summary */ /* print a summary */
int first = 1; int first = 1;
backend = topology->backends; backend = topology->backends;
fprintf(stderr, "Final list of enabled discovery components: "); fprintf(stderr, "hwloc: Final list of enabled discovery components: ");
while (backend != NULL) { while (backend != NULL) {
fprintf(stderr, "%s%s(0x%x)", first ? "" : ",", backend->component->name, backend->phases); fprintf(stderr, "%s%s(0x%x)", first ? "" : ",", backend->component->name, backend->phases);
backend = backend->next; backend = backend->next;
@@ -935,7 +939,7 @@ hwloc_backend_alloc(struct hwloc_topology *topology,
/* filter-out component phases that are excluded */ /* filter-out component phases that are excluded */
backend->phases = component->phases & ~topology->backend_excluded_phases; backend->phases = component->phases & ~topology->backend_excluded_phases;
if (backend->phases != component->phases && hwloc_components_verbose) if (backend->phases != component->phases && hwloc_components_verbose)
fprintf(stderr, "Trying discovery component `%s' with phases 0x%x instead of 0x%x\n", fprintf(stderr, "hwloc: Trying discovery component `%s' with phases 0x%x instead of 0x%x\n",
component->name, backend->phases, component->phases); component->name, backend->phases, component->phases);
backend->flags = 0; backend->flags = 0;
backend->discover = NULL; backend->discover = NULL;
@@ -963,8 +967,9 @@ hwloc_backend_enable(struct hwloc_backend *backend)
/* check backend flags */ /* check backend flags */
if (backend->flags) { if (backend->flags) {
fprintf(stderr, "Cannot enable discovery component `%s' phases 0x%x with unknown flags %lx\n", if (hwloc_hide_errors() < 2)
backend->component->name, backend->component->phases, backend->flags); fprintf(stderr, "hwloc: Cannot enable discovery component `%s' phases 0x%x with unknown flags %lx\n",
backend->component->name, backend->component->phases, backend->flags);
return -1; return -1;
} }
@@ -973,7 +978,7 @@ hwloc_backend_enable(struct hwloc_backend *backend)
while (NULL != *pprev) { while (NULL != *pprev) {
if ((*pprev)->component == backend->component) { if ((*pprev)->component == backend->component) {
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Cannot enable discovery component `%s' phases 0x%x twice\n", fprintf(stderr, "hwloc: Cannot enable discovery component `%s' phases 0x%x twice\n",
backend->component->name, backend->component->phases); backend->component->name, backend->component->phases);
hwloc_backend_disable(backend); hwloc_backend_disable(backend);
errno = EBUSY; errno = EBUSY;
@@ -983,7 +988,7 @@ hwloc_backend_enable(struct hwloc_backend *backend)
} }
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Enabling discovery component `%s' with phases 0x%x (among 0x%x)\n", fprintf(stderr, "hwloc: Enabling discovery component `%s' with phases 0x%x (among 0x%x)\n",
backend->component->name, backend->phases, backend->component->phases); backend->component->name, backend->phases, backend->component->phases);
/* enqueue at the end */ /* enqueue at the end */
@@ -1067,7 +1072,7 @@ hwloc_backends_disable_all(struct hwloc_topology *topology)
while (NULL != (backend = topology->backends)) { while (NULL != (backend = topology->backends)) {
struct hwloc_backend *next = backend->next; struct hwloc_backend *next = backend->next;
if (hwloc_components_verbose) if (hwloc_components_verbose)
fprintf(stderr, "Disabling discovery component `%s'\n", fprintf(stderr, "hwloc: Disabling discovery component `%s'\n",
backend->component->name); backend->component->name);
hwloc_backend_disable(backend); hwloc_backend_disable(backend);
topology->backends = next; topology->backends = next;

View File

@@ -42,6 +42,9 @@ hwloc_internal_cpukinds_dup(hwloc_topology_t new, hwloc_topology_t old)
struct hwloc_internal_cpukind_s *kinds; struct hwloc_internal_cpukind_s *kinds;
unsigned i; unsigned i;
if (!old->nr_cpukinds)
return 0;
kinds = hwloc_tma_malloc(tma, old->nr_cpukinds * sizeof(*kinds)); kinds = hwloc_tma_malloc(tma, old->nr_cpukinds * sizeof(*kinds));
if (!kinds) if (!kinds)
return -1; return -1;
@@ -343,7 +346,8 @@ enum hwloc_cpukinds_ranking {
HWLOC_CPUKINDS_RANKING_DEFAULT, /* forced + frequency on ARM, forced + coretype_frequency otherwise */ HWLOC_CPUKINDS_RANKING_DEFAULT, /* forced + frequency on ARM, forced + coretype_frequency otherwise */
HWLOC_CPUKINDS_RANKING_NO_FORCED_EFFICIENCY, /* default without forced */ HWLOC_CPUKINDS_RANKING_NO_FORCED_EFFICIENCY, /* default without forced */
HWLOC_CPUKINDS_RANKING_FORCED_EFFICIENCY, HWLOC_CPUKINDS_RANKING_FORCED_EFFICIENCY,
HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY, HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY, /* either coretype or frequency or both */
HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY_STRICT, /* both coretype and frequency are required */
HWLOC_CPUKINDS_RANKING_CORETYPE, HWLOC_CPUKINDS_RANKING_CORETYPE,
HWLOC_CPUKINDS_RANKING_FREQUENCY, HWLOC_CPUKINDS_RANKING_FREQUENCY,
HWLOC_CPUKINDS_RANKING_FREQUENCY_MAX, HWLOC_CPUKINDS_RANKING_FREQUENCY_MAX,
@@ -358,9 +362,9 @@ hwloc__cpukinds_try_rank_by_info(struct hwloc_topology *topology,
{ {
unsigned i; unsigned i;
if (HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY == heuristics) { if (HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY_STRICT == heuristics) {
hwloc_debug("Trying to rank cpukinds by coretype+frequency...\n"); hwloc_debug("Trying to rank cpukinds by coretype+frequency_strict...\n");
/* we need intel_core_type + (base or max freq) for all kinds */ /* we need intel_core_type AND (base or max freq) for all kinds */
if (!summary->have_intel_core_type if (!summary->have_intel_core_type
|| (!summary->have_max_freq && !summary->have_base_freq)) || (!summary->have_max_freq && !summary->have_base_freq))
return -1; return -1;
@@ -373,6 +377,21 @@ hwloc__cpukinds_try_rank_by_info(struct hwloc_topology *topology,
kind->ranking_value = (summary->summaries[i].intel_core_type << 20) + summary->summaries[i].max_freq; kind->ranking_value = (summary->summaries[i].intel_core_type << 20) + summary->summaries[i].max_freq;
} }
} else if (HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY == heuristics) {
hwloc_debug("Trying to rank cpukinds by coretype+frequency...\n");
/* we need intel_core_type OR (base or max freq) for all kinds */
if (!summary->have_intel_core_type
&& (!summary->have_max_freq && !summary->have_base_freq))
return -1;
/* rank first by coretype (Core>>Atom) then by frequency, base if available, max otherwise */
for(i=0; i<topology->nr_cpukinds; i++) {
struct hwloc_internal_cpukind_s *kind = &topology->cpukinds[i];
if (summary->have_base_freq)
kind->ranking_value = (summary->summaries[i].intel_core_type << 20) + summary->summaries[i].base_freq;
else
kind->ranking_value = (summary->summaries[i].intel_core_type << 20) + summary->summaries[i].max_freq;
}
} else if (HWLOC_CPUKINDS_RANKING_CORETYPE == heuristics) { } else if (HWLOC_CPUKINDS_RANKING_CORETYPE == heuristics) {
hwloc_debug("Trying to rank cpukinds by coretype...\n"); hwloc_debug("Trying to rank cpukinds by coretype...\n");
/* we need intel_core_type */ /* we need intel_core_type */
@@ -429,7 +448,9 @@ static int hwloc__cpukinds_compare_ranking_values(const void *_a, const void *_b
{ {
const struct hwloc_internal_cpukind_s *a = _a; const struct hwloc_internal_cpukind_s *a = _a;
const struct hwloc_internal_cpukind_s *b = _b; const struct hwloc_internal_cpukind_s *b = _b;
return a->ranking_value - b->ranking_value; uint64_t arv = a->ranking_value;
uint64_t brv = b->ranking_value;
return arv < brv ? -1 : arv > brv ? 1 : 0;
} }
/* this function requires ranking values to be unique */ /* this function requires ranking values to be unique */
@@ -469,6 +490,8 @@ hwloc_internal_cpukinds_rank(struct hwloc_topology *topology)
heuristics = HWLOC_CPUKINDS_RANKING_NONE; heuristics = HWLOC_CPUKINDS_RANKING_NONE;
else if (!strcmp(env, "coretype+frequency")) else if (!strcmp(env, "coretype+frequency"))
heuristics = HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY; heuristics = HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY;
else if (!strcmp(env, "coretype+frequency_strict"))
heuristics = HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY_STRICT;
else if (!strcmp(env, "coretype")) else if (!strcmp(env, "coretype"))
heuristics = HWLOC_CPUKINDS_RANKING_CORETYPE; heuristics = HWLOC_CPUKINDS_RANKING_CORETYPE;
else if (!strcmp(env, "frequency")) else if (!strcmp(env, "frequency"))
@@ -481,16 +504,14 @@ hwloc_internal_cpukinds_rank(struct hwloc_topology *topology)
heuristics = HWLOC_CPUKINDS_RANKING_FORCED_EFFICIENCY; heuristics = HWLOC_CPUKINDS_RANKING_FORCED_EFFICIENCY;
else if (!strcmp(env, "no_forced_efficiency")) else if (!strcmp(env, "no_forced_efficiency"))
heuristics = HWLOC_CPUKINDS_RANKING_NO_FORCED_EFFICIENCY; heuristics = HWLOC_CPUKINDS_RANKING_NO_FORCED_EFFICIENCY;
else if (!hwloc_hide_errors()) else if (hwloc_hide_errors() < 2)
fprintf(stderr, "Failed to recognize HWLOC_CPUKINDS_RANKING value %s\n", env); fprintf(stderr, "hwloc: Failed to recognize HWLOC_CPUKINDS_RANKING value %s\n", env);
} }
if (heuristics == HWLOC_CPUKINDS_RANKING_DEFAULT if (heuristics == HWLOC_CPUKINDS_RANKING_DEFAULT
|| heuristics == HWLOC_CPUKINDS_RANKING_NO_FORCED_EFFICIENCY) { || heuristics == HWLOC_CPUKINDS_RANKING_NO_FORCED_EFFICIENCY) {
/* default is forced_efficiency first */ /* default is forced_efficiency first */
struct hwloc_cpukinds_info_summary summary; struct hwloc_cpukinds_info_summary summary;
enum hwloc_cpukinds_ranking subheuristics;
const char *arch;
if (heuristics == HWLOC_CPUKINDS_RANKING_DEFAULT) if (heuristics == HWLOC_CPUKINDS_RANKING_DEFAULT)
hwloc_debug("Using default ranking strategy...\n"); hwloc_debug("Using default ranking strategy...\n");
@@ -508,16 +529,7 @@ hwloc_internal_cpukinds_rank(struct hwloc_topology *topology)
goto failed; goto failed;
hwloc__cpukinds_summarize_info(topology, &summary); hwloc__cpukinds_summarize_info(topology, &summary);
arch = hwloc_obj_get_info_by_name(topology->levels[0][0], "Architecture"); err = hwloc__cpukinds_try_rank_by_info(topology, HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY, &summary);
/* TODO: rather coretype_frequency only on x86/Intel? */
if (arch && (!strncmp(arch, "arm", 3) || !strncmp(arch, "aarch", 5)))
/* then frequency on ARM */
subheuristics = HWLOC_CPUKINDS_RANKING_FREQUENCY;
else
/* or coretype+frequency otherwise */
subheuristics = HWLOC_CPUKINDS_RANKING_CORETYPE_FREQUENCY;
err = hwloc__cpukinds_try_rank_by_info(topology, subheuristics, &summary);
free(summary.summaries); free(summary.summaries);
if (!err) if (!err)
goto ready; goto ready;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2010-2020 Inria. All rights reserved. * Copyright © 2010-2021 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.
@@ -17,6 +17,37 @@
static struct hwloc_internal_distances_s * static struct hwloc_internal_distances_s *
hwloc__internal_distances_from_public(hwloc_topology_t topology, struct hwloc_distances_s *distances); hwloc__internal_distances_from_public(hwloc_topology_t topology, struct hwloc_distances_s *distances);
static void
hwloc__groups_by_distances(struct hwloc_topology *topology, unsigned nbobjs, struct hwloc_obj **objs, uint64_t *values, unsigned long kind, unsigned nbaccuracies, float *accuracies, int needcheck);
static void
hwloc_internal_distances_restrict(hwloc_obj_t *objs,
uint64_t *indexes,
hwloc_obj_type_t *different_types,
uint64_t *values,
unsigned nbobjs, unsigned disappeared);
static void
hwloc_internal_distances_print_matrix(struct hwloc_internal_distances_s *dist)
{
unsigned nbobjs = dist->nbobjs;
hwloc_obj_t *objs = dist->objs;
hwloc_uint64_t *values = dist->values;
int gp = !HWLOC_DIST_TYPE_USE_OS_INDEX(dist->unique_type);
unsigned i, j;
fprintf(stderr, "%s", gp ? "gp_index" : "os_index");
for(j=0; j<nbobjs; j++)
fprintf(stderr, " % 5d", (int)(gp ? objs[j]->gp_index : objs[j]->os_index));
fprintf(stderr, "\n");
for(i=0; i<nbobjs; i++) {
fprintf(stderr, " % 5d", (int)(gp ? objs[i]->gp_index : objs[i]->os_index));
for(j=0; j<nbobjs; j++)
fprintf(stderr, " % 5lld", (long long) values[i*nbobjs + j]);
fprintf(stderr, "\n");
}
}
/****************************************************** /******************************************************
* Global init, prepare, destroy, dup * Global init, prepare, destroy, dup
*/ */
@@ -244,27 +275,33 @@ int hwloc_distances_release_remove(hwloc_topology_t topology,
return 0; return 0;
} }
/****************************************************** /*********************************************************
* Add distances to the topology * Backend functions for adding distances to the topology
*/ */
/* cancel a distances handle. only needed internally for now */
static void static void
hwloc__groups_by_distances(struct hwloc_topology *topology, unsigned nbobjs, struct hwloc_obj **objs, uint64_t *values, unsigned long kind, unsigned nbaccuracies, float *accuracies, int needcheck); hwloc_backend_distances_add__cancel(struct hwloc_internal_distances_s *dist)
{
/* everything is set to NULL in hwloc_backend_distances_add_create() */
free(dist->name);
free(dist->indexes);
free(dist->objs);
free(dist->different_types);
free(dist->values);
free(dist);
}
/* insert a distance matrix in the topology. /* prepare a distances handle for later commit in the topology.
* the caller gives us the distances and objs pointers, we'll free them later. * we duplicate the caller's name.
*/ */
static int hwloc_backend_distances_add_handle_t
hwloc_internal_distances__add(hwloc_topology_t topology, const char *name, hwloc_backend_distances_add_create(hwloc_topology_t topology,
hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types, const char *name, unsigned long kind, unsigned long flags)
unsigned nbobjs, hwloc_obj_t *objs, uint64_t *indexes, uint64_t *values,
unsigned long kind, unsigned iflags)
{ {
struct hwloc_internal_distances_s *dist; struct hwloc_internal_distances_s *dist;
if (different_types) { if (flags) {
kind |= HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES; /* the user isn't forced to give it */
} else if (kind & HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES) {
errno = EINVAL; errno = EINVAL;
goto err; goto err;
} }
@@ -273,110 +310,54 @@ hwloc_internal_distances__add(hwloc_topology_t topology, const char *name,
if (!dist) if (!dist)
goto err; goto err;
if (name) if (name) {
dist->name = strdup(name); /* ignore failure */ dist->name = strdup(name); /* ignore failure */
if (!dist->name)
dist->unique_type = unique_type;
dist->different_types = different_types;
dist->nbobjs = nbobjs;
dist->kind = kind;
dist->iflags = iflags;
assert(!!(iflags & HWLOC_INTERNAL_DIST_FLAG_OBJS_VALID) == !!objs);
if (!objs) {
assert(indexes);
/* we only have indexes, we'll refresh objs from there */
dist->indexes = indexes;
dist->objs = calloc(nbobjs, sizeof(hwloc_obj_t));
if (!dist->objs)
goto err_with_dist; goto err_with_dist;
} else {
unsigned i;
assert(!indexes);
/* we only have objs, generate the indexes arrays so that we can refresh objs later */
dist->objs = objs;
dist->indexes = malloc(nbobjs * sizeof(*dist->indexes));
if (!dist->indexes)
goto err_with_dist;
if (HWLOC_DIST_TYPE_USE_OS_INDEX(dist->unique_type)) {
for(i=0; i<nbobjs; i++)
dist->indexes[i] = objs[i]->os_index;
} else {
for(i=0; i<nbobjs; i++)
dist->indexes[i] = objs[i]->gp_index;
}
} }
dist->values = values; dist->kind = kind;
dist->iflags = HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED;
dist->unique_type = HWLOC_OBJ_TYPE_NONE;
dist->different_types = NULL;
dist->nbobjs = 0;
dist->indexes = NULL;
dist->objs = NULL;
dist->values = NULL;
dist->id = topology->next_dist_id++; dist->id = topology->next_dist_id++;
return dist;
if (topology->last_dist)
topology->last_dist->next = dist;
else
topology->first_dist = dist;
dist->prev = topology->last_dist;
dist->next = NULL;
topology->last_dist = dist;
return 0;
err_with_dist: err_with_dist:
if (name) hwloc_backend_distances_add__cancel(dist);
free(dist->name);
free(dist);
err: err:
free(different_types); return NULL;
free(objs);
free(indexes);
free(values);
return -1;
} }
int hwloc_internal_distances_add_by_index(hwloc_topology_t topology, const char *name, /* attach objects and values to a distances handle.
hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types, unsigned nbobjs, uint64_t *indexes, uint64_t *values, * on success, objs and values arrays are attached and will be freed with the distances.
unsigned long kind, unsigned long flags) * on failure, the handle is freed.
*/
int
hwloc_backend_distances_add_values(hwloc_topology_t topology __hwloc_attribute_unused,
hwloc_backend_distances_add_handle_t handle,
unsigned nbobjs, hwloc_obj_t *objs,
hwloc_uint64_t *values,
unsigned long flags)
{ {
unsigned iflags = 0; /* objs not valid */ struct hwloc_internal_distances_s *dist = handle;
hwloc_obj_type_t unique_type, *different_types = NULL;
if (nbobjs < 2) { hwloc_uint64_t *indexes = NULL;
errno = EINVAL;
goto err;
}
/* cannot group without objects,
* and we don't group from XML anyway since the hwloc that generated the XML should have grouped already.
*/
if (flags & HWLOC_DISTANCES_ADD_FLAG_GROUP) {
errno = EINVAL;
goto err;
}
return hwloc_internal_distances__add(topology, name, unique_type, different_types, nbobjs, NULL, indexes, values, kind, iflags);
err:
free(indexes);
free(values);
free(different_types);
return -1;
}
static void
hwloc_internal_distances_restrict(hwloc_obj_t *objs,
uint64_t *indexes,
uint64_t *values,
unsigned nbobjs, unsigned disappeared);
int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
unsigned nbobjs, hwloc_obj_t *objs, uint64_t *values,
unsigned long kind, unsigned long flags)
{
hwloc_obj_type_t unique_type, *different_types;
unsigned i, disappeared = 0; unsigned i, disappeared = 0;
unsigned iflags = HWLOC_INTERNAL_DIST_FLAG_OBJS_VALID;
if (nbobjs < 2) { if (dist->nbobjs || !(dist->iflags & HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED)) {
/* target distances is already set */
errno = EINVAL;
goto err;
}
if (flags || nbobjs < 2 || !objs || !values) {
errno = EINVAL; errno = EINVAL;
goto err; goto err;
} }
@@ -389,15 +370,18 @@ int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
/* some objects are NULL */ /* some objects are NULL */
if (disappeared == nbobjs) { if (disappeared == nbobjs) {
/* nothing left, drop the matrix */ /* nothing left, drop the matrix */
free(objs); errno = ENOENT;
free(values); goto err;
return 0;
} }
/* restrict the matrix */ /* restrict the matrix */
hwloc_internal_distances_restrict(objs, NULL, values, nbobjs, disappeared); hwloc_internal_distances_restrict(objs, NULL, NULL, values, nbobjs, disappeared);
nbobjs -= disappeared; nbobjs -= disappeared;
} }
indexes = malloc(nbobjs * sizeof(*indexes));
if (!indexes)
goto err;
unique_type = objs[0]->type; unique_type = objs[0]->type;
for(i=1; i<nbobjs; i++) for(i=1; i<nbobjs; i++)
if (objs[i]->type != unique_type) { if (objs[i]->type != unique_type) {
@@ -408,16 +392,108 @@ int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
/* heterogeneous types */ /* heterogeneous types */
different_types = malloc(nbobjs * sizeof(*different_types)); different_types = malloc(nbobjs * sizeof(*different_types));
if (!different_types) if (!different_types)
goto err; goto err_with_indexes;
for(i=0; i<nbobjs; i++) for(i=0; i<nbobjs; i++)
different_types[i] = objs[i]->type; different_types[i] = objs[i]->type;
} else {
/* homogeneous types */
different_types = NULL;
} }
if (topology->grouping && (flags & HWLOC_DISTANCES_ADD_FLAG_GROUP) && !different_types) { dist->nbobjs = nbobjs;
dist->objs = objs;
dist->iflags |= HWLOC_INTERNAL_DIST_FLAG_OBJS_VALID;
dist->indexes = indexes;
dist->unique_type = unique_type;
dist->different_types = different_types;
dist->values = values;
if (different_types)
dist->kind |= HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES;
if (HWLOC_DIST_TYPE_USE_OS_INDEX(dist->unique_type)) {
for(i=0; i<nbobjs; i++)
dist->indexes[i] = objs[i]->os_index;
} else {
for(i=0; i<nbobjs; i++)
dist->indexes[i] = objs[i]->gp_index;
}
return 0;
err_with_indexes:
free(indexes);
err:
hwloc_backend_distances_add__cancel(dist);
return -1;
}
/* attach objects and values to a distance handle.
* on success, objs and values arrays are attached and will be freed with the distances.
* on failure, the handle is freed.
*/
static int
hwloc_backend_distances_add_values_by_index(hwloc_topology_t topology __hwloc_attribute_unused,
hwloc_backend_distances_add_handle_t handle,
unsigned nbobjs, hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types, hwloc_uint64_t *indexes,
hwloc_uint64_t *values)
{
struct hwloc_internal_distances_s *dist = handle;
hwloc_obj_t *objs;
if (dist->nbobjs || !(dist->iflags & HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED)) {
/* target distances is already set */
errno = EINVAL;
goto err;
}
if (nbobjs < 2 || !indexes || !values || (unique_type == HWLOC_OBJ_TYPE_NONE && !different_types)) {
errno = EINVAL;
goto err;
}
objs = malloc(nbobjs * sizeof(*objs));
if (!objs)
goto err;
dist->nbobjs = nbobjs;
dist->objs = objs;
dist->indexes = indexes;
dist->unique_type = unique_type;
dist->different_types = different_types;
dist->values = values;
if (different_types)
dist->kind |= HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES;
return 0;
err:
hwloc_backend_distances_add__cancel(dist);
return -1;
}
/* commit a distances handle.
* on failure, the handle is freed with its objects and values arrays.
*/
int
hwloc_backend_distances_add_commit(hwloc_topology_t topology,
hwloc_backend_distances_add_handle_t handle,
unsigned long flags)
{
struct hwloc_internal_distances_s *dist = handle;
if (!dist->nbobjs || !(dist->iflags & HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED)) {
/* target distances not ready for commit */
errno = EINVAL;
goto err;
}
if ((flags & HWLOC_DISTANCES_ADD_FLAG_GROUP) && !dist->objs) {
/* cannot group without objects,
* and we don't group from XML anyway since the hwloc that generated the XML should have grouped already.
*/
errno = EINVAL;
goto err;
}
if (topology->grouping && (flags & HWLOC_DISTANCES_ADD_FLAG_GROUP) && !dist->different_types) {
float full_accuracy = 0.f; float full_accuracy = 0.f;
float *accuracies; float *accuracies;
unsigned nbaccuracies; unsigned nbaccuracies;
@@ -431,26 +507,94 @@ int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
} }
if (topology->grouping_verbose) { if (topology->grouping_verbose) {
unsigned j;
int gp = !HWLOC_DIST_TYPE_USE_OS_INDEX(unique_type);
fprintf(stderr, "Trying to group objects using distance matrix:\n"); fprintf(stderr, "Trying to group objects using distance matrix:\n");
fprintf(stderr, "%s", gp ? "gp_index" : "os_index"); hwloc_internal_distances_print_matrix(dist);
for(j=0; j<nbobjs; j++)
fprintf(stderr, " % 5d", (int)(gp ? objs[j]->gp_index : objs[j]->os_index));
fprintf(stderr, "\n");
for(i=0; i<nbobjs; i++) {
fprintf(stderr, " % 5d", (int)(gp ? objs[i]->gp_index : objs[i]->os_index));
for(j=0; j<nbobjs; j++)
fprintf(stderr, " % 5lld", (long long) values[i*nbobjs + j]);
fprintf(stderr, "\n");
}
} }
hwloc__groups_by_distances(topology, nbobjs, objs, values, hwloc__groups_by_distances(topology, dist->nbobjs, dist->objs, dist->values,
kind, nbaccuracies, accuracies, 1 /* check the first matrice */); dist->kind, nbaccuracies, accuracies, 1 /* check the first matrix */);
} }
return hwloc_internal_distances__add(topology, name, unique_type, different_types, nbobjs, objs, NULL, values, kind, iflags); if (topology->last_dist)
topology->last_dist->next = dist;
else
topology->first_dist = dist;
dist->prev = topology->last_dist;
dist->next = NULL;
topology->last_dist = dist;
dist->iflags &= ~HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED;
return 0;
err:
hwloc_backend_distances_add__cancel(dist);
return -1;
}
/* all-in-one backend function not exported to plugins, only used by XML for now */
int hwloc_internal_distances_add_by_index(hwloc_topology_t topology, const char *name,
hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types, unsigned nbobjs, uint64_t *indexes, uint64_t *values,
unsigned long kind, unsigned long flags)
{
hwloc_backend_distances_add_handle_t handle;
int err;
handle = hwloc_backend_distances_add_create(topology, name, kind, 0);
if (!handle)
goto err;
err = hwloc_backend_distances_add_values_by_index(topology, handle,
nbobjs, unique_type, different_types, indexes,
values);
if (err < 0)
goto err;
/* arrays are now attached to the handle */
indexes = NULL;
different_types = NULL;
values = NULL;
err = hwloc_backend_distances_add_commit(topology, handle, flags);
if (err < 0)
goto err;
return 0;
err:
free(indexes);
free(different_types);
free(values);
return -1;
}
/* all-in-one backend function not exported to plugins, used by OS backends */
int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
unsigned nbobjs, hwloc_obj_t *objs, uint64_t *values,
unsigned long kind, unsigned long flags)
{
hwloc_backend_distances_add_handle_t handle;
int err;
handle = hwloc_backend_distances_add_create(topology, name, kind, 0);
if (!handle)
goto err;
err = hwloc_backend_distances_add_values(topology, handle,
nbobjs, objs,
values,
0);
if (err < 0)
goto err;
/* arrays are now attached to the handle */
objs = NULL;
values = NULL;
err = hwloc_backend_distances_add_commit(topology, handle, flags);
if (err < 0)
goto err;
return 0;
err: err:
free(objs); free(objs);
@@ -458,44 +602,54 @@ int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
return -1; return -1;
} }
/********************************
* User API for adding distances
*/
#define HWLOC_DISTANCES_KIND_FROM_ALL (HWLOC_DISTANCES_KIND_FROM_OS|HWLOC_DISTANCES_KIND_FROM_USER) #define HWLOC_DISTANCES_KIND_FROM_ALL (HWLOC_DISTANCES_KIND_FROM_OS|HWLOC_DISTANCES_KIND_FROM_USER)
#define HWLOC_DISTANCES_KIND_MEANS_ALL (HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH) #define HWLOC_DISTANCES_KIND_MEANS_ALL (HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH)
#define HWLOC_DISTANCES_KIND_ALL (HWLOC_DISTANCES_KIND_FROM_ALL|HWLOC_DISTANCES_KIND_MEANS_ALL) #define HWLOC_DISTANCES_KIND_ALL (HWLOC_DISTANCES_KIND_FROM_ALL|HWLOC_DISTANCES_KIND_MEANS_ALL|HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES)
#define HWLOC_DISTANCES_ADD_FLAG_ALL (HWLOC_DISTANCES_ADD_FLAG_GROUP|HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE) #define HWLOC_DISTANCES_ADD_FLAG_ALL (HWLOC_DISTANCES_ADD_FLAG_GROUP|HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE)
/* The actual function exported to the user void * hwloc_distances_add_create(hwloc_topology_t topology,
*/ const char *name, unsigned long kind,
int hwloc_distances_add(hwloc_topology_t topology, unsigned long flags)
unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values, {
unsigned long kind, unsigned long flags) if (!topology->is_loaded) {
errno = EINVAL;
return NULL;
}
if (topology->adopted_shmem_addr) {
errno = EPERM;
return NULL;
}
if ((kind & ~HWLOC_DISTANCES_KIND_ALL)
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_FROM_ALL) != 1
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_MEANS_ALL) != 1) {
errno = EINVAL;
return NULL;
}
return hwloc_backend_distances_add_create(topology, name, kind, flags);
}
int hwloc_distances_add_values(hwloc_topology_t topology,
void *handle,
unsigned nbobjs, hwloc_obj_t *objs,
hwloc_uint64_t *values,
unsigned long flags)
{ {
unsigned i; unsigned i;
uint64_t *_values; uint64_t *_values;
hwloc_obj_t *_objs; hwloc_obj_t *_objs;
int err; int err;
if (nbobjs < 2 || !objs || !values || !topology->is_loaded) {
errno = EINVAL;
return -1;
}
if (topology->adopted_shmem_addr) {
errno = EPERM;
return -1;
}
if ((kind & ~HWLOC_DISTANCES_KIND_ALL)
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_FROM_ALL) != 1
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_MEANS_ALL) != 1
|| (flags & ~HWLOC_DISTANCES_ADD_FLAG_ALL)) {
errno = EINVAL;
return -1;
}
/* no strict need to check for duplicates, things shouldn't break */ /* no strict need to check for duplicates, things shouldn't break */
for(i=1; i<nbobjs; i++) for(i=1; i<nbobjs; i++)
if (!objs[i]) { if (!objs[i]) {
errno = EINVAL; errno = EINVAL;
return -1; goto out;
} }
/* copy the input arrays and give them to the topology */ /* copy the input arrays and give them to the topology */
@@ -506,22 +660,78 @@ int hwloc_distances_add(hwloc_topology_t topology,
memcpy(_objs, objs, nbobjs*sizeof(hwloc_obj_t)); memcpy(_objs, objs, nbobjs*sizeof(hwloc_obj_t));
memcpy(_values, values, nbobjs*nbobjs*sizeof(*_values)); memcpy(_values, values, nbobjs*nbobjs*sizeof(*_values));
err = hwloc_internal_distances_add(topology, NULL, nbobjs, _objs, _values, kind, flags);
if (err < 0) err = hwloc_backend_distances_add_values(topology, handle, nbobjs, _objs, _values, flags);
goto out; /* _objs and _values freed in hwloc_internal_distances_add() */ if (err < 0) {
/* handle was canceled inside hwloc_backend_distances_add_values */
handle = NULL;
goto out_with_arrays;
}
return 0;
out_with_arrays:
free(_objs);
free(_values);
out:
if (handle)
hwloc_backend_distances_add__cancel(handle);
return -1;
}
int
hwloc_distances_add_commit(hwloc_topology_t topology,
void *handle,
unsigned long flags)
{
int err;
if (flags & ~HWLOC_DISTANCES_ADD_FLAG_ALL) {
errno = EINVAL;
goto out;
}
err = hwloc_backend_distances_add_commit(topology, handle, flags);
if (err < 0) {
/* handle was canceled inside hwloc_backend_distances_add_commit */
handle = NULL;
goto out;
}
/* in case we added some groups, see if we need to reconnect */ /* in case we added some groups, see if we need to reconnect */
hwloc_topology_reconnect(topology, 0); hwloc_topology_reconnect(topology, 0);
return 0; return 0;
out_with_arrays:
free(_values);
free(_objs);
out: out:
if (handle)
hwloc_backend_distances_add__cancel(handle);
return -1; return -1;
} }
/* deprecated all-in-one user function */
int hwloc_distances_add(hwloc_topology_t topology,
unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values,
unsigned long kind, unsigned long flags)
{
void *handle;
int err;
handle = hwloc_distances_add_create(topology, NULL, kind, 0);
if (!handle)
return -1;
err = hwloc_distances_add_values(topology, handle, nbobjs, objs, values, 0);
if (err < 0)
return -1;
err = hwloc_distances_add_commit(topology, handle, flags);
if (err < 0)
return -1;
return 0;
}
/****************************************************** /******************************************************
* Refresh objects in distances * Refresh objects in distances
*/ */
@@ -529,6 +739,7 @@ int hwloc_distances_add(hwloc_topology_t topology,
static void static void
hwloc_internal_distances_restrict(hwloc_obj_t *objs, hwloc_internal_distances_restrict(hwloc_obj_t *objs,
uint64_t *indexes, uint64_t *indexes,
hwloc_obj_type_t *different_types,
uint64_t *values, uint64_t *values,
unsigned nbobjs, unsigned disappeared) unsigned nbobjs, unsigned disappeared)
{ {
@@ -550,6 +761,8 @@ hwloc_internal_distances_restrict(hwloc_obj_t *objs,
objs[newi] = objs[i]; objs[newi] = objs[i];
if (indexes) if (indexes)
indexes[newi] = indexes[i]; indexes[newi] = indexes[i];
if (different_types)
different_types[newi] = different_types[i];
newi++; newi++;
} }
} }
@@ -594,7 +807,7 @@ hwloc_internal_distances_refresh_one(hwloc_topology_t topology,
return -1; return -1;
if (disappeared) { if (disappeared) {
hwloc_internal_distances_restrict(objs, dist->indexes, dist->values, nbobjs, disappeared); hwloc_internal_distances_restrict(objs, dist->indexes, dist->different_types, dist->values, nbobjs, disappeared);
dist->nbobjs -= disappeared; dist->nbobjs -= disappeared;
} }
@@ -1087,3 +1300,210 @@ hwloc__groups_by_distances(struct hwloc_topology *topology,
out_with_groupids: out_with_groupids:
free(groupids); free(groupids);
} }
static int
hwloc__distances_transform_remove_null(struct hwloc_distances_s *distances)
{
hwloc_uint64_t *values = distances->values;
hwloc_obj_t *objs = distances->objs;
unsigned i, nb, nbobjs = distances->nbobjs;
hwloc_obj_type_t unique_type;
for(i=0, nb=0; i<nbobjs; i++)
if (objs[i])
nb++;
if (nb < 2) {
errno = EINVAL;
return -1;
}
if (nb == nbobjs)
return 0;
hwloc_internal_distances_restrict(objs, NULL, NULL, values, nbobjs, nbobjs-nb);
distances->nbobjs = nb;
/* update HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES for convenience */
unique_type = objs[0]->type;
for(i=1; i<nb; i++)
if (objs[i]->type != unique_type) {
unique_type = HWLOC_OBJ_TYPE_NONE;
break;
}
if (unique_type == HWLOC_OBJ_TYPE_NONE)
distances->kind |= HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES;
else
distances->kind &= ~HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES;
return 0;
}
static int
hwloc__distances_transform_links(struct hwloc_distances_s *distances)
{
/* FIXME: we should look for the greatest common denominator
* but we just use the smallest positive value, that's enough for current use-cases.
* We'll return -1 in other cases.
*/
hwloc_uint64_t divider, *values = distances->values;
unsigned i, nbobjs = distances->nbobjs;
if (!(distances->kind & HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH)) {
errno = EINVAL;
return -1;
}
for(i=0; i<nbobjs; i++)
values[i*nbobjs+i] = 0;
/* find the smallest positive value */
divider = 0;
for(i=0; i<nbobjs*nbobjs; i++)
if (values[i] && (!divider || values[i] < divider))
divider = values[i];
if (!divider)
/* only zeroes? do nothing */
return 0;
/* check it divides all values */
for(i=0; i<nbobjs*nbobjs; i++)
if (values[i]%divider) {
errno = ENOENT;
return -1;
}
/* ok, now divide for real */
for(i=0; i<nbobjs*nbobjs; i++)
values[i] /= divider;
return 0;
}
static __hwloc_inline int is_nvswitch(hwloc_obj_t obj)
{
return obj && obj->subtype && !strcmp(obj->subtype, "NVSwitch");
}
static int
hwloc__distances_transform_merge_switch_ports(hwloc_topology_t topology,
struct hwloc_distances_s *distances)
{
struct hwloc_internal_distances_s *dist = hwloc__internal_distances_from_public(topology, distances);
hwloc_obj_t *objs = distances->objs;
hwloc_uint64_t *values = distances->values;
unsigned first, i, j, nbobjs = distances->nbobjs;
if (strcmp(dist->name, "NVLinkBandwidth")) {
errno = EINVAL;
return -1;
}
/* find the first port */
first = (unsigned) -1;
for(i=0; i<nbobjs; i++)
if (is_nvswitch(objs[i])) {
first = i;
break;
}
if (first == (unsigned)-1) {
errno = ENOENT;
return -1;
}
for(j=i+1; j<nbobjs; j++) {
if (is_nvswitch(objs[j])) {
/* another port, merge it */
unsigned k;
for(k=0; k<nbobjs; k++) {
if (k==i || k==j)
continue;
values[k*nbobjs+i] += values[k*nbobjs+j];
values[k*nbobjs+j] = 0;
values[i*nbobjs+k] += values[j*nbobjs+k];
values[j*nbobjs+k] = 0;
}
values[i*nbobjs+i] += values[j*nbobjs+j];
values[j*nbobjs+j] = 0;
}
/* the caller will also call REMOVE_NULL to remove other ports */
objs[j] = NULL;
}
return 0;
}
static int
hwloc__distances_transform_transitive_closure(hwloc_topology_t topology,
struct hwloc_distances_s *distances)
{
struct hwloc_internal_distances_s *dist = hwloc__internal_distances_from_public(topology, distances);
hwloc_obj_t *objs = distances->objs;
hwloc_uint64_t *values = distances->values;
unsigned nbobjs = distances->nbobjs;
unsigned i, j, k;
if (strcmp(dist->name, "NVLinkBandwidth")) {
errno = EINVAL;
return -1;
}
for(i=0; i<nbobjs; i++) {
hwloc_uint64_t bw_i2sw = 0;
if (is_nvswitch(objs[i]))
continue;
/* count our BW to the switch */
for(k=0; k<nbobjs; k++)
if (is_nvswitch(objs[k]))
bw_i2sw += values[i*nbobjs+k];
for(j=0; j<nbobjs; j++) {
hwloc_uint64_t bw_sw2j = 0;
if (i == j || is_nvswitch(objs[j]))
continue;
/* count our BW from the switch */
for(k=0; k<nbobjs; k++)
if (is_nvswitch(objs[k]))
bw_sw2j += values[k*nbobjs+j];
/* bandwidth from i to j is now min(i2sw,sw2j) */
values[i*nbobjs+j] = bw_i2sw > bw_sw2j ? bw_sw2j : bw_i2sw;
}
}
return 0;
}
int
hwloc_distances_transform(hwloc_topology_t topology,
struct hwloc_distances_s *distances,
enum hwloc_distances_transform_e transform,
void *transform_attr,
unsigned long flags)
{
if (flags || transform_attr) {
errno = EINVAL;
return -1;
}
switch (transform) {
case HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL:
return hwloc__distances_transform_remove_null(distances);
case HWLOC_DISTANCES_TRANSFORM_LINKS:
return hwloc__distances_transform_links(distances);
case HWLOC_DISTANCES_TRANSFORM_MERGE_SWITCH_PORTS:
{
int err;
err = hwloc__distances_transform_merge_switch_ports(topology, distances);
if (!err)
err = hwloc__distances_transform_remove_null(distances);
return err;
}
case HWLOC_DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE:
return hwloc__distances_transform_transitive_closure(topology, distances);
default:
errno = EINVAL;
return -1;
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2020 Inria. All rights reserved. * Copyright © 2020-2021 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -127,6 +127,8 @@ hwloc_internal_memattrs_dup(struct hwloc_topology *new, struct hwloc_topology *o
struct hwloc_internal_memattr_s *imattrs; struct hwloc_internal_memattr_s *imattrs;
hwloc_memattr_id_t id; hwloc_memattr_id_t id;
/* old->nr_memattrs is always > 0 thanks to default memattrs */
imattrs = hwloc_tma_malloc(tma, old->nr_memattrs * sizeof(*imattrs)); imattrs = hwloc_tma_malloc(tma, old->nr_memattrs * sizeof(*imattrs));
if (!imattrs) if (!imattrs)
return -1; return -1;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2021 Inria. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -146,8 +146,9 @@ hwloc_pci_discovery_prepare(struct hwloc_topology *topology)
} }
free(buffer); free(buffer);
} else { } else {
fprintf(stderr, "Ignoring HWLOC_PCI_LOCALITY file `%s' too large (%lu bytes)\n", if (hwloc_hide_errors() < 2)
env, (unsigned long) st.st_size); fprintf(stderr, "hwloc/pci: Ignoring HWLOC_PCI_LOCALITY file `%s' too large (%lu bytes)\n",
env, (unsigned long) st.st_size);
} }
} }
close(fd); close(fd);
@@ -206,8 +207,11 @@ hwloc_pci_traverse_print_cb(void * cbdata __hwloc_attribute_unused,
else else
hwloc_debug("%s Bridge [%04x:%04x]", busid, hwloc_debug("%s Bridge [%04x:%04x]", busid,
pcidev->attr->pcidev.vendor_id, pcidev->attr->pcidev.device_id); pcidev->attr->pcidev.vendor_id, pcidev->attr->pcidev.device_id);
hwloc_debug(" to %04x:[%02x:%02x]\n", if (pcidev->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI)
pcidev->attr->bridge.downstream.pci.domain, pcidev->attr->bridge.downstream.pci.secondary_bus, pcidev->attr->bridge.downstream.pci.subordinate_bus); hwloc_debug(" to %04x:[%02x:%02x]\n",
pcidev->attr->bridge.downstream.pci.domain, pcidev->attr->bridge.downstream.pci.secondary_bus, pcidev->attr->bridge.downstream.pci.subordinate_bus);
else
assert(0);
} else } else
hwloc_debug("%s Device [%04x:%04x (%04x:%04x) rev=%02x class=%04x]\n", busid, hwloc_debug("%s Device [%04x:%04x (%04x:%04x) rev=%02x class=%04x]\n", busid,
pcidev->attr->pcidev.vendor_id, pcidev->attr->pcidev.device_id, pcidev->attr->pcidev.vendor_id, pcidev->attr->pcidev.device_id,
@@ -251,11 +255,11 @@ hwloc_pci_compare_busids(struct hwloc_obj *a, struct hwloc_obj *b)
if (a->attr->pcidev.domain > b->attr->pcidev.domain) if (a->attr->pcidev.domain > b->attr->pcidev.domain)
return HWLOC_PCI_BUSID_HIGHER; return HWLOC_PCI_BUSID_HIGHER;
if (a->type == HWLOC_OBJ_BRIDGE if (a->type == HWLOC_OBJ_BRIDGE && a->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
&& b->attr->pcidev.bus >= a->attr->bridge.downstream.pci.secondary_bus && b->attr->pcidev.bus >= a->attr->bridge.downstream.pci.secondary_bus
&& b->attr->pcidev.bus <= a->attr->bridge.downstream.pci.subordinate_bus) && b->attr->pcidev.bus <= a->attr->bridge.downstream.pci.subordinate_bus)
return HWLOC_PCI_BUSID_SUPERSET; return HWLOC_PCI_BUSID_SUPERSET;
if (b->type == HWLOC_OBJ_BRIDGE if (b->type == HWLOC_OBJ_BRIDGE && b->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
&& a->attr->pcidev.bus >= b->attr->bridge.downstream.pci.secondary_bus && a->attr->pcidev.bus >= b->attr->bridge.downstream.pci.secondary_bus
&& a->attr->pcidev.bus <= b->attr->bridge.downstream.pci.subordinate_bus) && a->attr->pcidev.bus <= b->attr->bridge.downstream.pci.subordinate_bus)
return HWLOC_PCI_BUSID_INCLUDED; return HWLOC_PCI_BUSID_INCLUDED;
@@ -302,7 +306,7 @@ hwloc_pci_add_object(struct hwloc_obj *parent, struct hwloc_obj **parent_io_firs
new->next_sibling = *curp; new->next_sibling = *curp;
*curp = new; *curp = new;
new->parent = parent; new->parent = parent;
if (new->type == HWLOC_OBJ_BRIDGE) { if (new->type == HWLOC_OBJ_BRIDGE && new->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI) {
/* look at remaining siblings and move some below new */ /* look at remaining siblings and move some below new */
childp = &new->io_first_child; childp = &new->io_first_child;
curp = &new->next_sibling; curp = &new->next_sibling;
@@ -329,7 +333,7 @@ hwloc_pci_add_object(struct hwloc_obj *parent, struct hwloc_obj **parent_io_firs
} }
case HWLOC_PCI_BUSID_EQUAL: { case HWLOC_PCI_BUSID_EQUAL: {
static int reported = 0; static int reported = 0;
if (!reported && !hwloc_hide_errors()) { if (!reported && hwloc_hide_errors() < 2) {
fprintf(stderr, "*********************************************************\n"); fprintf(stderr, "*********************************************************\n");
fprintf(stderr, "* hwloc %s received invalid PCI information.\n", HWLOC_VERSION); fprintf(stderr, "* hwloc %s received invalid PCI information.\n", HWLOC_VERSION);
fprintf(stderr, "*\n"); fprintf(stderr, "*\n");
@@ -411,7 +415,7 @@ hwloc_pcidisc_add_hostbridges(struct hwloc_topology *topology,
dstnextp = &child->next_sibling; dstnextp = &child->next_sibling;
/* compute hostbridge secondary/subordinate buses */ /* compute hostbridge secondary/subordinate buses */
if (child->type == HWLOC_OBJ_BRIDGE if (child->type == HWLOC_OBJ_BRIDGE && child->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
&& child->attr->bridge.downstream.pci.subordinate_bus > current_subordinate) && child->attr->bridge.downstream.pci.subordinate_bus > current_subordinate)
current_subordinate = child->attr->bridge.downstream.pci.subordinate_bus; current_subordinate = child->attr->bridge.downstream.pci.subordinate_bus;
@@ -486,7 +490,8 @@ hwloc__pci_find_busid_parent(struct hwloc_topology *topology, struct hwloc_pcide
if (env) { if (env) {
static int reported = 0; static int reported = 0;
if (!topology->pci_has_forced_locality && !reported) { if (!topology->pci_has_forced_locality && !reported) {
fprintf(stderr, "Environment variable %s is deprecated, please use HWLOC_PCI_LOCALITY instead.\n", env); if (!hwloc_hide_errors())
fprintf(stderr, "hwloc/pci: Environment variable %s is deprecated, please use HWLOC_PCI_LOCALITY instead.\n", env);
reported = 1; reported = 1;
} }
if (*env) { if (*env) {
@@ -565,7 +570,7 @@ hwloc_pcidisc_tree_attach(struct hwloc_topology *topology, struct hwloc_obj *tre
assert(pciobj->type == HWLOC_OBJ_PCI_DEVICE assert(pciobj->type == HWLOC_OBJ_PCI_DEVICE
|| (pciobj->type == HWLOC_OBJ_BRIDGE && pciobj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI)); || (pciobj->type == HWLOC_OBJ_BRIDGE && pciobj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI));
if (obj->type == HWLOC_OBJ_BRIDGE) { if (obj->type == HWLOC_OBJ_BRIDGE && obj->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI) {
domain = obj->attr->bridge.downstream.pci.domain; domain = obj->attr->bridge.downstream.pci.domain;
bus_min = obj->attr->bridge.downstream.pci.secondary_bus; bus_min = obj->attr->bridge.downstream.pci.secondary_bus;
bus_max = obj->attr->bridge.downstream.pci.subordinate_bus; bus_max = obj->attr->bridge.downstream.pci.subordinate_bus;
@@ -805,13 +810,14 @@ hwloc_pcidisc_find_linkspeed(const unsigned char *config,
* PCIe Gen3 = 8 GT/s signal-rate per lane with 128/130 encoding = 1 GB/s data-rate per lane * PCIe Gen3 = 8 GT/s signal-rate per lane with 128/130 encoding = 1 GB/s data-rate per lane
* PCIe Gen4 = 16 GT/s signal-rate per lane with 128/130 encoding = 2 GB/s data-rate per lane * PCIe Gen4 = 16 GT/s signal-rate per lane with 128/130 encoding = 2 GB/s data-rate per lane
* PCIe Gen5 = 32 GT/s signal-rate per lane with 128/130 encoding = 4 GB/s data-rate per lane * PCIe Gen5 = 32 GT/s signal-rate per lane with 128/130 encoding = 4 GB/s data-rate per lane
* PCIe Gen6 = 64 GT/s signal-rate per lane with 128/130 encoding = 8 GB/s data-rate per lane
*/ */
/* lanespeed in Gbit/s */ /* lanespeed in Gbit/s */
if (speed <= 2) if (speed <= 2)
lanespeed = 2.5f * speed * 0.8f; lanespeed = 2.5f * speed * 0.8f;
else else
lanespeed = 8.0f * (1<<(speed-3)) * 128/130; /* assume Gen6 will be 64 GT/s and so on */ lanespeed = 8.0f * (1<<(speed-3)) * 128/130; /* assume Gen7 will be 128 GT/s and so on */
/* linkspeed in GB/s */ /* linkspeed in GB/s */
*linkspeed = lanespeed * width / 8; *linkspeed = lanespeed * width / 8;

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2021 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.
@@ -11,7 +11,9 @@
#include "private/autogen/config.h" #include "private/autogen/config.h"
#include "hwloc.h" #include "hwloc.h"
#include "hwloc/windows.h"
#include "private/private.h" #include "private/private.h"
#include "private/windows.h" /* must be before windows.h */
#include "private/debug.h" #include "private/debug.h"
#include <windows.h> #include <windows.h>
@@ -64,26 +66,6 @@ typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
# endif /* HAVE_RELATIONPROCESSORPACKAGE */ # endif /* HAVE_RELATIONPROCESSORPACKAGE */
#endif /* HAVE_LOGICAL_PROCESSOR_RELATIONSHIP */ #endif /* HAVE_LOGICAL_PROCESSOR_RELATIONSHIP */
#ifndef HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION
typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
ULONG_PTR ProcessorMask;
LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
_ANONYMOUS_UNION
union {
struct {
BYTE flags;
} ProcessorCore;
struct {
DWORD NodeNumber;
} NumaNode;
CACHE_DESCRIPTOR Cache;
ULONGLONG Reserved[2];
} DUMMYUNIONNAME;
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION;
#endif
/* Extended interface, for group support */
#ifndef HAVE_GROUP_AFFINITY #ifndef HAVE_GROUP_AFFINITY
typedef struct _GROUP_AFFINITY { typedef struct _GROUP_AFFINITY {
KAFFINITY Mask; KAFFINITY Mask;
@@ -92,35 +74,40 @@ typedef struct _GROUP_AFFINITY {
} GROUP_AFFINITY, *PGROUP_AFFINITY; } GROUP_AFFINITY, *PGROUP_AFFINITY;
#endif #endif
#ifndef HAVE_PROCESSOR_RELATIONSHIP /* always use our own structure because the EfficiencyClass field didn't exist before Win10 */
typedef struct HWLOC_PROCESSOR_RELATIONSHIP { typedef struct HWLOC_PROCESSOR_RELATIONSHIP {
BYTE Flags; BYTE Flags;
BYTE EfficiencyClass; /* for RelationProcessorCore, higher means greater performance but less efficiency, only available in Win10+ */ BYTE EfficiencyClass; /* for RelationProcessorCore, higher means greater performance but less efficiency */
BYTE Reserved[20]; BYTE Reserved[20];
WORD GroupCount; WORD GroupCount;
GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY]; GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY];
} PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP; } HWLOC_PROCESSOR_RELATIONSHIP;
#endif
#ifndef HAVE_NUMA_NODE_RELATIONSHIP /* always use our own structure because the GroupCount and GroupMasks fields didn't exist in some Win10 */
typedef struct _NUMA_NODE_RELATIONSHIP { typedef struct HWLOC_NUMA_NODE_RELATIONSHIP {
DWORD NodeNumber; DWORD NodeNumber;
BYTE Reserved[20]; BYTE Reserved[18];
GROUP_AFFINITY GroupMask; WORD GroupCount;
} NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP; _ANONYMOUS_UNION
#endif union {
GROUP_AFFINITY GroupMask;
GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY];
} DUMMYUNIONNAME;
} HWLOC_NUMA_NODE_RELATIONSHIP;
#ifndef HAVE_CACHE_RELATIONSHIP typedef struct HWLOC_CACHE_RELATIONSHIP {
typedef struct _CACHE_RELATIONSHIP {
BYTE Level; BYTE Level;
BYTE Associativity; BYTE Associativity;
WORD LineSize; WORD LineSize;
DWORD CacheSize; DWORD CacheSize;
PROCESSOR_CACHE_TYPE Type; PROCESSOR_CACHE_TYPE Type;
BYTE Reserved[20]; BYTE Reserved[18];
GROUP_AFFINITY GroupMask; WORD GroupCount;
} CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP; union {
#endif GROUP_AFFINITY GroupMask;
GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY];
} DUMMYUNIONNAME;
} HWLOC_CACHE_RELATIONSHIP;
#ifndef HAVE_PROCESSOR_GROUP_INFO #ifndef HAVE_PROCESSOR_GROUP_INFO
typedef struct _PROCESSOR_GROUP_INFO { typedef struct _PROCESSOR_GROUP_INFO {
@@ -140,20 +127,19 @@ typedef struct _GROUP_RELATIONSHIP {
} GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP; } GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP;
#endif #endif
#ifndef HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX /* always use our own structure because we need our own HWLOC_PROCESSOR/CACHE/NUMA_NODE_RELATIONSHIP */
typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { typedef struct HWLOC_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX {
LOGICAL_PROCESSOR_RELATIONSHIP Relationship; LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
DWORD Size; DWORD Size;
_ANONYMOUS_UNION _ANONYMOUS_UNION
union { union {
PROCESSOR_RELATIONSHIP Processor; HWLOC_PROCESSOR_RELATIONSHIP Processor;
NUMA_NODE_RELATIONSHIP NumaNode; HWLOC_NUMA_NODE_RELATIONSHIP NumaNode;
CACHE_RELATIONSHIP Cache; HWLOC_CACHE_RELATIONSHIP Cache;
GROUP_RELATIONSHIP Group; GROUP_RELATIONSHIP Group;
/* Odd: no member to tell the cpu mask of the package... */ /* Odd: no member to tell the cpu mask of the package... */
} DUMMYUNIONNAME; } DUMMYUNIONNAME;
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX; } HWLOC_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
#endif
#ifndef HAVE_PSAPI_WORKING_SET_EX_BLOCK #ifndef HAVE_PSAPI_WORKING_SET_EX_BLOCK
typedef union _PSAPI_WORKING_SET_EX_BLOCK { typedef union _PSAPI_WORKING_SET_EX_BLOCK {
@@ -190,9 +176,6 @@ typedef struct _PROCESSOR_NUMBER {
typedef WORD (WINAPI *PFN_GETACTIVEPROCESSORGROUPCOUNT)(void); typedef WORD (WINAPI *PFN_GETACTIVEPROCESSORGROUPCOUNT)(void);
static PFN_GETACTIVEPROCESSORGROUPCOUNT GetActiveProcessorGroupCountProc; static PFN_GETACTIVEPROCESSORGROUPCOUNT GetActiveProcessorGroupCountProc;
static unsigned long nr_processor_groups = 1;
static unsigned long max_numanode_index = 0;
typedef WORD (WINAPI *PFN_GETACTIVEPROCESSORCOUNT)(WORD); typedef WORD (WINAPI *PFN_GETACTIVEPROCESSORCOUNT)(WORD);
static PFN_GETACTIVEPROCESSORCOUNT GetActiveProcessorCountProc; static PFN_GETACTIVEPROCESSORCOUNT GetActiveProcessorCountProc;
@@ -202,10 +185,7 @@ static PFN_GETCURRENTPROCESSORNUMBER GetCurrentProcessorNumberProc;
typedef VOID (WINAPI *PFN_GETCURRENTPROCESSORNUMBEREX)(PPROCESSOR_NUMBER); typedef VOID (WINAPI *PFN_GETCURRENTPROCESSORNUMBEREX)(PPROCESSOR_NUMBER);
static PFN_GETCURRENTPROCESSORNUMBEREX GetCurrentProcessorNumberExProc; static PFN_GETCURRENTPROCESSORNUMBEREX GetCurrentProcessorNumberExProc;
typedef BOOL (WINAPI *PFN_GETLOGICALPROCESSORINFORMATION)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, PDWORD ReturnLength); typedef BOOL (WINAPI *PFN_GETLOGICALPROCESSORINFORMATIONEX)(LOGICAL_PROCESSOR_RELATIONSHIP relationship, HWLOC_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *Buffer, PDWORD ReturnLength);
static PFN_GETLOGICALPROCESSORINFORMATION GetLogicalProcessorInformationProc;
typedef BOOL (WINAPI *PFN_GETLOGICALPROCESSORINFORMATIONEX)(LOGICAL_PROCESSOR_RELATIONSHIP relationship, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, PDWORD ReturnLength);
static PFN_GETLOGICALPROCESSORINFORMATIONEX GetLogicalProcessorInformationExProc; static PFN_GETLOGICALPROCESSORINFORMATIONEX GetLogicalProcessorInformationExProc;
typedef BOOL (WINAPI *PFN_SETTHREADGROUPAFFINITY)(HANDLE hThread, const GROUP_AFFINITY *GroupAffinity, PGROUP_AFFINITY PreviousGroupAffinity); typedef BOOL (WINAPI *PFN_SETTHREADGROUPAFFINITY)(HANDLE hThread, const GROUP_AFFINITY *GroupAffinity, PGROUP_AFFINITY PreviousGroupAffinity);
@@ -246,8 +226,6 @@ static void hwloc_win_get_function_ptrs(void)
(PFN_GETACTIVEPROCESSORGROUPCOUNT) GetProcAddress(kernel32, "GetActiveProcessorGroupCount"); (PFN_GETACTIVEPROCESSORGROUPCOUNT) GetProcAddress(kernel32, "GetActiveProcessorGroupCount");
GetActiveProcessorCountProc = GetActiveProcessorCountProc =
(PFN_GETACTIVEPROCESSORCOUNT) GetProcAddress(kernel32, "GetActiveProcessorCount"); (PFN_GETACTIVEPROCESSORCOUNT) GetProcAddress(kernel32, "GetActiveProcessorCount");
GetLogicalProcessorInformationProc =
(PFN_GETLOGICALPROCESSORINFORMATION) GetProcAddress(kernel32, "GetLogicalProcessorInformation");
GetCurrentProcessorNumberProc = GetCurrentProcessorNumberProc =
(PFN_GETCURRENTPROCESSORNUMBER) GetProcAddress(kernel32, "GetCurrentProcessorNumber"); (PFN_GETCURRENTPROCESSORNUMBER) GetProcAddress(kernel32, "GetCurrentProcessorNumber");
GetCurrentProcessorNumberExProc = GetCurrentProcessorNumberExProc =
@@ -270,9 +248,6 @@ static void hwloc_win_get_function_ptrs(void)
(PFN_VIRTUALFREEEX) GetProcAddress(kernel32, "VirtualFreeEx"); (PFN_VIRTUALFREEEX) GetProcAddress(kernel32, "VirtualFreeEx");
} }
if (GetActiveProcessorGroupCountProc)
nr_processor_groups = GetActiveProcessorGroupCountProc();
if (!QueryWorkingSetExProc) { if (!QueryWorkingSetExProc) {
HMODULE psapi = LoadLibrary("psapi.dll"); HMODULE psapi = LoadLibrary("psapi.dll");
if (psapi) if (psapi)
@@ -363,6 +338,173 @@ static int hwloc_bitmap_to_single_ULONG_PTR(hwloc_const_bitmap_t set, unsigned *
return 0; return 0;
} }
/**********************
* Processor Groups
*/
static unsigned long max_numanode_index = 0;
static unsigned long nr_processor_groups = 1;
static hwloc_cpuset_t * processor_group_cpusets = NULL;
static void
hwloc_win_get_processor_groups(void)
{
HWLOC_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *procInfoTotal, *tmpprocInfoTotal, *procInfo;
DWORD length;
unsigned i;
hwloc_debug("querying windows processor groups\n");
if (!GetLogicalProcessorInformationExProc)
goto error;
nr_processor_groups = GetActiveProcessorGroupCountProc();
if (!nr_processor_groups)
goto error;
hwloc_debug("found %lu windows processor groups\n", nr_processor_groups);
if (nr_processor_groups > 1 && SIZEOF_VOID_P == 4) {
if (!hwloc_hide_errors())
fprintf(stderr, "hwloc: multiple processor groups found on 32bits Windows, topology may be invalid/incomplete.\n");
}
length = 0;
procInfoTotal = NULL;
while (1) {
if (GetLogicalProcessorInformationExProc(RelationGroup, procInfoTotal, &length))
break;
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto error;
tmpprocInfoTotal = realloc(procInfoTotal, length);
if (!tmpprocInfoTotal)
goto error_with_procinfo;
procInfoTotal = tmpprocInfoTotal;
}
processor_group_cpusets = calloc(nr_processor_groups, sizeof(*processor_group_cpusets));
if (!processor_group_cpusets)
goto error_with_procinfo;
for (procInfo = procInfoTotal;
(void*) procInfo < (void*) ((uintptr_t) procInfoTotal + length);
procInfo = (void*) ((uintptr_t) procInfo + procInfo->Size)) {
unsigned id;
assert(procInfo->Relationship == RelationGroup);
hwloc_debug("Found %u active windows processor groups\n",
(unsigned) procInfo->Group.ActiveGroupCount);
for (id = 0; id < procInfo->Group.ActiveGroupCount; id++) {
KAFFINITY mask;
hwloc_bitmap_t set;
set = hwloc_bitmap_alloc();
if (!set)
goto error_with_cpusets;
mask = procInfo->Group.GroupInfo[id].ActiveProcessorMask;
hwloc_debug("group %u with %u cpus mask 0x%llx\n", id,
(unsigned) procInfo->Group.GroupInfo[id].ActiveProcessorCount, (unsigned long long) mask);
/* KAFFINITY is ULONG_PTR */
hwloc_bitmap_set_ith_ULONG_PTR(set, id, mask);
/* FIXME: what if running 32bits on a 64bits windows with 64-processor groups?
* ULONG_PTR is 32bits, so half the group is invisible?
* maybe scale id to id*8/sizeof(ULONG_PTR) so that groups are 64-PU aligned?
*/
hwloc_debug_2args_bitmap("group %u %d bitmap %s\n", id, procInfo->Group.GroupInfo[id].ActiveProcessorCount, set);
processor_group_cpusets[id] = set;
}
}
free(procInfoTotal);
return;
error_with_cpusets:
for(i=0; i<nr_processor_groups; i++) {
if (processor_group_cpusets[i])
hwloc_bitmap_free(processor_group_cpusets[i]);
}
free(processor_group_cpusets);
processor_group_cpusets = NULL;
error_with_procinfo:
free(procInfoTotal);
error:
/* on error set nr to 1 and keep cpusets NULL. We'll use the topology cpuset whenever needed */
nr_processor_groups = 1;
}
static void
hwloc_win_free_processor_groups(void)
{
unsigned i;
for(i=0; i<nr_processor_groups; i++) {
if (processor_group_cpusets[i])
hwloc_bitmap_free(processor_group_cpusets[i]);
}
free(processor_group_cpusets);
processor_group_cpusets = NULL;
nr_processor_groups = 1;
}
int
hwloc_windows_get_nr_processor_groups(hwloc_topology_t topology, unsigned long flags)
{
if (!topology->is_loaded || !topology->is_thissystem) {
errno = EINVAL;
return -1;
}
if (flags) {
errno = EINVAL;
return -1;
}
return nr_processor_groups;
}
int
hwloc_windows_get_processor_group_cpuset(hwloc_topology_t topology, unsigned pg_index, hwloc_cpuset_t cpuset, unsigned long flags)
{
if (!topology->is_loaded || !topology->is_thissystem) {
errno = EINVAL;
return -1;
}
if (!cpuset) {
errno = EINVAL;
return -1;
}
if (flags) {
errno = EINVAL;
return -1;
}
if (pg_index >= nr_processor_groups) {
errno = ENOENT;
return -1;
}
if (!processor_group_cpusets) {
assert(nr_processor_groups == 1);
/* we found no processor groups, return the entire topology as a single one */
hwloc_bitmap_copy(cpuset, topology->levels[0][0]->cpuset);
return 0;
}
if (!processor_group_cpusets[pg_index]) {
errno = ENOENT;
return -1;
}
hwloc_bitmap_copy(cpuset, processor_group_cpusets[pg_index]);
return 0;
}
/************************************************************** /**************************************************************
* hwloc PU numbering with respect to Windows processor groups * hwloc PU numbering with respect to Windows processor groups
* *
@@ -848,6 +990,8 @@ hwloc_look_windows(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
unsigned hostname_size = sizeof(hostname); unsigned hostname_size = sizeof(hostname);
int has_efficiencyclass = 0; int has_efficiencyclass = 0;
struct hwloc_win_efficiency_classes eclasses; struct hwloc_win_efficiency_classes eclasses;
char *env = getenv("HWLOC_WINDOWS_PROCESSOR_GROUP_OBJS");
int keep_pgroup_objs = (env && atoi(env));
assert(dstatus->phase == HWLOC_DISC_PHASE_CPU); assert(dstatus->phase == HWLOC_DISC_PHASE_CPU);
@@ -878,137 +1022,8 @@ hwloc_look_windows(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
GetSystemInfo(&SystemInfo); GetSystemInfo(&SystemInfo);
if (!GetLogicalProcessorInformationExProc && GetLogicalProcessorInformationProc) {
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION procInfo, tmpprocInfo;
unsigned id;
unsigned i;
struct hwloc_obj *obj;
hwloc_obj_type_t type;
length = 0;
procInfo = NULL;
while (1) {
if (GetLogicalProcessorInformationProc(procInfo, &length))
break;
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return -1;
tmpprocInfo = realloc(procInfo, length);
if (!tmpprocInfo) {
free(procInfo);
goto out;
}
procInfo = tmpprocInfo;
}
assert(!length || procInfo);
for (i = 0; i < length / sizeof(*procInfo); i++) {
/* Ignore unknown caches */
if (procInfo->Relationship == RelationCache
&& procInfo->Cache.Type != CacheUnified
&& procInfo->Cache.Type != CacheData
&& procInfo->Cache.Type != CacheInstruction)
continue;
id = HWLOC_UNKNOWN_INDEX;
switch (procInfo[i].Relationship) {
case RelationNumaNode:
type = HWLOC_OBJ_NUMANODE;
id = procInfo[i].NumaNode.NodeNumber;
gotnuma++;
if (id > max_numanode_index)
max_numanode_index = id;
break;
case RelationProcessorPackage:
type = HWLOC_OBJ_PACKAGE;
break;
case RelationCache:
type = (procInfo[i].Cache.Type == CacheInstruction ? HWLOC_OBJ_L1ICACHE : HWLOC_OBJ_L1CACHE) + procInfo[i].Cache.Level - 1;
break;
case RelationProcessorCore:
type = HWLOC_OBJ_CORE;
break;
case RelationGroup:
default:
type = HWLOC_OBJ_GROUP;
break;
}
if (!hwloc_filter_check_keep_object_type(topology, type))
continue;
obj = hwloc_alloc_setup_object(topology, type, id);
obj->cpuset = hwloc_bitmap_alloc();
hwloc_debug("%s#%u mask %llx\n", hwloc_obj_type_string(type), id, (unsigned long long) procInfo[i].ProcessorMask);
/* ProcessorMask is a ULONG_PTR */
hwloc_bitmap_set_ith_ULONG_PTR(obj->cpuset, 0, procInfo[i].ProcessorMask);
hwloc_debug_2args_bitmap("%s#%u bitmap %s\n", hwloc_obj_type_string(type), id, obj->cpuset);
switch (type) {
case HWLOC_OBJ_NUMANODE:
{
ULONGLONG avail;
obj->nodeset = hwloc_bitmap_alloc();
hwloc_bitmap_set(obj->nodeset, id);
if ((GetNumaAvailableMemoryNodeExProc && GetNumaAvailableMemoryNodeExProc(id, &avail))
|| (GetNumaAvailableMemoryNodeProc && GetNumaAvailableMemoryNodeProc(id, &avail))) {
obj->attr->numanode.local_memory = avail;
gotnumamemory++;
}
obj->attr->numanode.page_types_len = 2;
obj->attr->numanode.page_types = malloc(2 * sizeof(*obj->attr->numanode.page_types));
memset(obj->attr->numanode.page_types, 0, 2 * sizeof(*obj->attr->numanode.page_types));
obj->attr->numanode.page_types_len = 1;
obj->attr->numanode.page_types[0].size = SystemInfo.dwPageSize;
#if HAVE_DECL__SC_LARGE_PAGESIZE
obj->attr->numanode.page_types_len++;
obj->attr->numanode.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE);
#endif
break;
}
case HWLOC_OBJ_L1CACHE:
case HWLOC_OBJ_L2CACHE:
case HWLOC_OBJ_L3CACHE:
case HWLOC_OBJ_L4CACHE:
case HWLOC_OBJ_L5CACHE:
case HWLOC_OBJ_L1ICACHE:
case HWLOC_OBJ_L2ICACHE:
case HWLOC_OBJ_L3ICACHE:
obj->attr->cache.size = procInfo[i].Cache.Size;
obj->attr->cache.associativity = procInfo[i].Cache.Associativity == CACHE_FULLY_ASSOCIATIVE ? -1 : procInfo[i].Cache.Associativity ;
obj->attr->cache.linesize = procInfo[i].Cache.LineSize;
obj->attr->cache.depth = procInfo[i].Cache.Level;
switch (procInfo->Cache.Type) {
case CacheUnified:
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
break;
case CacheData:
obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
break;
case CacheInstruction:
obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
break;
default:
hwloc_free_unlinked_object(obj);
continue;
}
break;
case HWLOC_OBJ_GROUP:
obj->attr->group.kind = procInfo[i].Relationship == RelationGroup ? HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP : HWLOC_GROUP_KIND_WINDOWS_RELATIONSHIP_UNKNOWN;
break;
default:
break;
}
hwloc__insert_object_by_cpuset(topology, NULL, obj, "windows:GetLogicalProcessorInformation");
}
free(procInfo);
}
if (GetLogicalProcessorInformationExProc) { if (GetLogicalProcessorInformationExProc) {
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX procInfoTotal, tmpprocInfoTotal, procInfo; HWLOC_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *procInfoTotal, *tmpprocInfoTotal, *procInfo;
unsigned id; unsigned id;
struct hwloc_obj *obj; struct hwloc_obj *obj;
hwloc_obj_type_t type; hwloc_obj_type_t type;
@@ -1047,8 +1062,16 @@ hwloc_look_windows(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
switch (procInfo->Relationship) { switch (procInfo->Relationship) {
case RelationNumaNode: case RelationNumaNode:
type = HWLOC_OBJ_NUMANODE; type = HWLOC_OBJ_NUMANODE;
num = 1; /* Starting with Windows 11 and Server 2022, the GroupCount field is valid and >=1
GroupMask = &procInfo->NumaNode.GroupMask; * and we may read GroupMasks[]. Older releases have GroupCount==0 and we must read GroupMask.
*/
if (procInfo->NumaNode.GroupCount) {
num = procInfo->NumaNode.GroupCount;
GroupMask = procInfo->NumaNode.GroupMasks;
} else {
num = 1;
GroupMask = &procInfo->NumaNode.GroupMask;
}
id = procInfo->NumaNode.NodeNumber; id = procInfo->NumaNode.NodeNumber;
gotnuma++; gotnuma++;
if (id > max_numanode_index) if (id > max_numanode_index)
@@ -1061,18 +1084,20 @@ hwloc_look_windows(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
break; break;
case RelationCache: case RelationCache:
type = (procInfo->Cache.Type == CacheInstruction ? HWLOC_OBJ_L1ICACHE : HWLOC_OBJ_L1CACHE) + procInfo->Cache.Level - 1; type = (procInfo->Cache.Type == CacheInstruction ? HWLOC_OBJ_L1ICACHE : HWLOC_OBJ_L1CACHE) + procInfo->Cache.Level - 1;
num = 1; /* GroupCount added approximately with NumaNode.GroupCount above */
GroupMask = &procInfo->Cache.GroupMask; if (procInfo->Cache.GroupCount) {
num = procInfo->Cache.GroupCount;
GroupMask = procInfo->Cache.GroupMasks;
} else {
num = 1;
GroupMask = &procInfo->Cache.GroupMask;
}
break; break;
case RelationProcessorCore: case RelationProcessorCore:
type = HWLOC_OBJ_CORE; type = HWLOC_OBJ_CORE;
num = procInfo->Processor.GroupCount; num = procInfo->Processor.GroupCount;
GroupMask = procInfo->Processor.GroupMask; GroupMask = procInfo->Processor.GroupMask;
if (has_efficiencyclass) efficiency_class = procInfo->Processor.EfficiencyClass;
/* the EfficiencyClass field didn't exist before Windows10 and recent MSVC headers,
* so just access it manually instead of trying to detect it.
*/
efficiency_class = * ((&procInfo->Processor.Flags) + 1);
break; break;
case RelationGroup: case RelationGroup:
/* So strange an interface... */ /* So strange an interface... */
@@ -1097,11 +1122,12 @@ hwloc_look_windows(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
groups_pu_set = hwloc_bitmap_alloc(); groups_pu_set = hwloc_bitmap_alloc();
hwloc_bitmap_or(groups_pu_set, groups_pu_set, set); hwloc_bitmap_or(groups_pu_set, groups_pu_set, set);
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_GROUP)) { /* Ignore processor groups unless requested and filtered-in */
if (keep_pgroup_objs && hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_GROUP)) {
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_GROUP, id); obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_GROUP, id);
obj->cpuset = set; obj->cpuset = set;
obj->attr->group.kind = HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP; obj->attr->group.kind = HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP;
hwloc__insert_object_by_cpuset(topology, NULL, obj, "windows:GetLogicalProcessorInformation:ProcessorGroup"); hwloc__insert_object_by_cpuset(topology, NULL, obj, "windows:GetLogicalProcessorInformationEx:ProcessorGroup");
} else } else
hwloc_bitmap_free(set); hwloc_bitmap_free(set);
} }
@@ -1328,11 +1354,13 @@ hwloc_set_windows_hooks(struct hwloc_binding_hooks *hooks,
static int hwloc_windows_component_init(unsigned long flags __hwloc_attribute_unused) static int hwloc_windows_component_init(unsigned long flags __hwloc_attribute_unused)
{ {
hwloc_win_get_function_ptrs(); hwloc_win_get_function_ptrs();
hwloc_win_get_processor_groups();
return 0; return 0;
} }
static void hwloc_windows_component_finalize(unsigned long flags __hwloc_attribute_unused) static void hwloc_windows_component_finalize(unsigned long flags __hwloc_attribute_unused)
{ {
hwloc_win_free_processor_groups();
} }
static struct hwloc_backend * static struct hwloc_backend *

View File

@@ -7,11 +7,14 @@
* *
* This backend is only used when the operating system does not export * This backend is only 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, only the FreeBSD backend relies on this x86 backend. * Currently, FreeBSD and NetBSD only add PUs and then fallback to this
* backend for CPU/Cache discovery.
* *
* Other backends such as Linux have their own way to retrieve various * Other backends such as Linux have their own way to retrieve various
* pieces of hardware topology information from the operating system * pieces of hardware topology information from the operating system
* 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
* additional details (CPU info in Package, Inclusiveness in Caches).
*/ */
#include "private/autogen/config.h" #include "private/autogen/config.h"
@@ -497,7 +500,8 @@ static void read_amd_cores_topoext(struct procinfo *infos, unsigned long flags,
nodes_per_proc = ((ecx >> 8) & 7) + 1; nodes_per_proc = ((ecx >> 8) & 7) + 1;
} }
if ((infos->cpufamilynumber == 0x15 && nodes_per_proc > 2) if ((infos->cpufamilynumber == 0x15 && nodes_per_proc > 2)
|| ((infos->cpufamilynumber == 0x17 || infos->cpufamilynumber == 0x18) && nodes_per_proc > 4)) { || ((infos->cpufamilynumber == 0x17 || infos->cpufamilynumber == 0x18) && nodes_per_proc > 4)
|| (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);
} }
} }
@@ -610,10 +614,13 @@ static void look_proc(struct hwloc_backend *backend, struct procinfo *infos, uns
eax = 0x01; eax = 0x01;
cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump); cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump);
infos->apicid = ebx >> 24; infos->apicid = ebx >> 24;
if (edx & (1 << 28)) if (edx & (1 << 28)) {
legacy_max_log_proc = 1 << hwloc_flsl(((ebx >> 16) & 0xff) - 1); legacy_max_log_proc = 1 << hwloc_flsl(((ebx >> 16) & 0xff) - 1);
else } else {
hwloc_debug("HTT bit not set in CPUID 0x01.edx, assuming legacy_max_log_proc = 1\n");
legacy_max_log_proc = 1; legacy_max_log_proc = 1;
}
hwloc_debug("APIC ID 0x%02x legacy_max_log_proc %u\n", infos->apicid, legacy_max_log_proc); hwloc_debug("APIC ID 0x%02x legacy_max_log_proc %u\n", infos->apicid, legacy_max_log_proc);
infos->ids[PKG] = infos->apicid / legacy_max_log_proc; infos->ids[PKG] = infos->apicid / legacy_max_log_proc;
legacy_log_proc_id = infos->apicid % legacy_max_log_proc; legacy_log_proc_id = infos->apicid % legacy_max_log_proc;
@@ -676,12 +683,23 @@ static void look_proc(struct hwloc_backend *backend, struct procinfo *infos, uns
unsigned max_nbcores; unsigned max_nbcores;
unsigned max_nbthreads; unsigned max_nbthreads;
unsigned threadid __hwloc_attribute_unused; unsigned threadid __hwloc_attribute_unused;
hwloc_debug("Trying to get core/thread IDs from 0x04...\n");
max_nbcores = ((eax >> 26) & 0x3f) + 1; max_nbcores = ((eax >> 26) & 0x3f) + 1;
max_nbthreads = legacy_max_log_proc / max_nbcores; hwloc_debug("found %u cores max\n", max_nbcores);
hwloc_debug("thus %u threads\n", max_nbthreads); /* some VMs (e.g. issue#525) don't report valid information, check things before dividing by 0. */
threadid = legacy_log_proc_id % max_nbthreads; if (!max_nbcores) {
infos->ids[CORE] = legacy_log_proc_id / max_nbthreads; hwloc_debug("cannot detect core/thread IDs from 0x04 without a valid max of cores\n");
hwloc_debug("this is thread %u of core %u\n", threadid, infos->ids[CORE]); } else {
max_nbthreads = legacy_max_log_proc / max_nbcores;
hwloc_debug("found %u threads max\n", max_nbthreads);
if (!max_nbthreads) {
hwloc_debug("cannot detect core/thread IDs from 0x04 without a valid max of threads\n");
} else {
threadid = legacy_log_proc_id % max_nbthreads;
infos->ids[CORE] = legacy_log_proc_id / max_nbthreads;
hwloc_debug("this is thread %u of core %u\n", threadid, infos->ids[CORE]);
}
}
} }
} }
@@ -772,13 +790,19 @@ static void look_proc(struct hwloc_backend *backend, struct procinfo *infos, uns
} else if (cpuid_type == amd) { } else if (cpuid_type == amd) {
/* AMD quirks */ /* AMD quirks */
if (infos->cpufamilynumber == 0x17 if (infos->cpufamilynumber >= 0x17 && cache->level == 3) {
&& cache->level == 3 && cache->nbthreads_sharing == 6) { /* AMD family 0x19 always shares L3 between 16 APIC ids (8 HT cores).
/* AMD family 0x17 always shares L3 between 8 APIC ids, * while Family 0x17 shares between 8 APIC ids (4 HT cores).
* even when only 6 APIC ids are enabled and reported in nbthreads_sharing * But many models have less APIC ids enabled and reported in nbthreads_sharing.
* (on 24-core CPUs). * It means we must round-up nbthreads_sharing to the nearest power of 2
* before computing cacheid.
*/ */
cache->cacheid = infos->apicid / 8; unsigned nbapics_sharing = cache->nbthreads_sharing;
if (nbapics_sharing & (nbapics_sharing-1))
/* not a power of two, round-up */
nbapics_sharing = 1U<<(1+hwloc_ffsl(nbapics_sharing));
cache->cacheid = infos->apicid / nbapics_sharing;
} else if (infos->cpufamilynumber== 0x10 && infos->cpumodelnumber == 0x9 } else if (infos->cpufamilynumber== 0x10 && infos->cpumodelnumber == 0x9
&& cache->level == 3 && cache->level == 3
@@ -804,7 +828,7 @@ static void look_proc(struct hwloc_backend *backend, struct procinfo *infos, uns
} else if (infos->cpufamilynumber == 0x15 } else if (infos->cpufamilynumber == 0x15
&& (infos->cpumodelnumber == 0x1 /* Bulldozer */ || infos->cpumodelnumber == 0x2 /* Piledriver */) && (infos->cpumodelnumber == 0x1 /* Bulldozer */ || infos->cpumodelnumber == 0x2 /* Piledriver */)
&& cache->level == 3 && cache->nbthreads_sharing == 6) { && cache->level == 3 && cache->nbthreads_sharing == 6) {
/* AMD Bulldozer and Piledriver 12-core processors have same APIC ids as Magny-Cours below, /* AMD Bulldozer and Piledriver 12-core processors have same APIC ids as Magny-Cours above,
* but we can't merge the checks because the original nbthreads_sharing must be exactly 6 here. * but we can't merge the checks because the original nbthreads_sharing must be exactly 6 here.
*/ */
cache->cacheid = (infos->apicid % legacy_max_log_proc) / cache->nbthreads_sharing /* cacheid within the package */ cache->cacheid = (infos->apicid % legacy_max_log_proc) / cache->nbthreads_sharing /* cacheid within the package */
@@ -1228,6 +1252,18 @@ static void summarize(struct hwloc_backend *backend, struct procinfo *infos, uns
} }
} }
cache = hwloc_alloc_setup_object(topology, otype, HWLOC_UNKNOWN_INDEX); cache = hwloc_alloc_setup_object(topology, otype, HWLOC_UNKNOWN_INDEX);
/* We don't specify the os_index of caches because we want to be
* 100% sure they are identical to what the Linux kernel reports
* (so that things like resctrl work).
* However, vendor/model-specific quirks in the x86 code above
* make this difficult.
*
* Caveat: if the x86 backend is used on Linux to avoid kernel bugs,
* IDs won't be available to resctrl users. But resctrl heavily
* relies on the kernel x86 discovery being non-buggy anyway.
*
* TODO: make this optional? or only disable it on Linux?
*/
cache->attr->cache.depth = level; cache->attr->cache.depth = level;
cache->attr->cache.size = infos[i].cache[l].size; cache->attr->cache.size = infos[i].cache[l].size;
cache->attr->cache.linesize = infos[i].cache[l].linesize; cache->attr->cache.linesize = infos[i].cache[l].linesize;
@@ -1257,7 +1293,8 @@ static int
look_procs(struct hwloc_backend *backend, struct procinfo *infos, unsigned long flags, look_procs(struct hwloc_backend *backend, struct procinfo *infos, unsigned long flags,
unsigned highest_cpuid, unsigned highest_ext_cpuid, unsigned *features, enum cpuid_type cpuid_type, unsigned highest_cpuid, unsigned highest_ext_cpuid, unsigned *features, enum cpuid_type cpuid_type,
int (*get_cpubind)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags), int (*get_cpubind)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags),
int (*set_cpubind)(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags)) int (*set_cpubind)(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags),
hwloc_bitmap_t restrict_set)
{ {
struct hwloc_x86_backend_data_s *data = backend->private_data; struct hwloc_x86_backend_data_s *data = backend->private_data;
struct hwloc_topology *topology = backend->topology; struct hwloc_topology *topology = backend->topology;
@@ -1277,6 +1314,12 @@ look_procs(struct hwloc_backend *backend, struct procinfo *infos, unsigned long
for (i = 0; i < nbprocs; i++) { for (i = 0; i < nbprocs; i++) {
struct cpuiddump *src_cpuiddump = NULL; struct cpuiddump *src_cpuiddump = NULL;
if (restrict_set && !hwloc_bitmap_isset(restrict_set, i)) {
/* skip this CPU outside of the binding mask */
continue;
}
if (data->src_cpuiddump_path) { if (data->src_cpuiddump_path) {
src_cpuiddump = cpuiddump_read(data->src_cpuiddump_path, i); src_cpuiddump = cpuiddump_read(data->src_cpuiddump_path, i);
if (!src_cpuiddump) if (!src_cpuiddump)
@@ -1410,6 +1453,7 @@ static
int hwloc_look_x86(struct hwloc_backend *backend, unsigned long flags) int hwloc_look_x86(struct hwloc_backend *backend, unsigned long flags)
{ {
struct hwloc_x86_backend_data_s *data = backend->private_data; struct hwloc_x86_backend_data_s *data = backend->private_data;
struct hwloc_topology *topology = backend->topology;
unsigned nbprocs = data->nbprocs; unsigned nbprocs = data->nbprocs;
unsigned eax, ebx, ecx = 0, edx; unsigned eax, ebx, ecx = 0, edx;
unsigned i; unsigned i;
@@ -1425,9 +1469,21 @@ int hwloc_look_x86(struct hwloc_backend *backend, unsigned long flags)
struct hwloc_topology_membind_support memsupport __hwloc_attribute_unused; struct hwloc_topology_membind_support memsupport __hwloc_attribute_unused;
int (*get_cpubind)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags) = NULL; int (*get_cpubind)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags) = NULL;
int (*set_cpubind)(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags) = NULL; int (*set_cpubind)(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags) = NULL;
hwloc_bitmap_t restrict_set = NULL;
struct cpuiddump *src_cpuiddump = NULL; struct cpuiddump *src_cpuiddump = NULL;
int ret = -1; int ret = -1;
/* check if binding works */
memset(&hooks, 0, sizeof(hooks));
support.membind = &memsupport;
/* We could just copy the main hooks (except in some corner cases),
* but the current overhead is negligible, so just always reget them.
*/
hwloc_set_native_binding_hooks(&hooks, &support);
/* in theory, those are only needed if !data->src_cpuiddump_path || HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_BINDING
* but that's the vast majority of cases anyway, and the overhead is very small.
*/
if (data->src_cpuiddump_path) { if (data->src_cpuiddump_path) {
/* Just read cpuid from the dump (implies !topology->is_thissystem by default) */ /* Just read cpuid from the dump (implies !topology->is_thissystem by default) */
src_cpuiddump = cpuiddump_read(data->src_cpuiddump_path, 0); src_cpuiddump = cpuiddump_read(data->src_cpuiddump_path, 0);
@@ -1440,13 +1496,6 @@ int hwloc_look_x86(struct hwloc_backend *backend, unsigned long flags)
* we may still force use this backend when debugging with !thissystem. * we may still force use this backend when debugging with !thissystem.
*/ */
/* check if binding works */
memset(&hooks, 0, sizeof(hooks));
support.membind = &memsupport;
/* We could just copy the main hooks (except in some corner cases),
* but the current overhead is negligible, so just always reget them.
*/
hwloc_set_native_binding_hooks(&hooks, &support);
if (hooks.get_thisthread_cpubind && hooks.set_thisthread_cpubind) { if (hooks.get_thisthread_cpubind && hooks.set_thisthread_cpubind) {
get_cpubind = hooks.get_thisthread_cpubind; get_cpubind = hooks.get_thisthread_cpubind;
set_cpubind = hooks.set_thisthread_cpubind; set_cpubind = hooks.set_thisthread_cpubind;
@@ -1466,6 +1515,20 @@ int hwloc_look_x86(struct hwloc_backend *backend, unsigned long flags)
} }
} }
if (topology->flags & HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING) {
restrict_set = hwloc_bitmap_alloc();
if (!restrict_set)
goto out;
if (hooks.get_thisproc_cpubind)
hooks.get_thisproc_cpubind(topology, restrict_set, 0);
else if (hooks.get_thisthread_cpubind)
hooks.get_thisthread_cpubind(topology, restrict_set, 0);
if (hwloc_bitmap_iszero(restrict_set)) {
hwloc_bitmap_free(restrict_set);
restrict_set = NULL;
}
}
if (!src_cpuiddump && !hwloc_have_x86_cpuid()) if (!src_cpuiddump && !hwloc_have_x86_cpuid())
goto out; goto out;
@@ -1530,7 +1593,7 @@ int hwloc_look_x86(struct hwloc_backend *backend, unsigned long flags)
ret = look_procs(backend, infos, flags, ret = look_procs(backend, infos, flags,
highest_cpuid, highest_ext_cpuid, features, cpuid_type, highest_cpuid, highest_ext_cpuid, features, cpuid_type,
get_cpubind, set_cpubind); get_cpubind, set_cpubind, restrict_set);
if (!ret) if (!ret)
/* success, we're done */ /* success, we're done */
goto out_with_os_state; goto out_with_os_state;
@@ -1555,6 +1618,7 @@ out_with_infos:
} }
out: out:
hwloc_bitmap_free(restrict_set);
if (src_cpuiddump) if (src_cpuiddump)
cpuiddump_free(src_cpuiddump); cpuiddump_free(src_cpuiddump);
return ret; return ret;
@@ -1571,6 +1635,11 @@ hwloc_x86_discover(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
assert(dstatus->phase == HWLOC_DISC_PHASE_CPU); assert(dstatus->phase == HWLOC_DISC_PHASE_CPU);
if (topology->flags & HWLOC_TOPOLOGY_FLAG_DONT_CHANGE_BINDING) {
/* TODO: Things would work if there's a single PU, no need to rebind */
return 0;
}
if (getenv("HWLOC_X86_TOPOEXT_NUMANODES")) { if (getenv("HWLOC_X86_TOPOEXT_NUMANODES")) {
flags |= HWLOC_X86_DISC_FLAG_TOPOEXT_NUMANODES; flags |= HWLOC_X86_DISC_FLAG_TOPOEXT_NUMANODES;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2021 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.
@@ -192,8 +192,9 @@ hwloc__xml_import_object_attr(struct hwloc_topology *topology,
|| lvalue == HWLOC_OBJ_CACHE_INSTRUCTION) || lvalue == HWLOC_OBJ_CACHE_INSTRUCTION)
obj->attr->cache.type = (hwloc_obj_cache_type_t) lvalue; obj->attr->cache.type = (hwloc_obj_cache_type_t) lvalue;
else else
fprintf(stderr, "%s: ignoring invalid cache_type attribute %lu\n", if (hwloc__xml_verbose())
state->global->msgprefix, lvalue); fprintf(stderr, "%s: ignoring invalid cache_type attribute %lu\n",
state->global->msgprefix, lvalue);
} else if (hwloc__xml_verbose()) } else if (hwloc__xml_verbose())
fprintf(stderr, "%s: ignoring cache_type attribute for non-cache object type\n", fprintf(stderr, "%s: ignoring cache_type attribute for non-cache object type\n",
state->global->msgprefix); state->global->msgprefix);
@@ -242,7 +243,7 @@ hwloc__xml_import_object_attr(struct hwloc_topology *topology,
else if (!strcmp(name, "dont_merge")) { else if (!strcmp(name, "dont_merge")) {
unsigned long lvalue = strtoul(value, NULL, 10); unsigned long lvalue = strtoul(value, NULL, 10);
if (obj->type == HWLOC_OBJ_GROUP) if (obj->type == HWLOC_OBJ_GROUP)
obj->attr->group.dont_merge = lvalue; obj->attr->group.dont_merge = (unsigned char) lvalue;
else if (hwloc__xml_verbose()) else if (hwloc__xml_verbose())
fprintf(stderr, "%s: ignoring dont_merge attribute for non-group object type\n", fprintf(stderr, "%s: ignoring dont_merge attribute for non-group object type\n",
state->global->msgprefix); state->global->msgprefix);
@@ -262,8 +263,8 @@ hwloc__xml_import_object_attr(struct hwloc_topology *topology,
#ifndef HWLOC_HAVE_32BITS_PCI_DOMAIN #ifndef HWLOC_HAVE_32BITS_PCI_DOMAIN
} else if (domain > 0xffff) { } else if (domain > 0xffff) {
static int warned = 0; static int warned = 0;
if (!warned && !hwloc_hide_errors()) if (!warned && hwloc_hide_errors() < 2)
fprintf(stderr, "Ignoring PCI device with non-16bit domain.\nPass --enable-32bits-pci-domain to configure to support such devices\n(warning: it would break the library ABI, don't enable unless really needed).\n"); fprintf(stderr, "hwloc/xml: Ignoring PCI device with non-16bit domain.\nPass --enable-32bits-pci-domain to configure to support such devices\n(warning: it would break the library ABI, don't enable unless really needed).\n");
warned = 1; warned = 1;
*ignore = 1; *ignore = 1;
#endif #endif
@@ -337,6 +338,7 @@ hwloc__xml_import_object_attr(struct hwloc_topology *topology,
} else { } else {
obj->attr->bridge.upstream_type = (hwloc_obj_bridge_type_t) upstream_type; obj->attr->bridge.upstream_type = (hwloc_obj_bridge_type_t) upstream_type;
obj->attr->bridge.downstream_type = (hwloc_obj_bridge_type_t) downstream_type; obj->attr->bridge.downstream_type = (hwloc_obj_bridge_type_t) downstream_type;
/* FIXME verify that upstream/downstream type is valid */
}; };
break; break;
} }
@@ -361,12 +363,13 @@ hwloc__xml_import_object_attr(struct hwloc_topology *topology,
#ifndef HWLOC_HAVE_32BITS_PCI_DOMAIN #ifndef HWLOC_HAVE_32BITS_PCI_DOMAIN
} else if (domain > 0xffff) { } else if (domain > 0xffff) {
static int warned = 0; static int warned = 0;
if (!warned && !hwloc_hide_errors()) if (!warned && hwloc_hide_errors() < 2)
fprintf(stderr, "Ignoring bridge to PCI with non-16bit domain.\nPass --enable-32bits-pci-domain to configure to support such devices\n(warning: it would break the library ABI, don't enable unless really needed).\n"); fprintf(stderr, "hwloc/xml: Ignoring bridge to PCI with non-16bit domain.\nPass --enable-32bits-pci-domain to configure to support such devices\n(warning: it would break the library ABI, don't enable unless really needed).\n");
warned = 1; warned = 1;
*ignore = 1; *ignore = 1;
#endif #endif
} else { } else {
/* FIXME verify that downstream type vs pci info are valid */
obj->attr->bridge.downstream.pci.domain = domain; obj->attr->bridge.downstream.pci.domain = domain;
obj->attr->bridge.downstream.pci.secondary_bus = secbus; obj->attr->bridge.downstream.pci.secondary_bus = secbus;
obj->attr->bridge.downstream.pci.subordinate_bus = subbus; obj->attr->bridge.downstream.pci.subordinate_bus = subbus;
@@ -1232,7 +1235,7 @@ hwloc__xml_import_object(hwloc_topology_t topology,
/* next should be before cur */ /* next should be before cur */
if (!childrengotignored) { if (!childrengotignored) {
static int reported = 0; static int reported = 0;
if (!reported && !hwloc_hide_errors()) { if (!reported && hwloc_hide_errors() < 2) {
hwloc__xml_import_report_outoforder(topology, next, cur); hwloc__xml_import_report_outoforder(topology, next, cur);
reported = 1; reported = 1;
} }
@@ -1565,7 +1568,7 @@ hwloc__xml_v2import_distances(hwloc_topology_t topology,
} }
} }
hwloc_internal_distances_add_by_index(topology, name, unique_type, different_types, nbobjs, indexes, u64values, kind, 0); hwloc_internal_distances_add_by_index(topology, name, unique_type, different_types, nbobjs, indexes, u64values, kind, 0 /* assume grouping was applied when this matrix was discovered before exporting to XML */);
/* prevent freeing below */ /* prevent freeing below */
indexes = NULL; indexes = NULL;
@@ -2647,7 +2650,8 @@ hwloc__xml_export_object_contents (hwloc__xml_export_state_t state, hwloc_topolo
logical_to_v2array = malloc(nbobjs * sizeof(*logical_to_v2array)); logical_to_v2array = malloc(nbobjs * sizeof(*logical_to_v2array));
if (!logical_to_v2array) { if (!logical_to_v2array) {
fprintf(stderr, "xml/export/v1: failed to allocated logical_to_v2array\n"); if (!hwloc_hide_errors())
fprintf(stderr, "hwloc/xml/export/v1: failed to allocated logical_to_v2array\n");
continue; continue;
} }
@@ -2821,6 +2825,7 @@ hwloc__xml_v1export_object_with_memory(hwloc__xml_export_state_t parentstate, hw
/* child has sibling, we must add a Group around those memory children */ /* child has sibling, we must add a Group around those memory children */
hwloc_obj_t group = parentstate->global->v1_memory_group; hwloc_obj_t group = parentstate->global->v1_memory_group;
parentstate->new_child(parentstate, &gstate, "object"); parentstate->new_child(parentstate, &gstate, "object");
group->parent = obj->parent;
group->cpuset = obj->cpuset; group->cpuset = obj->cpuset;
group->complete_cpuset = obj->complete_cpuset; group->complete_cpuset = obj->complete_cpuset;
group->nodeset = obj->nodeset; group->nodeset = obj->nodeset;

View File

@@ -3,6 +3,7 @@
* Copyright © 2009-2021 Inria. All rights reserved. * Copyright © 2009-2021 Inria. All rights reserved.
* Copyright © 2009-2012, 2020 Université Bordeaux * Copyright © 2009-2012, 2020 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* Copyright © 2022 IBM Corporation. All rights reserved.
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
@@ -52,6 +53,57 @@
#include <windows.h> #include <windows.h>
#endif #endif
#ifdef HWLOC_HAVE_LEVELZERO
/*
* Define ZES_ENABLE_SYSMAN=1 early so that the LevelZero backend gets Sysman enabled.
*
* Only if the levelzero was enabled in this build so that we don't enable sysman
* for external levelzero users when hwloc doesn't need it. If somebody ever loads
* an external levelzero plugin in a hwloc library built without levelzero (unlikely),
* he may have to manually set ZES_ENABLE_SYSMAN=1.
*
* Use the constructor if supported and/or the Windows DllMain callback.
* Do it in the main hwloc library instead of the levelzero component because
* the latter could be loaded later as a plugin.
*
* L0 seems to be using getenv() to check this variable on Windows
* (at least in the Intel Compute-Runtime of March 2021),
* but setenv() doesn't seem to exist on Windows, hence use putenv() to set the variable.
*
* For the record, Get/SetEnvironmentVariable() is not exactly the same as getenv/putenv():
* - getenv() doesn't see what was set with SetEnvironmentVariable()
* - GetEnvironmentVariable() doesn't see putenv() in cygwin (while it does in MSVC and MinGW).
* Hence, if L0 ever switches from getenv() to GetEnvironmentVariable(),
* it will break in cygwin, we'll have to use both putenv() and SetEnvironmentVariable().
* Hopefully L0 will provide a way to enable Sysman without env vars before it happens.
*/
#if HWLOC_HAVE_ATTRIBUTE_CONSTRUCTOR
static void hwloc_constructor(void) __attribute__((constructor));
static void hwloc_constructor(void)
{
if (!getenv("ZES_ENABLE_SYSMAN"))
#ifdef HWLOC_WIN_SYS
putenv("ZES_ENABLE_SYSMAN=1");
#else
setenv("ZES_ENABLE_SYSMAN", "1", 1);
#endif
}
#endif
#ifdef HWLOC_WIN_SYS
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH) {
if (!getenv("ZES_ENABLE_SYSMAN"))
/* Windows does not have a setenv, so use putenv. */
putenv((char *) "ZES_ENABLE_SYSMAN=1");
}
return TRUE;
}
#endif
#endif /* HWLOC_HAVE_LEVELZERO */
unsigned hwloc_get_api_version(void) unsigned hwloc_get_api_version(void)
{ {
return HWLOC_API_VERSION; return HWLOC_API_VERSION;
@@ -64,7 +116,7 @@ int hwloc_topology_abi_check(hwloc_topology_t topology)
int hwloc_hide_errors(void) int hwloc_hide_errors(void)
{ {
static int hide = 0; static int hide = 1; /* only show critical errors by default. lstopo will show others */
static int checked = 0; static int checked = 0;
if (!checked) { if (!checked) {
const char *envvar = getenv("HWLOC_HIDE_ERRORS"); const char *envvar = getenv("HWLOC_HIDE_ERRORS");
@@ -106,7 +158,7 @@ static void report_insert_error(hwloc_obj_t new, hwloc_obj_t old, const char *ms
{ {
static int reported = 0; static int reported = 0;
if (reason && !reported && !hwloc_hide_errors()) { if (reason && !reported && hwloc_hide_errors() < 2) {
char newstr[512]; char newstr[512];
char oldstr[512]; char oldstr[512];
report_insert_error_format_obj(newstr, sizeof(newstr), new); report_insert_error_format_obj(newstr, sizeof(newstr), new);
@@ -1865,6 +1917,9 @@ hwloc_topology_alloc_group_object(struct hwloc_topology *topology)
static void hwloc_propagate_symmetric_subtree(hwloc_topology_t topology, hwloc_obj_t root); static void hwloc_propagate_symmetric_subtree(hwloc_topology_t topology, hwloc_obj_t root);
static void propagate_total_memory(hwloc_obj_t obj); static void propagate_total_memory(hwloc_obj_t obj);
static void hwloc_set_group_depth(hwloc_topology_t topology); static void hwloc_set_group_depth(hwloc_topology_t topology);
static void hwloc_connect_children(hwloc_obj_t parent);
static int hwloc_connect_levels(hwloc_topology_t topology);
static int hwloc_connect_special_levels(hwloc_topology_t topology);
hwloc_obj_t hwloc_obj_t
hwloc_topology_insert_group_object(struct hwloc_topology *topology, hwloc_obj_t obj) hwloc_topology_insert_group_object(struct hwloc_topology *topology, hwloc_obj_t obj)
@@ -2307,9 +2362,15 @@ hwloc__filter_bridges(hwloc_topology_t topology, hwloc_obj_t root, unsigned dept
child->attr->bridge.depth = depth; child->attr->bridge.depth = depth;
if (child->type == HWLOC_OBJ_BRIDGE /* remove bridges that have no child,
&& filter == HWLOC_TYPE_FILTER_KEEP_IMPORTANT * and pci-to-non-pci bridges (pcidev) that no child either.
&& !child->io_first_child) { * keep NVSwitch since they may be used in NVLink matrices.
*/
if (filter == HWLOC_TYPE_FILTER_KEEP_IMPORTANT
&& !child->io_first_child
&& (child->type == HWLOC_OBJ_BRIDGE
|| (child->type == HWLOC_OBJ_PCI_DEVICE && (child->attr->pcidev.class_id >> 8) == 0x06
&& (!child->subtype || strcmp(child->subtype, "NVSwitch"))))) {
unlink_and_free_single_object(pchild); unlink_and_free_single_object(pchild);
topology->modified = 1; topology->modified = 1;
} }
@@ -2432,13 +2493,26 @@ hwloc_compare_levels_structure(hwloc_topology_t topology, unsigned i)
return 0; return 0;
} }
/* return > 0 if any level was removed, which means reconnect is needed */ /* return > 0 if any level was removed.
static void * performs its own reconnect internally if needed
*/
static int
hwloc_filter_levels_keep_structure(hwloc_topology_t topology) hwloc_filter_levels_keep_structure(hwloc_topology_t topology)
{ {
unsigned i, j; unsigned i, j;
int res = 0; int res = 0;
if (topology->modified) {
/* WARNING: hwloc_topology_reconnect() is duplicated partially here
* and at the end of this function:
* - we need normal levels before merging.
* - and we'll need to update special levels after merging.
*/
hwloc_connect_children(topology->levels[0][0]);
if (hwloc_connect_levels(topology) < 0)
return -1;
}
/* start from the bottom since we'll remove intermediate levels */ /* start from the bottom since we'll remove intermediate levels */
for(i=topology->nb_levels-1; i>0; i--) { for(i=topology->nb_levels-1; i>0; i--) {
int replacechild = 0, replaceparent = 0; int replacechild = 0, replaceparent = 0;
@@ -2604,6 +2678,22 @@ hwloc_filter_levels_keep_structure(hwloc_topology_t topology)
topology->type_depth[type] = HWLOC_TYPE_DEPTH_MULTIPLE; topology->type_depth[type] = HWLOC_TYPE_DEPTH_MULTIPLE;
} }
} }
if (res > 0 || topology-> modified) {
/* WARNING: hwloc_topology_reconnect() is duplicated partially here
* and at the beginning of this function.
* If we merged some levels, some child+parent special children lisst
* may have been merged, hence specials level might need reordering,
* So reconnect special levels only here at the end
* (it's not needed at the beginning of this function).
*/
if (hwloc_connect_special_levels(topology) < 0)
return -1;
topology->modified = 0;
}
return 0;
} }
static void static void
@@ -2921,9 +3011,9 @@ hwloc_list_special_objects(hwloc_topology_t topology, hwloc_obj_t obj)
} }
} }
/* Build I/O levels */ /* Build Memory, I/O and Misc levels */
static int static int
hwloc_connect_io_misc_levels(hwloc_topology_t topology) hwloc_connect_special_levels(hwloc_topology_t topology)
{ {
unsigned i; unsigned i;
@@ -3088,7 +3178,8 @@ hwloc_connect_levels(hwloc_topology_t topology)
tmpnbobjs = realloc(topology->level_nbobjects, tmpnbobjs = realloc(topology->level_nbobjects,
2 * topology->nb_levels_allocated * sizeof(*topology->level_nbobjects)); 2 * topology->nb_levels_allocated * sizeof(*topology->level_nbobjects));
if (!tmplevels || !tmpnbobjs) { if (!tmplevels || !tmpnbobjs) {
fprintf(stderr, "hwloc failed to realloc level arrays to %u\n", topology->nb_levels_allocated * 2); if (hwloc_hide_errors() < 2)
fprintf(stderr, "hwloc: failed to realloc level arrays to %u\n", topology->nb_levels_allocated * 2);
/* if one realloc succeeded, make sure the caller will free the new buffer */ /* if one realloc succeeded, make sure the caller will free the new buffer */
if (tmplevels) if (tmplevels)
@@ -3133,6 +3224,10 @@ hwloc_connect_levels(hwloc_topology_t topology)
int int
hwloc_topology_reconnect(struct hwloc_topology *topology, unsigned long flags) hwloc_topology_reconnect(struct hwloc_topology *topology, unsigned long flags)
{ {
/* WARNING: when updating this function, the replicated code must
* also be updated inside hwloc_filter_levels_keep_structure()
*/
if (flags) { if (flags) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@@ -3145,7 +3240,7 @@ hwloc_topology_reconnect(struct hwloc_topology *topology, unsigned long flags)
if (hwloc_connect_levels(topology) < 0) if (hwloc_connect_levels(topology) < 0)
return -1; return -1;
if (hwloc_connect_io_misc_levels(topology) < 0) if (hwloc_connect_special_levels(topology) < 0)
return -1; return -1;
topology->modified = 0; topology->modified = 0;
@@ -3470,28 +3565,28 @@ hwloc_discover(struct hwloc_topology *topology,
hwloc_debug("%s", "\nRemoving empty objects\n"); hwloc_debug("%s", "\nRemoving empty objects\n");
remove_empty(topology, &topology->levels[0][0]); remove_empty(topology, &topology->levels[0][0]);
if (!topology->levels[0][0]) { if (!topology->levels[0][0]) {
fprintf(stderr, "Topology became empty, aborting!\n"); if (hwloc_hide_errors() < 2)
fprintf(stderr, "hwloc: Topology became empty, aborting!\n");
return -1; return -1;
} }
if (hwloc_bitmap_iszero(topology->levels[0][0]->cpuset)) { if (hwloc_bitmap_iszero(topology->levels[0][0]->cpuset)) {
fprintf(stderr, "Topology does not contain any PU, aborting!\n"); if (hwloc_hide_errors() < 2)
fprintf(stderr, "hwloc: Topology does not contain any PU, aborting!\n");
return -1; return -1;
} }
if (hwloc_bitmap_iszero(topology->levels[0][0]->nodeset)) { if (hwloc_bitmap_iszero(topology->levels[0][0]->nodeset)) {
fprintf(stderr, "Topology does not contain any NUMA node, aborting!\n"); if (hwloc_hide_errors() < 2)
fprintf(stderr, "hwloc: Topology does not contain any NUMA node, aborting!\n");
return -1; return -1;
} }
hwloc_debug_print_objects(0, topology->levels[0][0]); hwloc_debug_print_objects(0, topology->levels[0][0]);
/* Reconnect things after all these changes.
* Often needed because of Groups inserted for I/Os.
* And required for KEEP_STRUCTURE below.
*/
if (hwloc_topology_reconnect(topology, 0) < 0)
return -1;
hwloc_debug("%s", "\nRemoving levels with HWLOC_TYPE_FILTER_KEEP_STRUCTURE\n"); hwloc_debug("%s", "\nRemoving levels with HWLOC_TYPE_FILTER_KEEP_STRUCTURE\n");
hwloc_filter_levels_keep_structure(topology); if (hwloc_filter_levels_keep_structure(topology) < 0)
return -1;
/* takes care of reconnecting children/levels internally,
* because it needs normal levels.
* and it's often needed below because of Groups inserted for I/Os anyway */
hwloc_debug_print_objects(0, topology->levels[0][0]); hwloc_debug_print_objects(0, topology->levels[0][0]);
/* accumulate children memory in total_memory fields (only once parent is set) */ /* accumulate children memory in total_memory fields (only once parent is set) */
@@ -3716,7 +3811,18 @@ hwloc_topology_set_flags (struct hwloc_topology *topology, unsigned long flags)
return -1; return -1;
} }
if (flags & ~(HWLOC_TOPOLOGY_FLAG_INCLUDE_DISALLOWED|HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM|HWLOC_TOPOLOGY_FLAG_THISSYSTEM_ALLOWED_RESOURCES|HWLOC_TOPOLOGY_FLAG_IMPORT_SUPPORT)) { if (flags & ~(HWLOC_TOPOLOGY_FLAG_INCLUDE_DISALLOWED|HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM|HWLOC_TOPOLOGY_FLAG_THISSYSTEM_ALLOWED_RESOURCES|HWLOC_TOPOLOGY_FLAG_IMPORT_SUPPORT|HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING|HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_MEMBINDING|HWLOC_TOPOLOGY_FLAG_DONT_CHANGE_BINDING)) {
errno = EINVAL;
return -1;
}
if ((flags & (HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING|HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM)) == HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING) {
/* RESTRICT_TO_CPUBINDING requires THISSYSTEM for binding */
errno = EINVAL;
return -1;
}
if ((flags & (HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_MEMBINDING|HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM)) == HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_MEMBINDING) {
/* RESTRICT_TO_MEMBINDING requires THISSYSTEM for binding */
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -4003,6 +4109,31 @@ hwloc_topology_load (struct hwloc_topology *topology)
topology->is_loaded = 1; topology->is_loaded = 1;
if (topology->flags & HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_CPUBINDING) {
/* FIXME: filter directly in backends during the discovery.
* Only x86 does it because binding may cause issues on Windows.
*/
hwloc_bitmap_t set = hwloc_bitmap_alloc();
if (set) {
err = hwloc_get_cpubind(topology, set, HWLOC_CPUBIND_STRICT);
if (!err)
hwloc_topology_restrict(topology, set, 0);
hwloc_bitmap_free(set);
}
}
if (topology->flags & HWLOC_TOPOLOGY_FLAG_RESTRICT_TO_MEMBINDING) {
/* FIXME: filter directly in backends during the discovery.
*/
hwloc_bitmap_t set = hwloc_bitmap_alloc();
hwloc_membind_policy_t policy;
if (set) {
err = hwloc_get_membind(topology, set, &policy, HWLOC_MEMBIND_STRICT | HWLOC_MEMBIND_BYNODESET);
if (!err)
hwloc_topology_restrict(topology, set, HWLOC_RESTRICT_FLAG_BYNODESET);
hwloc_bitmap_free(set);
}
}
if (topology->backend_phases & HWLOC_DISC_PHASE_TWEAK) { if (topology->backend_phases & HWLOC_DISC_PHASE_TWEAK) {
dstatus.phase = HWLOC_DISC_PHASE_TWEAK; dstatus.phase = HWLOC_DISC_PHASE_TWEAK;
hwloc_discover_by_phase(topology, &dstatus, "TWEAK"); hwloc_discover_by_phase(topology, &dstatus, "TWEAK");
@@ -4278,14 +4409,13 @@ hwloc_topology_restrict(struct hwloc_topology *topology, hwloc_const_bitmap_t se
hwloc_bitmap_free(droppedcpuset); hwloc_bitmap_free(droppedcpuset);
hwloc_bitmap_free(droppednodeset); hwloc_bitmap_free(droppednodeset);
if (hwloc_topology_reconnect(topology, 0) < 0) if (hwloc_filter_levels_keep_structure(topology) < 0) /* takes care of reconnecting internally */
goto out; goto out;
/* some objects may have disappeared, we need to update distances objs arrays */ /* some objects may have disappeared, we need to update distances objs arrays */
hwloc_internal_distances_invalidate_cached_objs(topology); hwloc_internal_distances_invalidate_cached_objs(topology);
hwloc_internal_memattrs_need_refresh(topology); hwloc_internal_memattrs_need_refresh(topology);
hwloc_filter_levels_keep_structure(topology);
hwloc_propagate_symmetric_subtree(topology, topology->levels[0][0]); hwloc_propagate_symmetric_subtree(topology, topology->levels[0][0]);
propagate_total_memory(topology->levels[0][0]); propagate_total_memory(topology->levels[0][0]);
hwloc_internal_cpukinds_restrict(topology); hwloc_internal_cpukinds_restrict(topology);

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2009 CNRS * Copyright © 2009 CNRS
* Copyright © 2009-2020 Inria. All rights reserved. * Copyright © 2009-2021 Inria. All rights reserved.
* Copyright © 2009-2010, 2020 Université Bordeaux * Copyright © 2009-2010, 2020 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.
@@ -395,6 +395,8 @@ hwloc_type_sscanf(const char *string, hwloc_obj_type_t *typep,
} else if (hwloc__type_match(string, "pcibridge", 5)) { } else if (hwloc__type_match(string, "pcibridge", 5)) {
type = HWLOC_OBJ_BRIDGE; type = HWLOC_OBJ_BRIDGE;
ubtype = HWLOC_OBJ_BRIDGE_PCI; ubtype = HWLOC_OBJ_BRIDGE_PCI;
/* if downstream_type can ever be non-PCI, we'll have to make strings more precise,
* or relax the hwloc_type_sscanf test */
} else if (hwloc__type_match(string, "pcidev", 3)) { } else if (hwloc__type_match(string, "pcidev", 3)) {
type = HWLOC_OBJ_PCI_DEVICE; type = HWLOC_OBJ_PCI_DEVICE;
@@ -448,7 +450,9 @@ hwloc_type_sscanf(const char *string, hwloc_obj_type_t *typep,
attrp->group.depth = depthattr; attrp->group.depth = depthattr;
} else if (type == HWLOC_OBJ_BRIDGE && attrsize >= sizeof(attrp->bridge)) { } else if (type == HWLOC_OBJ_BRIDGE && attrsize >= sizeof(attrp->bridge)) {
attrp->bridge.upstream_type = ubtype; attrp->bridge.upstream_type = ubtype;
attrp->bridge.downstream_type = HWLOC_OBJ_BRIDGE_PCI; /* nothing else so far */ attrp->bridge.downstream_type = HWLOC_OBJ_BRIDGE_PCI;
/* if downstream_type can ever be non-PCI, we'll have to make strings more precise,
* or relax the hwloc_type_sscanf test */
} else if (type == HWLOC_OBJ_OS_DEVICE && attrsize >= sizeof(attrp->osdev)) { } else if (type == HWLOC_OBJ_OS_DEVICE && attrsize >= sizeof(attrp->osdev)) {
attrp->osdev.type = ostype; attrp->osdev.type = ostype;
} }
@@ -531,6 +535,9 @@ hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t
else else
return hwloc_snprintf(string, size, "%s", hwloc_obj_type_string(type)); return hwloc_snprintf(string, size, "%s", hwloc_obj_type_string(type));
case HWLOC_OBJ_BRIDGE: case HWLOC_OBJ_BRIDGE:
/* if downstream_type can ever be non-PCI, we'll have to make strings more precise,
* or relax the hwloc_type_sscanf test */
assert(obj->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI);
return hwloc_snprintf(string, size, obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI ? "PCIBridge" : "HostBridge"); return hwloc_snprintf(string, size, obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI ? "PCIBridge" : "HostBridge");
case HWLOC_OBJ_PCI_DEVICE: case HWLOC_OBJ_PCI_DEVICE:
return hwloc_snprintf(string, size, "PCI"); return hwloc_snprintf(string, size, "PCI");
@@ -648,8 +655,11 @@ hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t
} else } else
*up = '\0'; *up = '\0';
/* downstream is_PCI */ /* downstream is_PCI */
snprintf(down, sizeof(down), "buses=%04x:[%02x-%02x]", if (obj->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI) {
obj->attr->bridge.downstream.pci.domain, obj->attr->bridge.downstream.pci.secondary_bus, obj->attr->bridge.downstream.pci.subordinate_bus); snprintf(down, sizeof(down), "buses=%04x:[%02x-%02x]",
obj->attr->bridge.downstream.pci.domain, obj->attr->bridge.downstream.pci.secondary_bus, obj->attr->bridge.downstream.pci.subordinate_bus);
} else
assert(0);
if (*up) if (*up)
res = hwloc_snprintf(string, size, "%s%s%s", up, separator, down); res = hwloc_snprintf(string, size, "%s%s%s", up, separator, down);
else else
@@ -736,3 +746,92 @@ int hwloc_bitmap_singlify_per_core(hwloc_topology_t topology, hwloc_bitmap_t cpu
} }
return 0; return 0;
} }
hwloc_obj_t
hwloc_get_obj_with_same_locality(hwloc_topology_t topology, hwloc_obj_t src,
hwloc_obj_type_t type, const char *subtype, const char *nameprefix,
unsigned long flags)
{
if (flags) {
errno = EINVAL;
return NULL;
}
if (hwloc_obj_type_is_normal(src->type) || hwloc_obj_type_is_memory(src->type)) {
/* normal/memory type, look for normal/memory type with same sets */
hwloc_obj_t obj;
if (!hwloc_obj_type_is_normal(type) && !hwloc_obj_type_is_memory(type)) {
errno = EINVAL;
return NULL;
}
obj = NULL;
while ((obj = hwloc_get_next_obj_by_type(topology, type, obj)) != NULL) {
if (!hwloc_bitmap_isequal(src->cpuset, obj->cpuset)
|| !hwloc_bitmap_isequal(src->nodeset, obj->nodeset))
continue;
if (subtype && (!obj->subtype || strcasecmp(subtype, obj->subtype)))
continue;
if (nameprefix && (!obj->name || hwloc_strncasecmp(nameprefix, obj->name, strlen(nameprefix))))
continue;
return obj;
}
errno = ENOENT;
return NULL;
} else if (hwloc_obj_type_is_io(src->type)) {
/* I/O device, look for PCI/OS in same PCI */
hwloc_obj_t pci;
if ((src->type != HWLOC_OBJ_OS_DEVICE && src->type != HWLOC_OBJ_PCI_DEVICE)
|| (type != HWLOC_OBJ_OS_DEVICE && type != HWLOC_OBJ_PCI_DEVICE)) {
errno = EINVAL;
return NULL;
}
/* walk up to find the container */
pci = src;
while (pci->type == HWLOC_OBJ_OS_DEVICE)
pci = pci->parent;
if (type == HWLOC_OBJ_PCI_DEVICE) {
if (pci->type != HWLOC_OBJ_PCI_DEVICE) {
errno = ENOENT;
return NULL;
}
if (subtype && (!pci->subtype || strcasecmp(subtype, pci->subtype))) {
errno = ENOENT;
return NULL;
}
if (nameprefix && (!pci->name || hwloc_strncasecmp(nameprefix, pci->name, strlen(nameprefix)))) {
errno = ENOENT;
return NULL;
}
return pci;
} else {
/* find a matching osdev child */
assert(type == HWLOC_OBJ_OS_DEVICE);
/* FIXME: won't work if we ever store osdevs in osdevs */
hwloc_obj_t child;
for(child = pci->io_first_child; child; child = child->next_sibling) {
if (child->type != HWLOC_OBJ_OS_DEVICE)
/* FIXME: should never occur currently */
continue;
if (subtype && (!child->subtype || strcasecmp(subtype, child->subtype)))
continue;
if (nameprefix && (!child->name || hwloc_strncasecmp(nameprefix, child->name, strlen(nameprefix))))
continue;
return child;
}
}
errno = ENOENT;
return NULL;
} else {
/* nothing for Misc */
errno = EINVAL;
return NULL;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,28 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_ALLOCATORS_H_ #ifndef RAPIDJSON_ALLOCATORS_H_
#define RAPIDJSON_ALLOCATORS_H_ #define RAPIDJSON_ALLOCATORS_H_
#include "rapidjson.h" #include "rapidjson.h"
#include "internal/meta.h"
#include <memory>
#if RAPIDJSON_HAS_CXX11
#include <type_traits>
#endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@@ -24,10 +31,10 @@ RAPIDJSON_NAMESPACE_BEGIN
/*! \class rapidjson::Allocator /*! \class rapidjson::Allocator
\brief Concept for allocating, resizing and freeing memory block. \brief Concept for allocating, resizing and freeing memory block.
Note that Malloc() and Realloc() are non-static but Free() is static. Note that Malloc() and Realloc() are non-static but Free() is static.
So if an allocator need to support Free(), it needs to put its pointer in So if an allocator need to support Free(), it needs to put its pointer in
the header of memory block. the header of memory block.
\code \code
@@ -75,28 +82,35 @@ concept Allocator {
class CrtAllocator { class CrtAllocator {
public: public:
static const bool kNeedFree = true; static const bool kNeedFree = true;
void* Malloc(size_t size) { void* Malloc(size_t size) {
if (size) // behavior of malloc(0) is implementation defined. if (size) // behavior of malloc(0) is implementation defined.
return std::malloc(size); return RAPIDJSON_MALLOC(size);
else else
return NULL; // standardize to returning NULL. return NULL; // standardize to returning NULL.
} }
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
(void)originalSize; (void)originalSize;
if (newSize == 0) { if (newSize == 0) {
std::free(originalPtr); RAPIDJSON_FREE(originalPtr);
return NULL; return NULL;
} }
return std::realloc(originalPtr, newSize); return RAPIDJSON_REALLOC(originalPtr, newSize);
}
static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
return true;
}
bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
return false;
} }
static void Free(void *ptr) { std::free(ptr); }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// MemoryPoolAllocator // MemoryPoolAllocator
//! Default memory allocator used by the parser and DOM. //! Default memory allocator used by the parser and DOM.
/*! This allocator allocate memory blocks from pre-allocated memory chunks. /*! This allocator allocate memory blocks from pre-allocated memory chunks.
It does not free memory blocks. And Realloc() only allocate new memory. It does not free memory blocks. And Realloc() only allocate new memory.
@@ -113,16 +127,64 @@ public:
*/ */
template <typename BaseAllocator = CrtAllocator> template <typename BaseAllocator = CrtAllocator>
class MemoryPoolAllocator { class MemoryPoolAllocator {
//! Chunk header for perpending to each chunk.
/*! Chunks are stored as a singly linked list.
*/
struct ChunkHeader {
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
size_t size; //!< Current size of allocated memory in bytes.
ChunkHeader *next; //!< Next chunk in the linked list.
};
struct SharedData {
ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
size_t refcount;
bool ownBuffer;
};
static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
static inline ChunkHeader *GetChunkHead(SharedData *shared)
{
return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
}
static inline uint8_t *GetChunkBuffer(SharedData *shared)
{
return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
}
static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
public: public:
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy
//! Constructor with chunkSize. //! Constructor with chunkSize.
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks. \param baseAllocator The allocator for allocating memory chunks.
*/ */
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : explicit
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunk_capacity_(chunkSize),
baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
{ {
RAPIDJSON_ASSERT(baseAllocator_ != 0);
RAPIDJSON_ASSERT(shared_ != 0);
if (baseAllocator) {
shared_->ownBaseAllocator = 0;
}
else {
shared_->ownBaseAllocator = baseAllocator_;
}
shared_->chunkHead = GetChunkHead(shared_);
shared_->chunkHead->capacity = 0;
shared_->chunkHead->size = 0;
shared_->chunkHead->next = 0;
shared_->ownBuffer = true;
shared_->refcount = 1;
} }
//! Constructor with user-supplied buffer. //! Constructor with user-supplied buffer.
@@ -136,41 +198,101 @@ public:
\param baseAllocator The allocator for allocating memory chunks. \param baseAllocator The allocator for allocating memory chunks.
*/ */
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) chunk_capacity_(chunkSize),
baseAllocator_(baseAllocator),
shared_(static_cast<SharedData*>(AlignBuffer(buffer, size)))
{ {
RAPIDJSON_ASSERT(buffer != 0); RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); shared_->chunkHead = GetChunkHead(shared_);
chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer); shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
chunkHead_->capacity = size - sizeof(ChunkHeader); shared_->chunkHead->size = 0;
chunkHead_->size = 0; shared_->chunkHead->next = 0;
chunkHead_->next = 0; shared_->ownBaseAllocator = 0;
shared_->ownBuffer = false;
shared_->refcount = 1;
} }
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
chunk_capacity_(rhs.chunk_capacity_),
baseAllocator_(rhs.baseAllocator_),
shared_(rhs.shared_)
{
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
++shared_->refcount;
}
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
{
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
++rhs.shared_->refcount;
this->~MemoryPoolAllocator();
baseAllocator_ = rhs.baseAllocator_;
chunk_capacity_ = rhs.chunk_capacity_;
shared_ = rhs.shared_;
return *this;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
chunk_capacity_(rhs.chunk_capacity_),
baseAllocator_(rhs.baseAllocator_),
shared_(rhs.shared_)
{
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
rhs.shared_ = 0;
}
MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
{
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
this->~MemoryPoolAllocator();
baseAllocator_ = rhs.baseAllocator_;
chunk_capacity_ = rhs.chunk_capacity_;
shared_ = rhs.shared_;
rhs.shared_ = 0;
return *this;
}
#endif
//! Destructor. //! Destructor.
/*! This deallocates all memory chunks, excluding the user-supplied buffer. /*! This deallocates all memory chunks, excluding the user-supplied buffer.
*/ */
~MemoryPoolAllocator() { ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT {
if (!shared_) {
// do nothing if moved
return;
}
if (shared_->refcount > 1) {
--shared_->refcount;
return;
}
Clear(); Clear();
RAPIDJSON_DELETE(ownBaseAllocator_); BaseAllocator *a = shared_->ownBaseAllocator;
if (shared_->ownBuffer) {
baseAllocator_->Free(shared_);
}
RAPIDJSON_DELETE(a);
} }
//! Deallocates all memory chunks, excluding the user-supplied buffer. //! Deallocates all memory chunks, excluding the first/user one.
void Clear() { void Clear() RAPIDJSON_NOEXCEPT {
while (chunkHead_ && chunkHead_ != userBuffer_) { RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
ChunkHeader* next = chunkHead_->next; for (;;) {
baseAllocator_->Free(chunkHead_); ChunkHeader* c = shared_->chunkHead;
chunkHead_ = next; if (!c->next) {
break;
}
shared_->chunkHead = c->next;
baseAllocator_->Free(c);
} }
if (chunkHead_ && chunkHead_ == userBuffer_) shared_->chunkHead->size = 0;
chunkHead_->size = 0; // Clear user buffer
} }
//! Computes the total capacity of allocated memory chunks. //! Computes the total capacity of allocated memory chunks.
/*! \return total capacity in bytes. /*! \return total capacity in bytes.
*/ */
size_t Capacity() const { size_t Capacity() const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
size_t capacity = 0; size_t capacity = 0;
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
capacity += c->capacity; capacity += c->capacity;
return capacity; return capacity;
} }
@@ -178,25 +300,35 @@ public:
//! Computes the memory blocks allocated. //! Computes the memory blocks allocated.
/*! \return total used bytes. /*! \return total used bytes.
*/ */
size_t Size() const { size_t Size() const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
size_t size = 0; size_t size = 0;
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
size += c->size; size += c->size;
return size; return size;
} }
//! Whether the allocator is shared.
/*! \return true or false.
*/
bool Shared() const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
return shared_->refcount > 1;
}
//! Allocates a memory block. (concept Allocator) //! Allocates a memory block. (concept Allocator)
void* Malloc(size_t size) { void* Malloc(size_t size) {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
if (!size) if (!size)
return NULL; return NULL;
size = RAPIDJSON_ALIGN(size); size = RAPIDJSON_ALIGN(size);
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
return NULL; return NULL;
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
chunkHead_->size += size; shared_->chunkHead->size += size;
return buffer; return buffer;
} }
@@ -205,6 +337,7 @@ public:
if (originalPtr == 0) if (originalPtr == 0)
return Malloc(newSize); return Malloc(newSize);
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
if (newSize == 0) if (newSize == 0)
return NULL; return NULL;
@@ -216,10 +349,10 @@ public:
return originalPtr; return originalPtr;
// Simply expand it if it is the last allocation and there is sufficient space // Simply expand it if it is the last allocation and there is sufficient space
if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
size_t increment = static_cast<size_t>(newSize - originalSize); size_t increment = static_cast<size_t>(newSize - originalSize);
if (chunkHead_->size + increment <= chunkHead_->capacity) { if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
chunkHead_->size += increment; shared_->chunkHead->size += increment;
return originalPtr; return originalPtr;
} }
} }
@@ -235,50 +368,325 @@ public:
} }
//! Frees a memory block (concept Allocator) //! Frees a memory block (concept Allocator)
static void Free(void *ptr) { (void)ptr; } // Do nothing static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
//! Compare (equality) with another MemoryPoolAllocator
bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
return shared_ == rhs.shared_;
}
//! Compare (inequality) with another MemoryPoolAllocator
bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
return !operator==(rhs);
}
private: private:
//! Copy constructor is not permitted.
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
//! Copy assignment operator is not permitted.
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
//! Creates a new chunk. //! Creates a new chunk.
/*! \param capacity Capacity of the chunk in bytes. /*! \param capacity Capacity of the chunk in bytes.
\return true if success. \return true if success.
*/ */
bool AddChunk(size_t capacity) { bool AddChunk(size_t capacity) {
if (!baseAllocator_) if (!baseAllocator_)
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)(); shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) { if (ChunkHeader* chunk = static_cast<ChunkHeader*>(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
chunk->capacity = capacity; chunk->capacity = capacity;
chunk->size = 0; chunk->size = 0;
chunk->next = chunkHead_; chunk->next = shared_->chunkHead;
chunkHead_ = chunk; shared_->chunkHead = chunk;
return true; return true;
} }
else else
return false; return false;
} }
static const int kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity. static inline void* AlignBuffer(void* buf, size_t &size)
{
RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
const uintptr_t mask = sizeof(void*) - 1;
const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf);
if (RAPIDJSON_UNLIKELY(ubuf & mask)) {
const uintptr_t abuf = (ubuf + mask) & ~mask;
RAPIDJSON_ASSERT(size >= abuf - ubuf);
buf = reinterpret_cast<void*>(abuf);
size -= abuf - ubuf;
}
return buf;
}
//! Chunk header for perpending to each chunk. size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
/*! Chunks are stored as a singly linked list. BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
*/ SharedData *shared_; //!< The shared data of the allocator
struct ChunkHeader { };
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
size_t size; //!< Current size of allocated memory in bytes. namespace internal {
ChunkHeader *next; //!< Next chunk in the linked list. template<typename, typename = void>
struct IsRefCounted :
public FalseType
{ };
template<typename T>
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> :
public TrueType
{ };
}
template<typename T, typename A>
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));
return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
}
template<typename T, typename A>
inline T *Malloc(A& a, size_t n = 1)
{
return Realloc<T, A>(a, NULL, 0, n);
}
template<typename T, typename A>
inline void Free(A& a, T *p, size_t n = 1)
{
static_cast<void>(Realloc<T, A>(a, p, n, 0));
}
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
#endif
template <typename T, typename BaseAllocator = CrtAllocator>
class StdAllocator :
public std::allocator<T>
{
typedef std::allocator<T> allocator_type;
#if RAPIDJSON_HAS_CXX11
typedef std::allocator_traits<allocator_type> traits_type;
#else
typedef allocator_type traits_type;
#endif
public:
typedef BaseAllocator BaseAllocatorType;
StdAllocator() RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_()
{ }
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
template<typename U>
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(std::move(rhs)),
baseAllocator_(std::move(rhs.baseAllocator_))
{ }
#endif
#if RAPIDJSON_HAS_CXX11
using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type;
#endif
/* implicit */
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_(allocator)
{ }
~StdAllocator() RAPIDJSON_NOEXCEPT
{ }
template<typename U>
struct rebind {
typedef StdAllocator<U, BaseAllocator> other;
}; };
ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. typedef typename traits_type::size_type size_type;
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. typedef typename traits_type::difference_type difference_type;
void *userBuffer_; //!< User supplied buffer.
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. typedef typename traits_type::value_type value_type;
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. typedef typename traits_type::pointer pointer;
typedef typename traits_type::const_pointer const_pointer;
#if RAPIDJSON_HAS_CXX11
typedef typename std::add_lvalue_reference<value_type>::type &reference;
typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type &const_reference;
pointer address(reference r) const RAPIDJSON_NOEXCEPT
{
return std::addressof(r);
}
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
{
return std::addressof(r);
}
size_type max_size() const RAPIDJSON_NOEXCEPT
{
return traits_type::max_size(*this);
}
template <typename ...Args>
void construct(pointer p, Args&&... args)
{
traits_type::construct(*this, p, std::forward<Args>(args)...);
}
void destroy(pointer p)
{
traits_type::destroy(*this, p);
}
#else // !RAPIDJSON_HAS_CXX11
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
pointer address(reference r) const RAPIDJSON_NOEXCEPT
{
return allocator_type::address(r);
}
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
{
return allocator_type::address(r);
}
size_type max_size() const RAPIDJSON_NOEXCEPT
{
return allocator_type::max_size();
}
void construct(pointer p, const_reference r)
{
allocator_type::construct(p, r);
}
void destroy(pointer p)
{
allocator_type::destroy(p);
}
#endif // !RAPIDJSON_HAS_CXX11
template <typename U>
U* allocate(size_type n = 1, const void* = 0)
{
return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
}
template <typename U>
void deallocate(U* p, size_type n = 1)
{
RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
}
pointer allocate(size_type n = 1, const void* = 0)
{
return allocate<value_type>(n);
}
void deallocate(pointer p, size_type n = 1)
{
deallocate<value_type>(p, n);
}
#if RAPIDJSON_HAS_CXX11
using is_always_equal = std::is_empty<BaseAllocator>;
#endif
template<typename U>
bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
{
return baseAllocator_ == rhs.baseAllocator_;
}
template<typename U>
bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
{
return !operator==(rhs);
}
//! rapidjson Allocator concept
static const bool kNeedFree = BaseAllocator::kNeedFree;
static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
void* Malloc(size_t size)
{
return baseAllocator_.Malloc(size);
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
{
return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
}
static void Free(void *ptr) RAPIDJSON_NOEXCEPT
{
BaseAllocator::Free(ptr);
}
private:
template <typename, typename>
friend class StdAllocator; // access to StdAllocator<!T>.*
BaseAllocator baseAllocator_;
}; };
#if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17
template <typename BaseAllocator>
class StdAllocator<void, BaseAllocator> :
public std::allocator<void>
{
typedef std::allocator<void> allocator_type;
public:
typedef BaseAllocator BaseAllocatorType;
StdAllocator() RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_()
{ }
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
template<typename U>
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
/* implicit */
StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_(baseAllocator)
{ }
~StdAllocator() RAPIDJSON_NOEXCEPT
{ }
template<typename U>
struct rebind {
typedef StdAllocator<U, BaseAllocator> other;
};
typedef typename allocator_type::value_type value_type;
private:
template <typename, typename>
friend class StdAllocator; // access to StdAllocator<!T>.*
BaseAllocator baseAllocator_;
};
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_ENCODINGS_H_ #endif // RAPIDJSON_ENCODINGS_H_

View File

@@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_ENCODEDSTREAM_H_ #ifndef RAPIDJSON_ENCODEDSTREAM_H_
@@ -41,7 +41,7 @@ class EncodedInputStream {
public: public:
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
EncodedInputStream(InputByteStream& is) : is_(is) { EncodedInputStream(InputByteStream& is) : is_(is) {
current_ = Encoding::TakeBOM(is_); current_ = Encoding::TakeBOM(is_);
} }
@@ -51,7 +51,7 @@ public:
// Not implemented // Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
@@ -80,7 +80,7 @@ public:
// Not implemented // Not implemented
void Put(Ch) {} void Put(Ch) {}
void Flush() {} void Flush() {}
Ch* PutBegin() { return 0; } Ch* PutBegin() { return 0; }
size_t PutEnd(Ch*) { return 0; } size_t PutEnd(Ch*) { return 0; }
@@ -102,7 +102,7 @@ class EncodedOutputStream {
public: public:
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
if (putBOM) if (putBOM)
Encoding::PutBOM(os_); Encoding::PutBOM(os_);
} }
@@ -143,7 +143,7 @@ public:
\param type UTF encoding type if it is not detected from the stream. \param type UTF encoding type if it is not detected from the stream.
*/ */
AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
DetectType(); DetectType();
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
takeFunc_ = f[type_]; takeFunc_ = f[type_];
@@ -159,7 +159,7 @@ public:
// Not implemented // Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
@@ -258,7 +258,7 @@ public:
UTFType GetType() const { return type_; } UTFType GetType() const { return type_; }
void Put(Ch c) { putFunc_(*os_, c); } void Put(Ch c) { putFunc_(*os_, c); }
void Flush() { os_->Flush(); } void Flush() { os_->Flush(); }
// Not implemented // Not implemented
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
@@ -271,7 +271,7 @@ private:
AutoUTFOutputStream(const AutoUTFOutputStream&); AutoUTFOutputStream(const AutoUTFOutputStream&);
AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
void PutBOM() { void PutBOM() {
typedef void (*PutBOMFunc)(OutputByteStream&); typedef void (*PutBOMFunc)(OutputByteStream&);
static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
f[type_](*os_); f[type_](*os_);

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_ENCODINGS_H_ #ifndef RAPIDJSON_ENCODINGS_H_
@@ -100,7 +100,7 @@ struct UTF8 {
template<typename OutputStream> template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint) { static void Encode(OutputStream& os, unsigned codepoint) {
if (codepoint <= 0x7F) if (codepoint <= 0x7F)
os.Put(static_cast<Ch>(codepoint & 0xFF)); os.Put(static_cast<Ch>(codepoint & 0xFF));
else if (codepoint <= 0x7FF) { else if (codepoint <= 0x7FF) {
os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
@@ -122,7 +122,7 @@ struct UTF8 {
template<typename OutputStream> template<typename OutputStream>
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
if (codepoint <= 0x7F) if (codepoint <= 0x7F)
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
else if (codepoint <= 0x7FF) { else if (codepoint <= 0x7FF) {
PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
@@ -276,7 +276,7 @@ struct UTF16 {
static void Encode(OutputStream& os, unsigned codepoint) { static void Encode(OutputStream& os, unsigned codepoint) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
if (codepoint <= 0xFFFF) { if (codepoint <= 0xFFFF) {
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
os.Put(static_cast<typename OutputStream::Ch>(codepoint)); os.Put(static_cast<typename OutputStream::Ch>(codepoint));
} }
else { else {
@@ -292,7 +292,7 @@ struct UTF16 {
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
if (codepoint <= 0xFFFF) { if (codepoint <= 0xFFFF) {
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint)); PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
} }
else { else {
@@ -406,7 +406,7 @@ struct UTF16BE : UTF16<CharType> {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// UTF32 // UTF32
//! UTF-32 encoding. //! UTF-32 encoding.
/*! http://en.wikipedia.org/wiki/UTF-32 /*! http://en.wikipedia.org/wiki/UTF-32
\tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
\note implements Encoding concept \note implements Encoding concept
@@ -498,7 +498,7 @@ struct UTF32BE : UTF32<CharType> {
static CharType TakeBOM(InputByteStream& is) { static CharType TakeBOM(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
CharType c = Take(is); CharType c = Take(is);
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
} }
template <typename InputByteStream> template <typename InputByteStream>
@@ -694,13 +694,13 @@ struct Transcoder<Encoding, Encoding> {
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true; return true;
} }
template<typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true; return true;
} }
template<typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
return Encoding::Validate(is, os); // source/target encoding are the same return Encoding::Validate(is, os); // source/target encoding are the same

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_ERROR_EN_H_ #ifndef RAPIDJSON_ERROR_EN_H_
@@ -39,13 +39,13 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
@@ -65,6 +65,54 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
} }
} }
//! Maps error code of validation into error message.
/*!
\ingroup RAPIDJSON_ERRORS
\param validateErrorCode Error code obtained from validator.
\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* GetValidateError_En(ValidateErrorCode validateErrorCode) {
switch (validateErrorCode) {
case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'.");
case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'.");
case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'.");
case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'.");
case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'.");
case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'.");
case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'.");
case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'.");
case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'.");
case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true.");
case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema.");
case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'.");
case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'.");
case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema.");
case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema.");
case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors.");
case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values.");
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 kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'.");
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 kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
}
}
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END
#ifdef __clang__ #ifdef __clang__

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_ERROR_ERROR_H_ #ifndef RAPIDJSON_ERROR_ERROR_H_
@@ -152,6 +152,61 @@ private:
*/ */
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
///////////////////////////////////////////////////////////////////////////////
// ValidateErrorCode
//! Error codes when validating.
/*! \ingroup RAPIDJSON_ERRORS
\see GenericSchemaValidator
*/
enum ValidateErrorCode {
kValidateErrors = -1, //!< Top level error code when kValidateContinueOnErrorsFlag set.
kValidateErrorNone = 0, //!< No error.
kValidateErrorMultipleOf, //!< Number is not a multiple of the 'multipleOf' value.
kValidateErrorMaximum, //!< Number is greater than the 'maximum' value.
kValidateErrorExclusiveMaximum, //!< Number is greater than or equal to the 'maximum' value.
kValidateErrorMinimum, //!< Number is less than the 'minimum' value.
kValidateErrorExclusiveMinimum, //!< Number is less than or equal to the 'minimum' value.
kValidateErrorMaxLength, //!< String is longer than the 'maxLength' value.
kValidateErrorMinLength, //!< String is longer than the 'maxLength' value.
kValidateErrorPattern, //!< String does not match the 'pattern' regular expression.
kValidateErrorMaxItems, //!< Array is longer than the 'maxItems' value.
kValidateErrorMinItems, //!< Array is shorter than the 'minItems' value.
kValidateErrorUniqueItems, //!< Array has duplicate items but 'uniqueItems' is true.
kValidateErrorAdditionalItems, //!< Array has additional items that are not allowed by the schema.
kValidateErrorMaxProperties, //!< Object has more members than 'maxProperties' value.
kValidateErrorMinProperties, //!< Object has less members than 'minProperties' value.
kValidateErrorRequired, //!< Object is missing one or more members required by the schema.
kValidateErrorAdditionalProperties, //!< Object has additional members that are not allowed by the schema.
kValidateErrorPatternProperties, //!< See other errors.
kValidateErrorDependencies, //!< Object has missing property or schema dependencies.
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..
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'.
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'.
kValidateErrorNot //!< Property matched the sub-schema specified by 'not'.
};
//! Function pointer type of GetValidateError().
/*! \ingroup RAPIDJSON_ERRORS
This is the prototype for \c GetValidateError_X(), where \c X is a locale.
User can dynamically change locale in runtime, e.g.:
\code
GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever
const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode());
\endcode
*/
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode);
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END
#ifdef __clang__ #ifdef __clang__

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_FILEREADSTREAM_H_ #ifndef RAPIDJSON_FILEREADSTREAM_H_
@@ -41,7 +41,7 @@ public:
\param buffer user-supplied buffer. \param buffer user-supplied buffer.
\param bufferSize size of buffer in bytes. Must >=4 bytes. \param bufferSize size of buffer in bytes. Must >=4 bytes.
*/ */
FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
RAPIDJSON_ASSERT(fp_ != 0); RAPIDJSON_ASSERT(fp_ != 0);
RAPIDJSON_ASSERT(bufferSize >= 4); RAPIDJSON_ASSERT(bufferSize >= 4);
Read(); Read();
@@ -53,7 +53,7 @@ public:
// Not implemented // Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_FILEWRITESTREAM_H_ #ifndef RAPIDJSON_FILEWRITESTREAM_H_
@@ -33,11 +33,11 @@ class FileWriteStream {
public: public:
typedef char Ch; //!< Character type. Only support char. typedef char Ch; //!< Character type. Only support char.
FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
RAPIDJSON_ASSERT(fp_ != 0); RAPIDJSON_ASSERT(fp_ != 0);
} }
void Put(char c) { void Put(char c) {
if (current_ >= bufferEnd_) if (current_ >= bufferEnd_)
Flush(); Flush();

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_FWD_H_ #ifndef RAPIDJSON_FWD_H_
@@ -101,8 +101,8 @@ class PrettyWriter;
// document.h // document.h
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
struct GenericMember; class GenericMember;
template <bool Const, typename Encoding, typename Allocator> template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator; class GenericMemberIterator;
@@ -110,7 +110,7 @@ class GenericMemberIterator;
template<typename CharType> template<typename CharType>
struct GenericStringRef; struct GenericStringRef;
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class GenericValue; class GenericValue;
typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value; typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_BIGINTEGER_H_ #ifndef RAPIDJSON_BIGINTEGER_H_
@@ -17,7 +17,7 @@
#include "../rapidjson.h" #include "../rapidjson.h"
#if defined(_MSC_VER) && !__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
#pragma intrinsic(_umul128) #pragma intrinsic(_umul128)
#endif #endif
@@ -37,7 +37,8 @@ public:
digits_[0] = u; digits_[0] = u;
} }
BigInteger(const char* decimals, size_t length) : count_(1) { template<typename Ch>
BigInteger(const Ch* decimals, size_t length) : count_(1) {
RAPIDJSON_ASSERT(length > 0); RAPIDJSON_ASSERT(length > 0);
digits_[0] = 0; digits_[0] = 0;
size_t i = 0; size_t i = 0;
@@ -51,7 +52,7 @@ public:
if (length > 0) if (length > 0)
AppendDecimal64(decimals + i, decimals + i + length); AppendDecimal64(decimals + i, decimals + i + length);
} }
BigInteger& operator=(const BigInteger &rhs) BigInteger& operator=(const BigInteger &rhs)
{ {
if (this != &rhs) { if (this != &rhs) {
@@ -60,9 +61,9 @@ public:
} }
return *this; return *this;
} }
BigInteger& operator=(uint64_t u) { BigInteger& operator=(uint64_t u) {
digits_[0] = u; digits_[0] = u;
count_ = 1; count_ = 1;
return *this; return *this;
} }
@@ -95,7 +96,7 @@ public:
digits_[i] = MulAdd64(digits_[i], u, k, &hi); digits_[i] = MulAdd64(digits_[i], u, k, &hi);
k = hi; k = hi;
} }
if (k > 0) if (k > 0)
PushBack(k); PushBack(k);
@@ -118,7 +119,7 @@ public:
digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
k = p1 >> 32; k = p1 >> 32;
} }
if (k > 0) if (k > 0)
PushBack(k); PushBack(k);
@@ -221,7 +222,8 @@ public:
bool IsZero() const { return count_ == 1 && digits_[0] == 0; } bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
private: private:
void AppendDecimal64(const char* begin, const char* end) { template<typename Ch>
void AppendDecimal64(const Ch* begin, const Ch* end) {
uint64_t u = ParseUint64(begin, end); uint64_t u = ParseUint64(begin, end);
if (IsZero()) if (IsZero())
*this = u; *this = u;
@@ -236,11 +238,12 @@ private:
digits_[count_++] = digit; digits_[count_++] = digit;
} }
static uint64_t ParseUint64(const char* begin, const char* end) { template<typename Ch>
static uint64_t ParseUint64(const Ch* begin, const Ch* end) {
uint64_t r = 0; uint64_t r = 0;
for (const char* p = begin; p != end; ++p) { for (const Ch* p = begin; p != end; ++p) {
RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); RAPIDJSON_ASSERT(*p >= Ch('0') && *p <= Ch('9'));
r = r * 10u + static_cast<unsigned>(*p - '0'); r = r * 10u + static_cast<unsigned>(*p - Ch('0'));
} }
return r; return r;
} }

71
src/3rdparty/rapidjson/internal/clzll.h vendored Normal file
View File

@@ -0,0 +1,71 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_CLZLL_H_
#define RAPIDJSON_CLZLL_H_
#include "../rapidjson.h"
#if defined(_MSC_VER) && !defined(UNDER_CE)
#include <intrin.h>
#if defined(_WIN64)
#pragma intrinsic(_BitScanReverse64)
#else
#pragma intrinsic(_BitScanReverse)
#endif
#endif
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
inline uint32_t clzll(uint64_t x) {
// Passing 0 to __builtin_clzll is UB in GCC and results in an
// infinite loop in the software implementation.
RAPIDJSON_ASSERT(x != 0);
#if defined(_MSC_VER) && !defined(UNDER_CE)
unsigned long r = 0;
#if defined(_WIN64)
_BitScanReverse64(&r, x);
#else
// Scan the high 32 bits.
if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
return 63 - (r + 32);
// Scan the low 32 bits.
_BitScanReverse(&r, static_cast<uint32_t>(x & 0xFFFFFFFF));
#endif // _WIN64
return 63 - r;
#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
// __builtin_clzll wrapper
return static_cast<uint32_t>(__builtin_clzll(x));
#else
// naive version
uint32_t r = 0;
while (!(x & (static_cast<uint64_t>(1) << 63))) {
x <<= 1;
++r;
}
return r;
#endif // _MSC_VER
}
#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
} // namespace internal
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_CLZLL_H_

View File

@@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
@@ -20,11 +20,11 @@
#define RAPIDJSON_DIYFP_H_ #define RAPIDJSON_DIYFP_H_
#include "../rapidjson.h" #include "../rapidjson.h"
#include "clzll.h"
#include <limits> #include <limits>
#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>
#pragma intrinsic(_BitScanReverse64)
#pragma intrinsic(_umul128) #pragma intrinsic(_umul128)
#endif #endif
@@ -100,22 +100,8 @@ struct DiyFp {
} }
DiyFp Normalize() const { DiyFp Normalize() const {
RAPIDJSON_ASSERT(f != 0); // https://stackoverflow.com/a/26809183/291737 int s = static_cast<int>(clzll(f));
#if defined(_MSC_VER) && defined(_M_AMD64)
unsigned long index;
_BitScanReverse64(&index, f);
return DiyFp(f << (63 - index), e - (63 - index));
#elif defined(__GNUC__) && __GNUC__ >= 4
int s = __builtin_clzll(f);
return DiyFp(f << s, e - s); return DiyFp(f << s, e - s);
#else
DiyFp res = *this;
while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
res.f <<= 1;
res.e--;
}
return res;
#endif
} }
DiyFp NormalizeBoundary() const { DiyFp NormalizeBoundary() const {

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
// This is a C++ header-only implementation of Grisu2 algorithm from the publication: // This is a C++ header-only implementation of Grisu2 algorithm from the publication:
@@ -58,7 +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 uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; static const uint64_t kPow10[] = { 1U, 10U, 100U, 1000U, 10000U, 100000U, 1000000U, 10000000U, 100000000U,
1000000000U, 10000000000U, 100000000000U, 1000000000000U,
10000000000000U, 100000000000000U, 1000000000000000U,
10000000000000000U, 100000000000000000U, 1000000000000000000U,
10000000000000000000U };
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);
@@ -86,7 +90,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2; uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
if (tmp <= delta) { if (tmp <= delta) {
*K += kappa; *K += kappa;
GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f); GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f);
return; return;
} }
} }
@@ -103,7 +107,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
if (p2 < delta) { if (p2 < delta) {
*K += kappa; *K += kappa;
int index = -kappa; int index = -kappa;
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0)); GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0));
return; return;
} }
} }

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_IEEE754_ #ifndef RAPIDJSON_IEEE754_

View File

@@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_INTERNAL_META_H_ #ifndef RAPIDJSON_INTERNAL_META_H_

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_POW10_ #ifndef RAPIDJSON_POW10_
@@ -27,8 +27,8 @@ namespace internal {
*/ */
inline double Pow10(int n) { inline double Pow10(int n) {
static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
1e+0, 1e+0,
1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_INTERNAL_REGEX_H_ #ifndef RAPIDJSON_INTERNAL_REGEX_H_
@@ -23,7 +23,6 @@
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum) RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
@@ -32,9 +31,6 @@ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#ifdef __GNUC__ #ifdef __GNUC__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) RAPIDJSON_DIAG_OFF(effc++)
#if __GNUC__ >= 7
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
#endif
#endif #endif
#ifndef RAPIDJSON_REGEX_VERBOSE #ifndef RAPIDJSON_REGEX_VERBOSE
@@ -106,9 +102,9 @@ class GenericRegexSearch;
- \c \\t Tab (U+0009) - \c \\t Tab (U+0009)
- \c \\v Vertical tab (U+000B) - \c \\v Vertical tab (U+000B)
\note This is a Thompson NFA engine, implemented with reference to \note This is a Thompson NFA engine, implemented with reference to
Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
https://swtch.com/~rsc/regexp/regexp1.html https://swtch.com/~rsc/regexp/regexp1.html
*/ */
template <typename Encoding, typename Allocator = CrtAllocator> template <typename Encoding, typename Allocator = CrtAllocator>
class GenericRegex { class GenericRegex {
@@ -117,9 +113,9 @@ public:
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
template <typename, typename> friend class GenericRegexSearch; template <typename, typename> friend class GenericRegexSearch;
GenericRegex(const Ch* source, Allocator* allocator = 0) : GenericRegex(const Ch* source, Allocator* allocator = 0) :
ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_), ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_),
states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
anchorBegin_(), anchorEnd_() anchorBegin_(), anchorEnd_()
{ {
GenericStringStream<Encoding> ss(source); GenericStringStream<Encoding> ss(source);
@@ -151,7 +147,7 @@ private:
static const unsigned kRangeNegationFlag = 0x80000000; static const unsigned kRangeNegationFlag = 0x80000000;
struct Range { struct Range {
unsigned start; // unsigned start; //
unsigned end; unsigned end;
SizeType next; SizeType next;
}; };
@@ -291,6 +287,7 @@ private:
if (!CharacterEscape(ds, &codepoint)) if (!CharacterEscape(ds, &codepoint))
return; // Unsupported escape character return; // Unsupported escape character
// fall through to default // fall through to default
RAPIDJSON_DELIBERATE_FALLTHROUGH;
default: // Pattern character default: // Pattern character
PushOperand(operandStack, codepoint); PushOperand(operandStack, codepoint);
@@ -405,7 +402,7 @@ private:
} }
return false; return false;
default: default:
// syntax error (e.g. unclosed kLeftParenthesis) // syntax error (e.g. unclosed kLeftParenthesis)
return false; return false;
} }
@@ -520,6 +517,7 @@ private:
else if (!CharacterEscape(ds, &codepoint)) else if (!CharacterEscape(ds, &codepoint))
return false; return false;
// fall through to default // fall through to default
RAPIDJSON_DELIBERATE_FALLTHROUGH;
default: default:
switch (step) { switch (step) {
@@ -529,6 +527,7 @@ private:
break; break;
} }
// fall through to step 0 for other characters // fall through to step 0 for other characters
RAPIDJSON_DELIBERATE_FALLTHROUGH;
case 0: case 0:
{ {
@@ -551,7 +550,7 @@ private:
} }
return false; return false;
} }
SizeType NewRange(unsigned codepoint) { SizeType NewRange(unsigned codepoint) {
Range* r = ranges_.template Push<Range>(); Range* r = ranges_.template Push<Range>();
r->start = r->end = codepoint; r->start = r->end = codepoint;
@@ -609,7 +608,7 @@ public:
typedef typename RegexType::EncodingType Encoding; typedef typename RegexType::EncodingType Encoding;
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) :
regex_(regex), allocator_(allocator), ownAllocator_(0), regex_(regex), allocator_(allocator), ownAllocator_(0),
state0_(allocator, 0), state1_(allocator, 0), stateSet_() state0_(allocator, 0), state1_(allocator, 0), stateSet_()
{ {
@@ -668,7 +667,7 @@ private:
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) { for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
const State& sr = regex_.GetState(*s); const State& sr = regex_.GetState(*s);
if (sr.codepoint == codepoint || if (sr.codepoint == codepoint ||
sr.codepoint == RegexType::kAnyCharacterClass || sr.codepoint == RegexType::kAnyCharacterClass ||
(sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
{ {
matched = AddState(*next, sr.out) || matched; matched = AddState(*next, sr.out) || matched;

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_INTERNAL_STACK_H_ #ifndef RAPIDJSON_INTERNAL_STACK_H_
@@ -98,7 +98,7 @@ public:
void Clear() { stackTop_ = stack_; } void Clear() { stackTop_ = stack_; }
void ShrinkToFit() { void ShrinkToFit() {
if (Empty()) { if (Empty()) {
// If the stack is empty, completely deallocate the memory. // If the stack is empty, completely deallocate the memory.
Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc) Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
@@ -142,7 +142,7 @@ public:
} }
template<typename T> template<typename T>
T* Top() { T* Top() {
RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
return reinterpret_cast<T*>(stackTop_ - sizeof(T)); return reinterpret_cast<T*>(stackTop_ - sizeof(T));
} }

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
@@ -24,7 +24,7 @@ namespace internal {
//! Custom strlen() which works on different character types. //! Custom strlen() which works on different character types.
/*! \tparam Ch Character type (e.g. char, wchar_t, short) /*! \tparam Ch Character type (e.g. char, wchar_t, short)
\param s Null-terminated input string. \param s Null-terminated input string.
\return Number of characters in the string. \return Number of characters in the string.
\note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
*/ */
template <typename Ch> template <typename Ch>
@@ -45,6 +45,20 @@ inline SizeType StrLen(const wchar_t* s) {
return SizeType(std::wcslen(s)); return SizeType(std::wcslen(s));
} }
//! Custom strcmpn() which works on different character types.
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
\param s1 Null-terminated input string.
\param s2 Null-terminated input string.
\return 0 if equal
*/
template<typename Ch>
inline int StrCmp(const Ch* s1, const Ch* s2) {
RAPIDJSON_ASSERT(s1 != 0);
RAPIDJSON_ASSERT(s2 != 0);
while(*s1 && (*s1 == *s2)) { s1++; s2++; }
return static_cast<unsigned>(*s1) < static_cast<unsigned>(*s2) ? -1 : static_cast<unsigned>(*s1) > static_cast<unsigned>(*s2);
}
//! Returns number of code points in a encoded string. //! Returns number of code points in a encoded string.
template<typename Encoding> template<typename Encoding>
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_STRTOD_ #ifndef RAPIDJSON_STRTOD_
@@ -128,17 +128,18 @@ inline bool StrtodFast(double d, int p, double* result) {
} }
// Compute an approximation and see if it is within 1/2 ULP // Compute an approximation and see if it is within 1/2 ULP
inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) { template<typename Ch>
inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result) {
uint64_t significand = 0; uint64_t significand = 0;
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] > '5')) (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > Ch('5')))
break; break;
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0'); significand = significand * 10u + static_cast<unsigned>(decimals[i] - Ch('0'));
} }
if (i < dLen && decimals[i] >= '5') // Rounding if (i < dLen && decimals[i] >= Ch('5')) // Rounding
significand++; significand++;
int remaining = dLen - i; int remaining = dLen - i;
@@ -184,7 +185,7 @@ inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result
if (precisionSize + kUlpShift >= 64) { if (precisionSize + kUlpShift >= 64) {
int scaleExp = (precisionSize + kUlpShift) - 63; int scaleExp = (precisionSize + kUlpShift) - 63;
v.f >>= scaleExp; v.f >>= scaleExp;
v.e += scaleExp; v.e += scaleExp;
error = (error >> scaleExp) + 1 + kUlp; error = (error >> scaleExp) + 1 + kUlp;
precisionSize -= scaleExp; precisionSize -= scaleExp;
} }
@@ -205,7 +206,8 @@ inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error); return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
} }
inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) { template<typename Ch>
inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) {
RAPIDJSON_ASSERT(dLen >= 0); RAPIDJSON_ASSERT(dLen >= 0);
const BigInteger dInt(decimals, static_cast<unsigned>(dLen)); const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
Double a(approx); Double a(approx);
@@ -223,7 +225,8 @@ inline double StrtodBigInteger(double approx, const char* decimals, int dLen, in
return a.NextPositiveDouble(); return a.NextPositiveDouble();
} }
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { template<typename Ch>
inline double StrtodFullPrecision(double d, int p, const Ch* decimals, size_t length, size_t decimalPosition, int exp) {
RAPIDJSON_ASSERT(d >= 0.0); RAPIDJSON_ASSERT(d >= 0.0);
RAPIDJSON_ASSERT(length >= 1); RAPIDJSON_ASSERT(length >= 1);

View File

@@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_ISTREAMWRAPPER_H_ #ifndef RAPIDJSON_ISTREAMWRAPPER_H_
@@ -44,7 +44,7 @@ RAPIDJSON_NAMESPACE_BEGIN
\tparam StreamType Class derived from \c std::basic_istream. \tparam StreamType Class derived from \c std::basic_istream.
*/ */
template <typename StreamType> template <typename StreamType>
class BasicIStreamWrapper { class BasicIStreamWrapper {
public: public:
@@ -54,7 +54,7 @@ public:
/*! /*!
\param stream stream opened for read. \param stream stream opened for read.
*/ */
BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
Read(); Read();
} }
@@ -64,7 +64,7 @@ public:
\param buffer user-supplied buffer. \param buffer user-supplied buffer.
\param bufferSize size of buffer in bytes. Must >=4 bytes. \param bufferSize size of buffer in bytes. Must >=4 bytes.
*/ */
BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
RAPIDJSON_ASSERT(bufferSize >= 4); RAPIDJSON_ASSERT(bufferSize >= 4);
Read(); Read();
} }
@@ -75,7 +75,7 @@ public:
// Not implemented // Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }

View File

@@ -1,5 +1,5 @@
Tencent is pleased to support the open source community by making RapidJSON available. Tencent is pleased to support the open source community by making RapidJSON available.
Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License.
@@ -11,13 +11,13 @@ Other dependencies and licenses:
Open Source Software Licensed Under the BSD License: Open Source Software Licensed Under the BSD License:
-------------------------------------------------------------------- --------------------------------------------------------------------
The msinttypes r29 The msinttypes r29
Copyright (c) 2006-2013 Alexander Chemeris Copyright (c) 2006-2013 Alexander Chemeris
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. * Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
@@ -26,7 +26,7 @@ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPR
Open Source Software Licensed Under the JSON License: Open Source Software Licensed Under the JSON License:
-------------------------------------------------------------------- --------------------------------------------------------------------
json.org json.org
Copyright (c) 2002 JSON.org Copyright (c) 2002 JSON.org
All Rights Reserved. All Rights Reserved.
@@ -34,7 +34,7 @@ JSON_checker
Copyright (c) 2002 JSON.org Copyright (c) 2002 JSON.org
All Rights Reserved. All Rights Reserved.
Terms of the JSON License: Terms of the JSON License:
--------------------------------------------------- ---------------------------------------------------

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_MEMORYBUFFER_H_ #ifndef RAPIDJSON_MEMORYBUFFER_H_
@@ -27,7 +27,7 @@ RAPIDJSON_NAMESPACE_BEGIN
It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file.
Differences between MemoryBuffer and StringBuffer: Differences between MemoryBuffer and StringBuffer:
1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer.
2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator.
\tparam Allocator type for allocating memory buffer. \tparam Allocator type for allocating memory buffer.

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_MEMORYSTREAM_H_ #ifndef RAPIDJSON_MEMORYSTREAM_H_

View File

@@ -1,37 +1,37 @@
// ISO C9x compliant inttypes.h for Microsoft Visual Studio // ISO C9x compliant inttypes.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
// //
// Copyright (c) 2006-2013 Alexander Chemeris // Copyright (c) 2006-2013 Alexander Chemeris
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: // modification, are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright // 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the // notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution. // documentation and/or other materials provided with the distribution.
// //
// 3. Neither the name of the product nor the names of its contributors may // 3. Neither the name of the product nor the names of its contributors may
// be used to endorse or promote products derived from this software // be used to endorse or promote products derived from this software
// without specific prior written permission. // without specific prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// The above software in this distribution may have been modified by // The above software in this distribution may have been modified by
// THL A29 Limited ("Tencent Modifications"). // THL A29 Limited ("Tencent Modifications").
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. // All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
#ifndef _MSC_VER // [ #ifndef _MSC_VER // [

View File

@@ -1,37 +1,37 @@
// ISO C9x compliant stdint.h for Microsoft Visual Studio // ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
// //
// Copyright (c) 2006-2013 Alexander Chemeris // Copyright (c) 2006-2013 Alexander Chemeris
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: // modification, are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright // 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the // notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution. // documentation and/or other materials provided with the distribution.
// //
// 3. Neither the name of the product nor the names of its contributors may // 3. Neither the name of the product nor the names of its contributors may
// be used to endorse or promote products derived from this software // be used to endorse or promote products derived from this software
// without specific prior written permission. // without specific prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// The above software in this distribution may have been modified by // The above software in this distribution may have been modified by
// THL A29 Limited ("Tencent Modifications"). // THL A29 Limited ("Tencent Modifications").
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. // All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
#ifndef _MSC_VER // [ #ifndef _MSC_VER // [

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_OSTREAMWRAPPER_H_ #ifndef RAPIDJSON_OSTREAMWRAPPER_H_
@@ -40,7 +40,7 @@ RAPIDJSON_NAMESPACE_BEGIN
\tparam StreamType Class derived from \c std::basic_ostream. \tparam StreamType Class derived from \c std::basic_ostream.
*/ */
template <typename StreamType> template <typename StreamType>
class BasicOStreamWrapper { class BasicOStreamWrapper {
public: public:

View File

@@ -1,21 +1,22 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_POINTER_H_ #ifndef RAPIDJSON_POINTER_H_
#define RAPIDJSON_POINTER_H_ #define RAPIDJSON_POINTER_H_
#include "document.h" #include "document.h"
#include "uri.h"
#include "internal/itoa.h" #include "internal/itoa.h"
#ifdef __clang__ #ifdef __clang__
@@ -48,16 +49,16 @@ enum PointerParseErrorCode {
//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. //! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
/*! /*!
This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer"
(https://tools.ietf.org/html/rfc6901). (https://tools.ietf.org/html/rfc6901).
A JSON pointer is for identifying a specific value in a JSON document A JSON pointer is for identifying a specific value in a JSON document
(GenericDocument). It can simplify coding of DOM tree manipulation, because it (GenericDocument). It can simplify coding of DOM tree manipulation, because it
can access multiple-level depth of DOM tree with single API call. can access multiple-level depth of DOM tree with single API call.
After it parses a string representation (e.g. "/foo/0" or URI fragment After it parses a string representation (e.g. "/foo/0" or URI fragment
representation (e.g. "#/foo/0") into its internal representation (tokens), representation (e.g. "#/foo/0") into its internal representation (tokens),
it can be used to resolve a specific value in multiple documents, or sub-tree it can be used to resolve a specific value in multiple documents, or sub-tree
of documents. of documents.
Contrary to GenericValue, Pointer can be copy constructed and copy assigned. Contrary to GenericValue, Pointer can be copy constructed and copy assigned.
@@ -68,10 +69,10 @@ enum PointerParseErrorCode {
supplied tokens eliminates these. supplied tokens eliminates these.
GenericPointer depends on GenericDocument and GenericValue. GenericPointer depends on GenericDocument and GenericValue.
\tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> > \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
\tparam Allocator The allocator type for allocating memory for internal representation. \tparam Allocator The allocator type for allocating memory for internal representation.
\note GenericPointer uses same encoding of ValueType. \note GenericPointer uses same encoding of ValueType.
However, Allocator of GenericPointer is independent of Allocator of Value. However, Allocator of GenericPointer is independent of Allocator of Value.
*/ */
@@ -80,10 +81,12 @@ class GenericPointer {
public: public:
typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
typedef typename ValueType::Ch Ch; //!< Character type from Value typedef typename ValueType::Ch Ch; //!< Character type from Value
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.
They are resolved according to the actual value type (object or array). They are resolved according to the actual value type (object or array).
@@ -91,7 +94,7 @@ public:
(greater than limits of SizeType), they are only treated as string form (greater than limits of SizeType), they are only treated as string form
(i.e. the token's index will be equal to kPointerInvalidIndex). (i.e. the token's index will be equal to kPointerInvalidIndex).
This struct is public so that user can create a Pointer without parsing and This struct is public so that user can create a Pointer without parsing and
allocation, using a special constructor. allocation, using a special constructor.
*/ */
struct Token { struct Token {
@@ -163,7 +166,7 @@ public:
GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
//! Copy constructor. //! Copy constructor.
GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
*this = rhs; *this = rhs;
} }
@@ -370,7 +373,7 @@ public:
for (size_t i = 0; i < tokenCount_; i++) { for (size_t i = 0; i < tokenCount_; i++) {
if (tokens_[i].index != rhs.tokens_[i].index || if (tokens_[i].index != rhs.tokens_[i].index ||
tokens_[i].length != rhs.tokens_[i].length || tokens_[i].length != rhs.tokens_[i].length ||
(tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
{ {
return false; return false;
@@ -448,9 +451,9 @@ public:
If the value is not exist, it creates all parent values and a JSON Null value. If the value is not exist, it creates all parent values and a JSON Null value.
So it always succeed and return the newly created or existing value. So it always succeed and return the newly created or existing value.
Remind that it may change types of parents according to tokens, so it Remind that it may change types of parents according to tokens, so it
potentially removes previously stored values. For example, if a document potentially removes previously stored values. For example, if a document
was an array, and "/foo" is used to create a value, then the document was an array, and "/foo" is used to create a value, then the document
will be changed to an object, and all existing array elements are lost. will be changed to an object, and all existing array elements are lost.
\param root Root value of a DOM subtree to be resolved. It can be any value other than document root. \param root Root value of a DOM subtree to be resolved. It can be any value other than document root.
@@ -488,10 +491,11 @@ public:
v = &((*v)[t->index]); v = &((*v)[t->index]);
} }
else { else {
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd()) { if (m == v->MemberEnd()) {
v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end m = v->MemberEnd();
v = &(--m)->value; // Assumes AddMember() appends at the end
exist = false; exist = false;
} }
else else
@@ -519,6 +523,70 @@ public:
//@} //@}
//!@name Compute URI
//@{
//! Compute the in-scope URI for a subtree.
// For use with JSON pointers into JSON schema documents.
/*!
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
\param rootUri Root URI
\param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
\param allocator Allocator for Uris
\return Uri if it can be resolved. Otherwise null.
\note
There are only 3 situations when a URI cannot be resolved:
1. A value in the path is not an array nor object.
2. An object value does not contain the token.
3. A token is out of range of an array value.
Use unresolvedTokenIndex to retrieve the token index.
*/
UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
static const Ch kIdString[] = { 'i', 'd', '\0' };
static const ValueType kIdValue(kIdString, 2);
UriType base = UriType(rootUri, allocator);
RAPIDJSON_ASSERT(IsValid());
ValueType* v = &root;
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
switch (v->GetType()) {
case kObjectType:
{
// See if we have an id, and if so resolve with the current base
typename ValueType::MemberIterator m = v->FindMember(kIdValue);
if (m != v->MemberEnd() && (m->value).IsString()) {
UriType here = UriType(m->value, allocator).Resolve(base, allocator);
base = here;
}
m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd())
break;
v = &m->value;
}
continue;
case kArrayType:
if (t->index == kPointerInvalidIndex || t->index >= v->Size())
break;
v = &((*v)[t->index]);
continue;
default:
break;
}
// Error: unresolved token
if (unresolvedTokenIndex)
*unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
return UriType(allocator);
}
return base;
}
UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
}
//!@name Query value //!@name Query value
//@{ //@{
@@ -543,7 +611,7 @@ public:
switch (v->GetType()) { switch (v->GetType()) {
case kObjectType: case kObjectType:
{ {
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd()) if (m == v->MemberEnd())
break; break;
v = &m->value; v = &m->value;
@@ -571,7 +639,7 @@ public:
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
\return Pointer to the value if it can be resolved. Otherwise null. \return Pointer to the value if it can be resolved. Otherwise null.
*/ */
const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
return Get(const_cast<ValueType&>(root), unresolvedTokenIndex); return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
} }
@@ -633,7 +701,7 @@ public:
ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const { ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
return GetWithDefault(document, defaultValue, document.GetAllocator()); return GetWithDefault(document, defaultValue, document.GetAllocator());
} }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
//! Query a value in a document with default std::basic_string. //! Query a value in a document with default std::basic_string.
template <typename stackAllocator> template <typename stackAllocator>
@@ -779,7 +847,7 @@ public:
switch (v->GetType()) { switch (v->GetType()) {
case kObjectType: case kObjectType:
{ {
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd()) if (m == v->MemberEnd())
return false; return false;
v = &m->value; v = &m->value;
@@ -870,7 +938,7 @@ private:
// Count number of '/' as tokenCount // Count number of '/' as tokenCount
tokenCount_ = 0; tokenCount_ = 0;
for (const Ch* s = source; s != source + length; s++) for (const Ch* s = source; s != source + length; s++)
if (*s == '/') if (*s == '/')
tokenCount_++; tokenCount_++;
@@ -927,7 +995,7 @@ private:
} }
i++; i++;
// Escaping "~0" -> '~', "~1" -> '/' // Escaping "~0" -> '~', "~1" -> '/'
if (c == '~') { if (c == '~') {
if (i < length) { if (i < length) {
@@ -1016,7 +1084,7 @@ private:
os.Put('~'); os.Put('~');
os.Put('1'); os.Put('1');
} }
else if (uriFragment && NeedPercentEncode(c)) { else if (uriFragment && NeedPercentEncode(c)) {
// Transcode to UTF8 sequence // Transcode to UTF8 sequence
GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]); GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
PercentEncodeStream<OutputStream> target(os); PercentEncodeStream<OutputStream> target(os);
@@ -1034,7 +1102,7 @@ private:
//! A helper stream for decoding a percent-encoded sequence into code unit. //! A helper stream for decoding a percent-encoded sequence into code unit.
/*! /*!
This stream decodes %XY triplet into code unit (0-255). This stream decodes %XY triplet into code unit (0-255).
If it encounters invalid characters, it sets output code unit as 0 and If it encounters invalid characters, it sets output code unit as 0 and
mark invalid, and to be checked by IsValid(). mark invalid, and to be checked by IsValid().
*/ */
class PercentDecodeStream { class PercentDecodeStream {

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_PRETTYWRITER_H_ #ifndef RAPIDJSON_PRETTYWRITER_H_
@@ -55,12 +55,12 @@ public:
\param allocator User supplied allocator. If it is null, it will create a private one. \param allocator User supplied allocator. If it is null, it will create a private one.
\param levelDepth Initial capacity of stack. \param levelDepth Initial capacity of stack.
*/ */
explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
PrettyWriter(PrettyWriter&& rhs) : PrettyWriter(PrettyWriter&& rhs) :
@@ -133,13 +133,13 @@ public:
return Key(str.data(), SizeType(str.size())); return Key(str.data(), SizeType(str.size()));
} }
#endif #endif
bool EndObject(SizeType memberCount = 0) { bool EndObject(SizeType memberCount = 0) {
(void)memberCount; (void)memberCount;
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object
RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
if (!empty) { if (!empty) {
@@ -164,7 +164,7 @@ public:
(void)memberCount; (void)memberCount;
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray); RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
typename Base::Level* level = Base::level_stack_.template Pop<typename Base::Level>(1); auto level = Base::level_stack_.template Pop<typename Base::Level>(1);
bool empty = level->valueCount == 0; bool empty = level->valueCount == 0;
if (!empty && !level->inLine) { if (!empty && !level->inLine) {

View File

@@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
// //
// http://opensource.org/licenses/MIT // http://opensource.org/licenses/MIT
// //
// Unless required by applicable law or agreed to in writing, software distributed // Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_RAPIDJSON_H_ #ifndef RAPIDJSON_RAPIDJSON_H_
@@ -17,7 +17,7 @@
/*!\file rapidjson.h /*!\file rapidjson.h
\brief common definitions and configuration \brief common definitions and configuration
\see RAPIDJSON_CONFIG \see RAPIDJSON_CONFIG
*/ */
@@ -124,6 +124,19 @@
#define RAPIDJSON_NAMESPACE_END } #define RAPIDJSON_NAMESPACE_END }
#endif #endif
///////////////////////////////////////////////////////////////////////////////
// __cplusplus macro
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#if defined(_MSC_VER)
#define RAPIDJSON_CPLUSPLUS _MSVC_LANG
#else
#define RAPIDJSON_CPLUSPLUS __cplusplus
#endif
//!@endcond
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_HAS_STDSTRING // RAPIDJSON_HAS_STDSTRING
@@ -149,6 +162,24 @@
#include <string> #include <string>
#endif // RAPIDJSON_HAS_STDSTRING #endif // RAPIDJSON_HAS_STDSTRING
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_USE_MEMBERSMAP
/*! \def RAPIDJSON_USE_MEMBERSMAP
\ingroup RAPIDJSON_CONFIG
\brief Enable RapidJSON support for object members handling in a \c std::multimap
By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object
members are stored in a \c std::multimap for faster lookup and deletion times, a
trade off with a slightly slower insertion time and a small object allocat(or)ed
memory overhead.
\hideinitializer
*/
#ifndef RAPIDJSON_USE_MEMBERSMAP
#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default
#endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_NO_INT64DEFINE // RAPIDJSON_NO_INT64DEFINE
@@ -246,7 +277,7 @@
# elif defined(RAPIDJSON_DOXYGEN_RUNNING) # elif defined(RAPIDJSON_DOXYGEN_RUNNING)
# define RAPIDJSON_ENDIAN # define RAPIDJSON_ENDIAN
# else # else
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. # error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
# endif # endif
#endif // RAPIDJSON_ENDIAN #endif // RAPIDJSON_ENDIAN
@@ -403,7 +434,7 @@ RAPIDJSON_NAMESPACE_END
*/ */
#ifndef RAPIDJSON_ASSERT #ifndef RAPIDJSON_ASSERT
#include <cassert> #include <cassert>
#define RAPIDJSON_ASSERT(x) #define RAPIDJSON_ASSERT(x) assert(x)
#endif // RAPIDJSON_ASSERT #endif // RAPIDJSON_ASSERT
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -411,7 +442,7 @@ RAPIDJSON_NAMESPACE_END
// Prefer C++11 static_assert, if available // Prefer C++11 static_assert, if available
#ifndef RAPIDJSON_STATIC_ASSERT #ifndef RAPIDJSON_STATIC_ASSERT
#if __cplusplus >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 ) #if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )
#define RAPIDJSON_STATIC_ASSERT(x) \ #define RAPIDJSON_STATIC_ASSERT(x) \
static_assert(x, RAPIDJSON_STRINGIFY(x)) static_assert(x, RAPIDJSON_STRINGIFY(x))
#endif // C++11 #endif // C++11
@@ -431,7 +462,7 @@ RAPIDJSON_NAMESPACE_END
#if defined(__GNUC__) || defined(__clang__) #if defined(__GNUC__) || defined(__clang__)
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
#else #else
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
#endif #endif
#ifndef __clang__ #ifndef __clang__
//!@endcond //!@endcond
@@ -482,7 +513,7 @@ RAPIDJSON_NAMESPACE_END
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#define RAPIDJSON_MULTILINEMACRO_BEGIN do { #define RAPIDJSON_MULTILINEMACRO_BEGIN do {
#define RAPIDJSON_MULTILINEMACRO_END \ #define RAPIDJSON_MULTILINEMACRO_END \
} while((void)0, 0) } while((void)0, 0)
@@ -490,6 +521,12 @@ RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_VERSION_CODE(x,y,z) \ #define RAPIDJSON_VERSION_CODE(x,y,z) \
(((x)*100000) + ((y)*100) + (z)) (((x)*100000) + ((y)*100) + (z))
#if defined(__has_builtin)
#define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x)
#else
#define RAPIDJSON_HAS_BUILTIN(x) 0
#endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF // RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
@@ -535,8 +572,14 @@ RAPIDJSON_NAMESPACE_END
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// C++11 features // C++11 features
#ifndef RAPIDJSON_HAS_CXX11
#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L)
#endif
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS #ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if defined(__clang__) #if RAPIDJSON_HAS_CXX11
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#elif defined(__clang__)
#if __has_feature(cxx_rvalue_references) && \ #if __has_feature(cxx_rvalue_references) && \
(defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) (defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 #define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
@@ -553,8 +596,14 @@ RAPIDJSON_NAMESPACE_END
#endif #endif
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
#include <utility> // std::move
#endif
#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT #ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
#if defined(__clang__) #if RAPIDJSON_HAS_CXX11
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
#elif defined(__clang__)
#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) #define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ #elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1900) || \ (defined(_MSC_VER) && _MSC_VER >= 1900) || \
@@ -564,11 +613,13 @@ RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 #define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
#endif #endif
#endif #endif
#ifndef RAPIDJSON_NOEXCEPT
#if RAPIDJSON_HAS_CXX11_NOEXCEPT #if RAPIDJSON_HAS_CXX11_NOEXCEPT
#define RAPIDJSON_NOEXCEPT noexcept #define RAPIDJSON_NOEXCEPT noexcept
#else #else
#define RAPIDJSON_NOEXCEPT /* noexcept */ #define RAPIDJSON_NOEXCEPT throw()
#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT #endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
#endif
// no automatic detection, yet // no automatic detection, yet
#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS #ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
@@ -591,6 +642,27 @@ RAPIDJSON_NAMESPACE_END
#endif #endif
#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR #endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
///////////////////////////////////////////////////////////////////////////////
// C++17 features
#ifndef RAPIDJSON_HAS_CXX17
#define RAPIDJSON_HAS_CXX17 (RAPIDJSON_CPLUSPLUS >= 201703L)
#endif
#if RAPIDJSON_HAS_CXX17
# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]]
#elif defined(__has_cpp_attribute)
# if __has_cpp_attribute(clang::fallthrough)
# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]]
# elif __has_cpp_attribute(fallthrough)
# define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough))
# else
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
# endif
#else
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
#endif
//!@endcond //!@endcond
//! Assertion (in non-throwing contexts). //! Assertion (in non-throwing contexts).
@@ -609,16 +681,29 @@ RAPIDJSON_NAMESPACE_END
#ifndef RAPIDJSON_NOEXCEPT_ASSERT #ifndef RAPIDJSON_NOEXCEPT_ASSERT
#ifdef RAPIDJSON_ASSERT_THROWS #ifdef RAPIDJSON_ASSERT_THROWS
#if RAPIDJSON_HAS_CXX11_NOEXCEPT #include <cassert>
#define RAPIDJSON_NOEXCEPT_ASSERT(x) #define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x)
#else
#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
#else #else
#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x) #define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
#endif // RAPIDJSON_ASSERT_THROWS #endif // RAPIDJSON_ASSERT_THROWS
#endif // RAPIDJSON_NOEXCEPT_ASSERT #endif // RAPIDJSON_NOEXCEPT_ASSERT
///////////////////////////////////////////////////////////////////////////////
// malloc/realloc/free
#ifndef RAPIDJSON_MALLOC
///! customization point for global \c malloc
#define RAPIDJSON_MALLOC(size) std::malloc(size)
#endif
#ifndef RAPIDJSON_REALLOC
///! customization point for global \c realloc
#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size)
#endif
#ifndef RAPIDJSON_FREE
///! customization point for global \c free
#define RAPIDJSON_FREE(ptr) std::free(ptr)
#endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// new/delete // new/delete
@@ -646,7 +731,7 @@ enum Type {
kFalseType = 1, //!< false kFalseType = 1, //!< false
kTrueType = 2, //!< true kTrueType = 2, //!< true
kObjectType = 3, //!< object kObjectType = 3, //!< object
kArrayType = 4, //!< array kArrayType = 4, //!< array
kStringType = 5, //!< string kStringType = 5, //!< string
kNumberType = 6 //!< number kNumberType = 6 //!< number
}; };

View File

@@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available. // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Licensed under the MIT License (the "License"); you may not use this file except // Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at // in compliance with the License. You may obtain a copy of the License at
@@ -20,6 +20,7 @@
#include "allocators.h" #include "allocators.h"
#include "stream.h" #include "stream.h"
#include "encodedstream.h" #include "encodedstream.h"
#include "internal/clzll.h"
#include "internal/meta.h" #include "internal/meta.h"
#include "internal/stack.h" #include "internal/stack.h"
#include "internal/strtod.h" #include "internal/strtod.h"
@@ -153,6 +154,7 @@ enum ParseFlag {
kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings. kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings.
kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays. kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles. kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
kParseEscapedApostropheFlag = 512, //!< Allow escaped apostrophe in strings.
kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
}; };
@@ -443,16 +445,16 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
x = vmvnq_u8(x); // Negate x = vmvnq_u8(x); // Negate
x = vrev64q_u8(x); // Rev in 64 x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
int lz =__builtin_clzll(high);; uint32_t lz = internal::clzll(high);
return p + 8 + (lz >> 3); return p + 8 + (lz >> 3);
} }
} else { } else {
int lz = __builtin_clzll(low);; uint32_t lz = internal::clzll(low);
return p + (lz >> 3); return p + (lz >> 3);
} }
} }
@@ -479,16 +481,16 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
x = vmvnq_u8(x); // Negate x = vmvnq_u8(x); // Negate
x = vrev64q_u8(x); // Rev in 64 x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
int lz = __builtin_clzll(high); uint32_t lz = internal::clzll(high);
return p + 8 + (lz >> 3); return p + 8 + (lz >> 3);
} }
} else { } else {
int lz = __builtin_clzll(low); uint32_t lz = internal::clzll(low);
return p + (lz >> 3); return p + (lz >> 3);
} }
} }
@@ -990,7 +992,7 @@ private:
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
static const char escape[256] = { static const char escape[256] = {
Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/',
Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1013,19 +1015,31 @@ private:
is.Take(); is.Take();
os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)])); os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
} }
else if ((parseFlags & kParseEscapedApostropheFlag) && RAPIDJSON_LIKELY(e == '\'')) { // Allow escaped apostrophe
is.Take();
os.Put('\'');
}
else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode
is.Take(); is.Take();
unsigned codepoint = ParseHex4(is, escapeOffset); unsigned codepoint = ParseHex4(is, escapeOffset);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) { if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDFFF)) {
// Handle UTF-16 surrogate pair // high surrogate, check if followed by valid low surrogate
if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u'))) if (RAPIDJSON_LIKELY(codepoint <= 0xDBFF)) {
// Handle UTF-16 surrogate pair
if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
unsigned codepoint2 = ParseHex4(is, escapeOffset);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
}
// single low surrogate
else
{
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
unsigned codepoint2 = ParseHex4(is, escapeOffset); }
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
} }
TEncoding::Encode(os, codepoint); TEncoding::Encode(os, codepoint);
} }
@@ -1244,19 +1258,19 @@ private:
x = vorrq_u8(x, vcltq_u8(s, s3)); x = vorrq_u8(x, vcltq_u8(s, s3));
x = vrev64q_u8(x); // Rev in 64 x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
SizeType length = 0; SizeType length = 0;
bool escaped = false; bool escaped = false;
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
unsigned lz = (unsigned)__builtin_clzll(high);; uint32_t lz = internal::clzll(high);
length = 8 + (lz >> 3); length = 8 + (lz >> 3);
escaped = true; escaped = true;
} }
} else { } else {
unsigned lz = (unsigned)__builtin_clzll(low);; uint32_t lz = internal::clzll(low);
length = lz >> 3; length = lz >> 3;
escaped = true; escaped = true;
} }
@@ -1314,19 +1328,19 @@ private:
x = vorrq_u8(x, vcltq_u8(s, s3)); x = vorrq_u8(x, vcltq_u8(s, s3));
x = vrev64q_u8(x); // Rev in 64 x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
SizeType length = 0; SizeType length = 0;
bool escaped = false; bool escaped = false;
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
unsigned lz = (unsigned)__builtin_clzll(high); uint32_t lz = internal::clzll(high);
length = 8 + (lz >> 3); length = 8 + (lz >> 3);
escaped = true; escaped = true;
} }
} else { } else {
unsigned lz = (unsigned)__builtin_clzll(low); uint32_t lz = internal::clzll(low);
length = lz >> 3; length = lz >> 3;
escaped = true; escaped = true;
} }
@@ -1370,17 +1384,17 @@ private:
x = vorrq_u8(x, vcltq_u8(s, s3)); x = vorrq_u8(x, vcltq_u8(s, s3));
x = vrev64q_u8(x); // Rev in 64 x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
int lz = __builtin_clzll(high); uint32_t lz = internal::clzll(high);
p += 8 + (lz >> 3); p += 8 + (lz >> 3);
break; break;
} }
} else { } else {
int lz = __builtin_clzll(low); uint32_t lz = internal::clzll(low);
p += lz >> 3; p += lz >> 3;
break; break;
} }
@@ -1390,11 +1404,11 @@ private:
} }
#endif // RAPIDJSON_NEON #endif // RAPIDJSON_NEON
template<typename InputStream, bool backup, bool pushOnTake> template<typename InputStream, typename StackCharacter, bool backup, bool pushOnTake>
class NumberStream; class NumberStream;
template<typename InputStream> template<typename InputStream, typename StackCharacter>
class NumberStream<InputStream, false, false> { class NumberStream<InputStream, StackCharacter, false, false> {
public: public:
typedef typename InputStream::Ch Ch; typedef typename InputStream::Ch Ch;
@@ -1403,11 +1417,11 @@ private:
RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
RAPIDJSON_FORCEINLINE void Push(char) {} RAPIDJSON_FORCEINLINE void Push(char) {}
size_t Tell() { return is.Tell(); } size_t Tell() { return is.Tell(); }
size_t Length() { return 0; } size_t Length() { return 0; }
const char* Pop() { return 0; } const StackCharacter* Pop() { return 0; }
protected: protected:
NumberStream& operator=(const NumberStream&); NumberStream& operator=(const NumberStream&);
@@ -1415,35 +1429,35 @@ private:
InputStream& is; InputStream& is;
}; };
template<typename InputStream> template<typename InputStream, typename StackCharacter>
class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> { class NumberStream<InputStream, StackCharacter, true, false> : public NumberStream<InputStream, StackCharacter, false, false> {
typedef NumberStream<InputStream, 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& is) : Base(reader, is), stackStream(reader.stack_) {}
RAPIDJSON_FORCEINLINE Ch TakePush() { RAPIDJSON_FORCEINLINE Ch TakePush() {
stackStream.Put(static_cast<char>(Base::is.Peek())); stackStream.Put(static_cast<StackCharacter>(Base::is.Peek()));
return Base::is.Take(); return Base::is.Take();
} }
RAPIDJSON_FORCEINLINE void Push(char c) { RAPIDJSON_FORCEINLINE void Push(StackCharacter c) {
stackStream.Put(c); stackStream.Put(c);
} }
size_t Length() { return stackStream.Length(); } size_t Length() { return stackStream.Length(); }
const char* Pop() { const StackCharacter* Pop() {
stackStream.Put('\0'); stackStream.Put('\0');
return stackStream.Pop(); return stackStream.Pop();
} }
private: private:
StackStream<char> stackStream; StackStream<StackCharacter> stackStream;
}; };
template<typename InputStream> template<typename InputStream, typename StackCharacter>
class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> { class NumberStream<InputStream, StackCharacter, true, true> : public NumberStream<InputStream, StackCharacter, true, false> {
typedef NumberStream<InputStream, true, false> Base; typedef NumberStream<InputStream, StackCharacter, true, false> Base;
public: public:
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
@@ -1452,8 +1466,10 @@ private:
template<unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseNumber(InputStream& is, Handler& handler) { void ParseNumber(InputStream& is, Handler& handler) {
typedef typename internal::SelectIf<internal::BoolType<(parseFlags & kParseNumbersAsStringsFlag) != 0>, typename TargetEncoding::Ch, char>::Type NumberCharacter;
internal::StreamLocalCopy<InputStream> copy(is); internal::StreamLocalCopy<InputStream> copy(is);
NumberStream<InputStream, NumberStream<InputStream, NumberCharacter,
((parseFlags & kParseNumbersAsStringsFlag) != 0) ? ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
((parseFlags & kParseInsituFlag) == 0) : ((parseFlags & kParseInsituFlag) == 0) :
((parseFlags & kParseFullPrecisionFlag) != 0), ((parseFlags & kParseFullPrecisionFlag) != 0),
@@ -1678,10 +1694,10 @@ private:
} }
else { else {
SizeType numCharsToCopy = static_cast<SizeType>(s.Length()); SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
StringStream 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<>, TargetEncoding>::Transcode(srcStream, dstStream); Transcoder<UTF8<typename TargetEncoding::Ch>, TargetEncoding>::Transcode(srcStream, dstStream);
} }
dstStream.Put('\0'); dstStream.Put('\0');
const typename TargetEncoding::Ch* str = dstStream.Pop(); const typename TargetEncoding::Ch* str = dstStream.Pop();
@@ -1691,7 +1707,7 @@ private:
} }
else { else {
size_t length = s.Length(); size_t length = s.Length();
const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. const NumberCharacter* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
if (useDouble) { if (useDouble) {
int p = exp + expFrac; int p = exp + expFrac;

210
src/3rdparty/rapidjson/readme.md vendored Normal file
View File

@@ -0,0 +1,210 @@
![RapidJSON logo](doc/logo/rapidjson.png)
![Release version](https://img.shields.io/badge/release-v1.1.0-blue.svg)
## A fast JSON parser/generator for C++ with both SAX/DOM style API
Tencent is pleased to support the open source community by making RapidJSON available.
Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
* [RapidJSON GitHub](https://github.com/Tencent/rapidjson/)
* RapidJSON Documentation
* [English](http://rapidjson.org/)
* [简体中文](http://rapidjson.org/zh-cn/)
* [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference.
## Build status
| [Linux][lin-link] | [Windows][win-link] | [Coveralls][cov-link] |
| :---------------: | :-----------------: | :-------------------: |
| ![lin-badge] | ![win-badge] | ![cov-badge] |
[lin-badge]: https://travis-ci.org/Tencent/rapidjson.svg?branch=master "Travis build status"
[lin-link]: https://travis-ci.org/Tencent/rapidjson "Travis build status"
[win-badge]: https://ci.appveyor.com/api/projects/status/l6qulgqahcayidrf/branch/master?svg=true "AppVeyor build status"
[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson-0fdqj/branch/master "AppVeyor build status"
[cov-badge]: https://coveralls.io/repos/Tencent/rapidjson/badge.svg?branch=master "Coveralls coverage"
[cov-link]: https://coveralls.io/r/Tencent/rapidjson?branch=master "Coveralls coverage"
## Introduction
RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](http://rapidxml.sourceforge.net/).
* RapidJSON is **small** but **complete**. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code.
* RapidJSON is **fast**. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration.
* RapidJSON is **self-contained** and **header-only**. It does not depend on external libraries such as BOOST. It even does not depend on STL.
* RapidJSON is **memory-friendly**. Each JSON value occupies exactly 16 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing.
* RapidJSON is **Unicode-friendly**. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character).
More features can be read [here](doc/features.md).
JSON(JavaScript Object Notation) is a light-weight data exchange format. RapidJSON should be in full compliance with RFC7159/ECMA-404, with optional support of relaxed syntax. More information about JSON can be obtained at
* [Introducing JSON](http://json.org/)
* [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc7159)
* [Standard ECMA-404: The JSON Data Interchange Format](https://www.ecma-international.org/publications/standards/Ecma-404.htm)
## Highlights in v1.1 (2016-8-25)
* Added [JSON Pointer](doc/pointer.md)
* Added [JSON Schema](doc/schema.md)
* Added [relaxed JSON syntax](doc/dom.md) (comment, trailing comma, NaN/Infinity)
* Iterating array/object with [C++11 Range-based for loop](doc/tutorial.md)
* Reduce memory overhead of each `Value` from 24 bytes to 16 bytes in x86-64 architecture.
For other changes please refer to [change log](CHANGELOG.md).
## Compatibility
RapidJSON is cross-platform. Some platform/compiler combinations which have been tested are shown as follows.
* Visual C++ 2008/2010/2013 on Windows (32/64-bit)
* GNU C++ 3.8.x on Cygwin
* Clang 3.4 on Mac OS X (32/64-bit) and iOS
* Clang 3.4 on Android NDK
Users can build and run the unit tests on their platform/compiler.
## Installation
RapidJSON is a header-only C++ library. Just copy the `include/rapidjson` folder to system or project's include path.
Alternatively, if you are using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager you can download and install rapidjson with CMake integration in a single command:
* vcpkg install rapidjson
RapidJSON uses following software as its dependencies:
* [CMake](https://cmake.org/) as a general build tool
* (optional) [Doxygen](http://www.doxygen.org) to build documentation
* (optional) [googletest](https://github.com/google/googletest) for unit and performance testing
To generate user documentation and run tests please proceed with the steps below:
1. Execute `git submodule update --init` to get the files of thirdparty submodules (google test).
2. Create directory called `build` in rapidjson source directory.
3. Change to `build` directory and run `cmake ..` command to configure your build. Windows users can do the same with cmake-gui application.
4. On Windows, build the solution found in the build directory. On Linux, run `make` from the build directory.
On successful build you will find compiled test and example binaries in `bin`
directory. The generated documentation will be available in `doc/html`
directory of the build tree. To run tests after finished build please run `make
test` or `ctest` from your build tree. You can get detailed output using `ctest
-V` command.
It is possible to install library system-wide by running `make install` command
from the build tree with administrative privileges. This will install all files
according to system preferences. Once RapidJSON is installed, it is possible
to use it from other CMake projects by adding `find_package(RapidJSON)` line to
your CMakeLists.txt.
## Usage at a glance
This simple example parses a JSON string into a document (DOM), make a simple modification of the DOM, and finally stringify the DOM to a JSON string.
~~~~~~~~~~cpp
// rapidjson/example/simpledom/simpledom.cpp`
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>
using namespace rapidjson;
int main() {
// 1. Parse a JSON string into DOM.
const char* json = "{\"project\":\"rapidjson\",\"stars\":10}";
Document d;
d.Parse(json);
// 2. Modify it by DOM.
Value& s = d["stars"];
s.SetInt(s.GetInt() + 1);
// 3. Stringify the DOM
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
d.Accept(writer);
// Output {"project":"rapidjson","stars":11}
std::cout << buffer.GetString() << std::endl;
return 0;
}
~~~~~~~~~~
Note that this example did not handle potential errors.
The following diagram shows the process.
![simpledom](doc/diagram/simpledom.png)
More [examples](https://github.com/Tencent/rapidjson/tree/master/example) are available:
* DOM API
* [tutorial](https://github.com/Tencent/rapidjson/blob/master/example/tutorial/tutorial.cpp): Basic usage of DOM API.
* SAX API
* [simplereader](https://github.com/Tencent/rapidjson/blob/master/example/simplereader/simplereader.cpp): Dumps all SAX events while parsing a JSON by `Reader`.
* [condense](https://github.com/Tencent/rapidjson/blob/master/example/condense/condense.cpp): A command line tool to rewrite a JSON, with all whitespaces removed.
* [pretty](https://github.com/Tencent/rapidjson/blob/master/example/pretty/pretty.cpp): A command line tool to rewrite a JSON with indents and newlines by `PrettyWriter`.
* [capitalize](https://github.com/Tencent/rapidjson/blob/master/example/capitalize/capitalize.cpp): A command line tool to capitalize strings in JSON.
* [messagereader](https://github.com/Tencent/rapidjson/blob/master/example/messagereader/messagereader.cpp): Parse a JSON message with SAX API.
* [serialize](https://github.com/Tencent/rapidjson/blob/master/example/serialize/serialize.cpp): Serialize a C++ object into JSON with SAX API.
* [jsonx](https://github.com/Tencent/rapidjson/blob/master/example/jsonx/jsonx.cpp): Implements a `JsonxWriter` which stringify SAX events into [JSONx](https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html) (a kind of XML) format. The example is a command line tool which converts input JSON into JSONx format.
* Schema
* [schemavalidator](https://github.com/Tencent/rapidjson/blob/master/example/schemavalidator/schemavalidator.cpp) : A command line tool to validate a JSON with a JSON schema.
* Advanced
* [prettyauto](https://github.com/Tencent/rapidjson/blob/master/example/prettyauto/prettyauto.cpp): A modified version of [pretty](https://github.com/Tencent/rapidjson/blob/master/example/pretty/pretty.cpp) to automatically handle JSON with any UTF encodings.
* [parsebyparts](https://github.com/Tencent/rapidjson/blob/master/example/parsebyparts/parsebyparts.cpp): Implements an `AsyncDocumentParser` which can parse JSON in parts, using C++11 thread.
* [filterkey](https://github.com/Tencent/rapidjson/blob/master/example/filterkey/filterkey.cpp): A command line tool to remove all values with user-specified key.
* [filterkeydom](https://github.com/Tencent/rapidjson/blob/master/example/filterkeydom/filterkeydom.cpp): Same tool as above, but it demonstrates how to use a generator to populate a `Document`.
## Contributing
RapidJSON welcomes contributions. When contributing, please follow the code below.
### Issues
Feel free to submit issues and enhancement requests.
Please help us by providing **minimal reproducible examples**, because source code is easier to let other people understand what happens.
For crash problems on certain platforms, please bring stack dump content with the detail of the OS, compiler, etc.
Please try breakpoint debugging first, tell us what you found, see if we can start exploring based on more information been prepared.
### Workflow
In general, we follow the "fork-and-pull" Git workflow.
1. **Fork** the repo on GitHub
2. **Clone** the project to your own machine
3. **Checkout** a new branch on your fork, start developing on the branch
4. **Test** the change before commit, Make sure the changes pass all the tests, including `unittest` and `preftest`, please add test case for each new feature or bug-fix if needed.
5. **Commit** changes to your own branch
6. **Push** your work back up to your fork
7. Submit a **Pull request** so that we can review your changes
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
### Copyright and Licensing
You can copy and paste the license summary from below.
```
Tencent is pleased to support the open source community by making RapidJSON available.
Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
Licensed under the MIT License (the "License"); you may not use this file except
in compliance with the License. You may obtain a copy of the License at
http://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
```

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More