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