atomic_pointer.go 2.64 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 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.

17 18 19 20 21 22 23 24 25 26 27
// atomicwb performs a write barrier before an atomic pointer write.
// The caller should guard the call with "if writeBarrier.enabled".
//
//go:nosplit
func atomicwb(ptr *unsafe.Pointer, new unsafe.Pointer) {
	slot := (*uintptr)(unsafe.Pointer(ptr))
	if !getg().m.p.ptr().wbBuf.putFast(*slot, uintptr(new)) {
		wbBufFlush(slot, uintptr(new))
	}
}

28 29 30 31
// atomicstorep performs *ptr = new atomically and invokes a write barrier.
//
//go:nosplit
func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
32 33 34
	if writeBarrier.enabled {
		atomicwb((*unsafe.Pointer)(ptr), new)
	}
35 36 37 38 39 40 41
	atomic.StorepNoWB(noescape(ptr), 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.

42
//go:linkname sync_atomic_StoreUintptr sync..z2fatomic.StoreUintptr
43 44
func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr)

45
//go:linkname sync_atomic_StorePointer sync..z2fatomic.StorePointer
46 47
//go:nosplit
func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
48 49 50
	if writeBarrier.enabled {
		atomicwb(ptr, new)
	}
51 52 53
	sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
}

54
//go:linkname sync_atomic_SwapUintptr sync..z2fatomic.SwapUintptr
55 56
func sync_atomic_SwapUintptr(ptr *uintptr, new uintptr) uintptr

57
//go:linkname sync_atomic_SwapPointer sync..z2fatomic.SwapPointer
58 59
//go:nosplit
func sync_atomic_SwapPointer(ptr *unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
60 61 62
	if writeBarrier.enabled {
		atomicwb(ptr, new)
	}
63 64 65 66
	old := unsafe.Pointer(sync_atomic_SwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(new)))
	return old
}

67
//go:linkname sync_atomic_CompareAndSwapUintptr sync..z2fatomic.CompareAndSwapUintptr
68 69
func sync_atomic_CompareAndSwapUintptr(ptr *uintptr, old, new uintptr) bool

70
//go:linkname sync_atomic_CompareAndSwapPointer sync..z2fatomic.CompareAndSwapPointer
71 72
//go:nosplit
func sync_atomic_CompareAndSwapPointer(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
73 74 75
	if writeBarrier.enabled {
		atomicwb(ptr, new)
	}
76 77
	return sync_atomic_CompareAndSwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(old), uintptr(new))
}