sync/atomic: use a better first-store-in-progress marker
Unlike what the comment says, the GC can see this pointer.
Might as well make it a real pointer, even though ^uintptr(0)
isn't currently causing problems.
Removed the comment about GC not seeing the pointer.
Change-Id: I04bc1fd4848698bec6afb79bd5fda671dfc9a073
Reviewed-on: https://go-review.googlesource.com/c/go/+/241661
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Colin Arnott <colin@urandom.co.uk>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Keith Randall <khr@golang.org>
diff --git a/src/sync/atomic/value.go b/src/sync/atomic/value.go
index 3500cd2..af6295d 100644
--- a/src/sync/atomic/value.go
+++ b/src/sync/atomic/value.go
@@ -28,7 +28,7 @@
func (v *Value) Load() (val interface{}) {
vp := (*ifaceWords)(unsafe.Pointer(v))
typ := LoadPointer(&vp.typ)
- if typ == nil || uintptr(typ) == ^uintptr(0) {
+ if typ == nil || typ == unsafe.Pointer(&firstStoreInProgress) {
// First store not yet completed.
return nil
}
@@ -39,6 +39,8 @@
return
}
+var firstStoreInProgress byte
+
// Store sets the value of the Value to x.
// All calls to Store for a given Value must use values of the same concrete type.
// Store of an inconsistent type panics, as does Store(nil).
@@ -53,10 +55,9 @@
if typ == nil {
// Attempt to start first store.
// Disable preemption so that other goroutines can use
- // active spin wait to wait for completion; and so that
- // GC does not see the fake type accidentally.
+ // active spin wait to wait for completion.
runtime_procPin()
- if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
+ if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(&firstStoreInProgress)) {
runtime_procUnpin()
continue
}
@@ -66,7 +67,7 @@
runtime_procUnpin()
return
}
- if uintptr(typ) == ^uintptr(0) {
+ if typ == unsafe.Pointer(&firstStoreInProgress) {
// First store in progress. Wait.
// Since we disable preemption around the first store,
// we can wait with active spinning.