diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2011-06-22 10:44:56 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2011-06-22 10:44:56 (GMT) |
commit | 078a68ffc84a745830535f1eb0e19ab8a190f542 (patch) | |
tree | da6310c113b1be22c440a3548849d1ea28aa4d18 /src/corelib/kernel | |
parent | e4cce8849bf45be9a111072e3fca7bdf67364e8a (diff) | |
parent | af3bb0f146ec357ae6daf752a5f8bbdb074cde20 (diff) | |
download | Qt-078a68ffc84a745830535f1eb0e19ab8a190f542.zip Qt-078a68ffc84a745830535f1eb0e19ab8a190f542.tar.gz Qt-078a68ffc84a745830535f1eb0e19ab8a190f542.tar.bz2 |
Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1:
trivial: fix typo in comment
changelog
docu update for QNX 6.5
get rid of anacronysm
massive improvements for the QNX screen driver
massive improvements for the QNX mouse driver
massive improvements for the QNX keyboard driver
disable the Embedded Linux data directory permissions check for QNX
skip two subtests that are known to fail on QNX
implement POSIX IPC based QLock, QWSLock and QWSSharedMemory backends
implement POSIX IPC based QSystemSemaphore and QSharedMemory backends
add a configure-time check for an IPC support
make QProcess really work on QNX
make the kernel attempt to emulate an instruction with a misaligned access
use RoundRobin scheduler by default on QNX
a major refactoring of the mkspecs tree for QNX
buildfix for qmake
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 22 | ||||
-rw-r--r-- | src/corelib/kernel/qsharedmemory.cpp | 5 | ||||
-rw-r--r-- | src/corelib/kernel/qsharedmemory_p.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qsharedmemory_unix.cpp | 143 | ||||
-rw-r--r-- | src/corelib/kernel/qsystemsemaphore.cpp | 7 | ||||
-rw-r--r-- | src/corelib/kernel/qsystemsemaphore_p.h | 9 | ||||
-rw-r--r-- | src/corelib/kernel/qsystemsemaphore_unix.cpp | 124 |
7 files changed, 313 insertions, 1 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 7694a0f..dd46bc5 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -98,6 +98,12 @@ # include <taskLib.h> #endif +#ifdef Q_OS_QNX +# include <sys/neutrino.h> +# include <pthread.h> +# include <sched.h> +#endif + QT_BEGIN_NAMESPACE class QMutexUnlocker @@ -353,6 +359,22 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint qt_application_thread_id = QThread::currentThreadId(); #endif +#ifdef Q_OS_QNX + // make the kernel attempt to emulate an instruction with a misaligned access + // if the attempt fails, it faults with a SIGBUS + int tv = -1; + ThreadCtl(_NTO_TCTL_ALIGN_FAULT, &tv); + + // without Round Robin drawn intensive apps will hog the cpu + // and make the system appear frozen + int sched_policy; + sched_param param; + if (pthread_getschedparam(0, &sched_policy, ¶m) == 0 && sched_policy != SCHED_RR) { + sched_policy = SCHED_RR; + pthread_setschedparam(0, sched_policy, ¶m); + } +#endif + // note: this call to QThread::currentThread() may end up setting theMainThread! if (QThread::currentThread() != theMainThread) qWarning("WARNING: QApplication was not created in the main() thread."); diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp index 2882279..371974c 100644 --- a/src/corelib/kernel/qsharedmemory.cpp +++ b/src/corelib/kernel/qsharedmemory.cpp @@ -80,6 +80,8 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, return result; #elif defined(Q_OS_SYMBIAN) return result.left(KMaxKernelName); +#elif defined(QT_POSIX_IPC) + return QLatin1Char('/') + result; #else return QDir::tempPath() + QLatin1Char('/') + result; #endif @@ -117,6 +119,9 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, process crashes without running the QSharedMemory destructor, the shared memory segment survives the crash. + \o QNX: Due to possible race conditions in the POSIX IPC implementation, create() + should be called prior to any attach() calls (even across multiple threads). + \o HP-UX: Only one attach to a shared memory segment is allowed per process. This means that QSharedMemory should not be used across multiple threads in the same process in HP-UX. diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index 21b8612..780e52e 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -135,6 +135,8 @@ public: const QString &prefix = QLatin1String("qipc_sharedmemory_")); #ifdef Q_OS_WIN HANDLE handle(); +#elif defined(QT_POSIX_IPC) + int handle(); #else key_t handle(); #endif @@ -166,6 +168,8 @@ private: HANDLE hand; #elif defined(Q_OS_SYMBIAN) RChunk chunk; +#elif defined(QT_POSIX_IPC) + int hand; #else key_t unix_key; #endif diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index e991ce9..a086acd 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -50,8 +50,12 @@ #ifndef QT_NO_SHAREDMEMORY #include <sys/types.h> #include <sys/ipc.h> +#ifndef QT_POSIX_IPC #include <sys/shm.h> +#else +#include <sys/mman.h> #include <sys/stat.h> +#endif #include <fcntl.h> #include <unistd.h> #endif // QT_NO_SHAREDMEMORY @@ -70,7 +74,11 @@ QSharedMemoryPrivate::QSharedMemoryPrivate() #ifndef QT_NO_SYSTEMSEMAPHORE systemSemaphore(QString()), lockedByMe(false), #endif +#ifndef QT_POSIX_IPC unix_key(0) +#else + hand(0) +#endif { } @@ -91,12 +99,18 @@ void QSharedMemoryPrivate::setErrorString(const QString &function) errorString = QSharedMemory::tr("%1: doesn't exist").arg(function); error = QSharedMemory::NotFound; break; + case EAGAIN: case EMFILE: + case ENFILE: case ENOMEM: case ENOSPC: errorString = QSharedMemory::tr("%1: out of resources").arg(function); error = QSharedMemory::OutOfResources; break; + case EOVERFLOW: + errorString = QSharedMemory::tr("%1: invalid size").arg(function); + error = QSharedMemory::InvalidSize; + break; default: errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(errno); error = QSharedMemory::UnknownError; @@ -112,6 +126,7 @@ void QSharedMemoryPrivate::setErrorString(const QString &function) If not already made create the handle used for accessing the shared memory. */ +#ifndef QT_POSIX_IPC key_t QSharedMemoryPrivate::handle() { // already made @@ -140,6 +155,20 @@ key_t QSharedMemoryPrivate::handle() } return unix_key; } +#else +int QSharedMemoryPrivate::handle() +{ + // don't allow making handles on empty keys + QString safeKey = makePlatformSafeKey(key); + if (safeKey.isEmpty()) { + errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle")); + error = QSharedMemory::KeyError; + return 0; + } + + return 1; +} +#endif // QT_POSIX_IPC #endif // QT_NO_SHAREDMEMORY @@ -155,6 +184,7 @@ key_t QSharedMemoryPrivate::handle() */ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) { +#ifndef QT_POSIX_IPC if (QFile::exists(fileName)) return 0; @@ -168,6 +198,11 @@ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) qt_safe_close(fd); } return 1; +#else + Q_UNUSED(fileName); + // nothing to do + return -1; +#endif } #endif // QT_NO_SHAREDMEMORY && QT_NO_SYSTEMSEMAPHORE @@ -175,11 +210,17 @@ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) void QSharedMemoryPrivate::cleanHandle() { +#ifndef QT_POSIX_IPC unix_key = 0; +#else + qt_safe_close(hand); + hand = 0; +#endif } bool QSharedMemoryPrivate::create(int size) { +#ifndef QT_POSIX_IPC // build file if needed int built = createUnixKeyFile(nativeKey); if (built == -1) { @@ -211,12 +252,46 @@ bool QSharedMemoryPrivate::create(int size) QFile::remove(nativeKey); return false; } +#else + if (!handle()) + return false; + + QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key)); + + int fd; + EINTR_LOOP(fd, shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0666)); + if (fd == -1) { + QString function = QLatin1String("QSharedMemory::create"); + switch (errno) { + case ENAMETOOLONG: + case EINVAL: + errorString = QSharedMemory::tr("%1: bad name").arg(function); + error = QSharedMemory::KeyError; + break; + default: + setErrorString(function); + } + return false; + } + + // the size may only be set once; ignore errors + int ret; + EINTR_LOOP(ret, ftruncate(fd, size)); + if (ret == -1) { + setErrorString(QLatin1String("QSharedMemory::create (ftruncate)")); + qt_safe_close(fd); + return false; + } + + qt_safe_close(fd); +#endif // QT_POSIX_IPC return true; } bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode) { +#ifndef QT_POSIX_IPC // grab the shared memory segment id int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0444 : 0660)); if (-1 == id) { @@ -240,12 +315,55 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode) setErrorString(QLatin1String("QSharedMemory::attach (shmctl)")); return false; } +#else + QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key)); + + int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR); + mode_t omode = (mode == QSharedMemory::ReadOnly ? 0444 : 0660); + + EINTR_LOOP(hand, shm_open(shmName.constData(), oflag, omode)); + if (hand == -1) { + QString function = QLatin1String("QSharedMemory::attach (shm_open)"); + switch (errno) { + case ENAMETOOLONG: + case EINVAL: + errorString = QSharedMemory::tr("%1: bad name").arg(function); + error = QSharedMemory::KeyError; + break; + default: + setErrorString(function); + } + hand = 0; + return false; + } + + // grab the size + QT_STATBUF st; + if (QT_FSTAT(hand, &st) == -1) { + setErrorString(QLatin1String("QSharedMemory::attach (fstat)")); + cleanHandle(); + return false; + } + size = st.st_size; + + // grab the memory + int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE); + memory = mmap(0, size, mprot, MAP_SHARED, hand, 0); + if (memory == MAP_FAILED || !memory) { + setErrorString(QLatin1String("QSharedMemory::attach (mmap)")); + cleanHandle(); + memory = 0; + size = 0; + return false; + } +#endif // QT_POSIX_IPC return true; } bool QSharedMemoryPrivate::detach() { +#ifndef QT_POSIX_IPC // detach from the memory segment if (-1 == shmdt(memory)) { QString function = QLatin1String("QSharedMemory::detach"); @@ -292,6 +410,31 @@ bool QSharedMemoryPrivate::detach() if (!QFile::remove(nativeKey)) return false; } +#else + // detach from the memory segment + if (munmap(memory, size) == -1) { + setErrorString(QLatin1String("QSharedMemory::detach (munmap)")); + return false; + } + memory = 0; + size = 0; + + // get the number of current attachments + int shm_nattch = 0; + QT_STATBUF st; + if (QT_FSTAT(hand, &st) == 0) { + // subtract 2 from linkcount: one for our own open and one for the dir entry + shm_nattch = st.st_nlink - 2; + } + cleanHandle(); + // if there are no attachments then unlink the shared memory + if (shm_nattch == 0) { + QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key)); + if (shm_unlink(shmName.constData()) == -1 && errno != ENOENT) + setErrorString(QLatin1String("QSharedMemory::detach (shm_unlink)")); + } +#endif // QT_POSIX_IPC + return true; } diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp index 98ee6f4..ae30348 100644 --- a/src/corelib/kernel/qsystemsemaphore.cpp +++ b/src/corelib/kernel/qsystemsemaphore.cpp @@ -151,6 +151,11 @@ QT_BEGIN_NAMESPACE creates a new semaphore for that key and sets its resource count to \a initialValue. + In QNX, if the \a mode is \l {QSystemSemaphore::} {Create} and the + system already has a semaphore identified by \a key, that semaphore + will be deleted and the new one will be created for that key with + a resource count set to \a initialValue. + In Windows and in Symbian, \a mode is ignored, and the system always tries to create a semaphore for the specified \a key. If the system does not already have a semaphore identified as \a key, it creates the @@ -234,7 +239,7 @@ void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode m return; d->error = NoError; d->errorString = QString(); -#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN) +#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN) && !defined(QT_POSIX_IPC) // optimization to not destroy/create the file & semaphore if (key == d->key && mode == Create && d->createdSemaphore && d->createdFile) { d->initialValue = initialValue; diff --git a/src/corelib/kernel/qsystemsemaphore_p.h b/src/corelib/kernel/qsystemsemaphore_p.h index 3e5f737..d84d416 100644 --- a/src/corelib/kernel/qsystemsemaphore_p.h +++ b/src/corelib/kernel/qsystemsemaphore_p.h @@ -61,6 +61,9 @@ #ifndef Q_OS_WINCE # include <sys/types.h> #endif +#ifdef QT_POSIX_IPC +# include <semaphore.h> +#endif #ifdef Q_OS_SYMBIAN class RSemaphore; @@ -84,6 +87,9 @@ public: #elif defined(Q_OS_SYMBIAN) int handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open); void setErrorString(const QString &function,int err = 0); +#elif defined(QT_POSIX_IPC) + bool handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open); + void setErrorString(const QString &function); #else key_t handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open); void setErrorString(const QString &function); @@ -99,6 +105,9 @@ public: HANDLE semaphoreLock; #elif defined(Q_OS_SYMBIAN) RSemaphore semaphore; +#elif defined(QT_POSIX_IPC) + sem_t *semaphore; + bool createdSemaphore; #else key_t unix_key; int semaphore; diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp index 704afaf..e060eb2 100644 --- a/src/corelib/kernel/qsystemsemaphore_unix.cpp +++ b/src/corelib/kernel/qsystemsemaphore_unix.cpp @@ -50,7 +50,9 @@ #include <sys/types.h> #include <sys/ipc.h> +#ifndef QT_POSIX_IPC #include <sys/sem.h> +#endif #include <fcntl.h> #include <errno.h> @@ -67,7 +69,11 @@ QT_BEGIN_NAMESPACE QSystemSemaphorePrivate::QSystemSemaphorePrivate() : +#ifndef QT_POSIX_IPC unix_key(-1), semaphore(-1), createdFile(false), +#else + semaphore(SEM_FAILED), +#endif createdSemaphore(false), error(QSystemSemaphore::NoError) { } @@ -90,10 +96,18 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function) error = QSystemSemaphore::NotFound; break; case ERANGE: + case ENOMEM: case ENOSPC: + case EMFILE: + case ENFILE: + case EOVERFLOW: errorString = QCoreApplication::translate("QSystemSemaphore", "%1: out of resources").arg(function); error = QSystemSemaphore::OutOfResources; break; + case ENAMETOOLONG: + errorString = QCoreApplication::translate("QSystemSemaphore", "%1: name error").arg(function); + error = QSystemSemaphore::KeyError; + break; default: errorString = QCoreApplication::translate("QSystemSemaphore", "%1: unknown error %2").arg(function).arg(errno); error = QSystemSemaphore::UnknownError; @@ -109,6 +123,7 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function) Initialise the semaphore */ +#ifndef QT_POSIX_IPC key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) { if (-1 != unix_key) @@ -170,6 +185,54 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) return unix_key; } +#else +bool QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) +{ + if (semaphore != SEM_FAILED) + return true; // we already have a semaphore + + if (fileName.isEmpty()) { + errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle")); + error = QSystemSemaphore::KeyError; + return false; + } + + QByteArray semName = QFile::encodeName(fileName); + + // Always try with O_EXCL so we know whether we created the semaphore. + int oflag = O_CREAT | O_EXCL; + for (int tryNum = 0, maxTries = 1; tryNum < maxTries; ++tryNum) { + do { + semaphore = sem_open(semName.constData(), oflag, 0666, initialValue); + } while (semaphore == SEM_FAILED && errno == EINTR); + if (semaphore == SEM_FAILED && errno == EEXIST) { + if (mode == QSystemSemaphore::Create) { + if (sem_unlink(semName.constData()) == -1 && errno != ENOENT) { + setErrorString(QLatin1String("QSystemSemaphore::handle (sem_unlink)")); + return false; + } + // Race condition: the semaphore might be recreated before + // we call sem_open again, so we'll retry several times. + maxTries = 3; + } else { + // Race condition: if it no longer exists at the next sem_open + // call, we won't realize we created it, so we'll leak it later. + oflag &= ~O_EXCL; + maxTries = 2; + } + } else { + break; + } + } + if (semaphore == SEM_FAILED) { + setErrorString(QLatin1String("QSystemSemaphore::handle")); + return false; + } + + createdSemaphore = (oflag & O_EXCL) != 0; + return true; +} +#endif // QT_POSIX_IPC /*! \internal @@ -178,6 +241,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) */ void QSystemSemaphorePrivate::cleanHandle() { +#ifndef QT_POSIX_IPC unix_key = -1; // remove the file if we made it @@ -198,6 +262,27 @@ void QSystemSemaphorePrivate::cleanHandle() } createdSemaphore = false; } +#else + if (semaphore != SEM_FAILED) { + if (sem_close(semaphore) == -1) { + setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_close)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_close failed."); +#endif + } + semaphore = SEM_FAILED; + } + + if (createdSemaphore) { + if (sem_unlink(QFile::encodeName(fileName).constData()) == -1 && errno != ENOENT) { + setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_unlink)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_unlink failed."); +#endif + } + createdSemaphore = false; + } +#endif // QT_POSIX_IPC } /*! @@ -205,6 +290,7 @@ void QSystemSemaphorePrivate::cleanHandle() */ bool QSystemSemaphorePrivate::modifySemaphore(int count) { +#ifndef QT_POSIX_IPC if (-1 == handle()) return false; @@ -229,6 +315,44 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count) #endif return false; } +#else + if (!handle()) + return false; + + if (count > 0) { + int cnt = count; + do { + if (sem_post(semaphore) == -1) { + setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_post)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::modify sem_post failed") << count << errno; +#endif + // rollback changes to preserve the SysV semaphore behavior + for ( ; cnt < count; ++cnt) { + register int res; + EINTR_LOOP(res, sem_wait(semaphore)); + } + return false; + } + --cnt; + } while (cnt > 0); + } else { + register int res; + EINTR_LOOP(res, sem_wait(semaphore)); + if (res == -1) { + // If the semaphore was removed be nice and create it and then modifySemaphore again + if (errno == EINVAL || errno == EIDRM) { + semaphore = SEM_FAILED; + return modifySemaphore(count); + } + setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_wait)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::modify sem_wait failed") << count << errno; +#endif + return false; + } + } +#endif // QT_POSIX_IPC return true; } |