rsc.io/go@v0.0.0-20150416155037-e040fd465409/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 noteQueue struct {
    21  	lock mutex
    22  	data [qsize]*byte
    23  	ri   int
    24  	wi   int
    25  	full bool
    26  }
    27  
    28  func (q *noteQueue) push(item *byte) bool {
    29  	lock(&q.lock)
    30  	if q.full {
    31  		unlock(&q.lock)
    32  		return false
    33  	}
    34  	q.data[q.wi] = item
    35  	q.wi++
    36  	if q.wi == qsize {
    37  		q.wi = 0
    38  	}
    39  	if q.wi == q.ri {
    40  		q.full = true
    41  	}
    42  	unlock(&q.lock)
    43  	return true
    44  }
    45  
    46  func (q *noteQueue) pop() *byte {
    47  	lock(&q.lock)
    48  	q.full = false
    49  	if q.ri == q.wi {
    50  		unlock(&q.lock)
    51  		return nil
    52  	}
    53  	item := q.data[q.ri]
    54  	q.ri++
    55  	if q.ri == qsize {
    56  		q.ri = 0
    57  	}
    58  	unlock(&q.lock)
    59  	return item
    60  }
    61  
    62  // Called from sighandler to send a signal back out of the signal handling thread.
    63  // Reports whether the signal was sent. If not, the caller typically crashes the program.
    64  func sendNote(s *byte) bool {
    65  	if !sig.inuse {
    66  		return false
    67  	}
    68  
    69  	// Add signal to outgoing queue.
    70  	if !sig.q.push(s) {
    71  		return false
    72  	}
    73  
    74  	lock(&sig.lock)
    75  	if sig.sleeping {
    76  		sig.sleeping = false
    77  		notewakeup(&sig.note)
    78  	}
    79  	unlock(&sig.lock)
    80  
    81  	return true
    82  }
    83  
    84  // Called to receive the next queued signal.
    85  // Must only be called from a single goroutine at a time.
    86  func signal_recv() string {
    87  	for {
    88  		note := sig.q.pop()
    89  		if note != nil {
    90  			return gostring(note)
    91  		}
    92  
    93  		lock(&sig.lock)
    94  		sig.sleeping = true
    95  		noteclear(&sig.note)
    96  		unlock(&sig.lock)
    97  		notetsleepg(&sig.note, -1)
    98  	}
    99  }
   100  
   101  // Must only be called from a single goroutine at a time.
   102  func signal_enable(s uint32) {
   103  	if !sig.inuse {
   104  		// The first call to signal_enable is for us
   105  		// to use for initialization.  It does not pass
   106  		// signal information in m.
   107  		sig.inuse = true // enable reception of signals; cannot disable
   108  		noteclear(&sig.note)
   109  		return
   110  	}
   111  }
   112  
   113  // Must only be called from a single goroutine at a time.
   114  func signal_disable(s uint32) {
   115  }
   116  
   117  // Must only be called from a single goroutine at a time.
   118  func signal_ignore(s uint32) {
   119  }