1
0
mirror of https://github.com/golang/go synced 2024-11-08 06:26:19 -07:00
go/src/runtime/sigqueue_plan9.go
David du Colombier d5d4ab7819 os/signal, runtime: implement notes on Plan 9
This change is an implementation of the signal
runtime and os/signal package on Plan 9.

Contrary to Unix, on Plan 9 a signal is called
a note and is represented by a string.

For this reason, the sigsend and signal_recv
functions had to be reimplemented specifically
for Plan 9.

In order to reuse most of the code and internal
interface of the os/signal package, the note
strings are mapped to integers.

Thanks to Russ Cox for the early review.

Change-Id: I95836645efe21942bb1939f43f87fb3c0eaaef1a
Reviewed-on: https://go-review.googlesource.com/2164
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
2015-02-06 19:46:34 +00:00

116 lines
2.0 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
const qsize = 64
var sig struct {
q noteQueue
inuse bool
lock mutex
note note
sleeping bool
}
type noteQueue struct {
lock mutex
data [qsize]*byte
ri int
wi int
full bool
}
func (q *noteQueue) push(item *byte) bool {
lock(&q.lock)
if q.full {
unlock(&q.lock)
return false
}
q.data[q.wi] = item
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() *byte {
lock(&q.lock)
q.full = false
if q.ri == q.wi {
unlock(&q.lock)
return nil
}
item := q.data[q.ri]
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.
func signal_recv() string {
for {
note := sig.q.pop()
if note != nil {
return gostring(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.
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.
func signal_disable(s uint32) {
}