Commit c9321f3f authored by Dmitry Vyukov's avatar Dmitry Vyukov

runtime: fix nosplit stack overflow

The overflow happens only with -gcflags="-N -l"
and can be reproduced with:

$ go test -gcflags="-N -l" -a -run=none net

runtime.cgocall: nosplit stack overflow
	504	assumed on entry to runtime.cgocall
	480	after runtime.cgocall uses 24
	472	on entry to runtime.cgocall_errno
	408	after runtime.cgocall_errno uses 64
	400	on entry to runtime.exitsyscall
	288	after runtime.exitsyscall uses 112
	280	on entry to runtime.exitsyscallfast
	152	after runtime.exitsyscallfast uses 128
	144	on entry to runtime.writebarrierptr
	88	after runtime.writebarrierptr uses 56
	80	on entry to runtime.writebarrierptr_nostore1
	24	after runtime.writebarrierptr_nostore1 uses 56
	16	on entry to runtime.acquirem
	-24	after runtime.acquirem uses 40

Move closure creation into separate function so that
frames of writebarrierptr_shadow and writebarrierptr_nostore1
are overlapped.

Fixes #9721

Change-Id: I40851f0786763ee964af34814edbc3e3d73cf4e7
Reviewed-on: https://go-review.googlesource.com/3418Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 4a45ac57
......@@ -110,28 +110,33 @@ func writebarrierptr(dst *uintptr, src uintptr) {
}
if mheap_.shadow_enabled {
systemstack(func() {
addr := uintptr(unsafe.Pointer(dst))
shadow := shadowptr(addr)
if shadow == nil {
return
}
// There is a race here but only if the program is using
// racy writes instead of sync/atomic. In that case we
// don't mind crashing.
if *shadow != *dst && *shadow != noShadow && istrackedptr(*dst) {
mheap_.shadow_enabled = false
print("runtime: write barrier dst=", dst, " old=", hex(*dst), " shadow=", shadow, " old=", hex(*shadow), " new=", hex(src), "\n")
throw("missed write barrier")
}
*shadow = src
})
writebarrierptr_shadow(dst, src)
}
*dst = src
writebarrierptr_nostore1(dst, src)
}
//go:nosplit
func writebarrierptr_shadow(dst *uintptr, src uintptr) {
systemstack(func() {
addr := uintptr(unsafe.Pointer(dst))
shadow := shadowptr(addr)
if shadow == nil {
return
}
// There is a race here but only if the program is using
// racy writes instead of sync/atomic. In that case we
// don't mind crashing.
if *shadow != *dst && *shadow != noShadow && istrackedptr(*dst) {
mheap_.shadow_enabled = false
print("runtime: write barrier dst=", dst, " old=", hex(*dst), " shadow=", shadow, " old=", hex(*shadow), " new=", hex(src), "\n")
throw("missed write barrier")
}
*shadow = src
})
}
// Like writebarrierptr, but the store has already been applied.
// Do not reapply.
//go:nosplit
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment