2018-23-01 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / go / runtime / netpoll_epoll.go
blobced399d781e2b69136998020f2b61670042a9bef
1 // Copyright 2013 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.
5 // +build linux
7 package runtime
9 import "unsafe"
11 //extern epoll_create
12 func epollcreate(size int32) int32
14 //extern epoll_create1
15 func epollcreate1(flags int32) int32
17 //go:noescape
18 //extern epoll_ctl
19 func epollctl(epfd, op, fd int32, ev *epollevent) int32
21 //go:noescape
22 //extern epoll_wait
23 func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32
25 //extern __go_fcntl_uintptr
26 func fcntlUintptr(fd, cmd, arg uintptr) (uintptr, uintptr)
28 func closeonexec(fd int32) {
29 fcntlUintptr(uintptr(fd), _F_SETFD, _FD_CLOEXEC)
32 var (
33 epfd int32 = -1 // epoll descriptor
36 func netpollinit() {
37 epfd = epollcreate1(_EPOLL_CLOEXEC)
38 if epfd >= 0 {
39 return
41 epfd = epollcreate(1024)
42 if epfd >= 0 {
43 closeonexec(epfd)
44 return
46 println("netpollinit: failed to create epoll descriptor", errno())
47 throw("netpollinit: failed to create descriptor")
50 func netpolldescriptor() uintptr {
51 return uintptr(epfd)
54 func netpollopen(fd uintptr, pd *pollDesc) int32 {
55 var ev epollevent
56 ev.events = _EPOLLIN | _EPOLLOUT | _EPOLLRDHUP | _EPOLLETpos
57 *(**pollDesc)(unsafe.Pointer(&ev.data)) = pd
58 if epollctl(epfd, _EPOLL_CTL_ADD, int32(fd), &ev) < 0 {
59 return int32(errno())
61 return 0
64 func netpollclose(fd uintptr) int32 {
65 var ev epollevent
66 if epollctl(epfd, _EPOLL_CTL_DEL, int32(fd), &ev) < 0 {
67 return int32(errno())
69 return 0
72 func netpollarm(pd *pollDesc, mode int) {
73 throw("runtime: unused")
76 // polls for ready network connections
77 // returns list of goroutines that become runnable
78 func netpoll(block bool) *g {
79 if epfd == -1 {
80 return nil
82 waitms := int32(-1)
83 if !block {
84 waitms = 0
86 var events [128]epollevent
87 retry:
88 n := epollwait(epfd, &events[0], int32(len(events)), waitms)
89 if n < 0 {
90 e := errno()
91 if e != _EINTR {
92 println("runtime: epollwait on fd", epfd, "failed with", e)
93 throw("runtime: netpoll failed")
95 goto retry
97 var gp guintptr
98 for i := int32(0); i < n; i++ {
99 ev := &events[i]
100 if ev.events == 0 {
101 continue
103 var mode int32
104 if ev.events&(_EPOLLIN|_EPOLLRDHUP|_EPOLLHUP|_EPOLLERR) != 0 {
105 mode += 'r'
107 if ev.events&(_EPOLLOUT|_EPOLLHUP|_EPOLLERR) != 0 {
108 mode += 'w'
110 if mode != 0 {
111 pd := *(**pollDesc)(unsafe.Pointer(&ev.data))
113 netpollready(&gp, pd, mode)
116 if block && gp == 0 {
117 goto retry
119 return gp.ptr()