summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/core_timing.cpp55
-rw-r--r--src/core/core_timing.h6
-rw-r--r--src/core/hardware_properties.h8
-rw-r--r--src/core/hle/kernel/k_address_space_info.cpp4
-rw-r--r--src/core/hle/kernel/k_address_space_info.h2
-rw-r--r--src/core/hle/kernel/k_device_address_space.h4
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp3
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp45
8 files changed, 77 insertions, 50 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 3a63b52e3..742cfb996 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -6,6 +6,10 @@
#include <string>
#include <tuple>
+#ifdef _WIN32
+#include "common/windows/timer_resolution.h"
+#endif
+
#include "common/microprofile.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
@@ -38,7 +42,8 @@ struct CoreTiming::Event {
};
CoreTiming::CoreTiming()
- : clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {}
+ : cpu_clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)},
+ event_clock{Common::CreateStandardWallClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {}
CoreTiming::~CoreTiming() {
Reset();
@@ -185,15 +190,15 @@ void CoreTiming::ResetTicks() {
}
u64 CoreTiming::GetCPUTicks() const {
- if (is_multicore) {
- return clock->GetCPUCycles();
+ if (is_multicore) [[likely]] {
+ return cpu_clock->GetCPUCycles();
}
return ticks;
}
u64 CoreTiming::GetClockTicks() const {
- if (is_multicore) {
- return clock->GetClockCycles();
+ if (is_multicore) [[likely]] {
+ return cpu_clock->GetClockCycles();
}
return CpuCyclesToClockCycles(ticks);
}
@@ -252,21 +257,20 @@ void CoreTiming::ThreadLoop() {
const auto next_time = Advance();
if (next_time) {
// There are more events left in the queue, wait until the next event.
- const auto wait_time = *next_time - GetGlobalTimeNs().count();
+ auto wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time > 0) {
#ifdef _WIN32
- // Assume a timer resolution of 1ms.
- static constexpr s64 TimerResolutionNS = 1000000;
+ const auto timer_resolution_ns =
+ Common::Windows::GetCurrentTimerResolution().count();
- // Sleep in discrete intervals of the timer resolution, and spin the rest.
- const auto sleep_time = wait_time - (wait_time % TimerResolutionNS);
- if (sleep_time > 0) {
- event.WaitFor(std::chrono::nanoseconds(sleep_time));
- }
+ while (!paused && !event.IsSet() && wait_time > 0) {
+ wait_time = *next_time - GetGlobalTimeNs().count();
- while (!paused && !event.IsSet() && GetGlobalTimeNs().count() < *next_time) {
- // Yield to reduce thread starvation.
- std::this_thread::yield();
+ if (wait_time >= timer_resolution_ns) {
+ Common::Windows::SleepForOneTick();
+ } else {
+ std::this_thread::yield();
+ }
}
if (event.IsSet()) {
@@ -285,9 +289,9 @@ void CoreTiming::ThreadLoop() {
}
paused_set = true;
- clock->Pause(true);
+ event_clock->Pause(true);
pause_event.Wait();
- clock->Pause(false);
+ event_clock->Pause(false);
}
}
@@ -303,16 +307,23 @@ void CoreTiming::Reset() {
has_started = false;
}
+std::chrono::nanoseconds CoreTiming::GetCPUTimeNs() const {
+ if (is_multicore) [[likely]] {
+ return cpu_clock->GetTimeNS();
+ }
+ return CyclesToNs(ticks);
+}
+
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
- if (is_multicore) {
- return clock->GetTimeNS();
+ if (is_multicore) [[likely]] {
+ return event_clock->GetTimeNS();
}
return CyclesToNs(ticks);
}
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
- if (is_multicore) {
- return clock->GetTimeUS();
+ if (is_multicore) [[likely]] {
+ return event_clock->GetTimeUS();
}
return CyclesToUs(ticks);
}
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index da366637b..4b89c0c39 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -122,6 +122,9 @@ public:
/// Returns current time in emulated in Clock cycles
u64 GetClockTicks() const;
+ /// Returns current time in nanoseconds.
+ std::chrono::nanoseconds GetCPUTimeNs() const;
+
/// Returns current time in microseconds.
std::chrono::microseconds GetGlobalTimeUs() const;
@@ -139,7 +142,8 @@ private:
void Reset();
- std::unique_ptr<Common::WallClock> clock;
+ std::unique_ptr<Common::WallClock> cpu_clock;
+ std::unique_ptr<Common::WallClock> event_clock;
s64 global_timer = 0;
diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h
index 45567b840..191c28bb4 100644
--- a/src/core/hardware_properties.h
+++ b/src/core/hardware_properties.h
@@ -13,11 +13,9 @@ namespace Core {
namespace Hardware {
-// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
-// The exact value used is of course unverified.
-constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch cpu frequency is 1020MHz un/docked
-constexpr u64 CNTFREQ = 19200000; // Switch's hardware clock speed
-constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
+constexpr u64 BASE_CLOCK_RATE = 1'020'000'000; // Default CPU Frequency = 1020 MHz
+constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz
+constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
// Virtual to Physical core map.
constexpr std::array<s32, Common::BitSize<u64>()> VirtualToPhysicalCoreMap{
diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp
index 97972ebae..c36eb5dc4 100644
--- a/src/core/hle/kernel/k_address_space_info.cpp
+++ b/src/core/hle/kernel/k_address_space_info.cpp
@@ -44,11 +44,11 @@ const KAddressSpaceInfo& GetAddressSpaceInfo(size_t width, KAddressSpaceInfo::Ty
} // namespace
-uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(size_t width, KAddressSpaceInfo::Type type) {
+std::size_t KAddressSpaceInfo::GetAddressSpaceStart(size_t width, KAddressSpaceInfo::Type type) {
return GetAddressSpaceInfo(width, type).address;
}
-size_t KAddressSpaceInfo::GetAddressSpaceSize(size_t width, KAddressSpaceInfo::Type type) {
+std::size_t KAddressSpaceInfo::GetAddressSpaceSize(size_t width, KAddressSpaceInfo::Type type) {
return GetAddressSpaceInfo(width, type).size;
}
diff --git a/src/core/hle/kernel/k_address_space_info.h b/src/core/hle/kernel/k_address_space_info.h
index 69e9d77f2..9a26f6b90 100644
--- a/src/core/hle/kernel/k_address_space_info.h
+++ b/src/core/hle/kernel/k_address_space_info.h
@@ -18,7 +18,7 @@ struct KAddressSpaceInfo final {
Count,
};
- static u64 GetAddressSpaceStart(std::size_t width, Type type);
+ static std::size_t GetAddressSpaceStart(std::size_t width, Type type);
static std::size_t GetAddressSpaceSize(std::size_t width, Type type);
const std::size_t bit_width{};
diff --git a/src/core/hle/kernel/k_device_address_space.h b/src/core/hle/kernel/k_device_address_space.h
index 4709df995..b4a014c38 100644
--- a/src/core/hle/kernel/k_device_address_space.h
+++ b/src/core/hle/kernel/k_device_address_space.h
@@ -21,9 +21,9 @@ public:
~KDeviceAddressSpace();
Result Initialize(u64 address, u64 size);
- void Finalize();
+ void Finalize() override;
- bool IsInitialized() const {
+ bool IsInitialized() const override {
return m_is_initialized;
}
static void PostDestroy(uintptr_t arg) {}
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index b9d22b414..626517619 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
+#include "common/overflow.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_resource_limit.h"
@@ -104,7 +105,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
ASSERT(current_hints[index] <= current_values[index]);
// If we would overflow, don't allow to succeed.
- if (current_values[index] + value <= current_values[index]) {
+ if (Common::WrappingAdd(current_values[index], value) <= current_values[index]) {
break;
}
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index 1a8f7e191..9e7bf9530 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -48,19 +48,15 @@ Result ResetSignal(Core::System& system, Handle handle) {
return ResultInvalidHandle;
}
-/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
-Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, s32 num_handles,
- s64 nano_seconds) {
- LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}",
- handles_address, num_handles, nano_seconds);
-
+static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles,
+ int32_t num_handles, int64_t timeout_ns) {
// Ensure number of handles is valid.
- R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
+ R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
+ // Get the synchronization context.
auto& kernel = system.Kernel();
+ auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
std::vector<KSynchronizationObject*> objs(num_handles);
- const auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
- Handle* handles = system.Memory().GetPointer<Handle>(handles_address);
// Copy user handles.
if (num_handles > 0) {
@@ -68,21 +64,38 @@ Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_addre
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles,
num_handles),
ResultInvalidHandle);
- for (const auto& obj : objs) {
- kernel.RegisterInUseObject(obj);
- }
}
// Ensure handles are closed when we're done.
SCOPE_EXIT({
- for (s32 i = 0; i < num_handles; ++i) {
- kernel.UnregisterInUseObject(objs[i]);
+ for (auto i = 0; i < num_handles; ++i) {
objs[i]->Close();
}
});
- return KSynchronizationObject::Wait(kernel, index, objs.data(), static_cast<s32>(objs.size()),
- nano_seconds);
+ // Wait on the objects.
+ Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(),
+ static_cast<s32>(objs.size()), timeout_ns);
+
+ R_SUCCEED_IF(res == ResultSessionClosed);
+ R_RETURN(res);
+}
+
+/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
+Result WaitSynchronization(Core::System& system, int32_t* out_index, VAddr user_handles,
+ int32_t num_handles, int64_t timeout_ns) {
+ LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
+ num_handles, timeout_ns);
+
+ // Ensure number of handles is valid.
+ R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
+
+ std::vector<Handle> handles(num_handles);
+ if (num_handles > 0) {
+ system.Memory().ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
+ }
+
+ R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns));
}
/// Resumes a thread waiting on WaitSynchronization