Source file
src/runtime/netpoll_kqueue.go
1
2
3
4
5
6
7 package runtime
8
9
10
11 import (
12 "runtime/internal/atomic"
13 "unsafe"
14 )
15
16 var (
17 kq int32 = -1
18
19 netpollBreakRd, netpollBreakWr uintptr
20
21 netpollWakeSig uint32
22 )
23
24 func netpollinit() {
25 kq = kqueue()
26 if kq < 0 {
27 println("runtime: kqueue failed with", -kq)
28 throw("runtime: netpollinit failed")
29 }
30 closeonexec(kq)
31 r, w, errno := nonblockingPipe()
32 if errno != 0 {
33 println("runtime: pipe failed with", -errno)
34 throw("runtime: pipe failed")
35 }
36 ev := keventt{
37 filter: _EVFILT_READ,
38 flags: _EV_ADD,
39 }
40 *(*uintptr)(unsafe.Pointer(&ev.ident)) = uintptr(r)
41 n := kevent(kq, &ev, 1, nil, 0, nil)
42 if n < 0 {
43 println("runtime: kevent failed with", -n)
44 throw("runtime: kevent failed")
45 }
46 netpollBreakRd = uintptr(r)
47 netpollBreakWr = uintptr(w)
48 }
49
50 func netpollIsPollDescriptor(fd uintptr) bool {
51 return fd == uintptr(kq) || fd == netpollBreakRd || fd == netpollBreakWr
52 }
53
54 func netpollopen(fd uintptr, pd *pollDesc) int32 {
55
56
57
58 var ev [2]keventt
59 *(*uintptr)(unsafe.Pointer(&ev[0].ident)) = fd
60 ev[0].filter = _EVFILT_READ
61 ev[0].flags = _EV_ADD | _EV_CLEAR
62 ev[0].fflags = 0
63 ev[0].data = 0
64 ev[0].udata = (*byte)(unsafe.Pointer(pd))
65 ev[1] = ev[0]
66 ev[1].filter = _EVFILT_WRITE
67 n := kevent(kq, &ev[0], 2, nil, 0, nil)
68 if n < 0 {
69 return -n
70 }
71 return 0
72 }
73
74 func netpollclose(fd uintptr) int32 {
75
76
77 return 0
78 }
79
80 func netpollarm(pd *pollDesc, mode int) {
81 throw("runtime: unused")
82 }
83
84
85 func netpollBreak() {
86 if atomic.Cas(&netpollWakeSig, 0, 1) {
87 for {
88 var b byte
89 n := write(netpollBreakWr, unsafe.Pointer(&b), 1)
90 if n == 1 || n == -_EAGAIN {
91 break
92 }
93 if n == -_EINTR {
94 continue
95 }
96 println("runtime: netpollBreak write failed with", -n)
97 throw("runtime: netpollBreak write failed")
98 }
99 }
100 }
101
102
103
104
105
106
107 func netpoll(delay int64) gList {
108 if kq == -1 {
109 return gList{}
110 }
111 var tp *timespec
112 var ts timespec
113 if delay < 0 {
114 tp = nil
115 } else if delay == 0 {
116 tp = &ts
117 } else {
118 ts.setNsec(delay)
119 if ts.tv_sec > 1e6 {
120
121 ts.tv_sec = 1e6
122 }
123 tp = &ts
124 }
125 var events [64]keventt
126 retry:
127 n := kevent(kq, nil, 0, &events[0], int32(len(events)), tp)
128 if n < 0 {
129 if n != -_EINTR {
130 println("runtime: kevent on fd", kq, "failed with", -n)
131 throw("runtime: netpoll failed")
132 }
133
134
135 if delay > 0 {
136 return gList{}
137 }
138 goto retry
139 }
140 var toRun gList
141 for i := 0; i < int(n); i++ {
142 ev := &events[i]
143
144 if uintptr(ev.ident) == netpollBreakRd {
145 if ev.filter != _EVFILT_READ {
146 println("runtime: netpoll: break fd ready for", ev.filter)
147 throw("runtime: netpoll: break fd ready for something unexpected")
148 }
149 if delay != 0 {
150
151
152
153 var tmp [16]byte
154 read(int32(netpollBreakRd), noescape(unsafe.Pointer(&tmp[0])), int32(len(tmp)))
155 atomic.Store(&netpollWakeSig, 0)
156 }
157 continue
158 }
159
160 var mode int32
161 switch ev.filter {
162 case _EVFILT_READ:
163 mode += 'r'
164
165
166
167
168
169
170
171
172
173
174 if ev.flags&_EV_EOF != 0 {
175 mode += 'w'
176 }
177 case _EVFILT_WRITE:
178 mode += 'w'
179 }
180 if mode != 0 {
181 pd := (*pollDesc)(unsafe.Pointer(ev.udata))
182 pd.setEventErr(ev.flags == _EV_ERROR)
183 netpollready(&toRun, pd, mode)
184 }
185 }
186 return toRun
187 }
188
View as plain text