1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2016 Intel Corporation.
5** Copyright (C) 2012 Olivier Goffart <ogoffart@woboq.com>
6** Contact: https://www.qt.io/licensing/
7**
8** This file is part of the QtCore module of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial License Usage
12** Licensees holding valid commercial Qt licenses may use this file in
13** accordance with the commercial license agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and The Qt Company. For licensing terms
16** and conditions see https://www.qt.io/terms-conditions. For further
17** information use the contact form at https://www.qt.io/contact-us.
18**
19** GNU Lesser General Public License Usage
20** Alternatively, this file may be used under the terms of the GNU Lesser
21** General Public License version 3 as published by the Free Software
22** Foundation and appearing in the file LICENSE.LGPL3 included in the
23** packaging of this file. Please review the following information to
24** ensure the GNU Lesser General Public License version 3 requirements
25** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26**
27** GNU General Public License Usage
28** Alternatively, this file may be used under the terms of the GNU
29** General Public License version 2.0 or (at your option) the GNU General
30** Public license version 3 or any later version approved by the KDE Free
31** Qt Foundation. The licenses are as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33** included in the packaging of this file. Please review the following
34** information to ensure the GNU General Public License requirements will
35** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36** https://www.gnu.org/licenses/gpl-3.0.html.
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qplatformdefs.h"
43#include "qmutex.h"
44#include <qdebug.h>
45#include "qatomic.h"
46#include "qelapsedtimer.h"
47#include "qthread.h"
48#include "qmutex_p.h"
49
50#ifndef QT_LINUX_FUTEX
51#include "private/qfreelist_p.h"
52#endif
53
54QT_BEGIN_NAMESPACE
55
56static inline bool isRecursive(QMutexData *d)
57{
58 quintptr u = quintptr(d);
59 if (Q_LIKELY(u <= 0x3))
60 return false;
61#ifdef QT_LINUX_FUTEX
62 Q_ASSERT(d->recursive);
63 return true;
64#else
65 return d->recursive;
66#endif
67}
68
69class QRecursiveMutexPrivate : public QMutexData
70{
71public:
72 QRecursiveMutexPrivate()
73 : QMutexData(QMutex::Recursive), owner(0), count(0) {}
74
75 // written to by the thread that first owns 'mutex';
76 // read during attempts to acquire ownership of 'mutex' from any other thread:
77 QAtomicPointer<std::remove_pointer<Qt::HANDLE>::type> owner;
78
79 // only ever accessed from the thread that owns 'mutex':
80 uint count;
81
82 QMutex mutex;
83
84 bool lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT;
85 void unlock() noexcept;
86};
87
88/*
89 \class QBasicMutex
90 \inmodule QtCore
91 \brief QMutex POD
92 \internal
93
94 \ingroup thread
95
96 - Can be used as global static object.
97 - Always non-recursive
98 - Do not use tryLock with timeout > 0, else you can have a leak (see the ~QMutex destructor)
99*/
100
101/*!
102 \class QMutex
103 \inmodule QtCore
104 \brief The QMutex class provides access serialization between threads.
105
106 \threadsafe
107
108 \ingroup thread
109
110 The purpose of a QMutex is to protect an object, data structure or
111 section of code so that only one thread can access it at a time
112 (this is similar to the Java \c synchronized keyword). It is
113 usually best to use a mutex with a QMutexLocker since this makes
114 it easy to ensure that locking and unlocking are performed
115 consistently.
116
117 For example, say there is a method that prints a message to the
118 user on two lines:
119
120 \snippet code/src_corelib_thread_qmutex.cpp 0
121
122 If these two methods are called in succession, the following happens:
123
124 \snippet code/src_corelib_thread_qmutex.cpp 1
125
126 If these two methods are called simultaneously from two threads then the
127 following sequence could result:
128
129 \snippet code/src_corelib_thread_qmutex.cpp 2
130
131 If we add a mutex, we should get the result we want:
132
133 \snippet code/src_corelib_thread_qmutex.cpp 3
134
135 Then only one thread can modify \c number at any given time and
136 the result is correct. This is a trivial example, of course, but
137 applies to any other case where things need to happen in a
138 particular sequence.
139
140 When you call lock() in a thread, other threads that try to call
141 lock() in the same place will block until the thread that got the
142 lock calls unlock(). A non-blocking alternative to lock() is
143 tryLock().
144
145 QMutex is optimized to be fast in the non-contended case. A non-recursive
146 QMutex will not allocate memory if there is no contention on that mutex.
147 It is constructed and destroyed with almost no overhead,
148 which means it is fine to have many mutexes as part of other classes.
149
150 \sa QRecursiveMutex, QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition
151*/
152
153/*!
154 \enum QMutex::RecursionMode
155
156 \value Recursive In this mode, a thread can lock the same mutex
157 multiple times and the mutex won't be unlocked
158 until a corresponding number of unlock() calls
159 have been made. You should use QRecursiveMutex
160 for this use-case.
161
162 \value NonRecursive In this mode, a thread may only lock a mutex
163 once.
164
165 \sa QMutex(), QRecursiveMutex
166*/
167
168/*!
169 \fn QMutex::QMutex()
170
171 Constructs a new mutex. The mutex is created in an unlocked state.
172*/
173
174/*!
175 Constructs a new mutex. The mutex is created in an unlocked state.
176
177 If \a mode is QMutex::Recursive, a thread can lock the same mutex
178 multiple times and the mutex won't be unlocked until a
179 corresponding number of unlock() calls have been made. Otherwise
180 a thread may only lock a mutex once. The default is
181 QMutex::NonRecursive.
182
183 Recursive mutexes are slower and take more memory than non-recursive ones.
184
185 \sa lock(), unlock()
186*/
187QMutex::QMutex(RecursionMode mode)
188{
189 d_ptr.storeRelaxed(mode == Recursive ? new QRecursiveMutexPrivate : 0);
190}
191
192/*!
193 Destroys the mutex.
194
195 \warning Destroying a locked mutex may result in undefined behavior.
196*/
197QMutex::~QMutex()
198{
199 QMutexData *d = d_ptr.loadRelaxed();
200 if (isRecursive()) {
201 delete static_cast<QRecursiveMutexPrivate *>(d);
202 } else if (d) {
203#ifndef QT_LINUX_FUTEX
204 if (d != dummyLocked() && static_cast<QMutexPrivate *>(d)->possiblyUnlocked.loadRelaxed()
205 && tryLock()) {
206 unlock();
207 return;
208 }
209#endif
210 qWarning("QMutex: destroying locked mutex");
211 }
212}
213
214/*! \fn void QMutex::lock()
215 \fn QRecursiveMutex::lock()
216
217 Locks the mutex. If another thread has locked the mutex then this
218 call will block until that thread has unlocked it.
219
220 Calling this function multiple times on the same mutex from the
221 same thread is allowed if this mutex is a
222 \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
223 \l{QMutex}{non-recursive mutex}, this function will
224 \e dead-lock when the mutex is locked recursively.
225
226 \sa unlock()
227*/
228void QMutex::lock() QT_MUTEX_LOCK_NOEXCEPT
229{
230 QMutexData *current;
231 if (fastTryLock(current))
232 return;
233 if (QT_PREPEND_NAMESPACE(isRecursive)(current))
234 static_cast<QRecursiveMutexPrivate *>(current)->lock(-1);
235 else
236 lockInternal();
237}
238
239/*! \fn bool QMutex::tryLock(int timeout)
240 \fn bool QRecursiveMutex::tryLock(int timeout)
241
242 Attempts to lock the mutex. This function returns \c true if the lock
243 was obtained; otherwise it returns \c false. If another thread has
244 locked the mutex, this function will wait for at most \a timeout
245 milliseconds for the mutex to become available.
246
247 Note: Passing a negative number as the \a timeout is equivalent to
248 calling lock(), i.e. this function will wait forever until mutex
249 can be locked if \a timeout is negative.
250
251 If the lock was obtained, the mutex must be unlocked with unlock()
252 before another thread can successfully lock it.
253
254 Calling this function multiple times on the same mutex from the
255 same thread is allowed if this mutex is a
256 \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
257 \l{QMutex}{non-recursive mutex}, this function will
258 \e always return false when attempting to lock the mutex
259 recursively.
260
261 \sa lock(), unlock()
262*/
263bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
264{
265 QMutexData *current;
266 if (fastTryLock(current))
267 return true;
268 if (QT_PREPEND_NAMESPACE(isRecursive)(current))
269 return static_cast<QRecursiveMutexPrivate *>(current)->lock(timeout);
270 else
271 return lockInternal(timeout);
272}
273
274/*! \fn bool QMutex::try_lock()
275 \fn bool QRecursiveMutex::try_lock()
276 \since 5.8
277
278 Attempts to lock the mutex. This function returns \c true if the lock
279 was obtained; otherwise it returns \c false.
280
281 This function is provided for compatibility with the Standard Library
282 concept \c Lockable. It is equivalent to tryLock().
283
284 The function returns \c true if the lock was obtained; otherwise it
285 returns \c false
286*/
287
288/*! \fn template <class Rep, class Period> bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
289 \fn template <class Rep, class Period> bool QRecursiveMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
290 \since 5.8
291
292 Attempts to lock the mutex. This function returns \c true if the lock
293 was obtained; otherwise it returns \c false. If another thread has
294 locked the mutex, this function will wait for at least \a duration
295 for the mutex to become available.
296
297 Note: Passing a negative duration as the \a duration is equivalent to
298 calling try_lock(). This behavior differs from tryLock().
299
300 If the lock was obtained, the mutex must be unlocked with unlock()
301 before another thread can successfully lock it.
302
303 Calling this function multiple times on the same mutex from the
304 same thread is allowed if this mutex is a
305 \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
306 \l{QMutex}{non-recursive mutex}, this function will
307 \e always return false when attempting to lock the mutex
308 recursively.
309
310 \sa lock(), unlock()
311*/
312
313/*! \fn template<class Clock, class Duration> bool QMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
314 \fn template<class Clock, class Duration> bool QRecursiveMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
315 \since 5.8
316
317 Attempts to lock the mutex. This function returns \c true if the lock
318 was obtained; otherwise it returns \c false. If another thread has
319 locked the mutex, this function will wait at least until \a timePoint
320 for the mutex to become available.
321
322 Note: Passing a \a timePoint which has already passed is equivalent
323 to calling try_lock(). This behavior differs from tryLock().
324
325 If the lock was obtained, the mutex must be unlocked with unlock()
326 before another thread can successfully lock it.
327
328 Calling this function multiple times on the same mutex from the
329 same thread is allowed if this mutex is a
330 \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
331 \l{QMutex}{non-recursive mutex}, this function will
332 \e always return false when attempting to lock the mutex
333 recursively.
334
335 \sa lock(), unlock()
336*/
337
338/*! \fn void QMutex::unlock()
339 \fn void QRecursiveMutex::unlock()
340
341 Unlocks the mutex. Attempting to unlock a mutex in a different
342 thread to the one that locked it results in an error. Unlocking a
343 mutex that is not locked results in undefined behavior.
344
345 \sa lock()
346*/
347void QMutex::unlock() noexcept
348{
349 QMutexData *current;
350 if (fastTryUnlock(current))
351 return;
352 if (QT_PREPEND_NAMESPACE(isRecursive)(current))
353 static_cast<QRecursiveMutexPrivate *>(current)->unlock();
354 else
355 unlockInternal();
356}
357
358
359/*!
360 \fn bool QMutex::isRecursive() const
361 \since 5.7
362
363 Returns \c true if the mutex is recursive.
364*/
365
366bool QBasicMutex::isRecursive() noexcept
367{
368 return QT_PREPEND_NAMESPACE(isRecursive)(d_ptr.loadAcquire());
369}
370
371/*!
372 \since 5.7
373
374 Returns \c true if the mutex is recursive.
375*/
376bool QBasicMutex::isRecursive() const noexcept
377{
378 return QT_PREPEND_NAMESPACE(isRecursive)(d_ptr.loadAcquire());
379}
380
381/*!
382 \class QRecursiveMutex
383 \inmodule QtCore
384 \since 5.14
385 \brief The QRecursiveMutex class provides access serialization between threads.
386
387 \threadsafe
388
389 \ingroup thread
390
391 The QRecursiveMutex class is a mutex, like QMutex, with which it is
392 API-compatible. It differs from QMutex by accepting lock() calls from
393 the same thread any number of times. QMutex would deadlock in this situation.
394
395 QRecursiveMutex is much more expensive to construct and operate on, so
396 use a plain QMutex whenever you can. Sometimes, one public function,
397 however, calls another public function, and they both need to lock the
398 same mutex. In this case, you have two options:
399
400 \list
401 \li Factor the code that needs mutex protection into private functions,
402 which assume that the mutex is held when they are called, and lock a
403 plain QMutex in the public functions before you call the private
404 implementation ones.
405 \li Or use a recursive mutex, so it doesn't matter that the first public
406 function has already locked the mutex when the second one wishes to do so.
407 \endlist
408
409 \sa QMutex, QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition
410*/
411
412/*!
413 Constructs a new recursive mutex. The mutex is created in an unlocked state.
414
415 \sa lock(), unlock()
416*/
417QRecursiveMutex::QRecursiveMutex()
418 : QMutex()
419{
420 d_ptr.storeRelaxed(new QRecursiveMutexPrivate);
421}
422
423/*!
424 Destroys the mutex.
425
426 \warning Destroying a locked mutex may result in undefined behavior.
427*/
428QRecursiveMutex::~QRecursiveMutex()
429{
430 delete static_cast<QRecursiveMutexPrivate*>(d_ptr.fetchAndStoreAcquire(nullptr));
431}
432
433/*!
434 \class QMutexLocker
435 \inmodule QtCore
436 \brief The QMutexLocker class is a convenience class that simplifies
437 locking and unlocking mutexes.
438
439 \threadsafe
440
441 \ingroup thread
442
443 Locking and unlocking a QMutex in complex functions and
444 statements or in exception handling code is error-prone and
445 difficult to debug. QMutexLocker can be used in such situations
446 to ensure that the state of the mutex is always well-defined.
447
448 QMutexLocker should be created within a function where a
449 QMutex needs to be locked. The mutex is locked when QMutexLocker
450 is created. You can unlock and relock the mutex with \c unlock()
451 and \c relock(). If locked, the mutex will be unlocked when the
452 QMutexLocker is destroyed.
453
454 For example, this complex function locks a QMutex upon entering
455 the function and unlocks the mutex at all the exit points:
456
457 \snippet code/src_corelib_thread_qmutex.cpp 4
458
459 This example function will get more complicated as it is
460 developed, which increases the likelihood that errors will occur.
461
462 Using QMutexLocker greatly simplifies the code, and makes it more
463 readable:
464
465 \snippet code/src_corelib_thread_qmutex.cpp 5
466
467 Now, the mutex will always be unlocked when the QMutexLocker
468 object is destroyed (when the function returns since \c locker is
469 an auto variable).
470
471 The same principle applies to code that throws and catches
472 exceptions. An exception that is not caught in the function that
473 has locked the mutex has no way of unlocking the mutex before the
474 exception is passed up the stack to the calling function.
475
476 QMutexLocker also provides a \c mutex() member function that returns
477 the mutex on which the QMutexLocker is operating. This is useful
478 for code that needs access to the mutex, such as
479 QWaitCondition::wait(). For example:
480
481 \snippet code/src_corelib_thread_qmutex.cpp 6
482
483 \sa QReadLocker, QWriteLocker, QMutex
484*/
485
486/*!
487 \fn QMutexLocker::QMutexLocker(QMutex *mutex)
488
489 Constructs a QMutexLocker and locks \a mutex. The mutex will be
490 unlocked when the QMutexLocker is destroyed. If \a mutex is zero,
491 QMutexLocker does nothing.
492
493 \sa QMutex::lock()
494*/
495
496/*!
497 \fn QMutexLocker::QMutexLocker(QRecursiveMutex *mutex)
498 \since 5.14
499
500 Constructs a QMutexLocker and locks \a mutex. The mutex will be
501 unlocked (unlock() called) when the QMutexLocker is destroyed.
502 If \a mutex is \nullptr, QMutexLocker does nothing.
503
504 \sa QMutex::lock()
505*/
506
507/*!
508 \fn QMutexLocker::~QMutexLocker()
509
510 Destroys the QMutexLocker and unlocks the mutex that was locked
511 in the constructor.
512
513 \sa QMutex::unlock()
514*/
515
516/*!
517 \fn void QMutexLocker::unlock()
518
519 Unlocks this mutex locker. You can use \c relock() to lock
520 it again. It does not need to be locked when destroyed.
521
522 \sa relock()
523*/
524
525/*!
526 \fn void QMutexLocker::relock()
527
528 Relocks an unlocked mutex locker.
529
530 \sa unlock()
531*/
532
533/*!
534 \fn QMutex *QMutexLocker::mutex() const
535
536 Returns the mutex on which the QMutexLocker is operating.
537
538*/
539
540#ifndef QT_LINUX_FUTEX //linux implementation is in qmutex_linux.cpp
541
542/*
543 For a rough introduction on how this works, refer to
544 http://woboq.com/blog/internals-of-qmutex-in-qt5.html
545 which explains a slightly simplified version of it.
546 The differences are that here we try to work with timeout (requires the
547 possiblyUnlocked flag) and that we only wake one thread when unlocking
548 (requires maintaining the waiters count)
549 We also support recursive mutexes which always have a valid d_ptr.
550
551 The waiters flag represents the number of threads that are waiting or about
552 to wait on the mutex. There are two tricks to keep in mind:
553 We don't want to increment waiters after we checked no threads are waiting
554 (waiters == 0). That's why we atomically set the BigNumber flag on waiters when
555 we check waiters. Similarly, if waiters is decremented right after we checked,
556 the mutex would be unlocked (d->wakeUp() has (or will) be called), but there is
557 no thread waiting. This is only happening if there was a timeout in tryLock at the
558 same time as the mutex is unlocked. So when there was a timeout, we set the
559 possiblyUnlocked flag.
560*/
561
562/*!
563 \internal helper for lock()
564 */
565void QBasicMutex::lockInternal() QT_MUTEX_LOCK_NOEXCEPT
566{
567 lockInternal(-1);
568}
569
570/*!
571 \internal helper for lock(int)
572 */
573bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
574{
575 Q_ASSERT(!isRecursive());
576
577 while (!fastTryLock()) {
578 QMutexData *copy = d_ptr.loadAcquire();
579 if (!copy) // if d is 0, the mutex is unlocked
580 continue;
581
582 if (copy == dummyLocked()) {
583 if (timeout == 0)
584 return false;
585 // The mutex is locked but does not have a QMutexPrivate yet.
586 // we need to allocate a QMutexPrivate
587 QMutexPrivate *newD = QMutexPrivate::allocate();
588 if (!d_ptr.testAndSetOrdered(dummyLocked(), newD)) {
589 //Either the mutex is already unlocked, or another thread already set it.
590 newD->deref();
591 continue;
592 }
593 copy = newD;
594 //the d->refCount is already 1 the deref will occurs when we unlock
595 }
596
597 QMutexPrivate *d = static_cast<QMutexPrivate *>(copy);
598 if (timeout == 0 && !d->possiblyUnlocked.loadRelaxed())
599 return false;
600
601 // At this point we have a pointer to a QMutexPrivate. But the other thread
602 // may unlock the mutex at any moment and release the QMutexPrivate to the pool.
603 // We will try to reference it to avoid unlock to release it to the pool to make
604 // sure it won't be released. But if the refcount is already 0 it has been released.
605 if (!d->ref())
606 continue; //that QMutexData was already released
607
608 // We now hold a reference to the QMutexPrivate. It won't be released and re-used.
609 // But it is still possible that it was already re-used by another QMutex right before
610 // we did the ref(). So check if we still hold a pointer to the right mutex.
611 if (d != d_ptr.loadAcquire()) {
612 //Either the mutex is already unlocked, or relocked with another mutex
613 d->deref();
614 continue;
615 }
616
617 // In this part, we will try to increment the waiters count.
618 // We just need to take care of the case in which the old_waiters
619 // is set to the BigNumber magic value set in unlockInternal()
620 int old_waiters;
621 do {
622 old_waiters = d->waiters.loadRelaxed();
623 if (old_waiters == -QMutexPrivate::BigNumber) {
624 // we are unlocking, and the thread that unlocks is about to change d to 0
625 // we try to acquire the mutex by changing to dummyLocked()
626 if (d_ptr.testAndSetAcquire(d, dummyLocked())) {
627 // Mutex acquired
628 d->deref();
629 return true;
630 } else {
631 Q_ASSERT(d != d_ptr.loadRelaxed()); //else testAndSetAcquire should have succeeded
632 // Mutex is likely to bo 0, we should continue the outer-loop,
633 // set old_waiters to the magic value of BigNumber
634 old_waiters = QMutexPrivate::BigNumber;
635 break;
636 }
637 }
638 } while (!d->waiters.testAndSetRelaxed(old_waiters, old_waiters + 1));
639
640 if (d != d_ptr.loadAcquire()) {
641 // The mutex was unlocked before we incremented waiters.
642 if (old_waiters != QMutexPrivate::BigNumber) {
643 //we did not break the previous loop
644 Q_ASSERT(d->waiters.loadRelaxed() >= 1);
645 d->waiters.deref();
646 }
647 d->deref();
648 continue;
649 }
650
651 if (d->wait(timeout)) {
652 // reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
653 if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
654 d->deref();
655 d->derefWaiters(1);
656 //we got the lock. (do not deref)
657 Q_ASSERT(d == d_ptr.loadRelaxed());
658 return true;
659 } else {
660 Q_ASSERT(timeout >= 0);
661 //timeout
662 d->derefWaiters(1);
663 //There may be a race in which the mutex is unlocked right after we timed out,
664 // and before we deref the waiters, so maybe the mutex is actually unlocked.
665 // Set the possiblyUnlocked flag to indicate this possibility.
666 if (!d->possiblyUnlocked.testAndSetRelaxed(false, true)) {
667 // We keep a reference when possiblyUnlocked is true.
668 // but if possiblyUnlocked was already true, we don't need to keep the reference.
669 d->deref();
670 }
671 return false;
672 }
673 }
674 Q_ASSERT(d_ptr.loadRelaxed() != 0);
675 return true;
676}
677
678/*!
679 \internal
680*/
681void QBasicMutex::unlockInternal() noexcept
682{
683 QMutexData *copy = d_ptr.loadAcquire();
684 Q_ASSERT(copy); //we must be locked
685 Q_ASSERT(copy != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
686 Q_ASSERT(!isRecursive());
687
688 QMutexPrivate *d = reinterpret_cast<QMutexPrivate *>(copy);
689
690 // If no one is waiting for the lock anymore, we should reset d to 0x0.
691 // Using fetchAndAdd, we atomically check that waiters was equal to 0, and add a flag
692 // to the waiters variable (BigNumber). That way, we avoid the race in which waiters is
693 // incremented right after we checked, because we won't increment waiters if is
694 // equal to -BigNumber
695 if (d->waiters.fetchAndAddRelease(-QMutexPrivate::BigNumber) == 0) {
696 //there is no one waiting on this mutex anymore, set the mutex as unlocked (d = 0)
697 if (d_ptr.testAndSetRelease(d, 0)) {
698 // reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
699 if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
700 d->deref();
701 }
702 d->derefWaiters(0);
703 } else {
704 d->derefWaiters(0);
705 //there are thread waiting, transfer the lock.
706 d->wakeUp();
707 }
708 d->deref();
709}
710
711//The freelist management
712namespace {
713struct FreeListConstants : QFreeListDefaultConstants {
714 enum { BlockCount = 4, MaxIndex=0xffff };
715 static const int Sizes[BlockCount];
716};
717const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
718 16,
719 128,
720 1024,
721 FreeListConstants::MaxIndex - (16 + 128 + 1024)
722};
723
724typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList;
725// We cannot use Q_GLOBAL_STATIC because it uses QMutex
726static FreeList freeList_;
727FreeList *freelist()
728{
729 return &freeList_;
730}
731}
732
733QMutexPrivate *QMutexPrivate::allocate()
734{
735 int i = freelist()->next();
736 QMutexPrivate *d = &(*freelist())[i];
737 d->id = i;
738 Q_ASSERT(d->refCount.loadRelaxed() == 0);
739 Q_ASSERT(!d->recursive);
740 Q_ASSERT(!d->possiblyUnlocked.loadRelaxed());
741 Q_ASSERT(d->waiters.loadRelaxed() == 0);
742 d->refCount.storeRelaxed(1);
743 return d;
744}
745
746void QMutexPrivate::release()
747{
748 Q_ASSERT(!recursive);
749 Q_ASSERT(refCount.loadRelaxed() == 0);
750 Q_ASSERT(!possiblyUnlocked.loadRelaxed());
751 Q_ASSERT(waiters.loadRelaxed() == 0);
752 freelist()->release(id);
753}
754
755// atomically subtract "value" to the waiters, and remove the QMutexPrivate::BigNumber flag
756void QMutexPrivate::derefWaiters(int value) noexcept
757{
758 int old_waiters;
759 int new_waiters;
760 do {
761 old_waiters = waiters.loadRelaxed();
762 new_waiters = old_waiters;
763 if (new_waiters < 0) {
764 new_waiters += QMutexPrivate::BigNumber;
765 }
766 new_waiters -= value;
767 } while (!waiters.testAndSetRelaxed(old_waiters, new_waiters));
768}
769#endif
770
771/*!
772 \internal
773 */
774inline bool QRecursiveMutexPrivate::lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
775{
776 Qt::HANDLE self = QThread::currentThreadId();
777 if (owner.loadRelaxed() == self) {
778 ++count;
779 Q_ASSERT_X(count != 0, "QMutex::lock", "Overflow in recursion counter");
780 return true;
781 }
782 bool success = true;
783 if (timeout == -1) {
784 mutex.QBasicMutex::lock();
785 } else {
786 success = mutex.tryLock(timeout);
787 }
788
789 if (success)
790 owner.storeRelaxed(self);
791 return success;
792}
793
794/*!
795 \internal
796 */
797inline void QRecursiveMutexPrivate::unlock() noexcept
798{
799 if (count > 0) {
800 count--;
801 } else {
802 owner.storeRelaxed(0);
803 mutex.QBasicMutex::unlock();
804 }
805}
806
807QT_END_NAMESPACE
808
809#ifdef QT_LINUX_FUTEX
810# include "qmutex_linux.cpp"
811#elif defined(Q_OS_MAC)
812# include "qmutex_mac.cpp"
813#elif defined(Q_OS_WIN)
814# include "qmutex_win.cpp"
815#else
816# include "qmutex_unix.cpp"
817#endif
818