aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/malloc.go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-12-21 16:06:54 -0800
committerIan Lance Taylor <iant@golang.org>2019-01-04 02:40:56 +0000
commit0d6a2d5f9a0cd3c7111f38abd12a2255363bbd51 (patch)
tree0e6ac99573db4d54dbc613ee525579b9effd530b /src/runtime/malloc.go
parent95a6f112c6db064d3394f9f66aa569e9bbeb3617 (diff)
downloadgo-0d6a2d5f9a0cd3c7111f38abd12a2255363bbd51.tar.xz
runtime: skip writes to persistent memory in cgo checker
Fixes #23899 Fixes #28458 Change-Id: Ie177f2d4c399445d8d5e1a327f2419c7866cb45e Reviewed-on: https://go-review.googlesource.com/c/155697 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/malloc.go')
-rw-r--r--src/runtime/malloc.go40
1 files changed, 36 insertions, 4 deletions
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index 678e689311..c1a89dc588 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -1167,6 +1167,15 @@ var globalAlloc struct {
persistentAlloc
}
+// persistentChunkSize is the number of bytes we allocate when we grow
+// a persistentAlloc.
+const persistentChunkSize = 256 << 10
+
+// persistentChunks is a list of all the persistent chunks we have
+// allocated. The list is maintained through the first word in the
+// persistent chunk. This is updated atomically.
+var persistentChunks *notInHeap
+
// Wrapper around sysAlloc that can allocate small chunks.
// There is no associated free operation.
// Intended for things like function/type/debug-related persistent data.
@@ -1187,7 +1196,6 @@ func persistentalloc(size, align uintptr, sysStat *uint64) unsafe.Pointer {
//go:systemstack
func persistentalloc1(size, align uintptr, sysStat *uint64) *notInHeap {
const (
- chunk = 256 << 10
maxBlock = 64 << 10 // VM reservation granularity is 64K on windows
)
@@ -1218,15 +1226,24 @@ func persistentalloc1(size, align uintptr, sysStat *uint64) *notInHeap {
persistent = &globalAlloc.persistentAlloc
}
persistent.off = round(persistent.off, align)
- if persistent.off+size > chunk || persistent.base == nil {
- persistent.base = (*notInHeap)(sysAlloc(chunk, &memstats.other_sys))
+ if persistent.off+size > persistentChunkSize || persistent.base == nil {
+ persistent.base = (*notInHeap)(sysAlloc(persistentChunkSize, &memstats.other_sys))
if persistent.base == nil {
if persistent == &globalAlloc.persistentAlloc {
unlock(&globalAlloc.mutex)
}
throw("runtime: cannot allocate memory")
}
- persistent.off = 0
+
+ // Add the new chunk to the persistentChunks list.
+ for {
+ chunks := uintptr(unsafe.Pointer(persistentChunks))
+ *(*uintptr)(unsafe.Pointer(persistent.base)) = chunks
+ if atomic.Casuintptr((*uintptr)(unsafe.Pointer(&persistentChunks)), chunks, uintptr(unsafe.Pointer(persistent.base))) {
+ break
+ }
+ }
+ persistent.off = sys.PtrSize
}
p := persistent.base.add(persistent.off)
persistent.off += size
@@ -1242,6 +1259,21 @@ func persistentalloc1(size, align uintptr, sysStat *uint64) *notInHeap {
return p
}
+// inPersistentAlloc reports whether p points to memory allocated by
+// persistentalloc. This must be nosplit because it is called by the
+// cgo checker code, which is called by the write barrier code.
+//go:nosplit
+func inPersistentAlloc(p uintptr) bool {
+ chunk := atomic.Loaduintptr((*uintptr)(unsafe.Pointer(&persistentChunks)))
+ for chunk != 0 {
+ if p >= chunk && p < chunk+persistentChunkSize {
+ return true
+ }
+ chunk = *(*uintptr)(unsafe.Pointer(chunk))
+ }
+ return false
+}
+
// linearAlloc is a simple linear allocator that pre-reserves a region
// of memory and then maps that region as needed. The caller is
// responsible for locking.