From: qiulaidongfeng <2645477756@qq.com> Date: Tue, 15 Aug 2023 02:14:00 +0000 (+0000) Subject: sync: document why copyChecker checks the condition twice X-Git-Tag: go1.22rc1~1273 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=18b2c45b0abc81529644b7cc6b009395e1840756;p=gostls13.git sync: document why copyChecker checks the condition twice Fixes #40924 Change-Id: I249a278be1ec3c67088819af4456e6c393431724 Change-Id: I249a278be1ec3c67088819af4456e6c393431724 GitHub-Last-Rev: 772c7ae7e140ebd3896fc7786aae8b43ab3128c3 GitHub-Pull-Request: golang/go#61978 Reviewed-on: https://go-review.googlesource.com/c/go/+/518961 Reviewed-by: David Chase TryBot-Result: Gopher Robot Reviewed-by: Michael Knyszek Run-TryBot: Austin Clements Auto-Submit: Austin Clements --- diff --git a/src/sync/cond.go b/src/sync/cond.go index cc927adf58..7ef3188a1e 100644 --- a/src/sync/cond.go +++ b/src/sync/cond.go @@ -96,6 +96,10 @@ func (c *Cond) Broadcast() { type copyChecker uintptr func (c *copyChecker) check() { + // Check if c has been copied in three steps: + // 1. The first comparison is the fast-path. If c has been initialized and not copied, this will return immediately. Otherwise, c is either not initialized, or has been copied. + // 2. Ensure c is initialized. If the CAS succeeds, we're done. If it fails, c was either initialized concurrently and we simply lost the race, or c has been copied. + // 3. Do step 1 again. Now that c is definitely initialized, if this fails, c was copied. if uintptr(*c) != uintptr(unsafe.Pointer(c)) && !atomic.CompareAndSwapUintptr((*uintptr)(c), 0, uintptr(unsafe.Pointer(c))) && uintptr(*c) != uintptr(unsafe.Pointer(c)) {