github.com/aloncn/graphics-go@v0.0.1/src/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 // 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() string { 99 for { 100 note := sig.q.pop() 101 if note != "" { 102 return note 103 } 104 105 lock(&sig.lock) 106 sig.sleeping = true 107 noteclear(&sig.note) 108 unlock(&sig.lock) 109 notetsleepg(&sig.note, -1) 110 } 111 } 112 113 // Must only be called from a single goroutine at a time. 114 //go:linkname signal_enable os/signal.signal_enable 115 func signal_enable(s uint32) { 116 if !sig.inuse { 117 // The first call to signal_enable is for us 118 // to use for initialization. It does not pass 119 // signal information in m. 120 sig.inuse = true // enable reception of signals; cannot disable 121 noteclear(&sig.note) 122 return 123 } 124 } 125 126 // Must only be called from a single goroutine at a time. 127 //go:linkname signal_disable os/signal.signal_disable 128 func signal_disable(s uint32) { 129 } 130 131 // Must only be called from a single goroutine at a time. 132 //go:linkname signal_ignore os/signal.signal_ignore 133 func signal_ignore(s uint32) { 134 }