Skip to content

Commit 8bad008

Browse files
Clément Chigotianlancetaylor
Clément Chigot
authored andcommitted
runtime: handle syscalls without g or m for aix/ppc64
With cgo, some syscalls will be called with g == nil or m == nil. SyscallX functions cannot handle them so they call an equivalent function in sys_aix_ppc64.s which will directly call this syscall. Change-Id: I6508ec772b304111330e6833e7db729200af547c Reviewed-on: https://go-review.googlesource.com/c/go/+/164001 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 340129e commit 8bad008

File tree

2 files changed

+104
-60
lines changed

2 files changed

+104
-60
lines changed

src/runtime/os2_aix.go

Lines changed: 72 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -148,32 +148,35 @@ type libFunc uintptr
148148
// It's defined in sys_aix_ppc64.go.
149149
var asmsyscall6 libFunc
150150

151+
// syscallX functions must always be called with g != nil and m != nil,
152+
// as it relies on g.m.libcall to pass arguments to asmcgocall.
153+
// The few cases where syscalls haven't a g or a m must call their equivalent
154+
// function in sys_aix_ppc64.s to handle them.
155+
151156
//go:nowritebarrier
152157
//go:nosplit
153158
func syscall0(fn *libFunc) (r, err uintptr) {
154159
gp := getg()
155-
var mp *m
156-
if gp != nil {
157-
mp = gp.m
158-
}
159-
if mp != nil && mp.libcallsp == 0 {
160+
mp := gp.m
161+
resetLibcall := true
162+
if mp.libcallsp == 0 {
160163
mp.libcallg.set(gp)
161164
mp.libcallpc = getcallerpc()
162165
// sp must be the last, because once async cpu profiler finds
163166
// all three values to be non-zero, it will use them
164167
mp.libcallsp = getcallersp()
165168
} else {
166-
mp = nil // See comment in sys_darwin.go:libcCall
169+
resetLibcall = false // See comment in sys_darwin.go:libcCall
167170
}
168171

169-
c := &gp.m.libcall
172+
c := &mp.libcall
170173
c.fn = uintptr(unsafe.Pointer(fn))
171174
c.n = 0
172175
c.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
173176

174177
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
175178

176-
if mp != nil {
179+
if resetLibcall {
177180
mp.libcallsp = 0
178181
}
179182

@@ -184,18 +187,16 @@ func syscall0(fn *libFunc) (r, err uintptr) {
184187
//go:nosplit
185188
func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
186189
gp := getg()
187-
var mp *m
188-
if gp != nil {
189-
mp = gp.m
190-
}
191-
if mp != nil && mp.libcallsp == 0 {
190+
mp := gp.m
191+
resetLibcall := true
192+
if mp.libcallsp == 0 {
192193
mp.libcallg.set(gp)
193194
mp.libcallpc = getcallerpc()
194195
// sp must be the last, because once async cpu profiler finds
195196
// all three values to be non-zero, it will use them
196197
mp.libcallsp = getcallersp()
197198
} else {
198-
mp = nil // See comment in sys_darwin.go:libcCall
199+
resetLibcall = false // See comment in sys_darwin.go:libcCall
199200
}
200201

201202
c := &gp.m.libcall
@@ -205,7 +206,7 @@ func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
205206

206207
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
207208

208-
if mp != nil {
209+
if resetLibcall {
209210
mp.libcallsp = 0
210211
}
211212

@@ -216,18 +217,16 @@ func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
216217
//go:nosplit
217218
func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
218219
gp := getg()
219-
var mp *m
220-
if gp != nil {
221-
mp = gp.m
222-
}
223-
if mp != nil && mp.libcallsp == 0 {
220+
mp := gp.m
221+
resetLibcall := true
222+
if mp.libcallsp == 0 {
224223
mp.libcallg.set(gp)
225224
mp.libcallpc = getcallerpc()
226225
// sp must be the last, because once async cpu profiler finds
227226
// all three values to be non-zero, it will use them
228227
mp.libcallsp = getcallersp()
229228
} else {
230-
mp = nil // See comment in sys_darwin.go:libcCall
229+
resetLibcall = false // See comment in sys_darwin.go:libcCall
231230
}
232231

233232
c := &gp.m.libcall
@@ -237,7 +236,7 @@ func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
237236

238237
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
239238

240-
if mp != nil {
239+
if resetLibcall {
241240
mp.libcallsp = 0
242241
}
243242

@@ -248,18 +247,16 @@ func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
248247
//go:nosplit
249248
func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
250249
gp := getg()
251-
var mp *m
252-
if gp != nil {
253-
mp = gp.m
254-
}
255-
if mp != nil && mp.libcallsp == 0 {
250+
mp := gp.m
251+
resetLibcall := true
252+
if mp.libcallsp == 0 {
256253
mp.libcallg.set(gp)
257254
mp.libcallpc = getcallerpc()
258255
// sp must be the last, because once async cpu profiler finds
259256
// all three values to be non-zero, it will use them
260257
mp.libcallsp = getcallersp()
261258
} else {
262-
mp = nil // See comment in sys_darwin.go:libcCall
259+
resetLibcall = false // See comment in sys_darwin.go:libcCall
263260
}
264261

265262
c := &gp.m.libcall
@@ -269,7 +266,7 @@ func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
269266

270267
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
271268

272-
if mp != nil {
269+
if resetLibcall {
273270
mp.libcallsp = 0
274271
}
275272

@@ -280,18 +277,16 @@ func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
280277
//go:nosplit
281278
func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
282279
gp := getg()
283-
var mp *m
284-
if gp != nil {
285-
mp = gp.m
286-
}
287-
if mp != nil && mp.libcallsp == 0 {
280+
mp := gp.m
281+
resetLibcall := true
282+
if mp.libcallsp == 0 {
288283
mp.libcallg.set(gp)
289284
mp.libcallpc = getcallerpc()
290285
// sp must be the last, because once async cpu profiler finds
291286
// all three values to be non-zero, it will use them
292287
mp.libcallsp = getcallersp()
293288
} else {
294-
mp = nil // See comment in sys_darwin.go:libcCall
289+
resetLibcall = false // See comment in sys_darwin.go:libcCall
295290
}
296291

297292
c := &gp.m.libcall
@@ -301,7 +296,7 @@ func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
301296

302297
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
303298

304-
if mp != nil {
299+
if resetLibcall {
305300
mp.libcallsp = 0
306301
}
307302

@@ -312,18 +307,16 @@ func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
312307
//go:nosplit
313308
func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
314309
gp := getg()
315-
var mp *m
316-
if gp != nil {
317-
mp = gp.m
318-
}
319-
if mp != nil && mp.libcallsp == 0 {
310+
mp := gp.m
311+
resetLibcall := true
312+
if mp.libcallsp == 0 {
320313
mp.libcallg.set(gp)
321314
mp.libcallpc = getcallerpc()
322315
// sp must be the last, because once async cpu profiler finds
323316
// all three values to be non-zero, it will use them
324317
mp.libcallsp = getcallersp()
325318
} else {
326-
mp = nil // See comment in sys_darwin.go:libcCall
319+
resetLibcall = false // See comment in sys_darwin.go:libcCall
327320
}
328321

329322
c := &gp.m.libcall
@@ -333,7 +326,7 @@ func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
333326

334327
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
335328

336-
if mp != nil {
329+
if resetLibcall {
337330
mp.libcallsp = 0
338331
}
339332

@@ -344,18 +337,16 @@ func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
344337
//go:nosplit
345338
func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) {
346339
gp := getg()
347-
var mp *m
348-
if gp != nil {
349-
mp = gp.m
350-
}
351-
if mp != nil && mp.libcallsp == 0 {
340+
mp := gp.m
341+
resetLibcall := true
342+
if mp.libcallsp == 0 {
352343
mp.libcallg.set(gp)
353344
mp.libcallpc = getcallerpc()
354345
// sp must be the last, because once async cpu profiler finds
355346
// all three values to be non-zero, it will use them
356347
mp.libcallsp = getcallersp()
357348
} else {
358-
mp = nil // See comment in sys_darwin.go:libcCall
349+
resetLibcall = false // See comment in sys_darwin.go:libcCall
359350
}
360351

361352
c := &gp.m.libcall
@@ -365,7 +356,7 @@ func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) {
365356

366357
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
367358

368-
if mp != nil {
359+
if resetLibcall {
369360
mp.libcallsp = 0
370361
}
371362

@@ -461,13 +452,23 @@ func getsystemcfg(label uint) uintptr {
461452
return r
462453
}
463454

455+
func usleep1(us uint32)
456+
464457
//go:nosplit
465458
func usleep(us uint32) {
466-
r, err := syscall1(&libc_usleep, uintptr(us))
467-
if int32(r) == -1 {
468-
println("syscall usleep failed: ", hex(err))
469-
throw("syscall usleep")
459+
_g_ := getg()
460+
461+
// Check the validity of m because we might be called in cgo callback
462+
// path early enough where there isn't a g or a m available yet.
463+
if _g_ != nil && _g_.m != nil {
464+
r, err := syscall1(&libc_usleep, uintptr(us))
465+
if int32(r) == -1 {
466+
println("syscall usleep failed: ", hex(err))
467+
throw("syscall usleep")
468+
}
469+
return
470470
}
471+
usleep1(us)
471472
}
472473

473474
//go:nosplit
@@ -541,8 +542,8 @@ func osyield1()
541542
func osyield() {
542543
_g_ := getg()
543544

544-
// Check the validity of m because we might be called in cgo callback
545-
// path early enough where there isn't a m available yet.
545+
// Check the validity of m because it might be called during a cgo
546+
// callback early enough where m isn't available yet.
546547
if _g_ != nil && _g_.m != nil {
547548
r, err := syscall0(&libc_sched_yield)
548549
if int32(r) == -1 {
@@ -611,11 +612,22 @@ func pthread_create(tid *pthread, attr *pthread_attr, fn *funcDescriptor, arg un
611612

612613
// On multi-thread program, sigprocmask must not be called.
613614
// It's replaced by sigthreadmask.
615+
func sigprocmask1(how, new, old uintptr)
616+
614617
//go:nosplit
615618
func sigprocmask(how int32, new, old *sigset) {
616-
r, err := syscall3(&libpthread_sigthreadmask, uintptr(how), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
617-
if int32(r) != 0 {
618-
println("syscall sigthreadmask failed: ", hex(err))
619-
throw("syscall sigthreadmask")
619+
_g_ := getg()
620+
621+
// Check the validity of m because it might be called during a cgo
622+
// callback early enough where m isn't available yet.
623+
if _g_ != nil && _g_.m != nil {
624+
r, err := syscall3(&libpthread_sigthreadmask, uintptr(how), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
625+
if int32(r) != 0 {
626+
println("syscall sigthreadmask failed: ", hex(err))
627+
throw("syscall sigthreadmask")
628+
}
629+
return
620630
}
631+
sigprocmask1(uintptr(how), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
632+
621633
}

src/runtime/sys_aix_ppc64.s

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,36 @@ TEXT runtime·osyield1(SB),NOSPLIT,$0
204204
MOVD R0, CTR
205205
BL (CTR)
206206
MOVD 40(R1), R2
207+
BL runtime·reginit(SB)
208+
RET
209+
210+
211+
// Runs on OS stack, called from runtime·sigprocmask.
212+
TEXT runtime·sigprocmask1(SB),NOSPLIT,$0-24
213+
MOVD how+0(FP), R3
214+
MOVD new+8(FP), R4
215+
MOVD old+16(FP), R5
216+
MOVD $libpthread_sigthreadmask(SB), R12
217+
MOVD 0(R12), R12
218+
MOVD R2, 40(R1)
219+
MOVD 0(R12), R0
220+
MOVD 8(R12), R2
221+
MOVD R0, CTR
222+
BL (CTR)
223+
MOVD 40(R1), R2
224+
BL runtime·reginit(SB)
225+
RET
226+
227+
// Runs on OS stack, called from runtime·usleep.
228+
TEXT runtime·usleep1(SB),NOSPLIT,$0-8
229+
MOVW us+0(FP), R3
230+
MOVD $libc_usleep(SB), R12
231+
MOVD 0(R12), R12
232+
MOVD R2, 40(R1)
233+
MOVD 0(R12), R0
234+
MOVD 8(R12), R2
235+
MOVD R0, CTR
236+
BL (CTR)
237+
MOVD 40(R1), R2
238+
BL runtime·reginit(SB)
207239
RET

0 commit comments

Comments
 (0)