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