summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Michael Scire2018-06-21 01:40:29 -0600
committerGravatar Michael Scire2018-06-21 01:40:29 -0600
commit9d71ce88cee58d2e171ec5ed82daf075112fb422 (patch)
tree3e8dfaf638c2e63124295d2c8ed1b20c6060c847 /src
parentKernel/Arbiters: Add stubs for 4.x SignalToAddress/WaitForAddres SVCs. (diff)
downloadyuzu-9d71ce88cee58d2e171ec5ed82daf075112fb422.tar.gz
yuzu-9d71ce88cee58d2e171ec5ed82daf075112fb422.tar.xz
yuzu-9d71ce88cee58d2e171ec5ed82daf075112fb422.zip
Kernel/Arbiters: Implement WaitForAddress
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp59
-rw-r--r--src/core/hle/kernel/errors.h2
-rw-r--r--src/core/hle/kernel/thread.cpp6
-rw-r--r--src/core/hle/kernel/thread.h6
-rw-r--r--src/yuzu/debugger/wait_tree.cpp4
5 files changed, 71 insertions, 6 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index cfd2c1590..367c4520d 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -5,14 +5,31 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_funcs.h" 6#include "common/common_funcs.h"
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "core/core.h"
9#include "core/hle/kernel/errors.h"
8#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
9#include "core/hle/kernel/process.h" 11#include "core/hle/kernel/process.h"
10#include "core/hle/kernel/thread.h" 12#include "core/hle/kernel/thread.h"
13#include "core/hle/lock.h"
11#include "core/memory.h" 14#include "core/memory.h"
12 15
13namespace Kernel { 16namespace Kernel {
14 namespace AddressArbiter { 17 namespace AddressArbiter {
15 18
19 // Performs actual address waiting logic.
20 ResultCode WaitForAddress(VAddr address, s64 timeout) {
21 SharedPtr<Thread> current_thread = GetCurrentThread();
22 current_thread->arb_wait_address = address;
23 current_thread->arb_wait_result = RESULT_TIMEOUT;
24 current_thread->status = THREADSTATUS_WAIT_ARB;
25 current_thread->wakeup_callback = nullptr;
26
27 current_thread->WakeAfterDelay(timeout);
28
29 Core::System::GetInstance().CpuCore(current_thread->processor_id).PrepareReschedule();
30 return RESULT_SUCCESS;
31 }
32
16 // Signals an address being waited on. 33 // Signals an address being waited on.
17 ResultCode SignalToAddress(VAddr address, s32 value, s32 num_to_wake) { 34 ResultCode SignalToAddress(VAddr address, s32 value, s32 num_to_wake) {
18 // TODO 35 // TODO
@@ -33,14 +50,48 @@ namespace Kernel {
33 50
34 // Waits on an address if the value passed is less than the argument value, optionally decrementing. 51 // Waits on an address if the value passed is less than the argument value, optionally decrementing.
35 ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement) { 52 ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement) {
36 // TODO 53 // Ensure that we can read the address.
37 return RESULT_SUCCESS; 54 if (!Memory::IsValidVirtualAddress(address)) {
55 return ERR_INVALID_ADDRESS_STATE;
56 }
57
58 s32 cur_value;
59 // Get value, decrementing if less than
60 {
61 // Decrement if less than must be an atomic operation.
62 std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
63 cur_value = (s32)Memory::Read32(address);
64 if (cur_value < value) {
65 Memory::Write32(address, (u32)(cur_value - 1));
66 }
67 }
68 if (cur_value >= value) {
69 return ERR_INVALID_STATE;
70 }
71 // Short-circuit without rescheduling, if timeout is zero.
72 if (timeout == 0) {
73 return RESULT_TIMEOUT;
74 }
75
76 return WaitForAddress(address, timeout);
38 } 77 }
39 78
40 // Waits on an address if the value passed is equal to the argument value. 79 // Waits on an address if the value passed is equal to the argument value.
41 ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { 80 ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) {
42 // TODO 81 // Ensure that we can read the address.
43 return RESULT_SUCCESS; 82 if (!Memory::IsValidVirtualAddress(address)) {
83 return ERR_INVALID_ADDRESS_STATE;
84 }
85 // Only wait for the address if equal.
86 if ((s32)Memory::Read32(address) != value) {
87 return ERR_INVALID_STATE;
88 }
89 // Short-circuit without rescheduling, if timeout is zero.
90 if (timeout == 0) {
91 return RESULT_TIMEOUT;
92 }
93
94 return WaitForAddress(address, timeout);
44 } 95 }
45 } // namespace AddressArbiter 96 } // namespace AddressArbiter
46} // namespace Kernel \ No newline at end of file 97} // namespace Kernel \ No newline at end of file
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h
index 7ac960042..221cb1bb5 100644
--- a/src/core/hle/kernel/errors.h
+++ b/src/core/hle/kernel/errors.h
@@ -29,6 +29,7 @@ enum {
29 SynchronizationCanceled = 118, 29 SynchronizationCanceled = 118,
30 TooLarge = 119, 30 TooLarge = 119,
31 InvalidEnumValue = 120, 31 InvalidEnumValue = 120,
32 InvalidState = 125,
32}; 33};
33} 34}
34 35
@@ -49,6 +50,7 @@ constexpr ResultCode ERR_OUT_OF_MEMORY(-1);
49constexpr ResultCode ERR_INVALID_ADDRESS(ErrorModule::Kernel, ErrCodes::InvalidAddress); 50constexpr ResultCode ERR_INVALID_ADDRESS(ErrorModule::Kernel, ErrCodes::InvalidAddress);
50constexpr ResultCode ERR_INVALID_ADDRESS_STATE(ErrorModule::Kernel, ErrCodes::InvalidMemoryState); 51constexpr ResultCode ERR_INVALID_ADDRESS_STATE(ErrorModule::Kernel, ErrCodes::InvalidMemoryState);
51constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); 52constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle);
53constexpr ResultCode ERR_INVALID_STATE(ErrorModule::Kernel, ErrCodes::InvalidState);
52constexpr ResultCode ERR_INVALID_POINTER(-1); 54constexpr ResultCode ERR_INVALID_POINTER(-1);
53constexpr ResultCode ERR_INVALID_OBJECT_ADDR(-1); 55constexpr ResultCode ERR_INVALID_OBJECT_ADDR(-1);
54constexpr ResultCode ERR_NOT_AUTHORIZED(-1); 56constexpr ResultCode ERR_NOT_AUTHORIZED(-1);
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index cffa7ca83..2f333ec34 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -140,6 +140,11 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
140 } 140 }
141 } 141 }
142 142
143 if (thread->arb_wait_address != 0) {
144 ASSERT(thread->status == THREADSTATUS_WAIT_ARB);
145 thread->arb_wait_address = 0;
146 }
147
143 if (resume) 148 if (resume)
144 thread->ResumeFromWait(); 149 thread->ResumeFromWait();
145} 150}
@@ -179,6 +184,7 @@ void Thread::ResumeFromWait() {
179 case THREADSTATUS_WAIT_SLEEP: 184 case THREADSTATUS_WAIT_SLEEP:
180 case THREADSTATUS_WAIT_IPC: 185 case THREADSTATUS_WAIT_IPC:
181 case THREADSTATUS_WAIT_MUTEX: 186 case THREADSTATUS_WAIT_MUTEX:
187 case THREADSTATUS_WAIT_ARB:
182 break; 188 break;
183 189
184 case THREADSTATUS_READY: 190 case THREADSTATUS_READY:
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 023c9dbe9..79e5d6e5c 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -228,8 +228,10 @@ public:
228 228
229 // If waiting on a ConditionVariable, this is the ConditionVariable address 229 // If waiting on a ConditionVariable, this is the ConditionVariable address
230 VAddr condvar_wait_address; 230 VAddr condvar_wait_address;
231 VAddr mutex_wait_address; ///< If waiting on a Mutex, this is the mutex address 231 VAddr mutex_wait_address; ///< If waiting on a Mutex, this is the mutex address
232 Handle wait_handle; ///< The handle used to wait for the mutex. 232 Handle wait_handle; ///< The handle used to wait for the mutex.
233 VAddr arb_wait_address; ///< If waiting for an AddressArbiter, this is the address
234 ResultCode arb_wait_result; ///< If waiting for an AddressArbiter, this is the result that will be returned.
233 235
234 std::string name; 236 std::string name;
235 237
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 017bef13c..800e431bd 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -213,6 +213,9 @@ QString WaitTreeThread::GetText() const {
213 case THREADSTATUS_WAIT_MUTEX: 213 case THREADSTATUS_WAIT_MUTEX:
214 status = tr("waiting for mutex"); 214 status = tr("waiting for mutex");
215 break; 215 break;
216 case THREADSTATUS_WAIT_MUTEX:
217 status = tr("waiting for address arbiter");
218 break;
216 case THREADSTATUS_DORMANT: 219 case THREADSTATUS_DORMANT:
217 status = tr("dormant"); 220 status = tr("dormant");
218 break; 221 break;
@@ -240,6 +243,7 @@ QColor WaitTreeThread::GetColor() const {
240 case THREADSTATUS_WAIT_SYNCH_ALL: 243 case THREADSTATUS_WAIT_SYNCH_ALL:
241 case THREADSTATUS_WAIT_SYNCH_ANY: 244 case THREADSTATUS_WAIT_SYNCH_ANY:
242 case THREADSTATUS_WAIT_MUTEX: 245 case THREADSTATUS_WAIT_MUTEX:
246 case THREADSTATUS_WAIT_ARB:
243 return QColor(Qt::GlobalColor::red); 247 return QColor(Qt::GlobalColor::red);
244 case THREADSTATUS_DORMANT: 248 case THREADSTATUS_DORMANT:
245 return QColor(Qt::GlobalColor::darkCyan); 249 return QColor(Qt::GlobalColor::darkCyan);