Source file src/runtime/netpoll_aix.go
1
2
3
4
5 package runtime
6
7 import "unsafe"
8
9
10
11
12
13
14
15
16 var libc_poll libFunc
17
18
19 func poll(pfds *pollfd, npfds uintptr, timeout uintptr) (int32, int32) {
20 r, err := syscall3(&libc_poll, uintptr(unsafe.Pointer(pfds)), npfds, timeout)
21 return int32(r), int32(err)
22 }
23
24
25 func fcntl(fd, cmd int32, arg uintptr) int32 {
26 r, _ := syscall3(&libc_fcntl, uintptr(fd), uintptr(cmd), arg)
27 return int32(r)
28 }
29
30
31 type pollfd struct {
32 fd int32
33 events int16
34 revents int16
35 }
36
37 const _POLLIN = 0x0001
38 const _POLLOUT = 0x0002
39 const _POLLHUP = 0x2000
40 const _POLLERR = 0x4000
41 const _O_NONBLOCK = 0x4
42
43 var (
44 pfds []pollfd
45 pds []*pollDesc
46 mtxpoll mutex
47 mtxset mutex
48 rdwake int32
49 wrwake int32
50 pendingUpdates int32
51 )
52
53 func netpollinit() {
54 var p [2]int32
55
56
57 if err := pipe(&p[0]); err < 0 {
58 throw("netpollinit: failed to create pipe")
59 }
60 rdwake = p[0]
61 wrwake = p[1]
62
63 fl := uintptr(fcntl(rdwake, _F_GETFL, 0))
64 fcntl(rdwake, _F_SETFL, fl|_O_NONBLOCK)
65 fcntl(rdwake, _F_SETFD, _FD_CLOEXEC)
66
67 fl = uintptr(fcntl(wrwake, _F_GETFL, 0))
68 fcntl(wrwake, _F_SETFL, fl|_O_NONBLOCK)
69 fcntl(wrwake, _F_SETFD, _FD_CLOEXEC)
70
71
72 pfds = make([]pollfd, 1, 128)
73
74
75 pfds[0].fd = rdwake
76 pfds[0].events = _POLLIN
77
78 pds = make([]*pollDesc, 1, 128)
79 pds[0] = nil
80 }
81
82 func netpolldescriptor() uintptr {
83
84 if rdwake > 0xFFFF || wrwake > 0xFFFF {
85 throw("netpolldescriptor: invalid fd number")
86 }
87 return uintptr(rdwake<<16 | wrwake)
88 }
89
90
91 func netpollwakeup() {
92 if pendingUpdates == 0 {
93 pendingUpdates = 1
94 b := [1]byte{0}
95 write(uintptr(wrwake), unsafe.Pointer(&b[0]), 1)
96 }
97 }
98
99 func netpollopen(fd uintptr, pd *pollDesc) int32 {
100 lock(&mtxpoll)
101 netpollwakeup()
102
103 lock(&mtxset)
104 unlock(&mtxpoll)
105
106 pd.user = uint32(len(pfds))
107 pfds = append(pfds, pollfd{fd: int32(fd)})
108 pds = append(pds, pd)
109 unlock(&mtxset)
110 return 0
111 }
112
113 func netpollclose(fd uintptr) int32 {
114 lock(&mtxpoll)
115 netpollwakeup()
116
117 lock(&mtxset)
118 unlock(&mtxpoll)
119
120 for i := 0; i < len(pfds); i++ {
121 if pfds[i].fd == int32(fd) {
122 pfds[i] = pfds[len(pfds)-1]
123 pfds = pfds[:len(pfds)-1]
124
125 pds[i] = pds[len(pds)-1]
126 pds[i].user = uint32(i)
127 pds = pds[:len(pds)-1]
128 break
129 }
130 }
131 unlock(&mtxset)
132 return 0
133 }
134
135 func netpollarm(pd *pollDesc, mode int) {
136 lock(&mtxpoll)
137 netpollwakeup()
138
139 lock(&mtxset)
140 unlock(&mtxpoll)
141
142 switch mode {
143 case 'r':
144 pfds[pd.user].events |= _POLLIN
145 case 'w':
146 pfds[pd.user].events |= _POLLOUT
147 }
148 unlock(&mtxset)
149 }
150
151
152 func netpoll(block bool) gList {
153 timeout := ^uintptr(0)
154 if !block {
155 timeout = 0
156 return gList{}
157 }
158 retry:
159 lock(&mtxpoll)
160 lock(&mtxset)
161 pendingUpdates = 0
162 unlock(&mtxpoll)
163
164 n, e := poll(&pfds[0], uintptr(len(pfds)), timeout)
165 if n < 0 {
166 if e != _EINTR {
167 println("errno=", e, " len(pfds)=", len(pfds))
168 throw("poll failed")
169 }
170 unlock(&mtxset)
171 goto retry
172 }
173
174 if n != 0 && pfds[0].revents&(_POLLIN|_POLLHUP|_POLLERR) != 0 {
175 var b [1]byte
176 for read(rdwake, unsafe.Pointer(&b[0]), 1) == 1 {
177 }
178
179
180 unlock(&mtxset)
181 goto retry
182 }
183 var toRun gList
184 for i := 0; i < len(pfds) && n > 0; i++ {
185 pfd := &pfds[i]
186
187 var mode int32
188 if pfd.revents&(_POLLIN|_POLLHUP|_POLLERR) != 0 {
189 mode += 'r'
190 pfd.events &= ^_POLLIN
191 }
192 if pfd.revents&(_POLLOUT|_POLLHUP|_POLLERR) != 0 {
193 mode += 'w'
194 pfd.events &= ^_POLLOUT
195 }
196 if mode != 0 {
197 pds[i].everr = false
198 if pfd.revents == _POLLERR {
199 pds[i].everr = true
200 }
201 netpollready(&toRun, pds[i], mode)
202 n--
203 }
204 }
205 unlock(&mtxset)
206 if block && toRun.empty() {
207 goto retry
208 }
209 return toRun
210 }
211
View as plain text