1// Copyright 2024 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5//go:build netbsd || openbsd 6 7package runtime 8 9import "unsafe" 10 11// TODO(panjf2000): NetBSD didn't implement EVFILT_USER for user-established events 12// until NetBSD 10.0, check out https://www.netbsd.org/releases/formal-10/NetBSD-10.0.html 13// Therefore we use the pipe to wake up the kevent on NetBSD at this point. Get back here 14// and switch to EVFILT_USER when we bump up the minimal requirement of NetBSD to 10.0. 15// Alternatively, maybe we can use EVFILT_USER on the NetBSD by checking the kernel version 16// via uname(3) and fall back to the pipe if the kernel version is older than 10.0. 17 18var netpollBreakRd, netpollBreakWr uintptr // for netpollBreak 19 20func addWakeupEvent(kq int32) { 21 r, w, errno := nonblockingPipe() 22 if errno != 0 { 23 println("runtime: pipe failed with", -errno) 24 throw("runtime: pipe failed") 25 } 26 ev := keventt{ 27 filter: _EVFILT_READ, 28 flags: _EV_ADD, 29 } 30 *(*uintptr)(unsafe.Pointer(&ev.ident)) = uintptr(r) 31 n := kevent(kq, &ev, 1, nil, 0, nil) 32 if n < 0 { 33 println("runtime: kevent failed with", -n) 34 throw("runtime: kevent failed") 35 } 36 netpollBreakRd = uintptr(r) 37 netpollBreakWr = uintptr(w) 38} 39 40func wakeNetpoll(_ int32) { 41 for { 42 var b byte 43 n := write(netpollBreakWr, unsafe.Pointer(&b), 1) 44 if n == 1 || n == -_EAGAIN { 45 break 46 } 47 if n == -_EINTR { 48 continue 49 } 50 println("runtime: netpollBreak write failed with", -n) 51 throw("runtime: netpollBreak write failed") 52 } 53} 54 55func isWakeup(ev *keventt) bool { 56 if uintptr(ev.ident) == netpollBreakRd { 57 if ev.filter == _EVFILT_READ { 58 return true 59 } 60 println("runtime: netpoll: break fd ready for", ev.filter) 61 throw("runtime: netpoll: break fd ready for something unexpected") 62 } 63 return false 64} 65 66func drainWakeupEvent(_ int32) { 67 var buf [16]byte 68 read(int32(netpollBreakRd), noescape(unsafe.Pointer(&buf[0])), int32(len(buf))) 69} 70 71func netpollIsPollDescriptor(fd uintptr) bool { 72 return fd == uintptr(kq) || fd == netpollBreakRd || fd == netpollBreakWr 73} 74