runtime: pass to signal handler value of g at time of signal

The existing code assumed that signals only arrived
while executing on the goroutine stack (g == m->curg),
not while executing on the scheduler stack (g == m->g0).

Most of the signal handling trampolines correctly saved
and restored g already, but the sighandler C code did not
have access to it.

Some rewriting of assembly to make the various
implementations as similar as possible.

Will need to change Windows too but I don't
understand how sigtramp gets called there.

R=r
CC=golang-dev
https://golang.org/cl/4203042
diff --git a/src/pkg/runtime/linux/386/signal.c b/src/pkg/runtime/linux/386/signal.c
index 9651a6f..7f20d05 100644
--- a/src/pkg/runtime/linux/386/signal.c
+++ b/src/pkg/runtime/linux/386/signal.c
@@ -42,17 +42,16 @@
 }
 
 void
-runtime·sighandler(int32 sig, Siginfo* info, void* context)
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 {
 	Ucontext *uc;
 	Sigcontext *r;
 	uintptr *sp;
-	G *gp;
 
 	uc = context;
 	r = &uc->uc_mcontext;
 
-	if((gp = m->curg) != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
 		// Make it look like a call to the signal func.
 		// Have to pass arguments out of band since
 		// augmenting the stack frame would break
@@ -96,8 +95,8 @@
 	runtime·printf("\n");
 
 	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->eip, (void*)r->esp, 0, m->curg);
-		runtime·tracebackothers(m->curg);
+		runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
+		runtime·tracebackothers(gp);
 		runtime·dumpregs(r);
 	}
 
diff --git a/src/pkg/runtime/linux/386/sys.s b/src/pkg/runtime/linux/386/sys.s
index a1505b0..a684371 100644
--- a/src/pkg/runtime/linux/386/sys.s
+++ b/src/pkg/runtime/linux/386/sys.s
@@ -56,12 +56,12 @@
 	INT	$0x80
 	RET
 
-TEXT runtime·sigtramp(SB),7,$40
+TEXT runtime·sigtramp(SB),7,$44
 	get_tls(CX)
 	
 	// save g
-	MOVL	g(CX), BX
-	MOVL	BX, 20(SP)
+	MOVL	g(CX), DI
+	MOVL	DI, 20(SP)
 	
 	// g = m->gsignal
 	MOVL	m(CX), BX
@@ -75,6 +75,7 @@
 	MOVL	BX, 4(SP)
 	MOVL	context+8(FP), BX
 	MOVL	BX, 8(SP)
+	MOVL	DI, 12(SP)
 
 	CALL	runtime·sighandler(SB)
 	
diff --git a/src/pkg/runtime/linux/amd64/signal.c b/src/pkg/runtime/linux/amd64/signal.c
index 9e501c9..462f9a7 100644
--- a/src/pkg/runtime/linux/amd64/signal.c
+++ b/src/pkg/runtime/linux/amd64/signal.c
@@ -50,19 +50,18 @@
 }
 
 void
-runtime·sighandler(int32 sig, Siginfo* info, void* context)
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 {
 	Ucontext *uc;
 	Mcontext *mc;
 	Sigcontext *r;
 	uintptr *sp;
-	G *gp;
 
 	uc = context;
 	mc = &uc->uc_mcontext;
 	r = (Sigcontext*)mc;	// same layout, more conveient names
 
-	if((gp = m->curg) != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
 		// Make it look like a call to the signal func.
 		// Have to pass arguments out of band since
 		// augmenting the stack frame would break
@@ -106,8 +105,8 @@
 	runtime·printf("\n");
 
 	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->rip, (void*)r->rsp, 0, g);
-		runtime·tracebackothers(g);
+		runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp);
+		runtime·tracebackothers(gp);
 		runtime·dumpregs(r);
 	}
 
diff --git a/src/pkg/runtime/linux/amd64/sys.s b/src/pkg/runtime/linux/amd64/sys.s
index 170b659..1bf734d 100644
--- a/src/pkg/runtime/linux/amd64/sys.s
+++ b/src/pkg/runtime/linux/amd64/sys.s
@@ -64,8 +64,8 @@
 	get_tls(BX)
 
 	// save g
-	MOVQ	g(BX), BP
-	MOVQ	BP, 40(SP)
+	MOVQ	g(BX), R10
+	MOVQ	R10, 40(SP)
 
 	// g = m->gsignal
 	MOVQ	m(BX), BP
@@ -75,12 +75,14 @@
 	MOVQ	DI, 0(SP)
 	MOVQ	SI, 8(SP)
 	MOVQ	DX, 16(SP)
+	MOVQ	R10, 24(SP)
+
 	CALL	runtime·sighandler(SB)
 
 	// restore g
 	get_tls(BX)
-	MOVQ	40(SP), BP
-	MOVQ	BP, g(BX)
+	MOVQ	40(SP), R10
+	MOVQ	R10, g(BX)
 	RET
 
 TEXT runtime·sigignore(SB),7,$0
diff --git a/src/pkg/runtime/linux/arm/signal.c b/src/pkg/runtime/linux/arm/signal.c
index 481bd13..843c40b 100644
--- a/src/pkg/runtime/linux/arm/signal.c
+++ b/src/pkg/runtime/linux/arm/signal.c
@@ -50,16 +50,15 @@
 }
 
 void
-runtime·sighandler(int32 sig, Siginfo *info, void *context)
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 {
 	Ucontext *uc;
 	Sigcontext *r;
-	G *gp;
 
 	uc = context;
 	r = &uc->uc_mcontext;
 
-	if((gp = m->curg) != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
 		// Make it look like a call to the signal func.
 		// Have to pass arguments out of band since
 		// augmenting the stack frame would break
@@ -99,8 +98,8 @@
 	runtime·printf("\n");
 
 	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, m->curg);
-		runtime·tracebackothers(m->curg);
+		runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, gp);
+		runtime·tracebackothers(gp);
 		runtime·printf("\n");
 		runtime·dumpregs(r);
 	}
diff --git a/src/pkg/runtime/linux/arm/sys.s b/src/pkg/runtime/linux/arm/sys.s
index b25cf81..6c222fc 100644
--- a/src/pkg/runtime/linux/arm/sys.s
+++ b/src/pkg/runtime/linux/arm/sys.s
@@ -197,11 +197,24 @@
 	RET
 
 TEXT runtime·sigtramp(SB),7,$24
+	// save g
+	MOVW	g, R3
+	MOVW	g, 20(R13)
+	
+	// g = m->gsignal
 	MOVW	m_gsignal(m), g
+
+	// copy arguments for call to sighandler
 	MOVW	R0, 4(R13)
 	MOVW	R1, 8(R13)
 	MOVW	R2, 12(R13)
+	MOVW	R3, 16(R13)
+
 	BL	runtime·sighandler(SB)
+	
+	// restore g
+	MOVW	20(R13), g
+
 	RET
 
 TEXT runtime·rt_sigaction(SB),7,$0