github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/runtime/atomic_pointer.go (about)

     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  // Instead, these are wrappers around the actual atomics (casp1 and so on)
    17  // that use noescape to convey which arguments do not escape.
    18  //
    19  // Additionally, these functions must update the shadow heap for
    20  // write barrier checking.
    21  
    22  //go:nosplit
    23  func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
    24  	atomic.Storep1(noescape(ptr), new)
    25  	writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
    26  }
    27  
    28  //go:nosplit
    29  func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
    30  	if !atomic.Casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new) {
    31  		return false
    32  	}
    33  	writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
    34  	return true
    35  }
    36  
    37  // Like above, but implement in terms of sync/atomic's uintptr operations.
    38  // We cannot just call the runtime routines, because the race detector expects
    39  // to be able to intercept the sync/atomic forms but not the runtime forms.
    40  
    41  //go:linkname sync_atomic_StoreUintptr sync/atomic.StoreUintptr
    42  func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr)
    43  
    44  //go:linkname sync_atomic_StorePointer sync/atomic.StorePointer
    45  //go:nosplit
    46  func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
    47  	sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
    48  	atomic.Storep1(noescape(unsafe.Pointer(ptr)), new)
    49  	writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
    50  }
    51  
    52  //go:linkname sync_atomic_SwapUintptr sync/atomic.SwapUintptr
    53  func sync_atomic_SwapUintptr(ptr *uintptr, new uintptr) uintptr
    54  
    55  //go:linkname sync_atomic_SwapPointer sync/atomic.SwapPointer
    56  //go:nosplit
    57  func sync_atomic_SwapPointer(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
    58  	old := unsafe.Pointer(sync_atomic_SwapUintptr((*uintptr)(noescape(ptr)), uintptr(new)))
    59  	writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
    60  	return old
    61  }
    62  
    63  //go:linkname sync_atomic_CompareAndSwapUintptr sync/atomic.CompareAndSwapUintptr
    64  func sync_atomic_CompareAndSwapUintptr(ptr *uintptr, old, new uintptr) bool
    65  
    66  //go:linkname sync_atomic_CompareAndSwapPointer sync/atomic.CompareAndSwapPointer
    67  //go:nosplit
    68  func sync_atomic_CompareAndSwapPointer(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
    69  	if !sync_atomic_CompareAndSwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(old), uintptr(new)) {
    70  		return false
    71  	}
    72  	writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
    73  	return true
    74  }