diff options
Diffstat (limited to 'libgo/go/runtime/signal_gccgo.go')
-rw-r--r-- | libgo/go/runtime/signal_gccgo.go | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/libgo/go/runtime/signal_gccgo.go b/libgo/go/runtime/signal_gccgo.go new file mode 100644 index 0000000000..b4257c9f97 --- /dev/null +++ b/libgo/go/runtime/signal_gccgo.go @@ -0,0 +1,144 @@ +// Copyright 2016 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. + +// +build darwin dragonfly freebsd linux netbsd openbsd solaris + +package runtime + +import ( + "unsafe" +) + +// Functions for gccgo to support signal handling. In the gc runtime +// these are written in OS-specific files and in assembler. + +//extern sigaction +func sigaction(signum uint32, act *_sigaction, oact *_sigaction) int32 + +//extern sigprocmask +func sigprocmask(how int32, set *sigset, oldset *sigset) int32 + +//extern sigfillset +func sigfillset(set *sigset) int32 + +//extern sigemptyset +func sigemptyset(set *sigset) int32 + +//extern sigaddset +func c_sigaddset(set *sigset, signum uint32) int32 + +//extern sigdelset +func c_sigdelset(set *sigset, signum uint32) int32 + +//extern sigaltstack +func sigaltstack(ss *_stack_t, oss *_stack_t) int32 + +//extern raise +func raise(sig uint32) int32 + +//extern getpid +func getpid() _pid_t + +//extern kill +func kill(pid _pid_t, sig uint32) int32 + +//extern setitimer +func setitimer(which int32, new *_itimerval, old *_itimerval) int32 + +type sigTabT struct { + flags int32 + name string +} + +type sigctxt struct { + info *_siginfo_t + ctxt unsafe.Pointer +} + +func (c *sigctxt) sigcode() uint64 { + if c.info == nil { + // This can happen on Solaris 10. We don't know the + // code, just avoid a misleading value. + return _SI_USER + 1 + } + return uint64(c.info.si_code) +} + +//go:nosplit +//go:nowritebarrierrec +func setsig(i uint32, fn uintptr) { + var sa _sigaction + sa.sa_flags = _SA_SIGINFO | _SA_RESTART + + // For gccgo we do not set SA_ONSTACK for a signal that can + // cause a panic. Instead, we trust that the split stack has + // enough room to start the signal handler. This is because + // otherwise we have no good way to switch back to the + // original stack before panicing. + if sigtable[i].flags&_SigPanic == 0 { + sa.sa_flags |= _SA_ONSTACK + } + + sigfillset((*sigset)(unsafe.Pointer(&sa.sa_mask))) + setSigactionHandler(&sa, fn) + sigaction(i, &sa, nil) +} + +//go:nosplit +//go:nowritebarrierrec +func setsigstack(i uint32) { + var sa _sigaction + sigaction(i, nil, &sa) + handler := getSigactionHandler(&sa) + if handler == 0 || handler == _SIG_DFL || handler == _SIG_IGN || sa.sa_flags&_SA_ONSTACK != 0 { + return + } + if sigtable[i].flags&_SigPanic != 0 { + return + } + sa.sa_flags |= _SA_ONSTACK + sigaction(i, &sa, nil) +} + +//go:nosplit +//go:nowritebarrierrec +func getsig(i uint32) uintptr { + var sa _sigaction + if sigaction(i, nil, &sa) < 0 { + // On GNU/Linux glibc rejects attempts to call + // sigaction with signal 32 (SIGCANCEL) or 33 (SIGSETXID). + if GOOS == "linux" && (i == 32 || i == 33) { + return _SIG_DFL + } + throw("sigaction read failure") + } + return getSigactionHandler(&sa) +} + +func signalstack(p unsafe.Pointer, n uintptr) + +//go:nosplit +//go:nowritebarrierrec +func raiseproc(sig uint32) { + kill(getpid(), sig) +} + +//go:nosplit +//go:nowritebarrierrec +func sigfwd(fn uintptr, sig uint32, info *_siginfo_t, ctx unsafe.Pointer) { + f1 := [1]uintptr{fn} + f2 := &f1 + f3 := *(*func(uint32, *_siginfo_t, unsafe.Pointer))(unsafe.Pointer(&f2)) + f3(sig, info, ctx) +} + +//go:nosplit +//go:nowritebarrierrec +func sigaddset(mask *sigset, i int) { + c_sigaddset(mask, uint32(i)) +} + +func sigdelset(mask *sigset, i int) { + c_sigdelset(mask, uint32(i)) +} |