github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/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  // signalWaitUntilIdle waits until the signal delivery mechanism is idle.
   114  // This is used to ensure that we do not drop a signal notification due
   115  // to a race between disabling a signal and receiving a signal.
   116  // This assumes that signal delivery has already been disabled for
   117  // the signal(s) in question, and here we are just waiting to make sure
   118  // that all the signals have been delivered to the user channels
   119  // by the os/signal package.
   120  //go:linkname signalWaitUntilIdle os/signal.signalWaitUntilIdle
   121  func signalWaitUntilIdle() {
   122  	for {
   123  		lock(&sig.lock)
   124  		sleeping := sig.sleeping
   125  		unlock(&sig.lock)
   126  		if sleeping {
   127  			return
   128  		}
   129  		Gosched()
   130  	}
   131  }
   132  
   133  // Must only be called from a single goroutine at a time.
   134  //go:linkname signal_enable os/signal.signal_enable
   135  func signal_enable(s uint32) {
   136  	if !sig.inuse {
   137  		// The first call to signal_enable is for us
   138  		// to use for initialization. It does not pass
   139  		// signal information in m.
   140  		sig.inuse = true // enable reception of signals; cannot disable
   141  		noteclear(&sig.note)
   142  		return
   143  	}
   144  }
   145  
   146  // Must only be called from a single goroutine at a time.
   147  //go:linkname signal_disable os/signal.signal_disable
   148  func signal_disable(s uint32) {
   149  }
   150  
   151  // Must only be called from a single goroutine at a time.
   152  //go:linkname signal_ignore os/signal.signal_ignore
   153  func signal_ignore(s uint32) {
   154  }