| ... | @@ -500,6 +500,101 @@ const LinuxThreadImpl = struct { | ... | @@ -500,6 +500,101 @@ const LinuxThreadImpl = struct { |
| 500 | child_tid: Atomic(i32) = Atomic(i32).init(1), | 500 | child_tid: Atomic(i32) = Atomic(i32).init(1), |
| 501 | parent_tid: i32 = undefined, | 501 | parent_tid: i32 = undefined, |
| 502 | mapped: []align(std.mem.page_size) u8, | 502 | mapped: []align(std.mem.page_size) u8, |
| | 503 | |
| | 504 | /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`). |
| | 505 | /// Ported over from musl libc's pthread detached implementation: |
| | 506 | /// https://github.com/ifduyue/musl/search?q=__unmapself |
| | 507 | fn freeAndExit(self: *ThreadCompletion) noreturn { |
| | 508 | const unmap_and_exit: []const u8 = switch (target.cpu.arch) { |
| | 509 | .i386 => ( |
| | 510 | \\ movl $91, %%eax |
| | 511 | \\ movl %[ptr], %%ebx |
| | 512 | \\ movl %[len], %%ecx |
| | 513 | \\ int $128 |
| | 514 | \\ movl $1, %%eax |
| | 515 | \\ movl $0, %%ebx |
| | 516 | \\ int $128 |
| | 517 | ), |
| | 518 | .x86_64 => ( |
| | 519 | \\ movq $11, %%rax |
| | 520 | \\ movq %[ptr], %%rbx |
| | 521 | \\ movq %[len], %%rcx |
| | 522 | \\ syscall |
| | 523 | \\ movq $60, %%rax |
| | 524 | \\ movq $1, %%rdi |
| | 525 | \\ syscall |
| | 526 | ), |
| | 527 | .arm, .armeb, .thumb, .thumbeb => ( |
| | 528 | \\ mov r7, #91 |
| | 529 | \\ mov r0, %[ptr] |
| | 530 | \\ mov r1, %[len] |
| | 531 | \\ svc 0 |
| | 532 | \\ mov r7, #1 |
| | 533 | \\ mov r0, #0 |
| | 534 | \\ svc 0 |
| | 535 | ), |
| | 536 | .aarch64, .aarch64_be, .aarch64_32 => ( |
| | 537 | \\ mov x8, #215 |
| | 538 | \\ mov x0, %[ptr] |
| | 539 | \\ mov x1, %[len] |
| | 540 | \\ svc 0 |
| | 541 | \\ mov x8, #93 |
| | 542 | \\ mov x0, #0 |
| | 543 | \\ svc 0 |
| | 544 | ), |
| | 545 | .mips, .mipsel => ( |
| | 546 | \\ move $sp, $25 |
| | 547 | \\ li $2, 4091 |
| | 548 | \\ move $4, %[ptr] |
| | 549 | \\ move $5, %[len] |
| | 550 | \\ syscall |
| | 551 | \\ li $2, 4001 |
| | 552 | \\ li $4, 0 |
| | 553 | \\ syscall |
| | 554 | ), |
| | 555 | .mips64, .mips64el => ( |
| | 556 | \\ li $2, 4091 |
| | 557 | \\ move $4, %[ptr] |
| | 558 | \\ move $5, %[len] |
| | 559 | \\ syscall |
| | 560 | \\ li $2, 4001 |
| | 561 | \\ li $4, 0 |
| | 562 | \\ syscall |
| | 563 | ), |
| | 564 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => ( |
| | 565 | \\ li 0, 91 |
| | 566 | \\ mr %[ptr], 3 |
| | 567 | \\ mr %[len], 4 |
| | 568 | \\ sc |
| | 569 | \\ li 0, 1 |
| | 570 | \\ li 3, 0 |
| | 571 | \\ sc |
| | 572 | \\ blr |
| | 573 | ), |
| | 574 | .riscv64 => ( |
| | 575 | \\ li a7, 215 |
| | 576 | \\ mv a0, %[ptr] |
| | 577 | \\ mv a1, %[len] |
| | 578 | \\ ecall |
| | 579 | \\ li a7, 93 |
| | 580 | \\ mv a0, zero |
| | 581 | \\ ecall |
| | 582 | ), |
| | 583 | else => |cpu_arch| { |
| | 584 | @compileLog("Unsupported linux arch ", cpu_arch); |
| | 585 | }, |
| | 586 | }; |
| | 587 | |
| | 588 | asm volatile ( |
| | 589 | unmap_and_exit |
| | 590 | : |
| | 591 | : [ptr] "r" (@ptrToInt(self.mapped.ptr)), |
| | 592 | [len] "r" (self.mapped.len) |
| | 593 | : "memory" |
| | 594 | ); |
| | 595 | |
| | 596 | unreachable; |
| | 597 | } |
| 503 | }; | 598 | }; |
| 504 | | 599 | |
| 505 | fn spawn(config: SpawnConfig, comptime f: anytype, args: anytype) !Impl { | 600 | fn spawn(config: SpawnConfig, comptime f: anytype, args: anytype) !Impl { |
| ... | @@ -513,10 +608,7 @@ const LinuxThreadImpl = struct { | ... | @@ -513,10 +608,7 @@ const LinuxThreadImpl = struct { |
| 513 | defer switch (self.thread.completion.swap(.completed, .SeqCst)) { | 608 | defer switch (self.thread.completion.swap(.completed, .SeqCst)) { |
| 514 | .running => {}, | 609 | .running => {}, |
| 515 | .completed => unreachable, | 610 | .completed => unreachable, |
| 516 | .detached => { | 611 | .detached => self.thread.freeAndExit(), |
| 517 | const memory = self.thread.mapped; | | |
| 518 | __unmap_and_exit(@ptrToInt(memory.ptr), memory.len); | | |
| 519 | }, | | |
| 520 | }; | 612 | }; |
| 521 | return callFn(f, self.fn_args); | 613 | return callFn(f, self.fn_args); |
| 522 | } | 614 | } |
| ... | @@ -664,108 +756,6 @@ const LinuxThreadImpl = struct { | ... | @@ -664,108 +756,6 @@ const LinuxThreadImpl = struct { |
| 664 | } | 756 | } |
| 665 | } | 757 | } |
| 666 | } | 758 | } |
| 667 | | | |
| 668 | // Calls `munmap(ptr, len)` then `exit(1)` without touching the stack (which lives in `ptr`). | | |
| 669 | // Ported over from musl libc's pthread detached implementation (`__unmapself`). | | |
| 670 | extern fn __unmap_and_exit(ptr: usize, len: usize) callconv(.C) noreturn; | | |
| 671 | comptime { | | |
| 672 | if (target.os.tag == .linux) { | | |
| 673 | asm (switch (target.cpu.arch) { | | |
| 674 | .i386 => ( | | |
| 675 | \\.text | | |
| 676 | \\.global __unmap_and_exit | | |
| 677 | \\.type __unmap_and_exit, @function | | |
| 678 | \\__unmap_and_exit: | | |
| 679 | \\ movl $91, %eax | | |
| 680 | \\ movl 4(%esp), %ebx | | |
| 681 | \\ movl 8(%esp), %ecx | | |
| 682 | \\ int $128 | | |
| 683 | \\ xorl %ebx, %ebx | | |
| 684 | \\ movl $1, %eax | | |
| 685 | \\ int $128 | | |
| 686 | ), | | |
| 687 | .x86_64 => ( | | |
| 688 | \\.text | | |
| 689 | \\.global __unmap_and_exit | | |
| 690 | \\.type __unmap_and_exit, @function | | |
| 691 | \\__unmap_and_exit: | | |
| 692 | \\ movl $11, %eax | | |
| 693 | \\ syscall | | |
| 694 | \\ xor %rdi, %rdi | | |
| 695 | \\ movl $60, %eax | | |
| 696 | \\ syscall | | |
| 697 | ), | | |
| 698 | .arm, .armeb, .thumb, .thumbeb => ( | | |
| 699 | \\.syntax unified | | |
| 700 | \\.text | | |
| 701 | \\.global __unmap_and_exit | | |
| 702 | \\.type __unmap_and_exit, %function | | |
| 703 | \\__unmap_and_exit: | | |
| 704 | \\ mov r7, #91 | | |
| 705 | \\ svc 0 | | |
| 706 | \\ mov r7, #1 | | |
| 707 | \\ svc 0 | | |
| 708 | ), | | |
| 709 | .aarch64, .aarch64_be, .aarch64_32 => ( | | |
| 710 | \\.global __unmap_and_exit | | |
| 711 | \\.type __unmap_and_exit, %function | | |
| 712 | \\__unmap_and_exit: | | |
| 713 | \\ mov x8, #215 | | |
| 714 | \\ svc 0 | | |
| 715 | \\ mov x8, #93 | | |
| 716 | \\ svc 0 | | |
| 717 | ), | | |
| 718 | .mips, | | |
| 719 | .mipsel, | | |
| 720 | => ( | | |
| 721 | \\.set noreorder | | |
| 722 | \\.global __unmap_and_exit | | |
| 723 | \\.type __unmap_and_exit,@function | | |
| 724 | \\__unmap_and_exit: | | |
| 725 | \\ move $sp, $25 | | |
| 726 | \\ li $2, 4091 | | |
| 727 | \\ syscall | | |
| 728 | \\ li $4, 0 | | |
| 729 | \\ li $2, 4001 | | |
| 730 | \\ syscall | | |
| 731 | ), | | |
| 732 | .mips64, .mips64el => ( | | |
| 733 | \\.set noreorder | | |
| 734 | \\.global __unmap_and_exit | | |
| 735 | \\.type __unmap_and_exit, @function | | |
| 736 | \\__unmap_and_exit: | | |
| 737 | \\ li $2, 4091 | | |
| 738 | \\ syscall | | |
| 739 | \\ li $4, 0 | | |
| 740 | \\ li $2, 4001 | | |
| 741 | \\ syscall | | |
| 742 | ), | | |
| 743 | .powerpc, .powerpc64, .powerpc64le => ( | | |
| 744 | \\.text | | |
| 745 | \\.global __unmap_and_exit | | |
| 746 | \\.type __unmap_and_exit, %function | | |
| 747 | \\__unmap_and_exit: | | |
| 748 | \\ li 0, 91 | | |
| 749 | \\ sc | | |
| 750 | \\ li 0, 1 | | |
| 751 | \\ sc | | |
| 752 | \\ blr | | |
| 753 | ), | | |
| 754 | .riscv64 => ( | | |
| 755 | \\.global __unmap_and_exit | | |
| 756 | \\.type __unmap_and_exit, %function | | |
| 757 | \\__unmap_and_exit: | | |
| 758 | \\ li a7, 215 | | |
| 759 | \\ ecall | | |
| 760 | \\ li a7, 93 | | |
| 761 | \\ ecall | | |
| 762 | ), | | |
| 763 | else => |cpu_arch| { | | |
| 764 | @compileLog("linux arch", cpu_arch, "is not supported"); | | |
| 765 | }, | | |
| 766 | }); | | |
| 767 | } | | |
| 768 | } | | |
| 769 | }; | 759 | }; |
| 770 | | 760 | |
| 771 | test "std.Thread" { | 761 | test "std.Thread" { |