diff options
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/kernel/k_address_arbiter.cpp | 68 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_condition_variable.cpp | 27 |
2 files changed, 56 insertions, 39 deletions
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index 08c254028..78d43d729 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp | |||
| @@ -35,24 +35,30 @@ bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address | |||
| 35 | 35 | ||
| 36 | // TODO(bunnei): We should call CanAccessAtomic(..) here. | 36 | // TODO(bunnei): We should call CanAccessAtomic(..) here. |
| 37 | 37 | ||
| 38 | // Load the value from the address. | 38 | s32 current_value{}; |
| 39 | const s32 current_value = | 39 | |
| 40 | static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address))); | 40 | while (true) { |
| 41 | 41 | // Load the value from the address. | |
| 42 | // Compare it to the desired one. | 42 | current_value = |
| 43 | if (current_value < value) { | 43 | static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address))); |
| 44 | // If less than, we want to try to decrement. | 44 | |
| 45 | const s32 decrement_value = current_value - 1; | 45 | // Compare it to the desired one. |
| 46 | if (current_value < value) { | ||
| 47 | // If less than, we want to try to decrement. | ||
| 48 | const s32 decrement_value = current_value - 1; | ||
| 49 | |||
| 50 | // Decrement and try to store. | ||
| 51 | if (monitor.ExclusiveWrite32(current_core, GetInteger(address), | ||
| 52 | static_cast<u32>(decrement_value))) { | ||
| 53 | break; | ||
| 54 | } | ||
| 46 | 55 | ||
| 47 | // Decrement and try to store. | ||
| 48 | if (!monitor.ExclusiveWrite32(current_core, GetInteger(address), | ||
| 49 | static_cast<u32>(decrement_value))) { | ||
| 50 | // If we failed to store, try again. | 56 | // If we failed to store, try again. |
| 51 | DecrementIfLessThan(system, out, address, value); | 57 | } else { |
| 58 | // Otherwise, clear our exclusive hold and finish | ||
| 59 | monitor.ClearExclusive(current_core); | ||
| 60 | break; | ||
| 52 | } | 61 | } |
| 53 | } else { | ||
| 54 | // Otherwise, clear our exclusive hold and finish | ||
| 55 | monitor.ClearExclusive(current_core); | ||
| 56 | } | 62 | } |
| 57 | 63 | ||
| 58 | // We're done. | 64 | // We're done. |
| @@ -70,23 +76,29 @@ bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32 | |||
| 70 | 76 | ||
| 71 | // TODO(bunnei): We should call CanAccessAtomic(..) here. | 77 | // TODO(bunnei): We should call CanAccessAtomic(..) here. |
| 72 | 78 | ||
| 73 | // Load the value from the address. | 79 | s32 current_value{}; |
| 74 | const s32 current_value = | ||
| 75 | static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address))); | ||
| 76 | 80 | ||
| 77 | // Compare it to the desired one. | 81 | // Load the value from the address. |
| 78 | if (current_value == value) { | 82 | while (true) { |
| 79 | // If equal, we want to try to write the new value. | 83 | current_value = |
| 84 | static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address))); | ||
| 85 | |||
| 86 | // Compare it to the desired one. | ||
| 87 | if (current_value == value) { | ||
| 88 | // If equal, we want to try to write the new value. | ||
| 89 | |||
| 90 | // Try to store. | ||
| 91 | if (monitor.ExclusiveWrite32(current_core, GetInteger(address), | ||
| 92 | static_cast<u32>(new_value))) { | ||
| 93 | break; | ||
| 94 | } | ||
| 80 | 95 | ||
| 81 | // Try to store. | ||
| 82 | if (!monitor.ExclusiveWrite32(current_core, GetInteger(address), | ||
| 83 | static_cast<u32>(new_value))) { | ||
| 84 | // If we failed to store, try again. | 96 | // If we failed to store, try again. |
| 85 | UpdateIfEqual(system, out, address, value, new_value); | 97 | } else { |
| 98 | // Otherwise, clear our exclusive hold and finish. | ||
| 99 | monitor.ClearExclusive(current_core); | ||
| 100 | break; | ||
| 86 | } | 101 | } |
| 87 | } else { | ||
| 88 | // Otherwise, clear our exclusive hold and finish. | ||
| 89 | monitor.ClearExclusive(current_core); | ||
| 90 | } | 102 | } |
| 91 | 103 | ||
| 92 | // We're done. | 104 | // We're done. |
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 73017cf99..efbac0e6a 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp | |||
| @@ -33,21 +33,26 @@ bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u | |||
| 33 | auto& monitor = system.Monitor(); | 33 | auto& monitor = system.Monitor(); |
| 34 | const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); | 34 | const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); |
| 35 | 35 | ||
| 36 | // Load the value from the address. | 36 | u32 expected{}; |
| 37 | const auto expected = monitor.ExclusiveRead32(current_core, GetInteger(address)); | ||
| 38 | 37 | ||
| 39 | // Orr in the new mask. | 38 | while (true) { |
| 40 | u32 value = expected | new_orr_mask; | 39 | // Load the value from the address. |
| 40 | expected = monitor.ExclusiveRead32(current_core, GetInteger(address)); | ||
| 41 | 41 | ||
| 42 | // If the value is zero, use the if_zero value, otherwise use the newly orr'd value. | 42 | // Orr in the new mask. |
| 43 | if (!expected) { | 43 | u32 value = expected | new_orr_mask; |
| 44 | value = if_zero; | 44 | |
| 45 | } | 45 | // If the value is zero, use the if_zero value, otherwise use the newly orr'd value. |
| 46 | if (!expected) { | ||
| 47 | value = if_zero; | ||
| 48 | } | ||
| 49 | |||
| 50 | // Try to store. | ||
| 51 | if (monitor.ExclusiveWrite32(current_core, GetInteger(address), value)) { | ||
| 52 | break; | ||
| 53 | } | ||
| 46 | 54 | ||
| 47 | // Try to store. | ||
| 48 | if (!monitor.ExclusiveWrite32(current_core, GetInteger(address), value)) { | ||
| 49 | // If we failed to store, try again. | 55 | // If we failed to store, try again. |
| 50 | return UpdateLockAtomic(system, out, address, if_zero, new_orr_mask); | ||
| 51 | } | 56 | } |
| 52 | 57 | ||
| 53 | // We're done. | 58 | // We're done. |