yuzu-emu
/
yuzu
Archived
1
0
Fork 0

Kernel: Address Feedback.

This commit is contained in:
Fernando Sahmkow 2020-02-22 10:27:40 -04:00 committed by FernandoS27
parent ea956c823e
commit d219a96cc8
6 changed files with 47 additions and 30 deletions

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <atomic> #include <atomic>
#include <bitset>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
@ -17,6 +18,7 @@
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/core_timing_util.h" #include "core/core_timing_util.h"
#include "core/hardware_properties.h"
#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/errors.h" #include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
@ -188,6 +190,7 @@ struct KernelCore::Impl {
} }
void RegisterCoreThread(std::size_t core_id) { void RegisterCoreThread(std::size_t core_id) {
std::unique_lock lock{register_thread_mutex};
const std::thread::id this_id = std::this_thread::get_id(); const std::thread::id this_id = std::this_thread::get_id();
const auto it = host_thread_ids.find(this_id); const auto it = host_thread_ids.find(this_id);
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
@ -198,13 +201,14 @@ struct KernelCore::Impl {
} }
void RegisterHostThread() { void RegisterHostThread() {
std::unique_lock lock{register_thread_mutex};
const std::thread::id this_id = std::this_thread::get_id(); const std::thread::id this_id = std::this_thread::get_id();
const auto it = host_thread_ids.find(this_id); const auto it = host_thread_ids.find(this_id);
ASSERT(it == host_thread_ids.end()); ASSERT(it == host_thread_ids.end());
host_thread_ids[this_id] = registered_thread_ids++; host_thread_ids[this_id] = registered_thread_ids++;
} }
u32 GetCurrentHostThreadId() const { u32 GetCurrentHostThreadID() const {
const std::thread::id this_id = std::this_thread::get_id(); const std::thread::id this_id = std::this_thread::get_id();
const auto it = host_thread_ids.find(this_id); const auto it = host_thread_ids.find(this_id);
if (it == host_thread_ids.end()) { if (it == host_thread_ids.end()) {
@ -213,9 +217,9 @@ struct KernelCore::Impl {
return it->second; return it->second;
} }
Core::EmuThreadHandle GetCurrentEmuThreadId() const { Core::EmuThreadHandle GetCurrentEmuThreadID() const {
Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle(); Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
result.host_handle = GetCurrentHostThreadId(); result.host_handle = GetCurrentHostThreadID();
if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) { if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) {
return result; return result;
} }
@ -246,8 +250,8 @@ struct KernelCore::Impl {
std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type; std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type;
std::shared_ptr<Core::Timing::EventType> preemption_event; std::shared_ptr<Core::Timing::EventType> preemption_event;
// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, // This is the kernel's handle table or supervisor handle table which
// allowing us to simply use a pool index or similar. // stores all the objects in place.
Kernel::HandleTable global_handle_table; Kernel::HandleTable global_handle_table;
/// Map of named ports managed by the kernel, which can be retrieved using /// Map of named ports managed by the kernel, which can be retrieved using
@ -257,10 +261,11 @@ struct KernelCore::Impl {
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
std::vector<Kernel::PhysicalCore> cores; std::vector<Kernel::PhysicalCore> cores;
// 0-3 Ids represent core threads, >3 represent others // 0-3 IDs represent core threads, >3 represent others
std::unordered_map<std::thread::id, u32> host_thread_ids; std::unordered_map<std::thread::id, u32> host_thread_ids;
u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES};
std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads{}; std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads;
std::mutex register_thread_mutex;
// System context // System context
Core::System& system; Core::System& system;
@ -420,12 +425,12 @@ void KernelCore::RegisterHostThread() {
impl->RegisterHostThread(); impl->RegisterHostThread();
} }
u32 KernelCore::GetCurrentHostThreadId() const { u32 KernelCore::GetCurrentHostThreadID() const {
return impl->GetCurrentHostThreadId(); return impl->GetCurrentHostThreadID();
} }
Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadId() const { Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadID() const {
return impl->GetCurrentEmuThreadId(); return impl->GetCurrentEmuThreadID();
} }
} // namespace Kernel } // namespace Kernel

View File

@ -8,10 +8,10 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "core/hardware_properties.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
namespace Core { namespace Core {
struct EmuThreadHandle;
class ExclusiveMonitor; class ExclusiveMonitor;
class System; class System;
} // namespace Core } // namespace Core
@ -136,10 +136,10 @@ public:
bool IsValidNamedPort(NamedPortTable::const_iterator port) const; bool IsValidNamedPort(NamedPortTable::const_iterator port) const;
/// Gets the current host_thread/guest_thread handle. /// Gets the current host_thread/guest_thread handle.
Core::EmuThreadHandle GetCurrentEmuThreadId() const; Core::EmuThreadHandle GetCurrentEmuThreadID() const;
/// Gets the current host_thread handle. /// Gets the current host_thread handle.
u32 GetCurrentHostThreadId() const; u32 GetCurrentHostThreadID() const;
/// Register the current thread as a CPU Core Thread. /// Register the current thread as a CPU Core Thread.
void RegisterCoreThread(std::size_t core_id); void RegisterCoreThread(std::size_t core_id);

View File

@ -358,18 +358,22 @@ void GlobalScheduler::Shutdown() {
} }
void GlobalScheduler::Lock() { void GlobalScheduler::Lock() {
Core::EmuThreadHandle current_thread = kernel.GetCurrentEmuThreadId(); Core::EmuThreadHandle current_thread = kernel.GetCurrentEmuThreadID();
if (current_thread == current_owner) { if (current_thread == current_owner) {
++scope_lock; ++scope_lock;
} else { } else {
inner_lock.lock(); inner_lock.lock();
current_owner = current_thread; current_owner = current_thread;
ASSERT(current_owner != Core::EmuThreadHandle::InvalidHandle());
scope_lock = 1; scope_lock = 1;
} }
} }
void GlobalScheduler::Unlock() { void GlobalScheduler::Unlock() {
if (--scope_lock == 0) { if (--scope_lock != 0) {
ASSERT(scope_lock > 0);
return;
}
for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
SelectThread(i); SelectThread(i);
} }
@ -377,7 +381,6 @@ void GlobalScheduler::Unlock() {
scope_lock = 1; scope_lock = 1;
inner_lock.unlock(); inner_lock.unlock();
// TODO(Blinkhawk): Setup the interrupts and change context on current core. // TODO(Blinkhawk): Setup the interrupts and change context on current core.
}
} }
Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id)

View File

@ -171,7 +171,7 @@ private:
/// Scheduler lock mechanisms. /// Scheduler lock mechanisms.
std::mutex inner_lock{}; // TODO(Blinkhawk): Replace for a SpinLock std::mutex inner_lock{}; // TODO(Blinkhawk): Replace for a SpinLock
std::atomic<std::size_t> scope_lock{}; std::atomic<s64> scope_lock{};
Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()}; Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()};
/// Lists all thread ids that aren't deleted/etc. /// Lists all thread ids that aren't deleted/etc.
@ -245,7 +245,7 @@ private:
class SchedulerLock { class SchedulerLock {
public: public:
SchedulerLock(KernelCore& kernel); explicit SchedulerLock(KernelCore& kernel);
~SchedulerLock(); ~SchedulerLock();
protected: protected:
@ -254,7 +254,7 @@ protected:
class SchedulerLockAndSleep : public SchedulerLock { class SchedulerLockAndSleep : public SchedulerLock {
public: public:
SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, Thread* time_task, explicit SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, Thread* time_task,
s64 nanoseconds); s64 nanoseconds);
~SchedulerLockAndSleep(); ~SchedulerLockAndSleep();

View File

@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common/assert.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/core_timing_util.h" #include "core/core_timing_util.h"
@ -34,9 +35,10 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64
} }
void TimeManager::UnscheduleTimeEvent(Handle event_handle) { void TimeManager::UnscheduleTimeEvent(Handle event_handle) {
if (event_handle != InvalidHandle) { if (event_handle == InvalidHandle) {
system.CoreTiming().UnscheduleEvent(time_manager_event_type, event_handle); return;
} }
system.CoreTiming().UnscheduleEvent(time_manager_event_type, event_handle);
} }
} // namespace Kernel } // namespace Kernel

View File

@ -20,12 +20,19 @@ namespace Kernel {
class Thread; class Thread;
/**
* The `TimeManager` takes care of scheduling time events on threads and executes their TimeUp
* method when the event is triggered.
*/
class TimeManager { class TimeManager {
public: public:
TimeManager(Core::System& system); explicit TimeManager(Core::System& system);
/// Schedule a time event on `timetask` thread that will expire in 'nanoseconds'
/// returns a non-invalid handle in `event_handle` if correctly scheduled
void ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 nanoseconds); void ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 nanoseconds);
/// Unschedule an existing time event
void UnscheduleTimeEvent(Handle event_handle); void UnscheduleTimeEvent(Handle event_handle);
private: private: