runtime: scan register backing store on ia64
[official-gcc.git] / libgo / go / runtime / sigqueue.go
blobb108c39cc85271f626856717e2e3c5e104284b5a
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 // sig handles communication between the signal handler and os/signal.
37 // Other than the inuse and recv fields, the fields are accessed atomically.
39 // The wanted and ignored fields are only written by one goroutine at
40 // a time; access is controlled by the handlers Mutex in os/signal.
41 // The fields are only read by that one goroutine and by the signal handler.
42 // We access them atomically to minimize the race between setting them
43 // in the goroutine calling os/signal and the signal handler,
44 // which may be running in a different thread. That race is unavoidable,
45 // as there is no connection between handling a signal and receiving one,
46 // but atomic instructions should minimize it.
47 var sig struct {
48 note note
49 mask [(_NSIG + 31) / 32]uint32
50 wanted [(_NSIG + 31) / 32]uint32
51 ignored [(_NSIG + 31) / 32]uint32
52 recv [(_NSIG + 31) / 32]uint32
53 state uint32
54 delivering uint32
55 inuse bool
58 const (
59 sigIdle = iota
60 sigReceiving
61 sigSending
64 // sigsend delivers a signal from sighandler to the internal signal delivery queue.
65 // It reports whether the signal was sent. If not, the caller typically crashes the program.
66 // It runs from the signal handler, so it's limited in what it can do.
67 func sigsend(s uint32) bool {
68 bit := uint32(1) << uint(s&31)
69 if !sig.inuse || s >= uint32(32*len(sig.wanted)) {
70 return false
73 atomic.Xadd(&sig.delivering, 1)
74 // We are running in the signal handler; defer is not available.
76 if w := atomic.Load(&sig.wanted[s/32]); w&bit == 0 {
77 atomic.Xadd(&sig.delivering, -1)
78 return false
81 // Add signal to outgoing queue.
82 for {
83 mask := sig.mask[s/32]
84 if mask&bit != 0 {
85 atomic.Xadd(&sig.delivering, -1)
86 return true // signal already in queue
88 if atomic.Cas(&sig.mask[s/32], mask, mask|bit) {
89 break
93 // Notify receiver that queue has new bit.
94 Send:
95 for {
96 switch atomic.Load(&sig.state) {
97 default:
98 throw("sigsend: inconsistent state")
99 case sigIdle:
100 if atomic.Cas(&sig.state, sigIdle, sigSending) {
101 break Send
103 case sigSending:
104 // notification already pending
105 break Send
106 case sigReceiving:
107 if atomic.Cas(&sig.state, sigReceiving, sigIdle) {
108 notewakeup(&sig.note)
109 break Send
114 atomic.Xadd(&sig.delivering, -1)
115 return true
118 // Called to receive the next queued signal.
119 // Must only be called from a single goroutine at a time.
120 //go:linkname signal_recv os_signal.signal_recv
121 func signal_recv() uint32 {
122 for {
123 // Serve any signals from local copy.
124 for i := uint32(0); i < _NSIG; i++ {
125 if sig.recv[i/32]&(1<<(i&31)) != 0 {
126 sig.recv[i/32] &^= 1 << (i & 31)
127 return i
131 // Wait for updates to be available from signal sender.
132 Receive:
133 for {
134 switch atomic.Load(&sig.state) {
135 default:
136 throw("signal_recv: inconsistent state")
137 case sigIdle:
138 if atomic.Cas(&sig.state, sigIdle, sigReceiving) {
139 notetsleepg(&sig.note, -1)
140 noteclear(&sig.note)
141 break Receive
143 case sigSending:
144 if atomic.Cas(&sig.state, sigSending, sigIdle) {
145 break Receive
150 // Incorporate updates from sender into local copy.
151 for i := range sig.mask {
152 sig.recv[i] = atomic.Xchg(&sig.mask[i], 0)
157 // signalWaitUntilIdle waits until the signal delivery mechanism is idle.
158 // This is used to ensure that we do not drop a signal notification due
159 // to a race between disabling a signal and receiving a signal.
160 // This assumes that signal delivery has already been disabled for
161 // the signal(s) in question, and here we are just waiting to make sure
162 // that all the signals have been delivered to the user channels
163 // by the os/signal package.
164 //go:linkname signalWaitUntilIdle os_signal.signalWaitUntilIdle
165 func signalWaitUntilIdle() {
166 // Although the signals we care about have been removed from
167 // sig.wanted, it is possible that another thread has received
168 // a signal, has read from sig.wanted, is now updating sig.mask,
169 // and has not yet woken up the processor thread. We need to wait
170 // until all current signal deliveries have completed.
171 for atomic.Load(&sig.delivering) != 0 {
172 Gosched()
175 // Although WaitUntilIdle seems like the right name for this
176 // function, the state we are looking for is sigReceiving, not
177 // sigIdle. The sigIdle state is really more like sigProcessing.
178 for atomic.Load(&sig.state) != sigReceiving {
179 Gosched()
183 // Must only be called from a single goroutine at a time.
184 //go:linkname signal_enable os_signal.signal_enable
185 func signal_enable(s uint32) {
186 if !sig.inuse {
187 // The first call to signal_enable is for us
188 // to use for initialization. It does not pass
189 // signal information in m.
190 sig.inuse = true // enable reception of signals; cannot disable
191 noteclear(&sig.note)
192 return
195 if s >= uint32(len(sig.wanted)*32) {
196 return
199 w := sig.wanted[s/32]
200 w |= 1 << (s & 31)
201 atomic.Store(&sig.wanted[s/32], w)
203 i := sig.ignored[s/32]
204 i &^= 1 << (s & 31)
205 atomic.Store(&sig.ignored[s/32], i)
207 sigenable(s)
210 // Must only be called from a single goroutine at a time.
211 //go:linkname signal_disable os_signal.signal_disable
212 func signal_disable(s uint32) {
213 if s >= uint32(len(sig.wanted)*32) {
214 return
216 sigdisable(s)
218 w := sig.wanted[s/32]
219 w &^= 1 << (s & 31)
220 atomic.Store(&sig.wanted[s/32], w)
223 // Must only be called from a single goroutine at a time.
224 //go:linkname signal_ignore os_signal.signal_ignore
225 func signal_ignore(s uint32) {
226 if s >= uint32(len(sig.wanted)*32) {
227 return
229 sigignore(s)
231 w := sig.wanted[s/32]
232 w &^= 1 << (s & 31)
233 atomic.Store(&sig.wanted[s/32], w)
235 i := sig.ignored[s/32]
236 i |= 1 << (s & 31)
237 atomic.Store(&sig.ignored[s/32], i)
240 // Checked by signal handlers.
241 func signal_ignored(s uint32) bool {
242 i := atomic.Load(&sig.ignored[s/32])
243 return i&(1<<(s&31)) != 0