github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/runtime/netpoll_epoll.go (about) 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) (gp *g) { 59 if epfd == -1 { 60 return 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 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 netpollready((**g)(noescape(unsafe.Pointer(&gp))), pd, mode) 91 } 92 } 93 if block && gp == nil { 94 goto retry 95 } 96 return gp 97 }