diff options
| author | Luuk de Gram <luuk@degram.dev> | 2023-06-21 21:43:11 +0200 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2023-06-26 20:00:57 +0200 |
| commit | 10bf58b2db0e340137228f706ee2e8a67b46a892 (patch) | |
| tree | 4bee037f76f15189cf25a819cddf08b5da27274b /lib/std/Thread.zig | |
| parent | a97dbdfa0b1246913ba90cd5c05ff633e9003cb9 (diff) | |
| download | zig-10bf58b2db0e340137228f706ee2e8a67b46a892.tar.gz zig-10bf58b2db0e340137228f706ee2e8a67b46a892.zip | |
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.
Diffstat (limited to 'lib/std/Thread.zig')
| -rw-r--r-- | lib/std/Thread.zig | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index e7edc17a35..04531f97bc 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -739,32 +739,24 @@ const PosixThreadImpl = struct { }; const WasiThreadImpl = struct { - comptime { - // Sets the stack pointer, which is needed after creating a new thread - // to ensure the stack of the main thread isn't being poluted. - asm ( - \\ .text - \\ .export_name __set_stack_pointer, __set_stack_pointer - \\ .globaltype __stack_pointer, i32 - \\ .hidden wasi_thread_start - \\ .globl wasi_thread_start - \\ .type __set_stack_pointer, @function - \\ - \\ __set_stack_pointer: - \\ .functype __set_stack_pointer (i32) -> () - \\ local.get 0 # The raw pointer which replaces the stack pointer - \\ global.set __stack_pointer - \\ end_function - ); - } thread: *WasiThread, pub const ThreadHandle = i32; threadlocal var tls_thread_id: Id = 0; const WasiThread = struct { + /// Thread ID tid: Atomic(i32) = Atomic(i32).init(0), + /// Contains all memory which was allocated to bootstrap this thread, including: + /// - Guard page + /// - Stack + /// - TLS segment + /// - `Instance` + /// All memory is freed upon call to `join` memory: []u8, + /// The allocator used to allocate the thread's memory, + /// which is also used during `join` to ensure clean-up. + allocator: std.mem.Allocator, }; /// A meta-data structure used to bootstrap a thread @@ -790,7 +782,7 @@ const WasiThreadImpl = struct { } fn getHandle(self: Impl) ThreadHandle { - return self.thread.tid; + return self.thread.tid.load(.SeqCst); } fn detach(self: Impl) void { @@ -813,7 +805,6 @@ const WasiThreadImpl = struct { } }; - var guard_offset: usize = undefined; var stack_offset: usize = undefined; var tls_offset: usize = undefined; var wrapper_offset: usize = undefined; @@ -824,8 +815,11 @@ const WasiThreadImpl = struct { // - The TLS segment // - `Instance` - containing information about how to call the user's function. const map_bytes = blk: { + // start with atleast a single page, which is used as a guard to prevent + // other threads clobbering our new thread. + // Unfortunately, WebAssembly has no notion of read-only segments, so this + // is only a temporary measure until the entire page is "run over". var bytes: usize = std.wasm.page_size; - guard_offset = bytes; bytes = std.mem.alignForward(usize, bytes, 16); // align stack to 16 bytes stack_offset = bytes; @@ -855,7 +849,7 @@ const WasiThreadImpl = struct { const instance = @ptrCast(*Instance, @alignCast(@alignOf(Instance), &allocated_memory[instance_offset])); instance.* = .{ - .thread = .{ .memory = allocated_memory }, + .thread = .{ .memory = allocated_memory, .allocator = config.allocator.? }, .base = @ptrToInt(allocated_memory.ptr), .tls_base = tls_offset, .stack_pointer = stack_offset, @@ -923,6 +917,16 @@ const WasiThreadImpl = struct { : [ret] "=r" (-> u32), ); } + + /// Allows for setting the stack pointer in the WebAssembly module. + inline fn __set_stack_pointer(addr: [*]u8) void { + asm volatile ( + \\ local.get %[ptr] + \\ global.set __stack_pointer + : + : [ptr] "r" (addr), + ); + } }; const LinuxThreadImpl = struct { |
