diff options
Diffstat (limited to 'src/corelib/kernel/qcore_unix_p.h')
-rw-r--r-- | src/corelib/kernel/qcore_unix_p.h | 201 |
1 files changed, 101 insertions, 100 deletions
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index abe9bb3738..fd834cb2d9 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QCORE_UNIX_P_H #define QCORE_UNIX_P_H @@ -54,8 +18,8 @@ #include "qplatformdefs.h" #include <QtCore/private/qglobal_p.h> -#include "qatomic.h" #include "qbytearray.h" +#include "qdeadlinetimer.h" #ifndef Q_OS_UNIX # error "qcore_unix_p.h included on a non-Unix system" @@ -75,14 +39,11 @@ # include <selectLib.h> #endif +#include <chrono> #include <sys/wait.h> #include <errno.h> #include <fcntl.h> -#if !defined(QT_POSIX_IPC) && !defined(QT_NO_SHAREDMEMORY) && !defined(Q_OS_ANDROID) -# include <sys/ipc.h> -#endif - #if defined(Q_OS_VXWORKS) # include <ioLib.h> #endif @@ -95,7 +56,7 @@ struct sockaddr; -#define EINTR_LOOP(var, cmd) \ +#define QT_EINTR_LOOP(var, cmd) \ do { \ var = cmd; \ } while (var == -1 && errno == EINTR) @@ -104,53 +65,78 @@ QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(pollfd, Q_PRIMITIVE_TYPE); +static constexpr auto OneSecAsNsecs = std::chrono::nanoseconds(std::chrono::seconds{ 1 }).count(); + +inline timespec durationToTimespec(std::chrono::nanoseconds timeout) noexcept +{ + using namespace std::chrono; + const seconds secs = duration_cast<seconds>(timeout); + const nanoseconds frac = timeout - secs; + struct timespec ts; + ts.tv_sec = secs.count(); + ts.tv_nsec = frac.count(); + return ts; +} + +template <typename Duration> +inline Duration timespecToChrono(timespec ts) noexcept +{ + using namespace std::chrono; + return duration_cast<Duration>(seconds{ts.tv_sec} + nanoseconds{ts.tv_nsec}); +} + +inline std::chrono::milliseconds timespecToChronoMs(timespec ts) noexcept +{ + return timespecToChrono<std::chrono::milliseconds>(ts); +} + // Internal operator functions for timespecs -inline timespec &normalizedTimespec(timespec &t) +constexpr inline timespec &normalizedTimespec(timespec &t) { - while (t.tv_nsec >= 1000000000) { + while (t.tv_nsec >= OneSecAsNsecs) { ++t.tv_sec; - t.tv_nsec -= 1000000000; + t.tv_nsec -= OneSecAsNsecs; } while (t.tv_nsec < 0) { --t.tv_sec; - t.tv_nsec += 1000000000; + t.tv_nsec += OneSecAsNsecs; } return t; } -inline bool operator<(const timespec &t1, const timespec &t2) +constexpr inline bool operator<(const timespec &t1, const timespec &t2) { return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec); } -inline bool operator==(const timespec &t1, const timespec &t2) +constexpr inline bool operator==(const timespec &t1, const timespec &t2) { return t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec; } -inline bool operator!=(const timespec &t1, const timespec &t2) +constexpr inline bool operator!=(const timespec &t1, const timespec &t2) { return !(t1 == t2); } -inline timespec &operator+=(timespec &t1, const timespec &t2) +constexpr inline timespec &operator+=(timespec &t1, const timespec &t2) { t1.tv_sec += t2.tv_sec; t1.tv_nsec += t2.tv_nsec; return normalizedTimespec(t1); } -inline timespec operator+(const timespec &t1, const timespec &t2) +constexpr inline timespec operator+(const timespec &t1, const timespec &t2) { - timespec tmp; + timespec tmp = {}; tmp.tv_sec = t1.tv_sec + t2.tv_sec; tmp.tv_nsec = t1.tv_nsec + t2.tv_nsec; return normalizedTimespec(tmp); } -inline timespec operator-(const timespec &t1, const timespec &t2) +constexpr inline timespec operator-(const timespec &t1, const timespec &t2) { - timespec tmp; + timespec tmp = {}; tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1); - tmp.tv_nsec = t1.tv_nsec - (t2.tv_nsec + 1000000000); + tmp.tv_nsec = t1.tv_nsec - (t2.tv_nsec + OneSecAsNsecs); return normalizedTimespec(tmp); } -inline timespec operator*(const timespec &t1, int mul) +constexpr inline timespec operator*(const timespec &t1, int mul) { - timespec tmp; + timespec tmp = {}; tmp.tv_sec = t1.tv_sec * mul; tmp.tv_nsec = t1.tv_nsec * mul; return normalizedTimespec(tmp); } -inline timeval timespecToTimeval(const timespec &ts) +inline timeval timespecToTimeval(timespec ts) { timeval tv; tv.tv_sec = ts.tv_sec; @@ -158,23 +144,44 @@ inline timeval timespecToTimeval(const timespec &ts) return tv; } +inline timespec &operator+=(timespec &t1, std::chrono::milliseconds msecs) +{ + t1 += durationToTimespec(msecs); + return t1; +} -inline void qt_ignore_sigpipe() +inline timespec &operator+=(timespec &t1, int ms) { - // Set to ignore SIGPIPE once only. - static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0); - if (!atom.loadRelaxed()) { - // More than one thread could turn off SIGPIPE at the same time - // But that's acceptable because they all would be doing the same - // action - struct sigaction noaction; - memset(&noaction, 0, sizeof(noaction)); - noaction.sa_handler = SIG_IGN; - ::sigaction(SIGPIPE, &noaction, nullptr); - atom.storeRelaxed(1); + t1 += std::chrono::milliseconds{ms}; + return t1; +} + +inline timespec operator+(const timespec &t1, std::chrono::milliseconds msecs) +{ + timespec tmp = t1; + tmp += msecs; + return tmp; +} + +inline timespec operator+(const timespec &t1, int ms) +{ + return t1 + std::chrono::milliseconds{ms}; +} + +inline timespec qAbsTimespec(timespec ts) +{ + if (ts.tv_sec < 0) { + ts.tv_sec = -ts.tv_sec - 1; + ts.tv_nsec -= OneSecAsNsecs; + } + if (ts.tv_sec == 0 && ts.tv_nsec < 0) { + ts.tv_nsec = -ts.tv_nsec; } + return normalizedTimespec(ts); } +Q_CORE_EXPORT void qt_ignore_sigpipe() noexcept; + #if defined(Q_PROCESSOR_X86_32) && defined(__GLIBC__) # if !__GLIBC_PREREQ(2, 22) Q_CORE_EXPORT int qt_open64(const char *pathname, int flags, mode_t); @@ -183,6 +190,16 @@ Q_CORE_EXPORT int qt_open64(const char *pathname, int flags, mode_t); # endif #endif +#ifdef AT_FDCWD +static inline int qt_safe_openat(int dfd, const char *pathname, int flags, mode_t mode = 0777) +{ + // everyone already has O_CLOEXEC + int fd; + QT_EINTR_LOOP(fd, openat(dfd, pathname, flags | O_CLOEXEC, mode)); + return fd; +} +#endif + // don't call QT_OPEN or ::open // call qt_safe_open static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777) @@ -191,7 +208,7 @@ static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 07 flags |= O_CLOEXEC; #endif int fd; - EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode)); + QT_EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode)); #ifndef O_CLOEXEC if (fd != -1) @@ -263,10 +280,10 @@ static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC) int ret; #ifdef QT_THREADSAFE_CLOEXEC // use dup3 - EINTR_LOOP(ret, ::dup3(oldfd, newfd, flags ? O_CLOEXEC : 0)); + QT_EINTR_LOOP(ret, ::dup3(oldfd, newfd, flags ? O_CLOEXEC : 0)); return ret; #else - EINTR_LOOP(ret, ::dup2(oldfd, newfd)); + QT_EINTR_LOOP(ret, ::dup2(oldfd, newfd)); if (ret == -1) return -1; @@ -279,7 +296,7 @@ static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC) static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen) { qint64 ret = 0; - EINTR_LOOP(ret, QT_READ(fd, data, maxlen)); + QT_EINTR_LOOP(ret, QT_READ(fd, data, maxlen)); return ret; } #undef QT_READ @@ -288,7 +305,7 @@ static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen) static inline qint64 qt_safe_write(int fd, const void *data, qint64 len) { qint64 ret = 0; - EINTR_LOOP(ret, QT_WRITE(fd, data, len)); + QT_EINTR_LOOP(ret, QT_WRITE(fd, data, len)); return ret; } #undef QT_WRITE @@ -303,7 +320,7 @@ static inline qint64 qt_safe_write_nosignal(int fd, const void *data, qint64 len static inline int qt_safe_close(int fd) { int ret; - EINTR_LOOP(ret, QT_CLOSE(fd)); + QT_EINTR_LOOP(ret, QT_CLOSE(fd)); return ret; } #undef QT_CLOSE @@ -315,28 +332,28 @@ static inline int qt_safe_execve(const char *filename, char *const argv[], char *const envp[]) { int ret; - EINTR_LOOP(ret, ::execve(filename, argv, envp)); + QT_EINTR_LOOP(ret, ::execve(filename, argv, envp)); return ret; } static inline int qt_safe_execv(const char *path, char *const argv[]) { int ret; - EINTR_LOOP(ret, ::execv(path, argv)); + QT_EINTR_LOOP(ret, ::execv(path, argv)); return ret; } static inline int qt_safe_execvp(const char *file, char *const argv[]) { int ret; - EINTR_LOOP(ret, ::execvp(file, argv)); + QT_EINTR_LOOP(ret, ::execvp(file, argv)); return ret; } static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) { int ret; - EINTR_LOOP(ret, ::waitpid(pid, status, options)); + QT_EINTR_LOOP(ret, ::waitpid(pid, status, options)); return ret; } #endif // QT_CONFIG(process) @@ -345,9 +362,6 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) # define _POSIX_MONOTONIC_CLOCK -1 #endif -// in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp -timespec qt_gettime() noexcept; -void qt_nanosleep(timespec amount); QByteArray qt_readlink(const char *path); /* non-static */ @@ -365,20 +379,7 @@ inline bool qt_haveLinuxProcfs() #endif } -Q_CORE_EXPORT int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts); - -static inline int qt_poll_msecs(struct pollfd *fds, nfds_t nfds, int timeout) -{ - timespec ts, *pts = nullptr; - - if (timeout >= 0) { - ts.tv_sec = timeout / 1000; - ts.tv_nsec = (timeout % 1000) * 1000 * 1000; - pts = &ts; - } - - return qt_safe_poll(fds, nfds, pts); -} +Q_CORE_EXPORT int qt_safe_poll(struct pollfd *fds, nfds_t nfds, QDeadlineTimer deadline); static inline struct pollfd qt_make_pollfd(int fd, short events) { |