...

Source file src/runtime/netpoll_epoll.go

     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("runtime: epollcreate failed with", -epfd)
    36		throw("runtime: netpollinit failed")
    37	}
    38	
    39	func netpolldescriptor() uintptr {
    40		return uintptr(epfd)
    41	}
    42	
    43	func 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	
    50	func netpollclose(fd uintptr) int32 {
    51		var ev epollevent
    52		return -epollctl(epfd, _EPOLL_CTL_DEL, int32(fd), &ev)
    53	}
    54	
    55	func 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
    61	func netpoll(block bool) gList {
    62		if epfd == -1 {
    63			return gList{}
    64		}
    65		waitms := int32(-1)
    66		if !block {
    67			waitms = 0
    68		}
    69		var events [128]epollevent
    70	retry:
    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 toRun gList
    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				pd.everr = false
    95				if ev.events == _EPOLLERR {
    96					pd.everr = true
    97				}
    98				netpollready(&toRun, pd, mode)
    99			}
   100		}
   101		if block && toRun.empty() {
   102			goto retry
   103		}
   104		return toRun
   105	}
   106	

View as plain text