diff options
Diffstat (limited to 'libgo/go/runtime/sigqueue.go')
-rw-r--r-- | libgo/go/runtime/sigqueue.go | 182 |
1 files changed, 0 insertions, 182 deletions
diff --git a/libgo/go/runtime/sigqueue.go b/libgo/go/runtime/sigqueue.go deleted file mode 100644 index fed4560fe33..00000000000 --- a/libgo/go/runtime/sigqueue.go +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2009 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. - -// This file implements runtime support for signal handling. -// -// Most synchronization primitives are not available from -// the signal handler (it cannot block, allocate memory, or use locks) -// so the handler communicates with a processing goroutine -// via struct sig, below. -// -// sigsend is called by the signal handler to queue a new signal. -// signal_recv is called by the Go program to receive a newly queued signal. -// Synchronization between sigsend and signal_recv is based on the sig.state -// variable. It can be in 3 states: sigIdle, sigReceiving and sigSending. -// sigReceiving means that signal_recv is blocked on sig.Note and there are no -// new pending signals. -// sigSending means that sig.mask *may* contain new pending signals, -// signal_recv can't be blocked in this state. -// sigIdle means that there are no new pending signals and signal_recv is not blocked. -// Transitions between states are done atomically with CAS. -// When signal_recv is unblocked, it resets sig.Note and rechecks sig.mask. -// If several sigsends and signal_recv execute concurrently, it can lead to -// unnecessary rechecks of sig.mask, but it cannot lead to missed signals -// nor deadlocks. - -package runtime - -import "unsafe" - -var sig struct { - note note - mask [(_NSIG + 31) / 32]uint32 - wanted [(_NSIG + 31) / 32]uint32 - recv [(_NSIG + 31) / 32]uint32 - state uint32 - inuse bool -} - -const ( - sigIdle = iota - sigReceiving - sigSending -) - -// Called from sighandler to send a signal back out of the signal handling thread. -// Reports whether the signal was sent. If not, the caller typically crashes the program. -func sigsend(s int32) bool { - bit := uint32(1) << uint(s&31) - if !sig.inuse || s < 0 || int(s) >= 32*len(sig.wanted) || sig.wanted[s/32]&bit == 0 { - return false - } - - // Add signal to outgoing queue. - for { - mask := sig.mask[s/32] - if mask&bit != 0 { - return true // signal already in queue - } - if cas(&sig.mask[s/32], mask, mask|bit) { - break - } - } - - // Notify receiver that queue has new bit. -Send: - for { - switch atomicload(&sig.state) { - default: - gothrow("sigsend: inconsistent state") - case sigIdle: - if cas(&sig.state, sigIdle, sigSending) { - break Send - } - case sigSending: - // notification already pending - break Send - case sigReceiving: - if cas(&sig.state, sigReceiving, sigIdle) { - notewakeup(&sig.note) - break Send - } - } - } - - return true -} - -// Called to receive the next queued signal. -// Must only be called from a single goroutine at a time. -func signal_recv() uint32 { - for { - // Serve any signals from local copy. - for i := uint32(0); i < _NSIG; i++ { - if sig.recv[i/32]&(1<<(i&31)) != 0 { - sig.recv[i/32] &^= 1 << (i & 31) - return i - } - } - - // Wait for updates to be available from signal sender. - Receive: - for { - switch atomicload(&sig.state) { - default: - gothrow("signal_recv: inconsistent state") - case sigIdle: - if cas(&sig.state, sigIdle, sigReceiving) { - notetsleepg(&sig.note, -1) - noteclear(&sig.note) - break Receive - } - case sigSending: - if cas(&sig.state, sigSending, sigIdle) { - break Receive - } - } - } - - // Incorporate updates from sender into local copy. - for i := range sig.mask { - sig.recv[i] = xchg(&sig.mask[i], 0) - } - } -} - -// Must only be called from a single goroutine at a time. -func signal_enable(s uint32) { - if !sig.inuse { - // The first call to signal_enable is for us - // to use for initialization. It does not pass - // signal information in m. - sig.inuse = true // enable reception of signals; cannot disable - noteclear(&sig.note) - return - } - - if int(s) >= len(sig.wanted)*32 { - return - } - sig.wanted[s/32] |= 1 << (s & 31) - sigenable_go(s) -} - -// Must only be called from a single goroutine at a time. -func signal_disable(s uint32) { - if int(s) >= len(sig.wanted)*32 { - return - } - sig.wanted[s/32] &^= 1 << (s & 31) - sigdisable_go(s) -} - -// This runs on a foreign stack, without an m or a g. No stack split. -//go:nosplit -func badsignal(sig uintptr) { - // Some external libraries, for example, OpenBLAS, create worker threads in - // a global constructor. If we're doing cpu profiling, and the SIGPROF signal - // comes to one of the foreign threads before we make our first cgo call, the - // call to cgocallback below will bring down the whole process. - // It's better to miss a few SIGPROF signals than to abort in this case. - // See http://golang.org/issue/9456. - if _SIGPROF != 0 && sig == _SIGPROF && needextram != 0 { - return - } - cgocallback(unsafe.Pointer(funcPC(sigsend)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig)) -} - -func sigenable_m() -func sigdisable_m() - -func sigenable_go(s uint32) { - g := getg() - g.m.scalararg[0] = uintptr(s) - onM(sigenable_m) -} - -func sigdisable_go(s uint32) { - g := getg() - g.m.scalararg[0] = uintptr(s) - onM(sigdisable_m) -} |