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
38 func pollset_ctl(ps pollset_t
, pollctl_array
*poll_ctl
, array_length
int32) int32
41 func pollset_poll(ps pollset_t
, polldata_array
*pollfd
, array_length
int32, timeout
int32) int32
44 func libc_pipe(fd
*int32) int32
46 //extern __go_fcntl_uintptr
47 func fcntlUintptr(fd
, cmd
, arg
uintptr) (uintptr, uintptr)
49 func fcntl(fd
, cmd
int32, arg
uintptr) uintptr {
50 r
, _
:= fcntlUintptr(uintptr(fd
), uintptr(cmd
), arg
)
56 mpfds
map[int32]*pollDesc
66 if ps
= pollset_create(-1); ps
< 0 {
67 throw("netpollinit: failed to create pollset")
69 // It is not possible to add or remove descriptors from
70 // the pollset while pollset_poll is active.
71 // We use a pipe to wakeup pollset_poll when the pollset
72 // needs to be updated.
73 if err
:= libc_pipe(&p
[0]); err
< 0 {
74 throw("netpollinit: failed to create pipe")
79 fl
:= fcntl(rdwake
, _F_GETFL
, 0)
80 fcntl(rdwake
, _F_SETFL
, fl|_O_NONBLOCK
)
81 fcntl(rdwake
, _F_SETFD
, _FD_CLOEXEC
)
83 fl
= fcntl(wrwake
, _F_GETFL
, 0)
84 fcntl(wrwake
, _F_SETFL
, fl|_O_NONBLOCK
)
85 fcntl(wrwake
, _F_SETFD
, _FD_CLOEXEC
)
87 // Add the read side of the pipe to the pollset.
92 if pollset_ctl(ps
, &pctl
, 1) != 0 {
93 throw("netpollinit: failed to register pipe")
96 mpfds
= make(map[int32]*pollDesc
)
99 func netpollopen(fd
uintptr, pd
*pollDesc
) int32 {
100 // pollset_ctl will block if pollset_poll is active
101 // so wakeup pollset_poll first.
106 write(uintptr(wrwake
), unsafe
.Pointer(&b
[0]), 1)
111 pctl
.events
= _POLLIN | _POLLOUT
112 if pollset_ctl(ps
, &pctl
, 1) != 0 {
113 return int32(errno())
116 mpfds
[int32(fd
)] = pd
123 func netpollclose(fd
uintptr) int32 {
124 // pollset_ctl will block if pollset_poll is active
125 // so wakeup pollset_poll first.
130 write(uintptr(wrwake
), unsafe
.Pointer(&b
[0]), 1)
133 pctl
.cmd
= _PS_DELETE
135 if pollset_ctl(ps
, &pctl
, 1) != 0 {
136 return int32(errno())
139 delete(mpfds
, int32(fd
))
146 func netpollarm(pd
*pollDesc
, mode
int) {
150 func netpoll(block
bool) *g
{
167 nfound
:= pollset_poll(ps
, &pfds
[0], int32(len(pfds
)), timeout
)
171 throw("pollset_poll failed")
176 for i
:= int32(0); i
< nfound
; i
++ {
180 if pfd
.revents
&(_POLLIN|_POLLHUP|_POLLERR
) != 0 {
181 if pfd
.fd
== rdwake
{
183 read(pfd
.fd
, unsafe
.Pointer(&b
[0]), 1)
188 if pfd
.revents
&(_POLLOUT|_POLLHUP|_POLLERR
) != 0 {
196 netpollready(&gp
, pd
, mode
)
200 if block
&& gp
== 0 {