std.Thread: move linux detach code to inline asm

This commit is contained in:
kprotty 2021-07-01 17:34:23 -05:00
parent 98106b09d5
commit 483eb8e057

View File

@ -500,6 +500,101 @@ const LinuxThreadImpl = struct {
child_tid: Atomic(i32) = Atomic(i32).init(1),
parent_tid: i32 = undefined,
mapped: []align(std.mem.page_size) u8,
/// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`).
/// Ported over from musl libc's pthread detached implementation:
/// https://github.com/ifduyue/musl/search?q=__unmapself
fn freeAndExit(self: *ThreadCompletion) noreturn {
const unmap_and_exit: []const u8 = switch (target.cpu.arch) {
.i386 => (
\\ movl $91, %%eax
\\ movl %[ptr], %%ebx
\\ movl %[len], %%ecx
\\ int $128
\\ movl $1, %%eax
\\ movl $0, %%ebx
\\ int $128
),
.x86_64 => (
\\ movq $11, %%rax
\\ movq %[ptr], %%rbx
\\ movq %[len], %%rcx
\\ syscall
\\ movq $60, %%rax
\\ movq $1, %%rdi
\\ syscall
),
.arm, .armeb, .thumb, .thumbeb => (
\\ mov r7, #91
\\ mov r0, %[ptr]
\\ mov r1, %[len]
\\ svc 0
\\ mov r7, #1
\\ mov r0, #0
\\ svc 0
),
.aarch64, .aarch64_be, .aarch64_32 => (
\\ mov x8, #215
\\ mov x0, %[ptr]
\\ mov x1, %[len]
\\ svc 0
\\ mov x8, #93
\\ mov x0, #0
\\ svc 0
),
.mips, .mipsel => (
\\ move $sp, $25
\\ li $2, 4091
\\ move $4, %[ptr]
\\ move $5, %[len]
\\ syscall
\\ li $2, 4001
\\ li $4, 0
\\ syscall
),
.mips64, .mips64el => (
\\ li $2, 4091
\\ move $4, %[ptr]
\\ move $5, %[len]
\\ syscall
\\ li $2, 4001
\\ li $4, 0
\\ syscall
),
.powerpc, .powerpcle, .powerpc64, .powerpc64le => (
\\ li 0, 91
\\ mr %[ptr], 3
\\ mr %[len], 4
\\ sc
\\ li 0, 1
\\ li 3, 0
\\ sc
\\ blr
),
.riscv64 => (
\\ li a7, 215
\\ mv a0, %[ptr]
\\ mv a1, %[len]
\\ ecall
\\ li a7, 93
\\ mv a0, zero
\\ ecall
),
else => |cpu_arch| {
@compileLog("Unsupported linux arch ", cpu_arch);
},
};
asm volatile (
unmap_and_exit
:
: [ptr] "r" (@ptrToInt(self.mapped.ptr)),
[len] "r" (self.mapped.len)
: "memory"
);
unreachable;
}
};
fn spawn(config: SpawnConfig, comptime f: anytype, args: anytype) !Impl {
@ -513,10 +608,7 @@ const LinuxThreadImpl = struct {
defer switch (self.thread.completion.swap(.completed, .SeqCst)) {
.running => {},
.completed => unreachable,
.detached => {
const memory = self.thread.mapped;
__unmap_and_exit(@ptrToInt(memory.ptr), memory.len);
},
.detached => self.thread.freeAndExit(),
};
return callFn(f, self.fn_args);
}
@ -664,108 +756,6 @@ const LinuxThreadImpl = struct {
}
}
}
// Calls `munmap(ptr, len)` then `exit(1)` without touching the stack (which lives in `ptr`).
// Ported over from musl libc's pthread detached implementation (`__unmapself`).
extern fn __unmap_and_exit(ptr: usize, len: usize) callconv(.C) noreturn;
comptime {
if (target.os.tag == .linux) {
asm (switch (target.cpu.arch) {
.i386 => (
\\.text
\\.global __unmap_and_exit
\\.type __unmap_and_exit, @function
\\__unmap_and_exit:
\\ movl $91, %eax
\\ movl 4(%esp), %ebx
\\ movl 8(%esp), %ecx
\\ int $128
\\ xorl %ebx, %ebx
\\ movl $1, %eax
\\ int $128
),
.x86_64 => (
\\.text
\\.global __unmap_and_exit
\\.type __unmap_and_exit, @function
\\__unmap_and_exit:
\\ movl $11, %eax
\\ syscall
\\ xor %rdi, %rdi
\\ movl $60, %eax
\\ syscall
),
.arm, .armeb, .thumb, .thumbeb => (
\\.syntax unified
\\.text
\\.global __unmap_and_exit
\\.type __unmap_and_exit, %function
\\__unmap_and_exit:
\\ mov r7, #91
\\ svc 0
\\ mov r7, #1
\\ svc 0
),
.aarch64, .aarch64_be, .aarch64_32 => (
\\.global __unmap_and_exit
\\.type __unmap_and_exit, %function
\\__unmap_and_exit:
\\ mov x8, #215
\\ svc 0
\\ mov x8, #93
\\ svc 0
),
.mips,
.mipsel,
=> (
\\.set noreorder
\\.global __unmap_and_exit
\\.type __unmap_and_exit,@function
\\__unmap_and_exit:
\\ move $sp, $25
\\ li $2, 4091
\\ syscall
\\ li $4, 0
\\ li $2, 4001
\\ syscall
),
.mips64, .mips64el => (
\\.set noreorder
\\.global __unmap_and_exit
\\.type __unmap_and_exit, @function
\\__unmap_and_exit:
\\ li $2, 4091
\\ syscall
\\ li $4, 0
\\ li $2, 4001
\\ syscall
),
.powerpc, .powerpc64, .powerpc64le => (
\\.text
\\.global __unmap_and_exit
\\.type __unmap_and_exit, %function
\\__unmap_and_exit:
\\ li 0, 91
\\ sc
\\ li 0, 1
\\ sc
\\ blr
),
.riscv64 => (
\\.global __unmap_and_exit
\\.type __unmap_and_exit, %function
\\__unmap_and_exit:
\\ li a7, 215
\\ ecall
\\ li a7, 93
\\ ecall
),
else => |cpu_arch| {
@compileLog("linux arch", cpu_arch, "is not supported");
},
});
}
}
};
test "std.Thread" {