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