package poll
import (
)
type FD struct {
fdmu fdMutex
Sysfd int
pd pollDesc
iovecs *[]syscall.Iovec
csema uint32
isBlocking uint32
IsStream bool
ZeroReadIsEOF bool
isFile bool
}
func ( *FD) ( string, bool) error {
if == "file" {
.isFile = true
}
if ! {
.isBlocking = 1
return nil
}
:= .pd.init()
if != nil {
.isBlocking = 1
}
return
}
func ( *FD) () error {
.pd.close()
:= CloseFunc(.Sysfd)
.Sysfd = -1
runtime_Semrelease(&.csema)
return
}
func ( *FD) () error {
if !.fdmu.increfAndClose() {
return errClosing(.isFile)
}
.pd.evict()
:= .decref()
if .isBlocking == 0 {
runtime_Semacquire(&.csema)
}
return
}
func ( *FD) () error {
if := .incref(); != nil {
return
}
defer .decref()
atomic.StoreUint32(&.isBlocking, 1)
return syscall.SetNonblock(.Sysfd, false)
}
const maxRW = 1 << 30
func ( *FD) ( []byte) (int, error) {
if := .readLock(); != nil {
return 0,
}
defer .readUnlock()
if len() == 0 {
return 0, nil
}
if := .pd.prepareRead(.isFile); != nil {
return 0,
}
if .IsStream && len() > maxRW {
= [:maxRW]
}
for {
, := ignoringEINTRIO(syscall.Read, .Sysfd, )
if != nil {
= 0
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitRead(.isFile); == nil {
continue
}
}
}
= .eofError(, )
return ,
}
}
func ( *FD) ( []byte, int64) (int, error) {
if := .incref(); != nil {
return 0,
}
if .IsStream && len() > maxRW {
= [:maxRW]
}
var (
int
error
)
for {
, = syscall.Pread(.Sysfd, , )
if != syscall.EINTR {
break
}
}
if != nil {
= 0
}
.decref()
= .eofError(, )
return ,
}
func ( *FD) ( []byte) (int, syscall.Sockaddr, error) {
if := .readLock(); != nil {
return 0, nil,
}
defer .readUnlock()
if := .pd.prepareRead(.isFile); != nil {
return 0, nil,
}
for {
, , := syscall.Recvfrom(.Sysfd, , 0)
if != nil {
if == syscall.EINTR {
continue
}
= 0
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitRead(.isFile); == nil {
continue
}
}
}
= .eofError(, )
return , ,
}
}
func ( *FD) ( []byte, *syscall.SockaddrInet4) (int, error) {
if := .readLock(); != nil {
return 0,
}
defer .readUnlock()
if := .pd.prepareRead(.isFile); != nil {
return 0,
}
for {
, := unix.RecvfromInet4(.Sysfd, , 0, )
if != nil {
if == syscall.EINTR {
continue
}
= 0
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitRead(.isFile); == nil {
continue
}
}
}
= .eofError(, )
return ,
}
}
func ( *FD) ( []byte, *syscall.SockaddrInet6) (int, error) {
if := .readLock(); != nil {
return 0,
}
defer .readUnlock()
if := .pd.prepareRead(.isFile); != nil {
return 0,
}
for {
, := unix.RecvfromInet6(.Sysfd, , 0, )
if != nil {
if == syscall.EINTR {
continue
}
= 0
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitRead(.isFile); == nil {
continue
}
}
}
= .eofError(, )
return ,
}
}
func ( *FD) ( []byte, []byte, int) (int, int, int, syscall.Sockaddr, error) {
if := .readLock(); != nil {
return 0, 0, 0, nil,
}
defer .readUnlock()
if := .pd.prepareRead(.isFile); != nil {
return 0, 0, 0, nil,
}
for {
, , , , := syscall.Recvmsg(.Sysfd, , , )
if != nil {
if == syscall.EINTR {
continue
}
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitRead(.isFile); == nil {
continue
}
}
}
= .eofError(, )
return , , , ,
}
}
func ( *FD) ( []byte, []byte, int, *syscall.SockaddrInet4) (int, int, int, error) {
if := .readLock(); != nil {
return 0, 0, 0,
}
defer .readUnlock()
if := .pd.prepareRead(.isFile); != nil {
return 0, 0, 0,
}
for {
, , , := unix.RecvmsgInet4(.Sysfd, , , , )
if != nil {
if == syscall.EINTR {
continue
}
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitRead(.isFile); == nil {
continue
}
}
}
= .eofError(, )
return , , ,
}
}
func ( *FD) ( []byte, []byte, int, *syscall.SockaddrInet6) (int, int, int, error) {
if := .readLock(); != nil {
return 0, 0, 0,
}
defer .readUnlock()
if := .pd.prepareRead(.isFile); != nil {
return 0, 0, 0,
}
for {
, , , := unix.RecvmsgInet6(.Sysfd, , , , )
if != nil {
if == syscall.EINTR {
continue
}
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitRead(.isFile); == nil {
continue
}
}
}
= .eofError(, )
return , , ,
}
}
func ( *FD) ( []byte) (int, error) {
if := .writeLock(); != nil {
return 0,
}
defer .writeUnlock()
if := .pd.prepareWrite(.isFile); != nil {
return 0,
}
var int
for {
:= len()
if .IsStream && - > maxRW {
= + maxRW
}
, := ignoringEINTRIO(syscall.Write, .Sysfd, [:])
if > 0 {
+=
}
if == len() {
return ,
}
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitWrite(.isFile); == nil {
continue
}
}
if != nil {
return ,
}
if == 0 {
return , io.ErrUnexpectedEOF
}
}
}
func ( *FD) ( []byte, int64) (int, error) {
if := .incref(); != nil {
return 0,
}
defer .decref()
var int
for {
:= len()
if .IsStream && - > maxRW {
= + maxRW
}
, := syscall.Pwrite(.Sysfd, [:], +int64())
if == syscall.EINTR {
continue
}
if > 0 {
+=
}
if == len() {
return ,
}
if != nil {
return ,
}
if == 0 {
return , io.ErrUnexpectedEOF
}
}
}
func ( *FD) ( []byte, *syscall.SockaddrInet4) (int, error) {
if := .writeLock(); != nil {
return 0,
}
defer .writeUnlock()
if := .pd.prepareWrite(.isFile); != nil {
return 0,
}
for {
:= unix.SendtoInet4(.Sysfd, , 0, )
if == syscall.EINTR {
continue
}
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitWrite(.isFile); == nil {
continue
}
}
if != nil {
return 0,
}
return len(), nil
}
}
func ( *FD) ( []byte, *syscall.SockaddrInet6) (int, error) {
if := .writeLock(); != nil {
return 0,
}
defer .writeUnlock()
if := .pd.prepareWrite(.isFile); != nil {
return 0,
}
for {
:= unix.SendtoInet6(.Sysfd, , 0, )
if == syscall.EINTR {
continue
}
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitWrite(.isFile); == nil {
continue
}
}
if != nil {
return 0,
}
return len(), nil
}
}
func ( *FD) ( []byte, syscall.Sockaddr) (int, error) {
if := .writeLock(); != nil {
return 0,
}
defer .writeUnlock()
if := .pd.prepareWrite(.isFile); != nil {
return 0,
}
for {
:= syscall.Sendto(.Sysfd, , 0, )
if == syscall.EINTR {
continue
}
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitWrite(.isFile); == nil {
continue
}
}
if != nil {
return 0,
}
return len(), nil
}
}
func ( *FD) ( []byte, []byte, syscall.Sockaddr) (int, int, error) {
if := .writeLock(); != nil {
return 0, 0,
}
defer .writeUnlock()
if := .pd.prepareWrite(.isFile); != nil {
return 0, 0,
}
for {
, := syscall.SendmsgN(.Sysfd, , , , 0)
if == syscall.EINTR {
continue
}
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitWrite(.isFile); == nil {
continue
}
}
if != nil {
return , 0,
}
return , len(),
}
}
func ( *FD) ( []byte, []byte, *syscall.SockaddrInet4) (int, int, error) {
if := .writeLock(); != nil {
return 0, 0,
}
defer .writeUnlock()
if := .pd.prepareWrite(.isFile); != nil {
return 0, 0,
}
for {
, := unix.SendmsgNInet4(.Sysfd, , , , 0)
if == syscall.EINTR {
continue
}
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitWrite(.isFile); == nil {
continue
}
}
if != nil {
return , 0,
}
return , len(),
}
}
func ( *FD) ( []byte, []byte, *syscall.SockaddrInet6) (int, int, error) {
if := .writeLock(); != nil {
return 0, 0,
}
defer .writeUnlock()
if := .pd.prepareWrite(.isFile); != nil {
return 0, 0,
}
for {
, := unix.SendmsgNInet6(.Sysfd, , , , 0)
if == syscall.EINTR {
continue
}
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitWrite(.isFile); == nil {
continue
}
}
if != nil {
return , 0,
}
return , len(),
}
}
func ( *FD) () (int, syscall.Sockaddr, string, error) {
if := .readLock(); != nil {
return -1, nil, "",
}
defer .readUnlock()
if := .pd.prepareRead(.isFile); != nil {
return -1, nil, "",
}
for {
, , , := accept(.Sysfd)
if == nil {
return , , "",
}
switch {
case syscall.EINTR:
continue
case syscall.EAGAIN:
if .pd.pollable() {
if = .pd.waitRead(.isFile); == nil {
continue
}
}
case syscall.ECONNABORTED:
continue
}
return -1, nil, ,
}
}
func ( *FD) ( int64, int) (int64, error) {
if := .incref(); != nil {
return 0,
}
defer .decref()
return syscall.Seek(.Sysfd, , )
}
func ( *FD) ( []byte) (int, error) {
if := .incref(); != nil {
return 0,
}
defer .decref()
for {
, := ignoringEINTRIO(syscall.ReadDirent, .Sysfd, )
if != nil {
= 0
if == syscall.EAGAIN && .pd.pollable() {
if = .pd.waitRead(.isFile); == nil {
continue
}
}
}
return ,
}
}
func ( *FD) ( uint32) error {
if := .incref(); != nil {
return
}
defer .decref()
return ignoringEINTR(func() error {
return syscall.Fchmod(.Sysfd, )
})
}
func ( *FD) () error {
if := .incref(); != nil {
return
}
defer .decref()
return syscall.Fchdir(.Sysfd)
}
func ( *FD) ( *syscall.Stat_t) error {
if := .incref(); != nil {
return
}
defer .decref()
return ignoringEINTR(func() error {
return syscall.Fstat(.Sysfd, )
})
}
var tryDupCloexec = int32(1)
func ( int) (int, string, error) {
if syscall.F_DUPFD_CLOEXEC != 0 && atomic.LoadInt32(&tryDupCloexec) == 1 {
, := fcntl(, syscall.F_DUPFD_CLOEXEC, 0)
if == nil {
return , "", nil
}
switch .(syscall.Errno) {
case syscall.EINVAL, syscall.ENOSYS:
atomic.StoreInt32(&tryDupCloexec, 0)
default:
return -1, "fcntl",
}
}
return dupCloseOnExecOld()
}
func ( int) (int, string, error) {
syscall.ForkLock.RLock()
defer syscall.ForkLock.RUnlock()
, := syscall.Dup()
if != nil {
return -1, "dup",
}
syscall.CloseOnExec()
return , "", nil
}
func ( *FD) () (int, string, error) {
if := .incref(); != nil {
return -1, "",
}
defer .decref()
return DupCloseOnExec(.Sysfd)
}
func ( *FD) () error {
return .pd.waitWrite(.isFile)
}
func ( *FD) ( []byte) (int, error) {
if := .writeLock(); != nil {
return 0,
}
defer .writeUnlock()
return ignoringEINTRIO(syscall.Write, .Sysfd, )
}
func ( *FD) ( func(uintptr) bool) error {
if := .readLock(); != nil {
return
}
defer .readUnlock()
if := .pd.prepareRead(.isFile); != nil {
return
}
for {
if (uintptr(.Sysfd)) {
return nil
}
if := .pd.waitRead(.isFile); != nil {
return
}
}
}
func ( *FD) ( func(uintptr) bool) error {
if := .writeLock(); != nil {
return
}
defer .writeUnlock()
if := .pd.prepareWrite(.isFile); != nil {
return
}
for {
if (uintptr(.Sysfd)) {
return nil
}
if := .pd.waitWrite(.isFile); != nil {
return
}
}
}
func ( func( int, []byte) (int, error), int, []byte) (int, error) {
for {
, := (, )
if != syscall.EINTR {
return ,
}
}
}