summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmad Samir <a.samirh78@gmail.com>2023-04-29 15:07:14 +0300
committerAhmad Samir <a.samirh78@gmail.com>2023-10-24 18:29:45 +0300
commitceee7acf43464dbbcca7e05911e354532c5435f6 (patch)
treea366386e504305f72775059fb44fb559ba5bef36
parentdf2e07549e6edd1d271cce1d86cadd4a33dfd8fc (diff)
qcore_unix: port qt_safe_poll to QDeadlineTimer
Remove qt_poll_msecs() since the "forever" state can be simply expressed with a QDeadlineTimer::Forever arg, instead of passing a nullptr timespec, and the negative timeouts treated as "run forever" is also encapsulated by QDealineTimer. Use the QDealineTimer(qint64) constructor in the call sites where the timeout could be negative, so that it creates a Forever timer (the QDeadlineTimer(chrono::duration) constructor uses setRemainingTime(duration) which handles negative timeouts by creating expired timers). Remove qt_gettime() (and do_gettime()). Drive-by changes: - Fix a narrowing conversion warning, qt_make_pollfd() takes an int - Remove an unused include Change-Id: I096319af5e191e28c3d39295fb1aafe9d69841e6 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/io/qprocess_unix.cpp6
-rw-r--r--src/corelib/kernel/qcore_unix.cpp63
-rw-r--r--src/corelib/kernel/qcore_unix_p.h18
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp27
-rw-r--r--src/network/socket/qlocalserver_unix.cpp3
-rw-r--r--src/network/socket/qlocalsocket_unix.cpp5
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp2
-rw-r--r--tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp4
8 files changed, 32 insertions, 96 deletions
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 41fb08ad05..a949a492cd 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -221,7 +221,7 @@ QProcessPoller::QProcessPoller(const QProcessPrivate &proc)
int QProcessPoller::poll(const QDeadlineTimer &deadline)
{
- return qt_poll_msecs(pfds, n_pfds, deadline.remainingTime());
+ return qt_safe_poll(pfds, n_pfds, deadline);
}
struct QChildProcess
@@ -1092,15 +1092,15 @@ void QProcessPrivate::killProcess()
bool QProcessPrivate::waitForStarted(const QDeadlineTimer &deadline)
{
- const qint64 msecs = deadline.remainingTime();
#if defined (QPROCESS_DEBUG)
+ const qint64 msecs = deadline.remainingTime();
qDebug("QProcessPrivate::waitForStarted(%lld) waiting for child to start (fd = %d)",
msecs, childStartedPipe[0]);
#endif
pollfd pfd = qt_make_pollfd(childStartedPipe[0], POLLIN);
- if (qt_poll_msecs(&pfd, 1, msecs) == 0) {
+ if (qt_safe_poll(&pfd, 1, deadline) == 0) {
setError(QProcess::Timedout);
#if defined (QPROCESS_DEBUG)
qDebug("QProcessPrivate::waitForStarted(%lld) == false (timed out)", msecs);
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
index b4bdad1ebb..cec1ab2a0b 100644
--- a/src/corelib/kernel/qcore_unix.cpp
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -4,7 +4,6 @@
#include <QtCore/private/qglobal_p.h>
#include "qcore_unix_p.h"
-#include "qelapsedtimer.h"
#include <stdlib.h>
@@ -65,48 +64,10 @@ int qt_open64(const char *pathname, int flags, mode_t mode)
#ifndef QT_BOOTSTRAPPED
-static inline void do_gettime(qint64 *sec, qint64 *frac)
-{
- timespec ts;
- clockid_t clk = CLOCK_REALTIME;
-#if defined(CLOCK_MONOTONIC_RAW)
- clk = CLOCK_MONOTONIC_RAW;
-#elif defined(CLOCK_MONOTONIC)
- clk = CLOCK_MONOTONIC;
-#endif
-
- clock_gettime(clk, &ts);
- *sec = ts.tv_sec;
- *frac = ts.tv_nsec;
-}
-
-// also used in qeventdispatcher_unix.cpp
-struct timespec qt_gettime() noexcept
-{
- qint64 sec, frac;
- do_gettime(&sec, &frac);
-
- timespec tv;
- tv.tv_sec = sec;
- tv.tv_nsec = frac;
-
- return tv;
-}
-
#if QT_CONFIG(poll_pollts)
# define ppoll pollts
#endif
-static inline bool time_update(struct timespec *tv, const struct timespec &start,
- const struct timespec &timeout)
-{
- // clock source is (hopefully) monotonic, so we can recalculate how much timeout is left;
- // if it isn't monotonic, we'll simply hope that it hasn't jumped, because we have no alternative
- struct timespec now = qt_gettime();
- *tv = timeout + start - now;
- return tv->tv_sec >= 0;
-}
-
[[maybe_unused]]
static inline int timespecToMillisecs(const struct timespec *ts)
{
@@ -141,31 +102,27 @@ static inline int qt_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespe
using select(2) where necessary. In that case, returns -1 and sets errno
to EINVAL if passed any descriptor greater than or equal to FD_SETSIZE.
*/
-int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
+int qt_safe_poll(struct pollfd *fds, nfds_t nfds, QDeadlineTimer deadline)
{
- if (!timeout_ts) {
+ if (deadline.isForever()) {
// no timeout -> block forever
int ret;
EINTR_LOOP(ret, qt_ppoll(fds, nfds, nullptr));
return ret;
}
- timespec start = qt_gettime();
- timespec timeout = *timeout_ts;
-
+ using namespace std::chrono;
+ nanoseconds remaining = deadline.remainingTimeAsDuration();
// loop and recalculate the timeout as needed
- forever {
- const int ret = qt_ppoll(fds, nfds, &timeout);
+ do {
+ timespec ts = durationToTimespec(remaining);
+ const int ret = qt_ppoll(fds, nfds, &ts);
if (ret != -1 || errno != EINTR)
return ret;
+ remaining = deadline.remainingTimeAsDuration();
+ } while (remaining > 0ns);
- // recalculate the timeout
- if (!time_update(&timeout, start, *timeout_ts)) {
- // timeout during update
- // or clock reset, fake timeout error
- return 0;
- }
- }
+ return 0;
}
#endif // QT_BOOTSTRAPPED
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 2d55b9dcdc..cad1c4f54e 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -20,6 +20,7 @@
#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"
@@ -376,8 +377,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;
QByteArray qt_readlink(const char *path);
/* non-static */
@@ -395,20 +394,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)
{
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index 61f7b1a665..d0b47757bf 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -428,20 +428,18 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
if (d->interrupt.loadRelaxed())
return false;
- // If canWait is true, and include_timers is false or there are no pending
- // timers, call qt_safe_poll() with a nullptr so that it waits until there
- // are events to process (see QEventLoop::WaitForMoreEvents).
- timespec *tm = nullptr;
- timespec wait_tm = { 0, 0 };
-
- if (!canWait) {
- tm = &wait_tm;
- } else if (include_timers) {
- std::optional<std::chrono::milliseconds> msecs = d->timerList.timerWait();
- if (msecs) {
- wait_tm = durationToTimespec(*msecs);
- tm = &wait_tm;
+ QDeadlineTimer deadline;
+ if (canWait) {
+ if (include_timers) {
+ std::optional<std::chrono::milliseconds> msecs = d->timerList.timerWait();
+ deadline = msecs ? QDeadlineTimer{*msecs}
+ : QDeadlineTimer(QDeadlineTimer::Forever);
+ } else {
+ deadline = QDeadlineTimer(QDeadlineTimer::Forever);
}
+ } else {
+ // Using the default-constructed `deadline`, which is already expired,
+ // ensures the code in the do-while loop in qt_safe_poll runs at least once.
}
d->pollfds.clear();
@@ -455,8 +453,7 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
d->pollfds.append(d->threadPipe.prepare());
int nevents = 0;
-
- switch (qt_safe_poll(d->pollfds.data(), d->pollfds.size(), tm)) {
+ switch (qt_safe_poll(d->pollfds.data(), d->pollfds.size(), deadline)) {
case -1:
qErrnoWarning("qt_safe_poll");
if (QT_CONFIG(poll_exit_on_error))
diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp
index dcd001a263..9aa9a5b86f 100644
--- a/src/network/socket/qlocalserver_unix.cpp
+++ b/src/network/socket/qlocalserver_unix.cpp
@@ -279,8 +279,7 @@ void QLocalServerPrivate::_q_onNewConnection()
void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut)
{
pollfd pfd = qt_make_pollfd(listenSocket, POLLIN);
-
- switch (qt_poll_msecs(&pfd, 1, msec)) {
+ switch (qt_safe_poll(&pfd, 1, QDeadlineTimer(msec))) {
case 0:
if (timedOut)
*timedOut = true;
diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp
index 6e9133ad8f..af0dc988af 100644
--- a/src/network/socket/qlocalsocket_unix.cpp
+++ b/src/network/socket/qlocalsocket_unix.cpp
@@ -25,7 +25,6 @@ using namespace std::chrono_literals;
#define QT_CONNECT_TIMEOUT 30000
-
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
@@ -593,9 +592,7 @@ bool QLocalSocket::waitForConnected(int msec)
auto remainingTime = deadline.remainingTimeAsDuration();
do {
- timespec ts = durationToTimespec(remainingTime);
- const int result = qt_safe_poll(&pfd, 1, &ts);
-
+ const int result = qt_safe_poll(&pfd, 1, deadline);
if (result == -1)
d->setErrorAndEmit(QLocalSocket::UnknownSocketError,
"QLocalSocket::waitForConnected"_L1);
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 87c74f7f85..9656a3cef6 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -1364,7 +1364,7 @@ int QNativeSocketEnginePrivate::nativeSelect(QDeadlineTimer deadline, bool check
if (checkWrite)
pfd.events |= POLLOUT;
- const int ret = qt_poll_msecs(&pfd, 1, deadline.remainingTime());
+ const int ret = qt_safe_poll(&pfd, 1, deadline);
if (ret <= 0)
return ret;
diff --git a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
index 171f95157d..4ebeec6083 100644
--- a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
+++ b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
@@ -402,8 +402,8 @@ public slots:
dataSent = serverSocket->waitForBytesWritten(-1);
if (dataSent) {
- pollfd pfd = qt_make_pollfd(socket->socketDescriptor(), POLLIN);
- dataReadable = (1 == qt_safe_poll(&pfd, 1, nullptr));
+ pollfd pfd = qt_make_pollfd(int(socket->socketDescriptor()), POLLIN);
+ dataReadable = (1 == qt_safe_poll(&pfd, 1, QDeadlineTimer::Forever));
}
if (!dataReadable) {