github.com/c0deoo1/golang1.5@v0.0.0-20220525150107-c87c805d4593/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  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  }