diff options
| author | Chressie Himpel <chressie@google.com> | 2022-02-08 10:31:51 +0100 |
|---|---|---|
| committer | Chressie Himpel <chressie@google.com> | 2022-02-08 10:31:51 +0100 |
| commit | 74d25c624c01d8deefaf37ee7edb41980d0d5912 (patch) | |
| tree | 7a316cbfaca2f501aa0b8c47a6042973e18c6c67 /src/runtime | |
| parent | e14fee553a4646d15123caa04f7ca6ddb7b48362 (diff) | |
| parent | c856fbf36190cef65ac6639a048cd512e4b7fc0a (diff) | |
| download | go-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.go | 16 | ||||
| -rw-r--r-- | src/runtime/mbarrier.go | 2 | ||||
| -rw-r--r-- | src/runtime/mbitmap.go | 12 | ||||
| -rw-r--r-- | src/runtime/mgcpacer.go | 3 | ||||
| -rw-r--r-- | src/runtime/slice.go | 2 | ||||
| -rw-r--r-- | src/runtime/symtab.go | 2 | ||||
| -rw-r--r-- | src/runtime/syscall_windows.go | 2 | ||||
| -rw-r--r-- | src/runtime/testdata/testprogcgo/aprof.go | 7 | ||||
| -rw-r--r-- | src/runtime/testdata/testprogcgo/pprof_callback.go | 89 |
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") +} |
