diff options
| author | Lance Yang <ioworker0@gmail.com> | 2024-03-19 14:19:43 +0000 |
|---|---|---|
| committer | Michael Knyszek <mknyszek@google.com> | 2024-03-19 14:54:29 +0000 |
| commit | cb12198de57db6f514d7ef11839d446189e38f4b (patch) | |
| tree | badaa98ce8212fb9d331bee245c0abba19e0d420 /src/runtime/os_linux.go | |
| parent | b750841906c84e894dfa3ee43e0f65d94f989b01 (diff) | |
| download | go-cb12198de57db6f514d7ef11839d446189e38f4b.tar.xz | |
runtime: optimize permission changes with mprotect
On Linux, both mprotect() and mmap() acquire the mmap_lock (in writer mode),
posing scalability challenges.
The mmap_lock (formerly called mmap_sem) is a reader/writer lock that controls
access to a process's address space; before making changes there (mapping in a
new range, for example), the kernel must acquire that lock.
Page-fault handling must also acquire mmap_lock (in reader mode) to ensure that
the address space doesn't change in surprising ways while a fault is being resolved.
A process can have a large address space and many threads running (and incurring
page faults) concurrently, turning mmap_lock into a significant bottleneck.
While both mmap() and mprotect() are protected by the mmap_lock, the shorter
duration of mprotect system call, due to their simpler nature, results in a reduced
locking time for the mmap_lock.
Change-Id: I7f929544904e31eab34d0d8a9e368abe4de64637
GitHub-Last-Rev: 6f27a216b4fb789181d00316561b44358a118b19
GitHub-Pull-Request: golang/go#65038
Reviewed-on: https://go-review.googlesource.com/c/go/+/554935
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Mauri de Souza Meneguzzo <mauri870@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/runtime/os_linux.go')
| -rw-r--r-- | src/runtime/os_linux.go | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index ddacaa585c..c4f503c8c9 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -891,3 +891,9 @@ func (c *sigctxt) sigFromUser() bool { code := int32(c.sigcode()) return code == _SI_USER || code == _SI_TKILL } + +//go:nosplit +func mprotect(addr unsafe.Pointer, n uintptr, prot int32) (ret int32, errno int32) { + r, _, err := syscall.Syscall6(syscall.SYS_MPROTECT, uintptr(addr), n, uintptr(prot), 0, 0, 0) + return int32(r), int32(err) +} |
