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