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

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