summaryrefslogtreecommitdiff
path: root/src/common/x64/cpu_wait.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/x64/cpu_wait.cpp')
-rw-r--r--src/common/x64/cpu_wait.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/common/x64/cpu_wait.cpp b/src/common/x64/cpu_wait.cpp
new file mode 100644
index 000000000..c53dd4945
--- /dev/null
+++ b/src/common/x64/cpu_wait.cpp
@@ -0,0 +1,51 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <thread>
5
6#ifdef _MSC_VER
7#include <intrin.h>
8#endif
9
10#include "common/x64/cpu_detect.h"
11#include "common/x64/cpu_wait.h"
12#include "common/x64/rdtsc.h"
13
14namespace Common::X64 {
15
16#ifdef _MSC_VER
17__forceinline static void TPAUSE() {
18 // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
19 // For reference:
20 // At 1 GHz, 100K cycles is 100us
21 // At 2 GHz, 100K cycles is 50us
22 // At 4 GHz, 100K cycles is 25us
23 static constexpr auto PauseCycles = 100'000;
24 _tpause(0, FencedRDTSC() + PauseCycles);
25}
26#else
27static void TPAUSE() {
28 // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
29 // For reference:
30 // At 1 GHz, 100K cycles is 100us
31 // At 2 GHz, 100K cycles is 50us
32 // At 4 GHz, 100K cycles is 25us
33 static constexpr auto PauseCycles = 100'000;
34 const auto tsc = FencedRDTSC() + PauseCycles;
35 const auto eax = static_cast<u32>(tsc & 0xFFFFFFFF);
36 const auto edx = static_cast<u32>(tsc >> 32);
37 asm volatile("tpause %0" : : "r"(0), "d"(edx), "a"(eax));
38}
39#endif
40
41void MicroSleep() {
42 static const bool has_waitpkg = GetCPUCaps().waitpkg;
43
44 if (has_waitpkg) {
45 TPAUSE();
46 } else {
47 std::this_thread::yield();
48 }
49}
50
51} // namespace Common::X64