...

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

View as plain text