diff options
| author | 2020-02-25 16:38:33 -0400 | |
|---|---|---|
| committer | 2020-06-27 11:35:13 -0400 | |
| commit | 3b5b950c895a2db217a3e5c8105cec4498a2534e (patch) | |
| tree | 2a8e054af30c9aa8039f8faa4b993e2290642184 /src | |
| parent | SVC: Remove global HLE Lock. (diff) | |
| download | yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.tar.gz yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.tar.xz yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.zip | |
SVC: Correct SignalEvent, ClearEvent, ResetSignal, WaitSynchronization, CancelSynchronization, ArbitrateLock
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/mutex.cpp | 65 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/readable_event.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/synchronization.cpp | 118 | ||||
| -rw-r--r-- | src/core/hle/kernel/synchronization_object.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 14 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 17 |
8 files changed, 134 insertions, 90 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 7869eb32b..3520c5e49 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -72,42 +72,55 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, | |||
| 72 | return ERR_INVALID_ADDRESS; | 72 | return ERR_INVALID_ADDRESS; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 75 | auto& kernel = system.Kernel(); |
| 76 | std::shared_ptr<Thread> current_thread = | 76 | std::shared_ptr<Thread> current_thread = |
| 77 | SharedFrom(system.CurrentScheduler().GetCurrentThread()); | 77 | SharedFrom(kernel.CurrentScheduler().GetCurrentThread()); |
| 78 | std::shared_ptr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle); | 78 | { |
| 79 | std::shared_ptr<Thread> requesting_thread = handle_table.Get<Thread>(requesting_thread_handle); | 79 | SchedulerLock lock(kernel); |
| 80 | // The mutex address must be 4-byte aligned | ||
| 81 | if ((address % sizeof(u32)) != 0) { | ||
| 82 | return ERR_INVALID_ADDRESS; | ||
| 83 | } | ||
| 80 | 84 | ||
| 81 | // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another | 85 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 82 | // thread. | 86 | std::shared_ptr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle); |
| 83 | ASSERT(requesting_thread == current_thread); | 87 | std::shared_ptr<Thread> requesting_thread = handle_table.Get<Thread>(requesting_thread_handle); |
| 84 | 88 | ||
| 85 | const u32 addr_value = system.Memory().Read32(address); | 89 | // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another |
| 90 | // thread. | ||
| 91 | ASSERT(requesting_thread == current_thread); | ||
| 86 | 92 | ||
| 87 | // If the mutex isn't being held, just return success. | 93 | current_thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS); |
| 88 | if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) { | ||
| 89 | return RESULT_SUCCESS; | ||
| 90 | } | ||
| 91 | 94 | ||
| 92 | if (holding_thread == nullptr) { | 95 | const u32 addr_value = system.Memory().Read32(address); |
| 93 | LOG_ERROR(Kernel, "Holding thread does not exist! thread_handle={:08X}", | ||
| 94 | holding_thread_handle); | ||
| 95 | return ERR_INVALID_HANDLE; | ||
| 96 | } | ||
| 97 | 96 | ||
| 98 | // Wait until the mutex is released | 97 | // If the mutex isn't being held, just return success. |
| 99 | current_thread->SetMutexWaitAddress(address); | 98 | if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) { |
| 100 | current_thread->SetWaitHandle(requesting_thread_handle); | 99 | return RESULT_SUCCESS; |
| 100 | } | ||
| 101 | 101 | ||
| 102 | current_thread->SetStatus(ThreadStatus::WaitMutex); | 102 | if (holding_thread == nullptr) { |
| 103 | current_thread->InvalidateWakeupCallback(); | 103 | return ERR_INVALID_HANDLE; |
| 104 | } | ||
| 104 | 105 | ||
| 105 | // Update the lock holder thread's priority to prevent priority inversion. | 106 | // Wait until the mutex is released |
| 106 | holding_thread->AddMutexWaiter(current_thread); | 107 | current_thread->SetMutexWaitAddress(address); |
| 108 | current_thread->SetWaitHandle(requesting_thread_handle); | ||
| 107 | 109 | ||
| 108 | system.PrepareReschedule(); | 110 | current_thread->SetStatus(ThreadStatus::WaitMutex); |
| 109 | 111 | ||
| 110 | return RESULT_SUCCESS; | 112 | // Update the lock holder thread's priority to prevent priority inversion. |
| 113 | holding_thread->AddMutexWaiter(current_thread); | ||
| 114 | } | ||
| 115 | |||
| 116 | { | ||
| 117 | SchedulerLock lock(kernel); | ||
| 118 | auto* owner = current_thread->GetLockOwner(); | ||
| 119 | if (owner != nullptr) { | ||
| 120 | owner->RemoveMutexWaiter(current_thread); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | return current_thread->GetSignalingResult(); | ||
| 111 | } | 124 | } |
| 112 | 125 | ||
| 113 | ResultCode Mutex::Release(VAddr address) { | 126 | ResultCode Mutex::Release(VAddr address) { |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 7e26a54f4..cd4b0aa60 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -212,6 +212,7 @@ void Process::UnregisterThread(const Thread* thread) { | |||
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | ResultCode Process::ClearSignalState() { | 214 | ResultCode Process::ClearSignalState() { |
| 215 | SchedulerLock lock(system.Kernel()); | ||
| 215 | if (status == ProcessStatus::Exited) { | 216 | if (status == ProcessStatus::Exited) { |
| 216 | LOG_ERROR(Kernel, "called on a terminated process instance."); | 217 | LOG_ERROR(Kernel, "called on a terminated process instance."); |
| 217 | return ERR_INVALID_STATE; | 218 | return ERR_INVALID_STATE; |
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp index ef5e19e63..6e286419e 100644 --- a/src/core/hle/kernel/readable_event.cpp +++ b/src/core/hle/kernel/readable_event.cpp | |||
| @@ -6,8 +6,10 @@ | |||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/hle/kernel/errors.h" | 8 | #include "core/hle/kernel/errors.h" |
| 9 | #include "core/hle/kernel/kernel.h" | ||
| 9 | #include "core/hle/kernel/object.h" | 10 | #include "core/hle/kernel/object.h" |
| 10 | #include "core/hle/kernel/readable_event.h" | 11 | #include "core/hle/kernel/readable_event.h" |
| 12 | #include "core/hle/kernel/scheduler.h" | ||
| 11 | #include "core/hle/kernel/thread.h" | 13 | #include "core/hle/kernel/thread.h" |
| 12 | 14 | ||
| 13 | namespace Kernel { | 15 | namespace Kernel { |
| @@ -37,6 +39,7 @@ void ReadableEvent::Clear() { | |||
| 37 | } | 39 | } |
| 38 | 40 | ||
| 39 | ResultCode ReadableEvent::Reset() { | 41 | ResultCode ReadableEvent::Reset() { |
| 42 | SchedulerLock lock(kernel); | ||
| 40 | if (!is_signaled) { | 43 | if (!is_signaled) { |
| 41 | LOG_TRACE(Kernel, "Handle is not signaled! object_id={}, object_type={}, object_name={}", | 44 | LOG_TRACE(Kernel, "Handle is not signaled! object_id={}, object_type={}, object_name={}", |
| 42 | GetObjectId(), GetTypeName(), GetName()); | 45 | GetObjectId(), GetTypeName(), GetName()); |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index a071b0c09..0d905c0ca 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -448,7 +448,6 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand | |||
| 448 | } | 448 | } |
| 449 | 449 | ||
| 450 | thread->CancelWait(); | 450 | thread->CancelWait(); |
| 451 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 452 | return RESULT_SUCCESS; | 451 | return RESULT_SUCCESS; |
| 453 | } | 452 | } |
| 454 | 453 | ||
diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index dc37fad1a..b36e550a0 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp | |||
| @@ -10,78 +10,88 @@ | |||
| 10 | #include "core/hle/kernel/synchronization.h" | 10 | #include "core/hle/kernel/synchronization.h" |
| 11 | #include "core/hle/kernel/synchronization_object.h" | 11 | #include "core/hle/kernel/synchronization_object.h" |
| 12 | #include "core/hle/kernel/thread.h" | 12 | #include "core/hle/kernel/thread.h" |
| 13 | #include "core/hle/kernel/time_manager.h" | ||
| 13 | 14 | ||
| 14 | namespace Kernel { | 15 | namespace Kernel { |
| 15 | 16 | ||
| 16 | /// Default thread wakeup callback for WaitSynchronization | ||
| 17 | static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, | ||
| 18 | std::shared_ptr<SynchronizationObject> object, | ||
| 19 | std::size_t index) { | ||
| 20 | ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch); | ||
| 21 | |||
| 22 | if (reason == ThreadWakeupReason::Timeout) { | ||
| 23 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | ||
| 24 | return true; | ||
| 25 | } | ||
| 26 | |||
| 27 | ASSERT(reason == ThreadWakeupReason::Signal); | ||
| 28 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | ||
| 29 | thread->SetWaitSynchronizationOutput(static_cast<u32>(index)); | ||
| 30 | return true; | ||
| 31 | } | ||
| 32 | |||
| 33 | Synchronization::Synchronization(Core::System& system) : system{system} {} | 17 | Synchronization::Synchronization(Core::System& system) : system{system} {} |
| 34 | 18 | ||
| 35 | void Synchronization::SignalObject(SynchronizationObject& obj) const { | 19 | void Synchronization::SignalObject(SynchronizationObject& obj) const { |
| 20 | SchedulerLock lock(system.Kernel()); | ||
| 36 | if (obj.IsSignaled()) { | 21 | if (obj.IsSignaled()) { |
| 37 | obj.WakeupAllWaitingThreads(); | 22 | for (auto thread : obj.GetWaitingThreads()) { |
| 23 | if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) { | ||
| 24 | thread->SetSynchronizationResults(&obj, RESULT_SUCCESS); | ||
| 25 | thread->ResumeFromWait(); | ||
| 26 | } | ||
| 27 | } | ||
| 38 | } | 28 | } |
| 39 | } | 29 | } |
| 40 | 30 | ||
| 41 | std::pair<ResultCode, Handle> Synchronization::WaitFor( | 31 | std::pair<ResultCode, Handle> Synchronization::WaitFor( |
| 42 | std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds) { | 32 | std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds) { |
| 33 | auto& kernel = system.Kernel(); | ||
| 43 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); | 34 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); |
| 44 | // Find the first object that is acquirable in the provided list of objects | 35 | Handle event_handle = InvalidHandle; |
| 45 | const auto itr = std::find_if(sync_objects.begin(), sync_objects.end(), | 36 | { |
| 46 | [thread](const std::shared_ptr<SynchronizationObject>& object) { | 37 | SchedulerLockAndSleep lock(kernel, event_handle, thread, nano_seconds); |
| 47 | return object->IsSignaled(); | 38 | const auto itr = |
| 48 | }); | 39 | std::find_if(sync_objects.begin(), sync_objects.end(), |
| 49 | 40 | [thread](const std::shared_ptr<SynchronizationObject>& object) { | |
| 50 | if (itr != sync_objects.end()) { | 41 | return object->IsSignaled(); |
| 51 | // We found a ready object, acquire it and set the result value | 42 | }); |
| 52 | SynchronizationObject* object = itr->get(); | 43 | |
| 53 | object->Acquire(thread); | 44 | if (itr != sync_objects.end()) { |
| 54 | const u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr)); | 45 | // We found a ready object, acquire it and set the result value |
| 55 | return {RESULT_SUCCESS, index}; | 46 | SynchronizationObject* object = itr->get(); |
| 47 | object->Acquire(thread); | ||
| 48 | const u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr)); | ||
| 49 | lock.CancelSleep(); | ||
| 50 | return {RESULT_SUCCESS, index}; | ||
| 51 | } | ||
| 52 | |||
| 53 | if (nano_seconds == 0) { | ||
| 54 | lock.CancelSleep(); | ||
| 55 | return {RESULT_TIMEOUT, InvalidHandle}; | ||
| 56 | } | ||
| 57 | |||
| 58 | /// TODO(Blinkhawk): Check for termination pending | ||
| 59 | |||
| 60 | if (thread->IsSyncCancelled()) { | ||
| 61 | thread->SetSyncCancelled(false); | ||
| 62 | lock.CancelSleep(); | ||
| 63 | return {ERR_SYNCHRONIZATION_CANCELED, InvalidHandle}; | ||
| 64 | } | ||
| 65 | |||
| 66 | for (auto& object : sync_objects) { | ||
| 67 | object->AddWaitingThread(SharedFrom(thread)); | ||
| 68 | } | ||
| 69 | thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); | ||
| 70 | thread->SetStatus(ThreadStatus::WaitSynch); | ||
| 56 | } | 71 | } |
| 57 | 72 | ||
| 58 | // No objects were ready to be acquired, prepare to suspend the thread. | 73 | if (event_handle != InvalidHandle) { |
| 59 | 74 | auto& time_manager = kernel.TimeManager(); | |
| 60 | // If a timeout value of 0 was provided, just return the Timeout error code instead of | 75 | time_manager.UnscheduleTimeEvent(event_handle); |
| 61 | // suspending the thread. | ||
| 62 | if (nano_seconds == 0) { | ||
| 63 | return {RESULT_TIMEOUT, InvalidHandle}; | ||
| 64 | } | 76 | } |
| 65 | 77 | ||
| 66 | if (thread->IsSyncCancelled()) { | 78 | { |
| 67 | thread->SetSyncCancelled(false); | 79 | SchedulerLock lock(kernel); |
| 68 | return {ERR_SYNCHRONIZATION_CANCELED, InvalidHandle}; | 80 | ResultCode signaling_result = thread->GetSignalingResult(); |
| 81 | SynchronizationObject* signaling_object = thread->GetSignalingObject(); | ||
| 82 | if (signaling_result == RESULT_SUCCESS) { | ||
| 83 | const auto itr = std::find_if( | ||
| 84 | sync_objects.begin(), sync_objects.end(), | ||
| 85 | [signaling_object](const std::shared_ptr<SynchronizationObject>& object) { | ||
| 86 | return object.get() == signaling_object; | ||
| 87 | }); | ||
| 88 | ASSERT(itr != sync_objects.end()); | ||
| 89 | signaling_object->Acquire(thread); | ||
| 90 | const u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr)); | ||
| 91 | return {RESULT_SUCCESS, index}; | ||
| 92 | } | ||
| 93 | return {signaling_result, -1}; | ||
| 69 | } | 94 | } |
| 70 | |||
| 71 | for (auto& object : sync_objects) { | ||
| 72 | object->AddWaitingThread(SharedFrom(thread)); | ||
| 73 | } | ||
| 74 | |||
| 75 | thread->SetSynchronizationObjects(std::move(sync_objects)); | ||
| 76 | thread->SetStatus(ThreadStatus::WaitSynch); | ||
| 77 | |||
| 78 | // Create an event to wake the thread up after the specified nanosecond delay has passed | ||
| 79 | thread->WakeAfterDelay(nano_seconds); | ||
| 80 | thread->SetWakeupCallback(DefaultThreadWakeupCallback); | ||
| 81 | |||
| 82 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 83 | |||
| 84 | return {RESULT_TIMEOUT, InvalidHandle}; | ||
| 85 | } | 95 | } |
| 86 | 96 | ||
| 87 | } // namespace Kernel | 97 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/synchronization_object.h b/src/core/hle/kernel/synchronization_object.h index 741c31faf..0a0d069e0 100644 --- a/src/core/hle/kernel/synchronization_object.h +++ b/src/core/hle/kernel/synchronization_object.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | namespace Kernel { | 12 | namespace Kernel { |
| 13 | 13 | ||
| 14 | class KernelCore; | 14 | class KernelCore; |
| 15 | class Synchronization; | ||
| 15 | class Thread; | 16 | class Thread; |
| 16 | 17 | ||
| 17 | /// Class that represents a Kernel object that a thread can be waiting on | 18 | /// Class that represents a Kernel object that a thread can be waiting on |
| @@ -53,7 +54,7 @@ public: | |||
| 53 | * Wake up all threads waiting on this object that can be awoken, in priority order, | 54 | * Wake up all threads waiting on this object that can be awoken, in priority order, |
| 54 | * and set the synchronization result and output of the thread. | 55 | * and set the synchronization result and output of the thread. |
| 55 | */ | 56 | */ |
| 56 | void WakeupAllWaitingThreads(); | 57 | void /* deprecated */ WakeupAllWaitingThreads(); |
| 57 | 58 | ||
| 58 | /** | 59 | /** |
| 59 | * Wakes up a single thread waiting on this object. | 60 | * Wakes up a single thread waiting on this object. |
| @@ -62,7 +63,7 @@ public: | |||
| 62 | void WakeupWaitingThread(std::shared_ptr<Thread> thread); | 63 | void WakeupWaitingThread(std::shared_ptr<Thread> thread); |
| 63 | 64 | ||
| 64 | /// Obtains the highest priority thread that is ready to run from this object's waiting list. | 65 | /// Obtains the highest priority thread that is ready to run from this object's waiting list. |
| 65 | std::shared_ptr<Thread> GetHighestPriorityReadyThread() const; | 66 | std::shared_ptr<Thread> /* deprecated */ GetHighestPriorityReadyThread() const; |
| 66 | 67 | ||
| 67 | /// Get a const reference to the waiting threads list for debug use | 68 | /// Get a const reference to the waiting threads list for debug use |
| 68 | const std::vector<std::shared_ptr<Thread>>& GetWaitingThreads() const; | 69 | const std::vector<std::shared_ptr<Thread>>& GetWaitingThreads() const; |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index e6bb7c666..5fef3945b 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -139,12 +139,13 @@ ResultCode Thread::Start() { | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | void Thread::CancelWait() { | 141 | void Thread::CancelWait() { |
| 142 | SchedulerLock lock(kernel); | ||
| 142 | if (GetSchedulingStatus() != ThreadSchedStatus::Paused) { | 143 | if (GetSchedulingStatus() != ThreadSchedStatus::Paused) { |
| 143 | is_sync_cancelled = true; | 144 | is_sync_cancelled = true; |
| 144 | return; | 145 | return; |
| 145 | } | 146 | } |
| 146 | is_sync_cancelled = false; | 147 | is_sync_cancelled = false; |
| 147 | SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED); | 148 | SetSynchronizationResults(nullptr, ERR_SYNCHRONIZATION_CANCELED); |
| 148 | ResumeFromWait(); | 149 | ResumeFromWait(); |
| 149 | } | 150 | } |
| 150 | 151 | ||
| @@ -258,13 +259,16 @@ void Thread::SetPriority(u32 priority) { | |||
| 258 | } | 259 | } |
| 259 | 260 | ||
| 260 | void Thread::SetWaitSynchronizationResult(ResultCode result) { | 261 | void Thread::SetWaitSynchronizationResult(ResultCode result) { |
| 261 | context_32.cpu_registers[0] = result.raw; | 262 | UNREACHABLE(); |
| 262 | context_64.cpu_registers[0] = result.raw; | ||
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | void Thread::SetWaitSynchronizationOutput(s32 output) { | 265 | void Thread::SetWaitSynchronizationOutput(s32 output) { |
| 266 | context_32.cpu_registers[1] = output; | 266 | UNREACHABLE(); |
| 267 | context_64.cpu_registers[1] = output; | 267 | } |
| 268 | |||
| 269 | void Thread::SetSynchronizationResults(SynchronizationObject* object, ResultCode result) { | ||
| 270 | signaling_object = object; | ||
| 271 | signaling_result = result; | ||
| 268 | } | 272 | } |
| 269 | 273 | ||
| 270 | s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const { | 274 | s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const { |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 29fe5483b..a8ae1a66f 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -259,13 +259,23 @@ public: | |||
| 259 | * Sets the result after the thread awakens (from svcWaitSynchronization) | 259 | * Sets the result after the thread awakens (from svcWaitSynchronization) |
| 260 | * @param result Value to set to the returned result | 260 | * @param result Value to set to the returned result |
| 261 | */ | 261 | */ |
| 262 | void SetWaitSynchronizationResult(ResultCode result); | 262 | void /*deprecated*/ SetWaitSynchronizationResult(ResultCode result); |
| 263 | 263 | ||
| 264 | /** | 264 | /** |
| 265 | * Sets the output parameter value after the thread awakens (from svcWaitSynchronization) | 265 | * Sets the output parameter value after the thread awakens (from svcWaitSynchronization) |
| 266 | * @param output Value to set to the output parameter | 266 | * @param output Value to set to the output parameter |
| 267 | */ | 267 | */ |
| 268 | void SetWaitSynchronizationOutput(s32 output); | 268 | void /*deprecated*/ SetWaitSynchronizationOutput(s32 output); |
| 269 | |||
| 270 | void SetSynchronizationResults(SynchronizationObject* object, ResultCode result); | ||
| 271 | |||
| 272 | SynchronizationObject* GetSignalingObject() const { | ||
| 273 | return signaling_object; | ||
| 274 | } | ||
| 275 | |||
| 276 | ResultCode GetSignalingResult() const { | ||
| 277 | return signaling_result; | ||
| 278 | } | ||
| 269 | 279 | ||
| 270 | /** | 280 | /** |
| 271 | * Retrieves the index that this particular object occupies in the list of objects | 281 | * Retrieves the index that this particular object occupies in the list of objects |
| @@ -565,6 +575,9 @@ private: | |||
| 565 | /// passed to WaitSynchronization. | 575 | /// passed to WaitSynchronization. |
| 566 | ThreadSynchronizationObjects wait_objects; | 576 | ThreadSynchronizationObjects wait_objects; |
| 567 | 577 | ||
| 578 | SynchronizationObject* signaling_object; | ||
| 579 | ResultCode signaling_result{RESULT_SUCCESS}; | ||
| 580 | |||
| 568 | /// List of threads that are waiting for a mutex that is held by this thread. | 581 | /// List of threads that are waiting for a mutex that is held by this thread. |
| 569 | MutexWaitingThreads wait_mutex_threads; | 582 | MutexWaitingThreads wait_mutex_threads; |
| 570 | 583 | ||