diff options
author | Marc Mutz <marc.mutz@qt.io> | 2022-04-29 12:28:09 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2022-05-10 00:09:04 +0000 |
commit | 877c158c5976bebffd0ff02c39b6b66a842c6344 (patch) | |
tree | 32a53857dc83d6ad57f8a257752e2354ee84635f /src | |
parent | 71322ef36142570edc94c361ceb21f770303aceb (diff) |
Add ARM YIELD support to qYieldCpu()
YIELD is ARM's equivalent of x86's PAUSE, available since ARMv6k,
which should be old enough that we can use it unconditionally.
The ARM manual[1] defines the __yield() intrinsic for this, however:
- Clang has __builtin_arm_yield, the naming is compatible with what
GCC would use, so we use that if available, to avoid having to
include even more headers.
- GCC (incl. 12) doesn't have __yield() in arm_acle.h or anywhere
else, and it doesn't seem to have the builtin (yet, one can always
hope), so we use asm() there.
- Windows doesn't have an arm_acle.h header, but the docs[2] say it
should have __yield(). Unfortunately, the docs don't say where
the intrinsic is hiding, but we already include <intrin.h>, and
godbolt[3] confirms that's sufficient to use __yield(). We could use
YieldProcessor(), but we'd need to include qt_windows.h, I guess,
which I'd rather not.
- Integrity doesn't have the arm_acle.h header, we use asm(), here, too.
[1] https://developer.arm.com/documentation/dui0472/k/Compiler-specific-Features/--yield-intrinsic
[2] https://docs.microsoft.com/en-us/cpp/intrinsics/arm-intrinsics?view=msvc-140
[3] https://godbolt.org/z/Evfe79xhE
Pick-to: 6.3
Fixes: QTBUG-103011
Change-Id: Ibf496dfe9949f9a3d24c0dcf75a703c5fdbbb4b8
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/global/qsimd_p.h | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/src/corelib/global/qsimd_p.h b/src/corelib/global/qsimd_p.h index 8f71710a60..c5755faf8a 100644 --- a/src/corelib/global/qsimd_p.h +++ b/src/corelib/global/qsimd_p.h @@ -395,7 +395,7 @@ static inline uint64_t qCpuFeatures() || ((qCpuFeatures() & CpuFeature ## feature) == CpuFeature ## feature)) /* - Small wrapper around x86's PAUSE instruction. + Small wrapper around x86's PAUSE and ARM's YIELD instructions. This is completely different from QThread::yieldCurrentThread(), which is an OS-level operation that takes the whole thread off the CPU. @@ -420,6 +420,21 @@ static inline void qYieldCpu() { #if defined(Q_PROCESSOR_X86) _mm_pause(); +#elif defined(Q_PROCESSOR_ARM) +# if __has_builtin(__builtin_arm_yield) /* e.g. Clang */ + __builtin_arm_yield(); +# elif defined(Q_OS_INTEGRITY) || \ + (defined(Q_CC_GNU) && !defined(Q_CC_CLANG)) + /* + - Integrity is missing the arm_acle.h header + - GCC doesn't have __yield() in arm_acle.h + https://stackoverflow.com/a/70076751/134841 + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105416 + */ + asm volatile("yield"); /* this works everywhere */ +# else + __yield(); /* this is what should work everywhere */ +# endif #endif } |