| ... | ... | @@ -150,7 +150,7 @@ const Completion = Atomic(enum(u8) { |
| 150 | 150 | |
| 151 | 151 | /// Used by the Thread implementations to call the spawned function with the arguments. |
| 152 | 152 | fn callFn(comptime f: anytype, args: anytype) switch (Impl) { |
| 153 | | WindowsThreadImpl => windows.DWORD, |
| 153 | WindowsThreadImpl => std.os.windows.DWORD, |
| 154 | 154 | LinuxThreadImpl => u8, |
| 155 | 155 | PosixThreadImpl => ?*c_void, |
| 156 | 156 | else => unreachable, |
| ... | ... | @@ -223,7 +223,7 @@ const WindowsThreadImpl = struct { |
| 223 | 223 | |
| 224 | 224 | fn free(self: ThreadCompletion) void { |
| 225 | 225 | const status = windows.kernel32.HeapFree(self.heap_handle, 0, self.heap_ptr); |
| 226 | | assert(status == 0); |
| 226 | assert(status != 0); |
| 227 | 227 | } |
| 228 | 228 | }; |
| 229 | 229 | |
| ... | ... | @@ -233,9 +233,9 @@ const WindowsThreadImpl = struct { |
| 233 | 233 | fn_args: Args, |
| 234 | 234 | thread: ThreadCompletion, |
| 235 | 235 | |
| 236 | | fn entryFn(raw_ptr: *windows.PVOID) callconv(.C) windows.DWORD { |
| 236 | fn entryFn(raw_ptr: windows.PVOID) callconv(.C) windows.DWORD { |
| 237 | 237 | const self = @ptrCast(*@This(), @alignCast(@alignOf(@This()), raw_ptr)); |
| 238 | | defer switch (self.thread.completion.swap(.completed, .Acquire)) { |
| 238 | defer switch (self.thread.completion.swap(.completed, .SeqCst)) { |
| 239 | 239 | .running => {}, |
| 240 | 240 | .completed => unreachable, |
| 241 | 241 | .detached => self.thread.free(), |
| ... | ... | @@ -269,7 +269,7 @@ const WindowsThreadImpl = struct { |
| 269 | 269 | instance.thread.thread_handle = windows.kernel32.CreateThread( |
| 270 | 270 | null, |
| 271 | 271 | stack_size, |
| 272 | | Instance.entry, |
| 272 | Instance.entryFn, |
| 273 | 273 | @ptrCast(*c_void, instance), |
| 274 | 274 | 0, |
| 275 | 275 | null, |
| ... | ... | @@ -277,7 +277,7 @@ const WindowsThreadImpl = struct { |
| 277 | 277 | return windows.unexpectedError(windows.kernel32.GetLastError()); |
| 278 | 278 | }; |
| 279 | 279 | |
| 280 | | return .{ .thread = &instance.thread }; |
| 280 | return Impl{ .thread = &instance.thread }; |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | 283 | fn getHandle(self: Impl) ThreadHandle { |
| ... | ... | @@ -286,7 +286,7 @@ const WindowsThreadImpl = struct { |
| 286 | 286 | |
| 287 | 287 | fn detach(self: Impl) void { |
| 288 | 288 | windows.CloseHandle(self.thread.thread_handle); |
| 289 | | switch (self.thread.completion.swap(.detached, .AcqRel)) { |
| 289 | switch (self.thread.completion.swap(.detached, .SeqCst)) { |
| 290 | 290 | .running => {}, |
| 291 | 291 | .completed => self.thread.free(), |
| 292 | 292 | .detached => unreachable, |
| ... | ... | @@ -296,6 +296,7 @@ const WindowsThreadImpl = struct { |
| 296 | 296 | fn join(self: Impl) void { |
| 297 | 297 | windows.WaitForSingleObjectEx(self.thread.thread_handle, windows.INFINITE, false) catch unreachable; |
| 298 | 298 | windows.CloseHandle(self.thread.thread_handle); |
| 299 | assert(self.thread.completion.load(.SeqCst) == .completed); |
| 299 | 300 | self.thread.free(); |
| 300 | 301 | } |
| 301 | 302 | }; |
| ... | ... | @@ -625,67 +626,100 @@ const LinuxThreadImpl = struct { |
| 625 | 626 | } |
| 626 | 627 | |
| 627 | 628 | // Calls `munmap(ptr, len)` then `exit(1)` without touching the stack (which lives in `ptr`). |
| 628 | | // Ported over from musl libc's pthread detached implementation. |
| 629 | // Ported over from musl libc's pthread detached implementation (`__unmapself`). |
| 629 | 630 | extern fn __unmap_and_exit(ptr: usize, len: usize) callconv(.C) noreturn; |
| 630 | 631 | comptime { |
| 631 | | asm(switch (target.cpu.arch) { |
| 632 | | .i386 => ( |
| 633 | | \\.text |
| 634 | | \\.global __unmap_and_exit |
| 635 | | \\.type __unmap_and_exit, @function |
| 636 | | \\__unmap_and_exit: |
| 637 | | \\ movl $91, %eax |
| 638 | | \\ movl 4(%esp), %ebx |
| 639 | | \\ movl 8(%esp), %ecx |
| 640 | | \\ int $128 |
| 641 | | \\ xorl %ebx, %ebx |
| 642 | | \\ movl $1, %eax |
| 643 | | \\ int $128 |
| 644 | | ), |
| 645 | | .x86_64 => ( |
| 646 | | \\.text |
| 647 | | \\.global __unmap_and_exit |
| 648 | | \\.type __unmap_and_exit, @function |
| 649 | | \\__unmap_and_exit: |
| 650 | | \\ movl $11, %eax |
| 651 | | \\ syscall |
| 652 | | \\ xor %rdi, %rdi |
| 653 | | \\ movl $60, %eax |
| 654 | | \\ syscall |
| 655 | | ), |
| 656 | | .arm, .armeb, .aarch64, .aarch64_be, .aarch64_32 => ( |
| 657 | | \\.text |
| 658 | | \\.global __unmap_and_exit |
| 659 | | \\.type __unmap_and_exit, @function |
| 660 | | \\__unmap_and_exit: |
| 661 | | \\ mov r7, #91 |
| 662 | | \\ svc 0 |
| 663 | | \\ mov r7, #1 |
| 664 | | \\ svc 0 |
| 665 | | ), |
| 666 | | .mips, .mipsel, .mips64, .mips64el => ( |
| 667 | | \\.set noreorder |
| 668 | | \\.global __unmap_and_exit |
| 669 | | \\.type __unmap_and_exit, @function |
| 670 | | \\__unmap_and_exit: |
| 671 | | \\ li $2, 4091 |
| 672 | | \\ syscall |
| 673 | | \\ li $4, 0 |
| 674 | | \\ li $2, 4001 |
| 675 | | \\ syscall |
| 676 | | ), |
| 677 | | .powerpc, .powerpc64, .powerpc64le => ( |
| 678 | | \\.text |
| 679 | | \\.global __unmap_and_exit |
| 680 | | \\.type __unmap_and_exit, @function |
| 681 | | \\__unmap_and_exit: |
| 682 | | \\ li 0, 91 |
| 683 | | \\ sc |
| 684 | | \\ li 0, 1 |
| 685 | | \\ sc |
| 686 | | \\ blr |
| 687 | | ), |
| 688 | | else => @compileError("Platform not supported"), |
| 689 | | }); |
| 632 | if (target.os.tag == .linux) { |
| 633 | asm(switch (target.cpu.arch) { |
| 634 | .i386 => ( |
| 635 | \\.text |
| 636 | \\.global __unmap_and_exit |
| 637 | \\.type __unmap_and_exit, @function |
| 638 | \\__unmap_and_exit: |
| 639 | \\ movl $91, %eax |
| 640 | \\ movl 4(%esp), %ebx |
| 641 | \\ movl 8(%esp), %ecx |
| 642 | \\ int $128 |
| 643 | \\ xorl %ebx, %ebx |
| 644 | \\ movl $1, %eax |
| 645 | \\ int $128 |
| 646 | ), |
| 647 | .x86_64 => ( |
| 648 | \\.text |
| 649 | \\.global __unmap_and_exit |
| 650 | \\.type __unmap_and_exit, @function |
| 651 | \\__unmap_and_exit: |
| 652 | \\ movl $11, %eax |
| 653 | \\ syscall |
| 654 | \\ xor %rdi, %rdi |
| 655 | \\ movl $60, %eax |
| 656 | \\ syscall |
| 657 | ), |
| 658 | .arm, .armeb, .thumb, .thumb_eb => ( |
| 659 | \\.syntax unified |
| 660 | \\.text |
| 661 | \\.global __unmap_and_exit |
| 662 | \\.type __unmap_and_exit, %function |
| 663 | \\__unmap_and_exit: |
| 664 | \\ mov r7, #91 |
| 665 | \\ svc 0 |
| 666 | \\ mov r7, #1 |
| 667 | \\ svc 0 |
| 668 | ), |
| 669 | .aarch64, .aarch64_be, .aarch64_32 => ( |
| 670 | \\.global __unmap_and_exit |
| 671 | \\.type __unmap_and_exit, %function |
| 672 | \\__unmap_and_exit: |
| 673 | \\ mov x8, #215 |
| 674 | \\ svc 0 |
| 675 | \\ mov x8, #93 |
| 676 | \\ svc 0 |
| 677 | ), |
| 678 | .mips, .mipsel, => ( |
| 679 | \\.set noreorder |
| 680 | \\.global __unmap_and_exit |
| 681 | \\.type __unmap_and_exit,@function |
| 682 | \\__unmap_and_exit: |
| 683 | \\ move $sp, $25 |
| 684 | \\ li $2, 4091 |
| 685 | \\ syscall |
| 686 | \\ li $4, 0 |
| 687 | \\ li $2, 4001 |
| 688 | \\ syscall |
| 689 | ), |
| 690 | .mips64, .mips64el => ( |
| 691 | \\.set noreorder |
| 692 | \\.global __unmap_and_exit |
| 693 | \\.type __unmap_and_exit, @function |
| 694 | \\__unmap_and_exit: |
| 695 | \\ li $2, 4091 |
| 696 | \\ syscall |
| 697 | \\ li $4, 0 |
| 698 | \\ li $2, 4001 |
| 699 | \\ syscall |
| 700 | ), |
| 701 | .powerpc, .powerpc64, .powerpc64le => ( |
| 702 | \\.text |
| 703 | \\.global __unmap_and_exit |
| 704 | \\.type __unmap_and_exit, %function |
| 705 | \\__unmap_and_exit: |
| 706 | \\ li 0, 91 |
| 707 | \\ sc |
| 708 | \\ li 0, 1 |
| 709 | \\ sc |
| 710 | \\ blr |
| 711 | ), |
| 712 | .riscv64 => ( |
| 713 | \\.global __unmap_and_exit |
| 714 | \\.type __unmap_and_exit, %function |
| 715 | \\__unmap_and_exit: |
| 716 | \\ li a7, 215 |
| 717 | \\ ecall |
| 718 | \\ li a7, 93 |
| 719 | \\ ecall |
| 720 | ), |
| 721 | else => @compileError("Platform not supported"), |
| 722 | }); |
| 723 | } |
| 690 | 724 | } |
| 691 | 725 | }; |
| | \ No newline at end of file |