runtime_unsafe.go raw
1 // Copyright 2020 The gVisor Authors.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
5
6 // //go:linkname directives type-checked by checklinkname.
7 // Runtime type copies checked by checkoffset.
8
9 package sync
10
11 import (
12 "fmt"
13 "reflect"
14 "unsafe"
15 )
16
17 // Goyield is runtime.goyield, which is similar to runtime.Gosched but only
18 // yields the processor to other goroutines already on the processor's
19 // runqueue.
20 //
21 //go:nosplit
22 func Goyield() {
23 goyield()
24 }
25
26 // Gopark is runtime.gopark. Gopark calls unlockf(pointer to runtime.g, lock);
27 // if unlockf returns true, Gopark blocks until Goready(pointer to runtime.g)
28 // is called. unlockf and its callees must be nosplit and norace, since stack
29 // splitting and race context are not available where it is called.
30 //
31 //go:nosplit
32 func Gopark(unlockf func(uintptr, unsafe.Pointer) bool, lock unsafe.Pointer, reason uint8, traceReason TraceBlockReason, traceskip int) {
33 gopark(unlockf, lock, reason, traceReason, traceskip)
34 }
35
36 //go:linkname gopark runtime.gopark
37 func gopark(unlockf func(uintptr, unsafe.Pointer) bool, lock unsafe.Pointer, reason uint8, traceReason TraceBlockReason, traceskip int)
38
39 // TraceBlockReason is equivalent to runtime.traceBlockReason.
40 type TraceBlockReason uint8
41
42 //go:linkname wakep runtime.wakep
43 func wakep()
44
45 // Wakep is runtime.wakep.
46 //
47 //go:nosplit
48 func Wakep() {
49 // This is only supported if we can suppress the wakep called
50 // from Goready below, which is in certain architectures only.
51 if supportsWakeSuppression {
52 wakep()
53 }
54 }
55
56 //go:linkname goready runtime.goready
57 func goready(gp uintptr, traceskip int)
58
59 // Goready is runtime.goready.
60 //
61 // The additional wakep argument controls whether a new thread will be kicked to
62 // execute the P. This should be true in most circumstances. However, if the
63 // current thread is about to sleep, then this can be false for efficiency.
64 //
65 //go:nosplit
66 func Goready(gp uintptr, traceskip int, wakep bool) {
67 if supportsWakeSuppression && !wakep {
68 preGoReadyWakeSuppression()
69 }
70 goready(gp, traceskip)
71 if supportsWakeSuppression && !wakep {
72 postGoReadyWakeSuppression()
73 }
74 }
75
76 // Rand32 returns a non-cryptographically-secure random uint32.
77 func Rand32() uint32 {
78 return fastrand()
79 }
80
81 // Rand64 returns a non-cryptographically-secure random uint64.
82 func Rand64() uint64 {
83 return uint64(fastrand())<<32 | uint64(fastrand())
84 }
85
86 //go:linkname fastrand runtime.fastrand
87 func fastrand() uint32
88
89 // RandUintptr returns a non-cryptographically-secure random uintptr.
90 func RandUintptr() uintptr {
91 if unsafe.Sizeof(uintptr(0)) == 4 {
92 return uintptr(Rand32())
93 }
94 return uintptr(Rand64())
95 }
96
97 // MapKeyHasher returns a hash function for pointers of m's key type.
98 //
99 // Preconditions: m must be a map.
100 func MapKeyHasher(m any) func(unsafe.Pointer, uintptr) uintptr {
101 if rtyp := reflect.TypeOf(m); rtyp.Kind() != reflect.Map {
102 panic(fmt.Sprintf("sync.MapKeyHasher: m is %v, not map", rtyp))
103 }
104 mtyp := *(**maptype)(unsafe.Pointer(&m))
105 return mtyp.Hasher
106 }
107
108 // maptype is equivalent to the beginning of internal/abi.MapType.
109 type maptype struct {
110 size uintptr
111 ptrdata uintptr
112 hash uint32
113 tflag uint8
114 align uint8
115 fieldAlign uint8
116 kind uint8
117 equal func(unsafe.Pointer, unsafe.Pointer) bool
118 gcdata *byte
119 str int32
120 ptrToThis int32
121 key unsafe.Pointer
122 elem unsafe.Pointer
123 bucket unsafe.Pointer
124 Hasher func(unsafe.Pointer, uintptr) uintptr
125 // more fields
126 }
127
128 // These functions are only used within the sync package.
129
130 //go:linkname semacquire sync.runtime_Semacquire
131 func semacquire(addr *uint32)
132
133 //go:linkname semrelease sync.runtime_Semrelease
134 func semrelease(addr *uint32, handoff bool, skipframes int)
135
136 //go:linkname canSpin sync.runtime_canSpin
137 func canSpin(i int) bool
138
139 //go:linkname doSpin sync.runtime_doSpin
140 func doSpin()
141