source: trunk/src/gui/embedded/qwslock.cpp@ 1147

Last change on this file since 1147 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 6.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qwslock_p.h"
43
44#ifndef QT_NO_QWS_MULTIPROCESS
45
46#include "qwssignalhandler_p.h"
47
48#include <qglobal.h>
49#include <qdebug.h>
50#include <stdio.h>
51#include <errno.h>
52#include <string.h>
53#include <sys/types.h>
54#include <sys/ipc.h>
55#include <sys/sem.h>
56#include <sys/time.h>
57#include <time.h>
58#ifdef Q_OS_LINUX
59#include <linux/version.h>
60#endif
61#include <unistd.h>
62
63QT_BEGIN_NAMESPACE
64
65#ifdef QT_NO_SEMAPHORE
66#error QWSLock currently requires semaphores
67#endif
68
69#ifndef Q_OS_BSD4
70union semun {
71 int val;
72 struct semid_ds *buf;
73 unsigned short *array;
74 struct seminfo *__buf;
75};
76#endif
77
78QWSLock::QWSLock()
79{
80 semId = semget(IPC_PRIVATE, 3, IPC_CREAT | 0666);
81
82 if (semId == -1) {
83 perror("QWSLock::QWSLock");
84 qFatal("Unable to create semaphore");
85 }
86 QWSSignalHandler::instance()->addSemaphore(semId);
87
88 semun semval;
89 semval.val = 1;
90
91 if (semctl(semId, BackingStore, SETVAL, semval) == -1) {
92 perror("QWSLock::QWSLock");
93 qFatal("Unable to initialize backingstore semaphore");
94 }
95 lockCount[BackingStore] = 0;
96
97 if (semctl(semId, Communication, SETVAL, semval) == -1) {
98 perror("QWSLock::QWSLock");
99 qFatal("Unable to initialize communication semaphore");
100 }
101 lockCount[Communication] = 0;
102
103 semval.val = 0;
104 if (semctl(semId, RegionEvent, SETVAL, semval) == -1) {
105 perror("QWSLock::QWSLock");
106 qFatal("Unable to initialize region event semaphore");
107 }
108}
109
110QWSLock::QWSLock(int id)
111{
112 semId = id;
113 QWSSignalHandler::instance()->addSemaphore(semId);
114 lockCount[0] = lockCount[1] = 0;
115}
116
117QWSLock::~QWSLock()
118{
119 if (semId == -1)
120 return;
121 QWSSignalHandler::instance()->removeSemaphore(semId);
122}
123
124static bool forceLock(int semId, int semNum, int)
125{
126 int ret;
127 do {
128 sembuf sops = { semNum, -1, 0 };
129
130 // As the BackingStore lock is a mutex, and only one process may own
131 // the lock, it's safe to use SEM_UNDO. On the other hand, the
132 // Communication lock is locked by the client but unlocked by the
133 // server and therefore can't use SEM_UNDO.
134 if (semNum == QWSLock::BackingStore)
135 sops.sem_flg |= SEM_UNDO;
136
137 ret = semop(semId, &sops, 1);
138 if (ret == -1 && errno != EINTR)
139 qDebug("QWSLock::lock: %s", strerror(errno));
140 } while (ret == -1 && errno == EINTR);
141
142 return (ret != -1);
143}
144
145static bool up(int semId, int semNum)
146{
147 int ret;
148 do {
149 sembuf sops = { semNum, 1, 0 };
150 ret = semop(semId, &sops, 1);
151 if (ret == -1 && errno != EINTR)
152 qDebug("QWSLock::up: %s", strerror(errno));
153 } while (ret == -1 && errno == EINTR);
154
155 return (ret != -1);
156}
157
158static bool down(int semId, int semNum)
159{
160 int ret;
161 do {
162 sembuf sops = { semNum, -1, 0 };
163 ret = semop(semId, &sops, 1);
164 if (ret == -1 && errno != EINTR)
165 qDebug("QWSLock::down: %s", strerror(errno));
166 } while (ret == -1 && errno == EINTR);
167
168 return (ret != -1);
169}
170
171static int getValue(int semId, int semNum)
172{
173 int ret;
174 do {
175 ret = semctl(semId, semNum, GETVAL, 0);
176 if (ret == -1 && errno != EINTR)
177 qDebug("QWSLock::getValue: %s", strerror(errno));
178 } while (ret == -1 && errno == EINTR);
179
180 return ret;
181}
182
183bool QWSLock::lock(LockType type, int timeout)
184{
185 if (type == RegionEvent)
186 return up(semId, RegionEvent);
187
188 if (hasLock(type)) {
189 ++lockCount[type];
190 return true;
191 }
192
193 if (!forceLock(semId, type, timeout))
194 return false;
195 ++lockCount[type];
196 return true;
197}
198
199bool QWSLock::hasLock(LockType type)
200{
201 if (type == RegionEvent)
202 return (getValue(semId, RegionEvent) == 0);
203
204 return (lockCount[type] > 0);
205}
206
207void QWSLock::unlock(LockType type)
208{
209 if (type == RegionEvent) {
210 down(semId, RegionEvent);
211 return;
212 }
213
214 if (hasLock(type)) {
215 --lockCount[type];
216 if (hasLock(type))
217 return;
218 }
219
220 const int semNum = type;
221 int ret;
222 do {
223 sembuf sops = {semNum, 1, 0};
224 if (semNum == QWSLock::BackingStore)
225 sops.sem_flg |= SEM_UNDO;
226
227 ret = semop(semId, &sops, 1);
228 if (ret == -1 && errno != EINTR)
229 qDebug("QWSLock::unlock: %s", strerror(errno));
230 } while (ret == -1 && errno == EINTR);
231}
232
233bool QWSLock::wait(LockType type, int timeout)
234{
235 bool ok = forceLock(semId, type, timeout);
236 if (ok)
237 unlock(type);
238 return ok;
239}
240
241QT_END_NAMESPACE
242
243#endif // QT_NO_QWS_MULTIPROCESS
Note: See TracBrowser for help on using the repository browser.