poll_linux.go

 1//go:build !tinygo
 2
 3package sysfs
 4
 5import (
 6	"syscall"
 7	"time"
 8	"unsafe"
 9
10	"github.com/tetratelabs/wazero/experimental/sys"
11)
12
13// pollFd is the struct to query for file descriptor events using poll.
14type pollFd struct {
15	// fd is the file descriptor.
16	fd int32
17	// events is a bitmap containing the requested events.
18	events int16
19	// revents is a bitmap containing the returned events.
20	revents int16
21}
22
23// newPollFd is a constructor for pollFd that abstracts the platform-specific type of file descriptors.
24func newPollFd(fd uintptr, events, revents int16) pollFd {
25	return pollFd{fd: int32(fd), events: events, revents: revents}
26}
27
28// _POLLIN subscribes a notification when any readable data is available.
29const _POLLIN = 0x0001
30
31// _poll implements poll on Linux via ppoll.
32func _poll(fds []pollFd, timeoutMillis int32) (n int, errno sys.Errno) {
33	var ts syscall.Timespec
34	if timeoutMillis >= 0 {
35		ts = syscall.NsecToTimespec(int64(time.Duration(timeoutMillis) * time.Millisecond))
36	}
37	return ppoll(fds, &ts)
38}
39
40// ppoll is a poll variant that allows to subscribe to a mask of signals.
41// However, we do not need such mask, so the corresponding argument is always nil.
42func ppoll(fds []pollFd, timespec *syscall.Timespec) (n int, err sys.Errno) {
43	var fdptr *pollFd
44	nfd := len(fds)
45	if nfd != 0 {
46		fdptr = &fds[0]
47	}
48
49	n1, _, errno := syscall.Syscall6(
50		uintptr(syscall.SYS_PPOLL),
51		uintptr(unsafe.Pointer(fdptr)),
52		uintptr(nfd),
53		uintptr(unsafe.Pointer(timespec)),
54		uintptr(unsafe.Pointer(nil)), // sigmask is currently always ignored
55		uintptr(unsafe.Pointer(nil)),
56		uintptr(unsafe.Pointer(nil)))
57
58	return int(n1), sys.UnwrapOSError(errno)
59}