aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/netpoll_kqueue_pipe.go
diff options
context:
space:
mode:
authorAndy Pan <i@andypan.me>2024-04-10 16:48:09 +0800
committerGopher Robot <gobot@golang.org>2024-04-12 21:17:22 +0000
commit519f6a00e4dabb871eadaefc8ac295c09fd9b56f (patch)
tree8c18ffe9cc2a7199823dcd81c48e1b841dde92f7 /src/runtime/netpoll_kqueue_pipe.go
parent19626726205b5653ff9a1820d35bf1b7e820d4ce (diff)
downloadgo-519f6a00e4dabb871eadaefc8ac295c09fd9b56f.tar.xz
runtime: utilize EVFILT_USER to wake up kevent for kqueue
Fixes #66760 Change-Id: I6ba5bc5b00506b66cb8dc3984a61f32a6358d9bc Reviewed-on: https://go-review.googlesource.com/c/go/+/577895 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Run-TryBot: Andy Pan <panjf2000@gmail.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Diffstat (limited to 'src/runtime/netpoll_kqueue_pipe.go')
-rw-r--r--src/runtime/netpoll_kqueue_pipe.go73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/runtime/netpoll_kqueue_pipe.go b/src/runtime/netpoll_kqueue_pipe.go
new file mode 100644
index 0000000000..98f73e84d2
--- /dev/null
+++ b/src/runtime/netpoll_kqueue_pipe.go
@@ -0,0 +1,73 @@
+// Copyright 2024 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 netbsd || openbsd
+
+package runtime
+
+import "unsafe"
+
+// TODO(panjf2000): NetBSD didn't implement EVFILT_USER for user-established events
+// until NetBSD 10.0, check out https://www.netbsd.org/releases/formal-10/NetBSD-10.0.html
+// Therefore we use the pipe to wake up the kevent on NetBSD at this point. Get back here
+// and switch to EVFILT_USER when we bump up the minimal requirement of NetBSD to 10.0.
+// Alternatively, maybe we can use EVFILT_USER on the NetBSD by checking the kernel version
+// via uname(3) and fall back to the pipe if the kernel version is older than 10.0.
+
+var netpollBreakRd, netpollBreakWr uintptr // for netpollBreak
+
+func addWakeupEvent(kq int32) {
+ r, w, errno := nonblockingPipe()
+ if errno != 0 {
+ println("runtime: pipe failed with", -errno)
+ throw("runtime: pipe failed")
+ }
+ ev := keventt{
+ filter: _EVFILT_READ,
+ flags: _EV_ADD,
+ }
+ *(*uintptr)(unsafe.Pointer(&ev.ident)) = uintptr(r)
+ n := kevent(kq, &ev, 1, nil, 0, nil)
+ if n < 0 {
+ println("runtime: kevent failed with", -n)
+ throw("runtime: kevent failed")
+ }
+ netpollBreakRd = uintptr(r)
+ netpollBreakWr = uintptr(w)
+}
+
+func wakeNetpoll(_ int32) {
+ for {
+ var b byte
+ n := write(netpollBreakWr, unsafe.Pointer(&b), 1)
+ if n == 1 || n == -_EAGAIN {
+ break
+ }
+ if n == -_EINTR {
+ continue
+ }
+ println("runtime: netpollBreak write failed with", -n)
+ throw("runtime: netpollBreak write failed")
+ }
+}
+
+func isWakeup(ev *keventt) bool {
+ if uintptr(ev.ident) == netpollBreakRd {
+ if ev.filter == _EVFILT_READ {
+ return true
+ }
+ println("runtime: netpoll: break fd ready for", ev.filter)
+ throw("runtime: netpoll: break fd ready for something unexpected")
+ }
+ return false
+}
+
+func drainWakeupEvent(_ int32) {
+ var buf [16]byte
+ read(int32(netpollBreakRd), noescape(unsafe.Pointer(&buf[0])), int32(len(buf)))
+}
+
+func netpollIsPollDescriptor(fd uintptr) bool {
+ return fd == uintptr(kq) || fd == netpollBreakRd || fd == netpollBreakWr
+}