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 darwin || dragonfly || freebsd
6
7package runtime
8
9// Magic number of identifier used for EVFILT_USER.
10// This number had zero Google results when it's created.
11// That way, people will be directed here when this number
12// get printed somehow and they search for it.
13const kqIdent = 0xee1eb9f4
14
15func addWakeupEvent(kq int32) {
16	ev := keventt{
17		ident:  kqIdent,
18		filter: _EVFILT_USER,
19		flags:  _EV_ADD,
20	}
21	for {
22		n := kevent(kq, &ev, 1, nil, 0, nil)
23		if n == 0 {
24			break
25		}
26		if n == -_EINTR {
27			// All changes contained in the changelist should have been applied
28			// before returning EINTR. But let's be skeptical and retry it anyway,
29			// to make a 100% commitment.
30			continue
31		}
32		println("runtime: kevent for EVFILT_USER failed with", -n)
33		throw("runtime: kevent failed")
34	}
35}
36
37func wakeNetpoll(kq int32) {
38	ev := keventt{
39		ident:  kqIdent,
40		filter: _EVFILT_USER,
41		flags:  _EV_ENABLE,
42		fflags: _NOTE_TRIGGER,
43	}
44	for {
45		n := kevent(kq, &ev, 1, nil, 0, nil)
46		if n == 0 {
47			break
48		}
49		if n == -_EINTR {
50			// Check out the comment in addWakeupEvent.
51			continue
52		}
53		println("runtime: netpollBreak write failed with", -n)
54		throw("runtime: netpollBreak write failed")
55	}
56}
57
58func isWakeup(ev *keventt) bool {
59	if ev.filter == _EVFILT_USER {
60		if ev.ident == kqIdent {
61			return true
62		}
63		println("runtime: netpoll: break fd ready for", ev.ident)
64		throw("runtime: netpoll: break fd ready for something unexpected")
65	}
66	return false
67}
68
69func drainWakeupEvent(kq int32) {
70	ev := keventt{
71		ident:  kqIdent,
72		filter: _EVFILT_USER,
73		flags:  _EV_DISABLE,
74	}
75	kevent(kq, &ev, 1, nil, 0, nil)
76}
77
78func netpollIsPollDescriptor(fd uintptr) bool {
79	return fd == uintptr(kq)
80}
81