From 41ead20bfb32f03c1b36bd4e98bdcb569345dba1 Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov Date: Sat, 3 Aug 2024 02:34:00 +0300 Subject: [PATCH] * WebAssembly threads: fixed race condition LockMutex in the check where Locked is 1, but Owner still holds the current thread id, even though another thread has just acquired a lock, but still haven't updated the owner thread ID. We avoid this problem by setting Owner to nil before unlocking the mutex. And in InitMutex/DoneMutex, we store the creator thread ID in a different field - Creator, instead of Owner. --- rtl/wasi/sysosh.inc | 3 ++- rtl/wasi/wasmmutex.inc | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/rtl/wasi/sysosh.inc b/rtl/wasi/sysosh.inc index 1b7395daec..23af0955fc 100644 --- a/rtl/wasi/sysosh.inc +++ b/rtl/wasi/sysosh.inc @@ -27,6 +27,7 @@ type Count: LongInt; // Number of times locked. Waiters : LongInt; // Number of waiters Kind : LongInt; // Kind of mutex, Equals Ord(TMutexKind) - Owner : TThreadID; // Owner thread + Owner : TThreadID; // Owner thread (who holds the lock) + Creator : TThreadID; // Creator thread Destroying : Boolean; // Set when notifying that we're destroying the mutex. end; diff --git a/rtl/wasi/wasmmutex.inc b/rtl/wasi/wasmmutex.inc index fab110b9d0..97f62d0e77 100644 --- a/rtl/wasi/wasmmutex.inc +++ b/rtl/wasi/wasmmutex.inc @@ -20,7 +20,7 @@ begin FillChar(M,SizeOf(TWasmMutex),0); if aOwner=Nil then aOwner:=GetSelfThread; - M.Owner:=aOwner; + M.Creator:=aOwner; M.Kind:=Ord(aKind); end; @@ -30,7 +30,7 @@ Var a : LongInt; begin - if (M.Locked>0) and (M.Owner=GetSelfThread) then + if (M.Locked>0) and (M.Creator=GetSelfThread) then begin M.Destroying:=True; a:=fpc_wasm32_memory_atomic_notify(@M.Locked,MaxThreadSignal); @@ -190,6 +190,7 @@ begin InterLockedDecrement(M.Count); if (M.Count=0) then begin + M.Owner:=nil; M.Locked:=0; a:=fpc_wasm32_memory_atomic_notify(@M.Locked,1); end;