Long live qYieldCpu()!

This is a small wrapper around PAUSE (x86) (and, eventually, YIELD
(ARM) and whatever MIPS and Sparc have for this purpose) instructions
to improve the performance of tight CAS loops.

Pick-to: 6.3
Change-Id: I51e58484c7f02fdbdc491fd1f4a2e9a34f7c2cd0
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2022-04-28 08:41:16 +02:00
parent 2efd5ad7af
commit 23e580f1b4

View File

@ -394,6 +394,35 @@ static inline uint64_t qCpuFeatures()
#define qCpuHasFeature(feature) (((qCompilerCpuFeatures & CpuFeature ## feature) == CpuFeature ## feature) \
|| ((qCpuFeatures() & CpuFeature ## feature) == CpuFeature ## feature))
/*
Small wrapper around x86's PAUSE instruction.
This is completely different from QThread::yieldCurrentThread(), which is
an OS-level operation that takes the whole thread off the CPU.
This is just preventing one SMT thread from filling a core's pipeline with
speculated further loop iterations (which need to be expensively flushed on
final success) when it could just give those pipeline slots to a second SMT
thread that can do something useful with the core, such as unblocking this
SMT thread :)
So, instead of
while (!condition)
;
it's better to use
while (!condition)
qYieldCpu();
*/
static inline void qYieldCpu()
{
#if defined(Q_PROCESSOR_X86)
_mm_pause();
#endif
}
#ifdef __cplusplus
} // extern "C"