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 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