2017-03-02 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / go / runtime / sigqueue.go
bloba6d498f9b03cf3a3063f51c0d9057b7b66706e1d
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.
6 //
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
25 // nor deadlocks.
27 // +build !plan9
29 package runtime
31 import (
32 "runtime/internal/atomic"
33 _ "unsafe" // for go:linkname
36 var sig struct {
37 note note
38 mask [(_NSIG + 31) / 32]uint32
39 wanted [(_NSIG + 31) / 32]uint32
40 ignored [(_NSIG + 31) / 32]uint32
41 recv [(_NSIG + 31) / 32]uint32
42 state uint32
43 inuse bool
46 const (
47 sigIdle = iota
48 sigReceiving
49 sigSending
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 {
57 return false
60 // Add signal to outgoing queue.
61 for {
62 mask := sig.mask[s/32]
63 if mask&bit != 0 {
64 return true // signal already in queue
66 if atomic.Cas(&sig.mask[s/32], mask, mask|bit) {
67 break
71 // Notify receiver that queue has new bit.
72 Send:
73 for {
74 switch atomic.Load(&sig.state) {
75 default:
76 throw("sigsend: inconsistent state")
77 case sigIdle:
78 if atomic.Cas(&sig.state, sigIdle, sigSending) {
79 break Send
81 case sigSending:
82 // notification already pending
83 break Send
84 case sigReceiving:
85 if atomic.Cas(&sig.state, sigReceiving, sigIdle) {
86 notewakeup(&sig.note)
87 break Send
92 return true
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 {
99 for {
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)
104 return i
108 // Wait for updates to be available from signal sender.
109 Receive:
110 for {
111 switch atomic.Load(&sig.state) {
112 default:
113 throw("signal_recv: inconsistent state")
114 case sigIdle:
115 if atomic.Cas(&sig.state, sigIdle, sigReceiving) {
116 notetsleepg(&sig.note, -1)
117 noteclear(&sig.note)
118 break Receive
120 case sigSending:
121 if atomic.Cas(&sig.state, sigSending, sigIdle) {
122 break Receive
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) {
137 if !sig.inuse {
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
142 noteclear(&sig.note)
143 return
146 if s >= uint32(len(sig.wanted)*32) {
147 return
149 sig.wanted[s/32] |= 1 << (s & 31)
150 sig.ignored[s/32] &^= 1 << (s & 31)
151 sigenable(s)
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) {
158 return
160 sig.wanted[s/32] &^= 1 << (s & 31)
161 sigdisable(s)
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) {
168 return
170 sig.wanted[s/32] &^= 1 << (s & 31)
171 sig.ignored[s/32] |= 1 << (s & 31)
172 sigignore(s)
175 // Checked by signal handlers.
176 func signal_ignored(s uint32) bool {
177 return sig.ignored[s/32]&(1<<(s&31)) != 0