1 // Copyright 2017 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.
9 // This is based on the former libgo/runtime/netpoll_select.c implementation
10 // except that it uses AIX pollset_poll instead of select and is written in Go.
20 const _POLLIN
= 0x0001
21 const _POLLOUT
= 0x0002
22 const _POLLHUP
= 0x2000
23 const _POLLERR
= 0x4000
25 type poll_ctl
struct {
32 const _PS_DELETE
= 0x2
34 //extern pollset_create
35 func pollset_create(maxfd
int32) pollset_t
39 func pollset_ctl(ps pollset_t
, pollctl_array
*poll_ctl
, array_length
int32) int32
43 func pollset_poll(ps pollset_t
, polldata_array
*pollfd
, array_length
int32, timeout
int32) int32
47 func libc_pipe(fd
*int32) int32
49 //extern __go_fcntl_uintptr
50 func fcntlUintptr(fd
, cmd
, arg
uintptr) (uintptr, uintptr)
52 func fcntl(fd
, cmd
int32, arg
uintptr) uintptr {
53 r
, _
:= fcntlUintptr(uintptr(fd
), uintptr(cmd
), arg
)
59 mpfds
map[int32]*pollDesc
69 if ps
= pollset_create(-1); ps
< 0 {
70 throw("runtime: netpollinit failed to create pollset")
72 // It is not possible to add or remove descriptors from
73 // the pollset while pollset_poll is active.
74 // We use a pipe to wakeup pollset_poll when the pollset
75 // needs to be updated.
76 if err
:= libc_pipe(&p
[0]); err
< 0 {
77 throw("runtime: netpollinit failed to create pipe")
82 fl
:= fcntl(rdwake
, _F_GETFL
, 0)
83 fcntl(rdwake
, _F_SETFL
, fl|_O_NONBLOCK
)
84 fcntl(rdwake
, _F_SETFD
, _FD_CLOEXEC
)
86 fl
= fcntl(wrwake
, _F_GETFL
, 0)
87 fcntl(wrwake
, _F_SETFL
, fl|_O_NONBLOCK
)
88 fcntl(wrwake
, _F_SETFD
, _FD_CLOEXEC
)
90 // Add the read side of the pipe to the pollset.
95 if pollset_ctl(ps
, &pctl
, 1) != 0 {
96 throw("runtime: netpollinit failed to register pipe")
99 mpfds
= make(map[int32]*pollDesc
)
102 func netpolldescriptor() uintptr {
103 // ps is not a real file descriptor.
107 func netpollopen(fd
uintptr, pd
*pollDesc
) int32 {
108 // pollset_ctl will block if pollset_poll is active
109 // so wakeup pollset_poll first.
114 write(uintptr(wrwake
), unsafe
.Pointer(&b
[0]), 1)
119 pctl
.events
= _POLLIN | _POLLOUT
120 if pollset_ctl(ps
, &pctl
, 1) != 0 {
121 return int32(errno())
124 mpfds
[int32(fd
)] = pd
131 func netpollclose(fd
uintptr) int32 {
132 // pollset_ctl will block if pollset_poll is active
133 // so wakeup pollset_poll first.
138 write(uintptr(wrwake
), unsafe
.Pointer(&b
[0]), 1)
141 pctl
.cmd
= _PS_DELETE
143 if pollset_ctl(ps
, &pctl
, 1) != 0 {
144 return int32(errno())
147 delete(mpfds
, int32(fd
))
154 func netpollarm(pd
*pollDesc
, mode
int) {
155 throw("runtime: unused")
158 func netpoll(block
bool) *g
{
175 nfound
:= pollset_poll(ps
, &pfds
[0], int32(len(pfds
)), timeout
)
179 throw("runtime: pollset_poll failed")
184 for i
:= int32(0); i
< nfound
; i
++ {
188 if pfd
.revents
&(_POLLIN|_POLLHUP|_POLLERR
) != 0 {
189 if pfd
.fd
== rdwake
{
191 read(pfd
.fd
, unsafe
.Pointer(&b
[0]), 1)
196 if pfd
.revents
&(_POLLOUT|_POLLHUP|_POLLERR
) != 0 {
204 netpollready(&gp
, pd
, mode
)
208 if block
&& gp
== 0 {