diff options
| author | Ian Lance Taylor <iant@golang.org> | 2018-12-21 16:06:54 -0800 |
|---|---|---|
| committer | Ian Lance Taylor <iant@golang.org> | 2019-01-04 02:40:56 +0000 |
| commit | 0d6a2d5f9a0cd3c7111f38abd12a2255363bbd51 (patch) | |
| tree | 0e6ac99573db4d54dbc613ee525579b9effd530b /src/runtime/malloc.go | |
| parent | 95a6f112c6db064d3394f9f66aa569e9bbeb3617 (diff) | |
| download | go-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.go | 40 |
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. |
