aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2018-02-12 18:50:16 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2018-02-12 18:50:16 +0000
commitba77fca17780b71bcc94992a7e40130baf6b32ab (patch)
tree578d5adc5ed91aadca2a5f5059f17c7211a8d514 /libgo
parent322eecc05ae600004bdc1e93885c4b735f5924ed (diff)
PR go/84215
runtime, sync/atomic: use write barrier for atomic pointer functions This copies atomic_pointer.go from 1.10rc2. It was omitted during the transition of the runtime from C to Go, and I forgot about it. This may help with https://gcc.gnu.org/PR84215. Reviewed-on: https://go-review.googlesource.com/93197 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257599 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/runtime/atomic_pointer.go69
-rw-r--r--libgo/go/runtime/stubs.go16
-rw-r--r--libgo/go/sync/atomic/atomic.c34
3 files changed, 69 insertions, 50 deletions
diff --git a/libgo/go/runtime/atomic_pointer.go b/libgo/go/runtime/atomic_pointer.go
new file mode 100644
index 00000000000..b66ef5896db
--- /dev/null
+++ b/libgo/go/runtime/atomic_pointer.go
@@ -0,0 +1,69 @@
+// Copyright 2009 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.
+
+package runtime
+
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
+
+// These functions cannot have go:noescape annotations,
+// because while ptr does not escape, new does.
+// If new is marked as not escaping, the compiler will make incorrect
+// escape analysis decisions about the pointer value being stored.
+// Instead, these are wrappers around the actual atomics (casp1 and so on)
+// that use noescape to convey which arguments do not escape.
+
+// atomicstorep performs *ptr = new atomically and invokes a write barrier.
+//
+//go:nosplit
+func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
+ writebarrierptr_prewrite((*uintptr)(ptr), uintptr(new))
+ atomic.StorepNoWB(noescape(ptr), new)
+}
+
+//go:nosplit
+func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
+ // The write barrier is only necessary if the CAS succeeds,
+ // but since it needs to happen before the write becomes
+ // public, we have to do it conservatively all the time.
+ writebarrierptr_prewrite((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
+ return atomic.Casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new)
+}
+
+// Like above, but implement in terms of sync/atomic's uintptr operations.
+// We cannot just call the runtime routines, because the race detector expects
+// to be able to intercept the sync/atomic forms but not the runtime forms.
+
+//go:linkname sync_atomic_StoreUintptr sync_atomic.StoreUintptr
+func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr)
+
+//go:linkname sync_atomic_StorePointer sync_atomic.StorePointer
+//go:nosplit
+func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
+ writebarrierptr_prewrite((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
+ sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
+}
+
+//go:linkname sync_atomic_SwapUintptr sync_atomic.SwapUintptr
+func sync_atomic_SwapUintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:linkname sync_atomic_SwapPointer sync_atomic.SwapPointer
+//go:nosplit
+func sync_atomic_SwapPointer(ptr *unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
+ writebarrierptr_prewrite((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
+ old := unsafe.Pointer(sync_atomic_SwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(new)))
+ return old
+}
+
+//go:linkname sync_atomic_CompareAndSwapUintptr sync_atomic.CompareAndSwapUintptr
+func sync_atomic_CompareAndSwapUintptr(ptr *uintptr, old, new uintptr) bool
+
+//go:linkname sync_atomic_CompareAndSwapPointer sync_atomic.CompareAndSwapPointer
+//go:nosplit
+func sync_atomic_CompareAndSwapPointer(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
+ writebarrierptr_prewrite((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
+ return sync_atomic_CompareAndSwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(old), uintptr(new))
+}
diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go
index fa3b1ce9552..efb037399bf 100644
--- a/libgo/go/runtime/stubs.go
+++ b/libgo/go/runtime/stubs.go
@@ -5,7 +5,6 @@
package runtime
import (
- "runtime/internal/atomic"
"runtime/internal/sys"
"unsafe"
)
@@ -307,15 +306,6 @@ func setSupportAES(v bool) {
support_aes = v
}
-// Here for gccgo until we port atomic_pointer.go and mgc.go.
-//go:nosplit
-func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
- if !atomic.Casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new) {
- return false
- }
- return true
-}
-
// Here for gccgo until we port lock_*.go.
func lock(l *mutex)
func unlock(l *mutex)
@@ -347,12 +337,6 @@ func persistentalloc(size, align uintptr, sysStat *uint64) unsafe.Pointer
// Temporary for gccgo until we port mheap.go
func setprofilebucket(p unsafe.Pointer, b *bucket)
-// Temporary for gccgo until we port atomic_pointer.go.
-//go:nosplit
-func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
- atomic.StorepNoWB(noescape(ptr), new)
-}
-
// Get signal trampoline, written in C.
func getSigtramp() uintptr
diff --git a/libgo/go/sync/atomic/atomic.c b/libgo/go/sync/atomic/atomic.c
index 32cbf03c5cf..07a43063b7c 100644
--- a/libgo/go/sync/atomic/atomic.c
+++ b/libgo/go/sync/atomic/atomic.c
@@ -62,16 +62,6 @@ SwapUintptr (uintptr_t *addr, uintptr_t new)
return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
}
-void *SwapPointer (void **, void *)
- __asm__ (GOSYM_PREFIX "sync_atomic.SwapPointer")
- __attribute__ ((no_split_stack));
-
-void *
-SwapPointer (void **addr, void *new)
-{
- return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
-}
-
_Bool CompareAndSwapInt32 (int32_t *, int32_t, int32_t)
__asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt32")
__attribute__ ((no_split_stack));
@@ -126,16 +116,6 @@ CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new)
return __sync_bool_compare_and_swap (val, old, new);
}
-_Bool CompareAndSwapPointer (void **, void *, void *)
- __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapPointer")
- __attribute__ ((no_split_stack));
-
-_Bool
-CompareAndSwapPointer (void **val, void *old, void *new)
-{
- return __sync_bool_compare_and_swap (val, old, new);
-}
-
int32_t AddInt32 (int32_t *, int32_t)
__asm__ (GOSYM_PREFIX "sync_atomic.AddInt32")
__attribute__ ((no_split_stack));
@@ -357,17 +337,3 @@ StoreUintptr (uintptr_t *addr, uintptr_t val)
while (! __sync_bool_compare_and_swap (addr, v, val))
v = *addr;
}
-
-void StorePointer (void **addr, void *val)
- __asm__ (GOSYM_PREFIX "sync_atomic.StorePointer")
- __attribute__ ((no_split_stack));
-
-void
-StorePointer (void **addr, void *val)
-{
- void *v;
-
- v = *addr;
- while (! __sync_bool_compare_and_swap (addr, v, val))
- v = *addr;
-}