diff options
author | Nico Weber <thakis@chromium.org> | 2020-06-21 13:54:41 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-06-22 16:00:20 +0200 |
commit | d23e655c83b48d0ca6d8273a5de22644ec6db490 (patch) | |
tree | 856f5b78b7e7581b9f9e6566e7380b9c6d1b867d | |
parent | 29f509a2a09028950824742f7d23daa3d409ada3 (diff) | |
download | serenity-d23e655c83b48d0ca6d8273a5de22644ec6db490.zip |
LibC: Implement pselect
pselect() is similar() to select(), but it takes its timeout
as timespec instead of as timeval, and it takes an additional
sigmask parameter.
Change the sys$select parameters to match pselect() and implement
select() in terms of pselect().
-rw-r--r-- | Kernel/Process.cpp | 34 | ||||
-rw-r--r-- | Kernel/Scheduler.cpp | 6 | ||||
-rw-r--r-- | Kernel/Syscall.h | 3 | ||||
-rw-r--r-- | Kernel/Thread.h | 4 | ||||
-rw-r--r-- | Libraries/LibC/sys/select.cpp | 16 | ||||
-rw-r--r-- | Libraries/LibC/sys/select.h | 2 |
6 files changed, 46 insertions, 19 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index f902679548..0177fbba6b 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -27,6 +27,7 @@ #include <AK/Demangle.h> #include <AK/RefPtr.h> #include <AK/ScopeGuard.h> +#include <AK/ScopedValueRollback.h> #include <AK/StdLibExtras.h> #include <AK/StringBuilder.h> #include <AK/Time.h> @@ -2958,7 +2959,8 @@ int Process::sys$select(const Syscall::SC_select_params* params) fd_set* readfds = params->readfds; fd_set* writefds = params->writefds; fd_set* exceptfds = params->exceptfds; - timeval* timeout = params->timeout; + const timespec* timeout = params->timeout; + const sigset_t* sigmask = params->sigmask; if (writefds && !validate_write_typed(writefds)) return -EFAULT; @@ -2968,16 +2970,24 @@ int Process::sys$select(const Syscall::SC_select_params* params) return -EFAULT; if (timeout && !validate_read_typed(timeout)) return -EFAULT; + if (sigmask && !validate_read_typed(sigmask)) + return -EFAULT; if (nfds < 0) return -EINVAL; - timeval computed_timeout; + timespec computed_timeout; bool select_has_timeout = false; - if (timeout && (timeout->tv_sec || timeout->tv_usec)) { - timeval_add(Scheduler::time_since_boot(), *timeout, computed_timeout); + 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, *timeout, computed_timeout); select_has_timeout = true; } + ScopedValueRollback scoped_sigmask(Thread::current->m_signal_mask); + if (sigmask) + Thread::current->m_signal_mask = *sigmask; + Thread::SelectBlocker::FDVector rfds; Thread::SelectBlocker::FDVector wfds; Thread::SelectBlocker::FDVector efds; @@ -3061,18 +3071,20 @@ int Process::sys$poll(pollfd* fds, int nfds, int timeout) wfds.append(fds[i].fd); } - timeval actual_timeout; + timespec actual_timeout; bool has_timeout = false; if (timeout >= 0) { - // poll is in ms, we want s/us. - struct timeval tvtimeout; - tvtimeout.tv_sec = 0; + // poll is in ms, we want s/ns. + struct timespec tstimeout; + tstimeout.tv_sec = 0; while (timeout >= 1000) { - tvtimeout.tv_sec += 1; + tstimeout.tv_sec += 1; timeout -= 1000; } - tvtimeout.tv_usec = timeout * 1000; - timeval_add(Scheduler::time_since_boot(), tvtimeout, actual_timeout); + tstimeout.tv_nsec = timeout * 1000 * 1000; + timespec ts_since_boot; + timeval_to_timespec(Scheduler::time_since_boot(), ts_since_boot); + timespec_add(ts_since_boot, tstimeout, actual_timeout); has_timeout = true; } diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 76156bd283..730b2da773 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -210,8 +210,8 @@ bool Thread::SleepBlocker::should_unblock(Thread&, time_t, long) return m_wakeup_time <= g_uptime; } -Thread::SelectBlocker::SelectBlocker(const timeval& tv, bool select_has_timeout, const FDVector& read_fds, const FDVector& write_fds, const FDVector& except_fds) - : m_select_timeout(tv) +Thread::SelectBlocker::SelectBlocker(const timespec& ts, bool select_has_timeout, const FDVector& read_fds, const FDVector& write_fds, const FDVector& except_fds) + : m_select_timeout(ts) , m_select_has_timeout(select_has_timeout) , m_select_read_fds(read_fds) , m_select_write_fds(write_fds) @@ -222,7 +222,7 @@ Thread::SelectBlocker::SelectBlocker(const timeval& tv, bool select_has_timeout, bool Thread::SelectBlocker::should_unblock(Thread& thread, time_t now_sec, long now_usec) { if (m_select_has_timeout) { - if (now_sec > m_select_timeout.tv_sec || (now_sec == m_select_timeout.tv_sec && now_usec >= m_select_timeout.tv_usec)) + if (now_sec > m_select_timeout.tv_sec || (now_sec == m_select_timeout.tv_sec && now_usec * 1000 >= m_select_timeout.tv_nsec)) return true; } diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index e593aa985c..d1251d28fc 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -269,7 +269,8 @@ struct SC_select_params { fd_set* readfds; fd_set* writefds; fd_set* exceptfds; - struct timeval* timeout; + const struct timespec* timeout; + const u32* sigmask; }; struct SC_clock_nanosleep_params { diff --git a/Kernel/Thread.h b/Kernel/Thread.h index d1959ddc63..983e06fed0 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -219,12 +219,12 @@ public: class SelectBlocker final : public Blocker { public: typedef Vector<int, FD_SETSIZE> FDVector; - SelectBlocker(const timeval& tv, bool select_has_timeout, const FDVector& read_fds, const FDVector& write_fds, const FDVector& except_fds); + SelectBlocker(const timespec& ts, bool select_has_timeout, const FDVector& read_fds, const FDVector& write_fds, const FDVector& except_fds); virtual bool should_unblock(Thread&, time_t, long) override; virtual const char* state_string() const override { return "Selecting"; } private: - timeval m_select_timeout; + timespec m_select_timeout; bool m_select_has_timeout { false }; const FDVector& m_select_read_fds; const FDVector& m_select_write_fds; diff --git a/Libraries/LibC/sys/select.cpp b/Libraries/LibC/sys/select.cpp index a9533d21ac..e4ff159ef4 100644 --- a/Libraries/LibC/sys/select.cpp +++ b/Libraries/LibC/sys/select.cpp @@ -28,12 +28,24 @@ #include <errno.h> #include <stdio.h> #include <sys/select.h> +#include <sys/time.h> extern "C" { -int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout) +int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timeval* timeout_tv) { - Syscall::SC_select_params params { nfds, readfds, writefds, exceptfds, timeout }; + timespec* timeout_ts = nullptr; + timespec timeout; + if (timeout_tv) { + timeout_ts = &timeout; + TIMEVAL_TO_TIMESPEC(timeout_tv, timeout_ts); + } + return pselect(nfds, readfds, writefds, exceptfds, timeout_ts, nullptr); +} + +int pselect(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const timespec* timeout, const sigset_t* sigmask) +{ + Syscall::SC_select_params params { nfds, readfds, writefds, exceptfds, timeout, sigmask }; int rc = syscall(SC_select, ¶ms); __RETURN_WITH_ERRNO(rc, rc, -1); } diff --git a/Libraries/LibC/sys/select.h b/Libraries/LibC/sys/select.h index c32fdabb9b..9d451eb8ed 100644 --- a/Libraries/LibC/sys/select.h +++ b/Libraries/LibC/sys/select.h @@ -27,6 +27,7 @@ #pragma once #include <fd_set.h> +#include <signal.h> #include <string.h> #include <sys/cdefs.h> #include <sys/types.h> @@ -34,5 +35,6 @@ __BEGIN_DECLS int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout); +int pselect(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timespec* timeout, const sigset_t* sigmask); __END_DECLS |