Skip to content

Commit 4902778

Browse files
runtime: set libcall values for Solaris system calls
This lets SIGPROF signals get a useful traceback. Without it we just see sysvicallN calling asmcgocall. Updates #24142 Change-Id: I5dfe3add51f0c3a4cb1c98acb7738be6396214bc Reviewed-on: https://go-review.googlesource.com/99617 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Austin Clements <[email protected]>
1 parent 8e427a3 commit 4902778

File tree

2 files changed

+120
-1
lines changed

2 files changed

+120
-1
lines changed

src/runtime/os_solaris.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,71 +31,190 @@ var asmsysvicall6 libcFunc
3131

3232
//go:nosplit
3333
func sysvicall0(fn *libcFunc) uintptr {
34+
// Leave caller's PC/SP around for traceback.
35+
gp := getg()
36+
var mp *m
37+
if gp != nil {
38+
mp = gp.m
39+
}
40+
if mp != nil {
41+
mp.libcallg.set(gp)
42+
mp.libcallpc = getcallerpc()
43+
// sp must be the last, because once async cpu profiler finds
44+
// all three values to be non-zero, it will use them
45+
mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
46+
}
47+
3448
var libcall libcall
3549
libcall.fn = uintptr(unsafe.Pointer(fn))
3650
libcall.n = 0
3751
libcall.args = uintptr(unsafe.Pointer(fn)) // it's unused but must be non-nil, otherwise crashes
3852
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
53+
if mp != nil {
54+
mp.libcallsp = 0
55+
}
3956
return libcall.r1
4057
}
4158

4259
//go:nosplit
4360
func sysvicall1(fn *libcFunc, a1 uintptr) uintptr {
61+
// Leave caller's PC/SP around for traceback.
62+
gp := getg()
63+
var mp *m
64+
if gp != nil {
65+
mp = gp.m
66+
}
67+
if mp != nil {
68+
mp.libcallg.set(gp)
69+
mp.libcallpc = getcallerpc()
70+
// sp must be the last, because once async cpu profiler finds
71+
// all three values to be non-zero, it will use them
72+
mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
73+
}
74+
4475
var libcall libcall
4576
libcall.fn = uintptr(unsafe.Pointer(fn))
4677
libcall.n = 1
4778
// TODO(rsc): Why is noescape necessary here and below?
4879
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
4980
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
81+
if mp != nil {
82+
mp.libcallsp = 0
83+
}
5084
return libcall.r1
5185
}
5286

5387
//go:nosplit
5488
func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
89+
// Leave caller's PC/SP around for traceback.
90+
gp := getg()
91+
var mp *m
92+
if gp != nil {
93+
mp = gp.m
94+
}
95+
if mp != nil {
96+
mp.libcallg.set(gp)
97+
mp.libcallpc = getcallerpc()
98+
// sp must be the last, because once async cpu profiler finds
99+
// all three values to be non-zero, it will use them
100+
mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
101+
}
102+
55103
var libcall libcall
56104
libcall.fn = uintptr(unsafe.Pointer(fn))
57105
libcall.n = 2
58106
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
59107
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
108+
if mp != nil {
109+
mp.libcallsp = 0
110+
}
60111
return libcall.r1
61112
}
62113

63114
//go:nosplit
64115
func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr {
116+
// Leave caller's PC/SP around for traceback.
117+
gp := getg()
118+
var mp *m
119+
if gp != nil {
120+
mp = gp.m
121+
}
122+
if mp != nil {
123+
mp.libcallg.set(gp)
124+
mp.libcallpc = getcallerpc()
125+
// sp must be the last, because once async cpu profiler finds
126+
// all three values to be non-zero, it will use them
127+
mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
128+
}
129+
65130
var libcall libcall
66131
libcall.fn = uintptr(unsafe.Pointer(fn))
67132
libcall.n = 3
68133
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
69134
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
135+
if mp != nil {
136+
mp.libcallsp = 0
137+
}
70138
return libcall.r1
71139
}
72140

73141
//go:nosplit
74142
func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr {
143+
// Leave caller's PC/SP around for traceback.
144+
gp := getg()
145+
var mp *m
146+
if gp != nil {
147+
mp = gp.m
148+
}
149+
if mp != nil {
150+
mp.libcallg.set(gp)
151+
mp.libcallpc = getcallerpc()
152+
// sp must be the last, because once async cpu profiler finds
153+
// all three values to be non-zero, it will use them
154+
mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
155+
}
156+
75157
var libcall libcall
76158
libcall.fn = uintptr(unsafe.Pointer(fn))
77159
libcall.n = 4
78160
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
79161
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
162+
if mp != nil {
163+
mp.libcallsp = 0
164+
}
80165
return libcall.r1
81166
}
82167

83168
//go:nosplit
84169
func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
170+
// Leave caller's PC/SP around for traceback.
171+
gp := getg()
172+
var mp *m
173+
if gp != nil {
174+
mp = gp.m
175+
}
176+
if mp != nil {
177+
mp.libcallg.set(gp)
178+
mp.libcallpc = getcallerpc()
179+
// sp must be the last, because once async cpu profiler finds
180+
// all three values to be non-zero, it will use them
181+
mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
182+
}
183+
85184
var libcall libcall
86185
libcall.fn = uintptr(unsafe.Pointer(fn))
87186
libcall.n = 5
88187
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
89188
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
189+
if mp != nil {
190+
mp.libcallsp = 0
191+
}
90192
return libcall.r1
91193
}
92194

93195
//go:nosplit
94196
func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
197+
// Leave caller's PC/SP around for traceback.
198+
gp := getg()
199+
var mp *m
200+
if gp != nil {
201+
mp = gp.m
202+
}
203+
if mp != nil {
204+
mp.libcallg.set(gp)
205+
mp.libcallpc = getcallerpc()
206+
// sp must be the last, because once async cpu profiler finds
207+
// all three values to be non-zero, it will use them
208+
mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
209+
}
210+
95211
var libcall libcall
96212
libcall.fn = uintptr(unsafe.Pointer(fn))
97213
libcall.n = 6
98214
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
99215
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
216+
if mp != nil {
217+
mp.libcallsp = 0
218+
}
100219
return libcall.r1
101220
}

src/runtime/proc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3697,7 +3697,7 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
36973697
// Normal traceback is impossible or has failed.
36983698
// See if it falls into several common cases.
36993699
n = 0
3700-
if GOOS == "windows" && mp.libcallg != 0 && mp.libcallpc != 0 && mp.libcallsp != 0 {
3700+
if (GOOS == "windows" || GOOS == "solaris") && mp.libcallg != 0 && mp.libcallpc != 0 && mp.libcallsp != 0 {
37013701
// Libcall, i.e. runtime syscall on windows.
37023702
// Collect Go stack that leads to the call.
37033703
n = gentraceback(mp.libcallpc, mp.libcallsp, 0, mp.libcallg.ptr(), 0, &stk[0], len(stk), nil, nil, 0)

0 commit comments

Comments
 (0)