diff options
| -rw-r--r-- | src/core/hle/kernel/k_address_arbiter.cpp | 84 |
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 | ||
| 305 | ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { | 281 | ResultCode 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 |