authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-06-21 21:43:11+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-06-26 20:00:57+02:00
log10bf58b2db0e340137228f706ee2e8a67b46a892
tree4bee037f76f15189cf25a819cddf08b5da27274b
parenta97dbdfa0b1246913ba90cd5c05ff633e9003cb9
signaturelock-open Commit is signed but in an unrecognized format.

store allocator & remove global assembly

We now store the original allocator that was used to allocate the memory required for the thread. This allocator can then be used in any cleanup functionality to ensure the memory is freed correctly. Secondly, we now use a function to set the stack pointer instead of generating a function using global assembly. This is a lot cleaner and more readable.

1 files changed, 26 insertions(+), 22 deletions(-)

lib/std/Thread.zig+26-22
......@@ -739,32 +739,24 @@ const PosixThreadImpl = struct {
739739};
740740
741741const WasiThreadImpl = struct {
742 comptime {
743 // Sets the stack pointer, which is needed after creating a new thread
744 // to ensure the stack of the main thread isn't being poluted.
745 asm (
746 \\ .text
747 \\ .export_name __set_stack_pointer, __set_stack_pointer
748 \\ .globaltype __stack_pointer, i32
749 \\ .hidden wasi_thread_start
750 \\ .globl wasi_thread_start
751 \\ .type __set_stack_pointer, @function
752 \\
753 \\ __set_stack_pointer:
754 \\ .functype __set_stack_pointer (i32) -> ()
755 \\ local.get 0 # The raw pointer which replaces the stack pointer
756 \\ global.set __stack_pointer
757 \\ end_function
758 );
759 }
760742 thread: *WasiThread,
761743
762744 pub const ThreadHandle = i32;
763745 threadlocal var tls_thread_id: Id = 0;
764746
765747 const WasiThread = struct {
748 /// Thread ID
766749 tid: Atomic(i32) = Atomic(i32).init(0),
750 /// Contains all memory which was allocated to bootstrap this thread, including:
751 /// - Guard page
752 /// - Stack
753 /// - TLS segment
754 /// - `Instance`
755 /// All memory is freed upon call to `join`
767756 memory: []u8,
757 /// The allocator used to allocate the thread's memory,
758 /// which is also used during `join` to ensure clean-up.
759 allocator: std.mem.Allocator,
768760 };
769761
770762 /// A meta-data structure used to bootstrap a thread
......@@ -790,7 +782,7 @@ const WasiThreadImpl = struct {
790782 }
791783
792784 fn getHandle(self: Impl) ThreadHandle {
793 return self.thread.tid;
785 return self.thread.tid.load(.SeqCst);
794786 }
795787
796788 fn detach(self: Impl) void {
......@@ -813,7 +805,6 @@ const WasiThreadImpl = struct {
813805 }
814806 };
815807
816 var guard_offset: usize = undefined;
817808 var stack_offset: usize = undefined;
818809 var tls_offset: usize = undefined;
819810 var wrapper_offset: usize = undefined;
......@@ -824,8 +815,11 @@ const WasiThreadImpl = struct {
824815 // - The TLS segment
825816 // - `Instance` - containing information about how to call the user's function.
826817 const map_bytes = blk: {
818 // start with atleast a single page, which is used as a guard to prevent
819 // other threads clobbering our new thread.
820 // Unfortunately, WebAssembly has no notion of read-only segments, so this
821 // is only a temporary measure until the entire page is "run over".
827822 var bytes: usize = std.wasm.page_size;
828 guard_offset = bytes;
829823
830824 bytes = std.mem.alignForward(usize, bytes, 16); // align stack to 16 bytes
831825 stack_offset = bytes;
......@@ -855,7 +849,7 @@ const WasiThreadImpl = struct {
855849
856850 const instance = @ptrCast(*Instance, @alignCast(@alignOf(Instance), &allocated_memory[instance_offset]));
857851 instance.* = .{
858 .thread = .{ .memory = allocated_memory },
852 .thread = .{ .memory = allocated_memory, .allocator = config.allocator.? },
859853 .base = @ptrToInt(allocated_memory.ptr),
860854 .tls_base = tls_offset,
861855 .stack_pointer = stack_offset,
......@@ -923,6 +917,16 @@ const WasiThreadImpl = struct {
923917 : [ret] "=r" (-> u32),
924918 );
925919 }
920
921 /// Allows for setting the stack pointer in the WebAssembly module.
922 inline fn __set_stack_pointer(addr: [*]u8) void {
923 asm volatile (
924 \\ local.get %[ptr]
925 \\ global.set __stack_pointer
926 :
927 : [ptr] "r" (addr),
928 );
929 }
926930};
927931
928932const LinuxThreadImpl = struct {