Kernel/LibC: Add ppoll syscall and fix poll
poll is now using its own syscall instead of wrapping aroung pselect. This adds less overhead on top of poll and adds support for POLLHUP
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
struct pollfd
|
||||
{
|
||||
int fd; /* The following descriptor being polled. */
|
||||
@@ -28,6 +30,7 @@ typedef unsigned long nfds_t;
|
||||
#define POLLNVAL 0x200
|
||||
|
||||
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
|
||||
int ppoll(struct pollfd fds[], nfds_t nfds, const struct timespec* timeout, const sigset_t* sigmask);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ __BEGIN_DECLS
|
||||
O(SYS_CONNECT, connect) \
|
||||
O(SYS_LISTEN, listen) \
|
||||
O(SYS_PSELECT, pselect) \
|
||||
O(SYS_PPOLL, ppoll) \
|
||||
O(SYS_TRUNCATE, truncate) \
|
||||
O(SYS_SMO_CREATE, smo_create) \
|
||||
O(SYS_SMO_DELETE, smo_delete) \
|
||||
|
||||
@@ -1,56 +1,19 @@
|
||||
#include <poll.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
||||
{
|
||||
fd_set rfds, wfds, efds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
FD_ZERO(&efds);
|
||||
|
||||
for (nfds_t i = 0; i < nfds; i++)
|
||||
fds[i].revents = 0;
|
||||
|
||||
constexpr short rmask = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLHUP;
|
||||
constexpr short wmask = POLLOUT | POLLWRNORM | POLLWRBAND;
|
||||
constexpr short emask = POLLERR;
|
||||
|
||||
int max_fd = 0;
|
||||
for (nfds_t i = 0; i < nfds; i++)
|
||||
{
|
||||
if (fds[i].fd < 0)
|
||||
continue;
|
||||
|
||||
if (fds[i].events & rmask)
|
||||
FD_SET(fds[i].fd, &rfds);
|
||||
if (fds[i].events & wmask)
|
||||
FD_SET(fds[i].fd, &wfds);
|
||||
if (fds[i].events & emask)
|
||||
FD_SET(fds[i].fd, &efds);
|
||||
|
||||
if (fds[i].fd > max_fd)
|
||||
max_fd = fds[i].fd;
|
||||
}
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = timeout % 1000 * 1000;
|
||||
int nselect = select(max_fd + 1, &rfds, &wfds, &efds, &tv);
|
||||
if (nselect == -1)
|
||||
return -1;
|
||||
|
||||
for (nfds_t i = 0; i < nfds; i++)
|
||||
{
|
||||
if (fds[i].fd < 0)
|
||||
continue;
|
||||
|
||||
if (FD_ISSET(fds[i].fd, &rfds))
|
||||
fds[i].revents |= fds[i].events & rmask;
|
||||
if (FD_ISSET(fds[i].fd, &wfds))
|
||||
fds[i].revents |= fds[i].events & wmask;
|
||||
if (FD_ISSET(fds[i].fd, &efds))
|
||||
fds[i].revents |= fds[i].events & emask;
|
||||
}
|
||||
|
||||
return nselect;
|
||||
if (timeout < 0)
|
||||
return ppoll(fds, nfds, nullptr, nullptr);
|
||||
const timespec timeout_ts {
|
||||
.tv_sec = static_cast<time_t>(timeout / 1000),
|
||||
.tv_nsec = static_cast<long>(timeout % 1000),
|
||||
};
|
||||
return ppoll(fds, nfds, &timeout_ts, nullptr);
|
||||
}
|
||||
|
||||
int ppoll(struct pollfd fds[], nfds_t nfds, const struct timespec* timeout, const sigset_t* sigmask)
|
||||
{
|
||||
return syscall(SYS_PPOLL, fds, nfds, timeout, sigmask);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user