aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorDavid du Colombier <0intro@gmail.com>2015-01-22 23:38:29 +0100
committerDavid du Colombier <0intro@gmail.com>2015-02-06 19:46:34 +0000
commitd5d4ab78195aac74bf1824c0b13cb91d2d7d3f07 (patch)
tree551d1551db80317a541bd2d0d8692d7e59bc094d /src/runtime
parent1b523384dc5c46e0a137d73f65dda636bfeda350 (diff)
downloadgo-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.go6
-rw-r--r--src/runtime/sigqueue.go2
-rw-r--r--src/runtime/sigqueue_plan9.go115
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) {
+}