aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/runtime/netpoll_epoll.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/netpoll_epoll.go')
-rw-r--r--libgo/go/runtime/netpoll_epoll.go116
1 files changed, 116 insertions, 0 deletions
diff --git a/libgo/go/runtime/netpoll_epoll.go b/libgo/go/runtime/netpoll_epoll.go
new file mode 100644
index 0000000..777150e
--- /dev/null
+++ b/libgo/go/runtime/netpoll_epoll.go
@@ -0,0 +1,116 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+
+package runtime
+
+import "unsafe"
+
+//extern epoll_create
+func epollcreate(size int32) int32
+
+//extern epoll_create1
+func epollcreate1(flags int32) int32
+
+//go:noescape
+//extern epoll_ctl
+func epollctl(epfd, op, fd int32, ev *epollevent) int32
+
+//go:noescape
+//extern epoll_wait
+func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32
+
+//extern __go_fcntl_uintptr
+func fcntlUintptr(fd, cmd, arg uintptr) (uintptr, uintptr)
+
+func closeonexec(fd int32) {
+ fcntlUintptr(uintptr(fd), _F_SETFD, _FD_CLOEXEC)
+}
+
+var (
+ epfd int32 = -1 // epoll descriptor
+)
+
+func netpollinit() {
+ epfd = epollcreate1(_EPOLL_CLOEXEC)
+ if epfd >= 0 {
+ return
+ }
+ epfd = epollcreate(1024)
+ if epfd >= 0 {
+ closeonexec(epfd)
+ return
+ }
+ println("netpollinit: failed to create epoll descriptor", errno())
+ throw("netpollinit: failed to create descriptor")
+}
+
+func netpollopen(fd uintptr, pd *pollDesc) int32 {
+ var ev epollevent
+ ev.events = _EPOLLIN | _EPOLLOUT | _EPOLLRDHUP | _EPOLLET
+ *(**pollDesc)(unsafe.Pointer(&ev.data)) = pd
+ if epollctl(epfd, _EPOLL_CTL_ADD, int32(fd), &ev) < 0 {
+ return int32(errno())
+ }
+ return 0
+}
+
+func netpollclose(fd uintptr) int32 {
+ var ev epollevent
+ if epollctl(epfd, _EPOLL_CTL_DEL, int32(fd), &ev) < 0 {
+ return int32(errno())
+ }
+ return 0
+}
+
+func netpollarm(pd *pollDesc, mode int) {
+ throw("unused")
+}
+
+// polls for ready network connections
+// returns list of goroutines that become runnable
+func netpoll(block bool) *g {
+ if epfd == -1 {
+ return nil
+ }
+ waitms := int32(-1)
+ if !block {
+ waitms = 0
+ }
+ var events [128]epollevent
+retry:
+ n := epollwait(epfd, &events[0], int32(len(events)), waitms)
+ if n < 0 {
+ e := errno()
+ if e != _EINTR {
+ println("runtime: epollwait on fd", epfd, "failed with", e)
+ throw("epollwait failed")
+ }
+ goto retry
+ }
+ var gp guintptr
+ for i := int32(0); i < n; i++ {
+ ev := &events[i]
+ if ev.events == 0 {
+ continue
+ }
+ var mode int32
+ if ev.events&(_EPOLLIN|_EPOLLRDHUP|_EPOLLHUP|_EPOLLERR) != 0 {
+ mode += 'r'
+ }
+ if ev.events&(_EPOLLOUT|_EPOLLHUP|_EPOLLERR) != 0 {
+ mode += 'w'
+ }
+ if mode != 0 {
+ pd := *(**pollDesc)(unsafe.Pointer(&ev.data))
+
+ netpollready(&gp, pd, mode)
+ }
+ }
+ if block && gp == 0 {
+ goto retry
+ }
+ return gp.ptr()
+}