]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: move mem profile sampling into m-acquired section
authorDavid Chase <drchase@google.com>
Wed, 21 Jul 2021 22:38:05 +0000 (18:38 -0400)
committerDavid Chase <drchase@google.com>
Thu, 22 Jul 2021 17:01:15 +0000 (17:01 +0000)
It was not safe to do mcache profiling updates outside the critical
section, but we got lucky because the runtime was not preemptible.
Adding chunked memory clearing (CL 270943) created preemption
opportunities, which led to corruption of runtime data structures.

Fixes #47304.
Fixes #47302.

Change-Id: I461615470d62328a83ccbac537fbdc6dcde81c85
Reviewed-on: https://go-review.googlesource.com/c/go/+/336449
Trust: David Chase <drchase@google.com>
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/runtime/malloc.go

index 2759bbdaf90f5539a06197728d7fa8476bf89e64..cc22b0f276597e94b5e6138a4fcddb8d5e20bb5b 100644 (file)
@@ -1135,13 +1135,21 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                msanmalloc(x, size)
        }
 
+       if rate := MemProfileRate; rate > 0 {
+               // Note cache c only valid while m acquired; see #47302
+               if rate != 1 && size < c.nextSample {
+                       c.nextSample -= size
+               } else {
+                       profilealloc(mp, x, size)
+               }
+       }
        mp.mallocing = 0
        releasem(mp)
 
        // Pointerfree data can be zeroed late in a context where preemption can occur.
        // x will keep the memory alive.
        if !isZeroed && needzero {
-               memclrNoHeapPointersChunked(size, x)
+               memclrNoHeapPointersChunked(size, x) // This is a possible preemption point: see #47302
        }
 
        if debug.malloc {
@@ -1155,16 +1163,6 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                }
        }
 
-       if rate := MemProfileRate; rate > 0 {
-               if rate != 1 && size < c.nextSample {
-                       c.nextSample -= size
-               } else {
-                       mp := acquirem()
-                       profilealloc(mp, x, size)
-                       releasem(mp)
-               }
-       }
-
        if assistG != nil {
                // Account for internal fragmentation in the assist
                // debt now that we know it.