Add support for Linux eventfd(7) in the UNIX event loop
eventfd(7) uses less resources than a pipe, as it only needs to store a single 64-bit integer, as opposed to a full buffer. It was introduced first on Linux version 2.6.22 and glibc 2.7. However, both the configure-time test and the runtime usage require the use of EFD_CLOEXEC for thread-safety, so this code will be enabled only for Linux 2.6.27 and up as well as glibc 2.9 and up. Change-Id: Ic7e10b28d7b1d4ca24be614ed84055c4429a68e4 Reviewed-by: Robin Burchell <robin+qt@viroteck.net> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
This commit is contained in:
parent
dbfa651889
commit
f927efd77a
3
config.tests/unix/eventfd/eventfd.pro
Normal file
3
config.tests/unix/eventfd/eventfd.pro
Normal file
@ -0,0 +1,3 @@
|
||||
SOURCES = main.cpp
|
||||
CONFIG -= qt dylib
|
||||
mac:CONFIG -= app_bundle
|
51
config.tests/unix/eventfd/main.cpp
Normal file
51
config.tests/unix/eventfd/main.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Intel Corporation
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the config.tests 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
eventfd_t value;
|
||||
int fd = eventfd(0, EFD_CLOEXEC);
|
||||
eventfd_read(fd, &value);
|
||||
eventfd_write(fd, value);
|
||||
return 0;
|
||||
}
|
22
configure
vendored
22
configure
vendored
@ -842,6 +842,7 @@ CFG_GETADDRINFO=auto
|
||||
CFG_IPV6IFNAME=auto
|
||||
CFG_GETIFADDRS=auto
|
||||
CFG_INOTIFY=auto
|
||||
CFG_EVENTFD=auto
|
||||
CFG_RPATH=yes
|
||||
CFG_FRAMEWORK=auto
|
||||
CFG_MAC_HARFBUZZ=no
|
||||
@ -5099,6 +5100,23 @@ if [ "$CFG_INOTIFY" != "no" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# find if the platform provides eventfd
|
||||
if [ "$CFG_EVENTFD" != "no" ]; then
|
||||
if compileTest unix/eventfd "eventfd"; then
|
||||
CFG_EVENTFD=yes
|
||||
else
|
||||
if [ "$CFG_EVENTFD" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then
|
||||
echo "eventfd support cannot be enabled due to functionality tests!"
|
||||
echo " Turn on verbose messaging (-v) to $0 to see the final report."
|
||||
echo " If you believe this message is in error you may use the continue"
|
||||
echo " switch (-continue) to $0 to continue."
|
||||
exit 101
|
||||
else
|
||||
CFG_EVENTFD=no
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# find if the platform provides if_nametoindex (ipv6 interface name support)
|
||||
if [ "$CFG_IPV6IFNAME" != "no" ]; then
|
||||
if compileTest unix/ipv6ifname "IPv6 interface name"; then
|
||||
@ -5386,6 +5404,9 @@ fi
|
||||
if [ "$CFG_INOTIFY" = "yes" ]; then
|
||||
QT_CONFIG="$QT_CONFIG inotify"
|
||||
fi
|
||||
if [ "$CFG_EVENTFD" = "yes" ]; then
|
||||
QT_CONFIG="$QT_CONFIG eventfd"
|
||||
fi
|
||||
if [ "$CFG_LIBJPEG" = "no" ]; then
|
||||
CFG_JPEG="no"
|
||||
elif [ "$CFG_LIBJPEG" = "system" ]; then
|
||||
@ -5862,6 +5883,7 @@ QMakeVar set sql-plugins "$SQL_PLUGINS"
|
||||
[ "$CFG_IPV6IFNAME" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_IPV6IFNAME"
|
||||
[ "$CFG_GETIFADDRS" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_GETIFADDRS"
|
||||
[ "$CFG_INOTIFY" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_INOTIFY"
|
||||
[ "$CFG_EVENTFD" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_EVENTFD"
|
||||
[ "$CFG_NIS" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_NIS"
|
||||
[ "$CFG_OPENSSL" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_OPENSSL QT_NO_SSL"
|
||||
[ "$CFG_OPENSSL" = "linked" ]&& QCONFIG_FLAGS="$QCONFIG_FLAGS QT_LINKED_OPENSSL"
|
||||
|
@ -56,6 +56,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef QT_NO_EVENTFD
|
||||
# include <sys/eventfd.h>
|
||||
#endif
|
||||
|
||||
// VxWorks doesn't correctly set the _POSIX_... options
|
||||
#if defined(Q_OS_VXWORKS)
|
||||
# if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK <= 0)
|
||||
@ -127,6 +131,12 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate()
|
||||
}
|
||||
}
|
||||
#else
|
||||
# ifndef QT_NO_EVENTFD
|
||||
thread_pipe[0] = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
|
||||
if (thread_pipe[0] != -1)
|
||||
thread_pipe[1] = -1;
|
||||
else // fall through the next "if"
|
||||
# endif
|
||||
if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) {
|
||||
perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
|
||||
pipefail = true;
|
||||
@ -155,7 +165,8 @@ QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
|
||||
#else
|
||||
// cleanup the common parts of the event loop
|
||||
close(thread_pipe[0]);
|
||||
close(thread_pipe[1]);
|
||||
if (thread_pipe[1] != -1)
|
||||
close(thread_pipe[1]);
|
||||
#endif
|
||||
|
||||
// cleanup timers
|
||||
@ -279,9 +290,18 @@ int QEventDispatcherUNIXPrivate::processThreadWakeUp(int nsel)
|
||||
::read(thread_pipe[0], c, sizeof(c));
|
||||
::ioctl(thread_pipe[0], FIOFLUSH, 0);
|
||||
#else
|
||||
char c[16];
|
||||
while (::read(thread_pipe[0], c, sizeof(c)) > 0)
|
||||
;
|
||||
# ifndef QT_NO_EVENTFD
|
||||
if (thread_pipe[1] == -1) {
|
||||
// eventfd
|
||||
eventfd_t value;
|
||||
eventfd_read(thread_pipe[0], &value);
|
||||
} else
|
||||
# endif
|
||||
{
|
||||
char c[16];
|
||||
while (::read(thread_pipe[0], c, sizeof(c)) > 0) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!wakeUps.testAndSetRelease(1, 0)) {
|
||||
// hopefully, this is dead code
|
||||
@ -630,6 +650,15 @@ void QEventDispatcherUNIX::wakeUp()
|
||||
{
|
||||
Q_D(QEventDispatcherUNIX);
|
||||
if (d->wakeUps.testAndSetAcquire(0, 1)) {
|
||||
#ifndef QT_NO_EVENTFD
|
||||
if (d->thread_pipe[1] == -1) {
|
||||
// eventfd
|
||||
eventfd_t value = 1;
|
||||
int ret;
|
||||
EINTR_LOOP(ret, eventfd_write(d->thread_pipe[0], value));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
char c = 0;
|
||||
qt_safe_write( d->thread_pipe[1], &c, 1 );
|
||||
}
|
||||
|
@ -148,6 +148,9 @@ public:
|
||||
virtual int processThreadWakeUp(int nsel);
|
||||
|
||||
bool mainThread;
|
||||
|
||||
// note for eventfd(7) support:
|
||||
// if thread_pipe[1] is -1, then eventfd(7) is in use and is stored in thread_pipe[0]
|
||||
int thread_pipe[2];
|
||||
|
||||
// highest fd for all socket notifiers
|
||||
|
Loading…
x
Reference in New Issue
Block a user