Skip to content

Commit 02fff3c

Browse files
committed
Improve: Feature-gate HW-specific YIELDs
1 parent 08b3922 commit 02fff3c

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

c/lib.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ using thread_allocator_t = std::allocator<std::thread>;
1616

1717
using pool_variants_t = std::variant< //
1818

19+
#if _FU_WITH_ASM_YIELDS
1920
#if _FU_DETECT_ARCH_X86_64
2021
fu::basic_pool<thread_allocator_t, fu::x86_pause_t>, //
2122
fu::basic_pool<thread_allocator_t, fu::x86_tpause_t>, //
@@ -27,9 +28,11 @@ using pool_variants_t = std::variant< //
2728
#if _FU_DETECT_ARCH_RISC5
2829
fu::basic_pool<thread_allocator_t, fu::risc5_pause_t>, //
2930
#endif
31+
#endif // _FU_WITH_ASM_YIELDS
3032

3133
#if FU_ENABLE_NUMA
3234
fu::linux_distributed_pool<fu::standard_yield_t>, //
35+
#if _FU_WITH_ASM_YIELDS
3336
#if _FU_DETECT_ARCH_X86_64
3437
fu::linux_distributed_pool<fu::x86_pause_t>, //
3538
fu::linux_distributed_pool<fu::x86_tpause_t>, //
@@ -41,7 +44,9 @@ using pool_variants_t = std::variant< //
4144
#if _FU_DETECT_ARCH_RISC5
4245
fu::linux_distributed_pool<fu::risc5_pause_t>, //
4346
#endif
44-
#endif
47+
#endif // _FU_WITH_ASM_YIELDS
48+
#endif // FU_ENABLE_NUMA
49+
4550
fu::basic_pool<thread_allocator_t, fu::standard_yield_t> //
4651
>;
4752

@@ -232,6 +237,7 @@ fu_pool_t *fu_pool_new(char const *name) {
232237
return nullptr;
233238
}
234239

240+
#if _FU_WITH_ASM_YIELDS
235241
#if _FU_DETECT_ARCH_X86_64
236242
if (global_capabilities & fu::capability_x86_tpause_k) {
237243
new (opaque) opaque_pool_t(std::in_place_type<fu::linux_distributed_pool<fu::x86_tpause_t>>, name,
@@ -263,9 +269,11 @@ fu_pool_t *fu_pool_new(char const *name) {
263269
return reinterpret_cast<fu_pool_t *>(opaque);
264270
}
265271
#endif
272+
#endif // _FU_WITH_ASM_YIELDS
266273
#endif // FU_ENABLE_NUMA
267274

268275
// Common case of using modern hardware, but not having Linux installed
276+
#if _FU_WITH_ASM_YIELDS
269277
#if _FU_DETECT_ARCH_X86_64
270278
if (global_capabilities & fu::capability_x86_tpause_k) {
271279
new (opaque) opaque_pool_t(std::in_place_type<fu::basic_pool<thread_allocator_t, fu::x86_tpause_t>>);
@@ -292,6 +300,7 @@ fu_pool_t *fu_pool_new(char const *name) {
292300
return reinterpret_cast<fu_pool_t *>(opaque);
293301
}
294302
#endif
303+
#endif // _FU_WITH_ASM_YIELDS
295304

296305
// Worst case, use the standard yield pool
297306
new (opaque) opaque_pool_t(std::in_place_type<fu::basic_pool<thread_allocator_t, fu::standard_yield_t>>);

include/fork_union.hpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@
157157
#define _FU_UNLIKELY(x) (x)
158158
#endif
159159

160+
#if defined(__GNUC__) || defined(__clang__)
161+
#define _FU_WITH_ASM_YIELDS 1
162+
#else
163+
#define _FU_WITH_ASM_YIELDS 0
164+
#endif
165+
160166
/* Detect target CPU architecture.
161167
* We'll only use it when compiling Inline Assembly code on GCC or Clang.
162168
*/
@@ -1411,7 +1417,7 @@ concept is_unsafe_pool = //
14111417

14121418
#pragma region - Hardware Friendly Yield
14131419

1414-
#if defined(__GNUC__) || defined(__clang__) // We need inline assembly support
1420+
#if _FU_WITH_ASM_YIELDS // We need inline assembly support
14151421

14161422
#if _FU_DETECT_ARCH_ARM64
14171423

@@ -1425,6 +1431,12 @@ struct arm64_yield_t {
14251431
* Places the core into light sleep mode, waiting for an event to wake it up,
14261432
* or the timeout to expire.
14271433
*/
1434+
#pragma GCC push_options
1435+
#pragma GCC target("+wfxt")
1436+
#if defined(__clang__)
1437+
#pragma clang attribute push(__attribute__((target("+wfxt"))), apply_to = function)
1438+
#endif
1439+
14281440
struct arm64_wfet_t {
14291441
inline void operator()() const noexcept {
14301442
std::uint64_t cntfrq_el0, cntvct_el0;
@@ -1440,6 +1452,11 @@ struct arm64_wfet_t {
14401452
}
14411453
};
14421454

1455+
#pragma GCC pop_options
1456+
#if defined(__clang__)
1457+
#pragma clang attribute pop
1458+
#endif
1459+
14431460
#endif // _FU_DETECT_ARCH_ARM64
14441461

14451462
#if _FU_DETECT_ARCH_X86_64
@@ -1519,7 +1536,7 @@ inline capabilities_t cpu_capabilities() noexcept {
15191536
// Check for basic PAUSE instruction support (always available on x86-64)
15201537
caps = static_cast<capabilities_t>(caps | capability_x86_pause_k);
15211538

1522-
#if defined(__GNUC__) || defined(__clang__) // We use inline assembly - unavailable in MSVC
1539+
#if _FU_WITH_ASM_YIELDS // We use inline assembly - unavailable in MSVC
15231540
// CPUID to check for WAITPKG support (TPAUSE instruction)
15241541
std::uint32_t eax, ebx, ecx, edx;
15251542

@@ -1542,7 +1559,7 @@ inline capabilities_t cpu_capabilities() noexcept {
15421559
size_t size = sizeof(wfet_support);
15431560
if (sysctlbyname("hw.optional.arm.FEAT_WFxT", &wfet_support, &size, NULL, 0) == 0 && wfet_support)
15441561
caps = static_cast<capabilities_t>(caps | capability_arm64_wfet_k);
1545-
#elif defined(__GNUC__) || defined(__clang__) // We use inline assembly - unavailable in MSVC
1562+
#elif _FU_WITH_ASM_YIELDS // We use inline assembly - unavailable in MSVC
15461563
// On non-Apple ARM systems, try to read the system register
15471564
// Note: This may fail on some systems where userspace access is restricted
15481565
std::uint64_t id_aa64isar2_el0 = 0;

0 commit comments

Comments
 (0)