aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorChressie Himpel <chressie@google.com>2022-02-08 10:31:51 +0100
committerChressie Himpel <chressie@google.com>2022-02-08 10:31:51 +0100
commit74d25c624c01d8deefaf37ee7edb41980d0d5912 (patch)
tree7a316cbfaca2f501aa0b8c47a6042973e18c6c67 /src/runtime
parente14fee553a4646d15123caa04f7ca6ddb7b48362 (diff)
parentc856fbf36190cef65ac6639a048cd512e4b7fc0a (diff)
downloadgo-74d25c624c01d8deefaf37ee7edb41980d0d5912.tar.xz
[dev.boringcrypto] all: merge master into dev.boringcrypto
Change-Id: If6b68df0c90464566e68de6807d15f4b8bec6219
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/crash_cgo_test.go16
-rw-r--r--src/runtime/mbarrier.go2
-rw-r--r--src/runtime/mbitmap.go12
-rw-r--r--src/runtime/mgcpacer.go3
-rw-r--r--src/runtime/slice.go2
-rw-r--r--src/runtime/symtab.go2
-rw-r--r--src/runtime/syscall_windows.go2
-rw-r--r--src/runtime/testdata/testprogcgo/aprof.go7
-rw-r--r--src/runtime/testdata/testprogcgo/pprof_callback.go89
9 files changed, 122 insertions, 13 deletions
diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index 9444554d37..8c250f72d6 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -216,6 +216,19 @@ func TestCgoCCodeSIGPROF(t *testing.T) {
}
}
+func TestCgoPprofCallback(t *testing.T) {
+ t.Parallel()
+ switch runtime.GOOS {
+ case "windows", "plan9":
+ t.Skipf("skipping cgo pprof callback test on %s", runtime.GOOS)
+ }
+ got := runTestProg(t, "testprogcgo", "CgoPprofCallback")
+ want := "OK\n"
+ if got != want {
+ t.Errorf("expected %q got %v", want, got)
+ }
+}
+
func TestCgoCrashTraceback(t *testing.T) {
t.Parallel()
switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
@@ -596,6 +609,9 @@ func TestSegv(t *testing.T) {
t.Log(got)
want := "SIGSEGV"
if !strings.Contains(got, want) {
+ if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" && strings.Contains(got, "fatal: morestack on g0") {
+ testenv.SkipFlaky(t, 39457)
+ }
t.Errorf("did not see %q in output", want)
}
diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go
index 0f8b2af5fa..465c21f83f 100644
--- a/src/runtime/mbarrier.go
+++ b/src/runtime/mbarrier.go
@@ -198,7 +198,7 @@ func reflectlite_typedmemmove(typ *_type, dst, src unsafe.Pointer) {
// typedmemmovepartial is like typedmemmove but assumes that
// dst and src point off bytes into the value and only copies size bytes.
-// off must be a multiple of sys.PtrSize.
+// off must be a multiple of goarch.PtrSize.
//go:linkname reflect_typedmemmovepartial reflect.typedmemmovepartial
func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
if writeBarrier.needed && typ.ptrdata > off && size >= goarch.PtrSize {
diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go
index 1c6f3f959f..937968807b 100644
--- a/src/runtime/mbitmap.go
+++ b/src/runtime/mbitmap.go
@@ -843,7 +843,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
// size is sizeof(_defer{}) (at least 6 words) and dataSize may be
// arbitrarily larger.
//
- // The checks for size == sys.PtrSize and size == 2*sys.PtrSize can therefore
+ // The checks for size == goarch.PtrSize and size == 2*goarch.PtrSize can therefore
// assume that dataSize == size without checking it explicitly.
if goarch.PtrSize == 8 && size == goarch.PtrSize {
@@ -893,7 +893,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
}
return
}
- // Otherwise typ.size must be 2*sys.PtrSize,
+ // Otherwise typ.size must be 2*goarch.PtrSize,
// and typ.kind&kindGCProg == 0.
if doubleCheck {
if typ.size != 2*goarch.PtrSize || typ.kind&kindGCProg != 0 {
@@ -1095,8 +1095,8 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
// Replicate ptrmask to fill entire pbits uintptr.
// Doubling and truncating is fewer steps than
// iterating by nb each time. (nb could be 1.)
- // Since we loaded typ.ptrdata/sys.PtrSize bits
- // but are pretending to have typ.size/sys.PtrSize,
+ // Since we loaded typ.ptrdata/goarch.PtrSize bits
+ // but are pretending to have typ.size/goarch.PtrSize,
// there might be no replication necessary/possible.
pbits = b
endnb = nb
@@ -1564,7 +1564,7 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u
// progToPointerMask returns the 1-bit pointer mask output by the GC program prog.
// size the size of the region described by prog, in bytes.
-// The resulting bitvector will have no more than size/sys.PtrSize bits.
+// The resulting bitvector will have no more than size/goarch.PtrSize bits.
func progToPointerMask(prog *byte, size uintptr) bitvector {
n := (size/goarch.PtrSize + 7) / 8
x := (*[1 << 30]byte)(persistentalloc(n+1, 1, &memstats.buckhash_sys))[:n+1]
@@ -1697,7 +1697,7 @@ Run:
// into a register and use that register for the entire loop
// instead of repeatedly reading from memory.
// Handling fewer than 8 bits here makes the general loop simpler.
- // The cutoff is sys.PtrSize*8 - 7 to guarantee that when we add
+ // The cutoff is goarch.PtrSize*8 - 7 to guarantee that when we add
// the pattern to a bit buffer holding at most 7 bits (a partial byte)
// it will not overflow.
src := dst
diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go
index 6df8af45a8..f06560201a 100644
--- a/src/runtime/mgcpacer.go
+++ b/src/runtime/mgcpacer.go
@@ -677,7 +677,8 @@ func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) floa
if debug.gcpacertrace > 0 {
printlock()
- print("pacer: ", int(utilization*100), "% CPU (", int(gcGoalUtilization*100), " exp.) for ")
+ goal := gcGoalUtilization * 100
+ print("pacer: ", int(utilization*100), "% CPU (", int(goal), " exp.) for ")
print(c.heapScanWork.Load(), "+", c.stackScanWork.Load(), "+", c.globalsScanWork.Load(), " B work (", c.lastHeapScan+c.stackScan+c.globalsScan, " B exp.) ")
print("in ", c.trigger, " B -> ", c.heapLive, " B (∆goal ", int64(c.heapLive)-int64(c.heapGoal), ", cons/mark ", oldConsMark, ")")
println()
diff --git a/src/runtime/slice.go b/src/runtime/slice.go
index ac0b7d5fef..e0aeba604f 100644
--- a/src/runtime/slice.go
+++ b/src/runtime/slice.go
@@ -214,7 +214,7 @@ func growslice(et *_type, old slice, cap int) slice {
var lenmem, newlenmem, capmem uintptr
// Specialize for common values of et.size.
// For 1 we don't need any division/multiplication.
- // For sys.PtrSize, compiler will optimize division/multiplication into a shift by a constant.
+ // For goarch.PtrSize, compiler will optimize division/multiplication into a shift by a constant.
// For powers of 2, use a variable shift.
switch {
case et.size == 1:
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go
index 21dd95a397..017b0a0749 100644
--- a/src/runtime/symtab.go
+++ b/src/runtime/symtab.go
@@ -863,7 +863,7 @@ type pcvalueCacheEnt struct {
// pcvalueCacheKey returns the outermost index in a pcvalueCache to use for targetpc.
// It must be very cheap to calculate.
-// For now, align to sys.PtrSize and reduce mod the number of entries.
+// For now, align to goarch.PtrSize and reduce mod the number of entries.
// In practice, this appears to be fairly randomly and evenly distributed.
func pcvalueCacheKey(targetpc uintptr) uintptr {
return (targetpc / goarch.PtrSize) % uintptr(len(pcvalueCache{}.entries))
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index e76b403ade..9c38facf08 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -152,7 +152,7 @@ func (p *abiDesc) assignArg(t *_type) {
// tryRegAssignArg tries to register-assign a value of type t.
// If this type is nested in an aggregate type, then offset is the
// offset of this type within its parent type.
-// Assumes t.size <= sys.PtrSize and t.size != 0.
+// Assumes t.size <= goarch.PtrSize and t.size != 0.
//
// Returns whether the assignment succeeded.
func (p *abiDesc) tryRegAssignArg(t *_type, offset uintptr) bool {
diff --git a/src/runtime/testdata/testprogcgo/aprof.go b/src/runtime/testdata/testprogcgo/aprof.go
index 44a15b0865..c70d6333bb 100644
--- a/src/runtime/testdata/testprogcgo/aprof.go
+++ b/src/runtime/testdata/testprogcgo/aprof.go
@@ -7,8 +7,11 @@ package main
// Test that SIGPROF received in C code does not crash the process
// looking for the C code's func pointer.
-// The test fails when the function is the first C function.
-// The exported functions are the first C functions, so we use that.
+// This is a regression test for issue 14599, where profiling fails when the
+// function is the first C function. Exported functions are the first C
+// functions, so we use an exported function. Exported functions are created in
+// lexigraphical order of source files, so this file is named aprof.go to
+// ensure its function is first.
// extern void CallGoNop();
import "C"
diff --git a/src/runtime/testdata/testprogcgo/pprof_callback.go b/src/runtime/testdata/testprogcgo/pprof_callback.go
new file mode 100644
index 0000000000..e34564395e
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/pprof_callback.go
@@ -0,0 +1,89 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !plan9 && !windows
+
+package main
+
+// Make many C-to-Go callback while collecting a CPU profile.
+//
+// This is a regression test for issue 50936.
+
+/*
+#include <unistd.h>
+
+void goCallbackPprof();
+
+static void callGo() {
+ // Spent >20us in C so this thread is eligible for sysmon to retake its
+ // P.
+ usleep(50);
+ goCallbackPprof();
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "runtime/pprof"
+ "runtime"
+ "time"
+)
+
+func init() {
+ register("CgoPprofCallback", CgoPprofCallback)
+}
+
+//export goCallbackPprof
+func goCallbackPprof() {
+ // No-op. We want to stress the cgocall and cgocallback internals,
+ // landing as many pprof signals there as possible.
+}
+
+func CgoPprofCallback() {
+ // Issue 50936 was a crash in the SIGPROF handler when the signal
+ // arrived during the exitsyscall following a cgocall(back) in dropg or
+ // execute, when updating mp.curg.
+ //
+ // These are reachable only when exitsyscall finds no P available. Thus
+ // we make C calls from significantly more Gs than there are available
+ // Ps. Lots of runnable work combined with >20us spent in callGo makes
+ // it possible for sysmon to retake Ps, forcing C calls to go down the
+ // desired exitsyscall path.
+ //
+ // High GOMAXPROCS is used to increase opportunities for failure on
+ // high CPU machines.
+ const (
+ P = 16
+ G = 64
+ )
+ runtime.GOMAXPROCS(P)
+
+ f, err := os.CreateTemp("", "prof")
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(2)
+ }
+ defer f.Close()
+
+ if err := pprof.StartCPUProfile(f); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(2)
+ }
+
+ for i := 0; i < G; i++ {
+ go func() {
+ for {
+ C.callGo()
+ }
+ }()
+ }
+
+ time.Sleep(time.Second)
+
+ pprof.StopCPUProfile()
+
+ fmt.Println("OK")
+}