libgo, compiler: Upgrade libgo to Go 1.4, except for runtime.
[official-gcc.git] / libgo / go / runtime / sigqueue.go
blob2d9c24d2d24909a206d7efddeb980ed9718b8f75
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 package runtime
29 import "unsafe"
31 var sig struct {
32 note note
33 mask [(_NSIG + 31) / 32]uint32
34 wanted [(_NSIG + 31) / 32]uint32
35 recv [(_NSIG + 31) / 32]uint32
36 state uint32
37 inuse bool
40 const (
41 sigIdle = iota
42 sigReceiving
43 sigSending
46 // Called from sighandler to send a signal back out of the signal handling thread.
47 // Reports whether the signal was sent. If not, the caller typically crashes the program.
48 func sigsend(s int32) bool {
49 bit := uint32(1) << uint(s&31)
50 if !sig.inuse || s < 0 || int(s) >= 32*len(sig.wanted) || sig.wanted[s/32]&bit == 0 {
51 return false
54 // Add signal to outgoing queue.
55 for {
56 mask := sig.mask[s/32]
57 if mask&bit != 0 {
58 return true // signal already in queue
60 if cas(&sig.mask[s/32], mask, mask|bit) {
61 break
65 // Notify receiver that queue has new bit.
66 Send:
67 for {
68 switch atomicload(&sig.state) {
69 default:
70 gothrow("sigsend: inconsistent state")
71 case sigIdle:
72 if cas(&sig.state, sigIdle, sigSending) {
73 break Send
75 case sigSending:
76 // notification already pending
77 break Send
78 case sigReceiving:
79 if cas(&sig.state, sigReceiving, sigIdle) {
80 notewakeup(&sig.note)
81 break Send
86 return true
89 // Called to receive the next queued signal.
90 // Must only be called from a single goroutine at a time.
91 func signal_recv() uint32 {
92 for {
93 // Serve any signals from local copy.
94 for i := uint32(0); i < _NSIG; i++ {
95 if sig.recv[i/32]&(1<<(i&31)) != 0 {
96 sig.recv[i/32] &^= 1 << (i & 31)
97 return i
101 // Wait for updates to be available from signal sender.
102 Receive:
103 for {
104 switch atomicload(&sig.state) {
105 default:
106 gothrow("signal_recv: inconsistent state")
107 case sigIdle:
108 if cas(&sig.state, sigIdle, sigReceiving) {
109 notetsleepg(&sig.note, -1)
110 noteclear(&sig.note)
111 break Receive
113 case sigSending:
114 if cas(&sig.state, sigSending, sigIdle) {
115 break Receive
120 // Incorporate updates from sender into local copy.
121 for i := range sig.mask {
122 sig.recv[i] = xchg(&sig.mask[i], 0)
127 // Must only be called from a single goroutine at a time.
128 func signal_enable(s uint32) {
129 if !sig.inuse {
130 // The first call to signal_enable is for us
131 // to use for initialization. It does not pass
132 // signal information in m.
133 sig.inuse = true // enable reception of signals; cannot disable
134 noteclear(&sig.note)
135 return
138 if int(s) >= len(sig.wanted)*32 {
139 return
141 sig.wanted[s/32] |= 1 << (s & 31)
142 sigenable_go(s)
145 // Must only be called from a single goroutine at a time.
146 func signal_disable(s uint32) {
147 if int(s) >= len(sig.wanted)*32 {
148 return
150 sig.wanted[s/32] &^= 1 << (s & 31)
151 sigdisable_go(s)
154 // This runs on a foreign stack, without an m or a g. No stack split.
155 //go:nosplit
156 func badsignal(sig uintptr) {
157 cgocallback(unsafe.Pointer(funcPC(sigsend)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
160 func sigenable_m()
161 func sigdisable_m()
163 func sigenable_go(s uint32) {
164 g := getg()
165 g.m.scalararg[0] = uintptr(s)
166 onM(sigenable_m)
169 func sigdisable_go(s uint32) {
170 g := getg()
171 g.m.scalararg[0] = uintptr(s)
172 onM(sigdisable_m)