Merge pull request #10005 from liamwhite/kernel-atomics

kernel: fix unbounded stack usage in atomics
This commit is contained in:
bunnei 2023-04-01 01:54:36 -07:00 committed by GitHub
commit 0730dc6c44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 37 deletions

View file

@ -35,8 +35,11 @@ bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address
// TODO(bunnei): We should call CanAccessAtomic(..) here.
s32 current_value{};
while (true) {
// Load the value from the address.
const s32 current_value =
current_value =
static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address)));
// Compare it to the desired one.
@ -45,14 +48,17 @@ bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address
const s32 decrement_value = current_value - 1;
// Decrement and try to store.
if (!monitor.ExclusiveWrite32(current_core, GetInteger(address),
if (monitor.ExclusiveWrite32(current_core, GetInteger(address),
static_cast<u32>(decrement_value))) {
// If we failed to store, try again.
DecrementIfLessThan(system, out, address, value);
break;
}
// If we failed to store, try again.
} else {
// Otherwise, clear our exclusive hold and finish
monitor.ClearExclusive(current_core);
break;
}
}
// We're done.
@ -70,8 +76,11 @@ bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32
// TODO(bunnei): We should call CanAccessAtomic(..) here.
s32 current_value{};
// Load the value from the address.
const s32 current_value =
while (true) {
current_value =
static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address)));
// Compare it to the desired one.
@ -79,14 +88,17 @@ bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32
// If equal, we want to try to write the new value.
// Try to store.
if (!monitor.ExclusiveWrite32(current_core, GetInteger(address),
if (monitor.ExclusiveWrite32(current_core, GetInteger(address),
static_cast<u32>(new_value))) {
// If we failed to store, try again.
UpdateIfEqual(system, out, address, value, new_value);
break;
}
// If we failed to store, try again.
} else {
// Otherwise, clear our exclusive hold and finish.
monitor.ClearExclusive(current_core);
break;
}
}
// We're done.

View file

@ -33,8 +33,11 @@ bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u
auto& monitor = system.Monitor();
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
u32 expected{};
while (true) {
// Load the value from the address.
const auto expected = monitor.ExclusiveRead32(current_core, GetInteger(address));
expected = monitor.ExclusiveRead32(current_core, GetInteger(address));
// Orr in the new mask.
u32 value = expected | new_orr_mask;
@ -45,9 +48,11 @@ bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u
}
// Try to store.
if (!monitor.ExclusiveWrite32(current_core, GetInteger(address), value)) {
if (monitor.ExclusiveWrite32(current_core, GetInteger(address), value)) {
break;
}
// If we failed to store, try again.
return UpdateLockAtomic(system, out, address, if_zero, new_orr_mask);
}
// We're done.