102 lines
3.6 KiB
Diff
102 lines
3.6 KiB
Diff
From fa95a1d8e7eda9ab90a7fd29785cad0ae7d816e2 Mon Sep 17 00:00:00 2001
|
|
From: jingrui <jingrui@huawei.com>
|
|
Date: Wed, 27 Nov 2019 09:54:22 +0800
|
|
Subject: [PATCH 1/6] 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 <howard.zhang@arm.com> and Bin Lu <bin.lu@arm.com>
|
|
|
|
Change-Id: Ia99d81d877f564ec60d19f17e596276836576eaf
|
|
Reviewed-on: https://go-review.googlesource.com/c/go/+/189418
|
|
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
|
|
TryBot-Result: Gobot Gobot <gobot@golang.org>
|
|
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
|
|
Reviewed-by: Cherry Zhang <cherryyz@google.com>
|
|
---
|
|
src/syscall/asm_linux_arm64.s | 23 +++++++++++++++++++++++
|
|
src/syscall/exec_linux.go | 2 +-
|
|
src/syscall/syscall_linux_arm64.go | 4 +---
|
|
3 files changed, 25 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s
|
|
index 7edeafc..fb22f8d 100644
|
|
--- a/src/syscall/asm_linux_arm64.s
|
|
+++ b/src/syscall/asm_linux_arm64.s
|
|
@@ -103,6 +103,29 @@ ok:
|
|
MOVD ZR, err+72(FP) // errno
|
|
RET
|
|
|
|
+// func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr)
|
|
+TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-32
|
|
+ MOVD a1+8(FP), R0
|
|
+ MOVD $0, R1
|
|
+ MOVD $0, R2
|
|
+ MOVD $0, R3
|
|
+ MOVD $0, R4
|
|
+ MOVD $0, R5
|
|
+ MOVD trap+0(FP), R8 // syscall entry
|
|
+ SVC
|
|
+ CMN $4095, R0
|
|
+ BCC ok
|
|
+ MOVD $-1, R4
|
|
+ MOVD R4, r1+16(FP) // r1
|
|
+ NEG R0, R0
|
|
+ MOVD R0, err+24(FP) // errno
|
|
+ RET
|
|
+ok:
|
|
+ MOVD R0, r1+16(FP) // r1
|
|
+ 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/exec_linux.go b/src/syscall/exec_linux.go
|
|
index a2242b2..3540d51 100644
|
|
--- a/src/syscall/exec_linux.go
|
|
+++ b/src/syscall/exec_linux.go
|
|
@@ -196,7 +196,7 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att
|
|
}
|
|
}
|
|
|
|
- hasRawVforkSyscall := runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "s390x"
|
|
+ hasRawVforkSyscall := runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64"
|
|
|
|
// About to call fork.
|
|
// No more allocation or calls of non-assembly functions.
|
|
diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go
|
|
index 48ad0bb..89b2ab2 100644
|
|
--- a/src/syscall/syscall_linux_arm64.go
|
|
+++ b/src/syscall/syscall_linux_arm64.go
|
|
@@ -154,6 +154,4 @@ const (
|
|
SYS_EPOLL_WAIT = 1069
|
|
)
|
|
|
|
-func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) {
|
|
- panic("not implemented")
|
|
-}
|
|
+func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno)
|
|
--
|
|
2.17.1
|
|
|