diff options
| author | 2020-02-22 10:27:40 -0400 | |
|---|---|---|
| committer | 2020-02-22 11:18:07 -0400 | |
| commit | d219a96cc828d17932beebead209ba696b92a911 (patch) | |
| tree | 1e973969f39a1901650626699117f93a4d731755 /src | |
| parent | Kernel: Implement Scheduler locks (diff) | |
| download | yuzu-d219a96cc828d17932beebead209ba696b92a911.tar.gz yuzu-d219a96cc828d17932beebead209ba696b92a911.tar.xz yuzu-d219a96cc828d17932beebead209ba696b92a911.zip | |
Kernel: Address Feedback.
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 27 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 21 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.h | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/time_manager.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/time_manager.h | 9 |
6 files changed, 47 insertions, 30 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index de14e1936..9232f4d7e 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <atomic> | 5 | #include <atomic> |
| 6 | #include <bitset> | ||
| 6 | #include <functional> | 7 | #include <functional> |
| 7 | #include <memory> | 8 | #include <memory> |
| 8 | #include <mutex> | 9 | #include <mutex> |
| @@ -17,6 +18,7 @@ | |||
| 17 | #include "core/core.h" | 18 | #include "core/core.h" |
| 18 | #include "core/core_timing.h" | 19 | #include "core/core_timing.h" |
| 19 | #include "core/core_timing_util.h" | 20 | #include "core/core_timing_util.h" |
| 21 | #include "core/hardware_properties.h" | ||
| 20 | #include "core/hle/kernel/client_port.h" | 22 | #include "core/hle/kernel/client_port.h" |
| 21 | #include "core/hle/kernel/errors.h" | 23 | #include "core/hle/kernel/errors.h" |
| 22 | #include "core/hle/kernel/handle_table.h" | 24 | #include "core/hle/kernel/handle_table.h" |
| @@ -188,6 +190,7 @@ struct KernelCore::Impl { | |||
| 188 | } | 190 | } |
| 189 | 191 | ||
| 190 | void RegisterCoreThread(std::size_t core_id) { | 192 | void RegisterCoreThread(std::size_t core_id) { |
| 193 | std::unique_lock lock{register_thread_mutex}; | ||
| 191 | const std::thread::id this_id = std::this_thread::get_id(); | 194 | const std::thread::id this_id = std::this_thread::get_id(); |
| 192 | const auto it = host_thread_ids.find(this_id); | 195 | const auto it = host_thread_ids.find(this_id); |
| 193 | ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); | 196 | ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); |
| @@ -198,13 +201,14 @@ struct KernelCore::Impl { | |||
| 198 | } | 201 | } |
| 199 | 202 | ||
| 200 | void RegisterHostThread() { | 203 | void RegisterHostThread() { |
| 204 | std::unique_lock lock{register_thread_mutex}; | ||
| 201 | const std::thread::id this_id = std::this_thread::get_id(); | 205 | const std::thread::id this_id = std::this_thread::get_id(); |
| 202 | const auto it = host_thread_ids.find(this_id); | 206 | const auto it = host_thread_ids.find(this_id); |
| 203 | ASSERT(it == host_thread_ids.end()); | 207 | ASSERT(it == host_thread_ids.end()); |
| 204 | host_thread_ids[this_id] = registered_thread_ids++; | 208 | host_thread_ids[this_id] = registered_thread_ids++; |
| 205 | } | 209 | } |
| 206 | 210 | ||
| 207 | u32 GetCurrentHostThreadId() const { | 211 | u32 GetCurrentHostThreadID() const { |
| 208 | const std::thread::id this_id = std::this_thread::get_id(); | 212 | const std::thread::id this_id = std::this_thread::get_id(); |
| 209 | const auto it = host_thread_ids.find(this_id); | 213 | const auto it = host_thread_ids.find(this_id); |
| 210 | if (it == host_thread_ids.end()) { | 214 | if (it == host_thread_ids.end()) { |
| @@ -213,9 +217,9 @@ struct KernelCore::Impl { | |||
| 213 | return it->second; | 217 | return it->second; |
| 214 | } | 218 | } |
| 215 | 219 | ||
| 216 | Core::EmuThreadHandle GetCurrentEmuThreadId() const { | 220 | Core::EmuThreadHandle GetCurrentEmuThreadID() const { |
| 217 | Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle(); | 221 | Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle(); |
| 218 | result.host_handle = GetCurrentHostThreadId(); | 222 | result.host_handle = GetCurrentHostThreadID(); |
| 219 | if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) { | 223 | if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) { |
| 220 | return result; | 224 | return result; |
| 221 | } | 225 | } |
| @@ -246,8 +250,8 @@ struct KernelCore::Impl { | |||
| 246 | std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type; | 250 | std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type; |
| 247 | std::shared_ptr<Core::Timing::EventType> preemption_event; | 251 | std::shared_ptr<Core::Timing::EventType> preemption_event; |
| 248 | 252 | ||
| 249 | // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, | 253 | // This is the kernel's handle table or supervisor handle table which |
| 250 | // allowing us to simply use a pool index or similar. | 254 | // stores all the objects in place. |
| 251 | Kernel::HandleTable global_handle_table; | 255 | Kernel::HandleTable global_handle_table; |
| 252 | 256 | ||
| 253 | /// Map of named ports managed by the kernel, which can be retrieved using | 257 | /// Map of named ports managed by the kernel, which can be retrieved using |
| @@ -257,10 +261,11 @@ struct KernelCore::Impl { | |||
| 257 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | 261 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
| 258 | std::vector<Kernel::PhysicalCore> cores; | 262 | std::vector<Kernel::PhysicalCore> cores; |
| 259 | 263 | ||
| 260 | // 0-3 Ids represent core threads, >3 represent others | 264 | // 0-3 IDs represent core threads, >3 represent others |
| 261 | std::unordered_map<std::thread::id, u32> host_thread_ids; | 265 | std::unordered_map<std::thread::id, u32> host_thread_ids; |
| 262 | u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; | 266 | u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; |
| 263 | std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads{}; | 267 | std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads; |
| 268 | std::mutex register_thread_mutex; | ||
| 264 | 269 | ||
| 265 | // System context | 270 | // System context |
| 266 | Core::System& system; | 271 | Core::System& system; |
| @@ -420,12 +425,12 @@ void KernelCore::RegisterHostThread() { | |||
| 420 | impl->RegisterHostThread(); | 425 | impl->RegisterHostThread(); |
| 421 | } | 426 | } |
| 422 | 427 | ||
| 423 | u32 KernelCore::GetCurrentHostThreadId() const { | 428 | u32 KernelCore::GetCurrentHostThreadID() const { |
| 424 | return impl->GetCurrentHostThreadId(); | 429 | return impl->GetCurrentHostThreadID(); |
| 425 | } | 430 | } |
| 426 | 431 | ||
| 427 | Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadId() const { | 432 | Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadID() const { |
| 428 | return impl->GetCurrentEmuThreadId(); | 433 | return impl->GetCurrentEmuThreadID(); |
| 429 | } | 434 | } |
| 430 | 435 | ||
| 431 | } // namespace Kernel | 436 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 76fd12ace..c4f78ab71 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -8,10 +8,10 @@ | |||
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <unordered_map> | 9 | #include <unordered_map> |
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | #include "core/hardware_properties.h" | ||
| 12 | #include "core/hle/kernel/object.h" | 11 | #include "core/hle/kernel/object.h" |
| 13 | 12 | ||
| 14 | namespace Core { | 13 | namespace Core { |
| 14 | struct EmuThreadHandle; | ||
| 15 | class ExclusiveMonitor; | 15 | class ExclusiveMonitor; |
| 16 | class System; | 16 | class System; |
| 17 | } // namespace Core | 17 | } // namespace Core |
| @@ -136,10 +136,10 @@ public: | |||
| 136 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; | 136 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; |
| 137 | 137 | ||
| 138 | /// Gets the current host_thread/guest_thread handle. | 138 | /// Gets the current host_thread/guest_thread handle. |
| 139 | Core::EmuThreadHandle GetCurrentEmuThreadId() const; | 139 | Core::EmuThreadHandle GetCurrentEmuThreadID() const; |
| 140 | 140 | ||
| 141 | /// Gets the current host_thread handle. | 141 | /// Gets the current host_thread handle. |
| 142 | u32 GetCurrentHostThreadId() const; | 142 | u32 GetCurrentHostThreadID() const; |
| 143 | 143 | ||
| 144 | /// Register the current thread as a CPU Core Thread. | 144 | /// Register the current thread as a CPU Core Thread. |
| 145 | void RegisterCoreThread(std::size_t core_id); | 145 | void RegisterCoreThread(std::size_t core_id); |
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 9556df951..e5892727e 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp | |||
| @@ -358,26 +358,29 @@ void GlobalScheduler::Shutdown() { | |||
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | void GlobalScheduler::Lock() { | 360 | void GlobalScheduler::Lock() { |
| 361 | Core::EmuThreadHandle current_thread = kernel.GetCurrentEmuThreadId(); | 361 | Core::EmuThreadHandle current_thread = kernel.GetCurrentEmuThreadID(); |
| 362 | if (current_thread == current_owner) { | 362 | if (current_thread == current_owner) { |
| 363 | ++scope_lock; | 363 | ++scope_lock; |
| 364 | } else { | 364 | } else { |
| 365 | inner_lock.lock(); | 365 | inner_lock.lock(); |
| 366 | current_owner = current_thread; | 366 | current_owner = current_thread; |
| 367 | ASSERT(current_owner != Core::EmuThreadHandle::InvalidHandle()); | ||
| 367 | scope_lock = 1; | 368 | scope_lock = 1; |
| 368 | } | 369 | } |
| 369 | } | 370 | } |
| 370 | 371 | ||
| 371 | void GlobalScheduler::Unlock() { | 372 | void GlobalScheduler::Unlock() { |
| 372 | if (--scope_lock == 0) { | 373 | if (--scope_lock != 0) { |
| 373 | for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { | 374 | ASSERT(scope_lock > 0); |
| 374 | SelectThread(i); | 375 | return; |
| 375 | } | 376 | } |
| 376 | current_owner = Core::EmuThreadHandle::InvalidHandle(); | 377 | for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { |
| 377 | scope_lock = 1; | 378 | SelectThread(i); |
| 378 | inner_lock.unlock(); | ||
| 379 | // TODO(Blinkhawk): Setup the interrupts and change context on current core. | ||
| 380 | } | 379 | } |
| 380 | current_owner = Core::EmuThreadHandle::InvalidHandle(); | ||
| 381 | scope_lock = 1; | ||
| 382 | inner_lock.unlock(); | ||
| 383 | // TODO(Blinkhawk): Setup the interrupts and change context on current core. | ||
| 381 | } | 384 | } |
| 382 | 385 | ||
| 383 | Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) | 386 | Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) |
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index a779bb70f..1c93a838c 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h | |||
| @@ -171,7 +171,7 @@ private: | |||
| 171 | 171 | ||
| 172 | /// Scheduler lock mechanisms. | 172 | /// Scheduler lock mechanisms. |
| 173 | std::mutex inner_lock{}; // TODO(Blinkhawk): Replace for a SpinLock | 173 | std::mutex inner_lock{}; // TODO(Blinkhawk): Replace for a SpinLock |
| 174 | std::atomic<std::size_t> scope_lock{}; | 174 | std::atomic<s64> scope_lock{}; |
| 175 | Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()}; | 175 | Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()}; |
| 176 | 176 | ||
| 177 | /// Lists all thread ids that aren't deleted/etc. | 177 | /// Lists all thread ids that aren't deleted/etc. |
| @@ -245,7 +245,7 @@ private: | |||
| 245 | 245 | ||
| 246 | class SchedulerLock { | 246 | class SchedulerLock { |
| 247 | public: | 247 | public: |
| 248 | SchedulerLock(KernelCore& kernel); | 248 | explicit SchedulerLock(KernelCore& kernel); |
| 249 | ~SchedulerLock(); | 249 | ~SchedulerLock(); |
| 250 | 250 | ||
| 251 | protected: | 251 | protected: |
| @@ -254,8 +254,8 @@ protected: | |||
| 254 | 254 | ||
| 255 | class SchedulerLockAndSleep : public SchedulerLock { | 255 | class SchedulerLockAndSleep : public SchedulerLock { |
| 256 | public: | 256 | public: |
| 257 | SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, Thread* time_task, | 257 | explicit SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, Thread* time_task, |
| 258 | s64 nanoseconds); | 258 | s64 nanoseconds); |
| 259 | ~SchedulerLockAndSleep(); | 259 | ~SchedulerLockAndSleep(); |
| 260 | 260 | ||
| 261 | void CancelSleep() { | 261 | void CancelSleep() { |
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index 0b3e464d0..21b290468 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/assert.h" | ||
| 5 | #include "core/core.h" | 6 | #include "core/core.h" |
| 6 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| 7 | #include "core/core_timing_util.h" | 8 | #include "core/core_timing_util.h" |
| @@ -34,9 +35,10 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 | |||
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | void TimeManager::UnscheduleTimeEvent(Handle event_handle) { | 37 | void TimeManager::UnscheduleTimeEvent(Handle event_handle) { |
| 37 | if (event_handle != InvalidHandle) { | 38 | if (event_handle == InvalidHandle) { |
| 38 | system.CoreTiming().UnscheduleEvent(time_manager_event_type, event_handle); | 39 | return; |
| 39 | } | 40 | } |
| 41 | system.CoreTiming().UnscheduleEvent(time_manager_event_type, event_handle); | ||
| 40 | } | 42 | } |
| 41 | 43 | ||
| 42 | } // namespace Kernel | 44 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/time_manager.h b/src/core/hle/kernel/time_manager.h index b760311f1..eaec486d1 100644 --- a/src/core/hle/kernel/time_manager.h +++ b/src/core/hle/kernel/time_manager.h | |||
| @@ -20,12 +20,19 @@ namespace Kernel { | |||
| 20 | 20 | ||
| 21 | class Thread; | 21 | class Thread; |
| 22 | 22 | ||
| 23 | /** | ||
| 24 | * The `TimeManager` takes care of scheduling time events on threads and executes their TimeUp | ||
| 25 | * method when the event is triggered. | ||
| 26 | */ | ||
| 23 | class TimeManager { | 27 | class TimeManager { |
| 24 | public: | 28 | public: |
| 25 | TimeManager(Core::System& system); | 29 | explicit TimeManager(Core::System& system); |
| 26 | 30 | ||
| 31 | /// Schedule a time event on `timetask` thread that will expire in 'nanoseconds' | ||
| 32 | /// returns a non-invalid handle in `event_handle` if correctly scheduled | ||
| 27 | void ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 nanoseconds); | 33 | void ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 nanoseconds); |
| 28 | 34 | ||
| 35 | /// Unschedule an existing time event | ||
| 29 | void UnscheduleTimeEvent(Handle event_handle); | 36 | void UnscheduleTimeEvent(Handle event_handle); |
| 30 | 37 | ||
| 31 | private: | 38 | private: |