Skip to content

Commit b25ec50

Browse files
zhlhahahatklauser
authored andcommitted
syscall: implement rawVforkSyscall for linux/arm64
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 linux/arm64. With CLONE_VM the child process shares the same memory with the parent process. On its own this would lead to conflicting use of the same memory, so CLONE_VFORK is used to suspend the parent process until the child releases the memory when switching to the new program binary via the exec syscall. When the parent process continues to run, one has to consider the changes to memory that the child process did, namely the return address of the syscall function needs to be restored from a register. exec.Command() callers can start in a faster manner, as child process who do exec commands job can be cloned faster via vfork than via fork on arm64. The same problem was addressed on linux/amd64 via issue #5838. Updates #31936 Contributed by Howard Zhang <[email protected]> and Bin Lu <[email protected]> Change-Id: Ia99d81d877f564ec60d19f17e596276836576eaf Reviewed-on: https://go-review.googlesource.com/c/go/+/189418 Run-TryBot: Tobias Klauser <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Tobias Klauser <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent 904f046 commit b25ec50

File tree

3 files changed

+25
-4
lines changed

3 files changed

+25
-4
lines changed

src/syscall/asm_linux_arm64.s

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,29 @@ ok:
103103
MOVD ZR, err+72(FP) // errno
104104
RET
105105

106+
// func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr)
107+
TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-32
108+
MOVD a1+8(FP), R0
109+
MOVD $0, R1
110+
MOVD $0, R2
111+
MOVD $0, R3
112+
MOVD $0, R4
113+
MOVD $0, R5
114+
MOVD trap+0(FP), R8 // syscall entry
115+
SVC
116+
CMN $4095, R0
117+
BCC ok
118+
MOVD $-1, R4
119+
MOVD R4, r1+16(FP) // r1
120+
NEG R0, R0
121+
MOVD R0, err+24(FP) // errno
122+
RET
123+
ok:
124+
MOVD R0, r1+16(FP) // r1
125+
MOVD ZR, err+24(FP) // errno
126+
RET
127+
128+
106129
// func rawSyscallNoError(trap uintptr, a1, a2, a3 uintptr) (r1, r2 uintptr);
107130
TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-48
108131
MOVD a1+8(FP), R0

src/syscall/exec_linux.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att
196196
}
197197
}
198198

199-
hasRawVforkSyscall := runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "s390x"
199+
hasRawVforkSyscall := runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64"
200200

201201
// About to call fork.
202202
// No more allocation or calls of non-assembly functions.

src/syscall/syscall_linux_arm64.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,4 @@ const (
155155
SYS_EPOLL_WAIT = 1069
156156
)
157157

158-
func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) {
159-
panic("not implemented")
160-
}
158+
func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno)

0 commit comments

Comments
 (0)