| ... | @@ -762,13 +762,13 @@ const WasiThreadImpl = struct { | ... | @@ -762,13 +762,13 @@ const WasiThreadImpl = struct { |
| 762 | /// A meta-data structure used to bootstrap a thread | 762 | /// A meta-data structure used to bootstrap a thread |
| 763 | const Instance = struct { | 763 | const Instance = struct { |
| 764 | thread: WasiThread, | 764 | thread: WasiThread, |
| 765 | /// Address of this `Instance` | 765 | /// Contains the offset to the new __tls_base. |
| 766 | base: usize, | 766 | /// The offset starting from the memory's base. |
| 767 | /// Contains the pointer of the new __tls_base. | 767 | tls_offset: usize, |
| 768 | tls_base: usize, | 768 | /// Contains the offset to the stack for the newly spawned thread. |
| 769 | /// Contains the pointer to the stack for the newly spawned thread. | 769 | /// The offset is calculated starting from the memory's base. |
| 770 | stack_pointer: usize, | 770 | stack_offset: usize, |
| 771 | /// Contains the pointer to the wrapper which holds all arguments | 771 | /// Contains the raw pointer value to the wrapper which holds all arguments |
| 772 | /// for the callback. | 772 | /// for the callback. |
| 773 | raw_ptr: usize, | 773 | raw_ptr: usize, |
| 774 | /// Function pointer to a wrapping function which will call the user's | 774 | /// Function pointer to a wrapping function which will call the user's |
| ... | @@ -790,9 +790,12 @@ const WasiThreadImpl = struct { | ... | @@ -790,9 +790,12 @@ const WasiThreadImpl = struct { |
| 790 | } | 790 | } |
| 791 | | 791 | |
| 792 | fn join(self: Impl) void { | 792 | fn join(self: Impl) void { |
| 793 | // TODO cleanup memory | 793 | defer { |
| 794 | // The memory also contains the thread's stack, which is problematic while freeing the memory | 794 | // Create a copy of the allocator so we do not free the reference to the |
| 795 | // defer self.thread.allocator.free(self.thread.memory); | 795 | // original allocator while freeing the memory. |
| | 796 | var allocator = self.thread.allocator; |
| | 797 | allocator.free(self.thread.memory); |
| | 798 | } |
| 796 | | 799 | |
| 797 | var spin: u8 = 10; | 800 | var spin: u8 = 10; |
| 798 | while (true) { | 801 | while (true) { |
| ... | @@ -808,11 +811,11 @@ const WasiThreadImpl = struct { | ... | @@ -808,11 +811,11 @@ const WasiThreadImpl = struct { |
| 808 | } | 811 | } |
| 809 | | 812 | |
| 810 | const result = asm ( | 813 | const result = asm ( |
| 811 | \\local.get %[ptr] | 814 | \\ local.get %[ptr] |
| 812 | \\local.get %[expected] | 815 | \\ local.get %[expected] |
| 813 | \\i64.const -1 # infinite | 816 | \\ i64.const -1 # infinite |
| 814 | \\memory.atomic.wait32 0 | 817 | \\ memory.atomic.wait32 0 |
| 815 | \\local.set %[ret] | 818 | \\ local.set %[ret] |
| 816 | : [ret] "=r" (-> u32), | 819 | : [ret] "=r" (-> u32), |
| 817 | : [ptr] "r" (&self.thread.tid.value), | 820 | : [ptr] "r" (&self.thread.tid.value), |
| 818 | [expected] "r" (tid), | 821 | [expected] "r" (tid), |
| ... | @@ -883,9 +886,8 @@ const WasiThreadImpl = struct { | ... | @@ -883,9 +886,8 @@ const WasiThreadImpl = struct { |
| 883 | const instance = @ptrCast(*Instance, @alignCast(@alignOf(Instance), &allocated_memory[instance_offset])); | 886 | const instance = @ptrCast(*Instance, @alignCast(@alignOf(Instance), &allocated_memory[instance_offset])); |
| 884 | instance.* = .{ | 887 | instance.* = .{ |
| 885 | .thread = .{ .memory = allocated_memory, .allocator = config.allocator.? }, | 888 | .thread = .{ .memory = allocated_memory, .allocator = config.allocator.? }, |
| 886 | .base = @ptrToInt(allocated_memory.ptr), | 889 | .tls_offset = tls_offset, |
| 887 | .tls_base = tls_offset, | 890 | .stack_offset = stack_offset, |
| 888 | .stack_pointer = stack_offset, | | |
| 889 | .raw_ptr = @ptrToInt(wrapper), | 891 | .raw_ptr = @ptrToInt(wrapper), |
| 890 | .call_back = &Wrapper.entry, | 892 | .call_back = &Wrapper.entry, |
| 891 | }; | 893 | }; |
| ... | @@ -903,8 +905,8 @@ const WasiThreadImpl = struct { | ... | @@ -903,8 +905,8 @@ const WasiThreadImpl = struct { |
| 903 | | 905 | |
| 904 | /// Bootstrap procedure, called by the HOST environment after thread creation. | 906 | /// Bootstrap procedure, called by the HOST environment after thread creation. |
| 905 | export fn wasi_thread_start(tid: i32, arg: *Instance) void { | 907 | export fn wasi_thread_start(tid: i32, arg: *Instance) void { |
| 906 | __set_stack_pointer(arg.thread.memory.ptr + arg.stack_pointer); | 908 | __set_stack_pointer(arg.thread.memory.ptr + arg.stack_offset); |
| 907 | __wasm_init_tls(arg.thread.memory.ptr + arg.tls_base); | 909 | __wasm_init_tls(arg.thread.memory.ptr + arg.tls_offset); |
| 908 | WasiThreadImpl.tls_thread_id = @intCast(u32, tid); | 910 | WasiThreadImpl.tls_thread_id = @intCast(u32, tid); |
| 909 | | 911 | |
| 910 | // Finished bootstrapping, call user's procedure. | 912 | // Finished bootstrapping, call user's procedure. |