Core: Address Feedback
This commit is contained in:
parent
1e6f8aba04
commit
2bc949628d
|
@ -8,14 +8,6 @@
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
union EmuThreadHandle {
|
|
||||||
u64 raw;
|
|
||||||
struct {
|
|
||||||
u32 host_handle;
|
|
||||||
u32 guest_handle;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Hardware {
|
namespace Hardware {
|
||||||
|
|
||||||
// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
|
// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
|
||||||
|
@ -23,6 +15,29 @@ namespace Hardware {
|
||||||
constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch cpu frequency is 1020MHz un/docked
|
constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch cpu frequency is 1020MHz un/docked
|
||||||
constexpr u64 CNTFREQ = 19200000; // Switch's hardware clock speed
|
constexpr u64 CNTFREQ = 19200000; // Switch's hardware clock speed
|
||||||
constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
|
constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
|
||||||
|
|
||||||
} // namespace Hardware
|
} // namespace Hardware
|
||||||
|
|
||||||
|
struct EmuThreadHandle {
|
||||||
|
u32 host_handle;
|
||||||
|
u32 guest_handle;
|
||||||
|
|
||||||
|
u64 GetRaw() const {
|
||||||
|
return (static_cast<u64>(host_handle) << 32) | guest_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const EmuThreadHandle& rhs) const {
|
||||||
|
return std::tie(host_handle, guest_handle) == std::tie(rhs.host_handle, rhs.guest_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const EmuThreadHandle& rhs) const {
|
||||||
|
return !operator==(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr EmuThreadHandle InvalidHandle() {
|
||||||
|
constexpr u32 invalid_handle = 0xFFFFFFFF;
|
||||||
|
return {invalid_handle, invalid_handle};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
|
@ -125,7 +125,7 @@ bool GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) {
|
||||||
scheduled_queue[core_id].yield(priority);
|
scheduled_queue[core_id].yield(priority);
|
||||||
|
|
||||||
std::array<Thread*, Core::Hardware::NUM_CPU_CORES> current_threads;
|
std::array<Thread*, Core::Hardware::NUM_CPU_CORES> current_threads;
|
||||||
for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
|
for (std::size_t i = 0; i < current_threads.size(); i++) {
|
||||||
current_threads[i] = scheduled_queue[i].empty() ? nullptr : scheduled_queue[i].front();
|
current_threads[i] = scheduled_queue[i].empty() ? nullptr : scheduled_queue[i].front();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread
|
||||||
if (scheduled_queue[core_id].empty()) {
|
if (scheduled_queue[core_id].empty()) {
|
||||||
// Here, "current_threads" is calculated after the ""yield"", unlike yield -1
|
// Here, "current_threads" is calculated after the ""yield"", unlike yield -1
|
||||||
std::array<Thread*, Core::Hardware::NUM_CPU_CORES> current_threads;
|
std::array<Thread*, Core::Hardware::NUM_CPU_CORES> current_threads;
|
||||||
for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
|
for (std::size_t i = 0; i < current_threads.size(); i++) {
|
||||||
current_threads[i] = scheduled_queue[i].empty() ? nullptr : scheduled_queue[i].front();
|
current_threads[i] = scheduled_queue[i].empty() ? nullptr : scheduled_queue[i].front();
|
||||||
}
|
}
|
||||||
for (auto& thread : suggested_queue[core_id]) {
|
for (auto& thread : suggested_queue[core_id]) {
|
||||||
|
|
|
@ -57,7 +57,7 @@ bool ServerSession::IsSignaled() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait if we have no pending requests, or if we're currently handling a request.
|
// Wait if we have no pending requests, or if we're currently handling a request.
|
||||||
return !(pending_requesting_threads.empty() || currently_handling != nullptr);
|
return !pending_requesting_threads.empty() && currently_handling == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerSession::Acquire(Thread* thread) {
|
void ServerSession::Acquire(Thread* thread) {
|
||||||
|
|
|
@ -474,7 +474,7 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
|
||||||
objects[i] = object;
|
objects[i] = object;
|
||||||
}
|
}
|
||||||
auto& synchronization = kernel.Synchronization();
|
auto& synchronization = kernel.Synchronization();
|
||||||
auto [result, handle_result] = synchronization.WaitFor(objects, nano_seconds);
|
const auto [result, handle_result] = synchronization.WaitFor(objects, nano_seconds);
|
||||||
*index = handle_result;
|
*index = handle_result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
#include "core/hle/kernel/errors.h"
|
||||||
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/scheduler.h"
|
#include "core/hle/kernel/scheduler.h"
|
||||||
#include "core/hle/kernel/synchronization.h"
|
#include "core/hle/kernel/synchronization.h"
|
||||||
|
@ -27,30 +28,30 @@ static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, std::shared_p
|
||||||
thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
|
thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
|
||||||
thread->SetWaitSynchronizationOutput(static_cast<u32>(index));
|
thread->SetWaitSynchronizationOutput(static_cast<u32>(index));
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
Synchronization::Synchronization(Core::System& system) : system{system} {}
|
Synchronization::Synchronization(Core::System& system) : system{system} {}
|
||||||
|
|
||||||
void Synchronization::SignalObject(SynchronizationObject& obj) const {
|
void Synchronization::SignalObject(SynchronizationObject& obj) const {
|
||||||
if (obj.IsSignaled()) {
|
if (obj.IsSignaled()) {
|
||||||
obj.WakeupAllWaitingThreads();
|
obj.WakeupAllWaitingThreads();
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<ResultCode, Handle> Synchronization::WaitFor(
|
std::pair<ResultCode, Handle> Synchronization::WaitFor(
|
||||||
std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds) {
|
std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds) {
|
||||||
auto* const thread = system.CurrentScheduler().GetCurrentThread();
|
auto* const thread = system.CurrentScheduler().GetCurrentThread();
|
||||||
// Find the first object that is acquirable in the provided list of objects
|
// Find the first object that is acquirable in the provided list of objects
|
||||||
auto itr = std::find_if(sync_objects.begin(), sync_objects.end(),
|
const auto itr = std::find_if(sync_objects.begin(), sync_objects.end(),
|
||||||
[thread](const std::shared_ptr<SynchronizationObject>& object) {
|
[thread](const std::shared_ptr<SynchronizationObject>& object) {
|
||||||
return object->IsSignaled();
|
return object->IsSignaled();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (itr != sync_objects.end()) {
|
if (itr != sync_objects.end()) {
|
||||||
// We found a ready object, acquire it and set the result value
|
// We found a ready object, acquire it and set the result value
|
||||||
SynchronizationObject* object = itr->get();
|
SynchronizationObject* object = itr->get();
|
||||||
object->Acquire(thread);
|
object->Acquire(thread);
|
||||||
u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr));
|
const u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr));
|
||||||
return {RESULT_SUCCESS, index};
|
return {RESULT_SUCCESS, index};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,12 +60,12 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor(
|
||||||
// If a timeout value of 0 was provided, just return the Timeout error code instead of
|
// If a timeout value of 0 was provided, just return the Timeout error code instead of
|
||||||
// suspending the thread.
|
// suspending the thread.
|
||||||
if (nano_seconds == 0) {
|
if (nano_seconds == 0) {
|
||||||
return {RESULT_TIMEOUT, 0};
|
return {RESULT_TIMEOUT, InvalidHandle};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread->IsSyncCancelled()) {
|
if (thread->IsSyncCancelled()) {
|
||||||
thread->SetSyncCancelled(false);
|
thread->SetSyncCancelled(false);
|
||||||
return {ERR_SYNCHRONIZATION_CANCELED, 0};
|
return {ERR_SYNCHRONIZATION_CANCELED, InvalidHandle};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& object : sync_objects) {
|
for (auto& object : sync_objects) {
|
||||||
|
@ -80,7 +81,7 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor(
|
||||||
|
|
||||||
system.PrepareReschedule(thread->GetProcessorID());
|
system.PrepareReschedule(thread->GetProcessorID());
|
||||||
|
|
||||||
return {RESULT_TIMEOUT, 0};
|
return {RESULT_TIMEOUT, InvalidHandle};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "core/hle/kernel/object.h"
|
#include "core/hle/kernel/object.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
@ -16,15 +17,24 @@ class System;
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
class KernelCore;
|
|
||||||
class SynchronizationObject;
|
class SynchronizationObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The 'Synchronization' class is an interface for handling synchronization methods
|
||||||
|
* used by Synchronization objects and synchronization SVCs. This centralizes processing of
|
||||||
|
* such
|
||||||
|
*/
|
||||||
class Synchronization {
|
class Synchronization {
|
||||||
public:
|
public:
|
||||||
Synchronization(Core::System& system);
|
explicit Synchronization(Core::System& system);
|
||||||
|
|
||||||
|
/// Signals a synchronization object, waking up all its waiting threads
|
||||||
void SignalObject(SynchronizationObject& obj) const;
|
void SignalObject(SynchronizationObject& obj) const;
|
||||||
|
|
||||||
|
/// Tries to see if waiting for any of the sync_objects is necessary, if not
|
||||||
|
/// it returns Success and the handle index of the signaled sync object. In
|
||||||
|
/// case not, the current thread will be locked and wait for nano_seconds or
|
||||||
|
/// for a synchronization object to signal.
|
||||||
std::pair<ResultCode, Handle> WaitFor(
|
std::pair<ResultCode, Handle> WaitFor(
|
||||||
std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds);
|
std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds);
|
||||||
|
|
||||||
|
|
Reference in New Issue