Home | History | Annotate | Download | only in runtime
      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 "unsafe"
      8 
      9 // These functions cannot have go:noescape annotations,
     10 // because while ptr does not escape, new does.
     11 // If new is marked as not escaping, the compiler will make incorrect
     12 // escape analysis decisions about the pointer value being stored.
     13 // Instead, these are wrappers around the actual atomics (xchgp1 and so on)
     14 // that use noescape to convey which arguments do not escape.
     15 //
     16 // Additionally, these functions must update the shadow heap for
     17 // write barrier checking.
     18 
     19 //go:nosplit
     20 func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
     21 	atomicstorep1(noescape(ptr), new)
     22 	writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
     23 }
     24 
     25 //go:nosplit
     26 func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
     27 	old := xchgp1(noescape(ptr), new)
     28 	writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
     29 	return old
     30 }
     31 
     32 //go:nosplit
     33 func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
     34 	if !casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new) {
     35 		return false
     36 	}
     37 	writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
     38 	return true
     39 }
     40 
     41 // Like above, but implement in terms of sync/atomic's uintptr operations.
     42 // We cannot just call the runtime routines, because the race detector expects
     43 // to be able to intercept the sync/atomic forms but not the runtime forms.
     44 
     45 //go:linkname sync_atomic_StoreUintptr sync/atomic.StoreUintptr
     46 func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr)
     47 
     48 //go:linkname sync_atomic_StorePointer sync/atomic.StorePointer
     49 //go:nosplit
     50 func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
     51 	sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
     52 	atomicstorep1(noescape(unsafe.Pointer(ptr)), new)
     53 	writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
     54 }
     55 
     56 //go:linkname sync_atomic_SwapUintptr sync/atomic.SwapUintptr
     57 func sync_atomic_SwapUintptr(ptr *uintptr, new uintptr) uintptr
     58 
     59 //go:linkname sync_atomic_SwapPointer sync/atomic.SwapPointer
     60 //go:nosplit
     61 func sync_atomic_SwapPointer(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
     62 	old := unsafe.Pointer(sync_atomic_SwapUintptr((*uintptr)(noescape(ptr)), uintptr(new)))
     63 	writebarrierptr_nostore((*uintptr)(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 !sync_atomic_CompareAndSwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(old), uintptr(new)) {
     74 		return false
     75 	}
     76 	writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
     77 	return true
     78 }
     79