summaryrefslogtreecommitdiff
path: root/src/runtime/netpoll_epoll.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/netpoll_epoll.go')
-rw-r--r--src/runtime/netpoll_epoll.go97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/runtime/netpoll_epoll.go b/src/runtime/netpoll_epoll.go
new file mode 100644
index 000000000..ecfc9cdde
--- /dev/null
+++ b/src/runtime/netpoll_epoll.go
@@ -0,0 +1,97 @@
+// 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"
+
+func epollcreate(size int32) int32
+func epollcreate1(flags int32) int32
+
+//go:noescape
+func epollctl(epfd, op, fd int32, ev *epollevent) int32
+
+//go:noescape
+func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32
+func closeonexec(fd int32)
+
+var (
+ epfd int32 = -1 // epoll descriptor
+ netpolllasterr int32
+)
+
+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", -epfd)
+ gothrow("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
+ return -epollctl(epfd, _EPOLL_CTL_ADD, int32(fd), &ev)
+}
+
+func netpollclose(fd uintptr) int32 {
+ var ev epollevent
+ return -epollctl(epfd, _EPOLL_CTL_DEL, int32(fd), &ev)
+}
+
+func netpollarm(pd *pollDesc, mode int) {
+ gothrow("unused")
+}
+
+// polls for ready network connections
+// returns list of goroutines that become runnable
+func netpoll(block bool) (gp *g) {
+ if epfd == -1 {
+ return
+ }
+ waitms := int32(-1)
+ if !block {
+ waitms = 0
+ }
+ var events [128]epollevent
+retry:
+ n := epollwait(epfd, &events[0], int32(len(events)), waitms)
+ if n < 0 {
+ if n != -_EINTR && n != netpolllasterr {
+ netpolllasterr = n
+ println("runtime: epollwait on fd", epfd, "failed with", -n)
+ }
+ goto retry
+ }
+ 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((**g)(noescape(unsafe.Pointer(&gp))), pd, mode)
+ }
+ }
+ if block && gp == nil {
+ goto retry
+ }
+ return gp
+}