Kernel: Address Feedback.
This commit is contained in:
parent
ea956c823e
commit
d219a96cc8
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Reference in New Issue