From 00cb841b83ad157bc21d36daf0626bbcd4af0d57 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 7 May 2019 17:56:49 +1000 Subject: syscall: implement rawVforkSyscall for remaining linux platforms This allows the use of CLONE_VFORK and CLONE_VM for fork/exec, preventing 'fork/exec ...: cannot allocate memory' failures from occuring when attempting to execute commands from a Go process that has a large memory footprint. Additionally, this should reduce the latency of fork/exec on these platforms. Fixes #31936 Change-Id: I4e28cf0763173145cacaa5340680dca9ff449305 Reviewed-on: https://go-review.googlesource.com/c/go/+/295849 Trust: Joel Sing Run-TryBot: Joel Sing Reviewed-by: Cherry Zhang --- src/syscall/asm_linux_386.s | 20 ++++++++++++++++++++ src/syscall/asm_linux_amd64.s | 2 +- src/syscall/asm_linux_arm.s | 21 +++++++++++++++++++++ src/syscall/asm_linux_arm64.s | 1 - src/syscall/asm_linux_mips64x.s | 20 ++++++++++++++++++++ src/syscall/asm_linux_mipsx.s | 17 +++++++++++++++++ src/syscall/exec_linux.go | 8 +------- src/syscall/syscall_linux_386.go | 4 +--- src/syscall/syscall_linux_arm.go | 4 +--- src/syscall/syscall_linux_mips64x.go | 4 +--- src/syscall/syscall_linux_mipsx.go | 4 +--- 11 files changed, 84 insertions(+), 21 deletions(-) diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s index 4201f367ba..1c69083118 100644 --- a/src/syscall/asm_linux_386.s +++ b/src/syscall/asm_linux_386.s @@ -110,6 +110,26 @@ ok2: MOVL $0, err+36(FP) RET +// func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16 + MOVL trap+0(FP), AX // syscall entry + MOVL a1+4(FP), BX + MOVL $0, CX + MOVL $0, DX + POPL SI // preserve return address + INVOKE_SYSCALL + PUSHL SI + CMPL AX, $0xfffff001 + JLS ok + MOVL $-1, r1+8(FP) + NEGL AX + MOVL AX, err+12(FP) + RET +ok: + MOVL AX, r1+8(FP) + MOVL $0, err+12(FP) + RET + // func rawSyscallNoError(trap uintptr, a1, a2, a3 uintptr) (r1, r2 uintptr); TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-24 MOVL trap+0(FP), AX // syscall entry diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s index ba22179dc2..a9af68d51d 100644 --- a/src/syscall/asm_linux_amd64.s +++ b/src/syscall/asm_linux_amd64.s @@ -108,7 +108,7 @@ ok2: RET // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-32 +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVQ a1+8(FP), DI MOVQ $0, SI MOVQ $0, DX diff --git a/src/syscall/asm_linux_arm.s b/src/syscall/asm_linux_arm.s index 458e9cce79..6bb4df81a0 100644 --- a/src/syscall/asm_linux_arm.s +++ b/src/syscall/asm_linux_arm.s @@ -154,6 +154,27 @@ ok1: MOVW R0, err+24(FP) RET +// func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16 + MOVW trap+0(FP), R7 // syscall entry + MOVW a1+4(FP), R0 + MOVW $0, R1 + MOVW $0, R2 + SWI $0 + MOVW $0xfffff001, R1 + CMP R1, R0 + BLS ok + MOVW $-1, R1 + MOVW R1, r1+8(FP) + RSB $0, R0, R0 + MOVW R0, err+12(FP) + RET +ok: + MOVW R0, r1+8(FP) + MOVW $0, R0 + MOVW R0, err+12(FP) + RET + // func rawSyscallNoError(trap uintptr, a1, a2, a3 uintptr) (r1, r2 uintptr); TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-24 MOVW trap+0(FP), R7 // syscall entry diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s index fb22f8d547..a30e4d87d4 100644 --- a/src/syscall/asm_linux_arm64.s +++ b/src/syscall/asm_linux_arm64.s @@ -125,7 +125,6 @@ ok: MOVD ZR, err+24(FP) // errno RET - // func rawSyscallNoError(trap uintptr, a1, a2, a3 uintptr) (r1, r2 uintptr); TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-48 MOVD a1+8(FP), R0 diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s index d0b0e5a0a8..b3ae59023d 100644 --- a/src/syscall/asm_linux_mips64x.s +++ b/src/syscall/asm_linux_mips64x.s @@ -102,6 +102,26 @@ ok2: MOVV R0, err+72(FP) // errno RET +// func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 + MOVV a1+8(FP), R4 + MOVV R0, R5 + MOVV R0, R6 + MOVV R0, R7 + MOVV R0, R8 + MOVV R0, R9 + MOVV trap+0(FP), R2 // syscall entry + SYSCALL + BEQ R7, ok + MOVV $-1, R1 + MOVV R1, r1+16(FP) // r1 + MOVV R2, err+24(FP) // errno + RET +ok: + MOVV R2, r1+16(FP) // r1 + MOVV R0, err+24(FP) // errno + RET + TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-48 MOVV a1+8(FP), R4 MOVV a2+16(FP), R5 diff --git a/src/syscall/asm_linux_mipsx.s b/src/syscall/asm_linux_mipsx.s index 5727e4d41d..ee436490b2 100644 --- a/src/syscall/asm_linux_mipsx.s +++ b/src/syscall/asm_linux_mipsx.s @@ -139,6 +139,23 @@ ok2: MOVW R0, err+36(FP) // errno RET +// func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16 + MOVW a1+4(FP), R4 + MOVW R0, R5 + MOVW R0, R6 + MOVW trap+0(FP), R2 // syscall entry + SYSCALL + BEQ R7, ok + MOVW $-1, R1 + MOVW R1, r1+8(FP) // r1 + MOVW R2, err+12(FP) // errno + RET +ok: + MOVW R2, r1+8(FP) // r1 + MOVW R0, err+12(FP) // errno + RET + TEXT ·rawSyscallNoError(SB),NOSPLIT,$20-24 MOVW a1+4(FP), R4 MOVW a2+8(FP), R5 diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index b0099cb4b0..6353da4048 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -208,18 +208,12 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att } } - var hasRawVforkSyscall bool - switch runtime.GOARCH { - case "amd64", "arm64", "ppc64", "riscv64", "s390x": - hasRawVforkSyscall = true - } - // About to call fork. // No more allocation or calls of non-assembly functions. runtime_BeforeFork() locked = true switch { - case hasRawVforkSyscall && (sys.Cloneflags&CLONE_NEWUSER == 0 && sys.Unshareflags&CLONE_NEWUSER == 0): + case sys.Cloneflags&CLONE_NEWUSER == 0 && sys.Unshareflags&CLONE_NEWUSER == 0: r1, err1 = rawVforkSyscall(SYS_CLONE, uintptr(SIGCHLD|CLONE_VFORK|CLONE_VM)|sys.Cloneflags) case runtime.GOARCH == "s390x": r1, _, err1 = RawSyscall6(SYS_CLONE, 0, uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0) diff --git a/src/syscall/syscall_linux_386.go b/src/syscall/syscall_linux_386.go index ed52647403..0db037470d 100644 --- a/src/syscall/syscall_linux_386.go +++ b/src/syscall/syscall_linux_386.go @@ -387,6 +387,4 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } -func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) { - panic("not implemented") -} +func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) diff --git a/src/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go index 4a3729f898..e887cf788f 100644 --- a/src/syscall/syscall_linux_arm.go +++ b/src/syscall/syscall_linux_arm.go @@ -236,6 +236,4 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } -func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) { - panic("not implemented") -} +func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go index dd51f3d00a..5feb03e915 100644 --- a/src/syscall/syscall_linux_mips64x.go +++ b/src/syscall/syscall_linux_mips64x.go @@ -214,6 +214,4 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } -func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) { - panic("not implemented") -} +func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) diff --git a/src/syscall/syscall_linux_mipsx.go b/src/syscall/syscall_linux_mipsx.go index 7894bdd465..39104d71d8 100644 --- a/src/syscall/syscall_linux_mipsx.go +++ b/src/syscall/syscall_linux_mipsx.go @@ -224,6 +224,4 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } -func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) { - panic("not implemented") -} +func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) -- cgit v1.2.3-54-g00ecf