Browse Source

* WebAssembly threads: simplified (optimized) the implementation of
TWasmRTLEvent, so it doesn't use a Mutex. Use atomic operations instead.

Nikolay Nikolov 1 year ago
parent
commit
a417b0db9b
1 changed files with 13 additions and 25 deletions
  1. 13 25
      rtl/wasi/systhrd.inc

+ 13 - 25
rtl/wasi/systhrd.inc

@@ -43,7 +43,6 @@ Type
   PWasmRTLEvent = ^TWasmRTLEvent;
   PWasmRTLEvent = ^TWasmRTLEvent;
   TWasmRTLEvent = record
   TWasmRTLEvent = record
     Signal : Longint;
     Signal : Longint;
-    mutex: TWasmMutex;
     Destroying : Boolean;
     Destroying : Boolean;
   end;
   end;
 
 
@@ -179,9 +178,8 @@ Var
 
 
 begin
 begin
   New(P);
   New(P);
-  P^.Signal:=0;
-  P^.Destroying:=False;
-  InitMutex(P^.Mutex);
+  fpc_wasm32_i32_atomic_store(@P^.Signal,0);
+  fpc_wasm32_i32_atomic_store8(@P^.Destroying,0);
   Result:=P;
   Result:=P;
 end;
 end;
 
 
@@ -192,12 +190,9 @@ Var
   a : longint;
   a : longint;
 
 
 begin
 begin
-  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventSetEvent : locking mutex');{$ENDIF}
-  LockMutex(P^.Mutex);
-  P^.Signal:=1;
-  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventSetEvent : unlocking mutex');{$ENDIF}
-  UnLockMutex(P^.Mutex);
-  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventSetEvent : send signal');{$ENDIF}
+  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventSetEvent : setting signal=1');{$ENDIF}
+  fpc_wasm32_i32_atomic_store(@P^.Signal,1);
+  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventSetEvent : notifying waiting threads');{$ENDIF}
   a:=fpc_wasm32_memory_atomic_notify(@(P^.Signal),MaxThreadSignal);
   a:=fpc_wasm32_memory_atomic_notify(@(P^.Signal),MaxThreadSignal);
 end;
 end;
 
 
@@ -207,14 +202,12 @@ Var
   P : PWasmRTLEvent absolute aEvent;
   P : PWasmRTLEvent absolute aEvent;
 
 
 begin
 begin
-  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventDestroy : locking mutex');{$ENDIF}
-  LockMutex(P^.Mutex);
-  P^.Destroying:=True;
-  UnlockMutex(P^.Mutex);
+  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventDestroy : setting destroying to true');{$ENDIF}
+  fpc_wasm32_i32_atomic_store8(@P^.Destroying,1);
   {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventDestroy : setting event to notify others');{$ENDIF}
   {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventDestroy : setting event to notify others');{$ENDIF}
   WasiRTLEventSetEvent(aEvent);
   WasiRTLEventSetEvent(aEvent);
-  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventDestroy : set event to notify others');{$ENDIF}
-  FreeMem(P);
+  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventDestroy : freeing memory');{$ENDIF}
+  Dispose(P);
 end;
 end;
 
 
 
 
@@ -224,11 +217,8 @@ Var
   P : PWasmRTLEvent absolute aEvent;
   P : PWasmRTLEvent absolute aEvent;
 
 
 begin
 begin
-  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventResetEvent : locking mutex');{$ENDIF}
-  LockMutex(P^.Mutex);
-  P^.Signal:=0;
-  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventResetEvent : unlocking mutex');{$ENDIF}
-  UnLockMutex(P^.Mutex);
+  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventResetEvent : setting signal=0');{$ENDIF}
+  fpc_wasm32_i32_atomic_store(@P^.Signal,0);
 end;
 end;
 
 
 procedure WasiRTLEventWaitFor_WaitAllowed(AEvent:PWasmRTLEvent; aTimeoutNs : Int64);
 procedure WasiRTLEventWaitFor_WaitAllowed(AEvent:PWasmRTLEvent; aTimeoutNs : Int64);
@@ -249,18 +239,16 @@ Var
   EndTime : Int64;
   EndTime : Int64;
   IsTimeOut : Boolean;
   IsTimeOut : Boolean;
   IsDone : Boolean;
   IsDone : Boolean;
-  isMain : Boolean;
 
 
 begin
 begin
-  IsMain:=GlobalIsMainThread<>0;
-  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventWaitFor_WaitNotAllowed : waiting (is main: '+intToStr(Ord(IsMain))+')');{$ENDIF}
+  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventWaitFor_WaitNotAllowed : waiting');{$ENDIF}
   if aTimeoutNs>=0 then
   if aTimeoutNs>=0 then
     EndTime:=GetClockTime+aTimeoutNs
     EndTime:=GetClockTime+aTimeoutNs
   else
   else
     EndTime:=0;
     EndTime:=0;
   Repeat
   Repeat
     IsTimeOut:=(aTimeoutNs>=0) and (GetClockTime>EndTime);
     IsTimeOut:=(aTimeoutNs>=0) and (GetClockTime>EndTime);
-    IsDone:=(aEvent^.Signal=1) or (aEvent^.Destroying) or (Not IsMain and (GetThreadState(GetSelfThread)<>tsRunning));
+    IsDone:=(fpc_wasm32_i32_atomic_load(@aEvent^.Signal)=1) or (fpc_wasm32_i32_atomic_load8_u(@aEvent^.Destroying)<>0);
   Until isTimeOut or IsDone;
   Until isTimeOut or IsDone;
   {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventWaitFor_WaitNotAllowed : done waiting (isTimeout='+intToStr(Ord(isTimeOut))+',IsDone='+intToStr(Ord(IsDone))+
   {$IFDEF DEBUGWASMTHREADS}DebugWriteln('WasiRTLEventWaitFor_WaitNotAllowed : done waiting (isTimeout='+intToStr(Ord(isTimeOut))+',IsDone='+intToStr(Ord(IsDone))+
                                         ',Signal='+IntToStr(aEvent^.Signal)+',Destroying='+IntToStr(Ord(aEvent^.Destroying))+')');{$ENDIF}
                                         ',Signal='+IntToStr(aEvent^.Signal)+',Destroying='+IntToStr(Ord(aEvent^.Destroying))+')');{$ENDIF}