diff options
Diffstat (limited to 'src/gui/embedded/qwslock.cpp')
-rw-r--r-- | src/gui/embedded/qwslock.cpp | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/src/gui/embedded/qwslock.cpp b/src/gui/embedded/qwslock.cpp index c14f50b..f9ea000 100644 --- a/src/gui/embedded/qwslock.cpp +++ b/src/gui/embedded/qwslock.cpp @@ -45,12 +45,15 @@ #include "qwssignalhandler_p.h" +#include <stdint.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> +#ifndef QT_POSIX_IPC #include <sys/sem.h> +#endif #include <sys/time.h> #include <time.h> #ifdef Q_OS_LINUX @@ -66,6 +69,12 @@ QT_BEGIN_NAMESPACE #error QWSLock currently requires semaphores #endif +#ifdef QT_POSIX_IPC +#include <QtCore/QAtomicInt> + +static QBasicAtomicInt localUniqueId = Q_BASIC_ATOMIC_INITIALIZER(1); +#endif + QWSLock::QWSLock(int id) : semId(id) { static unsigned short initialValues[3] = { 1, 1, 0 }; @@ -74,6 +83,7 @@ QWSLock::QWSLock(int id) : semId(id) QWSSignalHandler::instance()->addWSLock(this); #endif +#ifndef QT_POSIX_IPC if (semId == -1) { semId = semget(IPC_PRIVATE, 3, IPC_CREAT | 0666); if (semId == -1) { @@ -88,6 +98,30 @@ QWSLock::QWSLock(int id) : semId(id) qFatal("Unable to initialize semaphores"); } } +#else + sems[0] = sems[1] = sems[2] = SEM_FAILED; + owned = false; + + if (semId == -1) { + // ### generate really unique IDs + semId = (getpid() << 16) + (localUniqueId.fetchAndAddRelaxed(1) % ushort(-1)); + owned = true; + } + + QByteArray pfx = "/qwslock_" + QByteArray::number(semId, 16) + '_'; + QByteArray keys[3] = { pfx + "BackingStore", pfx + "Communication", pfx + "RegionEvent" }; + for (int i = 0; i < 3; ++i) { + if (owned) + sem_unlink(keys[i].constData()); + do { + sems[i] = sem_open(keys[i].constData(), (owned ? O_CREAT : 0), 0666, initialValues[i]); + } while (sems[i] == SEM_FAILED && errno == EINTR); + if (sems[i] == SEM_FAILED) { + perror("QWSLock::QWSLock"); + qFatal("Unable to %s semaphore", (owned ? "create" : "open")); + } + } +#endif lockCount[0] = lockCount[1] = 0; } @@ -99,10 +133,27 @@ QWSLock::~QWSLock() #endif if (semId != -1) { +#ifndef QT_POSIX_IPC qt_semun semval; semval.val = 0; semctl(semId, 0, IPC_RMID, semval); semId = -1; +#else + // emulate the SEM_UNDO behavior for the BackingStore lock + while (hasLock(BackingStore)) + unlock(BackingStore); + + QByteArray pfx = "/qwslock_" + QByteArray::number(semId, 16) + '_'; + QByteArray keys[3] = { pfx + "BackingStore", pfx + "Communication", pfx + "RegionEvent" }; + for (int i = 0; i < 3; ++i) { + if (sems[i] != SEM_FAILED) { + sem_close(sems[i]); + sems[i] = SEM_FAILED; + } + if (owned) + sem_unlink(keys[i].constData()); + } +#endif } } @@ -110,6 +161,7 @@ bool QWSLock::up(unsigned short semNum) { int ret; +#ifndef QT_POSIX_IPC sembuf sops = { semNum, 1, 0 }; // As the BackingStore lock is a mutex, and only one process may own // the lock, it's safe to use SEM_UNDO. On the other hand, the @@ -119,6 +171,9 @@ bool QWSLock::up(unsigned short semNum) sops.sem_flg |= SEM_UNDO; EINTR_LOOP(ret, semop(semId, &sops, 1)); +#else + ret = sem_post(sems[semNum]); +#endif if (ret == -1) { qDebug("QWSLock::up(): %s", strerror(errno)); return false; @@ -131,6 +186,7 @@ bool QWSLock::down(unsigned short semNum, int) { int ret; +#ifndef QT_POSIX_IPC sembuf sops = { semNum, -1, 0 }; // As the BackingStore lock is a mutex, and only one process may own // the lock, it's safe to use SEM_UNDO. On the other hand, the @@ -140,6 +196,9 @@ bool QWSLock::down(unsigned short semNum, int) sops.sem_flg |= SEM_UNDO; EINTR_LOOP(ret, semop(semId, &sops, 1)); +#else + EINTR_LOOP(ret, sem_wait(sems[semNum])); +#endif if (ret == -1) { qDebug("QWSLock::down(): %s", strerror(errno)); return false; @@ -150,7 +209,13 @@ bool QWSLock::down(unsigned short semNum, int) int QWSLock::getValue(unsigned short semNum) const { - int ret = semctl(semId, semNum, GETVAL, 0); + int ret; +#ifndef QT_POSIX_IPC + ret = semctl(semId, semNum, GETVAL, 0); +#else + if (sem_getvalue(sems[semNum], &ret) == -1) + ret = -1; +#endif if (ret == -1) qDebug("QWSLock::getValue(): %s", strerror(errno)); return ret; |