summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-02-25 19:43:28 -0400
committerGravatar Fernando Sahmkow2020-06-27 11:35:14 -0400
commit15a79eb0d7abe752a9a55d0cfa7ea220e17318b7 (patch)
tree863357ab4be1ff9a72804c40455d6a4c4c493acd /src
parentSVC: Correct ArbitrateUnlock (diff)
downloadyuzu-15a79eb0d7abe752a9a55d0cfa7ea220e17318b7.tar.gz
yuzu-15a79eb0d7abe752a9a55d0cfa7ea220e17318b7.tar.xz
yuzu-15a79eb0d7abe752a9a55d0cfa7ea220e17318b7.zip
SVC: Correct SendSyncRequest.
Diffstat (limited to 'src')
-rw-r--r--src/core/cpu_manager.cpp3
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp24
-rw-r--r--src/core/hle/kernel/scheduler.cpp9
-rw-r--r--src/core/hle/kernel/scheduler.h2
-rw-r--r--src/core/hle/kernel/server_session.cpp15
-rw-r--r--src/core/hle/kernel/svc.cpp21
-rw-r--r--src/core/hle/kernel/thread.cpp14
-rw-r--r--src/core/hle/kernel/thread.h82
8 files changed, 116 insertions, 54 deletions
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index 9b9337131..6032cb0bf 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -81,8 +81,7 @@ void CpuManager::RunGuestThread() {
81 while (true) { 81 while (true) {
82 auto& physical_core = kernel.CurrentPhysicalCore(); 82 auto& physical_core = kernel.CurrentPhysicalCore();
83 if (!physical_core.IsInterrupted()) { 83 if (!physical_core.IsInterrupted()) {
84 physical_core.Idle(); 84 physical_core.Run();
85 // physical_core.Run();
86 } 85 }
87 auto& scheduler = physical_core.Scheduler(); 86 auto& scheduler = physical_core.Scheduler();
88 scheduler.TryDoContextSwitch(); 87 scheduler.TryDoContextSwitch();
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 0d01a7047..955d5fe1c 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -14,6 +14,7 @@
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "core/hle/ipc_helpers.h" 16#include "core/hle/ipc_helpers.h"
17#include "core/hle/kernel/errors.h"
17#include "core/hle/kernel/handle_table.h" 18#include "core/hle/kernel/handle_table.h"
18#include "core/hle/kernel/hle_ipc.h" 19#include "core/hle/kernel/hle_ipc.h"
19#include "core/hle/kernel/kernel.h" 20#include "core/hle/kernel/kernel.h"
@@ -21,7 +22,9 @@
21#include "core/hle/kernel/process.h" 22#include "core/hle/kernel/process.h"
22#include "core/hle/kernel/readable_event.h" 23#include "core/hle/kernel/readable_event.h"
23#include "core/hle/kernel/server_session.h" 24#include "core/hle/kernel/server_session.h"
25#include "core/hle/kernel/scheduler.h"
24#include "core/hle/kernel/thread.h" 26#include "core/hle/kernel/thread.h"
27#include "core/hle/kernel/time_manager.h"
25#include "core/hle/kernel/writable_event.h" 28#include "core/hle/kernel/writable_event.h"
26#include "core/memory.h" 29#include "core/memory.h"
27 30
@@ -46,11 +49,10 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
46 const std::string& reason, u64 timeout, WakeupCallback&& callback, 49 const std::string& reason, u64 timeout, WakeupCallback&& callback,
47 std::shared_ptr<WritableEvent> writable_event) { 50 std::shared_ptr<WritableEvent> writable_event) {
48 // Put the client thread to sleep until the wait event is signaled or the timeout expires. 51 // Put the client thread to sleep until the wait event is signaled or the timeout expires.
49 thread->SetWakeupCallback( 52 thread->SetHLECallback(
50 [context = *this, callback](ThreadWakeupReason reason, std::shared_ptr<Thread> thread, 53 [context = *this, callback](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
51 std::shared_ptr<SynchronizationObject> object, 54 std::shared_ptr<SynchronizationObject> object,
52 std::size_t index) mutable -> bool { 55 std::size_t index) mutable -> bool {
53 ASSERT(thread->GetStatus() == ThreadStatus::WaitHLEEvent);
54 callback(thread, context, reason); 56 callback(thread, context, reason);
55 context.WriteToOutgoingCommandBuffer(*thread); 57 context.WriteToOutgoingCommandBuffer(*thread);
56 return true; 58 return true;
@@ -62,14 +64,16 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
62 writable_event = pair.writable; 64 writable_event = pair.writable;
63 } 65 }
64 66
65 const auto readable_event{writable_event->GetReadableEvent()}; 67 {
66 writable_event->Clear(); 68 Handle event_handle = InvalidHandle;
67 thread->SetStatus(ThreadStatus::WaitHLEEvent); 69 SchedulerLockAndSleep lock(kernel, event_handle, thread.get(), timeout);
68 thread->SetSynchronizationObjects({readable_event}); 70 const auto readable_event{writable_event->GetReadableEvent()};
69 readable_event->AddWaitingThread(thread); 71 writable_event->Clear();
70 72 thread->SetStatus(ThreadStatus::WaitHLEEvent);
71 if (timeout > 0) { 73 thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
72 thread->WakeAfterDelay(timeout); 74 readable_event->AddWaitingThread(thread);
75 lock.Release();
76 thread->SetHLETimeEvent(event_handle);
73 } 77 }
74 78
75 is_thread_waiting = true; 79 is_thread_waiting = true;
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index 5166020a0..0e85ee69e 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -715,4 +715,13 @@ SchedulerLockAndSleep::~SchedulerLockAndSleep() {
715 time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds); 715 time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds);
716} 716}
717 717
718void SchedulerLockAndSleep::Release() {
719 if (sleep_cancelled) {
720 return;
721 }
722 auto& time_manager = kernel.TimeManager();
723 time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds);
724 sleep_cancelled = true;
725}
726
718} // namespace Kernel 727} // namespace Kernel
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h
index 16655b03f..f5f64338f 100644
--- a/src/core/hle/kernel/scheduler.h
+++ b/src/core/hle/kernel/scheduler.h
@@ -279,6 +279,8 @@ public:
279 sleep_cancelled = true; 279 sleep_cancelled = true;
280 } 280 }
281 281
282 void Release();
283
282private: 284private:
283 Handle& event_handle; 285 Handle& event_handle;
284 Thread* time_task; 286 Thread* time_task;
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 25438b86b..05516a453 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -19,6 +19,7 @@
19#include "core/hle/kernel/process.h" 19#include "core/hle/kernel/process.h"
20#include "core/hle/kernel/server_session.h" 20#include "core/hle/kernel/server_session.h"
21#include "core/hle/kernel/session.h" 21#include "core/hle/kernel/session.h"
22#include "core/hle/kernel/scheduler.h"
22#include "core/hle/kernel/thread.h" 23#include "core/hle/kernel/thread.h"
23#include "core/memory.h" 24#include "core/memory.h"
24 25
@@ -168,9 +169,12 @@ ResultCode ServerSession::CompleteSyncRequest() {
168 } 169 }
169 170
170 // Some service requests require the thread to block 171 // Some service requests require the thread to block
171 if (!context.IsThreadWaiting()) { 172 {
172 context.GetThread().ResumeFromWait(); 173 SchedulerLock lock(kernel);
173 context.GetThread().SetWaitSynchronizationResult(result); 174 if (!context.IsThreadWaiting()) {
175 context.GetThread().ResumeFromWait();
176 context.GetThread().SetSynchronizationResults(nullptr, result);
177 }
174 } 178 }
175 179
176 request_queue.Pop(); 180 request_queue.Pop();
@@ -180,8 +184,9 @@ ResultCode ServerSession::CompleteSyncRequest() {
180 184
181ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread, 185ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,
182 Core::Memory::Memory& memory) { 186 Core::Memory::Memory& memory) {
183 Core::System::GetInstance().CoreTiming().ScheduleEvent(20000, request_event, {}); 187 ResultCode result = QueueSyncRequest(std::move(thread), memory);
184 return QueueSyncRequest(std::move(thread), memory); 188 Core::System::GetInstance().CoreTiming().ScheduleEvent(0, request_event, {});
189 return result;
185} 190}
186 191
187} // namespace Kernel 192} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 0d905c0ca..768d72b92 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -38,6 +38,7 @@
38#include "core/hle/kernel/svc_wrap.h" 38#include "core/hle/kernel/svc_wrap.h"
39#include "core/hle/kernel/synchronization.h" 39#include "core/hle/kernel/synchronization.h"
40#include "core/hle/kernel/thread.h" 40#include "core/hle/kernel/thread.h"
41#include "core/hle/kernel/time_manager.h"
41#include "core/hle/kernel/transfer_memory.h" 42#include "core/hle/kernel/transfer_memory.h"
42#include "core/hle/kernel/writable_event.h" 43#include "core/hle/kernel/writable_event.h"
43#include "core/hle/lock.h" 44#include "core/hle/lock.h"
@@ -318,11 +319,23 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
318 LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); 319 LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
319 320
320 auto thread = system.CurrentScheduler().GetCurrentThread(); 321 auto thread = system.CurrentScheduler().GetCurrentThread();
321 thread->InvalidateWakeupCallback(); 322 {
322 thread->SetStatus(ThreadStatus::WaitIPC); 323 SchedulerLock lock(system.Kernel());
323 system.PrepareReschedule(thread->GetProcessorID()); 324 thread->InvalidateHLECallback();
325 thread->SetStatus(ThreadStatus::WaitIPC);
326 session->SendSyncRequest(SharedFrom(thread), system.Memory());
327 }
328 ResultCode result = thread->GetSignalingResult();
329 if (thread->HasHLECallback()) {
330 Handle event_handle = thread->GetHLETimeEvent();
331 if (event_handle != InvalidHandle) {
332 auto& time_manager = system.Kernel().TimeManager();
333 time_manager.UnscheduleTimeEvent(event_handle);
334 }
335 thread->InvokeHLECallback(ThreadWakeupReason::Timeout, SharedFrom(thread), nullptr, 0);
336 }
324 337
325 return session->SendSyncRequest(SharedFrom(thread), system.Memory()); 338 return result;
326} 339}
327 340
328static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { 341static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f100ffc70..fb97535a3 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -96,7 +96,7 @@ void Thread::ResumeFromWait() {
96 case ThreadStatus::Ready: 96 case ThreadStatus::Ready:
97 // The thread's wakeup callback must have already been cleared when the thread was first 97 // The thread's wakeup callback must have already been cleared when the thread was first
98 // awoken. 98 // awoken.
99 ASSERT(wakeup_callback == nullptr); 99 ASSERT(hle_callback == nullptr);
100 // If the thread is waiting on multiple wait objects, it might be awoken more than once 100 // If the thread is waiting on multiple wait objects, it might be awoken more than once
101 // before actually resuming. We can ignore subsequent wakeups if the thread status has 101 // before actually resuming. We can ignore subsequent wakeups if the thread status has
102 // already been set to ThreadStatus::Ready. 102 // already been set to ThreadStatus::Ready.
@@ -112,7 +112,7 @@ void Thread::ResumeFromWait() {
112 return; 112 return;
113 } 113 }
114 114
115 wakeup_callback = nullptr; 115 hle_callback = nullptr;
116 116
117 if (activity == ThreadActivity::Paused) { 117 if (activity == ThreadActivity::Paused) {
118 SetStatus(ThreadStatus::Paused); 118 SetStatus(ThreadStatus::Paused);
@@ -398,8 +398,14 @@ bool Thread::AllSynchronizationObjectsReady() const {
398bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, 398bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
399 std::shared_ptr<SynchronizationObject> object, 399 std::shared_ptr<SynchronizationObject> object,
400 std::size_t index) { 400 std::size_t index) {
401 ASSERT(wakeup_callback); 401 ASSERT(hle_callback);
402 return wakeup_callback(reason, std::move(thread), std::move(object), index); 402 return hle_callback(reason, std::move(thread), std::move(object), index);
403}
404
405bool Thread::InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
406 std::shared_ptr<SynchronizationObject> object, std::size_t index) {
407 ASSERT(hle_callback);
408 return hle_callback(reason, std::move(thread), std::move(object), index);
403} 409}
404 410
405void Thread::SetActivity(ThreadActivity value) { 411void Thread::SetActivity(ThreadActivity value) {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index a8ae1a66f..04496f96e 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -31,12 +31,12 @@ class Process;
31class Scheduler; 31class Scheduler;
32 32
33enum ThreadPriority : u32 { 33enum ThreadPriority : u32 {
34 THREADPRIO_HIGHEST = 0, ///< Highest thread priority 34 THREADPRIO_HIGHEST = 0, ///< Highest thread priority
35 THREADPRIO_MAX_CORE_MIGRATION = 2, ///< Highest priority for a core migration 35 THREADPRIO_MAX_CORE_MIGRATION = 2, ///< Highest priority for a core migration
36 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps 36 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps
37 THREADPRIO_DEFAULT = 44, ///< Default thread priority for userland apps 37 THREADPRIO_DEFAULT = 44, ///< Default thread priority for userland apps
38 THREADPRIO_LOWEST = 63, ///< Lowest thread priority 38 THREADPRIO_LOWEST = 63, ///< Lowest thread priority
39 THREADPRIO_COUNT = 64, ///< Total number of possible thread priorities. 39 THREADPRIO_COUNT = 64, ///< Total number of possible thread priorities.
40}; 40};
41 41
42enum ThreadType : u32 { 42enum ThreadType : u32 {
@@ -129,23 +129,24 @@ public:
129 using WakeupCallback = 129 using WakeupCallback =
130 std::function<bool(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, 130 std::function<bool(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
131 std::shared_ptr<SynchronizationObject> object, std::size_t index)>; 131 std::shared_ptr<SynchronizationObject> object, std::size_t index)>;
132 using HLECallback = std::function<bool(std::shared_ptr<Thread> thread)>;
132 133
133 /** 134 /**
134 * Creates and returns a new thread. The new thread is immediately scheduled 135 * Creates and returns a new thread. The new thread is immediately scheduled
135 * @param system The instance of the whole system 136 * @param system The instance of the whole system
136 * @param name The friendly name desired for the thread 137 * @param name The friendly name desired for the thread
137 * @param entry_point The address at which the thread should start execution 138 * @param entry_point The address at which the thread should start execution
138 * @param priority The thread's priority 139 * @param priority The thread's priority
139 * @param arg User data to pass to the thread 140 * @param arg User data to pass to the thread
140 * @param processor_id The ID(s) of the processors on which the thread is desired to be run 141 * @param processor_id The ID(s) of the processors on which the thread is desired to be run
141 * @param stack_top The address of the thread's stack top 142 * @param stack_top The address of the thread's stack top
142 * @param owner_process The parent process for the thread, if null, it's a kernel thread 143 * @param owner_process The parent process for the thread, if null, it's a kernel thread
143 * @return A shared pointer to the newly created thread 144 * @return A shared pointer to the newly created thread
144 */ 145 */
145 static ResultVal<std::shared_ptr<Thread>> Create(Core::System& system, ThreadType type_flags, std::string name, 146 static ResultVal<std::shared_ptr<Thread>> Create(Core::System& system, ThreadType type_flags,
146 VAddr entry_point, u32 priority, u64 arg, 147 std::string name, VAddr entry_point,
147 s32 processor_id, VAddr stack_top, 148 u32 priority, u64 arg, s32 processor_id,
148 Process* owner_process); 149 VAddr stack_top, Process* owner_process);
149 150
150 /** 151 /**
151 * Creates and returns a new thread. The new thread is immediately scheduled 152 * Creates and returns a new thread. The new thread is immediately scheduled
@@ -161,10 +162,10 @@ public:
161 * @param thread_start_parameter The parameter which will passed to host context on init 162 * @param thread_start_parameter The parameter which will passed to host context on init
162 * @return A shared pointer to the newly created thread 163 * @return A shared pointer to the newly created thread
163 */ 164 */
164 static ResultVal<std::shared_ptr<Thread>> Create(Core::System& system, ThreadType type_flags, std::string name, 165 static ResultVal<std::shared_ptr<Thread>> Create(Core::System& system, ThreadType type_flags,
165 VAddr entry_point, u32 priority, u64 arg, 166 std::string name, VAddr entry_point,
166 s32 processor_id, VAddr stack_top, 167 u32 priority, u64 arg, s32 processor_id,
167 Process* owner_process, 168 VAddr stack_top, Process* owner_process,
168 std::function<void(void*)>&& thread_start_func, 169 std::function<void(void*)>&& thread_start_func,
169 void* thread_start_parameter); 170 void* thread_start_parameter);
170 171
@@ -447,17 +448,37 @@ public:
447 } 448 }
448 449
449 bool HasWakeupCallback() const { 450 bool HasWakeupCallback() const {
450 return wakeup_callback != nullptr; 451 return hle_callback != nullptr;
452 }
453
454 bool HasHLECallback() const {
455 return hle_callback != nullptr;
451 } 456 }
452 457
453 void SetWakeupCallback(WakeupCallback callback) { 458 void SetWakeupCallback(WakeupCallback callback) {
454 wakeup_callback = std::move(callback); 459 hle_callback = std::move(callback);
460 }
461
462 void SetHLECallback(WakeupCallback callback) {
463 hle_callback = std::move(callback);
464 }
465
466 void SetHLETimeEvent(Handle time_event) {
467 hle_time_event = time_event;
468 }
469
470 Handle GetHLETimeEvent() const {
471 return hle_time_event;
455 } 472 }
456 473
457 void InvalidateWakeupCallback() { 474 void InvalidateWakeupCallback() {
458 SetWakeupCallback(nullptr); 475 SetWakeupCallback(nullptr);
459 } 476 }
460 477
478 void InvalidateHLECallback() {
479 SetHLECallback(nullptr);
480 }
481
461 /** 482 /**
462 * Invokes the thread's wakeup callback. 483 * Invokes the thread's wakeup callback.
463 * 484 *
@@ -466,6 +487,8 @@ public:
466 */ 487 */
467 bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, 488 bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
468 std::shared_ptr<SynchronizationObject> object, std::size_t index); 489 std::shared_ptr<SynchronizationObject> object, std::size_t index);
490 bool InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
491 std::shared_ptr<SynchronizationObject> object, std::size_t index);
469 492
470 u32 GetIdealCore() const { 493 u32 GetIdealCore() const {
471 return ideal_core; 494 return ideal_core;
@@ -600,7 +623,8 @@ private:
600 /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread 623 /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
601 /// was waiting via WaitSynchronization then the object will be the last object that became 624 /// was waiting via WaitSynchronization then the object will be the last object that became
602 /// available. In case of a timeout, the object will be nullptr. 625 /// available. In case of a timeout, the object will be nullptr.
603 WakeupCallback wakeup_callback; 626 WakeupCallback hle_callback;
627 Handle hle_time_event;
604 628
605 Scheduler* scheduler = nullptr; 629 Scheduler* scheduler = nullptr;
606 630