package runtime
import (
"runtime/internal/atomic"
"unsafe"
)
func epollcreate(size int32 ) int32
func epollcreate1(flags int32 ) int32
func epollctl(epfd , op , fd int32 , ev *epollevent ) int32
func epollwait(epfd int32 , ev *epollevent , nev , timeout int32 ) int32
func closeonexec(fd int32 )
var (
epfd int32 = -1
netpollBreakRd, netpollBreakWr uintptr
netpollWakeSig uint32
)
func netpollinit() {
epfd = epollcreate1 (_EPOLL_CLOEXEC )
if epfd < 0 {
epfd = epollcreate (1024 )
if epfd < 0 {
println ("runtime: epollcreate failed with" , -epfd )
throw ("runtime: netpollinit failed" )
}
closeonexec (epfd )
}
r , w , errno := nonblockingPipe ()
if errno != 0 {
println ("runtime: pipe failed with" , -errno )
throw ("runtime: pipe failed" )
}
ev := epollevent {
events : _EPOLLIN ,
}
*(**uintptr )(unsafe .Pointer (&ev .data )) = &netpollBreakRd
errno = epollctl (epfd , _EPOLL_CTL_ADD , r , &ev )
if errno != 0 {
println ("runtime: epollctl failed with" , -errno )
throw ("runtime: epollctl failed" )
}
netpollBreakRd = uintptr (r )
netpollBreakWr = uintptr (w )
}
func netpollIsPollDescriptor(fd uintptr ) bool {
return fd == uintptr (epfd ) || fd == netpollBreakRd || fd == netpollBreakWr
}
func netpollopen(fd uintptr , pd *pollDesc ) int32 {
var ev epollevent
ev .events = _EPOLLIN | _EPOLLOUT | _EPOLLRDHUP | _EPOLLET
*(**pollDesc )(unsafe .Pointer (&ev .data )) = pd
return -epollctl (epfd , _EPOLL_CTL_ADD , int32 (fd ), &ev )
}
func netpollclose(fd uintptr ) int32 {
var ev epollevent
return -epollctl (epfd , _EPOLL_CTL_DEL , int32 (fd ), &ev )
}
func netpollarm(pd *pollDesc , mode int ) {
throw ("runtime: unused" )
}
func netpollBreak() {
if atomic .Cas (&netpollWakeSig , 0 , 1 ) {
for {
var b byte
n := write (netpollBreakWr , unsafe .Pointer (&b ), 1 )
if n == 1 {
break
}
if n == -_EINTR {
continue
}
if n == -_EAGAIN {
return
}
println ("runtime: netpollBreak write failed with" , -n )
throw ("runtime: netpollBreak write failed" )
}
}
}
func netpoll(delay int64 ) gList {
if epfd == -1 {
return gList {}
}
var waitms int32
if delay < 0 {
waitms = -1
} else if delay == 0 {
waitms = 0
} else if delay < 1e6 {
waitms = 1
} else if delay < 1e15 {
waitms = int32 (delay / 1e6 )
} else {
waitms = 1e9
}
var events [128 ]epollevent
retry :
n := epollwait (epfd , &events [0 ], int32 (len (events )), waitms )
if n < 0 {
if n != -_EINTR {
println ("runtime: epollwait on fd" , epfd , "failed with" , -n )
throw ("runtime: netpoll failed" )
}
if waitms > 0 {
return gList {}
}
goto retry
}
var toRun gList
for i := int32 (0 ); i < n ; i ++ {
ev := &events [i ]
if ev .events == 0 {
continue
}
if *(**uintptr )(unsafe .Pointer (&ev .data )) == &netpollBreakRd {
if ev .events != _EPOLLIN {
println ("runtime: netpoll: break fd ready for" , ev .events )
throw ("runtime: netpoll: break fd ready for something unexpected" )
}
if delay != 0 {
var tmp [16 ]byte
read (int32 (netpollBreakRd ), noescape (unsafe .Pointer (&tmp [0 ])), int32 (len (tmp )))
atomic .Store (&netpollWakeSig , 0 )
}
continue
}
var mode int32
if ev .events &(_EPOLLIN |_EPOLLRDHUP |_EPOLLHUP |_EPOLLERR ) != 0 {
mode += 'r'
}
if ev .events &(_EPOLLOUT |_EPOLLHUP |_EPOLLERR ) != 0 {
mode += 'w'
}
if mode != 0 {
pd := *(**pollDesc )(unsafe .Pointer (&ev .data ))
pd .setEventErr (ev .events == _EPOLLERR )
netpollready (&toRun , pd , mode )
}
}
return toRun
}
The pages are generated with Golds v0.4.5 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .