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