1
0
mirror of https://github.com/golang/go synced 2024-11-20 02:14:46 -07:00
go/src/runtime/sigqueue_plan9.go
Michael Hudson-Doyle 0b8d583320 runtime, os/signal: use //go:linkname instead of assembly stubs to get access to runtime functions
os/signal depends on a few unexported runtime functions. This removes the
assembly stubs it used to get access to these in favour of using
//go:linkname in runtime to make the functions accessible to os/signal.

This is motivated by ppc64le shared libraries, where you cannot BR to a symbol
defined in a shared library (only BL), but it seems like an improvment anyway.

Change-Id: I09361203ce38070bd3f132f6dc5ac212f2dc6f58
Reviewed-on: https://go-review.googlesource.com/15871
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Minux Ma <minux@golang.org>
Reviewed-by: Dave Cheney <dave@cheney.net>
2015-10-16 07:11:04 +00:00

135 lines
2.6 KiB
Go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements runtime support for signal handling.
package runtime
import _ "unsafe"
const qsize = 64
var sig struct {
q noteQueue
inuse bool
lock mutex
note note
sleeping bool
}
type noteData struct {
s [_ERRMAX]byte
n int // n bytes of s are valid
}
type noteQueue struct {
lock mutex
data [qsize]noteData
ri int
wi int
full bool
}
// It is not allowed to allocate memory in the signal handler.
func (q *noteQueue) push(item *byte) bool {
lock(&q.lock)
if q.full {
unlock(&q.lock)
return false
}
s := gostringnocopy(item)
copy(q.data[q.wi].s[:], s)
q.data[q.wi].n = len(s)
q.wi++
if q.wi == qsize {
q.wi = 0
}
if q.wi == q.ri {
q.full = true
}
unlock(&q.lock)
return true
}
func (q *noteQueue) pop() string {
lock(&q.lock)
q.full = false
if q.ri == q.wi {
unlock(&q.lock)
return ""
}
note := &q.data[q.ri]
item := string(note.s[:note.n])
q.ri++
if q.ri == qsize {
q.ri = 0
}
unlock(&q.lock)
return item
}
// Called from sighandler to send a signal back out of the signal handling thread.
// Reports whether the signal was sent. If not, the caller typically crashes the program.
func sendNote(s *byte) bool {
if !sig.inuse {
return false
}
// Add signal to outgoing queue.
if !sig.q.push(s) {
return false
}
lock(&sig.lock)
if sig.sleeping {
sig.sleeping = false
notewakeup(&sig.note)
}
unlock(&sig.lock)
return true
}
// Called to receive the next queued signal.
// Must only be called from a single goroutine at a time.
//go:linkname signal_recv os/signal.signal_recv
func signal_recv() string {
for {
note := sig.q.pop()
if note != "" {
return note
}
lock(&sig.lock)
sig.sleeping = true
noteclear(&sig.note)
unlock(&sig.lock)
notetsleepg(&sig.note, -1)
}
}
// Must only be called from a single goroutine at a time.
//go:linkname signal_enable os/signal.signal_enable
func signal_enable(s uint32) {
if !sig.inuse {
// The first call to signal_enable is for us
// to use for initialization. It does not pass
// signal information in m.
sig.inuse = true // enable reception of signals; cannot disable
noteclear(&sig.note)
return
}
}
// Must only be called from a single goroutine at a time.
//go:linkname signal_disable os/signal.signal_disable
func signal_disable(s uint32) {
}
// Must only be called from a single goroutine at a time.
//go:linkname signal_ignore os/signal.signal_ignore
func signal_ignore(s uint32) {
}