Merge pull request #1985 from CookiePLMonster/fix-rdtsc-overflow
Make RDTSC and ACPI timers stateful to fix overflows
This commit is contained in:
commit
efe42f4eba
|
@ -324,43 +324,64 @@ void InitDpcThread()
|
|||
g_DpcData.DpcEvent = CreateEvent(/*lpEventAttributes=*/nullptr, /*bManualReset=*/FALSE, /*bInitialState=*/FALSE, /*lpName=*/nullptr);
|
||||
}
|
||||
|
||||
#define XBOX_TSC_FREQUENCY 733333333 // Xbox Time Stamp Counter Frequency = 733333333 (CPU Clock)
|
||||
#define XBOX_ACPI_FREQUENCY 3375000 // Xbox ACPI frequency (3.375 mhz)
|
||||
ULONGLONG NativeToXbox_FactorForRdtsc;
|
||||
ULONGLONG NativeToXbox_FactorForAcpi;
|
||||
static constexpr uint32_t XBOX_TSC_FREQUENCY = 733333333; // Xbox Time Stamp Counter Frequency = 733333333 (CPU Clock)
|
||||
static constexpr uint32_t XBOX_ACPI_FREQUENCY = 3375000; // Xbox ACPI frequency (3.375 mhz)
|
||||
static constexpr uint32_t SEC_TO_NSEC = 1000000000; // For seconds -> nanoseconds conversions
|
||||
static uint64_t NativeToXbox_FactorForRdtsc = 0, NativeToXbox_FactorForAcpi = 0;
|
||||
|
||||
// State for CxbxGetPerformanceCounter - concurrent access should be next to non-existent, but secure against it anyway
|
||||
static std::mutex RdtscLock, AcpiLock;
|
||||
static LARGE_INTEGER LastRdtscQPC, LastAcpiQPC;
|
||||
static ULONGLONG CurrentRdtsc = 0, CurrentAcpi = 0;
|
||||
static ULONGLONG CurrentRdtscRemainder = 0, CurrentAcpiRemainder = 0;
|
||||
|
||||
ULONGLONG CxbxGetPerformanceCounter(bool acpi)
|
||||
{
|
||||
if (acpi == false && NativeToXbox_FactorForRdtsc != 0) {
|
||||
std::lock_guard<std::mutex> lock(RdtscLock);
|
||||
|
||||
ULONGLONG CxbxGetPerformanceCounter(bool acpi) {
|
||||
LARGE_INTEGER tsc;
|
||||
ULARGE_INTEGER scaledTsc;
|
||||
|
||||
QueryPerformanceCounter(&tsc);
|
||||
|
||||
scaledTsc.QuadPart = 1000000000;
|
||||
scaledTsc.QuadPart *= (ULONGLONG)tsc.QuadPart;
|
||||
LARGE_INTEGER lastTsc = std::exchange(LastRdtscQPC, tsc);
|
||||
tsc.QuadPart -= lastTsc.QuadPart;
|
||||
tsc.QuadPart *= SEC_TO_NSEC;
|
||||
tsc.QuadPart += CurrentRdtscRemainder;
|
||||
ULONGLONG quotient = tsc.QuadPart / NativeToXbox_FactorForRdtsc;
|
||||
ULONGLONG remainder = tsc.QuadPart % NativeToXbox_FactorForRdtsc;
|
||||
|
||||
if (acpi == false && NativeToXbox_FactorForRdtsc) {
|
||||
scaledTsc.QuadPart /= NativeToXbox_FactorForRdtsc;
|
||||
return scaledTsc.QuadPart;
|
||||
} else if (acpi == true && NativeToXbox_FactorForRdtsc) {
|
||||
scaledTsc.QuadPart /= NativeToXbox_FactorForAcpi;
|
||||
return scaledTsc.QuadPart;
|
||||
CurrentRdtscRemainder = remainder;
|
||||
return CurrentRdtsc += quotient;
|
||||
} else if (acpi == true && NativeToXbox_FactorForAcpi != 0) {
|
||||
std::lock_guard<std::mutex> lock(AcpiLock);
|
||||
|
||||
LARGE_INTEGER tsc;
|
||||
QueryPerformanceCounter(&tsc);
|
||||
|
||||
LARGE_INTEGER lastTsc = std::exchange(LastAcpiQPC, tsc);
|
||||
tsc.QuadPart -= lastTsc.QuadPart;
|
||||
tsc.QuadPart *= SEC_TO_NSEC;
|
||||
tsc.QuadPart += CurrentAcpiRemainder;
|
||||
ULONGLONG quotient = tsc.QuadPart / NativeToXbox_FactorForAcpi;
|
||||
ULONGLONG remainder = tsc.QuadPart % NativeToXbox_FactorForAcpi;
|
||||
|
||||
CurrentAcpiRemainder = remainder;
|
||||
return CurrentAcpi += quotient;
|
||||
}
|
||||
|
||||
return (uint64_t)tsc.QuadPart;
|
||||
LARGE_INTEGER tsc;
|
||||
QueryPerformanceCounter(&tsc);
|
||||
return static_cast<ULONGLONG>(tsc.QuadPart);
|
||||
}
|
||||
|
||||
void CxbxInitPerformanceCounters()
|
||||
{
|
||||
uint64_t t;
|
||||
t = 1000000000;
|
||||
t *= HostClockFrequency;
|
||||
t /= XBOX_TSC_FREQUENCY;
|
||||
NativeToXbox_FactorForRdtsc = t;
|
||||
NativeToXbox_FactorForRdtsc = Muldiv64(HostClockFrequency, SEC_TO_NSEC, XBOX_TSC_FREQUENCY);
|
||||
NativeToXbox_FactorForAcpi = Muldiv64(HostClockFrequency, SEC_TO_NSEC, XBOX_ACPI_FREQUENCY);
|
||||
|
||||
t = 1000000000;
|
||||
t *= HostClockFrequency;
|
||||
t /= XBOX_ACPI_FREQUENCY;
|
||||
NativeToXbox_FactorForAcpi = t;
|
||||
LARGE_INTEGER tsc;
|
||||
QueryPerformanceCounter(&tsc);
|
||||
LastRdtscQPC = LastAcpiQPC = tsc;
|
||||
|
||||
// Let's initialize the Dpc handling thread too,
|
||||
// here for now (should be called by our caller)
|
||||
|
|
Loading…
Reference in New Issue