summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp84
1 files changed, 30 insertions, 54 deletions
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp
index f2f497dc4..d0e90fd60 100644
--- a/src/core/hle/kernel/k_address_arbiter.cpp
+++ b/src/core/hle/kernel/k_address_arbiter.cpp
@@ -118,9 +118,10 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32
118 118
119 // Check the userspace value. 119 // Check the userspace value.
120 s32 user_value{}; 120 s32 user_value{};
121 R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1), 121 if (!UpdateIfEqual(system, &user_value, addr, value, value + 1)) {
122 Svc::ResultInvalidCurrentMemory); 122 LOG_ERROR(Kernel, "Invalid current memory!");
123 123 return Svc::ResultInvalidCurrentMemory;
124 }
124 if (user_value != value) { 125 if (user_value != value) {
125 return Svc::ResultInvalidState; 126 return Svc::ResultInvalidState;
126 } 127 }
@@ -146,61 +147,34 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
146 // Perform signaling. 147 // Perform signaling.
147 s32 num_waiters{}; 148 s32 num_waiters{};
148 { 149 {
149 KScopedSchedulerLock sl(kernel); 150 [[maybe_unused]] const KScopedSchedulerLock sl(kernel);
150 151
151 auto it = thread_tree.nfind_light({addr, -1}); 152 auto it = thread_tree.nfind_light({addr, -1});
152 // Determine the updated value. 153 // Determine the updated value.
153 s32 new_value{}; 154 s32 new_value{};
154 if (/*GetTargetFirmware() >= TargetFirmware_7_0_0*/ true) { 155 if (count <= 0) {
155 if (count <= 0) { 156 if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
156 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { 157 new_value = value - 2;
157 new_value = value - 2;
158 } else {
159 new_value = value + 1;
160 }
161 } else { 158 } else {
162 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { 159 new_value = value + 1;
163 auto tmp_it = it;
164 s32 tmp_num_waiters{};
165 while ((++tmp_it != thread_tree.end()) &&
166 (tmp_it->GetAddressArbiterKey() == addr)) {
167 if ((tmp_num_waiters++) >= count) {
168 break;
169 }
170 }
171
172 if (tmp_num_waiters < count) {
173 new_value = value - 1;
174 } else {
175 new_value = value;
176 }
177 } else {
178 new_value = value + 1;
179 }
180 } 160 }
181 } else { 161 } else {
182 if (count <= 0) { 162 if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
183 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
184 new_value = value - 1;
185 } else {
186 new_value = value + 1;
187 }
188 } else {
189 auto tmp_it = it; 163 auto tmp_it = it;
190 s32 tmp_num_waiters{}; 164 s32 tmp_num_waiters{};
191 while ((tmp_it != thread_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && 165 while (++tmp_it != thread_tree.end() && tmp_it->GetAddressArbiterKey() == addr) {
192 (tmp_num_waiters < count + 1)) { 166 if (tmp_num_waiters++ >= count) {
193 ++tmp_num_waiters; 167 break;
194 ++tmp_it; 168 }
195 } 169 }
196 170
197 if (tmp_num_waiters == 0) { 171 if (tmp_num_waiters < count) {
198 new_value = value + 1;
199 } else if (tmp_num_waiters <= count) {
200 new_value = value - 1; 172 new_value = value - 1;
201 } else { 173 } else {
202 new_value = value; 174 new_value = value;
203 } 175 }
176 } else {
177 new_value = value + 1;
204 } 178 }
205 } 179 }
206 180
@@ -208,13 +182,15 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
208 s32 user_value{}; 182 s32 user_value{};
209 bool succeeded{}; 183 bool succeeded{};
210 if (value != new_value) { 184 if (value != new_value) {
211 succeeded = UpdateIfEqual(system, std::addressof(user_value), addr, value, new_value); 185 succeeded = UpdateIfEqual(system, &user_value, addr, value, new_value);
212 } else { 186 } else {
213 succeeded = ReadFromUser(system, std::addressof(user_value), addr); 187 succeeded = ReadFromUser(system, &user_value, addr);
214 } 188 }
215 189
216 R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory); 190 if (!succeeded) {
217 191 LOG_ERROR(Kernel, "Invalid current memory!");
192 return Svc::ResultInvalidCurrentMemory;
193 }
218 if (user_value != value) { 194 if (user_value != value) {
219 return Svc::ResultInvalidState; 195 return Svc::ResultInvalidState;
220 } 196 }
@@ -255,9 +231,9 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
255 s32 user_value{}; 231 s32 user_value{};
256 bool succeeded{}; 232 bool succeeded{};
257 if (decrement) { 233 if (decrement) {
258 succeeded = DecrementIfLessThan(system, std::addressof(user_value), addr, value); 234 succeeded = DecrementIfLessThan(system, &user_value, addr, value);
259 } else { 235 } else {
260 succeeded = ReadFromUser(system, std::addressof(user_value), addr); 236 succeeded = ReadFromUser(system, &user_value, addr);
261 } 237 }
262 238
263 if (!succeeded) { 239 if (!succeeded) {
@@ -278,7 +254,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
278 } 254 }
279 255
280 // Set the arbiter. 256 // Set the arbiter.
281 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 257 cur_thread->SetAddressArbiter(&thread_tree, addr);
282 thread_tree.insert(*cur_thread); 258 thread_tree.insert(*cur_thread);
283 cur_thread->SetState(ThreadState::Waiting); 259 cur_thread->SetState(ThreadState::Waiting);
284 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); 260 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -299,7 +275,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
299 275
300 // Get the result. 276 // Get the result.
301 KSynchronizationObject* dummy{}; 277 KSynchronizationObject* dummy{};
302 return cur_thread->GetWaitResult(std::addressof(dummy)); 278 return cur_thread->GetWaitResult(&dummy);
303} 279}
304 280
305ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { 281ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
@@ -320,7 +296,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
320 296
321 // Read the value from userspace. 297 // Read the value from userspace.
322 s32 user_value{}; 298 s32 user_value{};
323 if (!ReadFromUser(system, std::addressof(user_value), addr)) { 299 if (!ReadFromUser(system, &user_value, addr)) {
324 slp.CancelSleep(); 300 slp.CancelSleep();
325 return Svc::ResultInvalidCurrentMemory; 301 return Svc::ResultInvalidCurrentMemory;
326 } 302 }
@@ -338,7 +314,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
338 } 314 }
339 315
340 // Set the arbiter. 316 // Set the arbiter.
341 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 317 cur_thread->SetAddressArbiter(&thread_tree, addr);
342 thread_tree.insert(*cur_thread); 318 thread_tree.insert(*cur_thread);
343 cur_thread->SetState(ThreadState::Waiting); 319 cur_thread->SetState(ThreadState::Waiting);
344 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); 320 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -359,7 +335,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
359 335
360 // Get the result. 336 // Get the result.
361 KSynchronizationObject* dummy{}; 337 KSynchronizationObject* dummy{};
362 return cur_thread->GetWaitResult(std::addressof(dummy)); 338 return cur_thread->GetWaitResult(&dummy);
363} 339}
364 340
365} // namespace Kernel 341} // namespace Kernel