aboutsummaryrefslogtreecommitdiff
path: root/src/common/x64/cpu_wait.cpp
diff options
context:
space:
mode:
authorMorph <39850852+Morph1984@users.noreply.github.com>2023-06-28 01:07:59 -0400
committerMorph <39850852+Morph1984@users.noreply.github.com>2023-06-28 01:38:55 -0400
commitcffefaf8a79884d8d44def727c8576a0c0ae87bb (patch)
treefbb7537115995eeed7f13f50393d8518e4b90f4f /src/common/x64/cpu_wait.cpp
parent841a3559a5e71cbdb0647b8296b89712b535a09e (diff)
x64: cpu_wait: Make use of MWAITX in MicroSleep
MWAITX is equivalent to UMWAIT on Intel's Alder Lake CPUs. We can emulate TPAUSE by using MONITORX in conjunction with MWAITX to wait for 100K cycles.
Diffstat (limited to 'src/common/x64/cpu_wait.cpp')
-rw-r--r--src/common/x64/cpu_wait.cpp33
1 files changed, 21 insertions, 12 deletions
diff --git a/src/common/x64/cpu_wait.cpp b/src/common/x64/cpu_wait.cpp
index c53dd49453..11b9c4d83a 100644
--- a/src/common/x64/cpu_wait.cpp
+++ b/src/common/x64/cpu_wait.cpp
@@ -13,24 +13,30 @@
namespace Common::X64 {
+namespace {
+
+// 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
+// For reference:
+// At 1 GHz, 100K cycles is 100us
+// At 2 GHz, 100K cycles is 50us
+// At 4 GHz, 100K cycles is 25us
+constexpr auto PauseCycles = 100'000U;
+
+} // Anonymous namespace
+
#ifdef _MSC_VER
__forceinline static void TPAUSE() {
- // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
- // For reference:
- // At 1 GHz, 100K cycles is 100us
- // At 2 GHz, 100K cycles is 50us
- // At 4 GHz, 100K cycles is 25us
- static constexpr auto PauseCycles = 100'000;
_tpause(0, FencedRDTSC() + PauseCycles);
}
+
+__forceinline static void MWAITX() {
+ // monitor_var should be aligned to a cache line.
+ alignas(64) u64 monitor_var{};
+ _mm_monitorx(&monitor_var, 0, 0);
+ _mm_mwaitx(/* extensions*/ 2, /* hints */ 0, /* cycles */ PauseCycles);
+}
#else
static void TPAUSE() {
- // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
- // For reference:
- // At 1 GHz, 100K cycles is 100us
- // At 2 GHz, 100K cycles is 50us
- // At 4 GHz, 100K cycles is 25us
- static constexpr auto PauseCycles = 100'000;
const auto tsc = FencedRDTSC() + PauseCycles;
const auto eax = static_cast<u32>(tsc & 0xFFFFFFFF);
const auto edx = static_cast<u32>(tsc >> 32);
@@ -40,9 +46,12 @@ static void TPAUSE() {
void MicroSleep() {
static const bool has_waitpkg = GetCPUCaps().waitpkg;
+ static const bool has_monitorx = GetCPUCaps().monitorx;
if (has_waitpkg) {
TPAUSE();
+ } else if (has_monitorx) {
+ MWAITX();
} else {
std::this_thread::yield();
}