summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2011-06-22 10:44:56 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2011-06-22 10:44:56 (GMT)
commit078a68ffc84a745830535f1eb0e19ab8a190f542 (patch)
treeda6310c113b1be22c440a3548849d1ea28aa4d18 /src/corelib/kernel
parente4cce8849bf45be9a111072e3fca7bdf67364e8a (diff)
parentaf3bb0f146ec357ae6daf752a5f8bbdb074cde20 (diff)
downloadQt-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.cpp22
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp5
-rw-r--r--src/corelib/kernel/qsharedmemory_p.h4
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp143
-rw-r--r--src/corelib/kernel/qsystemsemaphore.cpp7
-rw-r--r--src/corelib/kernel/qsystemsemaphore_p.h9
-rw-r--r--src/corelib/kernel/qsystemsemaphore_unix.cpp124
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, &param) == 0 && sched_policy != SCHED_RR) {
+ sched_policy = SCHED_RR;
+ pthread_setschedparam(0, sched_policy, &param);
+ }
+#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;
}