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(nullptr), 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(newValue: mode == Recursive ? new QRecursiveMutexPrivate : nullptr);
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(msg: "QMutex: destroying locked mutex");
211 }
212}
213
214/*! \fn void QMutex::lock()
215
216 Locks the mutex. If another thread has locked the mutex then this
217 call will block until that thread has unlocked it.
218
219 Calling this function multiple times on the same mutex from the
220 same thread is allowed if this mutex is a
221 \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
222 \l{QMutex}{non-recursive mutex}, this function will
223 \e dead-lock when the mutex is locked recursively.
224
225 \sa unlock()
226*/
227void QMutex::lock() QT_MUTEX_LOCK_NOEXCEPT
228{
229 QMutexData *current;
230 if (fastTryLock(current))
231 return;
232 if (QT_PREPEND_NAMESPACE(isRecursive)(d: current))
233 static_cast<QRecursiveMutexPrivate *>(current)->lock(timeout: -1);
234 else
235 lockInternal();
236}
237
238/*! \fn bool QMutex::tryLock(int timeout)
239
240 Attempts to lock the mutex. This function returns \c true if the lock
241 was obtained; otherwise it returns \c false. If another thread has
242 locked the mutex, this function will wait for at most \a timeout
243 milliseconds for the mutex to become available.
244
245 Note: Passing a negative number as the \a timeout is equivalent to
246 calling lock(), i.e. this function will wait forever until mutex
247 can be locked if \a timeout is negative.
248
249 If the lock was obtained, the mutex must be unlocked with unlock()
250 before another thread can successfully lock it.
251
252 Calling this function multiple times on the same mutex from the
253 same thread is allowed if this mutex is a
254 \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
255 \l{QMutex}{non-recursive mutex}, this function will
256 \e always return false when attempting to lock the mutex
257 recursively.
258
259 \sa lock(), unlock()
260*/
261bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
262{
263 QMutexData *current;
264 if (fastTryLock(current))
265 return true;
266 if (QT_PREPEND_NAMESPACE(isRecursive)(d: current))
267 return static_cast<QRecursiveMutexPrivate *>(current)->lock(timeout);
268 else
269 return lockInternal(timeout);
270}
271
272/*! \fn bool QMutex::try_lock()
273 \since 5.8
274
275 Attempts to lock the mutex. This function returns \c true if the lock
276 was obtained; otherwise it returns \c false.
277
278 This function is provided for compatibility with the Standard Library
279 concept \c Lockable. It is equivalent to tryLock().
280
281 The function returns \c true if the lock was obtained; otherwise it
282 returns \c false
283*/
284
285/*! \fn template <class Rep, class Period> bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
286 \since 5.8
287
288 Attempts to lock the mutex. This function returns \c true if the lock
289 was obtained; otherwise it returns \c false. If another thread has
290 locked the mutex, this function will wait for at least \a duration
291 for the mutex to become available.
292
293 Note: Passing a negative duration as the \a duration is equivalent to
294 calling try_lock(). This behavior differs from tryLock().
295
296 If the lock was obtained, the mutex must be unlocked with unlock()
297 before another thread can successfully lock it.
298
299 Calling this function multiple times on the same mutex from the
300 same thread is allowed if this mutex is a
301 \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
302 \l{QMutex}{non-recursive mutex}, this function will
303 \e always return false when attempting to lock the mutex
304 recursively.
305
306 \sa lock(), unlock()
307*/
308
309/*! \fn template<class Clock, class Duration> bool QMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
310 \since 5.8
311
312 Attempts to lock the mutex. This function returns \c true if the lock
313 was obtained; otherwise it returns \c false. If another thread has
314 locked the mutex, this function will wait at least until \a timePoint
315 for the mutex to become available.
316
317 Note: Passing a \a timePoint which has already passed is equivalent
318 to calling try_lock(). This behavior differs from tryLock().
319
320 If the lock was obtained, the mutex must be unlocked with unlock()
321 before another thread can successfully lock it.
322
323 Calling this function multiple times on the same mutex from the
324 same thread is allowed if this mutex is a
325 \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
326 \l{QMutex}{non-recursive mutex}, this function will
327 \e always return false when attempting to lock the mutex
328 recursively.
329
330 \sa lock(), unlock()
331*/
332
333/*! \fn void QMutex::unlock()
334
335 Unlocks the mutex. Attempting to unlock a mutex in a different
336 thread to the one that locked it results in an error. Unlocking a
337 mutex that is not locked results in undefined behavior.
338
339 \sa lock()
340*/
341void QMutex::unlock() noexcept
342{
343 QMutexData *current;
344 if (fastTryUnlock(current))
345 return;
346 if (QT_PREPEND_NAMESPACE(isRecursive)(d: current))
347 static_cast<QRecursiveMutexPrivate *>(current)->unlock();
348 else
349 unlockInternal();
350}
351
352
353/*!
354 \fn bool QMutex::isRecursive() const
355 \since 5.7
356
357 Returns \c true if the mutex is recursive.
358*/
359
360bool QBasicMutex::isRecursive() noexcept
361{
362 return QT_PREPEND_NAMESPACE(isRecursive)(d: d_ptr.loadAcquire());
363}
364
365/*!
366 \since 5.7
367
368 Returns \c true if the mutex is recursive.
369*/
370bool QBasicMutex::isRecursive() const noexcept
371{
372 return QT_PREPEND_NAMESPACE(isRecursive)(d: d_ptr.loadAcquire());
373}
374
375/*!
376 \class QRecursiveMutex
377 \inmodule QtCore
378 \since 5.14
379 \brief The QRecursiveMutex class provides access serialization between threads.
380
381 \threadsafe
382
383 \ingroup thread
384
385 The QRecursiveMutex class is a mutex, like QMutex, with which it is
386 API-compatible. It differs from QMutex by accepting lock() calls from
387 the same thread any number of times. QMutex would deadlock in this situation.
388
389 QRecursiveMutex is much more expensive to construct and operate on, so
390 use a plain QMutex whenever you can. Sometimes, one public function,
391 however, calls another public function, and they both need to lock the
392 same mutex. In this case, you have two options:
393
394 \list
395 \li Factor the code that needs mutex protection into private functions,
396 which assume that the mutex is held when they are called, and lock a
397 plain QMutex in the public functions before you call the private
398 implementation ones.
399 \li Or use a recursive mutex, so it doesn't matter that the first public
400 function has already locked the mutex when the second one wishes to do so.
401 \endlist
402
403 \sa QMutex, QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition
404*/
405
406/*!
407 Constructs a new recursive mutex. The mutex is created in an unlocked state.
408
409 \sa lock(), unlock()
410*/
411QRecursiveMutex::QRecursiveMutex()
412 : QMutex()
413{
414 d_ptr.storeRelaxed(newValue: new QRecursiveMutexPrivate);
415}
416
417/*!
418 Destroys the mutex.
419
420 \warning Destroying a locked mutex may result in undefined behavior.
421*/
422QRecursiveMutex::~QRecursiveMutex()
423{
424 delete static_cast<QRecursiveMutexPrivate*>(d_ptr.fetchAndStoreAcquire(newValue: nullptr));
425}
426
427/*!
428 \class QMutexLocker
429 \inmodule QtCore
430 \brief The QMutexLocker class is a convenience class that simplifies
431 locking and unlocking mutexes.
432
433 \threadsafe
434
435 \ingroup thread
436
437 Locking and unlocking a QMutex in complex functions and
438 statements or in exception handling code is error-prone and
439 difficult to debug. QMutexLocker can be used in such situations
440 to ensure that the state of the mutex is always well-defined.
441
442 QMutexLocker should be created within a function where a
443 QMutex needs to be locked. The mutex is locked when QMutexLocker
444 is created. You can unlock and relock the mutex with \c unlock()
445 and \c relock(). If locked, the mutex will be unlocked when the
446 QMutexLocker is destroyed.
447
448 For example, this complex function locks a QMutex upon entering
449 the function and unlocks the mutex at all the exit points:
450
451 \snippet code/src_corelib_thread_qmutex.cpp 4
452
453 This example function will get more complicated as it is
454 developed, which increases the likelihood that errors will occur.
455
456 Using QMutexLocker greatly simplifies the code, and makes it more
457 readable:
458
459 \snippet code/src_corelib_thread_qmutex.cpp 5
460
461 Now, the mutex will always be unlocked when the QMutexLocker
462 object is destroyed (when the function returns since \c locker is
463 an auto variable).
464
465 The same principle applies to code that throws and catches
466 exceptions. An exception that is not caught in the function that
467 has locked the mutex has no way of unlocking the mutex before the
468 exception is passed up the stack to the calling function.
469
470 QMutexLocker also provides a \c mutex() member function that returns
471 the mutex on which the QMutexLocker is operating. This is useful
472 for code that needs access to the mutex, such as
473 QWaitCondition::wait(). For example:
474
475 \snippet code/src_corelib_thread_qmutex.cpp 6
476
477 \sa QReadLocker, QWriteLocker, QMutex
478*/
479
480/*!
481 \fn QMutexLocker::QMutexLocker(QMutex *mutex)
482
483 Constructs a QMutexLocker and locks \a mutex. The mutex will be
484 unlocked when the QMutexLocker is destroyed. If \a mutex is \nullptr,
485 QMutexLocker does nothing.
486
487 \sa QMutex::lock()
488*/
489
490/*!
491 \fn QMutexLocker::QMutexLocker(QRecursiveMutex *mutex)
492 \since 5.14
493
494 Constructs a QMutexLocker and locks \a mutex. The mutex will be
495 unlocked (unlock() called) when the QMutexLocker is destroyed.
496 If \a mutex is \nullptr, QMutexLocker does nothing.
497
498 \sa QMutex::lock()
499*/
500
501/*!
502 \fn QMutexLocker::~QMutexLocker()
503
504 Destroys the QMutexLocker and unlocks the mutex that was locked
505 in the constructor.
506
507 \sa QMutex::unlock()
508*/
509
510/*!
511 \fn void QMutexLocker::unlock()
512
513 Unlocks this mutex locker. You can use \c relock() to lock
514 it again. It does not need to be locked when destroyed.
515
516 \sa relock()
517*/
518
519/*!
520 \fn void QMutexLocker::relock()
521
522 Relocks an unlocked mutex locker.
523
524 \sa unlock()
525*/
526
527/*!
528 \fn QMutex *QMutexLocker::mutex() const
529
530 Returns the mutex on which the QMutexLocker is operating.
531
532*/
533
534#ifndef QT_LINUX_FUTEX //linux implementation is in qmutex_linux.cpp
535
536/*
537 For a rough introduction on how this works, refer to
538 http://woboq.com/blog/internals-of-qmutex-in-qt5.html
539 which explains a slightly simplified version of it.
540 The differences are that here we try to work with timeout (requires the
541 possiblyUnlocked flag) and that we only wake one thread when unlocking
542 (requires maintaining the waiters count)
543 We also support recursive mutexes which always have a valid d_ptr.
544
545 The waiters flag represents the number of threads that are waiting or about
546 to wait on the mutex. There are two tricks to keep in mind:
547 We don't want to increment waiters after we checked no threads are waiting
548 (waiters == 0). That's why we atomically set the BigNumber flag on waiters when
549 we check waiters. Similarly, if waiters is decremented right after we checked,
550 the mutex would be unlocked (d->wakeUp() has (or will) be called), but there is
551 no thread waiting. This is only happening if there was a timeout in tryLock at the
552 same time as the mutex is unlocked. So when there was a timeout, we set the
553 possiblyUnlocked flag.
554*/
555
556/*!
557 \internal helper for lock()
558 */
559void QBasicMutex::lockInternal() QT_MUTEX_LOCK_NOEXCEPT
560{
561 lockInternal(-1);
562}
563
564/*!
565 \internal helper for lock(int)
566 */
567bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
568{
569 Q_ASSERT(!isRecursive());
570
571 while (!fastTryLock()) {
572 QMutexData *copy = d_ptr.loadAcquire();
573 if (!copy) // if d is 0, the mutex is unlocked
574 continue;
575
576 if (copy == dummyLocked()) {
577 if (timeout == 0)
578 return false;
579 // The mutex is locked but does not have a QMutexPrivate yet.
580 // we need to allocate a QMutexPrivate
581 QMutexPrivate *newD = QMutexPrivate::allocate();
582 if (!d_ptr.testAndSetOrdered(dummyLocked(), newD)) {
583 //Either the mutex is already unlocked, or another thread already set it.
584 newD->deref();
585 continue;
586 }
587 copy = newD;
588 //the d->refCount is already 1 the deref will occurs when we unlock
589 }
590
591 QMutexPrivate *d = static_cast<QMutexPrivate *>(copy);
592 if (timeout == 0 && !d->possiblyUnlocked.loadRelaxed())
593 return false;
594
595 // At this point we have a pointer to a QMutexPrivate. But the other thread
596 // may unlock the mutex at any moment and release the QMutexPrivate to the pool.
597 // We will try to reference it to avoid unlock to release it to the pool to make
598 // sure it won't be released. But if the refcount is already 0 it has been released.
599 if (!d->ref())
600 continue; //that QMutexData was already released
601
602 // We now hold a reference to the QMutexPrivate. It won't be released and re-used.
603 // But it is still possible that it was already re-used by another QMutex right before
604 // we did the ref(). So check if we still hold a pointer to the right mutex.
605 if (d != d_ptr.loadAcquire()) {
606 //Either the mutex is already unlocked, or relocked with another mutex
607 d->deref();
608 continue;
609 }
610
611 // In this part, we will try to increment the waiters count.
612 // We just need to take care of the case in which the old_waiters
613 // is set to the BigNumber magic value set in unlockInternal()
614 int old_waiters;
615 do {
616 old_waiters = d->waiters.loadAcquire();
617 if (old_waiters == -QMutexPrivate::BigNumber) {
618 // we are unlocking, and the thread that unlocks is about to change d to 0
619 // we try to acquire the mutex by changing to dummyLocked()
620 if (d_ptr.testAndSetAcquire(d, dummyLocked())) {
621 // Mutex acquired
622 d->deref();
623 return true;
624 } else {
625 Q_ASSERT(d != d_ptr.loadRelaxed()); //else testAndSetAcquire should have succeeded
626 // Mutex is likely to bo 0, we should continue the outer-loop,
627 // set old_waiters to the magic value of BigNumber
628 old_waiters = QMutexPrivate::BigNumber;
629 break;
630 }
631 }
632 } while (!d->waiters.testAndSetRelaxed(old_waiters, old_waiters + 1));
633
634 if (d != d_ptr.loadAcquire()) {
635 // The mutex was unlocked before we incremented waiters.
636 if (old_waiters != QMutexPrivate::BigNumber) {
637 //we did not break the previous loop
638 Q_ASSERT(d->waiters.loadRelaxed() >= 1);
639 d->waiters.deref();
640 }
641 d->deref();
642 continue;
643 }
644
645 if (d->wait(timeout)) {
646 // reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
647 if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
648 d->deref();
649 d->derefWaiters(1);
650 //we got the lock. (do not deref)
651 Q_ASSERT(d == d_ptr.loadRelaxed());
652 return true;
653 } else {
654 Q_ASSERT(timeout >= 0);
655 //timeout
656 d->derefWaiters(1);
657 //There may be a race in which the mutex is unlocked right after we timed out,
658 // and before we deref the waiters, so maybe the mutex is actually unlocked.
659 // Set the possiblyUnlocked flag to indicate this possibility.
660 if (!d->possiblyUnlocked.testAndSetRelaxed(false, true)) {
661 // We keep a reference when possiblyUnlocked is true.
662 // but if possiblyUnlocked was already true, we don't need to keep the reference.
663 d->deref();
664 }
665 return false;
666 }
667 }
668 Q_ASSERT(d_ptr.loadRelaxed() != 0);
669 return true;
670}
671
672/*!
673 \internal
674*/
675void QBasicMutex::unlockInternal() noexcept
676{
677 QMutexData *copy = d_ptr.loadAcquire();
678 Q_ASSERT(copy); //we must be locked
679 Q_ASSERT(copy != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
680 Q_ASSERT(!isRecursive());
681
682 QMutexPrivate *d = reinterpret_cast<QMutexPrivate *>(copy);
683
684 // If no one is waiting for the lock anymore, we should reset d to 0x0.
685 // Using fetchAndAdd, we atomically check that waiters was equal to 0, and add a flag
686 // to the waiters variable (BigNumber). That way, we avoid the race in which waiters is
687 // incremented right after we checked, because we won't increment waiters if is
688 // equal to -BigNumber
689 if (d->waiters.fetchAndAddRelease(-QMutexPrivate::BigNumber) == 0) {
690 //there is no one waiting on this mutex anymore, set the mutex as unlocked (d = 0)
691 if (d_ptr.testAndSetRelease(d, 0)) {
692 // reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
693 if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
694 d->deref();
695 }
696 d->derefWaiters(0);
697 } else {
698 d->derefWaiters(0);
699 //there are thread waiting, transfer the lock.
700 d->wakeUp();
701 }
702 d->deref();
703}
704
705//The freelist management
706namespace {
707struct FreeListConstants : QFreeListDefaultConstants {
708 enum { BlockCount = 4, MaxIndex=0xffff };
709 static const int Sizes[BlockCount];
710};
711const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
712 16,
713 128,
714 1024,
715 FreeListConstants::MaxIndex - (16 + 128 + 1024)
716};
717
718typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList;
719// We cannot use Q_GLOBAL_STATIC because it uses QMutex
720static FreeList freeList_;
721FreeList *freelist()
722{
723 return &freeList_;
724}
725}
726
727QMutexPrivate *QMutexPrivate::allocate()
728{
729 int i = freelist()->next();
730 QMutexPrivate *d = &(*freelist())[i];
731 d->id = i;
732 Q_ASSERT(d->refCount.loadRelaxed() == 0);
733 Q_ASSERT(!d->recursive);
734 Q_ASSERT(!d->possiblyUnlocked.loadRelaxed());
735 Q_ASSERT(d->waiters.loadRelaxed() == 0);
736 d->refCount.storeRelaxed(1);
737 return d;
738}
739
740void QMutexPrivate::release()
741{
742 Q_ASSERT(!recursive);
743 Q_ASSERT(refCount.loadRelaxed() == 0);
744 Q_ASSERT(!possiblyUnlocked.loadRelaxed());
745 Q_ASSERT(waiters.loadRelaxed() == 0);
746 freelist()->release(id);
747}
748
749// atomically subtract "value" to the waiters, and remove the QMutexPrivate::BigNumber flag
750void QMutexPrivate::derefWaiters(int value) noexcept
751{
752 int old_waiters;
753 int new_waiters;
754 do {
755 old_waiters = waiters.loadRelaxed();
756 new_waiters = old_waiters;
757 if (new_waiters < 0) {
758 new_waiters += QMutexPrivate::BigNumber;
759 }
760 new_waiters -= value;
761 } while (!waiters.testAndSetRelaxed(old_waiters, new_waiters));
762}
763#endif
764
765/*!
766 \internal
767 */
768inline bool QRecursiveMutexPrivate::lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
769{
770 Qt::HANDLE self = QThread::currentThreadId();
771 if (owner.loadRelaxed() == self) {
772 ++count;
773 Q_ASSERT_X(count != 0, "QMutex::lock", "Overflow in recursion counter");
774 return true;
775 }
776 bool success = true;
777 if (timeout == -1) {
778 mutex.QBasicMutex::lock();
779 } else {
780 success = mutex.tryLock(timeout);
781 }
782
783 if (success)
784 owner.storeRelaxed(newValue: self);
785 return success;
786}
787
788/*!
789 \internal
790 */
791inline void QRecursiveMutexPrivate::unlock() noexcept
792{
793 if (count > 0) {
794 count--;
795 } else {
796 owner.storeRelaxed(newValue: nullptr);
797 mutex.QBasicMutex::unlock();
798 }
799}
800
801QT_END_NAMESPACE
802
803#ifdef QT_LINUX_FUTEX
804# include "qmutex_linux.cpp"
805#elif defined(Q_OS_MAC)
806# include "qmutex_mac.cpp"
807#elif defined(Q_OS_WIN)
808# include "qmutex_win.cpp"
809#else
810# include "qmutex_unix.cpp"
811#endif
812

source code of qtbase/src/corelib/thread/qmutex.cpp