Răsfoiți Sursa

* WebAssembly threads: implement WasiEndThread using exceptions. There's no
other way to end a thread in WebAssembly, except by ending the thread
procedure. Therefore, the only way to implement WasiEndThread is to have it
raise an exception and handle it at the outermost level. This, of course,
requires one of the WebAssembly exception modes to be turned on, in order for
this to work.

Nikolay Nikolov 1 an în urmă
părinte
comite
fcfce9f2d5
1 a modificat fișierele cu 32 adăugiri și 9 ștergeri
  1. 32 9
      rtl/wasi/systhrd.inc

+ 32 - 9
rtl/wasi/systhrd.inc

@@ -63,6 +63,16 @@ Type
     ThreadName : Array of byte; // UTF8 name
     ThreadName : Array of byte; // UTF8 name
   end;
   end;
 
 
+  { EWasmThreadTerminate }
+
+  EWasmThreadTerminate = class(TObject)
+  strict private
+    FExitCode : DWord;
+  public
+    constructor Create(AExitCode: DWord);
+    property ExitCode: DWord read FExitCode;
+  end;
+
 Var
 Var
   MainThread : TWasmThread;
   MainThread : TWasmThread;
   WasiThreadManager : TThreadManager;
   WasiThreadManager : TThreadManager;
@@ -71,6 +81,12 @@ Var
   GlobalIsThreadBlockable : Longint; section 'WebAssembly.Global';
   GlobalIsThreadBlockable : Longint; section 'WebAssembly.Global';
   GlobalCurrentThread : PWasmThread; section 'WebAssembly.Global';
   GlobalCurrentThread : PWasmThread; section 'WebAssembly.Global';
 
 
+{ EWasmThreadTerminate }
+
+constructor EWasmThreadTerminate.Create(AExitCode: DWord);
+begin
+  FExitCode:=AExitCode;
+end;
 
 
 
 
 // Forward functions
 // Forward functions
@@ -341,7 +357,21 @@ begin
   start_arg^.State:=tsRunning;
   start_arg^.State:=tsRunning;
   InitThread(start_arg^.StackSize);
   InitThread(start_arg^.StackSize);
   StackBottom:=start_arg^.StackBlock;
   StackBottom:=start_arg^.StackBlock;
-  start_arg^.ExitCode:=Cardinal(start_arg^.ThreadFunction(start_arg^.ThreadFunctionArg));
+  try
+    start_arg^.ExitCode:=Cardinal(start_arg^.ThreadFunction(start_arg^.ThreadFunctionArg));
+  except
+    on e: EWasmThreadTerminate do
+      begin
+        {$IFDEF DEBUGWASMTHREADS}DebugWriteln('FPCWasmThreadStartPascal: Caught EWasmThreadTerminate with ExitCode='+IntToStr(e.ExitCode));{$ENDIF}
+        start_arg^.ExitCode:=e.ExitCode;
+      end;
+    else
+      begin
+        {$IFDEF DEBUGWASMTHREADS}DebugWriteln('FPCWasmThreadStartPascal: Uncaught exception');{$ENDIF}
+        { TODO: what should we return here? }
+        start_arg^.ExitCode:=High(Cardinal);
+      end;
+  end;
   {$IFDEF DEBUGWASMTHREADS}DebugWriteln('FPCWasmThreadStartPascal: Signaling end of thread');{$ENDIF}
   {$IFDEF DEBUGWASMTHREADS}DebugWriteln('FPCWasmThreadStartPascal: Signaling end of thread');{$ENDIF}
   WasiRTLEventSetEvent(start_arg^.DoneEvent);
   WasiRTLEventSetEvent(start_arg^.DoneEvent);
 end;
 end;
@@ -418,14 +448,7 @@ Var
   T : PWasmThread;
   T : PWasmThread;
 begin
 begin
   {$IFDEF DEBUGWASMTHREADS}DebugWriteln('EndThread('+IntToStr(ExitCode)+')');{$ENDIF}
   {$IFDEF DEBUGWASMTHREADS}DebugWriteln('EndThread('+IntToStr(ExitCode)+')');{$ENDIF}
-  T:=PWasmThread(GetSelfThread);
-  T^.ExitCode:=ExitCode;
-  // Signal that we're done
-  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('EndThread: Signaling end of thread');{$ENDIF}
-  WasiRTLEventSetEvent(T^.DoneEvent);
-  {$IFDEF DEBUGWASMTHREADS}DebugWriteln('EndThread: Unlocking mutex');{$ENDIF}
-  // Now unlock running mutex
-  UnlockMutex(T^.Running);
+  raise EWasmThreadTerminate.Create(ExitCode);
 end;
 end;
 
 
 function WasiSuspendThread(threadHandle : TThreadID) : dword;
 function WasiSuspendThread(threadHandle : TThreadID) : dword;