diff --git a/src/common/Timer.cpp b/src/common/Timer.cpp index 2a48976f1..2945fc32f 100644 --- a/src/common/Timer.cpp +++ b/src/common/Timer.cpp @@ -27,9 +27,7 @@ #include -#ifdef _WIN32 #include -#endif #include #include #include @@ -42,9 +40,6 @@ #include "devices\Xbox.h" #include "devices\usb\OHCI.h" #include "core\hle\DSOUND\DirectSound\DirectSoundGlobal.hpp" -#ifdef __linux__ -#include -#endif static uint64_t last_qpc; // last time when QPC was called @@ -56,6 +51,21 @@ static uint64_t pit_last_qpc; // last QPC time of the pit int64_t HostQPCFrequency, HostQPCStartTime; +void timer_init() +{ + QueryPerformanceFrequency(reinterpret_cast(&HostQPCFrequency)); + QueryPerformanceCounter(reinterpret_cast(&last_qpc)); + pit_last_qpc = last_qpc; + pit_last = get_now(); + + // Synchronize xbox system time with host time + LARGE_INTEGER HostSystemTime; + GetSystemTimeAsFileTime((LPFILETIME)&HostSystemTime); + xbox::KeSystemTime.High2Time = HostSystemTime.u.HighPart; + xbox::KeSystemTime.LowPart = HostSystemTime.u.LowPart; + xbox::KeSystemTime.High1Time = HostSystemTime.u.HighPart; +} + // More precise sleep, but with increased CPU usage void SleepPrecise(std::chrono::steady_clock::time_point targetTime) { @@ -168,21 +178,6 @@ xbox::void_xt NTAPI system_events(xbox::PVOID arg) } } -// Retrives the frequency of the high resolution clock of the host -void timer_init() -{ -#ifdef _WIN32 - QueryPerformanceFrequency(reinterpret_cast(&HostQPCFrequency)); - QueryPerformanceCounter(reinterpret_cast(&last_qpc)); - pit_last_qpc = last_qpc; - pit_last = get_now(); -#elif __linux__ - ClockFrequency = 0; -#else -#error "Unsupported OS" -#endif -} - int64_t Timer_GetScaledPerformanceCounter(int64_t Period) { LARGE_INTEGER currentQPC; diff --git a/src/core/kernel/common/rtl.h b/src/core/kernel/common/rtl.h index 924d11ed8..8af147374 100644 --- a/src/core/kernel/common/rtl.h +++ b/src/core/kernel/common/rtl.h @@ -605,6 +605,9 @@ XBSYSAPI EXPORTNUM(352) void_xt NTAPI RtlRip PCHAR Message ); +void_xt RtlInitSystem(); +extern RTL_CRITICAL_SECTION NtSystemTimeCritSec; + } #endif diff --git a/src/core/kernel/exports/EmuKrnlKe.cpp b/src/core/kernel/exports/EmuKrnlKe.cpp index 41a36ca14..25de991f7 100644 --- a/src/core/kernel/exports/EmuKrnlKe.cpp +++ b/src/core/kernel/exports/EmuKrnlKe.cpp @@ -166,7 +166,7 @@ xbox::void_xt NTAPI xbox::KeSetSystemTime ) { KIRQL OldIrql, OldIrql2; - LARGE_INTEGER DeltaTime, HostTime; + LARGE_INTEGER DeltaTime; PLIST_ENTRY ListHead, NextEntry; PKTIMER Timer; LIST_ENTRY TempList, TempList2; @@ -184,10 +184,6 @@ xbox::void_xt NTAPI xbox::KeSetSystemTime /* Query the system time now */ KeQuerySystemTime(OldTime); - /* Surely, we won't set the system time here, but we CAN remember a delta to the host system time */ - HostTime.QuadPart = OldTime->QuadPart - HostSystemTimeDelta.load(); - HostSystemTimeDelta = NewTime->QuadPart - HostTime.QuadPart; - /* Calculate the difference between the new and the old time */ DeltaTime.QuadPart = NewTime->QuadPart - OldTime->QuadPart; diff --git a/src/core/kernel/exports/EmuKrnlKi.cpp b/src/core/kernel/exports/EmuKrnlKi.cpp index fc416dbda..5dd308383 100644 --- a/src/core/kernel/exports/EmuKrnlKi.cpp +++ b/src/core/kernel/exports/EmuKrnlKi.cpp @@ -148,8 +148,7 @@ xbox::void_xt xbox::KiWaitListUnlock() xbox::void_xt xbox::KiClockIsr() { KIRQL OldIrql; - LARGE_INTEGER InterruptTime; - LARGE_INTEGER HostSystemTime; + LARGE_INTEGER InterruptTime, SystemTime; ULONG Hand; DWORD OldKeTickCount; @@ -164,13 +163,12 @@ xbox::void_xt xbox::KiClockIsr() KeInterruptTime.High1Time = InterruptTime.u.HighPart; // Update the system time - // NOTE: I'm not sure if we should round down the host system time to the nearest multiple - // of the Xbox clock increment... - GetSystemTimeAsFileTime((LPFILETIME)&HostSystemTime); - HostSystemTime.QuadPart += HostSystemTimeDelta.load(); - KeSystemTime.High2Time = HostSystemTime.u.HighPart; - KeSystemTime.LowPart = HostSystemTime.u.LowPart; - KeSystemTime.High1Time = HostSystemTime.u.HighPart; + SystemTime.u.LowPart = KeSystemTime.LowPart; + SystemTime.u.HighPart = KeSystemTime.High1Time; + SystemTime.QuadPart += CLOCK_TIME_INCREMENT; + KeSystemTime.High2Time = SystemTime.u.HighPart; + KeSystemTime.LowPart = SystemTime.u.LowPart; + KeSystemTime.High1Time = SystemTime.u.HighPart; // Update the tick counter OldKeTickCount = KeTickCount; diff --git a/src/core/kernel/exports/EmuKrnlNt.cpp b/src/core/kernel/exports/EmuKrnlNt.cpp index 19be4b8e0..35ee825e8 100644 --- a/src/core/kernel/exports/EmuKrnlNt.cpp +++ b/src/core/kernel/exports/EmuKrnlNt.cpp @@ -58,7 +58,7 @@ namespace NtDll #include // Prevent setting the system time from multiple threads at the same time -std::mutex NtSystemTimeMtx; +xbox::RTL_CRITICAL_SECTION xbox::NtSystemTimeCritSec; // ****************************************************************** // * 0x00B8 - NtAllocateVirtualMemory() @@ -1976,7 +1976,7 @@ XBSYSAPI EXPORTNUM(228) xbox::ntstatus_xt NTAPI xbox::NtSetSystemTime ret = STATUS_ACCESS_VIOLATION; } else { - NtSystemTimeMtx.lock(); + RtlEnterCriticalSectionAndRegion(&NtSystemTimeCritSec); NewSystemTime = *SystemTime; if (NewSystemTime.u.HighPart > 0 && NewSystemTime.u.HighPart <= 0x20000000) { /* Convert the time and set it in HAL */ @@ -1996,7 +1996,7 @@ XBSYSAPI EXPORTNUM(228) xbox::ntstatus_xt NTAPI xbox::NtSetSystemTime else { ret = STATUS_INVALID_PARAMETER; } - NtSystemTimeMtx.unlock(); + RtlLeaveCriticalSectionAndRegion(&NtSystemTimeCritSec); } RETURN(ret); diff --git a/src/core/kernel/exports/EmuKrnlRtl.cpp b/src/core/kernel/exports/EmuKrnlRtl.cpp index 671cca6d5..dad495104 100644 --- a/src/core/kernel/exports/EmuKrnlRtl.cpp +++ b/src/core/kernel/exports/EmuKrnlRtl.cpp @@ -89,6 +89,11 @@ xbox::boolean_xt RtlpCaptureStackLimits( return TRUE; } +xbox::void_xt xbox::RtlInitSystem() +{ + xbox::RtlInitializeCriticalSection(&NtSystemTimeCritSec); +} + // ****************************************************************** // * 0x0104 - RtlAnsiStringToUnicodeString() // ****************************************************************** diff --git a/src/core/kernel/init/CxbxKrnl.cpp b/src/core/kernel/init/CxbxKrnl.cpp index 3ed6d83ae..a679eb905 100644 --- a/src/core/kernel/init/CxbxKrnl.cpp +++ b/src/core/kernel/init/CxbxKrnl.cpp @@ -1285,6 +1285,7 @@ static void CxbxrKrnlInitHacks() } xbox::PsInitSystem(); xbox::KiInitSystem(); + xbox::RtlInitSystem(); // initialize graphics EmuLogInit(LOG_LEVEL::DEBUG, "Initializing render window."); diff --git a/src/core/kernel/support/Emu.cpp b/src/core/kernel/support/Emu.cpp index da98ab08f..45f697d85 100644 --- a/src/core/kernel/support/Emu.cpp +++ b/src/core/kernel/support/Emu.cpp @@ -49,11 +49,6 @@ bool g_DisablePixelShaders = false; bool g_UseAllCores = false; bool g_SkipRdtscPatching = false; -// Delta added to host SystemTime, used in KiClockIsr and KeSetSystemTime -// This shouldn't need to be atomic, but because raising the IRQL to high lv in KeSetSystemTime doesn't really stop KiClockIsr from running, -// we need it for now to prevent reading a corrupted value while KeSetSystemTime is in the middle of updating it -std::atomic_int64_t HostSystemTimeDelta(0); - // Static Function(s) static int ExitException(LPEXCEPTION_POINTERS e); diff --git a/src/core/kernel/support/Emu.h b/src/core/kernel/support/Emu.h index d12f493ab..2087adc84 100644 --- a/src/core/kernel/support/Emu.h +++ b/src/core/kernel/support/Emu.h @@ -68,9 +68,6 @@ extern HWND g_hEmuWindow; extern HANDLE g_CurrentProcessHandle; // Set in CxbxKrnlMain -// Delta added to host SystemTime, used in KiClockIsr and KeSetSystemTime -extern std::atomic_int64_t HostSystemTimeDelta; - typedef struct DUMMY_KERNEL { IMAGE_DOS_HEADER DosHeader;