Skip to content

Commit

Permalink
syscall: implement rawVforkSyscall for remaining linux platforms
Browse files Browse the repository at this point in the history
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 <joel@sing.id.au>
Run-TryBot: Joel Sing <joel@sing.id.au>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
  • Loading branch information
4a6f656c committed Mar 3, 2021
1 parent f2df1e3 commit 00cb841
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 21 deletions.
20 changes: 20 additions & 0 deletions src/syscall/asm_linux_386.s
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/syscall/asm_linux_amd64.s
Expand Up @@ -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
Expand Down
21 changes: 21 additions & 0 deletions src/syscall/asm_linux_arm.s
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion src/syscall/asm_linux_arm64.s
Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions src/syscall/asm_linux_mips64x.s
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions src/syscall/asm_linux_mipsx.s
Expand Up @@ -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
Expand Down
8 changes: 1 addition & 7 deletions src/syscall/exec_linux.go
Expand Up @@ -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)
Expand Down
4 changes: 1 addition & 3 deletions src/syscall/syscall_linux_386.go
Expand Up @@ -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)
4 changes: 1 addition & 3 deletions src/syscall/syscall_linux_arm.go
Expand Up @@ -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)
4 changes: 1 addition & 3 deletions src/syscall/syscall_linux_mips64x.go
Expand Up @@ -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)
4 changes: 1 addition & 3 deletions src/syscall/syscall_linux_mipsx.go
Expand Up @@ -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)

0 comments on commit 00cb841

Please sign in to comment.