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