Copyright 2017 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris

package poll

import (
	
	
	
)
FD is a file descriptor. The net and os packages use this type as a field of a larger type representing a network connection or OS file.
Lock sysfd and serialize access to Read and Write methods.
System file descriptor. Immutable until Close.
I/O poller.
Writev cache.
Semaphore signaled when file is closed.
Non-zero if this file has been set to blocking mode.
Whether this is a streaming descriptor, as opposed to a packet-based descriptor like a UDP socket. Immutable.
Whether a zero byte read indicates EOF. This is false for a message based socket connection.
Whether this is a file rather than a network socket.
Init initializes the FD. The Sysfd field should already be set. This can be called multiple times on a single FD. The net argument is a network name from the net package (e.g., "tcp"), or "file". Set pollable to true if fd should be managed by runtime netpoll.
We don't actually care about the various network types.
	if  == "file" {
		.isFile = true
	}
	if ! {
		.isBlocking = 1
		return nil
	}
	 := .pd.init()
If we could not initialize the runtime poller, assume we are using blocking mode.
		.isBlocking = 1
	}
	return 
}
Destroy closes the file descriptor. This is called when there are no remaining references.
Poller may want to unregister fd in readiness notification mechanism, so this must be executed before CloseFunc.
	.pd.close()
We don't use ignoringEINTR here because POSIX does not define whether the descriptor is closed if close returns EINTR. If the descriptor is indeed closed, using a loop would race with some other goroutine opening a new descriptor. (The Linux kernel guarantees that it is closed on an EINTR error.)
	 := CloseFunc(.Sysfd)

	.Sysfd = -1
	runtime_Semrelease(&.csema)
	return 
}
Close closes the FD. The underlying file descriptor is closed by the destroy method when there are no remaining references.
func ( *FD) () error {
	if !.fdmu.increfAndClose() {
		return errClosing(.isFile)
	}
Unblock any I/O. Once it all unblocks and returns, so that it cannot be referring to fd.sysfd anymore, the final decref will close fd.sysfd. This should happen fairly quickly, since all the I/O is non-blocking, and any attempts to block in the pollDesc will return errClosing(fd.isFile).
	.pd.evict()
The call to decref will call destroy if there are no other references.
	 := .decref()
Wait until the descriptor is closed. If this was the only reference, it is already closed. Only wait if the file has not been set to blocking mode, as otherwise any current I/O may be blocking, and that would block the Close. No need for an atomic read of isBlocking, increfAndClose means we have exclusive access to fd.
	if .isBlocking == 0 {
		runtime_Semacquire(&.csema)
	}

	return 
}
SetBlocking puts the file into blocking mode.
func ( *FD) () error {
	if  := .incref();  != nil {
		return 
	}
Atomic store so that concurrent calls to SetBlocking do not cause a race condition. isBlocking only ever goes from 0 to 1 so there is no real race here.
Darwin and FreeBSD can't read or write 2GB+ files at a time, even on 64-bit systems. The same is true of socket implementations on many systems. See golang.org/issue/7812 and golang.org/issue/16266. Use 1GB instead of, say, 2GB-1, to keep subsequent reads aligned.
const maxRW = 1 << 30
Read implements io.Reader.
func ( *FD) ( []byte) (int, error) {
	if  := .readLock();  != nil {
		return 0, 
	}
	defer .readUnlock()
If the caller wanted a zero byte read, return immediately without trying (but after acquiring the readLock). Otherwise syscall.Read returns 0, nil which looks like io.EOF. TODO(bradfitz): make it wait for readability? (Issue 15735)
		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 , 
	}
}
Pread wraps the pread system call.
Call incref, not readLock, because since pread specifies the offset it is independent from other reads. Similarly, using the poller doesn't make sense for pread.
	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 , 
}
ReadFrom wraps the recvfrom network call.
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 , , 
	}
}
ReadMsg wraps the recvmsg network call.
func ( *FD) ( []byte,  []byte) (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, , , 0)
		if  != nil {
			if  == syscall.EINTR {
				continue
TODO(dfc) should n and oobn be set to 0
			if  == syscall.EAGAIN && .pd.pollable() {
				if  = .pd.waitRead(.isFile);  == nil {
					continue
				}
			}
		}
		 = .eofError(, )
		return , , , , 
	}
}
Write implements io.Writer.
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
		}
	}
}
Pwrite wraps the pwrite system call.
Call incref, not writeLock, because since pwrite specifies the offset it is independent from other writes. Similarly, using the poller doesn't make sense for pwrite.
	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
		}
	}
}
WriteTo wraps the sendto network call.
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
	}
}
WriteMsg wraps the sendmsg network call.
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(), 
	}
}
Accept wraps the accept network call.
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
				}
			}
This means that a socket on the listen queue was closed before we Accept()ed it; it's a silly error, so try again.
			continue
		}
		return -1, nil, , 
	}
}
Seek wraps syscall.Seek.
func ( *FD) ( int64,  int) (int64, error) {
	if  := .incref();  != nil {
		return 0, 
	}
	defer .decref()
	return syscall.Seek(.Sysfd, , )
}
ReadDirent wraps syscall.ReadDirent. We treat this like an ordinary system call rather than a call that tries to fill the buffer.
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
				}
			}
Do not call eofError; caller does not expect to see io.EOF.
		return , 
	}
}
Fchmod wraps syscall.Fchmod.
func ( *FD) ( uint32) error {
	if  := .incref();  != nil {
		return 
	}
	defer .decref()
	return ignoringEINTR(func() error {
		return syscall.Fchmod(.Sysfd, )
	})
}
Fchdir wraps syscall.Fchdir.
func ( *FD) () error {
	if  := .incref();  != nil {
		return 
	}
	defer .decref()
	return syscall.Fchdir(.Sysfd)
}
Fstat wraps syscall.Fstat
func ( *FD) ( *syscall.Stat_t) error {
	if  := .incref();  != nil {
		return 
	}
	defer .decref()
	return ignoringEINTR(func() error {
		return syscall.Fstat(.Sysfd, )
	})
}
tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used. If the kernel doesn't support it, this is set to 0.
DupCloseOnExec dups fd and marks it close-on-exec.
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) {
Old kernel, or js/wasm (which returns ENOSYS). Fall back to the portable way from now on.
			atomic.StoreInt32(&tryDupCloexec, 0)
		default:
			return -1, "fcntl", 
		}
	}
	return dupCloseOnExecOld()
}
dupCloseOnExecOld is the traditional way to dup an fd and set its O_CLOEXEC bit, using two system calls.
func ( int) (int, string, error) {
	syscall.ForkLock.RLock()
	defer syscall.ForkLock.RUnlock()
	,  := syscall.Dup()
	if  != nil {
		return -1, "dup", 
	}
	syscall.CloseOnExec()
	return , "", nil
}
Dup duplicates the file descriptor.
func ( *FD) () (int, string, error) {
	if  := .incref();  != nil {
		return -1, "", 
	}
	defer .decref()
	return DupCloseOnExec(.Sysfd)
}
On Unix variants only, expose the IO event for the net code.
WaitWrite waits until data can be read from fd.
func ( *FD) () error {
	return .pd.waitWrite(.isFile)
}
WriteOnce is for testing only. It makes a single write call.
func ( *FD) ( []byte) (int, error) {
	if  := .writeLock();  != nil {
		return 0, 
	}
	defer .writeUnlock()
	return ignoringEINTRIO(syscall.Write, .Sysfd, )
}
RawRead invokes the user-defined function f for a read operation.
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 
		}
	}
}
RawWrite invokes the user-defined function f for a write operation.
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 
		}
	}
}
ignoringEINTRIO is like ignoringEINTR, but just for IO calls.
func ( func( int,  []byte) (int, error),  int,  []byte) (int, error) {
	for {
		,  := (, )
		if  != syscall.EINTR {
			return , 
		}
	}