| ... | @@ -819,7 +819,7 @@ const WasiThreadImpl = struct { | ... | @@ -819,7 +819,7 @@ const WasiThreadImpl = struct { |
| 819 | \\ memory.atomic.wait32 0 | 819 | \\ memory.atomic.wait32 0 |
| 820 | \\ local.set %[ret] | 820 | \\ local.set %[ret] |
| 821 | : [ret] "=r" (-> u32), | 821 | : [ret] "=r" (-> u32), |
| 822 | : [ptr] "r" (&self.thread.tid.value), | 822 | : [ptr] "r" (&self.thread.tid.raw), |
| 823 | [expected] "r" (tid), | 823 | [expected] "r" (tid), |
| 824 | ); | 824 | ); |
| 825 | switch (result) { | 825 | switch (result) { |
| ... | @@ -831,15 +831,42 @@ const WasiThreadImpl = struct { | ... | @@ -831,15 +831,42 @@ const WasiThreadImpl = struct { |
| 831 | } | 831 | } |
| 832 | } | 832 | } |
| 833 | | 833 | |
| 834 | fn spawn(config: std.Thread.SpawnConfig, comptime f: anytype, args: anytype) !WasiThreadImpl { | 834 | fn spawn(config: std.Thread.SpawnConfig, comptime f: anytype, args: anytype) SpawnError!WasiThreadImpl { |
| 835 | if (config.allocator == null) return error.OutOfMemory; // an allocator is required to spawn a WASI-thread | 835 | if (config.allocator == null) { |
| | 836 | @panic("an allocator is required to spawn a WASI thread"); |
| | 837 | } |
| 836 | | 838 | |
| 837 | // Wrapping struct required to hold the user-provided function arguments. | 839 | // Wrapping struct required to hold the user-provided function arguments. |
| 838 | const Wrapper = struct { | 840 | const Wrapper = struct { |
| 839 | args: @TypeOf(args), | 841 | args: @TypeOf(args), |
| 840 | fn entry(ptr: usize) void { | 842 | fn entry(ptr: usize) void { |
| 841 | const w: *@This() = @ptrFromInt(ptr); | 843 | const w: *@This() = @ptrFromInt(ptr); |
| 842 | @call(.auto, f, w.args); | 844 | const bad_fn_ret = "expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"; |
| | 845 | switch (@typeInfo(@typeInfo(@TypeOf(f)).Fn.return_type.?)) { |
| | 846 | .NoReturn, .Void => { |
| | 847 | @call(.auto, w, args); |
| | 848 | }, |
| | 849 | .Int => |info| { |
| | 850 | if (info.bits != 8) { |
| | 851 | @compileError(bad_fn_ret); |
| | 852 | } |
| | 853 | _ = @call(.auto, w, args); // WASI threads don't support exit status, ignore value |
| | 854 | }, |
| | 855 | .ErrorUnion => |info| { |
| | 856 | if (info.payload != void) { |
| | 857 | @compileError(bad_fn_ret); |
| | 858 | } |
| | 859 | @call(.auto, f, args) catch |err| { |
| | 860 | std.debug.print("error: {s}\n", .{@errorName(err)}); |
| | 861 | if (@errorReturnTrace()) |trace| { |
| | 862 | std.debug.dumpStackTrace(trace.*); |
| | 863 | } |
| | 864 | }; |
| | 865 | }, |
| | 866 | else => { |
| | 867 | @compileError(bad_fn_ret); |
| | 868 | }, |
| | 869 | } |
| 843 | } | 870 | } |
| 844 | }; | 871 | }; |
| 845 | | 872 | |
| ... | @@ -927,7 +954,7 @@ const WasiThreadImpl = struct { | ... | @@ -927,7 +954,7 @@ const WasiThreadImpl = struct { |
| 927 | \\ i32.const 0 | 954 | \\ i32.const 0 |
| 928 | \\ i32.atomic.store 0 | 955 | \\ i32.atomic.store 0 |
| 929 | : | 956 | : |
| 930 | : [ptr] "r" (&arg.thread.tid.value), | 957 | : [ptr] "r" (&arg.thread.tid.raw), |
| 931 | ); | 958 | ); |
| 932 | | 959 | |
| 933 | // Wake the main thread listening to this thread | 960 | // Wake the main thread listening to this thread |
| ... | @@ -937,7 +964,7 @@ const WasiThreadImpl = struct { | ... | @@ -937,7 +964,7 @@ const WasiThreadImpl = struct { |
| 937 | \\ memory.atomic.notify 0 | 964 | \\ memory.atomic.notify 0 |
| 938 | \\ drop # no need to know the waiters | 965 | \\ drop # no need to know the waiters |
| 939 | : | 966 | : |
| 940 | : [ptr] "r" (&arg.thread.tid.value), | 967 | : [ptr] "r" (&arg.thread.tid.raw), |
| 941 | ); | 968 | ); |
| 942 | }, | 969 | }, |
| 943 | .completed => unreachable, | 970 | .completed => unreachable, |