diff options
Diffstat (limited to 'src/corelib/kernel/qcore_unix.cpp')
-rw-r--r-- | src/corelib/kernel/qcore_unix.cpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp new file mode 100644 index 0000000..b04abae --- /dev/null +++ b/src/corelib/kernel/qcore_unix.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcore_unix_p.h" + +#include <sys/select.h> +#include <sys/time.h> +#include <stdlib.h> + +#include "qeventdispatcher_unix_p.h" // for the timeval operators + +#if !defined(QT_NO_CLOCK_MONOTONIC) +# if defined(QT_BOOTSTRAPPED) +# define QT_NO_CLOCK_MONOTONIC +# endif +#endif + +QT_BEGIN_NAMESPACE + +static inline timeval gettime() +{ + timeval tv; +#ifndef QT_NO_CLOCK_MONOTONIC + // use the monotonic clock + static volatile bool monotonicClockDisabled = false; + struct timespec ts; + if (!monotonicClockDisabled) { + if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) { + monotonicClockDisabled = true; + } else { + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; + } + } +#endif + // use gettimeofday + ::gettimeofday(&tv, 0); + return tv; +} + +static inline bool time_update(struct timeval *tv, const struct timeval &start, + const struct timeval &timeout) +{ + struct timeval now = gettime(); + if (now < start) { + // clock reset, give up + return false; + } + + *tv = timeout + start - now; + return true; +} + +int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, + const struct timeval *orig_timeout) +{ + if (!orig_timeout) { + // no timeout -> block forever + register int ret; + EINTR_LOOP(ret, select(nfds, fdread, fdwrite, fdexcept, 0)); + return ret; + } + + timeval start = gettime(); + timeval timeout = *orig_timeout; + + // loop and recalculate the timeout as needed + int ret; + forever { + ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeout); + if (ret != -1 || errno != EINTR) + return ret; + + // recalculate the timeout + if (!time_update(&timeout, start, *orig_timeout)) { + // clock reset, fake timeout error + return 0; + } + } +} + +QT_END_NAMESPACE + +#ifdef Q_OS_LINUX +// Don't wait for libc to supply the calls we need +// Make syscalls directly + +# if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0204 +// glibc 2.4 has syscall(...) +# include <sys/syscall.h> +# include <asm/unistd.h> +# else +// no syscall(...) +static inline int syscall(...) { errno = ENOSYS; return -1;} +# endif + +# ifndef __NR_dup3 +# if defined(__i386__) +# define __NR_dup3 330 +# define __NR_pipe2 331 +# elif defined(__x86_64__) +# define __NR_dup3 292 +# define __NR_pipe2 293 +# elif defined(__ia64__) +# define __NR_dup3 1316 +# define __NR_pipe2 1317 +# else +// set the syscalls to absurd numbers so that they'll cause ENOSYS errors +# warning "Please port the pipe2/dup3 code to this platform" +# define __NR_dup3 -1 +# define __NR_pipe2 -1 +# endif +# endif + +# if !defined(__NR_socketcall) && !defined(__NR_accept4) +# if defined(__x86_64__) +# define __NR_accept4 288 +# elif defined(__ia64__) +// not assigned yet to IA-64 +# define __NR_accept4 -1 +# else +// set the syscalls to absurd numbers so that they'll cause ENOSYS errors +# warning "Please port the accept4 code to this platform" +# define __NR_accept4 -1 +# endif +# endif + +QT_BEGIN_NAMESPACE +namespace QtLibcSupplement { + int pipe2(int pipes[], int flags) + { + return syscall(__NR_pipe2, pipes, flags); + } + + int dup3(int oldfd, int newfd, int flags) + { + return syscall(__NR_dup3, oldfd, newfd, flags); + } + + int accept4(int s, sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags) + { +# if defined(__NR_socketcall) + // This platform uses socketcall() instead of raw syscalls + // the SYS_ACCEPT4 number is cross-platform: 18 + return syscall(__NR_socketcall, 18, &s); +# else + return syscall(__NR_accept4, s, addr, addrlen, flags); +# endif + + Q_UNUSED(addr); Q_UNUSED(addrlen); Q_UNUSED(flags); // they're actually used + } +} +QT_END_NAMESPACE +#endif // Q_OS_LINUX + |