blob: ec2ea8a3384234ccb8f0a2ef58eeedc0d7a0e1e1 [file] [log] [blame]
Russ Cox7b4df8f2014-12-22 22:50:42 -05001// 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
5package runtime
6
7import "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.
Michael Hudson-Doyled497eeb2015-08-27 10:59:43 +120013// Instead, these are wrappers around the actual atomics (casp1 and so on)
Russ Cox7b4df8f2014-12-22 22:50:42 -050014// 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
20func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
21 atomicstorep1(noescape(ptr), new)
22 writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
Russ Cox7b4df8f2014-12-22 22:50:42 -050023}
24
25//go:nosplit
Russ Cox7b4df8f2014-12-22 22:50:42 -050026func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
27 if !casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new) {
28 return false
29 }
30 writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
Russ Cox7b4df8f2014-12-22 22:50:42 -050031 return true
32}
33
34// Like above, but implement in terms of sync/atomic's uintptr operations.
35// We cannot just call the runtime routines, because the race detector expects
36// to be able to intercept the sync/atomic forms but not the runtime forms.
37
38//go:linkname sync_atomic_StoreUintptr sync/atomic.StoreUintptr
39func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr)
40
41//go:linkname sync_atomic_StorePointer sync/atomic.StorePointer
42//go:nosplit
43func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
44 sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
45 atomicstorep1(noescape(unsafe.Pointer(ptr)), new)
46 writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
Russ Cox7b4df8f2014-12-22 22:50:42 -050047}
48
49//go:linkname sync_atomic_SwapUintptr sync/atomic.SwapUintptr
50func sync_atomic_SwapUintptr(ptr *uintptr, new uintptr) uintptr
51
52//go:linkname sync_atomic_SwapPointer sync/atomic.SwapPointer
53//go:nosplit
54func sync_atomic_SwapPointer(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
55 old := unsafe.Pointer(sync_atomic_SwapUintptr((*uintptr)(noescape(ptr)), uintptr(new)))
56 writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
Russ Cox7b4df8f2014-12-22 22:50:42 -050057 return old
58}
59
60//go:linkname sync_atomic_CompareAndSwapUintptr sync/atomic.CompareAndSwapUintptr
61func sync_atomic_CompareAndSwapUintptr(ptr *uintptr, old, new uintptr) bool
62
63//go:linkname sync_atomic_CompareAndSwapPointer sync/atomic.CompareAndSwapPointer
64//go:nosplit
65func sync_atomic_CompareAndSwapPointer(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
66 if !sync_atomic_CompareAndSwapUintptr((*uintptr)(noescape(unsafe.Pointer(ptr))), uintptr(old), uintptr(new)) {
67 return false
68 }
69 writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
Russ Cox7b4df8f2014-12-22 22:50:42 -050070 return true
71}