aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2016-11-30 02:09:24 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2016-11-30 02:09:24 +0000
commitbc816275bf9f410e0f53961d0c2053db0cc7e6f3 (patch)
treec1565b1daa9faf905ef5d66188008c4603dd4f77 /libgo
parent46d07ee0aa699dc6c3bf87c3e529359e838e80f2 (diff)
runtime: fixes for -buildmode=c-archive
With -buildmode=c-archive, initsig is called before the memory allocator has been initialized. The code was doing a memory allocation because of the call to funcPC(sigtramp). When escape analysis is fully implemented, that call should not allocate. For now, finesse the issue by calling a C function to get the C function pointer value of sigtramp. When returning from a call from C to a Go function, a deferred function is run to go back to syscall mode. When the call occurs on a non-Go thread, that call sets g to nil, making it impossible to add the _defer struct back to the pool. Just drop it and let the garbage collector clean it up. Reviewed-on: https://go-review.googlesource.com/33675 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@242992 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/runtime/panic.go9
-rw-r--r--libgo/go/runtime/signal1_unix.go6
-rw-r--r--libgo/go/runtime/stubs.go4
-rw-r--r--libgo/runtime/go-signal.c9
4 files changed, 23 insertions, 5 deletions
diff --git a/libgo/go/runtime/panic.go b/libgo/go/runtime/panic.go
index 29a2f021d99..0ad178f45f6 100644
--- a/libgo/go/runtime/panic.go
+++ b/libgo/go/runtime/panic.go
@@ -141,6 +141,15 @@ func freedefer(d *_defer) {
if d.special {
return
}
+
+ // When C code calls a Go function on a non-Go thread, the
+ // deferred call to cgocallBackDone will set g to nil.
+ // Don't crash trying to put d on the free list; just let it
+ // be garbage collected.
+ if getg() == nil {
+ return
+ }
+
mp := acquirem()
pp := mp.p.ptr()
if len(pp.deferpool) == cap(pp.deferpool) {
diff --git a/libgo/go/runtime/signal1_unix.go b/libgo/go/runtime/signal1_unix.go
index f9327651911..d21bf4c31d7 100644
--- a/libgo/go/runtime/signal1_unix.go
+++ b/libgo/go/runtime/signal1_unix.go
@@ -93,7 +93,7 @@ func initsig(preinit bool) {
}
t.flags |= _SigHandling
- setsig(i, funcPC(sigtramp), true)
+ setsig(i, getSigtramp(), true)
}
}
@@ -137,7 +137,7 @@ func sigenable(sig uint32) {
if t.flags&_SigHandling == 0 {
t.flags |= _SigHandling
fwdSig[sig] = getsig(int32(sig))
- setsig(int32(sig), funcPC(sigtramp), true)
+ setsig(int32(sig), getSigtramp(), true)
}
}
}
@@ -265,7 +265,7 @@ func raisebadsignal(sig int32, c *sigctxt) {
// We may receive another instance of the signal before we
// restore the Go handler, but that is not so bad: we know
// that the Go program has been ignoring the signal.
- setsig(sig, funcPC(sigtramp), true)
+ setsig(sig, getSigtramp(), true)
}
func crash() {
diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go
index 3bf8bb74bad..b2f1829fece 100644
--- a/libgo/go/runtime/stubs.go
+++ b/libgo/go/runtime/stubs.go
@@ -502,8 +502,8 @@ func goexit1()
func schedtrace(bool)
func freezetheworld()
-// Signal trampoline, written in C.
-func sigtramp()
+// Get signal trampoline, written in C.
+func getSigtramp() uintptr
// The sa_handler field is generally hidden in a union, so use C accessors.
func getSigactionHandler(*_sigaction) uintptr
diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c
index c1f1a52d201..711f71e8731 100644
--- a/libgo/runtime/go-signal.c
+++ b/libgo/runtime/go-signal.c
@@ -140,6 +140,15 @@ sigtramp(int sig, siginfo_t *info, void *context)
#endif // USING_SPLIT_STACK
+// C function to return the address of the sigtramp function.
+uintptr getSigtramp(void) __asm__ (GOSYM_PREFIX "runtime.getSigtramp");
+
+uintptr
+getSigtramp()
+{
+ return (uintptr)(void*)sigtramp;
+}
+
// C code to manage the sigaction sa_sigaction field, which is
// typically a union and so hard for mksysinfo.sh to handle.