Commit c470016743

Frank Denis <github@pureftpd.org>
2024-03-18 00:39:32
Unbreak support for WASI threads
1 parent 8e7d9af
Changed files (1)
lib
lib/std/Thread.zig
@@ -324,6 +324,9 @@ pub const SpawnError = error{
     /// would exceed the limit.
     LockedMemoryLimitExceeded,
 
+    /// An allocator is required to spawn a thread
+    AllocatorRequired,
+
     Unexpected,
 };
 
@@ -819,7 +822,7 @@ const WasiThreadImpl = struct {
                 \\ memory.atomic.wait32 0
                 \\ local.set %[ret]
                 : [ret] "=r" (-> u32),
-                : [ptr] "r" (&self.thread.tid.value),
+                : [ptr] "r" (&self.thread.tid.raw),
                   [expected] "r" (tid),
             );
             switch (result) {
@@ -831,15 +834,42 @@ const WasiThreadImpl = struct {
         }
     }
 
-    fn spawn(config: std.Thread.SpawnConfig, comptime f: anytype, args: anytype) !WasiThreadImpl {
-        if (config.allocator == null) return error.OutOfMemory; // an allocator is required to spawn a WASI-thread
+    fn spawn(config: std.Thread.SpawnConfig, comptime f: anytype, args: anytype) SpawnError!WasiThreadImpl {
+        if (config.allocator == null) {
+            return error.AllocatorRequired; // an allocator is required to spawn a WASI thread
+        }
 
         // Wrapping struct required to hold the user-provided function arguments.
         const Wrapper = struct {
             args: @TypeOf(args),
             fn entry(ptr: usize) void {
                 const w: *@This() = @ptrFromInt(ptr);
-                @call(.auto, f, w.args);
+                const bad_fn_ret = "expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'";
+                switch (@typeInfo(@typeInfo(@TypeOf(f)).Fn.return_type.?)) {
+                    .NoReturn, .Void => {
+                        @call(.auto, w, args);
+                    },
+                    .Int => |info| {
+                        if (info.bits != 8) {
+                            @compileError(bad_fn_ret);
+                        }
+                        _ = @call(.auto, w, args); // WASI threads don't support exit status, ignore value
+                    },
+                    .ErrorUnion => |info| {
+                        if (info.payload != void) {
+                            @compileError(bad_fn_ret);
+                        }
+                        @call(.auto, f, args) catch |err| {
+                            std.debug.print("error: {s}\n", .{@errorName(err)});
+                            if (@errorReturnTrace()) |trace| {
+                                std.debug.dumpStackTrace(trace.*);
+                            }
+                        };
+                    },
+                    else => {
+                        @compileError(bad_fn_ret);
+                    },
+                }
             }
         };
 
@@ -927,7 +957,7 @@ const WasiThreadImpl = struct {
                     \\ i32.const 0
                     \\ i32.atomic.store 0
                     :
-                    : [ptr] "r" (&arg.thread.tid.value),
+                    : [ptr] "r" (&arg.thread.tid.raw),
                 );
 
                 // Wake the main thread listening to this thread
@@ -937,7 +967,7 @@ const WasiThreadImpl = struct {
                     \\ memory.atomic.notify 0
                     \\ drop # no need to know the waiters
                     :
-                    : [ptr] "r" (&arg.thread.tid.value),
+                    : [ptr] "r" (&arg.thread.tid.raw),
                 );
             },
             .completed => unreachable,