1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This file implements runtime support for signal handling.
7 // Most synchronization primitives are not available from
8 // the signal handler (it cannot block, allocate memory, or use locks)
9 // so the handler communicates with a processing goroutine
10 // via struct sig, below.
12 // sigsend is called by the signal handler to queue a new signal.
13 // signal_recv is called by the Go program to receive a newly queued signal.
14 // Synchronization between sigsend and signal_recv is based on the sig.state
15 // variable. It can be in 3 states: sigIdle, sigReceiving and sigSending.
16 // sigReceiving means that signal_recv is blocked on sig.Note and there are no
17 // new pending signals.
18 // sigSending means that sig.mask *may* contain new pending signals,
19 // signal_recv can't be blocked in this state.
20 // sigIdle means that there are no new pending signals and signal_recv is not blocked.
21 // Transitions between states are done atomically with CAS.
22 // When signal_recv is unblocked, it resets sig.Note and rechecks sig.mask.
23 // If several sigsends and signal_recv execute concurrently, it can lead to
24 // unnecessary rechecks of sig.mask, but it cannot lead to missed signals
32 "runtime/internal/atomic"
33 _
"unsafe" // for go:linkname
38 mask
[(_NSIG
+ 31) / 32]uint32
39 wanted
[(_NSIG
+ 31) / 32]uint32
40 ignored
[(_NSIG
+ 31) / 32]uint32
41 recv
[(_NSIG
+ 31) / 32]uint32
52 // Called from sighandler to send a signal back out of the signal handling thread.
53 // Reports whether the signal was sent. If not, the caller typically crashes the program.
54 func sigsend(s
uint32) bool {
55 bit
:= uint32(1) << uint(s
&31)
56 if !sig
.inuse || s
>= uint32(32*len(sig
.wanted
)) || sig
.wanted
[s
/32]&bit
== 0 {
60 // Add signal to outgoing queue.
62 mask
:= sig
.mask
[s
/32]
64 return true // signal already in queue
66 if atomic
.Cas(&sig
.mask
[s
/32], mask
, mask|bit
) {
71 // Notify receiver that queue has new bit.
74 switch atomic
.Load(&sig
.state
) {
76 throw("sigsend: inconsistent state")
78 if atomic
.Cas(&sig
.state
, sigIdle
, sigSending
) {
82 // notification already pending
85 if atomic
.Cas(&sig
.state
, sigReceiving
, sigIdle
) {
95 // Called to receive the next queued signal.
96 // Must only be called from a single goroutine at a time.
97 //go:linkname signal_recv os_signal.signal_recv
98 func signal_recv() uint32 {
100 // Serve any signals from local copy.
101 for i
:= uint32(0); i
< _NSIG
; i
++ {
102 if sig
.recv
[i
/32]&(1<<(i
&31)) != 0 {
103 sig
.recv
[i
/32] &^= 1 << (i
& 31)
108 // Wait for updates to be available from signal sender.
111 switch atomic
.Load(&sig
.state
) {
113 throw("signal_recv: inconsistent state")
115 if atomic
.Cas(&sig
.state
, sigIdle
, sigReceiving
) {
116 notetsleepg(&sig
.note
, -1)
121 if atomic
.Cas(&sig
.state
, sigSending
, sigIdle
) {
127 // Incorporate updates from sender into local copy.
128 for i
:= range sig
.mask
{
129 sig
.recv
[i
] = atomic
.Xchg(&sig
.mask
[i
], 0)
134 // Must only be called from a single goroutine at a time.
135 //go:linkname signal_enable os_signal.signal_enable
136 func signal_enable(s
uint32) {
138 // The first call to signal_enable is for us
139 // to use for initialization. It does not pass
140 // signal information in m.
141 sig
.inuse
= true // enable reception of signals; cannot disable
146 if s
>= uint32(len(sig
.wanted
)*32) {
149 sig
.wanted
[s
/32] |
= 1 << (s
& 31)
150 sig
.ignored
[s
/32] &^= 1 << (s
& 31)
154 // Must only be called from a single goroutine at a time.
155 //go:linkname signal_disable os_signal.signal_disable
156 func signal_disable(s
uint32) {
157 if s
>= uint32(len(sig
.wanted
)*32) {
160 sig
.wanted
[s
/32] &^= 1 << (s
& 31)
164 // Must only be called from a single goroutine at a time.
165 //go:linkname signal_ignore os_signal.signal_ignore
166 func signal_ignore(s
uint32) {
167 if s
>= uint32(len(sig
.wanted
)*32) {
170 sig
.wanted
[s
/32] &^= 1 << (s
& 31)
171 sig
.ignored
[s
/32] |
= 1 << (s
& 31)
175 // Checked by signal handlers.
176 func signal_ignored(s
uint32) bool {
177 return sig
.ignored
[s
/32]&(1<<(s
&31)) != 0