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 const qsize = 64 10 11 var sig struct { 12 q noteQueue 13 inuse bool 14 15 lock mutex 16 note note 17 sleeping bool 18 } 19 20 type noteData struct { 21 s [_ERRMAX]byte 22 n int // n bytes of s are valid 23 } 24 25 type noteQueue struct { 26 lock mutex 27 data [qsize]noteData 28 ri int 29 wi int 30 full bool 31 } 32 33 // It is not allowed to allocate memory in the signal handler. 34 func (q *noteQueue) push(item *byte) bool { 35 lock(&q.lock) 36 if q.full { 37 unlock(&q.lock) 38 return false 39 } 40 s := gostringnocopy(item) 41 copy(q.data[q.wi].s[:], s) 42 q.data[q.wi].n = len(s) 43 q.wi++ 44 if q.wi == qsize { 45 q.wi = 0 46 } 47 if q.wi == q.ri { 48 q.full = true 49 } 50 unlock(&q.lock) 51 return true 52 } 53 54 func (q *noteQueue) pop() string { 55 lock(&q.lock) 56 q.full = false 57 if q.ri == q.wi { 58 unlock(&q.lock) 59 return "" 60 } 61 note := &q.data[q.ri] 62 item := string(note.s[:note.n]) 63 q.ri++ 64 if q.ri == qsize { 65 q.ri = 0 66 } 67 unlock(&q.lock) 68 return item 69 } 70 71 // Called from sighandler to send a signal back out of the signal handling thread. 72 // Reports whether the signal was sent. If not, the caller typically crashes the program. 73 func sendNote(s *byte) bool { 74 if !sig.inuse { 75 return false 76 } 77 78 // Add signal to outgoing queue. 79 if !sig.q.push(s) { 80 return false 81 } 82 83 lock(&sig.lock) 84 if sig.sleeping { 85 sig.sleeping = false 86 notewakeup(&sig.note) 87 } 88 unlock(&sig.lock) 89 90 return true 91 } 92 93 // Called to receive the next queued signal. 94 // Must only be called from a single goroutine at a time. 95 func signal_recv() string { 96 for { 97 note := sig.q.pop() 98 if note != "" { 99 return note 100 } 101 102 lock(&sig.lock) 103 sig.sleeping = true 104 noteclear(&sig.note) 105 unlock(&sig.lock) 106 notetsleepg(&sig.note, -1) 107 } 108 } 109 110 // Must only be called from a single goroutine at a time. 111 func signal_enable(s uint32) { 112 if !sig.inuse { 113 // The first call to signal_enable is for us 114 // to use for initialization. It does not pass 115 // signal information in m. 116 sig.inuse = true // enable reception of signals; cannot disable 117 noteclear(&sig.note) 118 return 119 } 120 } 121 122 // Must only be called from a single goroutine at a time. 123 func signal_disable(s uint32) { 124 } 125 126 // Must only be called from a single goroutine at a time. 127 func signal_ignore(s uint32) { 128 } 129