github.com/comwrg/go/src@v0.0.0-20220319063731-c238d0440370/runtime/sigqueue_plan9.go (about) 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 package runtime 8 9 import _ "unsafe" 10 11 const qsize = 64 12 13 var sig struct { 14 q noteQueue 15 inuse bool 16 17 lock mutex 18 note note 19 sleeping bool 20 } 21 22 type noteData struct { 23 s [_ERRMAX]byte 24 n int // n bytes of s are valid 25 } 26 27 type noteQueue struct { 28 lock mutex 29 data [qsize]noteData 30 ri int 31 wi int 32 full bool 33 } 34 35 // It is not allowed to allocate memory in the signal handler. 36 func (q *noteQueue) push(item *byte) bool { 37 lock(&q.lock) 38 if q.full { 39 unlock(&q.lock) 40 return false 41 } 42 s := gostringnocopy(item) 43 copy(q.data[q.wi].s[:], s) 44 q.data[q.wi].n = len(s) 45 q.wi++ 46 if q.wi == qsize { 47 q.wi = 0 48 } 49 if q.wi == q.ri { 50 q.full = true 51 } 52 unlock(&q.lock) 53 return true 54 } 55 56 func (q *noteQueue) pop() string { 57 lock(&q.lock) 58 q.full = false 59 if q.ri == q.wi { 60 unlock(&q.lock) 61 return "" 62 } 63 note := &q.data[q.ri] 64 item := string(note.s[:note.n]) 65 q.ri++ 66 if q.ri == qsize { 67 q.ri = 0 68 } 69 unlock(&q.lock) 70 return item 71 } 72 73 // Called from sighandler to send a signal back out of the signal handling thread. 74 // Reports whether the signal was sent. If not, the caller typically crashes the program. 75 func sendNote(s *byte) bool { 76 if !sig.inuse { 77 return false 78 } 79 80 // Add signal to outgoing queue. 81 if !sig.q.push(s) { 82 return false 83 } 84 85 lock(&sig.lock) 86 if sig.sleeping { 87 sig.sleeping = false 88 notewakeup(&sig.note) 89 } 90 unlock(&sig.lock) 91 92 return true 93 } 94 95 // sigRecvPrepareForFixup is a no-op on plan9. (This would only be 96 // called while GC is disabled.) 97 // 98 //go:nosplit 99 func sigRecvPrepareForFixup() { 100 } 101 102 // Called to receive the next queued signal. 103 // Must only be called from a single goroutine at a time. 104 //go:linkname signal_recv os/signal.signal_recv 105 func signal_recv() string { 106 for { 107 note := sig.q.pop() 108 if note != "" { 109 return note 110 } 111 112 lock(&sig.lock) 113 sig.sleeping = true 114 noteclear(&sig.note) 115 unlock(&sig.lock) 116 notetsleepg(&sig.note, -1) 117 } 118 } 119 120 // signalWaitUntilIdle waits until the signal delivery mechanism is idle. 121 // This is used to ensure that we do not drop a signal notification due 122 // to a race between disabling a signal and receiving a signal. 123 // This assumes that signal delivery has already been disabled for 124 // the signal(s) in question, and here we are just waiting to make sure 125 // that all the signals have been delivered to the user channels 126 // by the os/signal package. 127 //go:linkname signalWaitUntilIdle os/signal.signalWaitUntilIdle 128 func signalWaitUntilIdle() { 129 for { 130 lock(&sig.lock) 131 sleeping := sig.sleeping 132 unlock(&sig.lock) 133 if sleeping { 134 return 135 } 136 Gosched() 137 } 138 } 139 140 // Must only be called from a single goroutine at a time. 141 //go:linkname signal_enable os/signal.signal_enable 142 func signal_enable(s uint32) { 143 if !sig.inuse { 144 // This is the first call to signal_enable. Initialize. 145 sig.inuse = true // enable reception of signals; cannot disable 146 noteclear(&sig.note) 147 } 148 } 149 150 // Must only be called from a single goroutine at a time. 151 //go:linkname signal_disable os/signal.signal_disable 152 func signal_disable(s uint32) { 153 } 154 155 // Must only be called from a single goroutine at a time. 156 //go:linkname signal_ignore os/signal.signal_ignore 157 func signal_ignore(s uint32) { 158 } 159 160 //go:linkname signal_ignored os/signal.signal_ignored 161 func signal_ignored(s uint32) bool { 162 return false 163 }