OLD | NEW |
(Empty) | |
| 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 gothrow("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 gothrow("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, m
ode) |
| 91 } |
| 92 } |
| 93 if block && gp == nil { |
| 94 goto retry |
| 95 } |
| 96 return gp |
| 97 } |
OLD | NEW |