Home | History | Annotate | Download | only in runtime
      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.
      4 
      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.
     11 //
     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.
     26 
     27 // +build !plan9
     28 
     29 package runtime
     30 
     31 import (
     32 	"runtime/internal/atomic"
     33 	_ "unsafe" // for go:linkname
     34 )
     35 
     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
     44 }
     45 
     46 const (
     47 	sigIdle = iota
     48 	sigReceiving
     49 	sigSending
     50 )
     51 
     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
     58 	}
     59 
     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
     65 		}
     66 		if atomic.Cas(&sig.mask[s/32], mask, mask|bit) {
     67 			break
     68 		}
     69 	}
     70 
     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
     80 			}
     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
     88 			}
     89 		}
     90 	}
     91 
     92 	return true
     93 }
     94 
     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
    105 			}
    106 		}
    107 
    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
    119 				}
    120 			case sigSending:
    121 				if atomic.Cas(&sig.state, sigSending, sigIdle) {
    122 					break Receive
    123 				}
    124 			}
    125 		}
    126 
    127 		// Incorporate updates from sender into local copy.
    128 		for i := range sig.mask {
    129 			sig.recv[i] = atomic.Xchg(&sig.mask[i], 0)
    130 		}
    131 	}
    132 }
    133 
    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
    144 	}
    145 
    146 	if s >= uint32(len(sig.wanted)*32) {
    147 		return
    148 	}
    149 	sig.wanted[s/32] |= 1 << (s & 31)
    150 	sig.ignored[s/32] &^= 1 << (s & 31)
    151 	sigenable(s)
    152 }
    153 
    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
    159 	}
    160 	sig.wanted[s/32] &^= 1 << (s & 31)
    161 	sigdisable(s)
    162 }
    163 
    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
    169 	}
    170 	sig.wanted[s/32] &^= 1 << (s & 31)
    171 	sig.ignored[s/32] |= 1 << (s & 31)
    172 	sigignore(s)
    173 }
    174 
    175 // Checked by signal handlers.
    176 func signal_ignored(s uint32) bool {
    177 	return sig.ignored[s/32]&(1<<(s&31)) != 0
    178 }
    179