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 "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, false, waitReasonZero)
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 if trace.ok() {
171
172
173
174 trace.GoPark(traceBlockDebugCall, 1)
175 }
176 casGToWaiting(gp, _Grunning, waitReasonDebugCall)
177 if trace.ok() {
178 traceRelease(trace)
179 }
180 dropg()
181
182
183
184
185
186 execute(newg, true)
187 })
188
189
190
191
192 mp := gp.m
193 mp.lockedExt = lockedExt
194 mp.lockedg.set(gp)
195 gp.lockedm.set(mp)
196
197
198 unlockOSThread()
199
200 gp.asyncSafePoint = false
201 }
202
203 type debugCallWrapArgs struct {
204 dispatch uintptr
205 callingG *g
206 }
207
208
209
210 func debugCallWrap1() {
211 gp := getg()
212 args := (*debugCallWrapArgs)(gp.param)
213 dispatch, callingG := args.dispatch, args.callingG
214 gp.param = nil
215
216
217 debugCallWrap2(dispatch)
218
219
220 getg().schedlink.set(callingG)
221 mcall(func(gp *g) {
222 callingG := gp.schedlink.ptr()
223 gp.schedlink = 0
224
225
226
227 if gp.lockedm != 0 {
228 gp.lockedm = 0
229 gp.m.lockedg = 0
230 }
231
232
233
234
235 trace := traceAcquire()
236 if trace.ok() {
237
238
239
240 trace.GoSched()
241 }
242 casgstatus(gp, _Grunning, _Grunnable)
243 if trace.ok() {
244 traceRelease(trace)
245 }
246 dropg()
247 lock(&sched.lock)
248 globrunqput(gp)
249 unlock(&sched.lock)
250
251 trace = traceAcquire()
252 casgstatus(callingG, _Gwaiting, _Grunnable)
253 if trace.ok() {
254 trace.GoUnpark(callingG, 0)
255 traceRelease(trace)
256 }
257 execute(callingG, true)
258 })
259 }
260
261 func debugCallWrap2(dispatch uintptr) {
262
263 var dispatchF func()
264 dispatchFV := funcval{dispatch}
265 *(*unsafe.Pointer)(unsafe.Pointer(&dispatchF)) = noescape(unsafe.Pointer(&dispatchFV))
266
267 var ok bool
268 defer func() {
269 if !ok {
270 err := recover()
271 debugCallPanicked(err)
272 }
273 }()
274 dispatchF()
275 ok = true
276 }
277
View as plain text