kernel/spinlock: Fix a SMP race condition of SPIN_VALIDATE

z_spin_lock_valid() reads shared variable twice to do two checkings. If
this variable is modified by other CPU between two read accesses, the
checking value is inconsistent. This inconsistency causes the error
that CPU0 can pass the checking when it doesn't hold spinlock because
zeroed-out thread_cpu value is ambiguous with the CPU0 ID.

Fix the inconsistency by only reading shared variable once and using
local variable value to do two checkings.

Fixes #19299.

Signed-off-by: Jim Shu <cwshu@andestech.com>
This commit is contained in:
Jim Shu 2019-09-17 13:39:17 +08:00 committed by Anas Nashif
parent 14c200d022
commit e124670f0b

View file

@ -805,8 +805,10 @@ FUNC_NORETURN void k_thread_user_mode_enter(k_thread_entry_t entry,
#ifdef SPIN_VALIDATE
bool z_spin_lock_valid(struct k_spinlock *l)
{
if (l->thread_cpu) {
if ((l->thread_cpu & 3) == _current_cpu->id) {
uintptr_t thread_cpu = l->thread_cpu;
if (thread_cpu) {
if ((thread_cpu & 3) == _current_cpu->id) {
return false;
}
}