aboutsummaryrefslogtreecommitdiff
path: root/lib/std/Thread.zig
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2023-06-21 21:43:11 +0200
committerLuuk de Gram <luuk@degram.dev>2023-06-26 20:00:57 +0200
commit10bf58b2db0e340137228f706ee2e8a67b46a892 (patch)
tree4bee037f76f15189cf25a819cddf08b5da27274b /lib/std/Thread.zig
parenta97dbdfa0b1246913ba90cd5c05ff633e9003cb9 (diff)
downloadzig-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.zig48
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 {