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