Source file src/runtime/sigqueue_plan9.go

     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  //
    98  //go:linkname signal_recv os/signal.signal_recv
    99  func signal_recv() string {
   100  	for {
   101  		note := sig.q.pop()
   102  		if note != "" {
   103  			return note
   104  		}
   105  
   106  		lock(&sig.lock)
   107  		sig.sleeping = true
   108  		noteclear(&sig.note)
   109  		unlock(&sig.lock)
   110  		notetsleepg(&sig.note, -1)
   111  	}
   112  }
   113  
   114  // signalWaitUntilIdle waits until the signal delivery mechanism is idle.
   115  // This is used to ensure that we do not drop a signal notification due
   116  // to a race between disabling a signal and receiving a signal.
   117  // This assumes that signal delivery has already been disabled for
   118  // the signal(s) in question, and here we are just waiting to make sure
   119  // that all the signals have been delivered to the user channels
   120  // by the os/signal package.
   121  //
   122  //go:linkname signalWaitUntilIdle os/signal.signalWaitUntilIdle
   123  func signalWaitUntilIdle() {
   124  	for {
   125  		lock(&sig.lock)
   126  		sleeping := sig.sleeping
   127  		unlock(&sig.lock)
   128  		if sleeping {
   129  			return
   130  		}
   131  		Gosched()
   132  	}
   133  }
   134  
   135  // Must only be called from a single goroutine at a time.
   136  //
   137  //go:linkname signal_enable os/signal.signal_enable
   138  func signal_enable(s uint32) {
   139  	if !sig.inuse {
   140  		// This is the first call to signal_enable. Initialize.
   141  		sig.inuse = true // enable reception of signals; cannot disable
   142  		noteclear(&sig.note)
   143  	}
   144  }
   145  
   146  // Must only be called from a single goroutine at a time.
   147  //
   148  //go:linkname signal_disable os/signal.signal_disable
   149  func signal_disable(s uint32) {
   150  }
   151  
   152  // Must only be called from a single goroutine at a time.
   153  //
   154  //go:linkname signal_ignore os/signal.signal_ignore
   155  func signal_ignore(s uint32) {
   156  }
   157  
   158  //go:linkname signal_ignored os/signal.signal_ignored
   159  func signal_ignored(s uint32) bool {
   160  	return false
   161  }
   162  

View as plain text