early-access version 3816
This commit is contained in:
parent
16bc256b6e
commit
3e922c262d
@ -1,7 +1,7 @@
|
|||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3815.
|
This is the source code for early-access 3816.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
@ -19,13 +19,7 @@ public:
|
|||||||
void Initialize();
|
void Initialize();
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
s64 GetCount() const {
|
s64 GetTick() const;
|
||||||
return GetTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterTask(KTimerTask* task, s64 time_from_now) {
|
|
||||||
this->RegisterAbsoluteTask(task, GetTick() + time_from_now);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) {
|
void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) {
|
||||||
KScopedDisableDispatch dd{m_kernel};
|
KScopedDisableDispatch dd{m_kernel};
|
||||||
@ -42,7 +36,6 @@ private:
|
|||||||
void EnableInterrupt(s64 wakeup_time);
|
void EnableInterrupt(s64 wakeup_time);
|
||||||
void DisableInterrupt();
|
void DisableInterrupt();
|
||||||
bool GetInterruptEnabled();
|
bool GetInterruptEnabled();
|
||||||
s64 GetTick() const;
|
|
||||||
void DoTask();
|
void DoTask();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "common/overflow.h"
|
#include "common/overflow.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
|
#include "core/hle/kernel/k_hardware_timer.h"
|
||||||
#include "core/hle/kernel/k_resource_limit.h"
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/svc_results.h"
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
@ -15,9 +16,7 @@ KResourceLimit::KResourceLimit(KernelCore& kernel)
|
|||||||
: KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {}
|
: KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {}
|
||||||
KResourceLimit::~KResourceLimit() = default;
|
KResourceLimit::~KResourceLimit() = default;
|
||||||
|
|
||||||
void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing) {
|
void KResourceLimit::Initialize() {}
|
||||||
m_core_timing = core_timing;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KResourceLimit::Finalize() {}
|
void KResourceLimit::Finalize() {}
|
||||||
|
|
||||||
@ -86,7 +85,7 @@ Result KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
|
bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
|
||||||
return Reserve(which, value, m_core_timing->GetGlobalTimeNs().count() + DefaultTimeout);
|
return Reserve(which, value, m_kernel.HardwareTimer().GetTick() + DefaultTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
|
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
|
||||||
@ -117,7 +116,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_current_hints[index] + value <= m_limit_values[index] &&
|
if (m_current_hints[index] + value <= m_limit_values[index] &&
|
||||||
(timeout < 0 || m_core_timing->GetGlobalTimeNs().count() < timeout)) {
|
(timeout < 0 || m_kernel.HardwareTimer().GetTick() < timeout)) {
|
||||||
m_waiter_count++;
|
m_waiter_count++;
|
||||||
m_cond_var.Wait(std::addressof(m_lock), timeout, false);
|
m_cond_var.Wait(std::addressof(m_lock), timeout, false);
|
||||||
m_waiter_count--;
|
m_waiter_count--;
|
||||||
@ -154,7 +153,7 @@ void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) {
|
|||||||
|
|
||||||
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size) {
|
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size) {
|
||||||
auto* resource_limit = KResourceLimit::Create(system.Kernel());
|
auto* resource_limit = KResourceLimit::Create(system.Kernel());
|
||||||
resource_limit->Initialize(std::addressof(system.CoreTiming()));
|
resource_limit->Initialize();
|
||||||
|
|
||||||
// Initialize default resource limit values.
|
// Initialize default resource limit values.
|
||||||
// TODO(bunnei): These values are the system defaults, the limits for service processes are
|
// TODO(bunnei): These values are the system defaults, the limits for service processes are
|
||||||
|
@ -31,7 +31,7 @@ public:
|
|||||||
explicit KResourceLimit(KernelCore& kernel);
|
explicit KResourceLimit(KernelCore& kernel);
|
||||||
~KResourceLimit() override;
|
~KResourceLimit() override;
|
||||||
|
|
||||||
void Initialize(const Core::Timing::CoreTiming* core_timing);
|
void Initialize();
|
||||||
void Finalize() override;
|
void Finalize() override;
|
||||||
|
|
||||||
s64 GetLimitValue(LimitableResource which) const;
|
s64 GetLimitValue(LimitableResource which) const;
|
||||||
@ -57,7 +57,6 @@ private:
|
|||||||
mutable KLightLock m_lock;
|
mutable KLightLock m_lock;
|
||||||
s32 m_waiter_count{};
|
s32 m_waiter_count{};
|
||||||
KLightConditionVariable m_cond_var;
|
KLightConditionVariable m_cond_var;
|
||||||
const Core::Timing::CoreTiming* m_core_timing{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size);
|
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size);
|
||||||
|
@ -28,7 +28,7 @@ public:
|
|||||||
~KScopedSchedulerLockAndSleep() {
|
~KScopedSchedulerLockAndSleep() {
|
||||||
// Register the sleep.
|
// Register the sleep.
|
||||||
if (m_timeout_tick > 0) {
|
if (m_timeout_tick > 0) {
|
||||||
m_timer->RegisterTask(m_thread, m_timeout_tick);
|
m_timer->RegisterAbsoluteTask(m_thread, m_timeout_tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock the scheduler.
|
// Unlock the scheduler.
|
||||||
|
@ -231,7 +231,7 @@ struct KernelCore::Impl {
|
|||||||
void InitializeSystemResourceLimit(KernelCore& kernel,
|
void InitializeSystemResourceLimit(KernelCore& kernel,
|
||||||
const Core::Timing::CoreTiming& core_timing) {
|
const Core::Timing::CoreTiming& core_timing) {
|
||||||
system_resource_limit = KResourceLimit::Create(system.Kernel());
|
system_resource_limit = KResourceLimit::Create(system.Kernel());
|
||||||
system_resource_limit->Initialize(&core_timing);
|
system_resource_limit->Initialize();
|
||||||
KResourceLimit::Register(kernel, system_resource_limit);
|
KResourceLimit::Register(kernel, system_resource_limit);
|
||||||
|
|
||||||
const auto sizes{memory_layout->GetTotalAndKernelMemorySizes()};
|
const auto sizes{memory_layout->GetTotalAndKernelMemorySizes()};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/hle/kernel/k_hardware_timer.h"
|
||||||
#include "core/hle/kernel/k_memory_layout.h"
|
#include "core/hle/kernel/k_memory_layout.h"
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
@ -52,7 +53,7 @@ Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_typ
|
|||||||
if (timeout_ns > 0) {
|
if (timeout_ns > 0) {
|
||||||
const s64 offset_tick(timeout_ns);
|
const s64 offset_tick(timeout_ns);
|
||||||
if (offset_tick > 0) {
|
if (offset_tick > 0) {
|
||||||
timeout = offset_tick + 2;
|
timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2;
|
||||||
if (timeout <= 0) {
|
if (timeout <= 0) {
|
||||||
timeout = std::numeric_limits<s64>::max();
|
timeout = std::numeric_limits<s64>::max();
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/hle/kernel/k_hardware_timer.h"
|
||||||
#include "core/hle/kernel/k_memory_layout.h"
|
#include "core/hle/kernel/k_memory_layout.h"
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
@ -25,7 +26,7 @@ Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u
|
|||||||
if (timeout_ns > 0) {
|
if (timeout_ns > 0) {
|
||||||
const s64 offset_tick(timeout_ns);
|
const s64 offset_tick(timeout_ns);
|
||||||
if (offset_tick > 0) {
|
if (offset_tick > 0) {
|
||||||
timeout = offset_tick + 2;
|
timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2;
|
||||||
if (timeout <= 0) {
|
if (timeout <= 0) {
|
||||||
timeout = std::numeric_limits<s64>::max();
|
timeout = std::numeric_limits<s64>::max();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "common/scratch_buffer.h"
|
#include "common/scratch_buffer.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/k_client_session.h"
|
#include "core/hle/kernel/k_client_session.h"
|
||||||
|
#include "core/hle/kernel/k_hardware_timer.h"
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/k_server_session.h"
|
#include "core/hle/kernel/k_server_session.h"
|
||||||
#include "core/hle/kernel/svc.h"
|
#include "core/hle/kernel/svc.h"
|
||||||
@ -82,12 +83,29 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
|
|||||||
R_TRY(session->SendReply());
|
R_TRY(session->SendReply());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert the timeout from nanoseconds to ticks.
|
||||||
|
// NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
|
||||||
|
s64 timeout;
|
||||||
|
if (timeout_ns > 0) {
|
||||||
|
const s64 offset_tick(timeout_ns);
|
||||||
|
if (offset_tick > 0) {
|
||||||
|
timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
|
||||||
|
if (timeout <= 0) {
|
||||||
|
timeout = std::numeric_limits<s64>::max();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timeout = std::numeric_limits<s64>::max();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timeout = timeout_ns;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for a message.
|
// Wait for a message.
|
||||||
while (true) {
|
while (true) {
|
||||||
// Wait for an object.
|
// Wait for an object.
|
||||||
s32 index;
|
s32 index;
|
||||||
Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(),
|
Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(),
|
||||||
num_handles, timeout_ns);
|
num_handles, timeout);
|
||||||
if (result == ResultTimedOut) {
|
if (result == ResultTimedOut) {
|
||||||
R_RETURN(result);
|
R_RETURN(result);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
|
|||||||
SCOPE_EXIT({ resource_limit->Close(); });
|
SCOPE_EXIT({ resource_limit->Close(); });
|
||||||
|
|
||||||
// Initialize the resource limit.
|
// Initialize the resource limit.
|
||||||
resource_limit->Initialize(std::addressof(system.CoreTiming()));
|
resource_limit->Initialize();
|
||||||
|
|
||||||
// Register the limit.
|
// Register the limit.
|
||||||
KResourceLimit::Register(kernel, resource_limit);
|
KResourceLimit::Register(kernel, resource_limit);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "common/scratch_buffer.h"
|
#include "common/scratch_buffer.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/hle/kernel/k_hardware_timer.h"
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
#include "core/hle/kernel/svc.h"
|
#include "core/hle/kernel/svc.h"
|
||||||
@ -83,9 +84,20 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Convert the timeout from nanoseconds to ticks.
|
||||||
|
s64 timeout;
|
||||||
|
if (timeout_ns > 0) {
|
||||||
|
u64 ticks = kernel.HardwareTimer().GetTick();
|
||||||
|
ticks += timeout_ns;
|
||||||
|
ticks += 2;
|
||||||
|
|
||||||
|
timeout = ticks;
|
||||||
|
} else {
|
||||||
|
timeout = timeout_ns;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait on the objects.
|
// Wait on the objects.
|
||||||
Result res =
|
Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout);
|
||||||
KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout_ns);
|
|
||||||
|
|
||||||
R_SUCCEED_IF(res == ResultSessionClosed);
|
R_SUCCEED_IF(res == ResultSessionClosed);
|
||||||
R_RETURN(res);
|
R_RETURN(res);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
|
#include "core/hle/kernel/k_hardware_timer.h"
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
@ -42,9 +43,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u
|
|||||||
R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority);
|
R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority);
|
||||||
|
|
||||||
// Reserve a new thread from the process resource limit (waiting up to 100ms).
|
// Reserve a new thread from the process resource limit (waiting up to 100ms).
|
||||||
KScopedResourceReservation thread_reservation(
|
KScopedResourceReservation thread_reservation(std::addressof(process),
|
||||||
std::addressof(process), LimitableResource::ThreadCountMax, 1,
|
LimitableResource::ThreadCountMax, 1,
|
||||||
system.CoreTiming().GetGlobalTimeNs().count() + 100000000);
|
kernel.HardwareTimer().GetTick() + 100000000);
|
||||||
R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached);
|
R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached);
|
||||||
|
|
||||||
// Create the thread.
|
// Create the thread.
|
||||||
@ -102,20 +103,31 @@ void ExitThread(Core::System& system) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sleep the current thread
|
/// Sleep the current thread
|
||||||
void SleepThread(Core::System& system, s64 nanoseconds) {
|
void SleepThread(Core::System& system, s64 ns) {
|
||||||
auto& kernel = system.Kernel();
|
auto& kernel = system.Kernel();
|
||||||
const auto yield_type = static_cast<Svc::YieldType>(nanoseconds);
|
const auto yield_type = static_cast<Svc::YieldType>(ns);
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
|
LOG_TRACE(Kernel_SVC, "called nanoseconds={}", ns);
|
||||||
|
|
||||||
// When the input tick is positive, sleep.
|
// When the input tick is positive, sleep.
|
||||||
if (nanoseconds > 0) {
|
if (ns > 0) {
|
||||||
// Convert the timeout from nanoseconds to ticks.
|
// Convert the timeout from nanoseconds to ticks.
|
||||||
// NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
|
// NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
|
||||||
|
s64 timeout;
|
||||||
|
|
||||||
|
const s64 offset_tick(ns);
|
||||||
|
if (offset_tick > 0) {
|
||||||
|
timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
|
||||||
|
if (timeout <= 0) {
|
||||||
|
timeout = std::numeric_limits<s64>::max();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timeout = std::numeric_limits<s64>::max();
|
||||||
|
}
|
||||||
|
|
||||||
// Sleep.
|
// Sleep.
|
||||||
// NOTE: Nintendo does not check the result of this sleep.
|
// NOTE: Nintendo does not check the result of this sleep.
|
||||||
static_cast<void>(GetCurrentThread(kernel).Sleep(nanoseconds));
|
static_cast<void>(GetCurrentThread(kernel).Sleep(timeout));
|
||||||
} else if (yield_type == Svc::YieldType::WithoutCoreMigration) {
|
} else if (yield_type == Svc::YieldType::WithoutCoreMigration) {
|
||||||
KScheduler::YieldWithoutCoreMigration(kernel);
|
KScheduler::YieldWithoutCoreMigration(kernel);
|
||||||
} else if (yield_type == Svc::YieldType::WithCoreMigration) {
|
} else if (yield_type == Svc::YieldType::WithCoreMigration) {
|
||||||
@ -124,7 +136,6 @@ void SleepThread(Core::System& system, s64 nanoseconds) {
|
|||||||
KScheduler::YieldToAnyThread(kernel);
|
KScheduler::YieldToAnyThread(kernel);
|
||||||
} else {
|
} else {
|
||||||
// Nintendo does nothing at all if an otherwise invalid value is passed.
|
// Nintendo does nothing at all if an otherwise invalid value is passed.
|
||||||
ASSERT_MSG(false, "Unimplemented sleep yield type '{:016X}'!", nanoseconds);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user