diff options
| author | Keith Randall <khr@golang.org> | 2026-03-17 11:13:16 -0700 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-03-17 13:49:58 -0700 |
| commit | cd2fa3b48dc059203aa724474e19096928b3f71f (patch) | |
| tree | 320e87c87cb0e25263aa1af7b7a6914379b0c52a /src | |
| parent | a6949e942c4287fcccf3264b8df6190c88609cb7 (diff) | |
| download | go-cd2fa3b48dc059203aa724474e19096928b3f71f.tar.xz | |
runtime: fix memclrNoHeapPointersPreemptible
memclrNoHeapPointersChunked was originally written for
clearing fresh allocations. It converts to uintptr early and thus
doesn't handle the case where the pointer points to the stack.
At the preemption point, the buffer being pointed to might be
on the stack and copied to a new location. Then we'd end up
zeroing random heap memory when we return from preemption.
Fix it to keep the pointer to the allocation in an unsafe.Pointer,
so it gets updated correctly on a stack copy.
Update #78081
(Fixes?)
Change-Id: Id25c7faf45f201929cb8c8bbcc7c8bd4f67c31ac
Reviewed-on: https://go-review.googlesource.com/c/go/+/756122
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/runtime/malloc.go | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 2144ea602a..44b4b3bc57 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -2184,22 +2184,27 @@ func reusableSize(size uintptr) bool { // Use this with care; if the data being cleared is tagged to contain // pointers, this allows the GC to run before it is all cleared. func memclrNoHeapPointersChunked(size uintptr, x unsafe.Pointer) { - v := uintptr(x) + if getg().preempt { + // TODO: no need for this, except to test that + // the preemption point is ok for small zeroings. + // (The pre-CL-756122 allowed preemption in this case, + // which is probably why we noticed 78081 at all.) + // Remove once we think 78081 is fixed. + // may hold locks, e.g., profiling + goschedguarded() + } // got this from benchmarking. 128k is too small, 512k is too large. const chunkBytes = 256 * 1024 - vsize := v + size - for voff := v; voff < vsize; voff = voff + chunkBytes { + for size > chunkBytes { + memclrNoHeapPointers(x, chunkBytes) + x = add(x, chunkBytes) + size -= chunkBytes if getg().preempt { // may hold locks, e.g., profiling goschedguarded() } - // clear min(avail, lump) bytes - n := vsize - voff - if n > chunkBytes { - n = chunkBytes - } - memclrNoHeapPointers(unsafe.Pointer(voff), n) } + memclrNoHeapPointers(x, size) } // memclrNoHeapPointersPreemptible is the compiler-callable entry point |
