summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2022-04-29 12:28:09 +0200
committerMarc Mutz <marc.mutz@qt.io>2022-05-10 00:09:04 +0000
commit877c158c5976bebffd0ff02c39b6b66a842c6344 (patch)
tree32a53857dc83d6ad57f8a257752e2354ee84635f /src
parent71322ef36142570edc94c361ceb21f770303aceb (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.h17
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
}