summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Michael Scire2018-06-21 20:25:57 -0600
committerGravatar Michael Scire2018-06-21 20:25:57 -0600
commitdc70a87af1576e29dd6fda1d0313aca260982498 (patch)
treead2458fcae93251cd0110ab02f8d3a2db766b3dc /src/core/hle/kernel
parentKernel/Arbiters: Initialize arb_wait_address in thread struct. (diff)
downloadyuzu-dc70a87af1576e29dd6fda1d0313aca260982498.tar.gz
yuzu-dc70a87af1576e29dd6fda1d0313aca260982498.tar.xz
yuzu-dc70a87af1576e29dd6fda1d0313aca260982498.zip
Kernel/Arbiters: HLE is atomic, adjust code to reflect that.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp49
-rw-r--r--src/core/hle/kernel/thread.h1
2 files changed, 13 insertions, 37 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 63cdcb559..01c5bf61b 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -20,14 +20,14 @@ namespace Kernel {
20 ResultCode WaitForAddress(VAddr address, s64 timeout) { 20 ResultCode WaitForAddress(VAddr address, s64 timeout) {
21 SharedPtr<Thread> current_thread = GetCurrentThread(); 21 SharedPtr<Thread> current_thread = GetCurrentThread();
22 current_thread->arb_wait_address = address; 22 current_thread->arb_wait_address = address;
23 current_thread->arb_wait_result = RESULT_TIMEOUT;
24 current_thread->status = THREADSTATUS_WAIT_ARB; 23 current_thread->status = THREADSTATUS_WAIT_ARB;
25 current_thread->wakeup_callback = nullptr; 24 current_thread->wakeup_callback = nullptr;
26 25
27 current_thread->WakeAfterDelay(timeout); 26 current_thread->WakeAfterDelay(timeout);
28 27
29 Core::System::GetInstance().CpuCore(current_thread->processor_id).PrepareReschedule(); 28 Core::System::GetInstance().CpuCore(current_thread->processor_id).PrepareReschedule();
30 return current_thread->arb_wait_result; 29 // This should never actually execute.
30 return RESULT_SUCCESS;
31 } 31 }
32 32
33 // Gets the threads waiting on an address. 33 // Gets the threads waiting on an address.
@@ -67,7 +67,7 @@ namespace Kernel {
67 // TODO: Rescheduling should not occur while waking threads. How can it be prevented? 67 // TODO: Rescheduling should not occur while waking threads. How can it be prevented?
68 for (size_t i = 0; i < last; i++) { 68 for (size_t i = 0; i < last; i++) {
69 ASSERT(waiting_threads[i]->status = THREADSTATUS_WAIT_ARB); 69 ASSERT(waiting_threads[i]->status = THREADSTATUS_WAIT_ARB);
70 waiting_threads[i]->arb_wait_result = RESULT_SUCCESS; 70 waiting_threads[i]->SetWaitSynchronizationResult(RESULT_SUCCESS);
71 waiting_threads[i]->arb_wait_address = 0; 71 waiting_threads[i]->arb_wait_address = 0;
72 waiting_threads[i]->ResumeFromWait(); 72 waiting_threads[i]->ResumeFromWait();
73 } 73 }
@@ -91,17 +91,9 @@ namespace Kernel {
91 return ERR_INVALID_ADDRESS_STATE; 91 return ERR_INVALID_ADDRESS_STATE;
92 } 92 }
93 93
94 s32 cur_value; 94 if ((s32)Memory::Read32(address) == value) {
95 // Get value, incrementing if equal. 95 Memory::Write32(address, (u32)(value + 1));
96 { 96 } else {
97 // Increment if Equal must be an atomic operation.
98 std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
99 cur_value = (s32)Memory::Read32(address);
100 if (cur_value == value) {
101 Memory::Write32(address, (u32)(cur_value + 1));
102 }
103 }
104 if (cur_value != value) {
105 return ERR_INVALID_STATE; 97 return ERR_INVALID_STATE;
106 } 98 }
107 99
@@ -128,18 +120,10 @@ namespace Kernel {
128 } else { 120 } else {
129 updated_value = value; 121 updated_value = value;
130 } 122 }
131 s32 cur_value;
132 // Perform an atomic update if equal.
133 {
134 std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
135 cur_value = (s32)Memory::Read32(address);
136 if (cur_value == value) {
137 Memory::Write32(address, (u32)(updated_value));
138 }
139 }
140 123
141 // Only continue if equal. 124 if ((s32)Memory::Read32(address) == value) {
142 if (cur_value != value) { 125 Memory::Write32(address, (u32)(updated_value));
126 } else {
143 return ERR_INVALID_STATE; 127 return ERR_INVALID_STATE;
144 } 128 }
145 129
@@ -154,17 +138,10 @@ namespace Kernel {
154 return ERR_INVALID_ADDRESS_STATE; 138 return ERR_INVALID_ADDRESS_STATE;
155 } 139 }
156 140
157 s32 cur_value; 141 s32 cur_value = (s32)Memory::Read32(address);
158 // Get value, decrementing if less than 142 if (cur_value < value) {
159 { 143 Memory::Write32(address, (u32)(cur_value - 1));
160 // Decrement if less than must be an atomic operation. 144 } else {
161 std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
162 cur_value = (s32)Memory::Read32(address);
163 if (cur_value < value) {
164 Memory::Write32(address, (u32)(cur_value - 1));
165 }
166 }
167 if (cur_value >= value) {
168 return ERR_INVALID_STATE; 145 return ERR_INVALID_STATE;
169 } 146 }
170 // Short-circuit without rescheduling, if timeout is zero. 147 // Short-circuit without rescheduling, if timeout is zero.
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 7a28f3c1c..3851d1085 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -233,7 +233,6 @@ public:
233 233
234 // If waiting for an AddressArbiter, this is the address being waited on. 234 // If waiting for an AddressArbiter, this is the address being waited on.
235 VAddr arb_wait_address{0}; 235 VAddr arb_wait_address{0};
236 ResultCode arb_wait_result{RESULT_SUCCESS}; ///< Result returned when done waiting on AddressArbiter.
237 236
238 std::string name; 237 std::string name;
239 238