mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibC+Kernel: Implement ppoll
ppoll() is similar() to poll(), but it takes its timeout as timespec instead of as int, and it takes an additional sigmask parameter. Change the sys$poll parameters to match ppoll() and implement poll() in terms of ppoll().
This commit is contained in:
parent
4b19b99b36
commit
d2684a8645
Notes:
sideshowbarker
2024-07-19 05:26:15 +09:00
Author: https://github.com/nico Commit: https://github.com/SerenityOS/serenity/commit/d2684a86458 Pull-request: https://github.com/SerenityOS/serenity/pull/2612 Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/bugaevc
5 changed files with 55 additions and 19 deletions
|
@ -3055,18 +3055,33 @@ int Process::sys$select(const Syscall::SC_select_params* params)
|
|||
return marked_fd_count;
|
||||
}
|
||||
|
||||
int Process::sys$poll(pollfd* fds, int nfds, int timeout)
|
||||
int Process::sys$poll(const Syscall::SC_poll_params* params)
|
||||
{
|
||||
REQUIRE_PROMISE(stdio);
|
||||
if (!validate_read_typed(fds))
|
||||
// FIXME: Return -EINVAL if timeout is invalid.
|
||||
if (!validate_read_typed(params))
|
||||
return -EFAULT;
|
||||
|
||||
SmapDisabler disabler;
|
||||
|
||||
pollfd* fds = params->fds;
|
||||
unsigned nfds = params->nfds;
|
||||
const timespec* timeout = params->timeout;
|
||||
const sigset_t* sigmask = params->sigmask;
|
||||
|
||||
if (fds && !validate_read_typed(fds, nfds))
|
||||
return -EFAULT;
|
||||
if (timeout && !validate_read_typed(timeout))
|
||||
return -EFAULT;
|
||||
if (sigmask && !validate_read_typed(sigmask))
|
||||
return -EFAULT;
|
||||
if (!validate_read_typed(fds))
|
||||
return -EFAULT;
|
||||
|
||||
Thread::SelectBlocker::FDVector rfds;
|
||||
Thread::SelectBlocker::FDVector wfds;
|
||||
|
||||
for (int i = 0; i < nfds; ++i) {
|
||||
for (unsigned i = 0; i < nfds; ++i) {
|
||||
if (fds[i].events & POLLIN)
|
||||
rfds.append(fds[i].fd);
|
||||
if (fds[i].events & POLLOUT)
|
||||
|
@ -3075,33 +3090,29 @@ int Process::sys$poll(pollfd* fds, int nfds, int timeout)
|
|||
|
||||
timespec actual_timeout;
|
||||
bool has_timeout = false;
|
||||
if (timeout >= 0) {
|
||||
// poll is in ms, we want s/ns.
|
||||
struct timespec tstimeout;
|
||||
tstimeout.tv_sec = 0;
|
||||
while (timeout >= 1000) {
|
||||
tstimeout.tv_sec += 1;
|
||||
timeout -= 1000;
|
||||
}
|
||||
tstimeout.tv_nsec = timeout * 1000 * 1000;
|
||||
if (timeout && (timeout->tv_sec || timeout->tv_nsec)) {
|
||||
timespec ts_since_boot;
|
||||
timeval_to_timespec(Scheduler::time_since_boot(), ts_since_boot);
|
||||
timespec_add(ts_since_boot, tstimeout, actual_timeout);
|
||||
timespec_add(ts_since_boot, *timeout, actual_timeout);
|
||||
has_timeout = true;
|
||||
}
|
||||
|
||||
ScopedValueRollback scoped_sigmask(Thread::current->m_signal_mask);
|
||||
if (sigmask)
|
||||
Thread::current->m_signal_mask = *sigmask;
|
||||
|
||||
#if defined(DEBUG_IO) || defined(DEBUG_POLL_SELECT)
|
||||
dbg() << "polling on (read:" << rfds.size() << ", write:" << wfds.size() << "), timeout=" << timeout;
|
||||
#endif
|
||||
|
||||
if (has_timeout || timeout < 0) {
|
||||
if (!timeout || has_timeout) {
|
||||
if (Thread::current->block<Thread::SelectBlocker>(actual_timeout, has_timeout, rfds, wfds, Thread::SelectBlocker::FDVector()) != Thread::BlockResult::WokeNormally)
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
int fds_with_revents = 0;
|
||||
|
||||
for (int i = 0; i < nfds; ++i) {
|
||||
for (unsigned i = 0; i < nfds; ++i) {
|
||||
auto description = file_description(fds[i].fd);
|
||||
if (!description) {
|
||||
fds[i].revents = POLLNVAL;
|
||||
|
|
|
@ -217,7 +217,7 @@ public:
|
|||
int sys$minherit(void*, size_t, int inherit);
|
||||
int sys$purge(int mode);
|
||||
int sys$select(const Syscall::SC_select_params*);
|
||||
int sys$poll(pollfd*, int nfds, int timeout);
|
||||
int sys$poll(const Syscall::SC_poll_params*);
|
||||
ssize_t sys$get_dir_entries(int fd, void*, ssize_t);
|
||||
int sys$getcwd(char*, ssize_t);
|
||||
int sys$chdir(const char*, size_t);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
constexpr int syscall_vector = 0x82;
|
||||
|
||||
extern "C" {
|
||||
struct pollfd;
|
||||
struct timeval;
|
||||
struct timespec;
|
||||
struct sockaddr;
|
||||
|
@ -273,6 +274,13 @@ struct SC_select_params {
|
|||
const u32* sigmask;
|
||||
};
|
||||
|
||||
struct SC_poll_params {
|
||||
struct pollfd* fds;
|
||||
unsigned nfds;
|
||||
const struct timespec* timeout;
|
||||
const u32* sigmask;
|
||||
};
|
||||
|
||||
struct SC_clock_nanosleep_params {
|
||||
int clock_id;
|
||||
int flags;
|
||||
|
|
|
@ -27,12 +27,25 @@
|
|||
#include <Kernel/Syscall.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
int poll(struct pollfd* fds, int nfds, int timeout)
|
||||
int poll(pollfd* fds, nfds_t nfds, int timeout_ms)
|
||||
{
|
||||
int rc = syscall(SC_poll, fds, nfds, timeout);
|
||||
timespec timeout;
|
||||
timespec* timeout_ts = &timeout;
|
||||
if (timeout_ms < 0)
|
||||
timeout_ts = nullptr;
|
||||
else
|
||||
timeout = { timeout_ms / 1000, (timeout_ms % 1000) * 1'000'000 };
|
||||
return ppoll(fds, nfds, timeout_ts, nullptr);
|
||||
}
|
||||
|
||||
int ppoll(pollfd* fds, nfds_t nfds, const timespec* timeout, const sigset_t* sigmask)
|
||||
{
|
||||
Syscall::SC_poll_params params { fds, nfds, timeout, sigmask };
|
||||
int rc = syscall(SC_poll, ¶ms);
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
@ -43,6 +44,9 @@ struct pollfd {
|
|||
short revents;
|
||||
};
|
||||
|
||||
int poll(struct pollfd* fds, int nfds, int timeout);
|
||||
typedef unsigned nfds_t;
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue