summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-02-22 10:27:40 -0400
committerGravatar FernandoS272020-02-22 11:18:07 -0400
commitd219a96cc828d17932beebead209ba696b92a911 (patch)
tree1e973969f39a1901650626699117f93a4d731755
parentKernel: Implement Scheduler locks (diff)
downloadyuzu-d219a96cc828d17932beebead209ba696b92a911.tar.gz
yuzu-d219a96cc828d17932beebead209ba696b92a911.tar.xz
yuzu-d219a96cc828d17932beebead209ba696b92a911.zip
Kernel: Address Feedback.
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/kernel.cpp27
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/kernel/scheduler.cpp21
-rw-r--r--src/core/hle/kernel/scheduler.h8
-rw-r--r--src/core/hle/kernel/time_manager.cpp6
-rw-r--r--src/core/hle/kernel/time_manager.h9
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
423u32 KernelCore::GetCurrentHostThreadId() const { 428u32 KernelCore::GetCurrentHostThreadID() const {
424 return impl->GetCurrentHostThreadId(); 429 return impl->GetCurrentHostThreadID();
425} 430}
426 431
427Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadId() const { 432Core::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
14namespace Core { 13namespace Core {
14struct EmuThreadHandle;
15class ExclusiveMonitor; 15class ExclusiveMonitor;
16class System; 16class 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
360void GlobalScheduler::Lock() { 360void 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
371void GlobalScheduler::Unlock() { 372void 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
383Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) 386Scheduler::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
246class SchedulerLock { 246class SchedulerLock {
247public: 247public:
248 SchedulerLock(KernelCore& kernel); 248 explicit SchedulerLock(KernelCore& kernel);
249 ~SchedulerLock(); 249 ~SchedulerLock();
250 250
251protected: 251protected:
@@ -254,8 +254,8 @@ protected:
254 254
255class SchedulerLockAndSleep : public SchedulerLock { 255class SchedulerLockAndSleep : public SchedulerLock {
256public: 256public:
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
36void TimeManager::UnscheduleTimeEvent(Handle event_handle) { 37void 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
21class Thread; 21class 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 */
23class TimeManager { 27class TimeManager {
24public: 28public:
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
31private: 38private: