...
Source file
src/runtime/debugcall.go
Documentation: runtime
1
2
3
4
5
6
7
8
9
10 package runtime
11
12 import (
13 "internal/abi"
14 "unsafe"
15 )
16
17 const (
18 debugCallSystemStack = "executing on Go runtime stack"
19 debugCallUnknownFunc = "call from unknown function"
20 debugCallRuntime = "call from within the Go runtime"
21 debugCallUnsafePoint = "call not at safe point"
22 )
23
24 func debugCallV2()
25 func debugCallPanicked(val any)
26
27
28
29
30
31
32 func debugCallCheck(pc uintptr) string {
33
34 if getg() != getg().m.curg {
35 return debugCallSystemStack
36 }
37 if sp := getcallersp(); !(getg().stack.lo < sp && sp <= getg().stack.hi) {
38
39
40
41
42 return debugCallSystemStack
43 }
44
45
46
47 var ret string
48 systemstack(func() {
49 f := findfunc(pc)
50 if !f.valid() {
51 ret = debugCallUnknownFunc
52 return
53 }
54
55 name := funcname(f)
56
57 switch name {
58 case "debugCall32",
59 "debugCall64",
60 "debugCall128",
61 "debugCall256",
62 "debugCall512",
63 "debugCall1024",
64 "debugCall2048",
65 "debugCall4096",
66 "debugCall8192",
67 "debugCall16384",
68 "debugCall32768",
69 "debugCall65536":
70
71
72 return
73 }
74
75
76
77
78
79
80 if pfx := "runtime."; len(name) > len(pfx) && name[:len(pfx)] == pfx {
81 ret = debugCallRuntime
82 return
83 }
84
85
86 if pc != f.entry() {
87 pc--
88 }
89 up := pcdatavalue(f, abi.PCDATA_UnsafePoint, pc)
90 if up != abi.UnsafePointSafe {
91
92 ret = debugCallUnsafePoint
93 }
94 })
95 return ret
96 }
97
98
99
100
101
102
103
104
105
106
107 func debugCallWrap(dispatch uintptr) {
108 var lockedExt uint32
109 callerpc := getcallerpc()
110 gp := getg()
111
112
113
114
115
116
117
118 lockOSThread()
119
120
121
122 systemstack(func() {
123
124
125
126 fn := debugCallWrap1
127 newg := newproc1(*(**funcval)(unsafe.Pointer(&fn)), gp, callerpc)
128 args := &debugCallWrapArgs{
129 dispatch: dispatch,
130 callingG: gp,
131 }
132 newg.param = unsafe.Pointer(args)
133
134
135
136 mp := gp.m
137 if mp != gp.lockedm.ptr() {
138 throw("inconsistent lockedm")
139 }
140
141
142
143
144 lockedExt = mp.lockedExt
145 mp.lockedExt = 0
146
147 mp.lockedg.set(newg)
148 newg.lockedm.set(mp)
149 gp.lockedm = 0
150
151
152
153
154
155 gp.asyncSafePoint = true
156
157
158
159 gp.schedlink.set(newg)
160 })
161
162
163 mcall(func(gp *g) {
164
165 newg := gp.schedlink.ptr()
166 gp.schedlink = 0
167
168
169 trace := traceAcquire()
170 casGToWaiting(gp, _Grunning, waitReasonDebugCall)
171 if trace.ok() {
172 trace.GoPark(traceBlockDebugCall, 1)
173 traceRelease(trace)
174 }
175 dropg()
176
177
178
179
180
181 execute(newg, true)
182 })
183
184
185
186
187 mp := gp.m
188 mp.lockedExt = lockedExt
189 mp.lockedg.set(gp)
190 gp.lockedm.set(mp)
191
192
193 unlockOSThread()
194
195 gp.asyncSafePoint = false
196 }
197
198 type debugCallWrapArgs struct {
199 dispatch uintptr
200 callingG *g
201 }
202
203
204
205 func debugCallWrap1() {
206 gp := getg()
207 args := (*debugCallWrapArgs)(gp.param)
208 dispatch, callingG := args.dispatch, args.callingG
209 gp.param = nil
210
211
212 debugCallWrap2(dispatch)
213
214
215 getg().schedlink.set(callingG)
216 mcall(func(gp *g) {
217 callingG := gp.schedlink.ptr()
218 gp.schedlink = 0
219
220
221
222 if gp.lockedm != 0 {
223 gp.lockedm = 0
224 gp.m.lockedg = 0
225 }
226
227
228
229
230 trace := traceAcquire()
231 casgstatus(gp, _Grunning, _Grunnable)
232 if trace.ok() {
233 trace.GoSched()
234 traceRelease(trace)
235 }
236 dropg()
237 lock(&sched.lock)
238 globrunqput(gp)
239 unlock(&sched.lock)
240
241 trace = traceAcquire()
242 casgstatus(callingG, _Gwaiting, _Grunnable)
243 if trace.ok() {
244 trace.GoUnpark(callingG, 0)
245 traceRelease(trace)
246 }
247 execute(callingG, true)
248 })
249 }
250
251 func debugCallWrap2(dispatch uintptr) {
252
253 var dispatchF func()
254 dispatchFV := funcval{dispatch}
255 *(*unsafe.Pointer)(unsafe.Pointer(&dispatchF)) = noescape(unsafe.Pointer(&dispatchFV))
256
257 var ok bool
258 defer func() {
259 if !ok {
260 err := recover()
261 debugCallPanicked(err)
262 }
263 }()
264 dispatchF()
265 ok = true
266 }
267
View as plain text