summaryrefslogtreecommitdiffstats
path: root/src/runtime/export_unix_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/export_unix_test.go')
-rw-r--r--src/runtime/export_unix_test.go99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/runtime/export_unix_test.go b/src/runtime/export_unix_test.go
new file mode 100644
index 0000000..56ff771
--- /dev/null
+++ b/src/runtime/export_unix_test.go
@@ -0,0 +1,99 @@
+// Copyright 2017 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.
+
+//go:build unix
+
+package runtime
+
+import "unsafe"
+
+var NonblockingPipe = nonblockingPipe
+var Fcntl = fcntl
+var Closeonexec = closeonexec
+
+func sigismember(mask *sigset, i int) bool {
+ clear := *mask
+ sigdelset(&clear, i)
+ return clear != *mask
+}
+
+func Sigisblocked(i int) bool {
+ var sigmask sigset
+ sigprocmask(_SIG_SETMASK, nil, &sigmask)
+ return sigismember(&sigmask, i)
+}
+
+type M = m
+
+var waitForSigusr1 struct {
+ rdpipe int32
+ wrpipe int32
+ mID int64
+}
+
+// WaitForSigusr1 blocks until a SIGUSR1 is received. It calls ready
+// when it is set up to receive SIGUSR1. The ready function should
+// cause a SIGUSR1 to be sent. The r and w arguments are a pipe that
+// the signal handler can use to report when the signal is received.
+//
+// Once SIGUSR1 is received, it returns the ID of the current M and
+// the ID of the M the SIGUSR1 was received on. If the caller writes
+// a non-zero byte to w, WaitForSigusr1 returns immediately with -1, -1.
+func WaitForSigusr1(r, w int32, ready func(mp *M)) (int64, int64) {
+ lockOSThread()
+ // Make sure we can receive SIGUSR1.
+ unblocksig(_SIGUSR1)
+
+ waitForSigusr1.rdpipe = r
+ waitForSigusr1.wrpipe = w
+
+ mp := getg().m
+ testSigusr1 = waitForSigusr1Callback
+ ready(mp)
+
+ // Wait for the signal. We use a pipe rather than a note
+ // because write is always async-signal-safe.
+ entersyscallblock()
+ var b byte
+ read(waitForSigusr1.rdpipe, noescape(unsafe.Pointer(&b)), 1)
+ exitsyscall()
+
+ gotM := waitForSigusr1.mID
+ testSigusr1 = nil
+
+ unlockOSThread()
+
+ if b != 0 {
+ // timeout signal from caller
+ return -1, -1
+ }
+ return mp.id, gotM
+}
+
+// waitForSigusr1Callback is called from the signal handler during
+// WaitForSigusr1. It must not have write barriers because there may
+// not be a P.
+//
+//go:nowritebarrierrec
+func waitForSigusr1Callback(gp *g) bool {
+ if gp == nil || gp.m == nil {
+ waitForSigusr1.mID = -1
+ } else {
+ waitForSigusr1.mID = gp.m.id
+ }
+ b := byte(0)
+ write(uintptr(waitForSigusr1.wrpipe), noescape(unsafe.Pointer(&b)), 1)
+ return true
+}
+
+// SendSigusr1 sends SIGUSR1 to mp.
+func SendSigusr1(mp *M) {
+ signalM(mp, _SIGUSR1)
+}
+
+const (
+ O_WRONLY = _O_WRONLY
+ O_CREAT = _O_CREAT
+ O_TRUNC = _O_TRUNC
+)