Browse Source

kernel: barrier memory before condition variable write

pull/15/merge
Liam 3 years ago
parent
commit
367e89f984
  1. 18
      src/core/hle/kernel/k_condition_variable.cpp

18
src/core/hle/kernel/k_condition_variable.cpp

@ -112,7 +112,7 @@ Result KConditionVariable::SignalToAddress(VAddr addr) {
// Remove waiter thread. // Remove waiter thread.
s32 num_waiters{}; s32 num_waiters{};
KThread* next_owner_thread =
KThread* const next_owner_thread =
owner_thread->RemoveWaiterByKey(std::addressof(num_waiters), addr); owner_thread->RemoveWaiterByKey(std::addressof(num_waiters), addr);
// Determine the next tag. // Determine the next tag.
@ -122,6 +122,10 @@ Result KConditionVariable::SignalToAddress(VAddr addr) {
if (num_waiters > 1) { if (num_waiters > 1) {
next_value |= Svc::HandleWaitMask; next_value |= Svc::HandleWaitMask;
} }
}
// Synchronize memory before proceeding.
std::atomic_thread_fence(std::memory_order_seq_cst);
// Write the value to userspace. // Write the value to userspace.
Result result{ResultSuccess}; Result result{ResultSuccess};
@ -131,16 +135,12 @@ Result KConditionVariable::SignalToAddress(VAddr addr) {
result = ResultInvalidCurrentMemory; result = ResultInvalidCurrentMemory;
} }
// Signal the next owner thread.
// If necessary, signal the next owner thread.
if (next_owner_thread != nullptr) {
next_owner_thread->EndWait(result); next_owner_thread->EndWait(result);
return result;
} else {
// Just write the value to userspace.
R_UNLESS(WriteToUser(system, addr, std::addressof(next_value)),
ResultInvalidCurrentMemory);
return ResultSuccess;
} }
R_RETURN(result);
} }
} }

Loading…
Cancel
Save