Black Lives Matter. Support the Equal Justice Initiative.

Source file src/runtime/sigqueue_plan9.go

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

View as plain text