github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/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  // Must only be called from a single goroutine at a time.
   114  //go:linkname signal_enable os/signal.signal_enable
   115  func signal_enable(s uint32) {
   116  	if !sig.inuse {
   117  		// The first call to signal_enable is for us
   118  		// to use for initialization. It does not pass
   119  		// signal information in m.
   120  		sig.inuse = true // enable reception of signals; cannot disable
   121  		noteclear(&sig.note)
   122  		return
   123  	}
   124  }
   125  
   126  // Must only be called from a single goroutine at a time.
   127  //go:linkname signal_disable os/signal.signal_disable
   128  func signal_disable(s uint32) {
   129  }
   130  
   131  // Must only be called from a single goroutine at a time.
   132  //go:linkname signal_ignore os/signal.signal_ignore
   133  func signal_ignore(s uint32) {
   134  }