From ba418132cd04865d444f4da2b5553e4d83b18138 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 9 Dec 2017 09:41:09 -0500 Subject: osdep: add poll shim for macOS This implements a poll-compatible interface, backed by select on macOS, suitable for polling on device files - which are not supported by macOS's implementation of poll. This is a (long-standing) bug in macOS, so hopefully we can eventually remove this shim. --- osdep/polldev.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ osdep/polldev.h | 7 ++++++ 2 files changed, 82 insertions(+) create mode 100644 osdep/polldev.c create mode 100644 osdep/polldev.h (limited to 'osdep') diff --git a/osdep/polldev.c b/osdep/polldev.c new file mode 100644 index 0000000000..ba2df2a2e3 --- /dev/null +++ b/osdep/polldev.c @@ -0,0 +1,75 @@ +/* + * poll shim that supports device files on macOS. + * + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#include +#include +#include +#include + +#include "osdep/polldev.h" + +int polldev(struct pollfd fds[], nfds_t nfds, int timeout) { +#ifdef __APPLE__ + int maxfd = 0; + fd_set readfds, writefds, errorfds; + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&errorfds); + for (size_t i = 0; i < nfds; ++i) { + struct pollfd *fd = &fds[i]; + if (fd->fd > maxfd) { + maxfd = fd->fd; + } + if ((fd->events & POLLIN)) { + FD_SET(fd->fd, &readfds); + } + if ((fd->events & POLLOUT)) { + FD_SET(fd->fd, &writefds); + } + if ((fd->events & POLLERR)) { + FD_SET(fd->fd, &errorfds); + } + } + struct timeval _timeout = { + .tv_sec = timeout / 1000, + .tv_usec = (timeout % 1000) * 1000 + }; + int n = select(maxfd + 1, &readfds, &writefds, &errorfds, + timeout != -1 ? &_timeout : NULL); + if (n < 0) { + return n; + } + for (size_t i = 0; i < nfds; ++i) { + struct pollfd *fd = &fds[i]; + fd->revents = 0; + if (FD_ISSET(fd->fd, &readfds)) { + fd->revents |= POLLIN; + } + if (FD_ISSET(fd->fd, &writefds)) { + fd->revents |= POLLOUT; + } + if (FD_ISSET(fd->fd, &errorfds)) { + fd->revents |= POLLERR; + } + } + return n; +#else + return poll(fds, nfds, timeout); +#endif +} diff --git a/osdep/polldev.h b/osdep/polldev.h new file mode 100644 index 0000000000..50b6db29bc --- /dev/null +++ b/osdep/polldev.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +// Behaves like poll(3) but works for device files on macOS. +// Only supports POLLIN, POLLOUT, and POLLERR. +int polldev(struct pollfd fds[], nfds_t nfds, int timeout); -- cgit v1.2.3