Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std.process.Child: use clone() instead of fork() #22368

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
57 changes: 44 additions & 13 deletions lib/std/os/linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,40 @@ pub fn clone(
) callconv(.C) usize, @ptrCast(&syscall_bits.clone))(func, stack, flags, arg, ptid, tp, ctid);
}

pub const clone_args = extern struct {
flags: u64,
pidfd: u64,
child_tid: u64,
parent_tid: u64,
exit_signal: u64,
stack: u64,
stack_size: u64,
tls: u64,
set_tid: u64,
set_tid_size: u64,
cgroup: u64,
};

pub fn clone3(
cl_args: *const clone_args,
size: usize,
func: *const fn (arg: usize) callconv(.C) u8,
arg: usize,
) usize {
// TODO: write asm for other arch.
ruihe774 marked this conversation as resolved.
Show resolved Hide resolved
if (@hasDecl(syscall_bits, "clone3")) {
// Can't directly call a naked function; cast to C calling convention first.
return @as(*const fn (
cl_args: *const clone_args,
size: usize,
func: *const fn (arg: usize) callconv(.C) u8,
arg: usize,
) callconv(.C) usize, @ptrCast(&syscall_bits.clone3))(cl_args, size, func, arg);
} else {
@compileError("clone3() implementation has not been written for this target");
}
}

pub const ARCH = arch_bits.ARCH;
pub const Elf_Symndx = arch_bits.Elf_Symndx;
pub const F = arch_bits.F;
Expand Down Expand Up @@ -1710,24 +1744,21 @@ pub fn sigprocmask(flags: u32, noalias set: ?*const sigset_t, noalias oldset: ?*
return syscall4(.rt_sigprocmask, flags, @intFromPtr(set), @intFromPtr(oldset), NSIG / 8);
}

pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize {
assert(sig >= 1);
assert(sig != SIG.KILL);
assert(sig != SIG.STOP);

pub fn sigaction(sig: u8, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize {
var ksa: k_sigaction = undefined;
var oldksa: k_sigaction = undefined;
const mask_size = @sizeOf(@TypeOf(ksa.mask));

if (act) |new| {
const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) &restore_rt else &restore;
ksa = k_sigaction{
.handler = new.handler.handler,
.flags = new.flags | SA.RESTORER,
.mask = undefined,
.restorer = @ptrCast(restorer_fn),
};
@memcpy(@as([*]u8, @ptrCast(&ksa.mask))[0..mask_size], @as([*]const u8, @ptrCast(&new.mask)));
ksa.handler = new.handler.handler;
if (ksa.handler == SIG.DFL or ksa.handler == SIG.IGN) {
ksa.flags = new.flags;
} else {
const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) &restore_rt else &restore;
ksa.flags = new.flags | SA.RESTORER;
ksa.restorer = @ptrCast(restorer_fn);
@memcpy(@as([*]u8, @ptrCast(&ksa.mask))[0..mask_size], @as([*]const u8, @ptrCast(&new.mask)));
}
}

const ksa_arg = if (act != null) @intFromPtr(&ksa) else 0;
Expand Down
19 changes: 19 additions & 0 deletions lib/std/os/linux/aarch64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,25 @@ pub fn clone() callconv(.Naked) usize {
);
}

pub fn clone3() callconv(.Naked) usize {
asm volatile (
\\ mov x8,#435 // SYS_clone3
\\ svc #0
\\
\\ cbz x0,1f
\\ ret
\\
\\1: .cfi_undefined lr
\\ mov fp, 0
\\ mov lr, 0
\\
\\ mov x0,x3
\\ blr x2
\\ mov x8,#93 // SYS_exit
\\ svc #0
);
}

pub const restore = restore_rt;

pub fn restore_rt() callconv(.Naked) noreturn {
Expand Down
20 changes: 20 additions & 0 deletions lib/std/os/linux/arm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,26 @@ pub fn clone() callconv(.Naked) usize {
);
}

pub fn clone3() callconv(.Naked) usize {
asm volatile (
\\ stmfd sp!,{r7}
\\ mov r7,#435 // SYS_clone3
\\ svc 0
\\ tst r0,r0
\\ beq 1f
\\ ldmfd sp!,{r7}
\\ bx lr
\\
\\ // https://github.com/llvm/llvm-project/issues/115891
\\1: mov r11, #0
\\ mov lr, #0
\\ mov r0,r3
\\ bx r2
\\ mov r7,#1 // SYS_exit
\\ svc 0
);
}

pub fn restore() callconv(.Naked) noreturn {
switch (@import("builtin").zig_backend) {
.stage2_c => asm volatile (
Expand Down
1 change: 1 addition & 0 deletions lib/std/os/linux/thumb.zig
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ pub fn syscall6(
}

pub const clone = @import("arm.zig").clone;
pub const clone3 = @import("arm.zig").clone3;

pub fn restore() callconv(.Naked) noreturn {
asm volatile (
Expand Down
30 changes: 30 additions & 0 deletions lib/std/os/linux/x86.zig
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,36 @@ pub fn clone() callconv(.Naked) usize {
);
}

pub fn clone3() callconv(.Naked) usize {
asm volatile (
\\ pushl %%ebx
\\ pushl %%esi
\\ movl 12(%%esp),%%ebx
\\ movl 16(%%esp),%%ecx
\\ movl 20(%%esp),%%edx
\\ movl 24(%%esp),%%esi
\\ movl $435,%%eax // SYS_clone3
\\ int $128
\\ testl %%eax,%%eax
\\ jz 1f
\\ popl %%esi
\\ popl %%ebx
\\ retl
\\
\\1:
\\ .cfi_undefined %%eip
\\ xorl %%ebp,%%ebp
\\
\\ andl $-16,%%esp
\\ subl $12,%%esp
\\ pushl %%esi
\\ calll *%%edx
\\ movl %%eax,%%ebx
\\ movl $1,%%eax // SYS_exit
\\ int $128
);
}

pub fn restore() callconv(.Naked) noreturn {
switch (@import("builtin").zig_backend) {
.stage2_c => asm volatile (
Expand Down
21 changes: 21 additions & 0 deletions lib/std/os/linux/x86_64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,27 @@ pub fn clone() callconv(.Naked) usize {
);
}

pub fn clone3() callconv(.Naked) usize {
asm volatile (
\\ movl $435,%%eax // SYS_clone3
\\ movq %%rcx,%%r8
\\ syscall
\\ testq %%rax,%%rax
\\ jz 1f
\\ retq
\\
\\1: .cfi_undefined %%rip
\\ xorl %%ebp,%%ebp
\\
\\ movq %%r8,%%rdi
\\ callq *%%rdx
\\ movl %%eax,%%edi
\\ movl $60,%%eax // SYS_exit
\\ syscall
\\
);
}

pub const restore = restore_rt;

pub fn restore_rt() callconv(.Naked) noreturn {
Expand Down
Loading
Loading