diff options
Diffstat (limited to 'src/corelib/kernel/qcore_unix_p.h')
-rw-r--r-- | src/corelib/kernel/qcore_unix_p.h | 137 |
1 files changed, 87 insertions, 50 deletions
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 9ccc9ca10b..fd834cb2d9 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -18,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" @@ -39,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 @@ -59,7 +56,7 @@ struct sockaddr; -#define EINTR_LOOP(var, cmd) \ +#define QT_EINTR_LOOP(var, cmd) \ do { \ var = cmd; \ } while (var == -1 && errno == EINTR) @@ -68,16 +65,41 @@ 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 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; } @@ -104,7 +126,7 @@ constexpr inline timespec operator-(const timespec &t1, const timespec &t2) { 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); } constexpr inline timespec operator*(const timespec &t1, int mul) @@ -114,7 +136,7 @@ constexpr inline timespec operator*(const timespec &t1, int 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; @@ -122,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. - Q_CONSTINIT 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); @@ -147,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) @@ -155,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) @@ -227,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; @@ -243,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 @@ -252,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 @@ -267,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 @@ -279,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) @@ -309,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 */ @@ -329,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) { |