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. 4 5 // +build linux 6 7 package runtime 8 9 import "unsafe" 10 11 func epollcreate(size int32) int32 12 func epollcreate1(flags int32) int32 13 14 //go:noescape 15 func epollctl(epfd, op, fd int32, ev *epollevent) int32 16 17 //go:noescape 18 func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32 19 func closeonexec(fd int32) 20 21 var ( 22 epfd int32 = -1 // epoll descriptor 23 netpolllasterr int32 24 ) 25 26 func netpollinit() { 27 epfd = epollcreate1(_EPOLL_CLOEXEC) 28 if epfd >= 0 { 29 return 30 } 31 epfd = epollcreate(1024) 32 if epfd >= 0 { 33 closeonexec(epfd) 34 return 35 } 36 println("netpollinit: failed to create epoll descriptor", -epfd) 37 throw("netpollinit: failed to create descriptor") 38 } 39 40 func netpollopen(fd uintptr, pd *pollDesc) int32 { 41 var ev epollevent 42 ev.events = _EPOLLIN | _EPOLLOUT | _EPOLLRDHUP | _EPOLLET 43 *(**pollDesc)(unsafe.Pointer(&ev.data)) = pd 44 return -epollctl(epfd, _EPOLL_CTL_ADD, int32(fd), &ev) 45 } 46 47 func netpollclose(fd uintptr) int32 { 48 var ev epollevent 49 return -epollctl(epfd, _EPOLL_CTL_DEL, int32(fd), &ev) 50 } 51 52 func netpollarm(pd *pollDesc, mode int) { 53 throw("unused") 54 } 55 56 // polls for ready network connections 57 // returns list of goroutines that become runnable 58 func netpoll(block bool) *g { 59 if epfd == -1 { 60 return nil 61 } 62 waitms := int32(-1) 63 if !block { 64 waitms = 0 65 } 66 var events [128]epollevent 67 retry: 68 n := epollwait(epfd, &events[0], int32(len(events)), waitms) 69 if n < 0 { 70 if n != -_EINTR && n != netpolllasterr { 71 netpolllasterr = n 72 println("runtime: epollwait on fd", epfd, "failed with", -n) 73 } 74 goto retry 75 } 76 var gp guintptr 77 for i := int32(0); i < n; i++ { 78 ev := &events[i] 79 if ev.events == 0 { 80 continue 81 } 82 var mode int32 83 if ev.events&(_EPOLLIN|_EPOLLRDHUP|_EPOLLHUP|_EPOLLERR) != 0 { 84 mode += 'r' 85 } 86 if ev.events&(_EPOLLOUT|_EPOLLHUP|_EPOLLERR) != 0 { 87 mode += 'w' 88 } 89 if mode != 0 { 90 pd := *(**pollDesc)(unsafe.Pointer(&ev.data)) 91 92 netpollready(&gp, pd, mode) 93 } 94 } 95 if block && gp == 0 { 96 goto retry 97 } 98 return gp.ptr() 99 } 100