summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2023-04-01 01:54:36 -0700
committerGravatar GitHub2023-04-01 01:54:36 -0700
commit0730dc6c44d8b589efeb80d974650c72ba44c4f7 (patch)
tree90ebabf2585fef813efec5e3f751dc9914407416 /src
parentMerge pull request #10010 from maxdunbar/typo (diff)
parentkernel: fix unbounded stack usage in atomics (diff)
downloadyuzu-0730dc6c44d8b589efeb80d974650c72ba44c4f7.tar.gz
yuzu-0730dc6c44d8b589efeb80d974650c72ba44c4f7.tar.xz
yuzu-0730dc6c44d8b589efeb80d974650c72ba44c4f7.zip
Merge pull request #10005 from liamwhite/kernel-atomics
kernel: fix unbounded stack usage in atomics
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp68
-rw-r--r--src/core/hle/kernel/k_condition_variable.cpp27
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.