From a71ca3dfbd32faf351ff68bcc26a4d5abd9b06d7 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 26 Jan 2022 16:53:50 -0500 Subject: runtime, sync, sync/atomic: document happens-before guarantees A few of these are copied from the memory model doc. Many are entirely new, following discussion on #47141. See https://research.swtch.com/gomm for background. The rule we are establishing is that each type that is meant to help synchronize a Go program should document its happens-before guarantees. For #50859. Change-Id: I947c40639b263abe67499fa74f68711a97873a39 Reviewed-on: https://go-review.googlesource.com/c/go/+/381316 Auto-Submit: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Ian Lance Taylor Reviewed-by: Alan Donovan TryBot-Result: Gopher Robot Reviewed-by: Roland Shoemaker --- src/runtime/mfinal.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/runtime') diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go index 44174913de..f3f3a79fa5 100644 --- a/src/runtime/mfinal.go +++ b/src/runtime/mfinal.go @@ -321,11 +321,23 @@ func runfinq() { // closing p.d, causing syscall.Write to fail because it is writing to // a closed file descriptor (or, worse, to an entirely different // file descriptor opened by a different goroutine). To avoid this problem, -// call runtime.KeepAlive(p) after the call to syscall.Write. +// call KeepAlive(p) after the call to syscall.Write. // // A single goroutine runs all finalizers for a program, sequentially. // If a finalizer must run for a long time, it should do so by starting // a new goroutine. +// +// In the terminology of the Go memory model, a call +// SetFinalizer(x, f) “synchronizes before” the finalization call f(x). +// However, there is no guarantee that KeepAlive(x) or any other use of x +// “synchronizes before” f(x), so in general a finalizer should use a mutex +// or other synchronization mechanism if it needs to access mutable state in x. +// For example, consider a finalizer that inspects a mutable field in x +// that is modified from time to time in the main program before x +// becomes unreachable and the finalizer is invoked. +// The modifications in the main program and the inspection in the finalizer +// need to use appropriate synchronization, such as mutexes or atomic updates, +// to avoid read-write races. func SetFinalizer(obj any, finalizer any) { if debug.sbrk != 0 { // debug.sbrk never frees memory, so no finalizers run -- cgit v1.3