diff options
author | Dan Scales <danscales@google.com> | 2019-11-19 12:41:51 -0800 |
---|---|---|
committer | Dan Scales <danscales@google.com> | 2019-11-25 03:41:16 +0000 |
commit | 9940c7768261f035b14657053ada8d0e88283241 (patch) | |
tree | ae5dcc4fc4ea6cdf495f24755336fe1e6cdae945 /src/runtime/sys_darwin.go | |
parent | b81dd1c0e722a7d048ffe935d3f2062d2fae4e86 (diff) | |
download | go-9940c7768261f035b14657053ada8d0e88283241.tar.gz go-9940c7768261f035b14657053ada8d0e88283241.zip |
runtime: add go:nosplit to cgo_mmap.go:mmap() and sys_darwin.go:mmap()
cgo_mmap.go:mmap() is called by mem_linux.go:sysAlloc(), a low-level memory
allocation function. mmap() should be nosplit, since it is called in a lot of
low-level parts of the runtime and callers often assume it won't acquire any
locks.
As an example there is a potential deadlock involving two threads if mmap is not nosplit:
trace.bufLock acquired, then stackpool[order].item.mu, then mheap_.lock
- can happen for traceEvents that are not invoked on the system stack and cause
a traceFlush, which causes a sysAlloc, which calls mmap(), which may cause a
stack split. mheap_.lock
mheap_.lock acquired, then trace.bufLock
- can happen when doing a trace in reclaimChunk (which holds the mheap_ lock)
Also, sysAlloc() has a comment that it is nosplit because it may be invoked
without a valid G, in which case its callee mmap() should also be nosplit.
Similarly, sys_darwin.go:mmap() is called by mem_darwin.go:sysAlloc(), and should
be nosplit for the same reasons.
Extra gomote testing: linux/arm64, darwin/amd64
Change-Id: Ia4d10cec5cf1e186a0fe5aab2858c6e0e5b80fdc
Reviewed-on: https://go-review.googlesource.com/c/go/+/207844
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime/sys_darwin.go')
-rw-r--r-- | src/runtime/sys_darwin.go | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index 31304ce737..d2d1822aab 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -170,6 +170,10 @@ func pthread_kill(t pthread, sig uint32) { } func pthread_kill_trampoline() +// mmap is used to do low-level memory allocation via mmap. Don't allow stack +// splits, since this function (used by sysAlloc) is called in a lot of low-level +// parts of the runtime and callers often assume it won't acquire any locks. +// go:nosplit func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) { args := struct { addr unsafe.Pointer |