...

Source file src/runtime/atomic_pointer.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package runtime
     6	
     7	import (
     8		"runtime/internal/atomic"
     9		"unsafe"
    10	)
    11	
    12	// These functions cannot have go:noescape annotations,
    13	// because while ptr does not escape, new does.
    14	// If new is marked as not escaping, the compiler will make incorrect
    15	// escape analysis decisions about the pointer value being stored.
    16	
    17	// atomicwb performs a write barrier before an atomic pointer write.
    18	// The caller should guard the call with "if writeBarrier.enabled".
    19	//
    20	//go:nosplit
    21	func atomicwb(ptr *unsafe.Pointer, new unsafe.Pointer) {
    22		slot := (*uintptr)(unsafe.Pointer(ptr))
    23		if !getg().m.p.ptr().wbBuf.putFast(*slot, uintptr(new)) {
    24			wbBufFlush(slot, uintptr(new))
    25		}
    26	}
    27	
    28	// atomicstorep performs *ptr = new atomically and invokes a write barrier.
    29	//
    30	//go:nosplit
    31	func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
    32		if writeBarrier.enabled {
    33			atomicwb((*unsafe.Pointer)(ptr), new)
    34		}
    35		atomic.StorepNoWB(noescape(ptr), new)
    36	}
    37	
    38	// Like above, but implement in terms of sync/atomic's uintptr operations.
    39	// We cannot just call the runtime routines, because the race detector expects
    40	// to be able to intercept the sync/atomic forms but not the runtime forms.
    41	
    42	//go:linkname sync_atomic_StoreUintptr sync/atomic.StoreUintptr
    43	func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr)
    44	
    45	//go:linkname sync_atomic_StorePointer sync/atomic.StorePointer
    46	//go:nosplit
    47	func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
    48		if writeBarrier.enabled {
    49			atomicwb(ptr, new)
    50		}
    51		sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
    52	}
    53	
    54	//go:linkname sync_atomic_SwapUintptr sync/atomic.SwapUintptr
    55	func sync_atomic_SwapUintptr(ptr *uintptr, new uintptr) uintptr
    56	
    57	//go:linkname sync_atomic_SwapPointer sync/atomic.SwapPointer
    58	//go:nosplit
    59	func sync_atomic_SwapPointer(ptr *unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
    60		if writeBarrier.enabled {
    61			atomicwb(ptr, new)
    62		}
    63		old := unsafe.Pointer(sync_atomic_SwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(new)))
    64		return old
    65	}
    66	
    67	//go:linkname sync_atomic_CompareAndSwapUintptr sync/atomic.CompareAndSwapUintptr
    68	func sync_atomic_CompareAndSwapUintptr(ptr *uintptr, old, new uintptr) bool
    69	
    70	//go:linkname sync_atomic_CompareAndSwapPointer sync/atomic.CompareAndSwapPointer
    71	//go:nosplit
    72	func sync_atomic_CompareAndSwapPointer(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
    73		if writeBarrier.enabled {
    74			atomicwb(ptr, new)
    75		}
    76		return sync_atomic_CompareAndSwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(old), uintptr(new))
    77	}
    78	

View as plain text