diff options
| author | David du Colombier <0intro@gmail.com> | 2015-01-22 23:38:29 +0100 |
|---|---|---|
| committer | David du Colombier <0intro@gmail.com> | 2015-02-06 19:46:34 +0000 |
| commit | d5d4ab78195aac74bf1824c0b13cb91d2d7d3f07 (patch) | |
| tree | 551d1551db80317a541bd2d0d8692d7e59bc094d /src/runtime | |
| parent | 1b523384dc5c46e0a137d73f65dda636bfeda350 (diff) | |
| download | go-d5d4ab78195aac74bf1824c0b13cb91d2d7d3f07.tar.xz | |
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>
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/os3_plan9.go | 6 | ||||
| -rw-r--r-- | src/runtime/sigqueue.go | 2 | ||||
| -rw-r--r-- | src/runtime/sigqueue_plan9.go | 115 |
3 files changed, 120 insertions, 3 deletions
diff --git a/src/runtime/os3_plan9.go b/src/runtime/os3_plan9.go index 58ca0e7b2f..facaab2546 100644 --- a/src/runtime/os3_plan9.go +++ b/src/runtime/os3_plan9.go @@ -72,9 +72,9 @@ func sighandler(_ureg *ureg, note *byte, gp *g) int { return _NCONT } if flags&_SigNotify != 0 { - // TODO(ality): See if os/signal wants it. - //if(sigsend(...)) - // return _NCONT; + if sendNote(note) { + return _NCONT + } } if flags&_SigKill != 0 { goto Exit diff --git a/src/runtime/sigqueue.go b/src/runtime/sigqueue.go index fbe3425fa6..5cfc926f67 100644 --- a/src/runtime/sigqueue.go +++ b/src/runtime/sigqueue.go @@ -24,6 +24,8 @@ // unnecessary rechecks of sig.mask, but it cannot lead to missed signals // nor deadlocks. +// +build !plan9 + package runtime import "unsafe" diff --git a/src/runtime/sigqueue_plan9.go b/src/runtime/sigqueue_plan9.go new file mode 100644 index 0000000000..b029a300a8 --- /dev/null +++ b/src/runtime/sigqueue_plan9.go @@ -0,0 +1,115 @@ +// 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) { +} |
