Commit ca9128f1 authored by Srdjan Petrovic's avatar Srdjan Petrovic Committed by David Crawshaw

runtime: merge clone0 and clone

We initially added clone0 to handle the case when G or M don't exist, but
it turns out that we could have just modified clone.  (It also helps that
the function we're invoking in clone0 no longer needs arguments.)

As a side-effect, newosproc0 is now supported on all linux archs.

Change-Id: Ie603af75d8f164310fc16446052d83743961f3ca
Reviewed-on: https://go-review.googlesource.com/9164Reviewed-by: 's avatarDavid Crawshaw <crawshaw@golang.org>
parent 3f91a017
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Export guts for testing.
package runtime
var NewOSProc0 = newosproc0
......@@ -22,6 +22,8 @@ var Entersyscall = entersyscall
var Exitsyscall = exitsyscall
var LockedOSThread = lockedOSThread
var FuncPC = funcPC
type LFNode struct {
Next uint64
Pushcnt uintptr
......
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The file contains tests that can not run under race detector for some reason.
// +build !race
package runtime_test
import (
"runtime"
"testing"
"time"
"unsafe"
)
var newOSProcDone bool
//go:nosplit
func newOSProcCreated() {
newOSProcDone = true
}
func TestNewOSProc0(t *testing.T) {
runtime.NewOSProc0(0x800000, unsafe.Pointer(runtime.FuncPC(newOSProcCreated)))
check, end := time.Tick(1*time.Second), time.Tick(5*time.Second)
for {
select {
case <-check:
if newOSProcDone {
return
}
case <-end:
t.Fatalf("couldn't create new OS process")
}
}
}
......@@ -143,16 +143,16 @@ func newosproc(mp *m, stk unsafe.Pointer) {
}
}
// Version of newosproc that doesn't require any Go structs to be allocated.
// Version of newosproc that doesn't require a valid G.
//go:nosplit
func newosproc0(stacksize uintptr, fn unsafe.Pointer, fnarg unsafe.Pointer) {
func newosproc0(stacksize uintptr, fn unsafe.Pointer) {
var dummy uint64
stack := sysAlloc(stacksize, &dummy)
if stack == nil {
write(2, unsafe.Pointer(&failallocatestack[0]), int32(len(failallocatestack)))
exit(1)
}
ret := clone0(cloneFlags, unsafe.Pointer(uintptr(stack)+stacksize), fn, fnarg)
ret := clone(cloneFlags, unsafe.Pointer(uintptr(stack)+stacksize), nil, nil, fn)
if ret < 0 {
write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
exit(1)
......
......@@ -12,9 +12,6 @@ func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer,
//go:noescape
func clone(flags int32, stk, mm, gg, fn unsafe.Pointer) int32
//go:noescape
func clone0(flags int32, stk, fn, fnarg unsafe.Pointer) int32
//go:noescape
func rt_sigaction(sig uintptr, new, old *sigactiont, size uintptr) int32
......
......@@ -42,7 +42,6 @@ nocgo:
MOVL $0x800000, 0(SP) // stacksize = 8192KB
MOVL $_rt0_386_linux_lib_go(SB), AX
MOVL AX, 4(SP) // fn
MOVL $0, 8(SP) // fnarg
MOVL $runtime·newosproc0(SB), AX
CALL AX
......
......@@ -12,13 +12,13 @@ TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
// When building with -buildmode=c-shared, this symbol is called when the shared
// library is loaded.
TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0x58
MOVQ BX, 0x18(SP)
MOVQ BP, 0x20(SP)
MOVQ R12, 0x28(SP)
MOVQ R13, 0x30(SP)
MOVQ R14, 0x38(SP)
MOVQ R15, 0x40(SP)
TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0x40
MOVQ BX, 0x10(SP)
MOVQ BP, 0x18(SP)
MOVQ R12, 0x20(SP)
MOVQ R13, 0x28(SP)
MOVQ R14, 0x30(SP)
MOVQ R15, 0x38(SP)
MOVQ DI, _rt0_amd64_linux_lib_argc<>(SB)
MOVQ SI, _rt0_amd64_linux_lib_argv<>(SB)
......@@ -36,17 +36,16 @@ nocgo:
MOVQ $8388608, 0(SP) // stacksize
MOVQ $_rt0_amd64_linux_lib_go(SB), AX
MOVQ AX, 8(SP) // fn
MOVQ $0, 0x10(SP) // fnarg
MOVQ $runtime·newosproc0(SB), AX
CALL AX
restore:
MOVQ 0x18(SP), BX
MOVQ 0x20(SP), BP
MOVQ 0x28(SP), R12
MOVQ 0x30(SP), R13
MOVQ 0x38(SP), R14
MOVQ 0x40(SP), R15
MOVQ 0x10(SP), BX
MOVQ 0x18(SP), BP
MOVQ 0x20(SP), R12
MOVQ 0x28(SP), R13
MOVQ 0x30(SP), R14
MOVQ 0x38(SP), R15
RET
TEXT _rt0_amd64_linux_lib_go(SB),NOSPLIT,$0
......
......@@ -12,15 +12,15 @@ TEXT _rt0_arm_linux(SB),NOSPLIT,$-4
// When building with -buildmode=c-shared, this symbol is called when the shared
// library is loaded.
TEXT _rt0_arm_linux_lib(SB),NOSPLIT,$40
TEXT _rt0_arm_linux_lib(SB),NOSPLIT,$32
// Preserve callee-save registers. Raspberry Pi's dlopen(), for example,
// actually cares that R11 is preserved.
MOVW R4, 16(R13)
MOVW R5, 20(R13)
MOVW R6, 24(R13)
MOVW R7, 28(R13)
MOVW R8, 32(R13)
MOVW R11, 36(R13)
MOVW R4, 12(R13)
MOVW R5, 16(R13)
MOVW R6, 20(R13)
MOVW R7, 24(R13)
MOVW R8, 28(R13)
MOVW R11, 32(R13)
// Save argc/argv.
MOVW R0, _rt0_arm_linux_lib_argc<>(SB)
......@@ -37,19 +37,17 @@ TEXT _rt0_arm_linux_lib(SB),NOSPLIT,$40
nocgo:
MOVW $0x800000, R0 // stacksize = 8192KB
MOVW $_rt0_arm_linux_lib_go<>(SB), R1 // fn
MOVW $0, R2 // fnarg
MOVW R0, 4(R13)
MOVW R1, 8(R13)
MOVW R2, 12(R13)
BL runtime·newosproc0(SB)
rr:
// Restore callee-save registers and return.
MOVW 16(R13), R4
MOVW 20(R13), R5
MOVW 24(R13), R6
MOVW 28(R13), R7
MOVW 32(R13), R8
MOVW 36(R13), R11
MOVW 12(R13), R4
MOVW 16(R13), R5
MOVW 20(R13), R6
MOVW 24(R13), R7
MOVW 28(R13), R8
MOVW 32(R13), R11
RET
TEXT _rt0_arm_linux_lib_go<>(SB),NOSPLIT,$8
......
......@@ -291,18 +291,18 @@ TEXT runtime·futex(SB),NOSPLIT,$0
// int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL $120, AX // clone
MOVL flags+4(SP), BX
MOVL stack+8(SP), CX
MOVL flags+0(FP), BX
MOVL stack+4(FP), CX
MOVL $0, DX // parent tid ptr
MOVL $0, DI // child tid ptr
// Copy mp, gp, fn off parent stack for use by child.
SUBL $16, CX
MOVL mm+12(SP), SI
MOVL mm+8(FP), SI
MOVL SI, 0(CX)
MOVL gg+16(SP), SI
MOVL gg+12(FP), SI
MOVL SI, 4(CX)
MOVL fn+20(SP), SI
MOVL fn+16(FP), SI
MOVL SI, 8(CX)
MOVL $1234, 12(CX)
......@@ -319,7 +319,7 @@ TEXT runtime·clone(SB),NOSPLIT,$0
RET
// Paranoia: check that SP is as we expect.
MOVL mm+8(FP), BP
MOVL 12(SP), BP
CMPL BP, $1234
JEQ 2(PC)
INT $3
......@@ -328,10 +328,14 @@ TEXT runtime·clone(SB),NOSPLIT,$0
MOVL $224, AX
CALL *runtime·_vdso(SB)
// In child on new stack. Reload registers (paranoia).
MOVL 0(SP), BX // m
MOVL flags+0(FP), DX // g
MOVL stk+4(FP), SI // fn
MOVL 0(SP), BX // m
MOVL 4(SP), DX // g
MOVL 8(SP), SI // fn
CMPL BX, $0
JEQ nog
CMPL DX, $0
JEQ nog
MOVL AX, m_procid(BX) // save tid as m->procid
......@@ -365,16 +369,11 @@ TEXT runtime·clone(SB),NOSPLIT,$0
CALL runtime·emptyfunc(SB)
POPAL
nog:
CALL SI // fn()
CALL runtime·exit1(SB)
MOVL $0x1234, 0x1005
// int32 clone0(int32 flags, void *stack, void* fn, void* fnarg);
TEXT runtime·clone0(SB),NOSPLIT,$0
// TODO(spetrovic): Implement this method.
MOVL $-1, ret+16(FP)
RET
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
MOVL $186, AX // sigaltstack
MOVL new+4(SP), BX
......
......@@ -302,14 +302,16 @@ TEXT runtime·futex(SB),NOSPLIT,$0
// int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVL flags+8(SP), DI
MOVQ stack+16(SP), SI
MOVL flags+0(FP), DI
MOVQ stack+8(FP), SI
MOVQ $0, DX
MOVQ $0, R10
// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers CX and R11.
MOVQ mm+24(SP), R8
MOVQ gg+32(SP), R9
MOVQ fn+40(SP), R12
MOVQ mp+16(FP), R8
MOVQ gp+24(FP), R9
MOVQ fn+32(FP), R12
MOVL $56, AX
SYSCALL
......@@ -323,6 +325,12 @@ TEXT runtime·clone(SB),NOSPLIT,$0
// In child, on new stack.
MOVQ SI, SP
// If g or m are nil, skip Go-related setup.
CMPQ R8, $0 // m
JEQ nog
CMPQ R9, $0 // g
JEQ nog
// Initialize m->procid to Linux tid
MOVL $186, AX // gettid
SYSCALL
......@@ -338,6 +346,7 @@ TEXT runtime·clone(SB),NOSPLIT,$0
MOVQ R9, g(CX)
CALL runtime·stackcheck(SB)
nog:
// Call fn
CALL R12
......@@ -347,34 +356,6 @@ TEXT runtime·clone(SB),NOSPLIT,$0
SYSCALL
JMP -3(PC) // keep exiting
// int32 clone0(int32 flags, void *stack, void* fn, void* fnarg);
TEXT runtime·clone0(SB),NOSPLIT,$16-36
MOVL flags+0(FP), DI
MOVQ stack+8(FP), SI
MOVQ fn+16(FP), R12 // used by the child
MOVQ fnarg+24(FP), R13 // used by the child
MOVL $0, DX
MOVL $0, R10
MOVL $56, AX
SYSCALL
CMPQ AX, $0
JEQ child
// In parent, return.
MOVL AX, ret+32(FP)
RET
child:
MOVQ SI, SP
MOVQ R12, AX // fn
MOVQ R13, DI // fnarg
CALL AX
// fn shouldn't return; if it does, exit.
MOVL $111, DI
MOVL $60, AX
SYSCALL
JMP -3(PC) // keep exiting
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
MOVQ new+8(SP), DI
MOVQ old+16(SP), SI
......
......@@ -241,7 +241,6 @@ TEXT runtime·futex(SB),NOSPLIT,$0
MOVW R0, ret+24(FP)
RET
// int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$0
MOVW flags+0(FP), R0
......@@ -279,8 +278,15 @@ TEXT runtime·clone(SB),NOSPLIT,$0
BEQ 2(PC)
BL runtime·abort(SB)
MOVW 4(R13), g
MOVW 0(R13), R8
MOVW 0(R13), R8 // m
MOVW 4(R13), R0 // g
CMP $0, R8
BEQ nog
CMP $0, R0
BEQ nog
MOVW R0, g
MOVW R8, g_m(g)
// paranoia; check they are not nil
......@@ -295,54 +301,17 @@ TEXT runtime·clone(SB),NOSPLIT,$0
MOVW g_m(g), R8
MOVW R0, m_procid(R8)
nog:
// Call fn
MOVW 8(R13), R0
MOVW $16(R13), R13
BL (R0)
MOVW $0, R0
MOVW R0, 4(R13)
BL runtime·exit1(SB)
// It shouldn't return
MOVW $1234, R0
MOVW $1005, R1
MOVW R0, (R1)
// int32 clone0(int32 flags, void *stack, void* fn, void* fnarg);
TEXT runtime·clone0(SB),NOSPLIT,$0-20
MOVW flags+0(FP), R0
MOVW stack+4(FP), R1
// Update child's future stack and save fn and fnarg on it.
MOVW $-8(R1), R1
MOVW fn+8(FP), R6
MOVW R6, 0(R1)
MOVW fnarg+12(FP), R6
MOVW R6, 4(R1)
MOVW $0, R2 // parent tid ptr
MOVW $0, R3 // tls_val
MOVW $0, R4 // child tid ptr
MOVW $0, R5
MOVW $SYS_clone, R7
SWI $0
// In parent, return.
CMP $0, R0
BEQ 3(PC)
MOVW R0, ret+16(FP)
RET
// In child.
MOVW 0(R13), R6 // fn
MOVW 4(R13), R0 // fnarg
MOVW $8(R13), R13
BL (R6)
MOVW $0, R0
MOVW R0, 4(R13)
BL runtime·exit1(SB)
// It shouldn't return
MOVW $1234, R0
MOVW $1005, R1
MOVW R0, (R1)
......
......@@ -333,14 +333,19 @@ child:
MOVD $0, R0
MOVD R0, (R0) // crash
// Initialize m->procid to Linux tid
good:
// Initialize m->procid to Linux tid
MOVD $SYS_gettid, R8
SVC
MOVD -24(RSP), R12
MOVD -16(RSP), R11
MOVD -8(RSP), R10
MOVD -24(RSP), R12 // fn
MOVD -16(RSP), R11 // g
MOVD -8(RSP), R10 // m
CMP $0, R10
BEQ nog
CMP $0, R11
BEQ nog
MOVD R0, m_procid(R10)
......@@ -351,6 +356,7 @@ good:
MOVD R11, g
//CALL runtime·stackcheck(SB)
nog:
// Call fn
MOVD R12, R0
BL (R0)
......@@ -362,13 +368,6 @@ again:
SVC
B again // keep exiting
// int32 clone0(int32 flags, void *stack, void* fn, void* fnarg);
TEXT runtime·clone0(SB),NOSPLIT,$0
// TODO(spetrovic): Implement this method.
MOVW $-1, R0
MOVW R0, ret+32(FP)
RET
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
MOVD new+0(FP), R0
MOVD old+8(FP), R1
......
......@@ -323,9 +323,14 @@ TEXT runtime·clone(SB),NOSPLIT,$-8
// Initialize m->procid to Linux tid
SYSCALL $SYS_gettid
MOVD -24(R1), R12
MOVD -16(R1), R8
MOVD -8(R1), R7
MOVD -24(R1), R12 // fn
MOVD -16(R1), R8 // g
MOVD -8(R1), R7 // m
CMP R7, $0
BEQ nog
CMP R8, $0
BEQ nog
MOVD R3, m_procid(R7)
......@@ -336,6 +341,7 @@ TEXT runtime·clone(SB),NOSPLIT,$-8
MOVD R8, g
//CALL runtime·stackcheck(SB)
nog:
// Call fn
MOVD R12, CTR
BL (CTR)
......@@ -345,13 +351,6 @@ TEXT runtime·clone(SB),NOSPLIT,$-8
SYSCALL $SYS_exit_group
BR -2(PC) // keep exiting
// int32 clone0(int32 flags, void *stack, void* fn, void* fnarg);
TEXT runtime·clone0(SB),NOSPLIT,$0
// TODO(spetrovic): Implement this method.
MOVW $-1, R3
MOVW R3, ret+32(FP)
RETURN
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
MOVD new+0(FP), R3
MOVD old+8(FP), R4
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment