add fallback socket implementation for amd64 cpu (#1)
This commit updates the `epoll_wait` implementation and adds a fallback implementation incase of x86_64 android devices.
This commit is contained in:
parent
2158931305
commit
cd18c9b32c
|
@ -1,4 +1,6 @@
|
|||
//go:build linux && !(android && amd64)
|
||||
// +build linux
|
||||
// +build !android !amd64
|
||||
|
||||
package tcp
|
||||
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
//go:build android && amd64
|
||||
// +build android,amd64
|
||||
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const maxEpollEvents = 32
|
||||
|
||||
// createSocket creates a socket with necessary options set.
|
||||
func createSocketZeroLinger(zeroLinger bool) (fd int, err error) {
|
||||
// Create socket
|
||||
fd, err = _createNonBlockingSocket()
|
||||
if err == nil && zeroLinger {
|
||||
err = _setZeroLinger(fd)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// createNonBlockingSocket creates a non-blocking socket with necessary options all set.
|
||||
func _createNonBlockingSocket() (int, error) {
|
||||
// Create socket
|
||||
fd, err := _createSocket()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// Set necessary options
|
||||
err = _setSockOpts(fd)
|
||||
if err != nil {
|
||||
unix.Close(fd)
|
||||
}
|
||||
return fd, err
|
||||
}
|
||||
|
||||
// createSocket creates a socket with CloseOnExec set
|
||||
func _createSocket() (int, error) {
|
||||
fd, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0)
|
||||
if err != nil {
|
||||
return 0, os.NewSyscallError("socket", err)
|
||||
}
|
||||
|
||||
unix.CloseOnExec(fd)
|
||||
return fd, err
|
||||
}
|
||||
|
||||
// setSockOpts sets SOCK_NONBLOCK and TCP_QUICKACK for given fd
|
||||
func _setSockOpts(fd int) error {
|
||||
err := unix.SetNonblock(fd, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_QUICKACK, 0)
|
||||
}
|
||||
|
||||
var zeroLinger = unix.Linger{Onoff: 1, Linger: 0}
|
||||
|
||||
// setLinger sets SO_Linger with 0 timeout to given fd
|
||||
func _setZeroLinger(fd int) error {
|
||||
return unix.SetsockoptLinger(fd, unix.SOL_SOCKET, unix.SO_LINGER, &zeroLinger)
|
||||
}
|
||||
|
||||
func createPoller() (fd int, err error) {
|
||||
fd, err = unix.EpollCreate1(unix.EPOLL_CLOEXEC)
|
||||
if err != nil {
|
||||
err = os.NewSyscallError("epoll_create1", err)
|
||||
}
|
||||
return fd, err
|
||||
}
|
||||
|
||||
// registerEvents registers given fd with read and write events.
|
||||
func registerEvents(pollerFd int, fd int) error {
|
||||
var event unix.EpollEvent
|
||||
event.Events = unix.EPOLLOUT | unix.EPOLLIN | unix.EPOLLET
|
||||
event.Fd = int32(fd)
|
||||
if err := unix.EpollCtl(pollerFd, unix.EPOLL_CTL_ADD, fd, &event); err != nil {
|
||||
return os.NewSyscallError(fmt.Sprintf("epoll_ctl(%d, ADD, %d, ...)", pollerFd, fd), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pollEvents(pollerFd int, timeout time.Duration) ([]event, error) {
|
||||
eventCh := make(chan event)
|
||||
errorCh := make(chan error)
|
||||
doneCh := make(chan bool)
|
||||
|
||||
go func(fd int) {
|
||||
for {
|
||||
select {
|
||||
case <-doneCh:
|
||||
return
|
||||
default:
|
||||
n, _, err := unix.Recvfrom(fd, nil, unix.MSG_DONTWAIT|unix.MSG_PEEK)
|
||||
if err != nil && err != unix.EAGAIN && err != unix.EWOULDBLOCK {
|
||||
errorCh <- os.NewSyscallError("recvfrom", err)
|
||||
return
|
||||
}
|
||||
if n > 0 {
|
||||
eventCh <- event{Fd: fd, Err: nil}
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}(pollerFd)
|
||||
|
||||
var events []event
|
||||
|
||||
timer := time.NewTimer(timeout)
|
||||
defer timer.Stop()
|
||||
|
||||
Loop:
|
||||
for {
|
||||
select {
|
||||
case evt := <-eventCh:
|
||||
events = append(events, evt)
|
||||
case err := <-errorCh:
|
||||
return nil, err
|
||||
case <-timer.C:
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
|
||||
// Signal the goroutine to stop.
|
||||
close(doneCh)
|
||||
|
||||
return events, nil
|
||||
}
|
Loading…
Reference in New Issue